From a45ae5f869d9cfcb3e41dbab486e10bfa9e336bf Mon Sep 17 00:00:00 2001 From: John Marino Date: Fri, 11 May 2012 07:55:24 +0200 Subject: [PATCH] Upgrade GDB from 7.3 to 7.4.1 on the vendor branch --- contrib/gdb-7/bfd/archive.c | 121 +- contrib/gdb-7/bfd/archures.c | 81 +- contrib/gdb-7/bfd/bfd-in.h | 39 +- contrib/gdb-7/bfd/bfd-in2.h | 389 +- contrib/gdb-7/bfd/bfd.c | 13 +- contrib/gdb-7/bfd/bfdio.c | 29 +- contrib/gdb-7/bfd/bfdwin.c | 41 +- contrib/gdb-7/bfd/binary.c | 4 +- contrib/gdb-7/bfd/cache.c | 31 +- contrib/gdb-7/bfd/coffgen.c | 166 +- contrib/gdb-7/bfd/compress.c | 8 +- contrib/gdb-7/bfd/config.bfd | 141 +- contrib/gdb-7/bfd/cpu-i386.c | 7 +- contrib/gdb-7/bfd/dwarf2.c | 91 +- contrib/gdb-7/bfd/elf-bfd.h | 65 +- contrib/gdb-7/bfd/elf-eh-frame.c | 64 +- contrib/gdb-7/bfd/elf-ifunc.c | 7 +- contrib/gdb-7/bfd/elf.c | 198 +- contrib/gdb-7/bfd/elf32-i386.c | 652 +- contrib/gdb-7/bfd/elf64-x86-64.c | 499 +- contrib/gdb-7/bfd/elfcode.h | 88 +- contrib/gdb-7/bfd/elflink.c | 777 +- contrib/gdb-7/bfd/elfxx-target.h | 29 +- contrib/gdb-7/bfd/format.c | 40 +- contrib/gdb-7/bfd/hash.c | 76 +- contrib/gdb-7/bfd/ihex.c | 4 +- contrib/gdb-7/bfd/libbfd.c | 25 +- contrib/gdb-7/bfd/libbfd.h | 288 +- contrib/gdb-7/bfd/libcoff.h | 13 +- contrib/gdb-7/bfd/linker.c | 339 +- contrib/gdb-7/bfd/opncls.c | 6 +- contrib/gdb-7/bfd/reloc.c | 533 +- contrib/gdb-7/bfd/section.c | 18 +- contrib/gdb-7/bfd/simple.c | 7 +- contrib/gdb-7/bfd/srec.c | 5 +- contrib/gdb-7/bfd/targets.c | 46 +- contrib/gdb-7/bfd/tekhex.c | 4 +- contrib/gdb-7/bfd/verilog.c | 3 +- contrib/gdb-7/bfd/version.h | 2 +- contrib/gdb-7/gdb/README | 22 +- contrib/gdb-7/gdb/ada-exp.y | 16 +- contrib/gdb-7/gdb/ada-lang.c | 1033 +- contrib/gdb-7/gdb/ada-lang.h | 33 +- contrib/gdb-7/gdb/ada-lex.c | 4 +- contrib/gdb-7/gdb/ada-operator.def | 4 +- contrib/gdb-7/gdb/ada-operator.inc | 102 - contrib/gdb-7/gdb/ada-tasks.c | 876 +- contrib/gdb-7/gdb/ada-typeprint.c | 109 +- contrib/gdb-7/gdb/ada-valprint.c | 23 +- contrib/gdb-7/gdb/addrmap.c | 2 +- contrib/gdb-7/gdb/addrmap.h | 2 +- contrib/gdb-7/gdb/amd64-nat.c | 3 +- contrib/gdb-7/gdb/amd64-nat.h | 3 +- contrib/gdb-7/gdb/amd64-tdep.c | 159 +- contrib/gdb-7/gdb/amd64-tdep.h | 6 +- contrib/gdb-7/gdb/amd64bsd-nat.c | 3 +- contrib/gdb-7/gdb/annotate.c | 12 +- contrib/gdb-7/gdb/annotate.h | 4 +- contrib/gdb-7/gdb/arch-utils.c | 11 +- contrib/gdb-7/gdb/arch-utils.h | 9 +- contrib/gdb-7/gdb/auxv.c | 120 +- contrib/gdb-7/gdb/auxv.h | 3 +- contrib/gdb-7/gdb/ax-gdb.c | 118 +- contrib/gdb-7/gdb/ax-gdb.h | 7 +- contrib/gdb-7/gdb/ax-general.c | 3 +- contrib/gdb-7/gdb/ax.h | 3 +- contrib/gdb-7/gdb/bcache.c | 8 +- contrib/gdb-7/gdb/bcache.h | 4 +- contrib/gdb-7/gdb/bfd-target.c | 9 +- contrib/gdb-7/gdb/bfd-target.h | 3 +- contrib/gdb-7/gdb/block.c | 51 +- contrib/gdb-7/gdb/block.h | 12 +- contrib/gdb-7/gdb/blockframe.c | 6 +- contrib/gdb-7/gdb/breakpoint.c | 5612 +++--- contrib/gdb-7/gdb/breakpoint.h | 426 +- contrib/gdb-7/gdb/bsd-kvm.c | 3 +- contrib/gdb-7/gdb/bsd-kvm.h | 3 +- contrib/gdb-7/gdb/bsd-uthread.c | 3 +- contrib/gdb-7/gdb/bsd-uthread.h | 3 +- contrib/gdb-7/gdb/buildsym.c | 42 +- contrib/gdb-7/gdb/buildsym.h | 19 +- contrib/gdb-7/gdb/c-exp.y | 41 +- contrib/gdb-7/gdb/c-lang.c | 424 +- contrib/gdb-7/gdb/c-lang.h | 4 +- contrib/gdb-7/gdb/c-typeprint.c | 29 +- contrib/gdb-7/gdb/c-valprint.c | 22 +- contrib/gdb-7/gdb/call-cmds.h | 4 +- contrib/gdb-7/gdb/cc-with-index.sh | 9 +- contrib/gdb-7/gdb/charset-list.h | 2 +- contrib/gdb-7/gdb/charset.c | 26 +- contrib/gdb-7/gdb/charset.h | 3 +- contrib/gdb-7/gdb/cli-out.c | 6 +- contrib/gdb-7/gdb/cli-out.h | 3 +- contrib/gdb-7/gdb/cli/cli-cmds.c | 330 +- contrib/gdb-7/gdb/cli/cli-cmds.h | 5 +- contrib/gdb-7/gdb/cli/cli-decode.c | 47 +- contrib/gdb-7/gdb/cli/cli-decode.h | 3 +- contrib/gdb-7/gdb/cli/cli-dump.c | 19 +- contrib/gdb-7/gdb/cli/cli-dump.h | 3 +- contrib/gdb-7/gdb/cli/cli-interp.c | 50 +- contrib/gdb-7/gdb/cli/cli-logging.c | 8 +- contrib/gdb-7/gdb/cli/cli-script.c | 49 +- contrib/gdb-7/gdb/cli/cli-script.h | 3 +- contrib/gdb-7/gdb/cli/cli-setshow.c | 27 +- contrib/gdb-7/gdb/cli/cli-setshow.h | 3 +- contrib/gdb-7/gdb/cli/cli-utils.c | 2 +- contrib/gdb-7/gdb/cli/cli-utils.h | 2 +- contrib/gdb-7/gdb/coff-pe-read.c | 6 +- contrib/gdb-7/gdb/coff-pe-read.h | 3 +- contrib/gdb-7/gdb/coffread.c | 22 +- contrib/gdb-7/gdb/command.h | 6 +- contrib/gdb-7/gdb/common/ax.def | 6 +- contrib/gdb-7/gdb/common/buffer.c | 144 + contrib/gdb-7/gdb/common/buffer.h | 63 + contrib/gdb-7/gdb/common/common-utils.c | 168 + contrib/gdb-7/gdb/common/common-utils.h | 57 + contrib/gdb-7/gdb/{ => common}/gdb_assert.h | 9 +- .../gdb/{gdb_regex.h => common/gdb_dirent.h} | 35 +- contrib/gdb-7/gdb/{ => common}/gdb_locale.h | 3 +- contrib/gdb-7/gdb/common/gdb_signals.h | 4 +- .../gdb-7/gdb/{ => common}/gdb_thread_db.h | 18 +- contrib/gdb-7/gdb/common/i386-xstate.h | 2 +- contrib/gdb-7/gdb/common/linux-osdata.c | 588 + .../gdb/{ser-unix.h => common/linux-osdata.h} | 19 +- .../{tui/tui-main.c => common/linux-procfs.c} | 48 +- .../tui-command.h => common/linux-procfs.h} | 21 +- contrib/gdb-7/gdb/common/linux-ptrace.h | 68 + contrib/gdb-7/gdb/common/ptid.c | 92 + contrib/gdb-7/gdb/common/ptid.h | 85 + contrib/gdb-7/gdb/common/signals.c | 4 +- contrib/gdb-7/gdb/common/xml-utils.c | 90 + .../{tui/tui-command.h => common/xml-utils.h} | 16 +- contrib/gdb-7/gdb/complaints.c | 4 +- contrib/gdb-7/gdb/complaints.h | 4 +- contrib/gdb-7/gdb/completer.c | 3 +- contrib/gdb-7/gdb/completer.h | 3 +- contrib/gdb-7/gdb/config.in | 28 +- contrib/gdb-7/gdb/configure.ac | 93 +- contrib/gdb-7/gdb/configure.host | 1 - contrib/gdb-7/gdb/configure.tgt | 13 +- contrib/gdb-7/gdb/continuations.c | 326 + contrib/gdb-7/gdb/continuations.h | 74 + contrib/gdb-7/gdb/corefile.c | 3 +- contrib/gdb-7/gdb/corelow.c | 8 +- contrib/gdb-7/gdb/cp-abi.c | 6 +- contrib/gdb-7/gdb/cp-abi.h | 3 +- contrib/gdb-7/gdb/cp-name-parser.y | 141 +- contrib/gdb-7/gdb/cp-namespace.c | 481 +- contrib/gdb-7/gdb/cp-support.c | 458 +- contrib/gdb-7/gdb/cp-support.h | 68 +- contrib/gdb-7/gdb/cp-valprint.c | 21 +- contrib/gdb-7/gdb/d-lang.c | 5 +- contrib/gdb-7/gdb/d-lang.h | 3 +- contrib/gdb-7/gdb/d-valprint.c | 2 +- contrib/gdb-7/gdb/data-directory/Makefile.in | 6 +- contrib/gdb-7/gdb/dbxread.c | 43 +- contrib/gdb-7/gdb/dcache.c | 172 +- contrib/gdb-7/gdb/dcache.h | 4 +- contrib/gdb-7/gdb/defs.h | 166 +- contrib/gdb-7/gdb/demangle.c | 54 +- contrib/gdb-7/gdb/dfp.c | 2 +- contrib/gdb-7/gdb/dfp.h | 2 +- contrib/gdb-7/gdb/dictionary.c | 5 +- contrib/gdb-7/gdb/dictionary.h | 3 +- contrib/gdb-7/gdb/disasm.c | 3 +- contrib/gdb-7/gdb/disasm.h | 3 +- contrib/gdb-7/gdb/doc/GDBvn.texi | 4 - contrib/gdb-7/gdb/doc/agentexpr.texi | 8 +- contrib/gdb-7/gdb/doc/all-cfg.texi | 3 +- contrib/gdb-7/gdb/doc/annotate.texinfo | 4 +- contrib/gdb-7/gdb/doc/gdb.texinfo | 2898 ++- contrib/gdb-7/gdb/doc/gdbint.texinfo | 7 +- contrib/gdb-7/gdb/doc/observer.texi | 25 +- contrib/gdb-7/gdb/doc/stabs.texinfo | 5 +- contrib/gdb-7/gdb/doublest.c | 11 +- contrib/gdb-7/gdb/doublest.h | 5 +- contrib/gdb-7/gdb/dummy-frame.c | 6 +- contrib/gdb-7/gdb/dummy-frame.h | 3 +- contrib/gdb-7/gdb/dwarf2-frame-tailcall.c | 477 + .../tui-stack.h => dwarf2-frame-tailcall.h} | 29 +- contrib/gdb-7/gdb/dwarf2-frame.c | 353 +- contrib/gdb-7/gdb/dwarf2-frame.h | 3 +- contrib/gdb-7/gdb/dwarf2expr.c | 828 +- contrib/gdb-7/gdb/dwarf2expr.h | 144 +- contrib/gdb-7/gdb/dwarf2loc.c | 1291 +- contrib/gdb-7/gdb/dwarf2loc.h | 38 +- contrib/gdb-7/gdb/dwarf2read.c | 2218 ++- contrib/gdb-7/gdb/elfread.c | 76 +- contrib/gdb-7/gdb/environ.c | 4 +- contrib/gdb-7/gdb/environ.h | 4 +- contrib/gdb-7/gdb/eval.c | 65 +- contrib/gdb-7/gdb/event-loop.c | 58 +- contrib/gdb-7/gdb/event-loop.h | 5 +- contrib/gdb-7/gdb/event-top.c | 323 +- contrib/gdb-7/gdb/event-top.h | 59 +- contrib/gdb-7/gdb/exceptions.c | 84 +- contrib/gdb-7/gdb/exceptions.h | 24 +- contrib/gdb-7/gdb/exec.c | 4 +- contrib/gdb-7/gdb/exec.h | 3 +- contrib/gdb-7/gdb/expprint.c | 35 +- contrib/gdb-7/gdb/expression.h | 4 +- contrib/gdb-7/gdb/f-exp.y | 7 +- contrib/gdb-7/gdb/f-lang.c | 157 +- contrib/gdb-7/gdb/f-lang.h | 4 +- contrib/gdb-7/gdb/f-typeprint.c | 9 +- contrib/gdb-7/gdb/f-valprint.c | 45 +- contrib/gdb-7/gdb/fbsd-nat.c | 3 +- contrib/gdb-7/gdb/fbsd-nat.h | 3 +- contrib/gdb-7/gdb/features/feature_to_c.sh | 2 +- contrib/gdb-7/gdb/features/gdb-target.dtd | 2 +- contrib/gdb-7/gdb/features/i386/32bit-avx.xml | 2 +- .../gdb-7/gdb/features/i386/32bit-core.xml | 2 +- .../gdb-7/gdb/features/i386/32bit-linux.xml | 2 +- contrib/gdb-7/gdb/features/i386/32bit-sse.xml | 2 +- contrib/gdb-7/gdb/features/i386/64bit-avx.xml | 2 +- .../gdb-7/gdb/features/i386/64bit-core.xml | 2 +- .../gdb-7/gdb/features/i386/64bit-linux.xml | 2 +- contrib/gdb-7/gdb/features/i386/64bit-sse.xml | 2 +- .../gdb/features/i386/amd64-avx-linux.xml | 2 +- contrib/gdb-7/gdb/features/i386/amd64-avx.xml | 2 +- .../gdb-7/gdb/features/i386/amd64-linux.xml | 2 +- contrib/gdb-7/gdb/features/i386/amd64.xml | 2 +- .../gdb/features/i386/i386-avx-linux.xml | 2 +- contrib/gdb-7/gdb/features/i386/i386-avx.xml | 2 +- .../gdb-7/gdb/features/i386/i386-linux.xml | 2 +- .../gdb/features/i386/i386-mmx-linux.xml | 2 +- contrib/gdb-7/gdb/features/i386/i386-mmx.xml | 2 +- contrib/gdb-7/gdb/features/i386/i386.xml | 2 +- .../gdb-7/gdb/features/library-list-svr4.dtd | 16 + contrib/gdb-7/gdb/features/library-list.dtd | 2 +- contrib/gdb-7/gdb/features/osdata.dtd | 2 +- contrib/gdb-7/gdb/features/threads.dtd | 2 +- .../gdb-7/gdb/features/traceframe-info.dtd | 2 +- contrib/gdb-7/gdb/features/xinclude.dtd | 2 +- contrib/gdb-7/gdb/filesystem.c | 2 +- contrib/gdb-7/gdb/filesystem.h | 2 +- contrib/gdb-7/gdb/findcmd.c | 5 +- contrib/gdb-7/gdb/findvar.c | 101 +- contrib/gdb-7/gdb/fork-child.c | 100 +- contrib/gdb-7/gdb/frame-base.c | 3 +- contrib/gdb-7/gdb/frame-base.h | 3 +- contrib/gdb-7/gdb/frame-unwind.c | 3 +- contrib/gdb-7/gdb/frame-unwind.h | 3 +- contrib/gdb-7/gdb/frame.c | 55 +- contrib/gdb-7/gdb/frame.h | 101 +- contrib/gdb-7/gdb/gcore.c | 3 +- contrib/gdb-7/gdb/gcore.h | 2 +- contrib/gdb-7/gdb/gdb-demangle.h | 37 + contrib/gdb-7/gdb/gdb-dlfcn.c | 139 + contrib/gdb-7/gdb/gdb-dlfcn.h | 51 + contrib/gdb-7/gdb/gdb-gdb.py | 9 +- contrib/gdb-7/gdb/gdb-stabs.h | 4 +- contrib/gdb-7/gdb/gdb.1 | 2 +- contrib/gdb-7/gdb/gdb.c | 3 +- contrib/gdb-7/gdb/gdb.h | 3 +- contrib/gdb-7/gdb/gdb_curses.h | 11 +- contrib/gdb-7/gdb/gdb_obstack.h | 3 +- contrib/gdb-7/gdb/gdb_ptrace.h | 3 +- contrib/gdb-7/gdb/gdb_regex.h | 4 +- contrib/gdb-7/gdb/gdb_select.h | 3 +- contrib/gdb-7/gdb/gdb_stat.h | 3 +- contrib/gdb-7/gdb/gdb_string.h | 4 +- contrib/gdb-7/gdb/gdb_usleep.c | 2 +- contrib/gdb-7/gdb/gdb_usleep.h | 2 +- contrib/gdb-7/gdb/gdb_vfork.h | 3 +- contrib/gdb-7/gdb/gdb_wait.h | 9 +- contrib/gdb-7/gdb/gdb_wchar.h | 2 +- contrib/gdb-7/gdb/gdbarch.c | 85 +- contrib/gdb-7/gdb/gdbarch.h | 28 + contrib/gdb-7/gdb/gdbcmd.h | 6 +- contrib/gdb-7/gdb/gdbcore.h | 5 +- contrib/gdb-7/gdb/gdbthread.h | 43 +- contrib/gdb-7/gdb/gdbtypes.c | 88 +- contrib/gdb-7/gdb/gdbtypes.h | 131 +- contrib/gdb-7/gdb/gnu-v2-abi.c | 5 +- contrib/gdb-7/gdb/gnu-v3-abi.c | 9 +- contrib/gdb-7/gdb/i386-nat.c | 298 +- contrib/gdb-7/gdb/i386-nat.h | 2 +- contrib/gdb-7/gdb/i386-tdep.c | 376 +- contrib/gdb-7/gdb/i386-tdep.h | 12 +- contrib/gdb-7/gdb/i386bsd-nat.c | 12 +- contrib/gdb-7/gdb/i386bsd-nat.h | 3 +- contrib/gdb-7/gdb/i386bsd-tdep.c | 3 +- contrib/gdb-7/gdb/i386fbsd-tdep.c | 3 +- contrib/gdb-7/gdb/i387-tdep.c | 94 +- contrib/gdb-7/gdb/i387-tdep.h | 3 +- contrib/gdb-7/gdb/inf-child.c | 5 +- contrib/gdb-7/gdb/inf-child.h | 3 +- contrib/gdb-7/gdb/inf-loop.c | 93 +- contrib/gdb-7/gdb/inf-loop.h | 4 +- contrib/gdb-7/gdb/inf-ptrace.c | 7 +- contrib/gdb-7/gdb/inf-ptrace.h | 3 +- contrib/gdb-7/gdb/infcall.c | 33 +- contrib/gdb-7/gdb/infcall.h | 3 +- contrib/gdb-7/gdb/infcmd.c | 289 +- contrib/gdb-7/gdb/inferior.c | 9 +- contrib/gdb-7/gdb/inferior.h | 69 +- contrib/gdb-7/gdb/inflow.c | 4 +- contrib/gdb-7/gdb/inflow.h | 3 +- contrib/gdb-7/gdb/infrun.c | 814 +- contrib/gdb-7/gdb/inline-frame.c | 4 +- contrib/gdb-7/gdb/inline-frame.h | 2 +- contrib/gdb-7/gdb/interps.c | 54 +- contrib/gdb-7/gdb/interps.h | 29 +- contrib/gdb-7/gdb/jit-reader.in | 344 + contrib/gdb-7/gdb/jit.c | 882 +- contrib/gdb-7/gdb/jit.h | 2 +- contrib/gdb-7/gdb/jv-exp.y | 3 +- contrib/gdb-7/gdb/jv-lang.c | 229 +- contrib/gdb-7/gdb/jv-lang.h | 4 +- contrib/gdb-7/gdb/jv-typeprint.c | 7 +- contrib/gdb-7/gdb/jv-valprint.c | 3 +- contrib/gdb-7/gdb/language.c | 11 +- contrib/gdb-7/gdb/language.h | 42 +- contrib/gdb-7/gdb/linespec.c | 2700 ++- contrib/gdb-7/gdb/linespec.h | 117 +- contrib/gdb-7/gdb/m2-exp.y | 4 +- contrib/gdb-7/gdb/m2-lang.c | 6 +- contrib/gdb-7/gdb/m2-lang.h | 4 +- contrib/gdb-7/gdb/m2-typeprint.c | 5 +- contrib/gdb-7/gdb/m2-valprint.c | 4 +- contrib/gdb-7/gdb/macrocmd.c | 185 +- contrib/gdb-7/gdb/macroexp.c | 3 +- contrib/gdb-7/gdb/macroexp.h | 3 +- contrib/gdb-7/gdb/macroscope.c | 3 +- contrib/gdb-7/gdb/macroscope.h | 3 +- contrib/gdb-7/gdb/macrotab.c | 9 +- contrib/gdb-7/gdb/macrotab.h | 12 +- contrib/gdb-7/gdb/main.c | 48 +- contrib/gdb-7/gdb/main.h | 3 +- contrib/gdb-7/gdb/maint.c | 18 +- contrib/gdb-7/gdb/mdebugread.c | 87 +- contrib/gdb-7/gdb/mdebugread.h | 3 +- contrib/gdb-7/gdb/mem-break.c | 12 +- contrib/gdb-7/gdb/memattr.c | 3 +- contrib/gdb-7/gdb/memattr.h | 3 +- contrib/gdb-7/gdb/memory-map.c | 3 +- contrib/gdb-7/gdb/memory-map.h | 3 +- contrib/gdb-7/gdb/memrange.c | 2 +- contrib/gdb-7/gdb/memrange.h | 2 +- contrib/gdb-7/gdb/mi/mi-cmd-break.c | 20 +- contrib/gdb-7/gdb/mi/mi-cmd-disas.c | 6 +- contrib/gdb-7/gdb/mi/mi-cmd-env.c | 14 +- contrib/gdb-7/gdb/mi/mi-cmd-file.c | 10 +- contrib/gdb-7/gdb/mi/mi-cmd-stack.c | 162 +- contrib/gdb-7/gdb/mi/mi-cmd-target.c | 14 +- contrib/gdb-7/gdb/mi/mi-cmd-var.c | 23 +- contrib/gdb-7/gdb/mi/mi-cmds.c | 5 +- contrib/gdb-7/gdb/mi/mi-cmds.h | 5 +- contrib/gdb-7/gdb/mi/mi-common.c | 23 +- contrib/gdb-7/gdb/mi/mi-common.h | 12 +- contrib/gdb-7/gdb/mi/mi-console.c | 3 +- contrib/gdb-7/gdb/mi/mi-console.h | 3 +- contrib/gdb-7/gdb/mi/mi-getopt.c | 9 +- contrib/gdb-7/gdb/mi/mi-getopt.h | 5 +- contrib/gdb-7/gdb/mi/mi-interp.c | 155 +- contrib/gdb-7/gdb/mi/mi-main.c | 118 +- contrib/gdb-7/gdb/mi/mi-main.h | 4 +- contrib/gdb-7/gdb/mi/mi-out.c | 32 +- contrib/gdb-7/gdb/mi/mi-out.h | 3 +- contrib/gdb-7/gdb/mi/mi-parse.c | 7 +- contrib/gdb-7/gdb/mi/mi-parse.h | 3 +- contrib/gdb-7/gdb/mi/mi-symbol-cmds.c | 4 +- contrib/gdb-7/gdb/minsyms.c | 59 +- contrib/gdb-7/gdb/mipsread.c | 5 +- contrib/gdb-7/gdb/objc-exp.y | 8 +- contrib/gdb-7/gdb/objc-lang.c | 293 +- contrib/gdb-7/gdb/objc-lang.h | 15 +- contrib/gdb-7/gdb/objfiles.c | 30 +- contrib/gdb-7/gdb/objfiles.h | 59 +- contrib/gdb-7/gdb/observer.c | 3 +- contrib/gdb-7/gdb/observer.sh | 4 +- contrib/gdb-7/gdb/opencl-lang.c | 9 +- contrib/gdb-7/gdb/osabi.c | 17 +- contrib/gdb-7/gdb/osabi.h | 3 +- contrib/gdb-7/gdb/osdata.c | 56 +- contrib/gdb-7/gdb/osdata.h | 2 +- contrib/gdb-7/gdb/p-exp.y | 7 +- contrib/gdb-7/gdb/p-lang.c | 6 +- contrib/gdb-7/gdb/p-lang.h | 5 +- contrib/gdb-7/gdb/p-typeprint.c | 20 +- contrib/gdb-7/gdb/p-valprint.c | 21 +- contrib/gdb-7/gdb/parse.c | 37 +- contrib/gdb-7/gdb/parser-defs.h | 7 +- contrib/gdb-7/gdb/posix-hdep.c | 3 +- contrib/gdb-7/gdb/printcmd.c | 50 +- contrib/gdb-7/gdb/proc-service.list | 2 +- contrib/gdb-7/gdb/progspace.c | 4 +- contrib/gdb-7/gdb/progspace.h | 5 +- contrib/gdb-7/gdb/prologue-value.c | 5 +- contrib/gdb-7/gdb/prologue-value.h | 3 +- contrib/gdb-7/gdb/psympriv.h | 11 +- contrib/gdb-7/gdb/psymtab.c | 163 +- contrib/gdb-7/gdb/psymtab.h | 12 +- contrib/gdb-7/gdb/python/lib/gdb/__init__.py | 29 +- .../gdb/python/lib/gdb/command/__init__.py | 2 +- .../python/lib/gdb/command/pretty_printers.py | 6 +- .../gdb/python/lib/gdb/command/prompt.py | 66 + contrib/gdb-7/gdb/python/lib/gdb/printing.py | 41 +- contrib/gdb-7/gdb/python/lib/gdb/prompt.py | 149 + contrib/gdb-7/gdb/python/lib/gdb/types.py | 22 +- contrib/gdb-7/gdb/python/py-auto-load.c | 289 +- contrib/gdb-7/gdb/python/py-block.c | 117 +- contrib/gdb-7/gdb/python/py-bpevent.c | 10 +- contrib/gdb-7/gdb/python/py-breakpoint.c | 168 +- contrib/gdb-7/gdb/python/py-cmd.c | 49 +- contrib/gdb-7/gdb/python/py-continueevent.c | 2 +- contrib/gdb-7/gdb/python/py-event.c | 2 +- contrib/gdb-7/gdb/python/py-event.h | 5 +- contrib/gdb-7/gdb/python/py-events.h | 5 +- contrib/gdb-7/gdb/python/py-evtregistry.c | 4 +- contrib/gdb-7/gdb/python/py-evts.c | 5 +- contrib/gdb-7/gdb/python/py-exitedevent.c | 15 +- .../gdb-7/gdb/python/py-finishbreakpoint.c | 462 + contrib/gdb-7/gdb/python/py-frame.c | 111 +- contrib/gdb-7/gdb/python/py-function.c | 39 +- contrib/gdb-7/gdb/python/py-inferior.c | 129 +- contrib/gdb-7/gdb/python/py-infthread.c | 3 +- contrib/gdb-7/gdb/python/py-lazy-string.c | 12 +- contrib/gdb-7/gdb/python/py-newobjfileevent.c | 70 + contrib/gdb-7/gdb/python/py-objfile.c | 2 +- contrib/gdb-7/gdb/python/py-param.c | 8 +- contrib/gdb-7/gdb/python/py-prettyprint.c | 4 +- contrib/gdb-7/gdb/python/py-progspace.c | 2 +- contrib/gdb-7/gdb/python/py-signalevent.c | 2 +- contrib/gdb-7/gdb/python/py-stopevent.c | 45 +- contrib/gdb-7/gdb/python/py-stopevent.h | 5 +- contrib/gdb-7/gdb/python/py-symbol.c | 40 +- contrib/gdb-7/gdb/python/py-symtab.c | 2 +- contrib/gdb-7/gdb/python/py-threadevent.c | 2 +- contrib/gdb-7/gdb/python/py-type.c | 678 +- contrib/gdb-7/gdb/python/py-utils.c | 2 +- contrib/gdb-7/gdb/python/py-value.c | 181 +- contrib/gdb-7/gdb/python/python-internal.h | 69 +- contrib/gdb-7/gdb/python/python.c | 394 +- contrib/gdb-7/gdb/python/python.h | 4 +- contrib/gdb-7/gdb/ravenscar-sparc-thread.c | 2 +- contrib/gdb-7/gdb/ravenscar-thread.c | 9 +- contrib/gdb-7/gdb/ravenscar-thread.h | 2 +- contrib/gdb-7/gdb/record.c | 169 +- contrib/gdb-7/gdb/record.h | 2 +- contrib/gdb-7/gdb/regcache.c | 136 +- contrib/gdb-7/gdb/regcache.h | 16 +- contrib/gdb-7/gdb/regformats/regdat.sh | 3 +- contrib/gdb-7/gdb/regformats/regdef.h | 3 +- contrib/gdb-7/gdb/reggroups.c | 3 +- contrib/gdb-7/gdb/reggroups.h | 3 +- contrib/gdb-7/gdb/regset.c | 3 +- contrib/gdb-7/gdb/regset.h | 3 +- contrib/gdb-7/gdb/remote-fileio.c | 17 +- contrib/gdb-7/gdb/remote-fileio.h | 3 +- contrib/gdb-7/gdb/remote.c | 851 +- contrib/gdb-7/gdb/remote.h | 7 +- contrib/gdb-7/gdb/reverse.c | 8 +- contrib/gdb-7/gdb/scm-exp.c | 502 - contrib/gdb-7/gdb/scm-lang.c | 308 - contrib/gdb-7/gdb/scm-lang.h | 77 - contrib/gdb-7/gdb/scm-tags.h | 378 - contrib/gdb-7/gdb/scm-valprint.c | 462 - contrib/gdb-7/gdb/sentinel-frame.c | 19 +- contrib/gdb-7/gdb/sentinel-frame.h | 3 +- contrib/gdb-7/gdb/ser-base.c | 5 +- contrib/gdb-7/gdb/ser-base.h | 3 +- contrib/gdb-7/gdb/ser-pipe.c | 3 +- contrib/gdb-7/gdb/ser-tcp.c | 6 +- contrib/gdb-7/gdb/ser-tcp.h | 3 +- contrib/gdb-7/gdb/ser-unix.c | 4 +- contrib/gdb-7/gdb/ser-unix.h | 4 +- contrib/gdb-7/gdb/serial.c | 4 +- contrib/gdb-7/gdb/serial.h | 6 +- contrib/gdb-7/gdb/sim-regno.h | 3 +- contrib/gdb-7/gdb/skip.c | 602 + .../gdb-7/gdb/{tui/tui-command.h => skip.h} | 22 +- contrib/gdb-7/gdb/solib-svr4.c | 908 +- contrib/gdb-7/gdb/solib-svr4.h | 3 +- contrib/gdb-7/gdb/solib-target.c | 60 +- contrib/gdb-7/gdb/solib-target.h | 2 +- contrib/gdb-7/gdb/solib.c | 310 +- contrib/gdb-7/gdb/solib.h | 17 +- contrib/gdb-7/gdb/solist.h | 24 +- contrib/gdb-7/gdb/source.c | 146 +- contrib/gdb-7/gdb/source.h | 3 +- contrib/gdb-7/gdb/stabsread.c | 9 +- contrib/gdb-7/gdb/stabsread.h | 5 +- contrib/gdb-7/gdb/stack.c | 715 +- contrib/gdb-7/gdb/stack.h | 13 +- contrib/gdb-7/gdb/std-operator.def | 15 +- contrib/gdb-7/gdb/std-regs.c | 3 +- contrib/gdb-7/gdb/symfile.c | 183 +- contrib/gdb-7/gdb/symfile.h | 150 +- contrib/gdb-7/gdb/symmisc.c | 45 +- contrib/gdb-7/gdb/symtab.c | 789 +- contrib/gdb-7/gdb/symtab.h | 136 +- contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd | 2 +- contrib/gdb-7/gdb/target-descriptions.c | 3 +- contrib/gdb-7/gdb/target-descriptions.h | 3 +- contrib/gdb-7/gdb/target-memory.c | 3 +- contrib/gdb-7/gdb/target.c | 283 +- contrib/gdb-7/gdb/target.h | 162 +- contrib/gdb-7/gdb/terminal.h | 4 +- contrib/gdb-7/gdb/thread.c | 101 +- contrib/gdb-7/gdb/top.c | 146 +- contrib/gdb-7/gdb/top.h | 25 +- contrib/gdb-7/gdb/tracepoint.c | 658 +- contrib/gdb-7/gdb/tracepoint.h | 46 +- contrib/gdb-7/gdb/trad-frame.c | 3 +- contrib/gdb-7/gdb/trad-frame.h | 3 +- contrib/gdb-7/gdb/tramp-frame.c | 3 +- contrib/gdb-7/gdb/tramp-frame.h | 3 +- contrib/gdb-7/gdb/tui/tui-command.c | 3 +- contrib/gdb-7/gdb/tui/tui-command.h | 4 +- contrib/gdb-7/gdb/tui/tui-data.c | 3 +- contrib/gdb-7/gdb/tui/tui-data.h | 4 +- contrib/gdb-7/gdb/tui/tui-disasm.c | 3 +- contrib/gdb-7/gdb/tui/tui-disasm.h | 4 +- contrib/gdb-7/gdb/tui/tui-file.c | 3 +- contrib/gdb-7/gdb/tui/tui-file.h | 3 +- contrib/gdb-7/gdb/tui/tui-hooks.c | 9 +- contrib/gdb-7/gdb/tui/tui-hooks.h | 3 +- contrib/gdb-7/gdb/tui/tui-interp.c | 99 +- contrib/gdb-7/gdb/tui/tui-io.c | 23 +- contrib/gdb-7/gdb/tui/tui-io.h | 4 +- contrib/gdb-7/gdb/tui/tui-layout.c | 3 +- contrib/gdb-7/gdb/tui/tui-layout.h | 4 +- contrib/gdb-7/gdb/tui/tui-main.c | 8 +- contrib/gdb-7/gdb/tui/tui-out.c | 4 +- contrib/gdb-7/gdb/tui/tui-regs.c | 59 +- contrib/gdb-7/gdb/tui/tui-regs.h | 4 +- contrib/gdb-7/gdb/tui/tui-source.c | 3 +- contrib/gdb-7/gdb/tui/tui-source.h | 4 +- contrib/gdb-7/gdb/tui/tui-stack.c | 11 +- contrib/gdb-7/gdb/tui/tui-stack.h | 4 +- contrib/gdb-7/gdb/tui/tui-win.c | 3 +- contrib/gdb-7/gdb/tui/tui-win.h | 4 +- contrib/gdb-7/gdb/tui/tui-windata.c | 3 +- contrib/gdb-7/gdb/tui/tui-windata.h | 4 +- contrib/gdb-7/gdb/tui/tui-wingeneral.c | 3 +- contrib/gdb-7/gdb/tui/tui-wingeneral.h | 4 +- contrib/gdb-7/gdb/tui/tui-winsource.c | 50 +- contrib/gdb-7/gdb/tui/tui-winsource.h | 4 +- contrib/gdb-7/gdb/tui/tui.c | 3 +- contrib/gdb-7/gdb/tui/tui.h | 4 +- contrib/gdb-7/gdb/typeprint.c | 9 +- contrib/gdb-7/gdb/typeprint.h | 4 +- contrib/gdb-7/gdb/ui-file.c | 67 +- contrib/gdb-7/gdb/ui-file.h | 17 +- contrib/gdb-7/gdb/ui-out.c | 17 +- contrib/gdb-7/gdb/ui-out.h | 10 +- contrib/gdb-7/gdb/unwind_stop_reasons.def | 80 + contrib/gdb-7/gdb/user-regs.c | 3 +- contrib/gdb-7/gdb/user-regs.h | 3 +- contrib/gdb-7/gdb/utils.c | 776 +- contrib/gdb-7/gdb/valarith.c | 14 +- contrib/gdb-7/gdb/valops.c | 195 +- contrib/gdb-7/gdb/valprint.c | 467 +- contrib/gdb-7/gdb/valprint.h | 13 +- contrib/gdb-7/gdb/value.c | 119 +- contrib/gdb-7/gdb/value.h | 50 +- contrib/gdb-7/gdb/varobj.c | 139 +- contrib/gdb-7/gdb/varobj.h | 6 +- contrib/gdb-7/gdb/vec.c | 3 +- contrib/gdb-7/gdb/vec.h | 3 +- contrib/gdb-7/gdb/version.h | 3 +- contrib/gdb-7/gdb/version.in | 2 +- contrib/gdb-7/gdb/wrapper.c | 26 +- contrib/gdb-7/gdb/wrapper.h | 6 +- contrib/gdb-7/gdb/xcoffsolib.h | 4 +- contrib/gdb-7/gdb/xml-support.c | 69 +- contrib/gdb-7/gdb/xml-support.h | 9 +- contrib/gdb-7/gdb/xml-syscall.c | 2 +- contrib/gdb-7/gdb/xml-syscall.h | 2 +- contrib/gdb-7/gdb/xml-tdesc.c | 2 +- contrib/gdb-7/gdb/xml-tdesc.h | 2 +- contrib/gdb-7/include/ansidecl.h | 11 + contrib/gdb-7/include/bfdlink.h | 254 +- contrib/gdb-7/include/demangle.h | 17 +- contrib/gdb-7/include/dis-asm.h | 8 +- contrib/gdb-7/include/dwarf2.h | 25 + contrib/gdb-7/include/dyn-string.h | 73 + contrib/gdb-7/include/elf/common.h | 23 +- contrib/gdb-7/include/elf/mips.h | 84 +- contrib/gdb-7/include/elf/reloc-macros.h | 6 +- contrib/gdb-7/include/elf/x86-64.h | 1 + contrib/gdb-7/include/filenames.h | 8 + contrib/gdb-7/include/gdb/fileio.h | 2 +- contrib/gdb-7/include/gdb/signals.def | 2 +- contrib/gdb-7/include/gdb/signals.h | 4 +- contrib/gdb-7/include/gdb/sim-bfin.h | 2 +- contrib/gdb-7/include/libiberty.h | 9 +- contrib/gdb-7/include/mach-o/ChangeLog | 19 + contrib/gdb-7/include/mach-o/external.h | 273 + contrib/gdb-7/include/mach-o/loader.h | 345 + contrib/gdb-7/include/mach-o/reloc.h | 53 + contrib/gdb-7/include/mach-o/x86-64.h | 37 + contrib/gdb-7/include/obstack.h | 6 +- .../timeval-utils.h} | 42 +- contrib/gdb-7/include/xregex.h | 1 + contrib/gdb-7/libdecnumber/decNumber.c | 80 +- contrib/gdb-7/libiberty/argv.c | 23 + contrib/gdb-7/libiberty/cp-demangle.c | 227 +- contrib/gdb-7/libiberty/cp-demint.c | 6 +- contrib/gdb-7/libiberty/cplus-dem.c | 3 +- contrib/gdb-7/libiberty/dyn-string.c | 397 + contrib/gdb-7/libiberty/filename_cmp.c | 28 +- contrib/gdb-7/libiberty/getpwd.c | 128 + contrib/gdb-7/libiberty/pex-common.c | 9 +- contrib/gdb-7/libiberty/regex.c | 11 +- contrib/gdb-7/libiberty/setproctitle.c | 4 +- .../gdb-7/libiberty/simple-object-mach-o.c | 515 +- contrib/gdb-7/libiberty/stack-limit.c | 62 + contrib/gdb-7/libiberty/timeval-utils.c | 87 + contrib/gdb-7/opcodes/disassemble.c | 27 +- contrib/gdb-7/opcodes/i386-dis.c | 1893 +- contrib/gdb-7/opcodes/i386-opc.h | 32 +- contrib/gdb-7/opcodes/i386-tbl.h | 15307 +++++++++------- .../doc/{inc-hist.texinfo => hsuser.texi} | 36 +- contrib/gdb-7/readline/doc/rluser.texi | 283 +- 617 files changed, 48339 insertions(+), 24294 deletions(-) delete mode 100644 contrib/gdb-7/gdb/ada-operator.inc create mode 100644 contrib/gdb-7/gdb/common/buffer.c create mode 100644 contrib/gdb-7/gdb/common/buffer.h create mode 100644 contrib/gdb-7/gdb/common/common-utils.c create mode 100644 contrib/gdb-7/gdb/common/common-utils.h rename contrib/gdb-7/gdb/{ => common}/gdb_assert.h (89%) copy contrib/gdb-7/gdb/{gdb_regex.h => common/gdb_dirent.h} (52%) rename contrib/gdb-7/gdb/{ => common}/gdb_locale.h (94%) rename contrib/gdb-7/gdb/{ => common}/gdb_thread_db.h (96%) create mode 100644 contrib/gdb-7/gdb/common/linux-osdata.c copy contrib/gdb-7/gdb/{ser-unix.h => common/linux-osdata.h} (65%) copy contrib/gdb-7/gdb/{tui/tui-main.c => common/linux-procfs.c} (50%) copy contrib/gdb-7/gdb/{tui/tui-command.h => common/linux-procfs.h} (66%) create mode 100644 contrib/gdb-7/gdb/common/linux-ptrace.h create mode 100644 contrib/gdb-7/gdb/common/ptid.c create mode 100644 contrib/gdb-7/gdb/common/ptid.h create mode 100644 contrib/gdb-7/gdb/common/xml-utils.c copy contrib/gdb-7/gdb/{tui/tui-command.h => common/xml-utils.h} (69%) create mode 100644 contrib/gdb-7/gdb/continuations.c create mode 100644 contrib/gdb-7/gdb/continuations.h delete mode 100644 contrib/gdb-7/gdb/doc/GDBvn.texi create mode 100644 contrib/gdb-7/gdb/dwarf2-frame-tailcall.c copy contrib/gdb-7/gdb/{tui/tui-stack.h => dwarf2-frame-tailcall.h} (52%) create mode 100644 contrib/gdb-7/gdb/features/library-list-svr4.dtd create mode 100644 contrib/gdb-7/gdb/gdb-demangle.h create mode 100644 contrib/gdb-7/gdb/gdb-dlfcn.c create mode 100644 contrib/gdb-7/gdb/gdb-dlfcn.h create mode 100644 contrib/gdb-7/gdb/jit-reader.in create mode 100644 contrib/gdb-7/gdb/python/lib/gdb/command/prompt.py create mode 100644 contrib/gdb-7/gdb/python/lib/gdb/prompt.py create mode 100644 contrib/gdb-7/gdb/python/py-finishbreakpoint.c create mode 100644 contrib/gdb-7/gdb/python/py-newobjfileevent.c delete mode 100644 contrib/gdb-7/gdb/scm-exp.c delete mode 100644 contrib/gdb-7/gdb/scm-lang.c delete mode 100644 contrib/gdb-7/gdb/scm-lang.h delete mode 100644 contrib/gdb-7/gdb/scm-tags.h delete mode 100644 contrib/gdb-7/gdb/scm-valprint.c create mode 100644 contrib/gdb-7/gdb/skip.c copy contrib/gdb-7/gdb/{tui/tui-command.h => skip.h} (59%) create mode 100644 contrib/gdb-7/gdb/unwind_stop_reasons.def create mode 100644 contrib/gdb-7/include/dyn-string.h create mode 100644 contrib/gdb-7/include/mach-o/ChangeLog create mode 100644 contrib/gdb-7/include/mach-o/external.h create mode 100644 contrib/gdb-7/include/mach-o/loader.h create mode 100644 contrib/gdb-7/include/mach-o/reloc.h create mode 100644 contrib/gdb-7/include/mach-o/x86-64.h copy contrib/gdb-7/{libiberty/setproctitle.c => include/timeval-utils.h} (54%) create mode 100644 contrib/gdb-7/libiberty/dyn-string.c create mode 100644 contrib/gdb-7/libiberty/getpwd.c create mode 100644 contrib/gdb-7/libiberty/stack-limit.c create mode 100644 contrib/gdb-7/libiberty/timeval-utils.c rename contrib/gdb-7/readline/doc/{inc-hist.texinfo => hsuser.texi} (92%) diff --git a/contrib/gdb-7/bfd/archive.c b/contrib/gdb-7/bfd/archive.c index 86d07e9f4a..3e333c7e89 100644 --- a/contrib/gdb-7/bfd/archive.c +++ b/contrib/gdb-7/bfd/archive.c @@ -343,6 +343,7 @@ static bfd * _bfd_find_nested_archive (bfd *arch_bfd, const char *filename) { bfd *abfd; + const char *target; for (abfd = arch_bfd->nested_archives; abfd != NULL; @@ -351,7 +352,10 @@ _bfd_find_nested_archive (bfd *arch_bfd, const char *filename) if (filename_cmp (filename, abfd->filename) == 0) return abfd; } - abfd = bfd_openr (filename, NULL); + target = NULL; + if (!arch_bfd->target_defaulted) + target = arch_bfd->xvec->name; + abfd = bfd_openr (filename, target); if (abfd) { abfd->archive_next = arch_bfd->nested_archives; @@ -597,6 +601,8 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) if (bfd_is_thin_archive (archive)) { + const char *target; + /* This is a proxy entry for an external file. */ if (! IS_ABSOLUTE_PATH (filename)) { @@ -628,7 +634,12 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) } /* It's not an element of a nested archive; open the external file as a bfd. */ - n_nfd = bfd_openr (filename, NULL); + target = NULL; + if (!archive->target_defaulted) + target = archive->xvec->name; + n_nfd = bfd_openr (filename, target); + if (n_nfd == NULL) + bfd_set_error (bfd_error_malformed_archive); } else { @@ -661,10 +672,6 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos) if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd)) return n_nfd; - /* Huh? */ - /* FIXME: n_nfd isn't allocated in the archive's memory pool. - If we reach this point, I think bfd_release will abort. */ - bfd_release (archive, n_nfd); bfd_release (archive, new_areldata); return NULL; } @@ -721,6 +728,7 @@ bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file) else { unsigned int size = arelt_size (last_file); + filestart = last_file->proxy_origin; if (! bfd_is_thin_archive (archive)) filestart += size; @@ -754,7 +762,7 @@ bfd_generic_archive_p (bfd *abfd) if (strncmp (armag, ARMAG, SARMAG) != 0 && strncmp (armag, ARMAGB, SARMAG) != 0 && ! bfd_is_thin_archive (abfd)) - return 0; + return NULL; tdata_hold = bfd_ardata (abfd); @@ -785,7 +793,7 @@ bfd_generic_archive_p (bfd *abfd) return NULL; } - if (bfd_has_map (abfd)) + if (abfd->target_defaulted && bfd_has_map (abfd)) { bfd *first; @@ -1337,19 +1345,51 @@ normalize (bfd *abfd ATTRIBUTE_UNUSED, const char *file) } #endif -/* Adjust a relative path name based on the reference path. */ - +/* Adjust a relative path name based on the reference path. + For example: + + Relative path Reference path Result + ------------- -------------- ------ + bar.o lib.a bar.o + foo/bar.o lib.a foo/bar.o + bar.o foo/lib.a ../bar.o + foo/bar.o baz/lib.a ../foo/bar.o + bar.o ../lib.a /bar.o + ; ../bar.o ../lib.a bar.o + ; ../bar.o lib.a ../bar.o + foo/bar.o ../lib.a /foo/bar.o + bar.o ../../lib.a //bar.o + bar.o foo/baz/lib.a ../../bar.o + + Note - the semicolons above are there to prevent the BFD chew + utility from interpreting those lines as prototypes to put into + the autogenerated bfd.h header... + + Note - the string is returned in a static buffer. */ + static const char * adjust_relative_path (const char * path, const char * ref_path) { static char *pathbuf = NULL; - static int pathbuf_len = 0; - const char *pathp = path; - const char *refp = ref_path; - int element_count = 0; - int len; + static unsigned int pathbuf_len = 0; + const char *pathp; + const char *refp; + char * lpath; + char * rpath; + unsigned int len; + unsigned int dir_up = 0; + unsigned int dir_down = 0; char *newp; + char * pwd = getpwd (); + const char * down; + /* Remove symlinks, '.' and '..' from the paths, if possible. */ + lpath = lrealpath (path); + pathp = lpath == NULL ? path : lpath; + + rpath = lrealpath (ref_path); + refp = rpath == NULL ? ref_path : rpath; + /* Remove common leading path elements. */ for (;;) { @@ -1367,12 +1407,42 @@ adjust_relative_path (const char * path, const char * ref_path) refp = e2 + 1; } + len = strlen (pathp) + 1; /* For each leading path element in the reference path, insert "../" into the path. */ for (; *refp; ++refp) if (IS_DIR_SEPARATOR (*refp)) - ++element_count; - len = 3 * element_count + strlen (path) + 1; + { + /* PR 12710: If the path element is "../" then instead of + inserting "../" we need to insert the name of the directory + at the current level. */ + if (refp > ref_path + 1 + && refp[-1] == '.' + && refp[-2] == '.') + dir_down ++; + else + dir_up ++; + } + + /* If the lrealpath calls above succeeded then we should never + see dir_up and dir_down both being non-zero. */ + + len += 3 * dir_up; + + if (dir_down) + { + down = pwd + strlen (pwd) - 1; + + while (dir_down && down > pwd) + { + if (IS_DIR_SEPARATOR (*down)) + --dir_down; + } + BFD_ASSERT (dir_down == 0); + len += strlen (down) + 1; + } + else + down = NULL; if (len > pathbuf_len) { @@ -1381,19 +1451,26 @@ adjust_relative_path (const char * path, const char * ref_path) pathbuf_len = 0; pathbuf = (char *) bfd_malloc (len); if (pathbuf == NULL) - return path; + goto out; pathbuf_len = len; } newp = pathbuf; - while (element_count-- > 0) + while (dir_up-- > 0) { /* FIXME: Support Windows style path separators as well. */ strcpy (newp, "../"); newp += 3; } - strcpy (newp, pathp); + if (down) + sprintf (newp, "%s/%s", down, pathp); + else + strcpy (newp, pathp); + + out: + free (lpath); + free (rpath); return pathbuf; } @@ -1435,7 +1512,7 @@ _bfd_construct_extended_name_table (bfd *abfd, char **tabloc, bfd_size_type *tablen) { - unsigned int maxname = abfd->xvec->ar_max_namelen; + unsigned int maxname = ar_maxnamelen (abfd); bfd_size_type total_namelen = 0; bfd *current; char *strptr; @@ -1630,7 +1707,7 @@ _bfd_archive_bsd44_construct_extended_name_table (bfd *abfd, bfd_size_type *tablen, const char **name) { - unsigned int maxname = abfd->xvec->ar_max_namelen; + unsigned int maxname = ar_maxnamelen (abfd); bfd *current; *tablen = 0; diff --git a/contrib/gdb-7/bfd/archures.c b/contrib/gdb-7/bfd/archures.c index cd8500f779..f609534900 100644 --- a/contrib/gdb-7/bfd/archures.c +++ b/contrib/gdb-7/bfd/archures.c @@ -1,6 +1,6 @@ /* BFD library support routines for architectures. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Hacked by John Gilmore and Steve Chamberlain of Cygnus Support. @@ -176,22 +176,29 @@ DESCRIPTION .#define bfd_mach_mips_loongson_3a 3003 .#define bfd_mach_mips_sb1 12310201 {* octal 'SB', 01 *} .#define bfd_mach_mips_octeon 6501 +.#define bfd_mach_mips_octeonp 6601 +.#define bfd_mach_mips_octeon2 6502 .#define bfd_mach_mips_xlr 887682 {* decimal 'XLR' *} .#define bfd_mach_mipsisa32 32 .#define bfd_mach_mipsisa32r2 33 .#define bfd_mach_mipsisa64 64 .#define bfd_mach_mipsisa64r2 65 +.#define bfd_mach_mips_micromips 96 . bfd_arch_i386, {* Intel 386 *} -.#define bfd_mach_i386_i386 1 -.#define bfd_mach_i386_i8086 2 -.#define bfd_mach_i386_i386_intel_syntax 3 -.#define bfd_mach_x64_32 32 -.#define bfd_mach_x64_32_intel_syntax 33 -.#define bfd_mach_x86_64 64 -.#define bfd_mach_x86_64_intel_syntax 65 +.#define bfd_mach_i386_intel_syntax (1 << 0) +.#define bfd_mach_i386_i8086 (1 << 1) +.#define bfd_mach_i386_i386 (1 << 2) +.#define bfd_mach_x86_64 (1 << 3) +.#define bfd_mach_x64_32 (1 << 4) +.#define bfd_mach_i386_i386_intel_syntax (bfd_mach_i386_i386 | bfd_mach_i386_intel_syntax) +.#define bfd_mach_x86_64_intel_syntax (bfd_mach_x86_64 | bfd_mach_i386_intel_syntax) +.#define bfd_mach_x64_32_intel_syntax (bfd_mach_x64_32 | bfd_mach_i386_intel_syntax) . bfd_arch_l1om, {* Intel L1OM *} -.#define bfd_mach_l1om 66 -.#define bfd_mach_l1om_intel_syntax 67 +.#define bfd_mach_l1om (1 << 5) +.#define bfd_mach_l1om_intel_syntax (bfd_mach_l1om | bfd_mach_i386_intel_syntax) +. bfd_arch_k1om, {* Intel K1OM *} +.#define bfd_mach_k1om (1 << 6) +.#define bfd_mach_k1om_intel_syntax (bfd_mach_k1om | bfd_mach_i386_intel_syntax) . bfd_arch_we32k, {* AT&T WE32xxx *} . bfd_arch_tahoe, {* CCI/Harris Tahoe *} . bfd_arch_i860, {* Intel 860 *} @@ -360,6 +367,9 @@ DESCRIPTION . bfd_arch_iq2000, {* Vitesse IQ2000. *} .#define bfd_mach_iq2000 1 .#define bfd_mach_iq10 2 +. bfd_arch_epiphany, {* Adapteva EPIPHANY *} +.#define bfd_mach_epiphany16 1 +.#define bfd_mach_epiphany32 2 . bfd_arch_mt, .#define bfd_mach_ms1 1 .#define bfd_mach_mrisc2 2 @@ -395,6 +405,8 @@ DESCRIPTION .#define bfd_mach_cris_v0_v10 255 .#define bfd_mach_cris_v32 32 .#define bfd_mach_cris_v10_v32 1032 +. bfd_arch_rl78, +.#define bfd_mach_rl78 0x75 . bfd_arch_rx, {* Renesas RX. *} .#define bfd_mach_rx 0x75 . bfd_arch_s390, {* IBM s390 *} @@ -437,6 +449,10 @@ DESCRIPTION . bfd_arch_lm32, {* Lattice Mico32 *} .#define bfd_mach_lm32 1 . bfd_arch_microblaze,{* Xilinx MicroBlaze. *} +. bfd_arch_tilepro, {* Tilera TILEPro *} +. bfd_arch_tilegx, {* Tilera TILE-Gx *} +.#define bfd_mach_tilepro 1 +.#define bfd_mach_tilegx 1 . bfd_arch_last . }; */ @@ -487,6 +503,7 @@ extern const bfd_arch_info_type bfd_crx_arch; extern const bfd_arch_info_type bfd_d10v_arch; extern const bfd_arch_info_type bfd_d30v_arch; extern const bfd_arch_info_type bfd_dlx_arch; +extern const bfd_arch_info_type bfd_epiphany_arch; extern const bfd_arch_info_type bfd_fr30_arch; extern const bfd_arch_info_type bfd_frv_arch; extern const bfd_arch_info_type bfd_h8300_arch; @@ -499,6 +516,7 @@ extern const bfd_arch_info_type bfd_i960_arch; extern const bfd_arch_info_type bfd_ia64_arch; extern const bfd_arch_info_type bfd_ip2k_arch; extern const bfd_arch_info_type bfd_iq2000_arch; +extern const bfd_arch_info_type bfd_k1om_arch; extern const bfd_arch_info_type bfd_l1om_arch; extern const bfd_arch_info_type bfd_lm32_arch; extern const bfd_arch_info_type bfd_m32c_arch; @@ -526,6 +544,7 @@ extern const bfd_arch_info_type bfd_plugin_arch; extern const bfd_arch_info_type bfd_powerpc_archs[]; #define bfd_powerpc_arch bfd_powerpc_archs[0] extern const bfd_arch_info_type bfd_rs6000_arch; +extern const bfd_arch_info_type bfd_rl78_arch; extern const bfd_arch_info_type bfd_rx_arch; extern const bfd_arch_info_type bfd_s390_arch; extern const bfd_arch_info_type bfd_score_arch; @@ -537,6 +556,8 @@ extern const bfd_arch_info_type bfd_tic4x_arch; extern const bfd_arch_info_type bfd_tic54x_arch; extern const bfd_arch_info_type bfd_tic6x_arch; extern const bfd_arch_info_type bfd_tic80_arch; +extern const bfd_arch_info_type bfd_tilegx_arch; +extern const bfd_arch_info_type bfd_tilepro_arch; extern const bfd_arch_info_type bfd_v850_arch; extern const bfd_arch_info_type bfd_vax_arch; extern const bfd_arch_info_type bfd_w65_arch; @@ -564,6 +585,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_d10v_arch, &bfd_d30v_arch, &bfd_dlx_arch, + &bfd_epiphany_arch, &bfd_fr30_arch, &bfd_frv_arch, &bfd_h8300_arch, @@ -576,6 +598,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_ia64_arch, &bfd_ip2k_arch, &bfd_iq2000_arch, + &bfd_k1om_arch, &bfd_l1om_arch, &bfd_lm32_arch, &bfd_m32c_arch, @@ -600,6 +623,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_pdp11_arch, &bfd_powerpc_arch, &bfd_rs6000_arch, + &bfd_rl78_arch, &bfd_rx_arch, &bfd_s390_arch, &bfd_score_arch, @@ -611,6 +635,8 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_tic54x_arch, &bfd_tic6x_arch, &bfd_tic80_arch, + &bfd_tilegx_arch, + &bfd_tilepro_arch, &bfd_v850_arch, &bfd_vax_arch, &bfd_w65_arch, @@ -748,25 +774,26 @@ bfd_arch_get_compatible (const bfd *abfd, const bfd *bbfd, bfd_boolean accept_unknowns) { - const bfd * ubfd = NULL; + const bfd *ubfd, *kbfd; /* Look for an unknown architecture. */ - if (((ubfd = abfd) && ubfd->arch_info->arch == bfd_arch_unknown) - || ((ubfd = bbfd) && ubfd->arch_info->arch == bfd_arch_unknown)) - { - /* We can allow an unknown architecture if accept_unknowns - is true, or if the target is the "binary" format, which - has an unknown architecture. Since the binary format can - only be set by explicit request from the user, it is safe - to assume that they know what they are doing. */ - if (accept_unknowns - || strcmp (bfd_get_target (ubfd), "binary") == 0) - return ubfd->arch_info; - return NULL; - } - - /* Otherwise architecture-specific code has to decide. */ - return abfd->arch_info->compatible (abfd->arch_info, bbfd->arch_info); + if (abfd->arch_info->arch == bfd_arch_unknown) + ubfd = abfd, kbfd = bbfd; + else if (bbfd->arch_info->arch == bfd_arch_unknown) + ubfd = bbfd, kbfd = abfd; + else + /* Otherwise architecture-specific code has to decide. */ + return abfd->arch_info->compatible (abfd->arch_info, bbfd->arch_info); + + /* We can allow an unknown architecture if accept_unknowns + is true, or if the target is the "binary" format, which + has an unknown architecture. Since the binary format can + only be set by explicit request from the user, it is safe + to assume that they know what they are doing. */ + if (accept_unknowns + || strcmp (bfd_get_target (ubfd), "binary") == 0) + return kbfd->arch_info; + return NULL; } /* diff --git a/contrib/gdb-7/bfd/bfd-in.h b/contrib/gdb-7/bfd/bfd-in.h index 63fcdc9bb4..40ed786628 100644 --- a/contrib/gdb-7/bfd/bfd-in.h +++ b/contrib/gdb-7/bfd/bfd-in.h @@ -1,7 +1,7 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -31,6 +31,8 @@ extern "C" { #include "ansidecl.h" #include "symcat.h" +#include + #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) #ifndef SABER /* This hack is to avoid a problem with some strict ANSI C preprocessors. @@ -291,8 +293,8 @@ typedef struct bfd_section *sec_ptr; #define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) /* Find the address one past the end of SEC. */ #define bfd_get_section_limit(bfd, sec) \ - (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \ - / bfd_octets_per_byte (bfd)) + (((bfd)->direction != write_direction && (sec)->rawsize != 0 \ + ? (sec)->rawsize : (sec)->size) / bfd_octets_per_byte (bfd)) /* Return TRUE if input section SEC has been discarded. */ #define elf_discarded_section(sec) \ @@ -300,9 +302,6 @@ typedef struct bfd_section *sec_ptr; && bfd_is_abs_section ((sec)->output_section) \ && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \ && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) - -/* Forward define. */ -struct stat; typedef enum bfd_print_symbol { @@ -432,7 +431,7 @@ extern void bfd_hash_traverse /* Allows the default size of a hash table to be configured. New hash tables allocated using bfd_hash_table_init will be created with this size. */ -extern void bfd_hash_set_default_size (bfd_size_type); +extern unsigned long bfd_hash_set_default_size (unsigned long); /* This structure is used to keep track of stabs in sections information while linking. */ @@ -552,11 +551,6 @@ void bfd_putl16 (bfd_vma, void *); bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean); void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean); -extern bfd_boolean bfd_section_already_linked_table_init (void); -extern void bfd_section_already_linked_table_free (void); - -/* Externally visible ECOFF routines. */ - #if defined(__STDC__) || defined(ALMOST_STDC) struct ecoff_debug_info; struct ecoff_debug_swap; @@ -564,8 +558,18 @@ struct ecoff_extr; struct bfd_symbol; struct bfd_link_info; struct bfd_link_hash_entry; +struct bfd_section_already_linked; struct bfd_elf_version_tree; #endif + +extern bfd_boolean bfd_section_already_linked_table_init (void); +extern void bfd_section_already_linked_table_free (void); +extern bfd_boolean _bfd_handle_already_linked + (struct bfd_section *, struct bfd_section_already_linked *, + struct bfd_link_info *); + +/* Externally visible ECOFF routines. */ + extern bfd_vma bfd_ecoff_get_gp_value (bfd * abfd); extern bfd_boolean bfd_ecoff_set_gp_value @@ -640,8 +644,7 @@ extern bfd_boolean bfd_elf_get_bfd_needed_list (bfd *, struct bfd_link_needed_list **); extern bfd_boolean bfd_elf_size_dynamic_sections (bfd *, const char *, const char *, const char *, const char *, const char *, - const char * const *, struct bfd_link_info *, struct bfd_section **, - struct bfd_elf_version_tree *); + const char * const *, struct bfd_link_info *, struct bfd_section **); extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *, struct bfd_link_info *); extern void bfd_elf_set_dt_needed_name @@ -869,7 +872,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation void bfd_elf32_arm_set_target_relocs (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, - int, int, int, int); + int, int, int, int, int); extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); @@ -912,6 +915,10 @@ extern bfd_boolean elf32_arm_build_stubs extern bfd_boolean elf32_arm_fix_exidx_coverage (struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean); +/* C6x unwind section editing support. */ +extern bfd_boolean elf32_tic6x_fix_exidx_coverage +(struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean); + /* PowerPC @tls opcode transform/validate. */ extern unsigned int _bfd_elf_ppc_at_tls_transform (unsigned int, unsigned int); diff --git a/contrib/gdb-7/bfd/bfd-in2.h b/contrib/gdb-7/bfd/bfd-in2.h index a1ef1c1ef3..2bb0ec7db5 100644 --- a/contrib/gdb-7/bfd/bfd-in2.h +++ b/contrib/gdb-7/bfd/bfd-in2.h @@ -7,8 +7,8 @@ /* Main header file for the bfd library -- portable access to object files. - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Cygnus Support. @@ -38,6 +38,8 @@ extern "C" { #include "ansidecl.h" #include "symcat.h" +#include + #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE) #ifndef SABER /* This hack is to avoid a problem with some strict ANSI C preprocessors. @@ -298,8 +300,8 @@ typedef struct bfd_section *sec_ptr; #define bfd_set_section_userdata(bfd, ptr, val) (((ptr)->userdata = (val)),TRUE) /* Find the address one past the end of SEC. */ #define bfd_get_section_limit(bfd, sec) \ - (((sec)->rawsize ? (sec)->rawsize : (sec)->size) \ - / bfd_octets_per_byte (bfd)) + (((bfd)->direction != write_direction && (sec)->rawsize != 0 \ + ? (sec)->rawsize : (sec)->size) / bfd_octets_per_byte (bfd)) /* Return TRUE if input section SEC has been discarded. */ #define elf_discarded_section(sec) \ @@ -307,9 +309,6 @@ typedef struct bfd_section *sec_ptr; && bfd_is_abs_section ((sec)->output_section) \ && (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \ && (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS) - -/* Forward define. */ -struct stat; typedef enum bfd_print_symbol { @@ -439,7 +438,7 @@ extern void bfd_hash_traverse /* Allows the default size of a hash table to be configured. New hash tables allocated using bfd_hash_table_init will be created with this size. */ -extern void bfd_hash_set_default_size (bfd_size_type); +extern unsigned long bfd_hash_set_default_size (unsigned long); /* This structure is used to keep track of stabs in sections information while linking. */ @@ -559,11 +558,6 @@ void bfd_putl16 (bfd_vma, void *); bfd_uint64_t bfd_get_bits (const void *, int, bfd_boolean); void bfd_put_bits (bfd_uint64_t, void *, int, bfd_boolean); -extern bfd_boolean bfd_section_already_linked_table_init (void); -extern void bfd_section_already_linked_table_free (void); - -/* Externally visible ECOFF routines. */ - #if defined(__STDC__) || defined(ALMOST_STDC) struct ecoff_debug_info; struct ecoff_debug_swap; @@ -571,8 +565,18 @@ struct ecoff_extr; struct bfd_symbol; struct bfd_link_info; struct bfd_link_hash_entry; +struct bfd_section_already_linked; struct bfd_elf_version_tree; #endif + +extern bfd_boolean bfd_section_already_linked_table_init (void); +extern void bfd_section_already_linked_table_free (void); +extern bfd_boolean _bfd_handle_already_linked + (struct bfd_section *, struct bfd_section_already_linked *, + struct bfd_link_info *); + +/* Externally visible ECOFF routines. */ + extern bfd_vma bfd_ecoff_get_gp_value (bfd * abfd); extern bfd_boolean bfd_ecoff_set_gp_value @@ -647,8 +651,7 @@ extern bfd_boolean bfd_elf_get_bfd_needed_list (bfd *, struct bfd_link_needed_list **); extern bfd_boolean bfd_elf_size_dynamic_sections (bfd *, const char *, const char *, const char *, const char *, const char *, - const char * const *, struct bfd_link_info *, struct bfd_section **, - struct bfd_elf_version_tree *); + const char * const *, struct bfd_link_info *, struct bfd_section **); extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *, struct bfd_link_info *); extern void bfd_elf_set_dt_needed_name @@ -876,7 +879,7 @@ extern bfd_boolean bfd_elf32_arm_process_before_allocation void bfd_elf32_arm_set_target_relocs (bfd *, struct bfd_link_info *, int, char *, int, int, bfd_arm_vfp11_fix, - int, int, int, int); + int, int, int, int, int); extern bfd_boolean bfd_elf32_arm_get_bfd_for_interworking (bfd *, struct bfd_link_info *); @@ -919,6 +922,10 @@ extern bfd_boolean elf32_arm_build_stubs extern bfd_boolean elf32_arm_fix_exidx_coverage (struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean); +/* C6x unwind section editing support. */ +extern bfd_boolean elf32_tic6x_fix_exidx_coverage +(struct bfd_section **, unsigned int, struct bfd_link_info *, bfd_boolean); + /* PowerPC @tls opcode transform/validate. */ extern unsigned int _bfd_elf_ppc_at_tls_transform (unsigned int, unsigned int); @@ -1029,9 +1036,9 @@ bfd_boolean bfd_fill_in_gnu_debuglink_section #define bfd_put_signed_8 \ bfd_put_8 #define bfd_get_8(abfd, ptr) \ - (*(unsigned char *) (ptr) & 0xff) + (*(const unsigned char *) (ptr) & 0xff) #define bfd_get_signed_8(abfd, ptr) \ - (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) + (((*(const unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) #define bfd_put_16(abfd, val, ptr) \ BFD_SEND (abfd, bfd_putx16, ((val),(ptr))) @@ -1139,7 +1146,8 @@ long bfd_get_mtime (bfd *abfd); file_ptr bfd_get_size (bfd *abfd); void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, - int prot, int flags, file_ptr offset); + int prot, int flags, file_ptr offset, + void **map_addr, bfd_size_type *map_len); /* Extracted from bfdwin.c. */ /* Extracted from section.c. */ @@ -1320,6 +1328,11 @@ typedef struct bfd_section sections. */ #define SEC_COFF_SHARED_LIBRARY 0x4000000 + /* This input section should be copied to output in reverse order + as an array of pointers. This is for ELF linker internal use + only. */ +#define SEC_ELF_REVERSE_COPY 0x4000000 + /* This section contains data which may be shared with other executables or shared objects. This is for COFF only. */ #define SEC_COFF_SHARED 0x8000000 @@ -1504,6 +1517,9 @@ typedef struct bfd_section /* The BFD which owns the section. */ bfd *owner; + /* INPUT_SECTION_FLAGS if specified in the linker script. */ + struct flag_info *section_flag_info; + /* A symbol which points at this section only. */ struct bfd_symbol *symbol; struct bfd_symbol **symbol_ptr_ptr; @@ -1682,6 +1698,9 @@ extern asection bfd_ind_section; /* target_index, used_by_bfd, constructor_chain, owner, */ \ 0, NULL, NULL, NULL, \ \ + /* flag_info, */ \ + NULL, \ + \ /* symbol, symbol_ptr_ptr, */ \ (struct bfd_symbol *) SYM, &SEC.symbol, \ \ @@ -1863,22 +1882,29 @@ enum bfd_architecture #define bfd_mach_mips_loongson_3a 3003 #define bfd_mach_mips_sb1 12310201 /* octal 'SB', 01 */ #define bfd_mach_mips_octeon 6501 +#define bfd_mach_mips_octeonp 6601 +#define bfd_mach_mips_octeon2 6502 #define bfd_mach_mips_xlr 887682 /* decimal 'XLR' */ #define bfd_mach_mipsisa32 32 #define bfd_mach_mipsisa32r2 33 #define bfd_mach_mipsisa64 64 #define bfd_mach_mipsisa64r2 65 +#define bfd_mach_mips_micromips 96 bfd_arch_i386, /* Intel 386 */ -#define bfd_mach_i386_i386 1 -#define bfd_mach_i386_i8086 2 -#define bfd_mach_i386_i386_intel_syntax 3 -#define bfd_mach_x64_32 32 -#define bfd_mach_x64_32_intel_syntax 33 -#define bfd_mach_x86_64 64 -#define bfd_mach_x86_64_intel_syntax 65 +#define bfd_mach_i386_intel_syntax (1 << 0) +#define bfd_mach_i386_i8086 (1 << 1) +#define bfd_mach_i386_i386 (1 << 2) +#define bfd_mach_x86_64 (1 << 3) +#define bfd_mach_x64_32 (1 << 4) +#define bfd_mach_i386_i386_intel_syntax (bfd_mach_i386_i386 | bfd_mach_i386_intel_syntax) +#define bfd_mach_x86_64_intel_syntax (bfd_mach_x86_64 | bfd_mach_i386_intel_syntax) +#define bfd_mach_x64_32_intel_syntax (bfd_mach_x64_32 | bfd_mach_i386_intel_syntax) bfd_arch_l1om, /* Intel L1OM */ -#define bfd_mach_l1om 66 -#define bfd_mach_l1om_intel_syntax 67 +#define bfd_mach_l1om (1 << 5) +#define bfd_mach_l1om_intel_syntax (bfd_mach_l1om | bfd_mach_i386_intel_syntax) + bfd_arch_k1om, /* Intel K1OM */ +#define bfd_mach_k1om (1 << 6) +#define bfd_mach_k1om_intel_syntax (bfd_mach_k1om | bfd_mach_i386_intel_syntax) bfd_arch_we32k, /* AT&T WE32xxx */ bfd_arch_tahoe, /* CCI/Harris Tahoe */ bfd_arch_i860, /* Intel 860 */ @@ -2047,6 +2073,9 @@ enum bfd_architecture bfd_arch_iq2000, /* Vitesse IQ2000. */ #define bfd_mach_iq2000 1 #define bfd_mach_iq10 2 + bfd_arch_epiphany, /* Adapteva EPIPHANY */ +#define bfd_mach_epiphany16 1 +#define bfd_mach_epiphany32 2 bfd_arch_mt, #define bfd_mach_ms1 1 #define bfd_mach_mrisc2 2 @@ -2082,6 +2111,8 @@ enum bfd_architecture #define bfd_mach_cris_v0_v10 255 #define bfd_mach_cris_v32 32 #define bfd_mach_cris_v10_v32 1032 + bfd_arch_rl78, +#define bfd_mach_rl78 0x75 bfd_arch_rx, /* Renesas RX. */ #define bfd_mach_rx 0x75 bfd_arch_s390, /* IBM s390 */ @@ -2124,6 +2155,10 @@ enum bfd_architecture bfd_arch_lm32, /* Lattice Mico32 */ #define bfd_mach_lm32 1 bfd_arch_microblaze,/* Xilinx MicroBlaze. */ + bfd_arch_tilepro, /* Tilera TILEPro */ + bfd_arch_tilegx, /* Tilera TILE-Gx */ +#define bfd_mach_tilepro 1 +#define bfd_mach_tilegx 1 bfd_arch_last }; @@ -2703,9 +2738,9 @@ between two procedure entry points is < 2^21, or else a hint. */ BFD_RELOC_ALPHA_TPREL_LO16, BFD_RELOC_ALPHA_TPREL16, -/* Bits 27..2 of the relocation address shifted right 2 bits; -simple reloc otherwise. */ +/* The MIPS jump instruction. */ BFD_RELOC_MIPS_JMP, + BFD_RELOC_MICROMIPS_JMP, /* The MIPS16 jump instruction. */ BFD_RELOC_MIPS16_JMP, @@ -2753,42 +2788,75 @@ to compensate for the borrow when the low bits are added. */ /* Relocation against a MIPS literal section. */ BFD_RELOC_MIPS_LITERAL, + BFD_RELOC_MICROMIPS_LITERAL, + +/* microMIPS PC-relative relocations. */ + BFD_RELOC_MICROMIPS_7_PCREL_S1, + BFD_RELOC_MICROMIPS_10_PCREL_S1, + BFD_RELOC_MICROMIPS_16_PCREL_S1, + +/* microMIPS versions of generic BFD relocs. */ + BFD_RELOC_MICROMIPS_GPREL16, + BFD_RELOC_MICROMIPS_HI16, + BFD_RELOC_MICROMIPS_HI16_S, + BFD_RELOC_MICROMIPS_LO16, /* MIPS ELF relocations. */ BFD_RELOC_MIPS_GOT16, + BFD_RELOC_MICROMIPS_GOT16, BFD_RELOC_MIPS_CALL16, + BFD_RELOC_MICROMIPS_CALL16, BFD_RELOC_MIPS_GOT_HI16, + BFD_RELOC_MICROMIPS_GOT_HI16, BFD_RELOC_MIPS_GOT_LO16, + BFD_RELOC_MICROMIPS_GOT_LO16, BFD_RELOC_MIPS_CALL_HI16, + BFD_RELOC_MICROMIPS_CALL_HI16, BFD_RELOC_MIPS_CALL_LO16, + BFD_RELOC_MICROMIPS_CALL_LO16, BFD_RELOC_MIPS_SUB, + BFD_RELOC_MICROMIPS_SUB, BFD_RELOC_MIPS_GOT_PAGE, + BFD_RELOC_MICROMIPS_GOT_PAGE, BFD_RELOC_MIPS_GOT_OFST, + BFD_RELOC_MICROMIPS_GOT_OFST, BFD_RELOC_MIPS_GOT_DISP, + BFD_RELOC_MICROMIPS_GOT_DISP, BFD_RELOC_MIPS_SHIFT5, BFD_RELOC_MIPS_SHIFT6, BFD_RELOC_MIPS_INSERT_A, BFD_RELOC_MIPS_INSERT_B, BFD_RELOC_MIPS_DELETE, BFD_RELOC_MIPS_HIGHEST, + BFD_RELOC_MICROMIPS_HIGHEST, BFD_RELOC_MIPS_HIGHER, + BFD_RELOC_MICROMIPS_HIGHER, BFD_RELOC_MIPS_SCN_DISP, + BFD_RELOC_MICROMIPS_SCN_DISP, BFD_RELOC_MIPS_REL16, BFD_RELOC_MIPS_RELGOT, BFD_RELOC_MIPS_JALR, + BFD_RELOC_MICROMIPS_JALR, BFD_RELOC_MIPS_TLS_DTPMOD32, BFD_RELOC_MIPS_TLS_DTPREL32, BFD_RELOC_MIPS_TLS_DTPMOD64, BFD_RELOC_MIPS_TLS_DTPREL64, BFD_RELOC_MIPS_TLS_GD, + BFD_RELOC_MICROMIPS_TLS_GD, BFD_RELOC_MIPS_TLS_LDM, + BFD_RELOC_MICROMIPS_TLS_LDM, BFD_RELOC_MIPS_TLS_DTPREL_HI16, + BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16, BFD_RELOC_MIPS_TLS_DTPREL_LO16, + BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16, BFD_RELOC_MIPS_TLS_GOTTPREL, + BFD_RELOC_MICROMIPS_TLS_GOTTPREL, BFD_RELOC_MIPS_TLS_TPREL32, BFD_RELOC_MIPS_TLS_TPREL64, BFD_RELOC_MIPS_TLS_TPREL_HI16, + BFD_RELOC_MICROMIPS_TLS_TPREL_HI16, BFD_RELOC_MIPS_TLS_TPREL_LO16, + BFD_RELOC_MICROMIPS_TLS_TPREL_LO16, /* MIPS ELF relocations (VxWorks and PLT extensions). */ @@ -3993,6 +4061,40 @@ instructions */ instructions */ BFD_RELOC_AVR_6_ADIW, +/* Renesas RL78 Relocations. */ + BFD_RELOC_RL78_NEG8, + BFD_RELOC_RL78_NEG16, + BFD_RELOC_RL78_NEG24, + BFD_RELOC_RL78_NEG32, + BFD_RELOC_RL78_16_OP, + BFD_RELOC_RL78_24_OP, + BFD_RELOC_RL78_32_OP, + BFD_RELOC_RL78_8U, + BFD_RELOC_RL78_16U, + BFD_RELOC_RL78_24U, + BFD_RELOC_RL78_DIR3U_PCREL, + BFD_RELOC_RL78_DIFF, + BFD_RELOC_RL78_GPRELB, + BFD_RELOC_RL78_GPRELW, + BFD_RELOC_RL78_GPRELL, + BFD_RELOC_RL78_SYM, + BFD_RELOC_RL78_OP_SUBTRACT, + BFD_RELOC_RL78_OP_NEG, + BFD_RELOC_RL78_OP_AND, + BFD_RELOC_RL78_OP_SHRA, + BFD_RELOC_RL78_ABS8, + BFD_RELOC_RL78_ABS16, + BFD_RELOC_RL78_ABS16_REV, + BFD_RELOC_RL78_ABS32, + BFD_RELOC_RL78_ABS32_REV, + BFD_RELOC_RL78_ABS16U, + BFD_RELOC_RL78_ABS16UW, + BFD_RELOC_RL78_ABS16UL, + BFD_RELOC_RL78_RELAX, + BFD_RELOC_RL78_HI16, + BFD_RELOC_RL78_HI8, + BFD_RELOC_RL78_LO16, + /* Renesas RX Relocations. */ BFD_RELOC_RX_NEG8, BFD_RELOC_RX_NEG16, @@ -4790,6 +4892,199 @@ value in a word. The relocation is relative offset from */ /* This is used to tell the dynamic linker to copy the value out of the dynamic object into the runtime process image. */ BFD_RELOC_MICROBLAZE_COPY, + +/* Tilera TILEPro Relocations. */ + BFD_RELOC_TILEPRO_COPY, + BFD_RELOC_TILEPRO_GLOB_DAT, + BFD_RELOC_TILEPRO_JMP_SLOT, + BFD_RELOC_TILEPRO_RELATIVE, + BFD_RELOC_TILEPRO_BROFF_X1, + BFD_RELOC_TILEPRO_JOFFLONG_X1, + BFD_RELOC_TILEPRO_JOFFLONG_X1_PLT, + BFD_RELOC_TILEPRO_IMM8_X0, + BFD_RELOC_TILEPRO_IMM8_Y0, + BFD_RELOC_TILEPRO_IMM8_X1, + BFD_RELOC_TILEPRO_IMM8_Y1, + BFD_RELOC_TILEPRO_DEST_IMM8_X1, + BFD_RELOC_TILEPRO_MT_IMM15_X1, + BFD_RELOC_TILEPRO_MF_IMM15_X1, + BFD_RELOC_TILEPRO_IMM16_X0, + BFD_RELOC_TILEPRO_IMM16_X1, + BFD_RELOC_TILEPRO_IMM16_X0_LO, + BFD_RELOC_TILEPRO_IMM16_X1_LO, + BFD_RELOC_TILEPRO_IMM16_X0_HI, + BFD_RELOC_TILEPRO_IMM16_X1_HI, + BFD_RELOC_TILEPRO_IMM16_X0_HA, + BFD_RELOC_TILEPRO_IMM16_X1_HA, + BFD_RELOC_TILEPRO_IMM16_X0_PCREL, + BFD_RELOC_TILEPRO_IMM16_X1_PCREL, + BFD_RELOC_TILEPRO_IMM16_X0_LO_PCREL, + BFD_RELOC_TILEPRO_IMM16_X1_LO_PCREL, + BFD_RELOC_TILEPRO_IMM16_X0_HI_PCREL, + BFD_RELOC_TILEPRO_IMM16_X1_HI_PCREL, + BFD_RELOC_TILEPRO_IMM16_X0_HA_PCREL, + BFD_RELOC_TILEPRO_IMM16_X1_HA_PCREL, + BFD_RELOC_TILEPRO_IMM16_X0_GOT, + BFD_RELOC_TILEPRO_IMM16_X1_GOT, + BFD_RELOC_TILEPRO_IMM16_X0_GOT_LO, + BFD_RELOC_TILEPRO_IMM16_X1_GOT_LO, + BFD_RELOC_TILEPRO_IMM16_X0_GOT_HI, + BFD_RELOC_TILEPRO_IMM16_X1_GOT_HI, + BFD_RELOC_TILEPRO_IMM16_X0_GOT_HA, + BFD_RELOC_TILEPRO_IMM16_X1_GOT_HA, + BFD_RELOC_TILEPRO_MMSTART_X0, + BFD_RELOC_TILEPRO_MMEND_X0, + BFD_RELOC_TILEPRO_MMSTART_X1, + BFD_RELOC_TILEPRO_MMEND_X1, + BFD_RELOC_TILEPRO_SHAMT_X0, + BFD_RELOC_TILEPRO_SHAMT_X1, + BFD_RELOC_TILEPRO_SHAMT_Y0, + BFD_RELOC_TILEPRO_SHAMT_Y1, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_LO, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_LO, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_HI, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_HI, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_HA, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_HA, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_LO, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_LO, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_HI, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_HI, + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_HA, + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_HA, + BFD_RELOC_TILEPRO_TLS_DTPMOD32, + BFD_RELOC_TILEPRO_TLS_DTPOFF32, + BFD_RELOC_TILEPRO_TLS_TPOFF32, + +/* Tilera TILE-Gx Relocations. */ + BFD_RELOC_TILEGX_HW0, + BFD_RELOC_TILEGX_HW1, + BFD_RELOC_TILEGX_HW2, + BFD_RELOC_TILEGX_HW3, + BFD_RELOC_TILEGX_HW0_LAST, + BFD_RELOC_TILEGX_HW1_LAST, + BFD_RELOC_TILEGX_HW2_LAST, + BFD_RELOC_TILEGX_COPY, + BFD_RELOC_TILEGX_GLOB_DAT, + BFD_RELOC_TILEGX_JMP_SLOT, + BFD_RELOC_TILEGX_RELATIVE, + BFD_RELOC_TILEGX_BROFF_X1, + BFD_RELOC_TILEGX_JUMPOFF_X1, + BFD_RELOC_TILEGX_JUMPOFF_X1_PLT, + BFD_RELOC_TILEGX_IMM8_X0, + BFD_RELOC_TILEGX_IMM8_Y0, + BFD_RELOC_TILEGX_IMM8_X1, + BFD_RELOC_TILEGX_IMM8_Y1, + BFD_RELOC_TILEGX_DEST_IMM8_X1, + BFD_RELOC_TILEGX_MT_IMM14_X1, + BFD_RELOC_TILEGX_MF_IMM14_X1, + BFD_RELOC_TILEGX_MMSTART_X0, + BFD_RELOC_TILEGX_MMEND_X0, + BFD_RELOC_TILEGX_SHAMT_X0, + BFD_RELOC_TILEGX_SHAMT_X1, + BFD_RELOC_TILEGX_SHAMT_Y0, + BFD_RELOC_TILEGX_SHAMT_Y1, + BFD_RELOC_TILEGX_IMM16_X0_HW0, + BFD_RELOC_TILEGX_IMM16_X1_HW0, + BFD_RELOC_TILEGX_IMM16_X0_HW1, + BFD_RELOC_TILEGX_IMM16_X1_HW1, + BFD_RELOC_TILEGX_IMM16_X0_HW2, + BFD_RELOC_TILEGX_IMM16_X1_HW2, + BFD_RELOC_TILEGX_IMM16_X0_HW3, + BFD_RELOC_TILEGX_IMM16_X1_HW3, + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST, + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST, + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST, + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST, + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST, + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST, + BFD_RELOC_TILEGX_IMM16_X0_HW0_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW0_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW1_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW1_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW2_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW2_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW3_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW3_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_PCREL, + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_PCREL, + BFD_RELOC_TILEGX_IMM16_X0_HW0_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW0_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW1_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW1_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW2_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW2_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW3_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW3_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_GOT, + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_GOT, + BFD_RELOC_TILEGX_IMM16_X0_HW0_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW0_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW1_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW1_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW2_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW2_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW3_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW3_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_TLS_GD, + BFD_RELOC_TILEGX_IMM16_X0_HW0_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW0_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X0_HW1_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW1_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X0_HW2_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW2_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X0_HW3_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW3_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_TLS_IE, + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_TLS_IE, + BFD_RELOC_TILEGX_TLS_DTPMOD64, + BFD_RELOC_TILEGX_TLS_DTPOFF64, + BFD_RELOC_TILEGX_TLS_TPOFF64, + BFD_RELOC_TILEGX_TLS_DTPMOD32, + BFD_RELOC_TILEGX_TLS_DTPOFF32, + BFD_RELOC_TILEGX_TLS_TPOFF32, + +/* Adapteva EPIPHANY - 8 bit signed pc-relative displacement */ + BFD_RELOC_EPIPHANY_SIMM8, + +/* Adapteva EPIPHANY - 24 bit signed pc-relative displacement */ + BFD_RELOC_EPIPHANY_SIMM24, + +/* Adapteva EPIPHANY - 16 most-significant bits of absolute address */ + BFD_RELOC_EPIPHANY_HIGH, + +/* Adapteva EPIPHANY - 16 least-significant bits of absolute address */ + BFD_RELOC_EPIPHANY_LOW, + +/* Adapteva EPIPHANY - 11 bit signed number - add/sub immediate */ + BFD_RELOC_EPIPHANY_SIMM11, + +/* Adapteva EPIPHANY - 11 bit sign-magnitude number (ld/st displacement) */ + BFD_RELOC_EPIPHANY_IMM11, + +/* Adapteva EPIPHANY - 8 bit immediate for 16 bit mov instruction. */ + BFD_RELOC_EPIPHANY_IMM8, BFD_RELOC_UNUSED }; typedef enum bfd_reloc_code_real bfd_reloc_code_real_type; reloc_howto_type *bfd_reloc_type_lookup @@ -5110,14 +5405,17 @@ struct bfd /* Decompress sections in this BFD. */ #define BFD_DECOMPRESS 0x10000 + /* BFD is a dummy, for plugins. */ +#define BFD_PLUGIN 0x20000 + /* Flags bits to be saved in bfd_preserve_save. */ #define BFD_FLAGS_SAVED \ - (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS) + (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN) /* Flags bits which are for BFD use only. */ #define BFD_FLAGS_FOR_BFD_USE_MASK \ (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ - | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) + | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) /* Currently my_archive is tested before adding origin to anything. I believe that this can become always an add of @@ -5382,6 +5680,9 @@ bfd_boolean bfd_set_private_flags (bfd *abfd, flagword flags); #define bfd_gc_sections(abfd, link_info) \ BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info)) +#define bfd_lookup_section_flags(link_info, flag_info) \ + BFD_SEND (abfd, _bfd_lookup_section_flags, (link_info, flag_info)) + #define bfd_merge_sections(abfd, link_info) \ BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info)) @@ -5538,6 +5839,9 @@ enum bfd_endian { BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN }; /* Forward declaration. */ typedef struct bfd_link_info _bfd_link_info; +/* Forward declaration. */ +typedef struct flag_info flag_info; + typedef struct bfd_target { /* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. */ @@ -5569,7 +5873,11 @@ typedef struct bfd_target char ar_pad_char; /* The maximum number of characters in an archive header. */ - unsigned short ar_max_namelen; + unsigned char ar_max_namelen; + + /* How well this target matches, used to select between various + possible targets when more than one target matches. */ + unsigned char match_priority; /* Entries for byte swapping for data. These are different from the other entry points, since they don't take a BFD as the first argument. @@ -5803,6 +6111,7 @@ typedef struct bfd_target NAME##_bfd_final_link, \ NAME##_bfd_link_split_section, \ NAME##_bfd_gc_sections, \ + NAME##_bfd_lookup_section_flags, \ NAME##_bfd_merge_sections, \ NAME##_bfd_is_group_section, \ NAME##_bfd_discard_group, \ @@ -5847,6 +6156,10 @@ typedef struct bfd_target /* Remove sections that are not referenced from the output. */ bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *); + /* Sets the bitmask of allowed and disallowed section flags. */ + void (*_bfd_lookup_section_flags) (struct bfd_link_info *, + struct flag_info *); + /* Attempt to merge SEC_MERGE sections. */ bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); @@ -5858,8 +6171,8 @@ typedef struct bfd_target /* Check if SEC has been already linked during a reloceatable or final link. */ - void (*_section_already_linked) (bfd *, struct bfd_section *, - struct bfd_link_info *); + bfd_boolean (*_section_already_linked) (bfd *, asection *, + struct bfd_link_info *); /* Define a common symbol. */ bfd_boolean (*_bfd_define_common_symbol) (bfd *, struct bfd_link_info *, @@ -5928,7 +6241,8 @@ bfd_boolean bfd_link_split_section (bfd *abfd, asection *sec); #define bfd_link_split_section(abfd, sec) \ BFD_SEND (abfd, _bfd_link_split_section, (abfd, sec)) -void bfd_section_already_linked (bfd *abfd, asection *sec, +bfd_boolean bfd_section_already_linked (bfd *abfd, + asection *sec, struct bfd_link_info *info); #define bfd_section_already_linked(abfd, sec, info) \ @@ -5945,6 +6259,9 @@ struct bfd_elf_version_tree * bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs, const char *sym_name, bfd_boolean *hide); +bfd_boolean bfd_hide_sym_by_version + (struct bfd_elf_version_tree *verdefs, const char *sym_name); + /* Extracted from simple.c. */ bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); diff --git a/contrib/gdb-7/bfd/bfd.c b/contrib/gdb-7/bfd/bfd.c index 77582ec82f..7c14c7a00a 100644 --- a/contrib/gdb-7/bfd/bfd.c +++ b/contrib/gdb-7/bfd/bfd.c @@ -157,14 +157,17 @@ CODE_FRAGMENT . {* Decompress sections in this BFD. *} .#define BFD_DECOMPRESS 0x10000 . +. {* BFD is a dummy, for plugins. *} +.#define BFD_PLUGIN 0x20000 +. . {* Flags bits to be saved in bfd_preserve_save. *} .#define BFD_FLAGS_SAVED \ -. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS) +. (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_PLUGIN) . . {* Flags bits which are for BFD use only. *} .#define BFD_FLAGS_FOR_BFD_USE_MASK \ . (BFD_IN_MEMORY | BFD_COMPRESS | BFD_DECOMPRESS | BFD_LINKER_CREATED \ -. | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) +. | BFD_PLUGIN | BFD_TRADITIONAL_FORMAT | BFD_DETERMINISTIC_OUTPUT) . . {* Currently my_archive is tested before adding origin to . anything. I believe that this can become always an add of @@ -1028,7 +1031,8 @@ bfd_get_sign_extend_vma (bfd *abfd) || strcmp (name, "pe-x86-64") == 0 || strcmp (name, "pei-x86-64") == 0 || strcmp (name, "pe-arm-wince-little") == 0 - || strcmp (name, "pei-arm-wince-little") == 0) + || strcmp (name, "pei-arm-wince-little") == 0 + || strcmp (name, "aixcoff-rs6000") == 0) return 1; if (CONST_STRNEQ (name, "mach-o")) @@ -1370,6 +1374,9 @@ DESCRIPTION .#define bfd_gc_sections(abfd, link_info) \ . BFD_SEND (abfd, _bfd_gc_sections, (abfd, link_info)) . +.#define bfd_lookup_section_flags(link_info, flag_info) \ +. BFD_SEND (abfd, _bfd_lookup_section_flags, (link_info, flag_info)) +. .#define bfd_merge_sections(abfd, link_info) \ . BFD_SEND (abfd, _bfd_merge_sections, (abfd, link_info)) . diff --git a/contrib/gdb-7/bfd/bfdio.c b/contrib/gdb-7/bfd/bfdio.c index ce92781d50..841c781f4b 100644 --- a/contrib/gdb-7/bfd/bfdio.c +++ b/contrib/gdb-7/bfd/bfdio.c @@ -1,7 +1,7 @@ /* Low-level I/O routines for BFDs. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -158,9 +158,15 @@ DESCRIPTION . int (*bclose) (struct bfd *abfd); . int (*bflush) (struct bfd *abfd); . int (*bstat) (struct bfd *abfd, struct stat *sb); -. {* Just like mmap: (void*)-1 on failure, mmapped address on success. *} +. {* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual +. mmap parameter, except that LEN and OFFSET do not need to be page +. aligned. Returns (void *)-1 on failure, mmapped address on success. +. Also write in MAP_ADDR the address of the page aligned buffer and in +. MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and +. MAP_LEN to unmap. *} . void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len, -. int prot, int flags, file_ptr offset); +. int prot, int flags, file_ptr offset, +. void **map_addr, bfd_size_type *map_len); .}; .extern const struct bfd_iovec _bfd_memory_iovec; @@ -423,23 +429,28 @@ FUNCTION SYNOPSIS void *bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, - int prot, int flags, file_ptr offset); + int prot, int flags, file_ptr offset, + void **map_addr, bfd_size_type *map_len); DESCRIPTION Return mmap()ed region of the file, if possible and implemented. + LEN and OFFSET do not need to be page aligned. The page aligned + address and length are written to MAP_ADDR and MAP_LEN. */ void * bfd_mmap (bfd *abfd, void *addr, bfd_size_type len, - int prot, int flags, file_ptr offset) + int prot, int flags, file_ptr offset, + void **map_addr, bfd_size_type *map_len) { void *ret = (void *)-1; if (abfd->iovec == NULL) return ret; - return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset); + return abfd->iovec->bmmap (abfd, addr, len, prot, flags, offset, + map_addr, map_len); } /* Memory file I/O operations. */ @@ -577,7 +588,7 @@ memory_bstat (bfd *abfd, struct stat *statbuf) { struct bfd_in_memory *bim = (struct bfd_in_memory *) abfd->iostream; - memset (statbuf, 0, sizeof (statbuf)); + memset (statbuf, 0, sizeof (*statbuf)); statbuf->st_size = bim->size; return 0; @@ -586,7 +597,9 @@ memory_bstat (bfd *abfd, struct stat *statbuf) static void * memory_bmmap (bfd *abfd ATTRIBUTE_UNUSED, void *addr ATTRIBUTE_UNUSED, bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED) + int flags ATTRIBUTE_UNUSED, file_ptr offset ATTRIBUTE_UNUSED, + void **map_addr ATTRIBUTE_UNUSED, + bfd_size_type *map_len ATTRIBUTE_UNUSED) { return (void *)-1; } diff --git a/contrib/gdb-7/bfd/bfdwin.c b/contrib/gdb-7/bfd/bfdwin.c index 63ad5ed3f5..4103e9c2f5 100644 --- a/contrib/gdb-7/bfd/bfdwin.c +++ b/contrib/gdb-7/bfd/bfdwin.c @@ -1,5 +1,5 @@ /* Support for memory-mapped windows into a BFD. - Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007, 2008, 2009 + Copyright 1995, 1996, 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -128,17 +128,16 @@ bfd_get_file_window (bfd *abfd, if (pagesize == 0) abort (); - if (i == 0) + if (i == NULL) { i = bfd_zmalloc (sizeof (bfd_window_internal)); - windowp->i = i; - if (i == 0) + if (i == NULL) return FALSE; - i->data = 0; + i->data = NULL; } #ifdef HAVE_MMAP if (ok_to_map - && (i->data == 0 || i->mapped == 1) + && (i->data == NULL || i->mapped == 1) && (abfd->flags & BFD_IN_MEMORY) == 0) { file_ptr file_offset, offset2; @@ -156,9 +155,9 @@ bfd_get_file_window (bfd *abfd, if (abfd->iostream == NULL && (abfd->iovec == NULL || abfd->iovec->bseek (abfd, offset, SEEK_SET) != 0)) - return FALSE; - fd = fileno ((FILE *) abfd->iostream); + goto free_and_fail; + fd = fileno ((FILE *) abfd->iostream); /* Compute offsets and size for mmap and for the user's data. */ offset2 = offset % pagesize; if (offset2 < 0) @@ -169,10 +168,10 @@ bfd_get_file_window (bfd *abfd, real_size -= real_size % pagesize; /* If we're re-using a memory region, make sure it's big enough. */ - if (i->data && i->size < size) + if (i->data != NULL && i->size < size) { munmap (i->data, i->size); - i->data = 0; + i->data = NULL; } i->data = mmap (i->data, real_size, writable ? PROT_WRITE | PROT_READ : PROT_READ, @@ -185,11 +184,10 @@ bfd_get_file_window (bfd *abfd, /* An error happened. Report it, or try using malloc, or something. */ bfd_set_error (bfd_error_system_call); - i->data = 0; windowp->data = 0; if (debug_windows) fprintf (stderr, "\t\tmmap failed!\n"); - return FALSE; + goto free_and_fail; } if (debug_windows) fprintf (stderr, "\n\tmapped %ld at %p, offset is %ld\n", @@ -198,6 +196,8 @@ bfd_get_file_window (bfd *abfd, windowp->data = (bfd_byte *) i->data + offset2; windowp->size = size; i->mapped = 1; + i->refcount = 1; + windowp->i = i; return TRUE; } else if (debug_windows) @@ -228,15 +228,18 @@ bfd_get_file_window (bfd *abfd, if (i->data == NULL) { if (size_to_alloc == 0) - return TRUE; - return FALSE; + { + windowp->i = i; + return TRUE; + } + goto free_and_fail; } i->refcount = 1; if (bfd_seek (abfd, offset, SEEK_SET) != 0) - return FALSE; + goto free_and_fail; i->size = bfd_bread (i->data, size, abfd); if (i->size != size) - return FALSE; + goto free_and_fail; i->mapped = 0; #ifdef HAVE_MPROTECT if (!writable) @@ -249,7 +252,13 @@ bfd_get_file_window (bfd *abfd, #endif windowp->data = i->data; windowp->size = i->size; + windowp->i = i; return TRUE; + + free_and_fail: + /* We have a bfd_window_internal, but an error occurred. Free it. */ + free (i); + return FALSE; } #endif /* USE_MMAP */ diff --git a/contrib/gdb-7/bfd/binary.c b/contrib/gdb-7/bfd/binary.c index 2af0293ef4..700c862f93 100644 --- a/contrib/gdb-7/bfd/binary.c +++ b/contrib/gdb-7/bfd/binary.c @@ -1,6 +1,6 @@ /* BFD back-end for binary objects. Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. + 2004, 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc. Written by Ian Lance Taylor, Cygnus Support, This file is part of BFD, the Binary File Descriptor library. @@ -299,6 +299,7 @@ binary_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, #define binary_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define binary_bfd_relax_section bfd_generic_relax_section #define binary_bfd_gc_sections bfd_generic_gc_sections +#define binary_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define binary_bfd_merge_sections bfd_generic_merge_sections #define binary_bfd_is_group_section bfd_generic_is_group_section #define binary_bfd_discard_group bfd_generic_discard_group @@ -326,6 +327,7 @@ const bfd_target binary_vec = 0, /* symbol_leading_char */ ' ', /* ar_pad_char */ 16, /* ar_max_namelen */ + 255, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */ diff --git a/contrib/gdb-7/bfd/cache.c b/contrib/gdb-7/bfd/cache.c index 2239c28aac..5ddbbe470a 100644 --- a/contrib/gdb-7/bfd/cache.c +++ b/contrib/gdb-7/bfd/cache.c @@ -45,6 +45,7 @@ SUBSECTION #include "bfd.h" #include "libbfd.h" #include "libiberty.h" +#include "bfd_stdint.h" #ifdef HAVE_MMAP #include @@ -398,7 +399,9 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, - file_ptr offset ATTRIBUTE_UNUSED) + file_ptr offset ATTRIBUTE_UNUSED, + void **map_addr ATTRIBUTE_UNUSED, + bfd_size_type *map_len ATTRIBUTE_UNUSED) { void *ret = (void *) -1; @@ -407,13 +410,35 @@ cache_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, #ifdef HAVE_MMAP else { - FILE *f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); + static uintptr_t pagesize_m1; + FILE *f; + file_ptr pg_offset; + bfd_size_type pg_len; + + f = bfd_cache_lookup (abfd, CACHE_NO_SEEK_ERROR); if (f == NULL) return ret; - ret = mmap (addr, len, prot, flags, fileno (f), offset); + if (pagesize_m1 == 0) + pagesize_m1 = getpagesize () - 1; + + /* Handle archive members. */ + if (abfd->my_archive != NULL) + offset += abfd->origin; + + /* Align. */ + pg_offset = offset & ~pagesize_m1; + pg_len = (len + (offset - pg_offset) + pagesize_m1) & ~pagesize_m1; + + ret = mmap (addr, pg_len, prot, flags, fileno (f), pg_offset); if (ret == (void *) -1) bfd_set_error (bfd_error_system_call); + else + { + *map_addr = ret; + *map_len = pg_len; + ret += offset & pagesize_m1; + } } #endif diff --git a/contrib/gdb-7/bfd/coffgen.c b/contrib/gdb-7/bfd/coffgen.c index fc82d57dd7..c0505c6c02 100644 --- a/contrib/gdb-7/bfd/coffgen.c +++ b/contrib/gdb-7/bfd/coffgen.c @@ -915,6 +915,9 @@ coff_write_symbol (bfd *abfd, unsigned int numaux = native->u.syment.n_numaux; int type = native->u.syment.n_type; int n_sclass = (int) native->u.syment.n_sclass; + asection *output_section = symbol->section->output_section + ? symbol->section->output_section + : symbol->section; void * buf; bfd_size_type symesz; @@ -933,7 +936,7 @@ coff_write_symbol (bfd *abfd, else native->u.syment.n_scnum = - symbol->section->output_section->target_index; + output_section->target_index; coff_fix_symbol_name (abfd, symbol, native, string_size_p, debug_string_section_p, debug_string_size_p); @@ -980,20 +983,36 @@ coff_write_symbol (bfd *abfd, file originally. This symbol may have been created by the linker, or we may be linking a non COFF file to a COFF file. */ -static bfd_boolean +bfd_boolean coff_write_alien_symbol (bfd *abfd, asymbol *symbol, + struct internal_syment *isym, bfd_vma *written, bfd_size_type *string_size_p, asection **debug_string_section_p, bfd_size_type *debug_string_size_p) { combined_entry_type *native; - combined_entry_type dummy; - - native = &dummy; + combined_entry_type dummy[2]; + asection *output_section = symbol->section->output_section + ? symbol->section->output_section + : symbol->section; + struct bfd_link_info *link_info = coff_data (abfd)->link_info; + bfd_boolean ret; + + if ((!link_info || link_info->strip_discarded) + && !bfd_is_abs_section (symbol->section) + && symbol->section->output_section == bfd_abs_section_ptr) + { + symbol->name = ""; + if (isym != NULL) + memset (isym, 0, sizeof(*isym)); + return TRUE; + } + native = dummy; native->u.syment.n_type = T_NULL; native->u.syment.n_flags = 0; + native->u.syment.n_numaux = 0; if (bfd_is_und_section (symbol->section)) { native->u.syment.n_scnum = N_UNDEF; @@ -1004,6 +1023,11 @@ coff_write_alien_symbol (bfd *abfd, native->u.syment.n_scnum = N_UNDEF; native->u.syment.n_value = symbol->value; } + else if (symbol->flags & BSF_FILE) + { + native->u.syment.n_scnum = N_DEBUG; + native->u.syment.n_numaux = 1; + } else if (symbol->flags & BSF_DEBUGGING) { /* There isn't much point to writing out a debugging symbol @@ -1011,16 +1035,17 @@ coff_write_alien_symbol (bfd *abfd, format. So, we just ignore them. We must clobber the symbol name to keep it from being put in the string table. */ symbol->name = ""; + if (isym != NULL) + memset (isym, 0, sizeof(*isym)); return TRUE; } else { - native->u.syment.n_scnum = - symbol->section->output_section->target_index; + native->u.syment.n_scnum = output_section->target_index; native->u.syment.n_value = (symbol->value + symbol->section->output_offset); if (! obj_pe (abfd)) - native->u.syment.n_value += symbol->section->output_section->vma; + native->u.syment.n_value += output_section->vma; /* Copy the any flags from the file header into the symbol. FIXME: Why? */ @@ -1032,16 +1057,20 @@ coff_write_alien_symbol (bfd *abfd, } native->u.syment.n_type = 0; - if (symbol->flags & BSF_LOCAL) + if (symbol->flags & BSF_FILE) + native->u.syment.n_sclass = C_FILE; + else if (symbol->flags & BSF_LOCAL) native->u.syment.n_sclass = C_STAT; else if (symbol->flags & BSF_WEAK) native->u.syment.n_sclass = obj_pe (abfd) ? C_NT_WEAK : C_WEAKEXT; else native->u.syment.n_sclass = C_EXT; - native->u.syment.n_numaux = 0; - return coff_write_symbol (abfd, symbol, native, written, string_size_p, - debug_string_section_p, debug_string_size_p); + ret = coff_write_symbol (abfd, symbol, native, written, string_size_p, + debug_string_section_p, debug_string_size_p); + if (isym != NULL) + *isym = native->u.syment; + return ret; } /* Write a native symbol to a COFF file. */ @@ -1056,6 +1085,15 @@ coff_write_native_symbol (bfd *abfd, { combined_entry_type *native = symbol->native; alent *lineno = symbol->lineno; + struct bfd_link_info *link_info = coff_data (abfd)->link_info; + + if ((!link_info || link_info->strip_discarded) + && !bfd_is_abs_section (symbol->symbol.section) + && symbol->symbol.section->output_section == bfd_abs_section_ptr) + { + symbol->symbol.name = ""; + return TRUE; + } /* If this symbol has an associated line number, we must store the symbol index in the line number field. We also tag the auxent to @@ -1148,8 +1186,8 @@ coff_write_symbols (bfd *abfd) if (c_symbol == (coff_symbol_type *) NULL || c_symbol->native == (combined_entry_type *) NULL) { - if (!coff_write_alien_symbol (abfd, symbol, &written, &string_size, - &debug_string_section, + if (!coff_write_alien_symbol (abfd, symbol, NULL, &written, + &string_size, &debug_string_section, &debug_string_size)) return FALSE; } @@ -2080,13 +2118,14 @@ _bfd_coff_is_local_label_name (bfd *abfd ATTRIBUTE_UNUSED, nearest to the wanted location. */ bfd_boolean -coff_find_nearest_line (bfd *abfd, - asection *section, - asymbol **symbols, - bfd_vma offset, - const char **filename_ptr, - const char **functionname_ptr, - unsigned int *line_ptr) +coff_find_nearest_line_with_names (bfd *abfd, + const struct dwarf_debug_section *debug_sections, + asection *section, + asymbol **symbols, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *line_ptr) { bfd_boolean found; unsigned int i; @@ -2111,7 +2150,8 @@ coff_find_nearest_line (bfd *abfd, return TRUE; /* Also try examining DWARF2 debugging information. */ - if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, debug_sections, + section, symbols, offset, filename_ptr, functionname_ptr, line_ptr, 0, &coff_data(abfd)->dwarf2_find_line_info)) @@ -2293,6 +2333,21 @@ coff_find_nearest_line (bfd *abfd, return TRUE; } +bfd_boolean +coff_find_nearest_line (bfd *abfd, + asection *section, + asymbol **symbols, + bfd_vma offset, + const char **filename_ptr, + const char **functionname_ptr, + unsigned int *line_ptr) +{ + return coff_find_nearest_line_with_names (abfd, dwarf_debug_sections, + section, symbols, offset, + filename_ptr, functionname_ptr, + line_ptr); +} + bfd_boolean coff_find_inliner_info (bfd *abfd, const char **filename_ptr, @@ -2394,3 +2449,70 @@ bfd_coff_get_comdat_section (bfd *abfd, struct bfd_section *sec) else return NULL; } + +bfd_boolean +_bfd_coff_section_already_linked (bfd *abfd, + asection *sec, + struct bfd_link_info *info) +{ + flagword flags; + const char *name, *key; + struct bfd_section_already_linked *l; + struct bfd_section_already_linked_hash_entry *already_linked_list; + struct coff_comdat_info *s_comdat; + + flags = sec->flags; + if ((flags & SEC_LINK_ONCE) == 0) + return FALSE; + + /* The COFF backend linker doesn't support group sections. */ + if ((flags & SEC_GROUP) != 0) + return FALSE; + + name = bfd_get_section_name (abfd, sec); + s_comdat = bfd_coff_get_comdat_section (abfd, sec); + + if (s_comdat != NULL) + key = s_comdat->name; + else + { + if (CONST_STRNEQ (name, ".gnu.linkonce.") + && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) + key++; + else + /* FIXME: gcc as of 2011-09 emits sections like .text$, + .xdata$ and .pdata$ only the first of which has a + comdat key. Should these all match the LTO IR key? */ + key = name; + } + + already_linked_list = bfd_section_already_linked_table_lookup (key); + + for (l = already_linked_list->entry; l != NULL; l = l->next) + { + struct coff_comdat_info *l_comdat; + + l_comdat = bfd_coff_get_comdat_section (l->sec->owner, l->sec); + + /* The section names must match, and both sections must be + comdat and have the same comdat name, or both sections must + be non-comdat. LTO IR plugin sections are an exception. They + are always named .gnu.linkonce.t. ( is some string) + and match any comdat section with comdat name of , and + any linkonce section with the same suffix, ie. + .gnu.linkonce.*.. */ + if (((s_comdat != NULL) == (l_comdat != NULL) + && strcmp (name, l->sec->name) == 0) + || (l->sec->owner->flags & BFD_PLUGIN) != 0) + { + /* The section has already been linked. See if we should + issue a warning. */ + return _bfd_handle_already_linked (sec, l, info); + } + } + + /* This is the first section with this name. Record it. */ + if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) + info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return FALSE; +} diff --git a/contrib/gdb-7/bfd/compress.c b/contrib/gdb-7/bfd/compress.c index 669033c5ec..a82a8bc9e3 100644 --- a/contrib/gdb-7/bfd/compress.c +++ b/contrib/gdb-7/bfd/compress.c @@ -1,5 +1,5 @@ /* Compressed section support (intended for debug sections). - Copyright 2008, 2010 + Copyright 2008, 2010, 2011 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -158,7 +158,7 @@ DESCRIPTION bfd_boolean bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) { - bfd_size_type sz = sec->rawsize ? sec->rawsize : sec->size; + bfd_size_type sz; bfd_byte *p = *ptr; #ifdef HAVE_ZLIB_H bfd_boolean ret; @@ -169,6 +169,10 @@ bfd_get_full_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **ptr) bfd_byte *uncompressed_buffer; #endif + if (abfd->direction != write_direction && sec->rawsize != 0) + sz = sec->rawsize; + else + sz = sec->size; if (sz == 0) return TRUE; diff --git a/contrib/gdb-7/bfd/config.bfd b/contrib/gdb-7/bfd/config.bfd index 76d1927147..5337ce55b8 100644 --- a/contrib/gdb-7/bfd/config.bfd +++ b/contrib/gdb-7/bfd/config.bfd @@ -53,7 +53,6 @@ case $targ in sparc-*-lynxos* | \ vax-*-vms* | \ arm-*-oabi | \ - thumb-*-oabi | \ a29k-* | \ hppa*-*-rtems* | \ *-go32-rtems* | \ @@ -101,11 +100,10 @@ s390*) targ_archs=bfd_s390_arch ;; sh*) targ_archs=bfd_sh_arch ;; sparc*) targ_archs=bfd_sparc_arch ;; spu*) targ_archs=bfd_spu_arch ;; -strongarm*) targ_archs=bfd_arm_arch ;; -thumb*) targ_archs=bfd_arm_arch ;; +tilegx*) targ_archs=bfd_tilegx_arch ;; +tilepro*) targ_archs=bfd_tilepro_arch ;; v850*) targ_archs=bfd_v850_arch ;; x86_64*) targ_archs=bfd_i386_arch ;; -xscale*) targ_archs=bfd_arm_arch ;; xtensa*) targ_archs=bfd_xtensa_arch ;; z80|r800) targ_archs=bfd_z80_arch ;; z8k*) targ_archs=bfd_z8k_arch ;; @@ -176,6 +174,7 @@ case "${targ}" in ;; alpha*-*-*vms*) targ_defvec=vms_alpha_vec + targ_selvecs=vms_lib_txt_vec want64=true ;; alpha*-*-*) @@ -194,6 +193,7 @@ case "${targ}" in ;; ia64*-*-*vms*) targ_defvec=bfd_elf64_ia64_vms_vec + targ_selvecs=vms_lib_txt_vec want64=true ;; sparc64-*-freebsd* | sparc64-*-kfreebsd*-gnu) @@ -275,7 +275,7 @@ case "${targ}" in targ_defvec=bfd_elf32_bigarm_vec targ_selvecs=bfd_elf32_littlearm_vec ;; - arm-*-kaos* | strongarm-*-kaos*) + arm-*-kaos*) targ_defvec=bfd_elf32_littlearm_vec targ_selvecs=bfd_elf32_bigarm_vec ;; @@ -298,44 +298,6 @@ case "${targ}" in targ_selvecs=bfd_elf32_bigarm_vec ;; - thumb-*-coff) - targ_defvec=armcoff_little_vec - targ_selvecs=armcoff_big_vec - targ_underscore=yes - ;; - thumb-*-elf) - targ_defvec=bfd_elf32_littlearm_vec - targ_selvecs=bfd_elf32_bigarm_vec - ;; - thumb-epoc-pe*) - targ_defvec=arm_epoc_pe_little_vec - targ_selvecs="arm_epoc_pe_little_vec arm_epoc_pe_big_vec arm_epoc_pei_little_vec arm_epoc_pei_big_vec" - targ_underscore=no - ;; - thumb-*-pe*) - targ_defvec=armpe_little_vec - targ_selvecs="armpe_little_vec armpe_big_vec armpei_little_vec armpei_big_vec" - targ_underscore=yes - ;; - strongarm-*-elf) - targ_defvec=bfd_elf32_littlearm_vec - targ_selvecs=bfd_elf32_bigarm_vec - ;; - strongarm-*-coff) - targ_defvec=armcoff_little_vec - targ_selvecs=armcoff_big_vec - targ_underscore=yes - ;; - xscale-*-elf) - targ_defvec=bfd_elf32_littlearm_vec - targ_selvecs=bfd_elf32_bigarm_vec - ;; - xscale-*-coff) - targ_defvec=armcoff_little_vec - targ_selvecs=armcoff_big_vec - targ_underscore=yes - ;; - avr-*-*) targ_defvec=bfd_elf32_avr_vec ;; @@ -399,6 +361,10 @@ case "${targ}" in targ_defvec=bfd_elf32_d30v_vec ;; + epiphany-*-elf) + targ_defvec=bfd_elf32_epiphany_vec + ;; + fido-*-elf* ) targ_defvec=bfd_elf32_m68k_vec targ_selvecs="m68kcoff_vec ieee_vec" @@ -498,13 +464,13 @@ case "${targ}" in i[3-7]86-*-solaris2*) targ_defvec=bfd_elf32_i386_sol2_vec targ_selvecs="i386coff_vec" - targ64_selvecs="bfd_elf64_x86_64_sol2_vec bfd_elf64_l1om_vec" + targ64_selvecs="bfd_elf64_x86_64_sol2_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" want64=true ;; #ifdef BFD64 x86_64-*-solaris2*) targ_defvec=bfd_elf32_i386_sol2_vec - targ_selvecs="bfd_elf64_x86_64_sol2_vec bfd_elf64_l1om_vec i386coff_vec" + targ_selvecs="bfd_elf64_x86_64_sol2_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec i386coff_vec" want64=true ;; #endif @@ -524,7 +490,7 @@ case "${targ}" in ;; i[3-7]86-*-dicos*) targ_defvec=bfd_elf32_i386_vec - targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec" + targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" ;; *-*-msdosdjgpp* | *-*-go32* ) targ_defvec=go32coff_vec @@ -553,7 +519,7 @@ case "${targ}" in ;; i[3-7]86-*-dragonfly*) targ_defvec=bfd_elf32_i386_vec - targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec" + targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" ;; i[3-7]86-*-freebsdaout* | i[3-7]86-*-freebsd[12].* | \ i[3-7]86-*-freebsd[12]) @@ -564,7 +530,7 @@ case "${targ}" in i[3-7]86-*-freebsd* | i[3-7]86-*-kfreebsd*-gnu) targ_defvec=bfd_elf32_i386_freebsd_vec targ_selvecs="bfd_elf32_i386_vec i386pei_vec i386coff_vec" - targ64_selvecs="bfd_elf64_x86_64_freebsd_vec bfd_elf64_x86_64_vec x86_64pei_vec bfd_elf64_l1om_vec bfd_elf64_l1om_freebsd_vec" + targ64_selvecs="bfd_elf64_x86_64_freebsd_vec bfd_elf64_x86_64_vec x86_64pei_vec bfd_elf64_l1om_vec bfd_elf64_l1om_freebsd_vec bfd_elf64_k1om_vec bfd_elf64_k1om_freebsd_vec" # FreeBSD <= 4.0 supports only the old nonstandard way of ABI labelling. case "${targ}" in i[3-7]86-*-freebsd3* | i[3-7]86-*-freebsd4 | i[3-7]86-*-freebsd4.0*) @@ -574,7 +540,7 @@ case "${targ}" in i[3-7]86-*-netbsdelf* | i[3-7]86-*-netbsd*-gnu* | i[3-7]86-*-knetbsd*-gnu) targ_defvec=bfd_elf32_i386_vec targ_selvecs=i386netbsd_vec - targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec" + targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" ;; i[3-7]86-*-netbsdpe*) targ_defvec=i386pe_vec @@ -602,7 +568,11 @@ case "${targ}" in i[3-7]86-*-linux-*) targ_defvec=bfd_elf32_i386_vec targ_selvecs="i386linux_vec i386pei_vec" - targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf32_x86_64_vec bfd_elf64_l1om_vec" + targ64_selvecs="bfd_elf64_x86_64_vec bfd_elf32_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" + ;; + i[3-7]86-*-nacl*) + targ_defvec=bfd_elf32_i386_nacl_vec + targ_selvecs="bfd_elf32_i386_vec" ;; #ifdef BFD64 x86_64-*-darwin*) @@ -613,37 +583,37 @@ case "${targ}" in ;; x86_64-*-dicos*) targ_defvec=bfd_elf64_x86_64_vec - targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec" + targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" want64=true ;; x86_64-*-elf*) targ_defvec=bfd_elf64_x86_64_vec - targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec i386coff_vec" + targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec i386coff_vec" want64=true ;; x86_64-*-dragonfly*) targ_defvec=bfd_elf64_x86_64_vec - targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec" + targ_selvecs="bfd_elf32_i386_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" want64=true ;; x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu) targ_defvec=bfd_elf64_x86_64_freebsd_vec - targ_selvecs="bfd_elf32_i386_freebsd_vec i386coff_vec i386pei_vec x86_64pei_vec bfd_elf32_i386_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_l1om_freebsd_vec" + targ_selvecs="bfd_elf32_i386_freebsd_vec i386coff_vec i386pei_vec x86_64pei_vec bfd_elf32_i386_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_l1om_freebsd_vec bfd_elf64_k1om_vec bfd_elf64_k1om_freebsd_vec" want64=true ;; x86_64-*-netbsd* | x86_64-*-openbsd*) targ_defvec=bfd_elf64_x86_64_vec - targ_selvecs="bfd_elf32_i386_vec i386netbsd_vec i386coff_vec i386pei_vec x86_64pei_vec bfd_elf64_l1om_vec" + targ_selvecs="bfd_elf32_i386_vec i386netbsd_vec i386coff_vec i386pei_vec x86_64pei_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" want64=true ;; x86_64-*-linux-*) targ_defvec=bfd_elf64_x86_64_vec - targ_selvecs="bfd_elf32_i386_vec bfd_elf32_x86_64_vec i386linux_vec i386pei_vec x86_64pei_vec bfd_elf64_l1om_vec" + targ_selvecs="bfd_elf32_i386_vec bfd_elf32_x86_64_vec i386linux_vec i386pei_vec x86_64pei_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec" want64=true ;; - x86_64-*-mingw*) + x86_64-*-mingw* | x86_64-*-pe | x86_64-*-pep) targ_defvec=x86_64pe_vec - targ_selvecs="x86_64pe_vec x86_64pei_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec i386pe_vec i386pei_vec bfd_elf32_i386_vec" + targ_selvecs="x86_64pe_vec x86_64pei_vec bfd_elf64_x86_64_vec bfd_elf64_l1om_vec bfd_elf64_k1om_vec i386pe_vec i386pei_vec bfd_elf32_i386_vec" want64=true targ_underscore=no ;; @@ -752,12 +722,12 @@ case "${targ}" in targ_defvec=bfd_elf32_lm32_vec targ_selvecs=bfd_elf32_lm32fdpic_vec ;; - + lm32-*-*linux*) targ_defvec=bfd_elf32_lm32fdpic_vec targ_selvecs=bfd_elf32_lm32_vec ;; - + m32c-*-elf | m32c-*-rtems*) targ_defvec=bfd_elf32_m32c_vec ;; @@ -965,11 +935,11 @@ case "${targ}" in want64=true ;; #endif - mips*el-sde-elf*) + mips*el-sde-elf*) targ_defvec=bfd_elf32_tradlittlemips_vec targ_selvecs="bfd_elf32_tradbigmips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec" want64=true - ;; + ;; mips*-sde-elf*) targ_defvec=bfd_elf32_tradbigmips_vec targ_selvecs="bfd_elf32_tradlittlemips_vec bfd_elf32_ntradbigmips_vec bfd_elf32_ntradlittlemips_vec bfd_elf64_tradbigmips_vec bfd_elf64_tradlittlemips_vec" @@ -1162,6 +1132,11 @@ case "${targ}" in targ_selvecs=rs6000coff_vec want64=true ;; + powerpc64-*-freebsd*) + targ_defvec=bfd_elf64_powerpc_freebsd_vec + targ_selvecs="bfd_elf64_powerpc_vec bfd_elf32_powerpc_vec bfd_elf32_powerpc_freebsd_vec bfd_elf32_powerpcle_vec rs6000coff_vec rs6000coff64_vec aix5coff64_vec" + want64=true + ;; powerpc64-*-elf* | powerpc-*-elf64* | powerpc64-*-linux* | \ powerpc64-*-*bsd*) targ_defvec=bfd_elf64_powerpc_vec @@ -1174,6 +1149,11 @@ case "${targ}" in want64=true ;; #endif + powerpc-*-*freebsd*) + targ_defvec=bfd_elf32_powerpc_freebsd_vec + targ_selvecs="rs6000coff_vec bfd_elf32_powerpc_vec bfd_elf32_powerpcle_vec ppcboot_vec" + targ64_selvecs="bfd_elf64_powerpc_vec bfd_elf64_powerpcle_vec bfd_elf64_powerpc_freebsd_vec" + ;; powerpc-*-*bsd* | powerpc-*-elf* | powerpc-*-sysv4* | powerpc-*-eabi* | \ powerpc-*-solaris2* | powerpc-*-linux-* | powerpc-*-rtems* | \ powerpc-*-chorus*) @@ -1227,9 +1207,13 @@ case "${targ}" in targ_selvecs="bfd_powerpcle_pei_vec bfd_powerpc_pei_vec bfd_powerpcle_pe_vec bfd_powerpc_pe_vec" ;; + rl78-*-elf) + targ_defvec=bfd_elf32_rl78_vec + ;; + rx-*-elf) targ_defvec=bfd_elf32_rx_le_vec - targ_selvecs="bfd_elf32_rx_be_vec bfd_elf32_rx_le_vec" + targ_selvecs="bfd_elf32_rx_be_vec bfd_elf32_rx_le_vec bfd_elf32_rx_be_ns_vec" ;; s390-*-linux*) @@ -1505,9 +1489,14 @@ case "${targ}" in ;; #endif - tic6x-*-*) - targ_defvec=bfd_elf32_tic6x_le_vec - targ_selvecs=bfd_elf32_tic6x_be_vec + tic6x-*-elf) + targ_defvec=bfd_elf32_tic6x_elf_le_vec + targ_selvecs="bfd_elf32_tic6x_elf_be_vec bfd_elf32_tic6x_le_vec bfd_elf32_tic6x_be_vec" + ;; + + tic6x-*-uclinux) + targ_defvec=bfd_elf32_tic6x_linux_le_vec + targ_selvecs="bfd_elf32_tic6x_linux_be_vec bfd_elf32_tic6x_le_vec bfd_elf32_tic6x_be_vec" ;; tic80*-*-*) @@ -1515,6 +1504,17 @@ case "${targ}" in targ_underscore=yes ;; +#ifdef BFD64 + tilegx-*-*) + targ_defvec=bfd_elf64_tilegx_vec + targ_selvecs=bfd_elf32_tilegx_vec + ;; +#endif + + tilepro-*-*) + targ_defvec=bfd_elf32_tilepro_vec + ;; + v850*-*-*) targ_defvec=bfd_elf32_v850_vec ;; @@ -1563,7 +1563,7 @@ case "${targ}" in xc16x-*-elf) targ_defvec=bfd_elf32_xc16x_vec ;; - + z80-*-*) targ_defvec=z80coff_vec targ_underscore=no @@ -1625,3 +1625,10 @@ case "${targ_defvec} ${targ_selvecs}" in targ_archs="$targ_archs bfd_l1om_arch" ;; esac + +# If we support Intel K1OM target, then add support for bfd_k1om_arch. +case "${targ_defvec} ${targ_selvecs}" in + *bfd_elf64_k1om_vec*) + targ_archs="$targ_archs bfd_k1om_arch" + ;; +esac diff --git a/contrib/gdb-7/bfd/cpu-i386.c b/contrib/gdb-7/bfd/cpu-i386.c index c4f41c50c2..f98c0e5052 100644 --- a/contrib/gdb-7/bfd/cpu-i386.c +++ b/contrib/gdb-7/bfd/cpu-i386.c @@ -31,7 +31,8 @@ bfd_i386_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *compat = bfd_default_compatible (a, b); /* Don't allow mixing x64_32 with x86_64. */ - if (compat && a->bits_per_address != b->bits_per_address) + if (compat + && (a->mach & bfd_mach_x64_32) != (b->mach & bfd_mach_x64_32)) compat = NULL; return compat; @@ -40,7 +41,7 @@ bfd_i386_compatible (const bfd_arch_info_type *a, static const bfd_arch_info_type bfd_x64_32_arch_intel_syntax = { 64, /* 64 bits in a word */ - 32, /* 32 bits in an address */ + 64, /* 64 bits in an address */ 8, /* 8 bits in a byte */ bfd_arch_i386, bfd_mach_x64_32_intel_syntax, @@ -104,7 +105,7 @@ static const bfd_arch_info_type i8086_arch = static const bfd_arch_info_type bfd_x64_32_arch = { 64, /* 64 bits in a word */ - 32, /* 32 bits in an address */ + 64, /* 64 bits in an address */ 8, /* 8 bits in a byte */ bfd_arch_i386, bfd_mach_x64_32, diff --git a/contrib/gdb-7/bfd/dwarf2.c b/contrib/gdb-7/bfd/dwarf2.c index 38268561fb..577f278322 100644 --- a/contrib/gdb-7/bfd/dwarf2.c +++ b/contrib/gdb-7/bfd/dwarf2.c @@ -90,6 +90,9 @@ struct dwarf2_debug /* Last comp unit in list above. */ struct comp_unit *last_comp_unit; + /* Names of the debug sections. */ + const struct dwarf_debug_section *debug_sections; + /* The next unread compilation unit within the .debug_info section. Zero indicates that the .debug_info section has not been loaded into a buffer yet. */ @@ -278,7 +281,7 @@ struct attr_abbrev /* Map of uncompressed DWARF debug section name to compressed one. It is terminated by NULL uncompressed_name. */ -struct dwarf_debug_section dwarf_debug_sections[] = +const struct dwarf_debug_section dwarf_debug_sections[] = { { ".debug_abbrev", ".zdebug_abbrev" }, { ".debug_aranges", ".zdebug_aranges" }, @@ -287,6 +290,7 @@ struct dwarf_debug_section dwarf_debug_sections[] = { ".debug_line", ".zdebug_line" }, { ".debug_loc", ".zdebug_loc" }, { ".debug_macinfo", ".zdebug_macinfo" }, + { ".debug_macro", ".zdebug_macro" }, { ".debug_pubnames", ".zdebug_pubnames" }, { ".debug_pubtypes", ".zdebug_pubtypes" }, { ".debug_ranges", ".zdebug_ranges" }, @@ -314,6 +318,7 @@ enum dwarf_debug_section_enum debug_line, debug_loc, debug_macinfo, + debug_macro, debug_pubnames, debug_pubtypes, debug_ranges, @@ -467,14 +472,14 @@ lookup_info_hash_table (struct info_hash_table *hash_table, const char *key) static bfd_boolean read_section (bfd * abfd, - enum dwarf_debug_section_enum sec, + const struct dwarf_debug_section *sec, asymbol ** syms, bfd_uint64_t offset, bfd_byte ** section_buffer, bfd_size_type * section_size) { asection *msec; - const char *section_name = dwarf_debug_sections[sec].uncompressed_name; + const char *section_name = sec->uncompressed_name; /* read_section is a noop if the section has already been read. */ if (!*section_buffer) @@ -482,12 +487,14 @@ read_section (bfd * abfd, msec = bfd_get_section_by_name (abfd, section_name); if (! msec) { - section_name = dwarf_debug_sections[sec].compressed_name; - msec = bfd_get_section_by_name (abfd, section_name); + section_name = sec->compressed_name; + if (section_name != NULL) + msec = bfd_get_section_by_name (abfd, section_name); } if (! msec) { - (*_bfd_error_handler) (_("Dwarf Error: Can't find %s section."), section_name); + (*_bfd_error_handler) (_("Dwarf Error: Can't find %s section."), + sec->uncompressed_name); bfd_set_error (bfd_error_bad_value); return FALSE; } @@ -604,7 +611,8 @@ read_indirect_string (struct comp_unit * unit, *bytes_read_ptr = unit->offset_size; - if (! read_section (unit->abfd, debug_str, stash->syms, offset, + if (! read_section (unit->abfd, &stash->debug_sections[debug_str], + stash->syms, offset, &stash->dwarf_str_buffer, &stash->dwarf_str_size)) return NULL; @@ -686,7 +694,8 @@ read_abbrevs (bfd *abfd, bfd_uint64_t offset, struct dwarf2_debug *stash) unsigned int abbrev_form, hash_number; bfd_size_type amt; - if (! read_section (abfd, debug_abbrev, stash->syms, offset, + if (! read_section (abfd, &stash->debug_sections[debug_abbrev], + stash->syms, offset, &stash->dwarf_abbrev_buffer, &stash->dwarf_abbrev_size)) return NULL; @@ -1394,7 +1403,8 @@ decode_line_info (struct comp_unit *unit, struct dwarf2_debug *stash) unsigned char op_code, extended_op, adj_opcode; bfd_size_type amt; - if (! read_section (abfd, debug_line, stash->syms, unit->line_offset, + if (! read_section (abfd, &stash->debug_sections[debug_line], + stash->syms, unit->line_offset, &stash->dwarf_line_buffer, &stash->dwarf_line_size)) return NULL; @@ -1809,7 +1819,8 @@ static bfd_boolean read_debug_ranges (struct comp_unit *unit) { struct dwarf2_debug *stash = unit->stash; - return read_section (unit->abfd, debug_ranges, stash->syms, 0, + return read_section (unit->abfd, &stash->debug_sections[debug_ranges], + stash->syms, 0, &stash->dwarf_ranges_buffer, &stash->dwarf_ranges_size); } @@ -2164,6 +2175,7 @@ scan_unit_for_symbols (struct comp_unit *unit) break; case DW_AT_abstract_origin: + case DW_AT_specification: func->name = find_abstract_instance_name (unit, &attr); break; @@ -2714,18 +2726,18 @@ comp_unit_hash_info (struct dwarf2_debug *stash, /* Locate a section in a BFD containing debugging info. The search starts from the section after AFTER_SEC, or from the first section in the BFD if AFTER_SEC is NULL. The search works by examining the names of the - sections. There are two permissiable names. The first is .debug_info. - This is the standard DWARF2 name. The second is a prefix .gnu.linkonce.wi. + sections. There are three permissiable names. The first two are given + by DEBUG_SECTIONS[debug_info] (whose standard DWARF2 names are .debug_info + and .zdebug_info). The third is a prefix .gnu.linkonce.wi. This is a variation on the .debug_info section which has a checksum describing the contents appended onto the name. This allows the linker to identify and discard duplicate debugging sections for different compilation units. */ -#define DWARF2_DEBUG_INFO ".debug_info" -#define DWARF2_COMPRESSED_DEBUG_INFO ".zdebug_info" #define GNU_LINKONCE_INFO ".gnu.linkonce.wi." static asection * -find_debug_info (bfd *abfd, asection *after_sec) +find_debug_info (bfd *abfd, const struct dwarf_debug_section *debug_sections, + asection *after_sec) { asection * msec; @@ -2733,10 +2745,13 @@ find_debug_info (bfd *abfd, asection *after_sec) while (msec) { - if (strcmp (msec->name, DWARF2_DEBUG_INFO) == 0) + if (strcmp (msec->name, + debug_sections[debug_info].uncompressed_name) == 0) return msec; - if (strcmp (msec->name, DWARF2_COMPRESSED_DEBUG_INFO) == 0) + if (debug_sections[debug_info].compressed_name != NULL + && strcmp (msec->name, + debug_sections[debug_info].compressed_name) == 0) return msec; if (CONST_STRNEQ (msec->name, GNU_LINKONCE_INFO)) @@ -2783,7 +2798,9 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) asection *sect; bfd_vma last_vma = 0, last_dwarf = 0; bfd_size_type amt; + const char *debug_info_name; + debug_info_name = stash->debug_sections[debug_info].uncompressed_name; i = 0; for (sect = abfd->sections; sect != NULL; sect = sect->next) { @@ -2796,7 +2813,7 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) /* We need to adjust the VMAs of any .debug_info sections. Skip compressed ones, since no relocations could target them - they should not appear in object files anyway. */ - if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0) + if (strcmp (sect->name, debug_info_name) == 0) is_debug_info = 1; else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO)) is_debug_info = 1; @@ -2832,7 +2849,7 @@ place_sections (bfd *abfd, struct dwarf2_debug *stash) /* We need to adjust the VMAs of any .debug_info sections. Skip compressed ones, since no relocations could target them - they should not appear in object files anyway. */ - if (strcmp (sect->name, DWARF2_DEBUG_INFO) == 0) + if (strcmp (sect->name, debug_info_name) == 0) is_debug_info = 1; else if (CONST_STRNEQ (sect->name, GNU_LINKONCE_INFO)) is_debug_info = 1; @@ -3107,12 +3124,14 @@ stash_find_line_fast (struct dwarf2_debug *stash, FILENAME_PTR and LINENUMBER_PTR. In the case where SYMBOL was NULL the FUNCTIONNAME_PTR is also filled in. SYMBOLS contains the symbol table for ABFD. + DEBUG_SECTIONS contains the name of the dwarf debug sections. ADDR_SIZE is the number of bytes in the initial .debug_info length field and in the abbreviation offset, or zero to indicate that the default value should be used. */ static bfd_boolean find_line (bfd *abfd, + const struct dwarf_debug_section *debug_sections, asection *section, bfd_vma offset, asymbol *symbol, @@ -3147,6 +3166,7 @@ find_line (bfd *abfd, stash = (struct dwarf2_debug *) bfd_zalloc (abfd, amt); if (! stash) return FALSE; + stash->debug_sections = debug_sections; } /* In a relocatable file, 2 functions may have the same address. @@ -3190,7 +3210,7 @@ find_line (bfd *abfd, *pinfo = stash; - msec = find_debug_info (abfd, NULL); + msec = find_debug_info (abfd, debug_sections, NULL); if (msec == NULL) { char * debug_filename = bfd_follow_gnu_debuglink (abfd, DEBUGDIR); @@ -3204,7 +3224,8 @@ find_line (bfd *abfd, if ((debug_bfd = bfd_openr (debug_filename, NULL)) == NULL || ! bfd_check_format (debug_bfd, bfd_object) - || (msec = find_debug_info (debug_bfd, NULL)) == NULL) + || (msec = find_debug_info (debug_bfd, + debug_sections, NULL)) == NULL) { if (debug_bfd) bfd_close (debug_bfd); @@ -3227,18 +3248,21 @@ find_line (bfd *abfd, some or all sections are compressed, then do things the slow way, with a bunch of reallocs. */ - if (! find_debug_info (debug_bfd, msec)) + if (! find_debug_info (debug_bfd, debug_sections, msec)) { /* Case 1: only one info section. */ total_size = msec->size; - if (! read_section (debug_bfd, debug_info, symbols, 0, + if (! read_section (debug_bfd, &stash->debug_sections[debug_info], + symbols, 0, &stash->info_ptr_memory, &total_size)) goto done; } else { /* Case 2: multiple sections. */ - for (total_size = 0; msec; msec = find_debug_info (debug_bfd, msec)) + for (total_size = 0; + msec; + msec = find_debug_info (debug_bfd, debug_sections, msec)) total_size += msec->size; stash->info_ptr_memory = (bfd_byte *) bfd_malloc (total_size); @@ -3246,9 +3270,9 @@ find_line (bfd *abfd, goto done; total_size = 0; - for (msec = find_debug_info (debug_bfd, NULL); + for (msec = find_debug_info (debug_bfd, debug_sections, NULL); msec; - msec = find_debug_info (debug_bfd, msec)) + msec = find_debug_info (debug_bfd, debug_sections, msec)) { bfd_size_type size; @@ -3267,7 +3291,7 @@ find_line (bfd *abfd, stash->info_ptr = stash->info_ptr_memory; stash->info_ptr_end = stash->info_ptr + total_size; - stash->sec = find_debug_info (debug_bfd, NULL); + stash->sec = find_debug_info (debug_bfd, debug_sections, NULL); stash->sec_info_ptr = stash->info_ptr; stash->syms = symbols; stash->bfd_ptr = debug_bfd; @@ -3422,7 +3446,8 @@ find_line (bfd *abfd, if ((bfd_vma) (stash->info_ptr - stash->sec_info_ptr) == stash->sec->size) { - stash->sec = find_debug_info (stash->bfd_ptr, stash->sec); + stash->sec = find_debug_info (stash->bfd_ptr, debug_sections, + stash->sec); stash->sec_info_ptr = stash->info_ptr; } @@ -3443,6 +3468,7 @@ done: bfd_boolean _bfd_dwarf2_find_nearest_line (bfd *abfd, + const struct dwarf_debug_section *debug_sections, asection *section, asymbol **symbols, bfd_vma offset, @@ -3452,8 +3478,8 @@ _bfd_dwarf2_find_nearest_line (bfd *abfd, unsigned int addr_size, void **pinfo) { - return find_line (abfd, section, offset, NULL, symbols, filename_ptr, - functionname_ptr, linenumber_ptr, addr_size, + return find_line (abfd, debug_sections, section, offset, NULL, symbols, + filename_ptr, functionname_ptr, linenumber_ptr, addr_size, pinfo); } @@ -3469,9 +3495,8 @@ _bfd_dwarf2_find_line (bfd *abfd, unsigned int addr_size, void **pinfo) { - return find_line (abfd, NULL, 0, symbol, symbols, filename_ptr, - NULL, linenumber_ptr, addr_size, - pinfo); + return find_line (abfd, dwarf_debug_sections, NULL, 0, symbol, symbols, + filename_ptr, NULL, linenumber_ptr, addr_size, pinfo); } bfd_boolean diff --git a/contrib/gdb-7/bfd/elf-bfd.h b/contrib/gdb-7/bfd/elf-bfd.h index 21ec38f2c9..486b76eecf 100644 --- a/contrib/gdb-7/bfd/elf-bfd.h +++ b/contrib/gdb-7/bfd/elf-bfd.h @@ -1,6 +1,6 @@ /* BFD back-end data structures for ELF files. Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -232,11 +232,7 @@ struct elf_link_hash_entry }; /* Will references to this symbol always reference the symbol - in this object? STV_PROTECTED is excluded from the visibility test - here so that function pointer comparisons work properly. Since - function symbols not defined in an app are set to their .plt entry, - it's necessary for shared libs to also reference the .plt even - though the symbol is really local to the shared lib. */ + in this object? */ #define SYMBOL_REFERENCES_LOCAL(INFO, H) \ _bfd_elf_symbol_refs_local_p (H, INFO, 0) @@ -432,6 +428,8 @@ enum elf_target_id TIC6X_ELF_DATA, X86_64_ELF_DATA, XTENSA_ELF_DATA, + TILEGX_ELF_DATA, + TILEPRO_ELF_DATA, GENERIC_ELF_DATA }; @@ -716,6 +714,10 @@ struct elf_backend_data /* The BFD flags applied to sections created for dynamic linking. */ flagword dynamic_sec_flags; + /* Architecture-specific data for this backend. + This is actually a pointer to some type like struct elf_ARCH_data. */ + const void *arch_data; + /* A function to translate an ELF RELA relocation to a BFD arelent structure. */ void (*elf_info_to_howto) @@ -1114,6 +1116,11 @@ struct elf_backend_data char *(*elf_backend_write_core_note) (bfd *abfd, char *buf, int *bufsiz, int note_type, ...); + /* This function, if defined, is called to convert target-specific + section flag names into hex values. */ + flagword (*elf_backend_lookup_section_flags_hook) + (char *); + /* This function returns class of a reloc type. */ enum elf_reloc_type_class (*elf_backend_reloc_type_class) (const Elf_Internal_Rela *); @@ -1476,6 +1483,15 @@ enum Tag_compatibility = 32 }; +/* The following struct stores information about every SystemTap section + found in the object file. */ +struct sdt_note +{ + struct sdt_note *next; + bfd_size_type size; + bfd_byte data[1]; +}; + /* Some private data is stashed away for future use using the tdata pointer in the bfd structure. */ @@ -1541,7 +1557,7 @@ struct elf_obj_tdata const char *dt_name; /* The linker emulation needs to know what audit libs - are used by a dynamic object. */ + are used by a dynamic object. */ const char *dt_audit; /* Records the result of `get_program_header_size'. */ @@ -1633,10 +1649,15 @@ struct elf_obj_tdata bfd_size_type build_id_size; bfd_byte *build_id; + /* Linked-list containing information about every Systemtap section + found in the object file. Each section corresponds to one entry + in the list. */ + struct sdt_note *sdt_note_head; + /* True if the bfd contains symbols that have the STT_GNU_IFUNC - symbol type. Used to set the osabi field in the ELF header - structure. */ - bfd_boolean has_ifunc_symbols; + symbol type or STB_GNU_UNIQUE binding. Used to set the osabi + field in the ELF header structure. */ + bfd_boolean has_gnu_symbols; /* An identifier used to distinguish different target specific extensions to this structure. */ @@ -1780,8 +1801,8 @@ extern bfd_boolean _bfd_elf_match_sections_by_type (bfd *, const asection *, bfd *, const asection *); extern bfd_boolean bfd_elf_is_group_section (bfd *, const struct bfd_section *); -extern void _bfd_elf_section_already_linked - (bfd *, struct bfd_section *, struct bfd_link_info *); +extern bfd_boolean _bfd_elf_section_already_linked + (bfd *, asection *, struct bfd_link_info *); extern void bfd_elf_set_group_contents (bfd *, asection *, void *); extern asection *_bfd_elf_check_kept_section @@ -1875,7 +1896,7 @@ extern bfd_boolean bfd_section_from_phdr extern int _bfd_elf_symbol_from_bfd_symbol (bfd *, asymbol **); -extern Elf_Internal_Sym *bfd_sym_from_r_symndx +extern Elf_Internal_Sym *bfd_sym_from_r_symndx (struct sym_cache *, bfd *, unsigned long); extern asection *bfd_section_from_elf_index (bfd *, unsigned int); @@ -2159,6 +2180,9 @@ extern bfd_boolean _bfd_elf_gc_mark_fdes extern bfd_boolean _bfd_elf_gc_mark (struct bfd_link_info *, asection *, elf_gc_mark_hook_fn); +extern bfd_boolean _bfd_elf_gc_mark_extra_sections + (struct bfd_link_info *, elf_gc_mark_hook_fn); + extern bfd_boolean bfd_elf_gc_common_finalize_got_offsets (bfd *, struct bfd_link_info *); @@ -2178,6 +2202,9 @@ extern bfd_boolean _bfd_elf_is_function_type (unsigned int); extern int bfd_elf_get_default_section_type (flagword); +extern void bfd_elf_lookup_section_flags + (struct bfd_link_info *, struct flag_info *); + extern Elf_Internal_Phdr * _bfd_elf_find_segment_containing_section (bfd * abfd, asection * section); @@ -2210,6 +2237,12 @@ extern char *elfcore_write_s390_ctrs (bfd *, char *, int *, const void *, int); extern char *elfcore_write_s390_prefix (bfd *, char *, int *, const void *, int); +extern char *elfcore_write_s390_last_break + (bfd *, char *, int *, const void *, int); +extern char *elfcore_write_s390_system_call + (bfd *, char *, int *, const void *, int); +extern char *elfcore_write_arm_vfp + (bfd *, char *, int *, const void *, int); extern char *elfcore_write_lwpstatus (bfd *, char *, int *, long, int, const void *); extern char *elfcore_write_register_note @@ -2246,7 +2279,7 @@ extern bfd_boolean _bfd_elf_merge_unknown_attribute_low (bfd *, bfd *, int); extern bfd_boolean _bfd_elf_merge_unknown_attribute_list (bfd *, bfd *); extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr (asection *sec); -/* The linker may needs to keep track of the number of relocs that it +/* The linker may need to keep track of the number of relocs that it decides to copy as dynamic relocs in check_relocs for each symbol. This is so that it can later discard them if they are found to be unnecessary. We can store the information in a field extending the @@ -2364,7 +2397,7 @@ extern asection _bfd_elf_large_com_section; /* This macro is to avoid lots of duplicated code in the body of the loop over relocations in xxx_relocate_section() in the various elfxx-xxxx.c files. - + Handle relocations against symbols from removed linkonce sections, or sections discarded by a linker script. When doing a relocatable link, we remove such relocations. Otherwise, we just want the @@ -2391,7 +2424,7 @@ extern asection _bfd_elf_large_com_section; rel_hdr = _bfd_elf_single_rel_hdr (input_section); \ rel_hdr->sh_size -= rel_hdr->sh_entsize; \ \ - memmove (rel, rel + 1, (relend - rel) * sizeof (*rel)); \ + memmove (rel, rel + 1, (relend - rel - 1) * sizeof (*rel)); \ \ input_section->reloc_count--; \ relend--; \ diff --git a/contrib/gdb-7/bfd/elf-eh-frame.c b/contrib/gdb-7/bfd/elf-eh-frame.c index 0a22138147..54142b2952 100644 --- a/contrib/gdb-7/bfd/elf-eh-frame.c +++ b/contrib/gdb-7/bfd/elf-eh-frame.c @@ -1,5 +1,5 @@ /* .eh_frame section optimization. - Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Jakub Jelinek . @@ -490,7 +490,8 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, if (hdr_info->parsed_eh_frames) return; - if (sec->size == 0) + if (sec->size == 0 + || sec->sec_info_type != ELF_INFO_TYPE_NONE) { /* This file does not contain .eh_frame information. */ return; @@ -777,8 +778,6 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, } else { - asection *rsec; - /* Find the corresponding CIE. */ unsigned int cie_offset = this_inf->offset + 4 - hdr_id; for (cie = local_cies; cie < local_cies + cie_count; cie++) @@ -794,17 +793,22 @@ _bfd_elf_parse_eh_frame (bfd *abfd, struct bfd_link_info *info, = cie->cie_inf->add_augmentation_size; ENSURE_NO_RELOCS (buf); - REQUIRE (GET_RELOC (buf)); - - /* Chain together the FDEs for each section. */ - rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); - /* RSEC will be NULL if FDE was cleared out as it was belonging to - a discarded SHT_GROUP. */ - if (rsec) + if ((sec->flags & SEC_LINKER_CREATED) == 0 || cookie->rels != NULL) { - REQUIRE (rsec->owner == abfd); - this_inf->u.fde.next_for_section = elf_fde_list (rsec); - elf_fde_list (rsec) = this_inf; + asection *rsec; + + REQUIRE (GET_RELOC (buf)); + + /* Chain together the FDEs for each section. */ + rsec = _bfd_elf_gc_mark_rsec (info, sec, gc_mark_hook, cookie); + /* RSEC will be NULL if FDE was cleared out as it was belonging to + a discarded SHT_GROUP. */ + if (rsec) + { + REQUIRE (rsec->owner == abfd); + this_inf->u.fde.next_for_section = elf_fde_list (rsec); + elf_fde_list (rsec) = this_inf; + } } /* Skip the initial location and address range. */ @@ -1133,10 +1137,16 @@ _bfd_elf_discard_section_eh_frame struct eh_frame_hdr_info *hdr_info; unsigned int ptr_size, offset; + if (sec->sec_info_type != ELF_INFO_TYPE_EH_FRAME) + return FALSE; + sec_info = (struct eh_frame_sec_info *) elf_section_data (sec)->sec_info; if (sec_info == NULL) return FALSE; + ptr_size = (get_elf_backend_data (sec->owner) + ->elf_backend_eh_frame_address_size (sec->owner, sec)); + hdr_info = &elf_hash_table (info)->eh_info; for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent) if (ent->size == 4) @@ -1145,11 +1155,25 @@ _bfd_elf_discard_section_eh_frame ent->removed = sec->map_head.s != NULL; else if (!ent->cie) { - cookie->rel = cookie->rels + ent->reloc_index; - /* FIXME: octets_per_byte. */ - BFD_ASSERT (cookie->rel < cookie->relend - && cookie->rel->r_offset == ent->offset + 8); - if (!(*reloc_symbol_deleted_p) (ent->offset + 8, cookie)) + bfd_boolean keep; + if ((sec->flags & SEC_LINKER_CREATED) != 0 && cookie->rels == NULL) + { + unsigned int width + = get_DW_EH_PE_width (ent->fde_encoding, ptr_size); + bfd_vma value + = read_value (abfd, sec->contents + ent->offset + 8 + width, + width, get_DW_EH_PE_signed (ent->fde_encoding)); + keep = value != 0; + } + else + { + cookie->rel = cookie->rels + ent->reloc_index; + /* FIXME: octets_per_byte. */ + BFD_ASSERT (cookie->rel < cookie->relend + && cookie->rel->r_offset == ent->offset + 8); + keep = !(*reloc_symbol_deleted_p) (ent->offset + 8, cookie); + } + if (keep) { if (info->shared && (((ent->fde_encoding & 0x70) == DW_EH_PE_absptr @@ -1178,8 +1202,6 @@ _bfd_elf_discard_section_eh_frame sec_info->cies = NULL; } - ptr_size = (get_elf_backend_data (sec->owner) - ->elf_backend_eh_frame_address_size (sec->owner, sec)); offset = 0; for (ent = sec_info->entry; ent < sec_info->entry + sec_info->count; ++ent) if (!ent->removed) diff --git a/contrib/gdb-7/bfd/elf-ifunc.c b/contrib/gdb-7/bfd/elf-ifunc.c index 81429b8433..3ba96c7961 100644 --- a/contrib/gdb-7/bfd/elf-ifunc.c +++ b/contrib/gdb-7/bfd/elf-ifunc.c @@ -299,9 +299,10 @@ keep: 5. Otherwise use .got so that it can be shared among different objects at run-time. We only need to relocate .got entry in shared object. */ - if ((info->shared - && (h->dynindx == -1 - || h->forced_local)) + if (h->got.refcount <= 0 + || (info->shared + && (h->dynindx == -1 + || h->forced_local)) || (!info->shared && !h->pointer_equality_needed) || (info->executable && info->shared) diff --git a/contrib/gdb-7/bfd/elf.c b/contrib/gdb-7/bfd/elf.c index f69abf2218..f1e4882530 100644 --- a/contrib/gdb-7/bfd/elf.c +++ b/contrib/gdb-7/bfd/elf.c @@ -976,7 +976,9 @@ _bfd_elf_make_section_from_shdr (bfd *abfd, phdr = elf_tdata (abfd)->phdr; for (i = 0; i < elf_elfheader (abfd)->e_phnum; i++, phdr++) { - if (phdr->p_type == PT_LOAD + if (((phdr->p_type == PT_LOAD + && (hdr->sh_flags & SHF_TLS) == 0) + || phdr->p_type == PT_TLS) && ELF_SECTION_IN_SEGMENT (hdr, phdr)) { if ((flags & SEC_LOAD) == 0) @@ -2164,7 +2166,7 @@ static const struct bfd_elf_special_section special_sections_z[] = { NULL, 0, 0, 0, 0 } }; -static const struct bfd_elf_special_section *special_sections[] = +static const struct bfd_elf_special_section * const special_sections[] = { special_sections_b, /* 'b' */ special_sections_c, /* 'c' */ @@ -3987,8 +3989,12 @@ _bfd_elf_map_sections_to_segments (bfd *abfd, struct bfd_link_info *info) phdr_in_segment = FALSE; } - /* Create a final PT_LOAD program segment. */ - if (last_hdr != NULL) + /* Create a final PT_LOAD program segment, but not if it's just + for .tbss. */ + if (last_hdr != NULL + && (i - phdr_index != 1 + || ((last_hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) + != SEC_THREAD_LOCAL))) { m = make_mapping (abfd, sections, phdr_index, i, phdr_in_segment); if (m == NULL) @@ -4684,6 +4690,21 @@ assign_file_positions_for_load_sections (bfd *abfd, if (this_hdr->sh_type != SHT_NOBITS) off += this_hdr->sh_size; } + else if (this_hdr->sh_type == SHT_NOBITS + && (this_hdr->sh_flags & SHF_TLS) != 0 + && this_hdr->sh_offset == 0) + { + /* This is a .tbss section that didn't get a PT_LOAD. + (See _bfd_elf_map_sections_to_segments "Create a + final PT_LOAD".) Set sh_offset to the value it + would have if we had created a zero p_filesz and + p_memsz PT_LOAD header for the section. This + also makes the PT_TLS header have the same + p_offset value. */ + bfd_vma adjust = vma_page_aligned_bias (this_hdr->sh_addr, + off, align); + this_hdr->sh_offset = sec->filepos = off + adjust; + } if (this_hdr->sh_type != SHT_NOBITS) { @@ -4748,7 +4769,8 @@ assign_file_positions_for_load_sections (bfd *abfd, sec = m->sections[i]; this_hdr = &(elf_section_data(sec)->this_hdr); - if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0)) + if (!ELF_SECTION_IN_SEGMENT_1 (this_hdr, p, check_vma, 0) + && !ELF_TBSS_SPECIAL (this_hdr, p)) { (*_bfd_error_handler) (_("%B: section `%A' can't be allocated in segment %d"), @@ -4919,17 +4941,21 @@ assign_file_positions_for_non_load_sections (bfd *abfd, && (p->p_type != PT_NOTE || bfd_get_format (abfd) != bfd_core)) { - Elf_Internal_Shdr *hdr; - asection *sect; - BFD_ASSERT (!m->includes_filehdr && !m->includes_phdrs); - sect = m->sections[m->count - 1]; - hdr = &elf_section_data (sect)->this_hdr; - p->p_filesz = sect->filepos - m->sections[0]->filepos; - if (hdr->sh_type != SHT_NOBITS) - p->p_filesz += hdr->sh_size; + p->p_filesz = 0; p->p_offset = m->sections[0]->filepos; + for (i = m->count; i-- != 0;) + { + asection *sect = m->sections[i]; + Elf_Internal_Shdr *hdr = &elf_section_data (sect)->this_hdr; + if (hdr->sh_type != SHT_NOBITS) + { + p->p_filesz = (sect->filepos - m->sections[0]->filepos + + hdr->sh_size); + break; + } + } } } else if (m->includes_filehdr) @@ -6248,6 +6274,8 @@ _bfd_elf_init_private_section_data (bfd *ibfd, || obfd->xvec->flavour != bfd_target_elf_flavour) return TRUE; + BFD_ASSERT (elf_section_data (osec) != NULL); + /* For objcopy and relocatable link, don't copy the output ELF section type from input if the output BFD section flags have been set to something different. For a final link allow some flags @@ -7365,6 +7393,9 @@ elf_find_function (bfd *abfd, enum { nothing_seen, symbol_seen, file_after_symbol_seen } state; const struct elf_backend_data *bed = get_elf_backend_data (abfd); + if (symbols == NULL) + return FALSE; + filename = NULL; func = NULL; file = NULL; @@ -7445,7 +7476,8 @@ _bfd_elf_find_nearest_line (bfd *abfd, return TRUE; } - if (_bfd_dwarf2_find_nearest_line (abfd, section, symbols, offset, + if (_bfd_dwarf2_find_nearest_line (abfd, dwarf_debug_sections, + section, symbols, offset, filename_ptr, functionname_ptr, line_ptr, 0, &elf_tdata (abfd)->dwarf2_find_line_info)) @@ -7950,6 +7982,24 @@ elfcore_grok_s390_prefix (bfd *abfd, Elf_Internal_Note *note) return elfcore_make_note_pseudosection (abfd, ".reg-s390-prefix", note); } +static bfd_boolean +elfcore_grok_s390_last_break (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-last-break", note); +} + +static bfd_boolean +elfcore_grok_s390_system_call (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-s390-system-call", note); +} + +static bfd_boolean +elfcore_grok_arm_vfp (bfd *abfd, Elf_Internal_Note *note) +{ + return elfcore_make_note_pseudosection (abfd, ".reg-arm-vfp", note); +} + #if defined (HAVE_PRPSINFO_T) typedef prpsinfo_t elfcore_psinfo_t; #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */ @@ -8000,6 +8050,9 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); +#if defined (HAVE_PSINFO_T_PR_PID) || defined (HAVE_PRPSINFO_T_PR_PID) + elf_tdata (abfd)->core_pid = psinfo.pr_pid; +#endif elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); @@ -8016,6 +8069,9 @@ elfcore_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) memcpy (&psinfo, note->descdata, sizeof (psinfo)); +#if defined (HAVE_PSINFO32_T_PR_PID) || defined (HAVE_PRPSINFO32_T_PR_PID) + elf_tdata (abfd)->core_pid = psinfo.pr_pid; +#endif elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname)); @@ -8363,6 +8419,27 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note) else return TRUE; + case NT_S390_LAST_BREAK: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_last_break (abfd, note); + else + return TRUE; + + case NT_S390_SYSTEM_CALL: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_s390_system_call (abfd, note); + else + return TRUE; + + case NT_ARM_VFP: + if (note->namesz == 6 + && strcmp (note->namedata, "LINUX") == 0) + return elfcore_grok_arm_vfp (abfd, note); + else + return TRUE; + case NT_PRPSINFO: case NT_PSINFO: if (bed->elf_backend_grok_psinfo) @@ -8416,6 +8493,35 @@ elfobj_grok_gnu_note (bfd *abfd, Elf_Internal_Note *note) } } +static bfd_boolean +elfobj_grok_stapsdt_note_1 (bfd *abfd, Elf_Internal_Note *note) +{ + struct sdt_note *cur = + (struct sdt_note *) bfd_alloc (abfd, sizeof (struct sdt_note) + + note->descsz); + + cur->next = (struct sdt_note *) (elf_tdata (abfd))->sdt_note_head; + cur->size = (bfd_size_type) note->descsz; + memcpy (cur->data, note->descdata, note->descsz); + + elf_tdata (abfd)->sdt_note_head = cur; + + return TRUE; +} + +static bfd_boolean +elfobj_grok_stapsdt_note (bfd *abfd, Elf_Internal_Note *note) +{ + switch (note->type) + { + case NT_STAPSDT: + return elfobj_grok_stapsdt_note_1 (abfd, note); + + default: + return TRUE; + } +} + static bfd_boolean elfcore_netbsd_get_lwpid (Elf_Internal_Note *note, int *lwpidp) { @@ -9087,6 +9193,44 @@ elfcore_write_s390_prefix (bfd *abfd, note_name, NT_S390_PREFIX, s390_prefix, size); } +char * +elfcore_write_s390_last_break (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_last_break, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_LAST_BREAK, + s390_last_break, size); +} + +char * +elfcore_write_s390_system_call (bfd *abfd, + char *buf, + int *bufsiz, + const void *s390_system_call, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_S390_SYSTEM_CALL, + s390_system_call, size); +} + +char * +elfcore_write_arm_vfp (bfd *abfd, + char *buf, + int *bufsiz, + const void *arm_vfp, + int size) +{ + char *note_name = "LINUX"; + return elfcore_write_note (abfd, buf, bufsiz, + note_name, NT_ARM_VFP, arm_vfp, size); +} + char * elfcore_write_register_note (bfd *abfd, char *buf, @@ -9117,6 +9261,12 @@ elfcore_write_register_note (bfd *abfd, return elfcore_write_s390_ctrs (abfd, buf, bufsiz, data, size); if (strcmp (section, ".reg-s390-prefix") == 0) return elfcore_write_s390_prefix (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-last-break") == 0) + return elfcore_write_s390_last_break (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-s390-system-call") == 0) + return elfcore_write_s390_system_call (abfd, buf, bufsiz, data, size); + if (strcmp (section, ".reg-arm-vfp") == 0) + return elfcore_write_arm_vfp (abfd, buf, bufsiz, data, size); return NULL; } @@ -9189,6 +9339,12 @@ elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset) if (! elfobj_grok_gnu_note (abfd, &in)) return FALSE; } + else if (in.namesz == sizeof "stapsdt" + && strcmp (in.namedata, "stapsdt") == 0) + { + if (! elfobj_grok_stapsdt_note (abfd, &in)) + return FALSE; + } break; } @@ -9344,6 +9500,12 @@ _bfd_elf_section_offset (bfd *abfd, case ELF_INFO_TYPE_EH_FRAME: return _bfd_elf_eh_frame_section_offset (abfd, info, sec, offset); default: + if ((sec->flags & SEC_ELF_REVERSE_COPY) != 0) + { + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + bfd_size_type address_size = bed->s->arch_size / 8; + offset = sec->size - offset - address_size; + } return offset; } } @@ -9505,11 +9667,11 @@ _bfd_elf_set_osabi (bfd * abfd, i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi; /* To make things simpler for the loader on Linux systems we set the - osabi field to ELFOSABI_LINUX if the binary contains symbols of - the STT_GNU_IFUNC type. */ + osabi field to ELFOSABI_GNU if the binary contains symbols of + the STT_GNU_IFUNC type or STB_GNU_UNIQUE binding. */ if (i_ehdrp->e_ident[EI_OSABI] == ELFOSABI_NONE - && elf_tdata (abfd)->has_ifunc_symbols) - i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX; + && elf_tdata (abfd)->has_gnu_symbols) + i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_GNU; } diff --git a/contrib/gdb-7/bfd/elf32-i386.c b/contrib/gdb-7/bfd/elf32-i386.c index 693c8e89d2..d1873051b4 100644 --- a/contrib/gdb-7/bfd/elf32-i386.c +++ b/contrib/gdb-7/bfd/elf32-i386.c @@ -1,6 +1,7 @@ /* Intel 80386/80486-specific support for 32-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -28,6 +29,7 @@ #include "bfd_stdint.h" #include "objalloc.h" #include "hashtab.h" +#include "dwarf2.h" /* 386 uses REL relocations instead of RELA. */ #define USE_REL 1 @@ -323,7 +325,7 @@ elf_i386_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, case BFD_RELOC_386_IRELATIVE: TRACE ("BFD_RELOC_386_IRELATIVE"); - return &elf_howto_table[R_386_IRELATIVE]; + return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset]; case BFD_RELOC_VTABLE_INHERIT: TRACE ("BFD_RELOC_VTABLE_INHERIT"); @@ -573,12 +575,135 @@ static const bfd_byte elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] = 0, 0, 0, 0 /* replaced with offset to start of .plt. */ }; +/* .eh_frame covering the .plt section. */ + +static const bfd_byte elf_i386_eh_frame_plt[] = +{ +#define PLT_CIE_LENGTH 20 +#define PLT_FDE_LENGTH 36 +#define PLT_FDE_START_OFFSET 4 + PLT_CIE_LENGTH + 8 +#define PLT_FDE_LEN_OFFSET 4 + PLT_CIE_LENGTH + 12 + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x7c, /* Data alignment factor */ + 8, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */ + DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_386_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */ + DW_CFA_advance_loc + 10, /* DW_CFA_advance_loc: 10 to __PLT__+16 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 11, /* Block length */ + DW_OP_breg4, 4, /* DW_OP_breg4 (esp): 4 */ + DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */ + DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, + DW_OP_lit2, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop +}; + +struct elf_i386_plt_layout +{ + /* The first entry in an absolute procedure linkage table looks like this. */ + const bfd_byte *plt0_entry; + unsigned int plt0_entry_size; + + /* Offsets into plt0_entry that are to be replaced with GOT[1] and GOT[2]. */ + unsigned int plt0_got1_offset; + unsigned int plt0_got2_offset; + + /* Later entries in an absolute procedure linkage table look like this. */ + const bfd_byte *plt_entry; + unsigned int plt_entry_size; + + /* Offsets into plt_entry that are to be replaced with... */ + unsigned int plt_got_offset; /* ... address of this symbol in .got. */ + unsigned int plt_reloc_offset; /* ... offset into relocation table. */ + unsigned int plt_plt_offset; /* ... offset to start of .plt. */ + + /* Offset into plt_entry where the initial value of the GOT entry points. */ + unsigned int plt_lazy_offset; + + /* The first entry in a PIC procedure linkage table looks like this. */ + const bfd_byte *pic_plt0_entry; + + /* Subsequent entries in a PIC procedure linkage table look like this. */ + const bfd_byte *pic_plt_entry; + + /* .eh_frame covering the .plt section. */ + const bfd_byte *eh_frame_plt; + unsigned int eh_frame_plt_size; +}; + +#define GET_PLT_ENTRY_SIZE(abfd) \ + get_elf_i386_backend_data (abfd)->plt->plt_entry_size + +/* These are the standard parameters. */ +static const struct elf_i386_plt_layout elf_i386_plt = + { + elf_i386_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_plt0_entry), /* plt0_entry_size */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + elf_i386_plt_entry, /* plt_entry */ + PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt_got_offset */ + 7, /* plt_reloc_offset */ + 12, /* plt_plt_offset */ + 6, /* plt_lazy_offset */ + elf_i386_pic_plt0_entry, /* pic_plt0_entry */ + elf_i386_pic_plt_entry, /* pic_plt_entry */ + elf_i386_eh_frame_plt, /* eh_frame_plt */ + sizeof (elf_i386_eh_frame_plt), /* eh_frame_plt_size */ + }; + + /* On VxWorks, the .rel.plt.unloaded section has absolute relocations for the PLTResolve stub and then for each PLT entry. */ #define PLTRESOLVE_RELOCS_SHLIB 0 #define PLTRESOLVE_RELOCS 2 #define PLT_NON_JUMP_SLOT_RELOCS 2 +/* Architecture-specific backend data for i386. */ + +struct elf_i386_backend_data +{ + /* Parameters describing PLT generation. */ + const struct elf_i386_plt_layout *plt; + + /* Value used to fill the unused bytes of the first PLT entry. */ + bfd_byte plt0_pad_byte; + + /* True if the target system is VxWorks. */ + int is_vxworks; +}; + +#define get_elf_i386_backend_data(abfd) \ + ((const struct elf_i386_backend_data *) \ + get_elf_backend_data (abfd)->arch_data) + +/* These are the standard parameters. */ +static const struct elf_i386_backend_data elf_i386_arch_bed = + { + &elf_i386_plt, /* plt */ + 0, /* plt0_pad_byte */ + 0, /* is_vxworks */ + }; + +#define elf_backend_arch_data &elf_i386_arch_bed + /* i386 ELF linker hash entry. */ struct elf_i386_link_hash_entry @@ -654,6 +779,7 @@ struct elf_i386_link_hash_table /* Short-cuts to get to dynamic linker sections. */ asection *sdynbss; asection *srelbss; + asection *plt_eh_frame; union { @@ -678,14 +804,14 @@ struct elf_i386_link_hash_table /* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */ asection *srelplt2; - /* True if the target system is VxWorks. */ - int is_vxworks; - /* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */ bfd_vma next_tls_desc_index; - /* Value used to fill the last word of the first plt entry. */ - bfd_byte plt0_pad_byte; + /* The index of the next unused R_386_JUMP_SLOT slot in .rel.plt. */ + bfd_vma next_jump_slot_index; + + /* The index of the next unused R_386_IRELATIVE slot in .rel.plt. */ + bfd_vma next_irelative_index; }; /* Get the i386 ELF linker hash table from a link_info structure. */ @@ -819,14 +945,15 @@ elf_i386_link_hash_table_create (bfd *abfd) ret->sdynbss = NULL; ret->srelbss = NULL; + ret->plt_eh_frame = NULL; ret->tls_ldm_got.refcount = 0; ret->next_tls_desc_index = 0; ret->sgotplt_jump_table_size = 0; ret->sym_cache.abfd = NULL; - ret->is_vxworks = 0; ret->srelplt2 = NULL; - ret->plt0_pad_byte = 0; ret->tls_module_base = NULL; + ret->next_jump_slot_index = 0; + ret->next_irelative_index = 0; ret->loc_hash_table = htab_try_create (1024, elf_i386_local_htab_hash, @@ -881,11 +1008,30 @@ elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info) || (!info->shared && !htab->srelbss)) abort (); - if (htab->is_vxworks + if (get_elf_i386_backend_data (dynobj)->is_vxworks && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2)) return FALSE; + if (!info->no_ld_generated_unwind_info + && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL + && htab->elf.splt != NULL) + { + flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags; + htab->plt_eh_frame + = bfd_make_section_with_flags (dynobj, ".eh_frame", + flags | SEC_READONLY); + if (htab->plt_eh_frame == NULL + || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 2)) + return FALSE; + + htab->plt_eh_frame->size = sizeof (elf_i386_eh_frame_plt); + htab->plt_eh_frame->contents + = bfd_alloc (dynobj, htab->plt_eh_frame->size); + memcpy (htab->plt_eh_frame->contents, elf_i386_eh_frame_plt, + sizeof (elf_i386_eh_frame_plt)); + } + return TRUE; } @@ -956,13 +1102,6 @@ elf_i386_copy_indirect_symbol (struct bfd_link_info *info, _bfd_elf_link_hash_copy_indirect (info, dir, ind); } -typedef union - { - unsigned char c[2]; - uint16_t i; - } -i386_opcode16; - /* Return TRUE if the TLS access code sequence support transition from R_TYPE. */ @@ -1133,8 +1272,8 @@ elf_i386_check_tls_transition (bfd *abfd, asection *sec, if (offset + 2 <= sec->size) { /* Make sure that it's a call *x@tlsdesc(%rax). */ - static i386_opcode16 call = { { 0xff, 0x10 } }; - return bfd_get_16 (abfd, contents + offset) == call.i; + static const unsigned char call[] = { 0xff, 0x10 }; + return memcmp (contents + offset, call, 2) == 0; } return FALSE; @@ -1375,7 +1514,9 @@ elf_i386_check_relocs (bfd *abfd, case R_386_PLT32: case R_386_GOT32: case R_386_GOTOFF: - if (!_bfd_elf_create_ifunc_sections (abfd, info)) + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) return FALSE; break; } @@ -1452,7 +1593,7 @@ elf_i386_check_relocs (bfd *abfd, if (! elf_i386_tls_transition (info, abfd, sec, NULL, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, - rel, rel_end, h, r_symndx)) + rel, rel_end, h, r_symndx)) return FALSE; switch (r_type) @@ -1850,7 +1991,7 @@ elf_i386_gc_sweep_hook (bfd *abfd, if (! elf_i386_tls_transition (info, abfd, sec, NULL, symtab_hdr, sym_hashes, &r_type, GOT_UNKNOWN, - rel, relend, h, r_symndx)) + rel, relend, h, r_symndx)) return FALSE; switch (r_type) @@ -2015,7 +2156,8 @@ elf_i386_adjust_dynamic_symbol (struct bfd_link_info *info, we can keep the dynamic relocs and avoid the copy reloc. This doesn't work on VxWorks, where we can not have dynamic relocations (other than copy and jump slot relocations) in an executable. */ - if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks) + if (ELIMINATE_COPY_RELOCS + && !get_elf_i386_backend_data (info->output_bfd)->is_vxworks) { struct elf_i386_link_hash_entry * eh; struct elf_dyn_relocs *p; @@ -2076,15 +2218,11 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) struct elf_i386_link_hash_table *htab; struct elf_i386_link_hash_entry *eh; struct elf_dyn_relocs *p; + unsigned plt_entry_size; if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (h->root.type == bfd_link_hash_warning) - /* When warning symbols are created, they **replace** the "real" - entry in the hash table, thus we never get to see the real - symbol in a hash traversal. So look at it now. */ - h = (struct elf_link_hash_entry *) h->root.u.i.link; eh = (struct elf_i386_link_hash_entry *) h; info = (struct bfd_link_info *) inf; @@ -2092,13 +2230,14 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) if (htab == NULL) return FALSE; + plt_entry_size = GET_PLT_ENTRY_SIZE (info->output_bfd); + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ if (h->type == STT_GNU_IFUNC && h->def_regular) - return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, - &eh->dyn_relocs, - PLT_ENTRY_SIZE, 4); + return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &eh->dyn_relocs, + plt_entry_size, 4); else if (htab->elf.dynamic_sections_created && h->plt.refcount > 0) { @@ -2119,7 +2258,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* If this is the first .plt entry, make room for the special first entry. */ if (s->size == 0) - s->size += PLT_ENTRY_SIZE; + s->size += plt_entry_size; h->plt.offset = s->size; @@ -2136,7 +2275,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } /* Make room for this entry. */ - s->size += PLT_ENTRY_SIZE; + s->size += plt_entry_size; /* We also need to make an entry in the .got.plt section, which will be placed in the .got section by the linker script. */ @@ -2144,9 +2283,10 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* We also need to make an entry in the .rel.plt section. */ htab->elf.srelplt->size += sizeof (Elf32_External_Rel); - htab->next_tls_desc_index++; + htab->elf.srelplt->reloc_count++; - if (htab->is_vxworks && !info->shared) + if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks + && !info->shared) { /* VxWorks has a second set of relocations for each PLT entry in executables. They go in a separate relocation section, @@ -2156,7 +2296,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 4 and an R_386_32 relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ - if (h->plt.offset == PLT_ENTRY_SIZE) + if (h->plt.offset == plt_entry_size) htab->srelplt2->size += (sizeof (Elf32_External_Rel) * 2); /* There are two extra relocations for each subsequent PLT entry: @@ -2276,7 +2416,7 @@ elf_i386_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) } } - if (htab->is_vxworks) + if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks) { struct elf_dyn_relocs **pp; for (pp = &eh->dyn_relocs; (p = *pp) != NULL; ) @@ -2380,8 +2520,9 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) struct elf_i386_link_hash_entry *eh; struct elf_dyn_relocs *p; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Skip local IFUNC symbols. */ + if (h->forced_local && h->type == STT_GNU_IFUNC) + return TRUE; eh = (struct elf_i386_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) @@ -2394,6 +2535,11 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) info->flags |= DF_TEXTREL; + if (info->warn_shared_textrel && info->shared) + info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' in readonly section `%A'.\n"), + p->sec->owner, h->root.root.string, + p->sec); + /* Not an error, just cut short the traversal. */ return FALSE; } @@ -2404,8 +2550,7 @@ elf_i386_readonly_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Set the sizes of the dynamic sections. */ static bfd_boolean -elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, - struct bfd_link_info *info) +elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { struct elf_i386_link_hash_table *htab; bfd *dynobj; @@ -2465,7 +2610,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, linker script /DISCARD/, so we'll be discarding the relocs too. */ } - else if (htab->is_vxworks + else if (get_elf_i386_backend_data (output_bfd)->is_vxworks && strcmp (p->sec->output_section->name, ".tls_vars") == 0) { @@ -2476,8 +2621,14 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { srel = elf_section_data (p->sec)->sreloc; srel->size += p->count * sizeof (Elf32_External_Rel); - if ((p->sec->output_section->flags & SEC_READONLY) != 0) - info->flags |= DF_TEXTREL; + if ((p->sec->output_section->flags & SEC_READONLY) != 0 + && (info->flags & DF_TEXTREL) == 0) + { + info->flags |= DF_TEXTREL; + if (info->warn_shared_textrel && info->shared) + info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'.\n"), + p->sec->owner, p->sec); + } } } } @@ -2557,9 +2708,19 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, incremented. However, when we reserve space for TLS descriptors, it's not incremented, so in order to compute the space reserved for them, it suffices to multiply the reloc count by the jump - slot size. */ + slot size. + + PR ld/13302: We start next_irelative_index at the end of .rela.plt + so that R_386_IRELATIVE entries come last. */ if (htab->elf.srelplt) - htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; + { + htab->next_tls_desc_index = htab->elf.srelplt->reloc_count; + htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4; + htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; + } + else if (htab->elf.irelplt) + htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; + if (htab->elf.sgotplt) { @@ -2657,6 +2818,13 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return FALSE; } + if (htab->plt_eh_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) == 0) + bfd_put_32 (dynobj, htab->elf.splt->size, + htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the @@ -2701,7 +2869,7 @@ elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return FALSE; } } - if (htab->is_vxworks + if (get_elf_i386_backend_data (output_bfd)->is_vxworks && !elf_vxworks_add_dynamic_entries (output_bfd, info)) return FALSE; } @@ -2864,6 +3032,7 @@ elf_i386_relocate_section (bfd *output_bfd, Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; bfd_boolean is_vxworks_tls; + unsigned plt_entry_size; BFD_ASSERT (is_i386_elf (input_bfd)); @@ -2876,12 +3045,15 @@ elf_i386_relocate_section (bfd *output_bfd, local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd); /* We have to handle relocations in vxworks .tls_vars sections specially, because the dynamic loader is 'weird'. */ - is_vxworks_tls = (htab->is_vxworks && info->shared + is_vxworks_tls = (get_elf_i386_backend_data (output_bfd)->is_vxworks + && info->shared && !strcmp (input_section->output_section->name, ".tls_vars")); elf_i386_set_tls_module_base (info); + plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd); + rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) @@ -3009,7 +3181,7 @@ elf_i386_relocate_section (bfd *output_bfd, if (h == NULL) abort (); - /* Set STT_GNU_IFUNC symbol value. */ + /* Set STT_GNU_IFUNC symbol value. */ h->root.u.def.value = sym->st_value; h->root.u.def.section = sec; } @@ -3078,13 +3250,14 @@ elf_i386_relocate_section (bfd *output_bfd, case R_386_32: /* Generate dynamic relcoation only when there is a - non-GOF reference in a shared object. */ + non-GOT reference in a shared object. */ if (info->shared && h->non_got_ref) { Elf_Internal_Rela outrel; bfd_byte *loc; asection *sreloc; bfd_vma offset; + bfd_boolean relocate; /* Need a dynamic relocation to get the real function adddress. */ @@ -3105,15 +3278,14 @@ elf_i386_relocate_section (bfd *output_bfd, || info->executable) { /* This symbol is resolved locally. */ - outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); - bfd_put_32 (output_bfd, - (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset), - contents + offset); + outrel.r_info = ELF32_R_INFO (0, R_386_RELATIVE); + relocate = TRUE; } else - outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + { + outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); + relocate = FALSE; + } sreloc = htab->elf.irelifunc; loc = sreloc->contents; @@ -3126,7 +3298,8 @@ elf_i386_relocate_section (bfd *output_bfd, we need to include the symbol value so that it becomes an addend for the dynamic reloc. For an internal symbol, we have updated addend. */ - continue; + if (! relocate) + continue; } /* FALLTHROUGH */ case R_386_PC32: @@ -3148,13 +3321,13 @@ elf_i386_relocate_section (bfd *output_bfd, if (htab->elf.splt != NULL) { - plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; + plt_index = h->plt.offset / plt_entry_size - 1; off = (plt_index + 3) * 4; base_got = htab->elf.sgotplt; } else { - plt_index = h->plt.offset / PLT_ENTRY_SIZE; + plt_index = h->plt.offset / plt_entry_size; off = plt_index * 4; base_got = htab->elf.igotplt; } @@ -3451,7 +3624,11 @@ elf_i386_relocate_section (bfd *output_bfd, sreloc = elf_section_data (input_section)->sreloc; - BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL); + if (sreloc == NULL || sreloc->contents == NULL) + { + r = bfd_reloc_notsupported; + goto check_relocation_error; + } loc = sreloc->contents; loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel); @@ -3769,7 +3946,7 @@ elf_i386_relocate_section (bfd *output_bfd, relocation - elf_i386_dtpoff_base (info), htab->elf.sgot->contents + off); else if (dr_type == R_386_TLS_TPOFF32 && indx == 0) - bfd_put_32 (output_bfd, + bfd_put_32 (output_bfd, elf_i386_dtpoff_base (info) - relocation, htab->elf.sgot->contents + off); else if (dr_type != R_386_TLS_DESC) @@ -4025,7 +4202,7 @@ elf_i386_relocate_section (bfd *output_bfd, break; case R_386_TLS_LDO_32: - if (info->shared || (input_section->flags & SEC_CODE) == 0) + if (!info->executable || (input_section->flags & SEC_CODE) == 0) relocation -= elf_i386_dtpoff_base (info); else /* When converting LDO to LE, we must negate. */ @@ -4079,7 +4256,9 @@ elf_i386_relocate_section (bfd *output_bfd, not process them. */ if (unresolved_reloc && !((input_section->flags & SEC_DEBUGGING) != 0 - && h->def_dynamic)) + && h->def_dynamic) + && _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset) != (bfd_vma) -1) { (*_bfd_error_handler) (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), @@ -4096,6 +4275,7 @@ do_relocation: contents, rel->r_offset, relocation, 0); +check_relocation_error: if (r != bfd_reloc_ok) { const char *name; @@ -4145,11 +4325,16 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, Elf_Internal_Sym *sym) { struct elf_i386_link_hash_table *htab; + unsigned plt_entry_size; + const struct elf_i386_backend_data *abed; htab = elf_i386_hash_table (info); if (htab == NULL) return FALSE; + abed = get_elf_i386_backend_data (output_bfd); + plt_entry_size = GET_PLT_ENTRY_SIZE (output_bfd); + if (h->plt.offset != (bfd_vma) -1) { bfd_vma plt_index; @@ -4183,7 +4368,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, || plt == NULL || gotplt == NULL || relplt == NULL) - abort (); + return FALSE; /* Get the index in the procedure linkage table which corresponds to this symbol. This is the index of this symbol @@ -4198,27 +4383,28 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, if (plt == htab->elf.splt) { - plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; - got_offset = (plt_index + 3) * 4; + got_offset = h->plt.offset / plt_entry_size - 1; + got_offset = (got_offset + 3) * 4; } else { - plt_index = h->plt.offset / PLT_ENTRY_SIZE; - got_offset = plt_index * 4; + got_offset = h->plt.offset / plt_entry_size; + got_offset = got_offset * 4; } /* Fill in the entry in the procedure linkage table. */ if (! info->shared) { - memcpy (plt->contents + h->plt.offset, elf_i386_plt_entry, - PLT_ENTRY_SIZE); + memcpy (plt->contents + h->plt.offset, abed->plt->plt_entry, + abed->plt->plt_entry_size); bfd_put_32 (output_bfd, (gotplt->output_section->vma + gotplt->output_offset + got_offset), - plt->contents + h->plt.offset + 2); + plt->contents + h->plt.offset + + abed->plt->plt_got_offset); - if (htab->is_vxworks) + if (abed->is_vxworks) { int s, k, reloc_index; @@ -4226,7 +4412,8 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, for this PLT entry. */ /* S: Current slot number (zero-based). */ - s = (h->plt.offset - PLT_ENTRY_SIZE) / PLT_ENTRY_SIZE; + s = ((h->plt.offset - abed->plt->plt_entry_size) + / abed->plt->plt_entry_size); /* K: Number of relocations for PLTResolve. */ if (info->shared) k = PLTRESOLVE_RELOCS_SHLIB; @@ -4256,19 +4443,11 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, } else { - memcpy (plt->contents + h->plt.offset, elf_i386_pic_plt_entry, - PLT_ENTRY_SIZE); + memcpy (plt->contents + h->plt.offset, abed->plt->pic_plt_entry, + abed->plt->plt_entry_size); bfd_put_32 (output_bfd, got_offset, - plt->contents + h->plt.offset + 2); - } - - /* Don't fill PLT entry for static executables. */ - if (plt == htab->elf.splt) - { - bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), - plt->contents + h->plt.offset + 7); - bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), - plt->contents + h->plt.offset + 12); + plt->contents + h->plt.offset + + abed->plt->plt_got_offset); } /* Fill in the entry in the global offset table. */ @@ -4276,7 +4455,7 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, (plt->output_section->vma + plt->output_offset + h->plt.offset - + 6), + + abed->plt->plt_lazy_offset), gotplt->contents + got_offset); /* Fill in the entry in the .rel.plt section. */ @@ -4293,17 +4472,34 @@ elf_i386_finish_dynamic_symbol (bfd *output_bfd, R_386_IRELATIVE instead of R_386_JUMP_SLOT. Store addend in the .got.plt section. */ bfd_put_32 (output_bfd, - (h->root.u.def.value + (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset), gotplt->contents + got_offset); rel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE); + /* R_386_IRELATIVE comes last. */ + plt_index = htab->next_irelative_index--; } else - rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); + { + rel.r_info = ELF32_R_INFO (h->dynindx, R_386_JUMP_SLOT); + plt_index = htab->next_jump_slot_index++; + } loc = relplt->contents + plt_index * sizeof (Elf32_External_Rel); bfd_elf32_swap_reloc_out (output_bfd, &rel, loc); + /* Don't fill PLT entry for static executables. */ + if (plt == htab->elf.splt) + { + bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rel), + plt->contents + h->plt.offset + + abed->plt->plt_reloc_offset); + bfd_put_32 (output_bfd, - (h->plt.offset + + abed->plt->plt_plt_offset + 4), + plt->contents + h->plt.offset + + abed->plt->plt_plt_offset); + } + if (!h->def_regular) { /* Mark the symbol as undefined, rather than as defined in @@ -4417,7 +4613,8 @@ do_glob_dat: is relative to the ".got" section. */ if (sym != NULL && (strcmp (h->root.root.string, "_DYNAMIC") == 0 - || (!htab->is_vxworks && h == htab->elf.hgot))) + || (!abed->is_vxworks + && h == htab->elf.hgot))) sym->st_shndx = SHN_ABS; return TRUE; @@ -4432,7 +4629,7 @@ elf_i386_finish_local_dynamic_symbol (void **slot, void *inf) struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) *slot; struct bfd_link_info *info - = (struct bfd_link_info *) inf; + = (struct bfd_link_info *) inf; return elf_i386_finish_dynamic_symbol (info->output_bfd, info, h, NULL); @@ -4466,6 +4663,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, struct elf_i386_link_hash_table *htab; bfd *dynobj; asection *sdyn; + const struct elf_i386_backend_data *abed; htab = elf_i386_hash_table (info); if (htab == NULL) @@ -4473,6 +4671,7 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, dynobj = htab->elf.dynobj; sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + abed = get_elf_i386_backend_data (output_bfd); if (htab->elf.dynamic_sections_created) { @@ -4493,8 +4692,8 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, switch (dyn.d_tag) { default: - if (htab->is_vxworks - && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) + if (abed->is_vxworks + && elf_vxworks_finish_dynamic_entry (output_bfd, &dyn)) break; continue; @@ -4547,31 +4746,33 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, { if (info->shared) { - memcpy (htab->elf.splt->contents, elf_i386_pic_plt0_entry, - sizeof (elf_i386_pic_plt0_entry)); - memset (htab->elf.splt->contents + sizeof (elf_i386_pic_plt0_entry), - htab->plt0_pad_byte, - PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry)); + memcpy (htab->elf.splt->contents, abed->plt->pic_plt0_entry, + abed->plt->plt0_entry_size); + memset (htab->elf.splt->contents + abed->plt->plt0_entry_size, + abed->plt0_pad_byte, + abed->plt->plt_entry_size - abed->plt->plt0_entry_size); } else { - memcpy (htab->elf.splt->contents, elf_i386_plt0_entry, - sizeof(elf_i386_plt0_entry)); - memset (htab->elf.splt->contents + sizeof (elf_i386_plt0_entry), - htab->plt0_pad_byte, - PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry)); + memcpy (htab->elf.splt->contents, abed->plt->plt0_entry, + abed->plt->plt0_entry_size); + memset (htab->elf.splt->contents + abed->plt->plt0_entry_size, + abed->plt0_pad_byte, + abed->plt->plt_entry_size - abed->plt->plt0_entry_size); bfd_put_32 (output_bfd, (htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset + 4), - htab->elf.splt->contents + 2); + htab->elf.splt->contents + + abed->plt->plt0_got1_offset); bfd_put_32 (output_bfd, (htab->elf.sgotplt->output_section->vma + htab->elf.sgotplt->output_offset + 8), - htab->elf.splt->contents + 8); + htab->elf.splt->contents + + abed->plt->plt0_got2_offset); - if (htab->is_vxworks) + if (abed->is_vxworks) { Elf_Internal_Rela rel; @@ -4580,14 +4781,14 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, the PLT directly. */ rel.r_offset = (htab->elf.splt->output_section->vma + htab->elf.splt->output_offset - + 2); + + abed->plt->plt0_got1_offset); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); bfd_elf32_swap_reloc_out (output_bfd, &rel, htab->srelplt2->contents); /* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */ rel.r_offset = (htab->elf.splt->output_section->vma + htab->elf.splt->output_offset - + 8); + + abed->plt->plt0_got2_offset); rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32); bfd_elf32_swap_reloc_out (output_bfd, &rel, htab->srelplt2->contents + @@ -4601,9 +4802,10 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, ->this_hdr.sh_entsize = 4; /* Correct the .rel.plt.unloaded relocations. */ - if (htab->is_vxworks && !info->shared) + if (abed->is_vxworks && !info->shared) { - int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1; + int num_plts = (htab->elf.splt->size + / abed->plt->plt_entry_size) - 1; unsigned char *p; p = htab->srelplt2->contents; @@ -4652,6 +4854,33 @@ elf_i386_finish_dynamic_sections (bfd *output_bfd, elf_section_data (htab->elf.sgotplt->output_section)->this_hdr.sh_entsize = 4; } + /* Adjust .eh_frame for .plt section. */ + if (htab->plt_eh_frame != NULL) + { + if (htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 + && htab->elf.splt->output_section != NULL + && htab->plt_eh_frame->output_section != NULL) + { + bfd_vma plt_start = htab->elf.splt->output_section->vma; + bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma + + htab->plt_eh_frame->output_offset + + PLT_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, + htab->plt_eh_frame->contents + + PLT_FDE_START_OFFSET); + } + if (htab->plt_eh_frame->sec_info_type + == ELF_INFO_TYPE_EH_FRAME) + { + if (! _bfd_elf_write_section_eh_frame (output_bfd, info, + htab->plt_eh_frame, + htab->plt_eh_frame->contents)) + return FALSE; + } + } + if (htab->elf.sgot && htab->elf.sgot->size > 0) elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = 4; @@ -4670,7 +4899,7 @@ static bfd_vma elf_i386_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel ATTRIBUTE_UNUSED) { - return plt->vma + (i + 1) * PLT_ENTRY_SIZE; + return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner); } /* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */ @@ -4699,8 +4928,9 @@ elf_i386_add_symbol_hook (bfd * abfd, bfd_vma * valp ATTRIBUTE_UNUSED) { if ((abfd->flags & DYNAMIC) == 0 - && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) - elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; + && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) + elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; return TRUE; } @@ -4718,6 +4948,7 @@ elf_i386_add_symbol_hook (bfd * abfd, #define elf_backend_plt_readonly 1 #define elf_backend_want_plt_sym 0 #define elf_backend_got_header_size 12 +#define elf_backend_plt_alignment 4 /* Support RELA for objdump of prelink objects. */ #define elf_info_to_howto elf_i386_info_to_howto_rel @@ -4818,39 +5049,192 @@ elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info) #include "elf32-target.h" -/* VxWorks support. */ +/* Native Client support. */ #undef TARGET_LITTLE_SYM -#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec +#define TARGET_LITTLE_SYM bfd_elf32_i386_nacl_vec #undef TARGET_LITTLE_NAME -#define TARGET_LITTLE_NAME "elf32-i386-vxworks" +#define TARGET_LITTLE_NAME "elf32-i386-nacl" +#undef elf32_bed +#define elf32_bed elf32_i386_nacl_bed + +#undef ELF_MAXPAGESIZE +#define ELF_MAXPAGESIZE 0x10000 + +/* Restore defaults. */ #undef ELF_OSABI +#undef elf_backend_want_plt_sym +#define elf_backend_want_plt_sym 0 +#undef elf_backend_post_process_headers +#define elf_backend_post_process_headers _bfd_elf_set_osabi +#undef elf_backend_static_tls_alignment -/* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */ +/* NaCl uses substantially different PLT entries for the same effects. */ -static struct bfd_link_hash_table * -elf_i386_vxworks_link_hash_table_create (bfd *abfd) -{ - struct bfd_link_hash_table *ret; - struct elf_i386_link_hash_table *htab; +#undef elf_backend_plt_alignment +#define elf_backend_plt_alignment 5 +#define NACL_PLT_ENTRY_SIZE 64 +#define NACLMASK 0xe0 /* 32-byte alignment mask. */ - ret = elf_i386_link_hash_table_create (abfd); - if (ret) - { - htab = (struct elf_i386_link_hash_table *) ret; - htab->is_vxworks = 1; - htab->plt0_pad_byte = 0x90; - } +static const bfd_byte elf_i386_nacl_plt0_entry[] = + { + 0xff, 0x35, /* pushl contents of address */ + 0, 0, 0, 0, /* replaced with address of .got + 4. */ + 0x8b, 0x0d, /* movl contents of address, %ecx */ + 0, 0, 0, 0, /* replaced with address of .got + 8. */ + 0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */ + 0xff, 0xe1 /* jmp *%ecx */ + }; + +static const bfd_byte elf_i386_nacl_plt_entry[NACL_PLT_ENTRY_SIZE] = + { + 0x8b, 0x0d, /* movl contents of address, %ecx */ + 0, 0, 0, 0, /* replaced with GOT slot address. */ + 0x83, 0xe1, NACLMASK, /* andl $NACLMASK, %ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + + /* Lazy GOT entries point here (32-byte aligned). */ + 0x68, /* pushl immediate */ + 0, 0, 0, 0, /* replaced with reloc offset. */ + 0xe9, /* jmp relative */ + 0, 0, 0, 0, /* replaced with offset to .plt. */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90 + }; + +static const bfd_byte +elf_i386_nacl_pic_plt0_entry[sizeof (elf_i386_nacl_plt0_entry)] = + { + 0xff, 0x73, 0x04, /* pushl 4(%ebx) */ + 0x8b, 0x4b, 0x08, /* mov 0x8(%ebx), %ecx */ + 0x83, 0xe1, 0xe0, /* and $NACLMASK, %ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + 0x90 /* nop */ + }; + +static const bfd_byte elf_i386_nacl_pic_plt_entry[NACL_PLT_ENTRY_SIZE] = + { + 0x8b, 0x8b, /* movl offset(%ebx), %ecx */ + 0, 0, 0, 0, /* replaced with offset of this symbol in .got. */ + 0x83, 0xe1, 0xe0, /* andl $NACLMASK, %ecx */ + 0xff, 0xe1, /* jmp *%ecx */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + + /* Lazy GOT entries point here (32-byte aligned). */ + 0x68, /* pushl immediate */ + 0, 0, 0, 0, /* replaced with offset into relocation table. */ + 0xe9, /* jmp relative */ + 0, 0, 0, 0, /* replaced with offset to start of .plt. */ + + /* Pad to the next 32-byte boundary with nop instructions. */ + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, + 0x90, 0x90 + }; + +static const bfd_byte elf_i386_nacl_eh_frame_plt[] = + { +#if (PLT_CIE_LENGTH != 20 \ + || PLT_FDE_LENGTH != 36 \ + || PLT_FDE_START_OFFSET != 4 + PLT_CIE_LENGTH + 8 \ + || PLT_FDE_LEN_OFFSET != 4 + PLT_CIE_LENGTH + 12) +# error "Need elf_i386_backend_data parameters for eh_frame_plt offsets!" +#endif + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x7c, /* Data alignment factor: -4 */ + 8, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 4, 4, /* DW_CFA_def_cfa: r4 (esp) ofs 4 */ + DW_CFA_offset + 8, 1, /* DW_CFA_offset: r8 (eip) at cfa-4 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_386_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 8, /* DW_CFA_def_cfa_offset: 8 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 12, /* DW_CFA_def_cfa_offset: 12 */ + DW_CFA_advance_loc + 58, /* DW_CFA_advance_loc: 58 to __PLT__+64 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 13, /* Block length */ + DW_OP_breg4, 4, /* DW_OP_breg4 (esp): 4 */ + DW_OP_breg8, 0, /* DW_OP_breg8 (eip): 0 */ + DW_OP_const1u, 63, DW_OP_and, DW_OP_const1u, 37, DW_OP_ge, + DW_OP_lit2, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop + }; + +static const struct elf_i386_plt_layout elf_i386_nacl_plt = + { + elf_i386_nacl_plt0_entry, /* plt0_entry */ + sizeof (elf_i386_nacl_plt0_entry), /* plt0_entry_size */ + 2, /* plt0_got1_offset */ + 8, /* plt0_got2_offset */ + elf_i386_nacl_plt_entry, /* plt_entry */ + NACL_PLT_ENTRY_SIZE, /* plt_entry_size */ + 2, /* plt_got_offset */ + 33, /* plt_reloc_offset */ + 38, /* plt_plt_offset */ + 32, /* plt_lazy_offset */ + elf_i386_nacl_pic_plt0_entry, /* pic_plt0_entry */ + elf_i386_nacl_pic_plt_entry, /* pic_plt_entry */ + elf_i386_nacl_eh_frame_plt, /* eh_frame_plt */ + sizeof (elf_i386_nacl_eh_frame_plt),/* eh_frame_plt_size */ + }; + +static const struct elf_i386_backend_data elf_i386_nacl_arch_bed = + { + &elf_i386_nacl_plt, /* plt */ + 0x90, /* plt0_pad_byte: nop insn */ + 0, /* is_vxworks */ + }; - return ret; -} +#undef elf_backend_arch_data +#define elf_backend_arch_data &elf_i386_nacl_arch_bed + +#include "elf32-target.h" + +/* VxWorks support. */ + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec +#undef TARGET_LITTLE_NAME +#define TARGET_LITTLE_NAME "elf32-i386-vxworks" +#undef ELF_OSABI +#undef elf_backend_plt_alignment +#define elf_backend_plt_alignment 4 + +static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed = + { + &elf_i386_plt, /* plt */ + 0x90, /* plt0_pad_byte */ + 1, /* is_vxworks */ + }; +#undef elf_backend_arch_data +#define elf_backend_arch_data &elf_i386_vxworks_arch_bed #undef elf_backend_relocs_compatible #undef elf_backend_post_process_headers -#undef bfd_elf32_bfd_link_hash_table_create -#define bfd_elf32_bfd_link_hash_table_create \ - elf_i386_vxworks_link_hash_table_create #undef elf_backend_add_symbol_hook #define elf_backend_add_symbol_hook \ elf_vxworks_add_symbol_hook diff --git a/contrib/gdb-7/bfd/elf64-x86-64.c b/contrib/gdb-7/bfd/elf64-x86-64.c index 927b3ed4a5..fe0db0e8dc 100644 --- a/contrib/gdb-7/bfd/elf64-x86-64.c +++ b/contrib/gdb-7/bfd/elf64-x86-64.c @@ -1,6 +1,7 @@ /* X86-64 specific support for ELF Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011, 2012 + Free Software Foundation, Inc. Contributed by Jan Hubicka . This file is part of BFD, the Binary File Descriptor library. @@ -28,9 +29,16 @@ #include "bfd_stdint.h" #include "objalloc.h" #include "hashtab.h" +#include "dwarf2.h" +#include "libiberty.h" #include "elf/x86-64.h" +#ifdef CORE_HEADER +#include +#include CORE_HEADER +#endif + /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */ #define MINUS_ONE (~ (bfd_vma) 0) @@ -156,6 +164,9 @@ static reloc_howto_type x86_64_elf_howto_table[] = HOWTO(R_X86_64_IRELATIVE, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, bfd_elf_generic_reloc, "R_X86_64_IRELATIVE", FALSE, MINUS_ONE, MINUS_ONE, FALSE), + HOWTO(R_X86_64_RELATIVE64, 0, 4, 64, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_RELATIVE64", FALSE, MINUS_ONE, + MINUS_ONE, FALSE), /* We have a gap in the reloc numbers here. R_X86_64_standard counts the number up to this point, and @@ -171,7 +182,12 @@ static reloc_howto_type x86_64_elf_howto_table[] = /* GNU extension to record C++ vtable member usage. */ HOWTO (R_X86_64_GNU_VTENTRY, 0, 4, 0, FALSE, 0, complain_overflow_dont, _bfd_elf_rel_vtable_reloc_fn, "R_X86_64_GNU_VTENTRY", FALSE, 0, 0, - FALSE) + FALSE), + +/* Use complain_overflow_bitfield on R_X86_64_32 for x32. */ + HOWTO(R_X86_64_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield, + bfd_elf_generic_reloc, "R_X86_64_32", FALSE, 0xffffffff, 0xffffffff, + FALSE) }; #define IS_X86_64_PCREL_TYPE(TYPE) \ @@ -234,8 +250,15 @@ elf_x86_64_rtype_to_howto (bfd *abfd, unsigned r_type) { unsigned i; - if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT - || r_type >= (unsigned int) R_X86_64_max) + if (r_type == (unsigned int) R_X86_64_32) + { + if (ABI_64_P (abfd)) + i = r_type; + else + i = ARRAY_SIZE (x86_64_elf_howto_table) - 1; + } + else if (r_type < (unsigned int) R_X86_64_GNU_VTINHERIT + || r_type >= (unsigned int) R_X86_64_max) { if (r_type >= (unsigned int) R_X86_64_standard) { @@ -269,15 +292,21 @@ elf_x86_64_reloc_type_lookup (bfd *abfd, } static reloc_howto_type * -elf_x86_64_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, +elf_x86_64_reloc_name_lookup (bfd *abfd, const char *r_name) { unsigned int i; - for (i = 0; - i < (sizeof (x86_64_elf_howto_table) - / sizeof (x86_64_elf_howto_table[0])); - i++) + if (!ABI_64_P (abfd) && strcasecmp (r_name, "R_X86_64_32") == 0) + { + /* Get x32 R_X86_64_32. */ + reloc_howto_type *reloc + = &x86_64_elf_howto_table[ARRAY_SIZE (x86_64_elf_howto_table) - 1]; + BFD_ASSERT (reloc->type == (unsigned int) R_X86_64_32); + return reloc; + } + + for (i = 0; i < ARRAY_SIZE (x86_64_elf_howto_table); i++) if (x86_64_elf_howto_table[i].name != NULL && strcasecmp (x86_64_elf_howto_table[i].name, r_name) == 0) return &x86_64_elf_howto_table[i]; @@ -310,6 +339,19 @@ elf_x86_64_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) default: return FALSE; + case 296: /* sizeof(istruct elf_prstatus) on Linux/x32 */ + /* pr_cursig */ + elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); + + /* pr_pid */ + elf_tdata (abfd)->core_lwpid = bfd_get_32 (abfd, note->descdata + 24); + + /* pr_reg */ + offset = 72; + size = 216; + + break; + case 336: /* sizeof(istruct elf_prstatus) on Linux/x86_64 */ /* pr_cursig */ elf_tdata (abfd)->core_signal @@ -339,6 +381,15 @@ elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) default: return FALSE; + case 124: /* sizeof(struct elf_prpsinfo) on Linux/x32 */ + elf_tdata (abfd)->core_pid + = bfd_get_32 (abfd, note->descdata + 12); + elf_tdata (abfd)->core_program + = _bfd_elfcore_strndup (abfd, note->descdata + 28, 16); + elf_tdata (abfd)->core_command + = _bfd_elfcore_strndup (abfd, note->descdata + 44, 80); + break; + case 136: /* sizeof(struct elf_prpsinfo) on Linux/x86_64 */ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); @@ -362,6 +413,94 @@ elf_x86_64_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) return TRUE; } + +#ifdef CORE_HEADER +static char * +elf_x86_64_write_core_note (bfd *abfd, char *buf, int *bufsiz, + int note_type, ...) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + va_list ap; + const char *fname, *psargs; + long pid; + int cursig; + const void *gregs; + + switch (note_type) + { + default: + return NULL; + + case NT_PRPSINFO: + va_start (ap, note_type); + fname = va_arg (ap, const char *); + psargs = va_arg (ap, const char *); + va_end (ap); + + if (bed->s->elfclass == ELFCLASS32) + { + prpsinfo32_t data; + memset (&data, 0, sizeof (data)); + strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); + strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); + return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, + &data, sizeof (data)); + } + else + { + prpsinfo_t data; + memset (&data, 0, sizeof (data)); + strncpy (data.pr_fname, fname, sizeof (data.pr_fname)); + strncpy (data.pr_psargs, psargs, sizeof (data.pr_psargs)); + return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, + &data, sizeof (data)); + } + /* NOTREACHED */ + + case NT_PRSTATUS: + va_start (ap, note_type); + pid = va_arg (ap, long); + cursig = va_arg (ap, int); + gregs = va_arg (ap, const void *); + va_end (ap); + + if (bed->s->elfclass == ELFCLASS32) + { + if (bed->elf_machine_code == EM_X86_64) + { + prstatusx32_t prstat; + memset (&prstat, 0, sizeof (prstat)); + prstat.pr_pid = pid; + prstat.pr_cursig = cursig; + memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg)); + return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, + &prstat, sizeof (prstat)); + } + else + { + prstatus32_t prstat; + memset (&prstat, 0, sizeof (prstat)); + prstat.pr_pid = pid; + prstat.pr_cursig = cursig; + memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg)); + return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, + &prstat, sizeof (prstat)); + } + } + else + { + prstatus_t prstat; + memset (&prstat, 0, sizeof (prstat)); + prstat.pr_pid = pid; + prstat.pr_cursig = cursig; + memcpy (&prstat.pr_reg, gregs, sizeof (prstat.pr_reg)); + return elfcore_write_note (abfd, buf, bufsiz, "CORE", note_type, + &prstat, sizeof (prstat)); + } + } + /* NOTREACHED */ +} +#endif /* Functions for the x86-64 ELF linker. */ @@ -407,6 +546,45 @@ static const bfd_byte elf_x86_64_plt_entry[PLT_ENTRY_SIZE] = 0, 0, 0, 0 /* replaced with offset to start of .plt0. */ }; +/* .eh_frame covering the .plt section. */ + +static const bfd_byte elf_x86_64_eh_frame_plt[] = +{ +#define PLT_CIE_LENGTH 20 +#define PLT_FDE_LENGTH 36 +#define PLT_FDE_START_OFFSET 4 + PLT_CIE_LENGTH + 8 +#define PLT_FDE_LEN_OFFSET 4 + PLT_CIE_LENGTH + 12 + PLT_CIE_LENGTH, 0, 0, 0, /* CIE length */ + 0, 0, 0, 0, /* CIE ID */ + 1, /* CIE version */ + 'z', 'R', 0, /* Augmentation string */ + 1, /* Code alignment factor */ + 0x78, /* Data alignment factor */ + 16, /* Return address column */ + 1, /* Augmentation size */ + DW_EH_PE_pcrel | DW_EH_PE_sdata4, /* FDE encoding */ + DW_CFA_def_cfa, 7, 8, /* DW_CFA_def_cfa: r7 (rsp) ofs 8 */ + DW_CFA_offset + 16, 1, /* DW_CFA_offset: r16 (rip) at cfa-8 */ + DW_CFA_nop, DW_CFA_nop, + + PLT_FDE_LENGTH, 0, 0, 0, /* FDE length */ + PLT_CIE_LENGTH + 8, 0, 0, 0, /* CIE pointer */ + 0, 0, 0, 0, /* R_X86_64_PC32 .plt goes here */ + 0, 0, 0, 0, /* .plt size goes here */ + 0, /* Augmentation size */ + DW_CFA_def_cfa_offset, 16, /* DW_CFA_def_cfa_offset: 16 */ + DW_CFA_advance_loc + 6, /* DW_CFA_advance_loc: 6 to __PLT__+6 */ + DW_CFA_def_cfa_offset, 24, /* DW_CFA_def_cfa_offset: 24 */ + DW_CFA_advance_loc + 10, /* DW_CFA_advance_loc: 10 to __PLT__+16 */ + DW_CFA_def_cfa_expression, /* DW_CFA_def_cfa_expression */ + 11, /* Block length */ + DW_OP_breg7, 8, /* DW_OP_breg7 (rsp): 8 */ + DW_OP_breg16, 0, /* DW_OP_breg16 (rip): 0 */ + DW_OP_lit15, DW_OP_and, DW_OP_lit11, DW_OP_ge, + DW_OP_lit3, DW_OP_shl, DW_OP_plus, + DW_CFA_nop, DW_CFA_nop, DW_CFA_nop, DW_CFA_nop +}; + /* x86-64 ELF linker hash entry. */ struct elf_x86_64_link_hash_entry @@ -480,6 +658,7 @@ struct elf_x86_64_link_hash_table /* Short-cuts to get to dynamic linker sections. */ asection *sdynbss; asection *srelbss; + asection *plt_eh_frame; union { @@ -514,6 +693,11 @@ struct elf_x86_64_link_hash_table /* The offset into sgot of the GOT entry used by the PLT entry above. */ bfd_vma tlsdesc_got; + + /* The index of the next R_X86_64_JUMP_SLOT entry in .rela.plt. */ + bfd_vma next_jump_slot_index; + /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */ + bfd_vma next_irelative_index; }; /* Get the x86-64 ELF linker hash table from a link_info structure. */ @@ -648,12 +832,15 @@ elf_x86_64_link_hash_table_create (bfd *abfd) ret->sdynbss = NULL; ret->srelbss = NULL; + ret->plt_eh_frame = NULL; ret->sym_cache.abfd = NULL; ret->tlsdesc_plt = 0; ret->tlsdesc_got = 0; ret->tls_ld_got.refcount = 0; ret->sgotplt_jump_table_size = 0; ret->tls_module_base = NULL; + ret->next_jump_slot_index = 0; + ret->next_irelative_index = 0; if (ABI_64_P (abfd)) { @@ -726,6 +913,24 @@ elf_x86_64_create_dynamic_sections (bfd *dynobj, || (!info->shared && !htab->srelbss)) abort (); + if (!info->no_ld_generated_unwind_info + && bfd_get_section_by_name (dynobj, ".eh_frame") == NULL + && htab->elf.splt != NULL) + { + flagword flags = get_elf_backend_data (dynobj)->dynamic_sec_flags; + htab->plt_eh_frame + = bfd_make_section_with_flags (dynobj, ".eh_frame", + flags | SEC_READONLY); + if (htab->plt_eh_frame == NULL + || !bfd_set_section_alignment (dynobj, htab->plt_eh_frame, 3)) + return FALSE; + + htab->plt_eh_frame->size = sizeof (elf_x86_64_eh_frame_plt); + htab->plt_eh_frame->contents + = bfd_alloc (dynobj, htab->plt_eh_frame->size); + memcpy (htab->plt_eh_frame->contents, elf_x86_64_eh_frame_plt, + sizeof (elf_x86_64_eh_frame_plt)); + } return TRUE; } @@ -804,20 +1009,6 @@ elf64_x86_64_elf_object_p (bfd *abfd) return TRUE; } -typedef union - { - unsigned char c[2]; - uint16_t i; - } -x86_64_opcode16; - -typedef union - { - unsigned char c[4]; - uint32_t i; - } -x86_64_opcode32; - /* Return TRUE if the TLS access code sequence support transition from R_TYPE. */ @@ -873,24 +1064,23 @@ elf_x86_64_check_tls_transition (bfd *abfd, .word 0x6666; rex64; call __tls_get_addr can transit to different access model. */ - static x86_64_opcode32 call = { { 0x66, 0x66, 0x48, 0xe8 } }; + static const unsigned char call[] = { 0x66, 0x66, 0x48, 0xe8 }; + static const unsigned char leaq[] = { 0x66, 0x48, 0x8d, 0x3d }; + if ((offset + 12) > sec->size - || bfd_get_32 (abfd, contents + offset + 4) != call.i) + || memcmp (contents + offset + 4, call, 4) != 0) return FALSE; if (ABI_64_P (abfd)) { - static x86_64_opcode32 leaq = { { 0x66, 0x48, 0x8d, 0x3d } }; if (offset < 4 - || bfd_get_32 (abfd, contents + offset - 4) != leaq.i) + || memcmp (contents + offset - 4, leaq, 4) != 0) return FALSE; } else { - static x86_64_opcode16 lea = { { 0x8d, 0x3d } }; if (offset < 3 - || bfd_get_8 (abfd, contents + offset - 3) != 0x48 - || bfd_get_16 (abfd, contents + offset - 2) != lea.i) + || memcmp (contents + offset - 3, leaq + 1, 3) != 0) return FALSE; } } @@ -901,15 +1091,13 @@ elf_x86_64_check_tls_transition (bfd *abfd, call __tls_get_addr can transit to different access model. */ - static x86_64_opcode32 ld = { { 0x48, 0x8d, 0x3d, 0xe8 } }; - x86_64_opcode32 op; + static const unsigned char lea[] = { 0x48, 0x8d, 0x3d }; if (offset < 3 || (offset + 9) > sec->size) return FALSE; - op.i = bfd_get_32 (abfd, contents + offset - 3); - op.c[3] = bfd_get_8 (abfd, contents + offset + 4); - if (op.i != ld.i) + if (memcmp (contents + offset - 3, lea, 3) != 0 + || 0xe8 != *(contents + offset + 4)) return FALSE; } @@ -988,8 +1176,8 @@ elf_x86_64_check_tls_transition (bfd *abfd, if (offset + 2 <= sec->size) { /* Make sure that it's a call *x@tlsdesc(%rax). */ - static x86_64_opcode16 call = { { 0xff, 0x10 } }; - return bfd_get_16 (abfd, contents + offset) == call.i; + static const unsigned char call[] = { 0xff, 0x10 }; + return memcmp (contents + offset, call, 2) == 0; } return FALSE; @@ -1215,7 +1403,6 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, default: break; - case R_X86_64_64: case R_X86_64_DTPOFF64: case R_X86_64_TPOFF64: case R_X86_64_PC64: @@ -1260,7 +1447,9 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info, case R_X86_64_PLT32: case R_X86_64_GOTPCREL: case R_X86_64_GOTPCREL64: - if (!_bfd_elf_create_ifunc_sections (abfd, info)) + if (htab->elf.dynobj == NULL) + htab->elf.dynobj = abfd; + if (!_bfd_elf_create_ifunc_sections (htab->elf.dynobj, info)) return FALSE; break; } @@ -2029,8 +2218,6 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf) if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; eh = (struct elf_x86_64_link_hash_entry *) h; info = (struct bfd_link_info *) inf; @@ -2295,8 +2482,9 @@ elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, struct elf_x86_64_link_hash_entry *eh; struct elf_dyn_relocs *p; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Skip local IFUNC symbols. */ + if (h->forced_local && h->type == STT_GNU_IFUNC) + return TRUE; eh = (struct elf_x86_64_link_hash_entry *) h; for (p = eh->dyn_relocs; p != NULL; p = p->next) @@ -2309,6 +2497,11 @@ elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h, info->flags |= DF_TEXTREL; + if (info->warn_shared_textrel && info->shared) + info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' in readonly section `%A'.\n"), + p->sec->owner, h->root.root.string, + p->sec); + /* Not an error, just cut short the traversal. */ return FALSE; } @@ -2387,8 +2580,14 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, { srel = elf_section_data (p->sec)->sreloc; srel->size += p->count * bed->s->sizeof_rela; - if ((p->sec->output_section->flags & SEC_READONLY) != 0) - info->flags |= DF_TEXTREL; + if ((p->sec->output_section->flags & SEC_READONLY) != 0 + && (info->flags & DF_TEXTREL) == 0) + { + info->flags |= DF_TEXTREL; + if (info->warn_shared_textrel && info->shared) + info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'.\n"), + p->sec->owner, p->sec); + } } } } @@ -2470,10 +2669,18 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, incremented. However, when we reserve space for TLS descriptors, it's not incremented, so in order to compute the space reserved for them, it suffices to multiply the reloc count by the jump - slot size. */ + slot size. + + PR ld/13302: We start next_irelative_index at the end of .rela.plt + so that R_X86_64_IRELATIVE entries come last. */ if (htab->elf.srelplt) - htab->sgotplt_jump_table_size - = elf_x86_64_compute_jump_table_size (htab); + { + htab->sgotplt_jump_table_size + = elf_x86_64_compute_jump_table_size (htab); + htab->next_irelative_index = htab->elf.srelplt->reloc_count - 1; + } + else if (htab->elf.irelplt) + htab->next_irelative_index = htab->elf.irelplt->reloc_count - 1; if (htab->tlsdesc_plt) { @@ -2581,6 +2788,13 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd, return FALSE; } + if (htab->plt_eh_frame != NULL + && htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) == 0) + bfd_put_32 (dynobj, htab->elf.splt->size, + htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET); + if (htab->elf.dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the @@ -2815,7 +3029,12 @@ elf_x86_64_relocate_section (bfd *output_bfd, return FALSE; } - howto = x86_64_elf_howto_table + r_type; + if (r_type != (int) R_X86_64_32 + || ABI_64_P (output_bfd)) + howto = x86_64_elf_howto_table + r_type; + else + howto = (x86_64_elf_howto_table + + ARRAY_SIZE (x86_64_elf_howto_table) - 1); r_symndx = htab->r_sym (rel->r_info); h = NULL; sym = NULL; @@ -2860,6 +3079,16 @@ elf_x86_64_relocate_section (bfd *output_bfd, if (info->relocatable) continue; + if (rel->r_addend == 0 + && r_type == R_X86_64_64 + && !ABI_64_P (output_bfd)) + { + /* For x32, treat R_X86_64_64 like R_X86_64_32 and zero-extend + it to 64bit if addend is zero. */ + r_type = R_X86_64_32; + memset (contents + rel->r_offset + 4, 0, 4); + } + /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined in a non-shared object. */ if (h != NULL @@ -2922,11 +3151,12 @@ elf_x86_64_relocate_section (bfd *output_bfd, } /* Generate dynamic relcoation only when there is a - non-GOF reference in a shared object. */ + non-GOT reference in a shared object. */ if (info->shared && h->non_got_ref) { Elf_Internal_Rela outrel; asection *sreloc; + bfd_boolean relocate; /* Need a dynamic relocation to get the real function address. */ @@ -2946,15 +3176,15 @@ elf_x86_64_relocate_section (bfd *output_bfd, || info->executable) { /* This symbol is resolved locally. */ - outrel.r_info = htab->r_info (0, R_X86_64_IRELATIVE); - outrel.r_addend = (h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset); + outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); + outrel.r_addend = relocation; + relocate = FALSE; } else { outrel.r_info = htab->r_info (h->dynindx, r_type); outrel.r_addend = 0; + relocate = FALSE; } sreloc = htab->elf.irelifunc; @@ -2965,7 +3195,8 @@ elf_x86_64_relocate_section (bfd *output_bfd, we need to include the symbol value so that it becomes an addend for the dynamic reloc. For an internal symbol, we have updated addend. */ - continue; + if (! relocate) + continue; } /* FALLTHROUGH */ case R_X86_64_PC32: @@ -3374,6 +3605,14 @@ elf_x86_64_relocate_section (bfd *output_bfd, outrel.r_info = htab->r_info (0, R_X86_64_RELATIVE); outrel.r_addend = relocation + rel->r_addend; } + else if (r_type == R_X86_64_64 + && !ABI_64_P (output_bfd)) + { + relocate = TRUE; + outrel.r_info = htab->r_info (0, + R_X86_64_RELATIVE64); + outrel.r_addend = relocation + rel->r_addend; + } else { long sindx; @@ -3411,7 +3650,11 @@ elf_x86_64_relocate_section (bfd *output_bfd, sreloc = elf_section_data (input_section)->sreloc; - BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL); + if (sreloc == NULL || sreloc->contents == NULL) + { + r = bfd_reloc_notsupported; + goto check_relocation_error; + } elf_append_rela (output_bfd, sreloc, &outrel); @@ -3841,6 +4084,7 @@ elf_x86_64_relocate_section (bfd *output_bfd, break; case R_X86_64_TPOFF32: + case R_X86_64_TPOFF64: BFD_ASSERT (info->executable); relocation = elf_x86_64_tpoff (info, relocation); break; @@ -3854,7 +4098,9 @@ elf_x86_64_relocate_section (bfd *output_bfd, not process them. */ if (unresolved_reloc && !((input_section->flags & SEC_DEBUGGING) != 0 - && h->def_dynamic)) + && h->def_dynamic) + && _bfd_elf_section_offset (output_bfd, info, input_section, + rel->r_offset) != (bfd_vma) -1) (*_bfd_error_handler) (_("%B(%A+0x%lx): unresolvable %s relocation against symbol `%s'"), input_bfd, @@ -3868,6 +4114,7 @@ do_relocation: contents, rel->r_offset, relocation, rel->r_addend); +check_relocation_error: if (r != bfd_reloc_ok) { const char *name; @@ -3955,7 +4202,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, || plt == NULL || gotplt == NULL || relplt == NULL) - abort (); + return FALSE; /* Get the index in the procedure linkage table which corresponds to this symbol. This is the index of this symbol @@ -3970,13 +4217,13 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, if (plt == htab->elf.splt) { - plt_index = h->plt.offset / PLT_ENTRY_SIZE - 1; - got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; + got_offset = h->plt.offset / PLT_ENTRY_SIZE - 1; + got_offset = (got_offset + 3) * GOT_ENTRY_SIZE; } else { - plt_index = h->plt.offset / PLT_ENTRY_SIZE; - got_offset = plt_index * GOT_ENTRY_SIZE; + got_offset = h->plt.offset / PLT_ENTRY_SIZE; + got_offset = got_offset * GOT_ENTRY_SIZE; } /* Fill in the entry in the procedure linkage table. */ @@ -3998,17 +4245,6 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, - 6), plt->contents + h->plt.offset + 2); - /* Don't fill PLT entry for static executables. */ - if (plt == htab->elf.splt) - { - /* Put relocation index. */ - bfd_put_32 (output_bfd, plt_index, - plt->contents + h->plt.offset + 7); - /* Put offset for jmp .PLT0. */ - bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), - plt->contents + h->plt.offset + 12); - } - /* Fill in the entry in the global offset table, initially this points to the pushq instruction in the PLT which is at offset 6. */ bfd_put_64 (output_bfd, (plt->output_section->vma @@ -4032,11 +4268,25 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd, rela.r_addend = (h->root.u.def.value + h->root.u.def.section->output_section->vma + h->root.u.def.section->output_offset); + /* R_X86_64_IRELATIVE comes last. */ + plt_index = htab->next_irelative_index--; } else { rela.r_info = htab->r_info (h->dynindx, R_X86_64_JUMP_SLOT); rela.r_addend = 0; + plt_index = htab->next_jump_slot_index++; + } + + /* Don't fill PLT entry for static executables. */ + if (plt == htab->elf.splt) + { + /* Put relocation index. */ + bfd_put_32 (output_bfd, plt_index, + plt->contents + h->plt.offset + 7); + /* Put offset for jmp .PLT0. */ + bfd_put_32 (output_bfd, - (h->plt.offset + PLT_ENTRY_SIZE), + plt->contents + h->plt.offset + 12); } bed = get_elf_backend_data (output_bfd); @@ -4375,6 +4625,33 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd, GOT_ENTRY_SIZE; } + /* Adjust .eh_frame for .plt section. */ + if (htab->plt_eh_frame != NULL) + { + if (htab->elf.splt != NULL + && htab->elf.splt->size != 0 + && (htab->elf.splt->flags & SEC_EXCLUDE) == 0 + && htab->elf.splt->output_section != NULL + && htab->plt_eh_frame->output_section != NULL) + { + bfd_vma plt_start = htab->elf.splt->output_section->vma; + bfd_vma eh_frame_start = htab->plt_eh_frame->output_section->vma + + htab->plt_eh_frame->output_offset + + PLT_FDE_START_OFFSET; + bfd_put_signed_32 (dynobj, plt_start - eh_frame_start, + htab->plt_eh_frame->contents + + PLT_FDE_START_OFFSET); + } + if (htab->plt_eh_frame->sec_info_type + == ELF_INFO_TYPE_EH_FRAME) + { + if (! _bfd_elf_write_section_eh_frame (output_bfd, info, + htab->plt_eh_frame, + htab->plt_eh_frame->contents)) + return FALSE; + } + } + if (htab->elf.sgot && htab->elf.sgot->size > 0) elf_section_data (htab->elf.sgot->output_section)->this_hdr.sh_entsize = GOT_ENTRY_SIZE; @@ -4451,8 +4728,9 @@ elf_x86_64_add_symbol_hook (bfd *abfd, } if ((abfd->flags & DYNAMIC) == 0 - && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC) - elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE; + && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC + || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)) + elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE; return TRUE; } @@ -4529,14 +4807,14 @@ elf_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, bfd_boolean *override ATTRIBUTE_UNUSED, bfd_boolean *type_change_ok ATTRIBUTE_UNUSED, bfd_boolean *size_change_ok ATTRIBUTE_UNUSED, - bfd_boolean *newdef ATTRIBUTE_UNUSED, - bfd_boolean *newdyn, + bfd_boolean *newdyn ATTRIBUTE_UNUSED, + bfd_boolean *newdef, bfd_boolean *newdyncommon ATTRIBUTE_UNUSED, bfd_boolean *newweak ATTRIBUTE_UNUSED, bfd *abfd ATTRIBUTE_UNUSED, asection **sec, - bfd_boolean *olddef ATTRIBUTE_UNUSED, - bfd_boolean *olddyn, + bfd_boolean *olddyn ATTRIBUTE_UNUSED, + bfd_boolean *olddef, bfd_boolean *olddyncommon ATTRIBUTE_UNUSED, bfd_boolean *oldweak ATTRIBUTE_UNUSED, bfd *oldbfd, @@ -4545,9 +4823,9 @@ elf_x86_64_merge_symbol (struct bfd_link_info *info ATTRIBUTE_UNUSED, /* A normal common symbol and a large common symbol result in a normal common symbol. We turn the large common symbol into a normal one. */ - if (!*olddyn + if (!*olddef && h->root.type == bfd_link_hash_common - && !*newdyn + && !*newdef && bfd_is_com_section (*sec) && *oldsec != *sec) { @@ -4640,6 +4918,7 @@ static const struct bfd_elf_special_section #define elf_backend_want_plt_sym 0 #define elf_backend_got_header_size (GOT_ENTRY_SIZE*3) #define elf_backend_rela_normal 1 +#define elf_backend_plt_alignment 4 #define elf_info_to_howto elf_x86_64_info_to_howto @@ -4662,6 +4941,9 @@ static const struct bfd_elf_special_section #define elf_backend_gc_sweep_hook elf_x86_64_gc_sweep_hook #define elf_backend_grok_prstatus elf_x86_64_grok_prstatus #define elf_backend_grok_psinfo elf_x86_64_grok_psinfo +#ifdef CORE_HEADER +#define elf_backend_write_core_note elf_x86_64_write_core_note +#endif #define elf_backend_reloc_type_class elf_x86_64_reloc_type_class #define elf_backend_relocate_section elf_x86_64_relocate_section #define elf_backend_size_dynamic_sections elf_x86_64_size_dynamic_sections @@ -4695,7 +4977,6 @@ static const struct bfd_elf_special_section #define elf_backend_hash_symbol \ elf_x86_64_hash_symbol -#undef elf_backend_post_process_headers #define elf_backend_post_process_headers _bfd_elf_set_osabi #include "elf64-target.h" @@ -4771,7 +5052,6 @@ elf64_l1om_elf_object_p (bfd *abfd) #undef elf_backend_object_p #define elf_backend_object_p elf64_l1om_elf_object_p -#undef elf_backend_post_process_headers #undef elf_backend_static_tls_alignment #undef elf_backend_want_plt_sym @@ -4792,8 +5072,55 @@ elf64_l1om_elf_object_p (bfd *abfd) #undef elf64_bed #define elf64_bed elf64_l1om_fbsd_bed -#undef elf_backend_post_process_headers -#define elf_backend_post_process_headers _bfd_elf_set_osabi +#include "elf64-target.h" + +/* Intel K1OM support. */ + +static bfd_boolean +elf64_k1om_elf_object_p (bfd *abfd) +{ + /* Set the right machine number for an K1OM elf64 file. */ + bfd_default_set_arch_mach (abfd, bfd_arch_k1om, bfd_mach_k1om); + return TRUE; +} + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM bfd_elf64_k1om_vec +#undef TARGET_LITTLE_NAME +#define TARGET_LITTLE_NAME "elf64-k1om" +#undef ELF_ARCH +#define ELF_ARCH bfd_arch_k1om + +#undef ELF_MACHINE_CODE +#define ELF_MACHINE_CODE EM_K1OM + +#undef ELF_OSABI + +#undef elf64_bed +#define elf64_bed elf64_k1om_bed + +#undef elf_backend_object_p +#define elf_backend_object_p elf64_k1om_elf_object_p + +#undef elf_backend_static_tls_alignment + +#undef elf_backend_want_plt_sym +#define elf_backend_want_plt_sym 0 + +#include "elf64-target.h" + +/* FreeBSD K1OM support. */ + +#undef TARGET_LITTLE_SYM +#define TARGET_LITTLE_SYM bfd_elf64_k1om_freebsd_vec +#undef TARGET_LITTLE_NAME +#define TARGET_LITTLE_NAME "elf64-k1om-freebsd" + +#undef ELF_OSABI +#define ELF_OSABI ELFOSABI_FREEBSD + +#undef elf64_bed +#define elf64_bed elf64_k1om_fbsd_bed #include "elf64-target.h" @@ -4831,8 +5158,6 @@ elf32_x86_64_elf_object_p (bfd *abfd) #undef ELF_OSABI -#undef elf_backend_post_process_headers - #undef elf_backend_object_p #define elf_backend_object_p \ elf32_x86_64_elf_object_p diff --git a/contrib/gdb-7/bfd/elfcode.h b/contrib/gdb-7/bfd/elfcode.h index 28b6b904e5..b7e022614c 100644 --- a/contrib/gdb-7/bfd/elfcode.h +++ b/contrib/gdb-7/bfd/elfcode.h @@ -1,6 +1,6 @@ /* ELF executable support for BFD. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Fred Fish @ Cygnus Support, from information published @@ -499,7 +499,6 @@ elf_object_p (bfd *abfd) asection *s; bfd_size_type amt; const bfd_target *target; - const bfd_target * const *target_ptr; preserve.marker = NULL; @@ -588,34 +587,9 @@ elf_object_p (bfd *abfd) && (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1) && (ebd->elf_machine_alt2 == 0 - || i_ehdrp->e_machine != ebd->elf_machine_alt2)) - { - if (ebd->elf_machine_code != EM_NONE) - goto got_wrong_format_error; - - /* This is the generic ELF target. Let it match any ELF target - for which we do not have a specific backend. */ - for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++) - { - const struct elf_backend_data *back; - - if ((*target_ptr)->flavour != bfd_target_elf_flavour) - continue; - back = xvec_get_elf_backend_data (*target_ptr); - if (back->s->arch_size != ARCH_SIZE) - continue; - if (back->elf_machine_code == i_ehdrp->e_machine - || (back->elf_machine_alt1 != 0 - && back->elf_machine_alt1 == i_ehdrp->e_machine) - || (back->elf_machine_alt2 != 0 - && back->elf_machine_alt2 == i_ehdrp->e_machine)) - { - /* target_ptr is an ELF backend which matches this - object file, so reject the generic ELF target. */ - goto got_wrong_format_error; - } - } - } + || i_ehdrp->e_machine != ebd->elf_machine_alt2) + && ebd->elf_machine_code != EM_NONE) + goto got_wrong_format_error; if (i_ehdrp->e_type == ET_EXEC) abfd->flags |= EXEC_P; @@ -633,43 +607,9 @@ elf_object_p (bfd *abfd) } if (ebd->elf_machine_code != EM_NONE - && i_ehdrp->e_ident[EI_OSABI] != ebd->elf_osabi) - { - if (ebd->elf_osabi != ELFOSABI_NONE) - goto got_wrong_format_error; - - /* This is an ELFOSABI_NONE ELF target. Let it match any ELF - target of the compatible machine for which we do not have a - backend with matching ELFOSABI. */ - for (target_ptr = bfd_target_vector; - *target_ptr != NULL; - target_ptr++) - { - const struct elf_backend_data *back; - - /* Skip this target and targets with incompatible byte - order. */ - if (*target_ptr == target - || (*target_ptr)->flavour != bfd_target_elf_flavour - || (*target_ptr)->byteorder != target->byteorder - || ((*target_ptr)->header_byteorder - != target->header_byteorder)) - continue; - - back = xvec_get_elf_backend_data (*target_ptr); - if (back->elf_osabi == i_ehdrp->e_ident[EI_OSABI] - && (back->elf_machine_code == i_ehdrp->e_machine - || (back->elf_machine_alt1 != 0 - && back->elf_machine_alt1 == i_ehdrp->e_machine) - || (back->elf_machine_alt2 != 0 - && back->elf_machine_alt2 == i_ehdrp->e_machine))) - { - /* target_ptr is an ELF backend which matches this - object file, so reject the ELFOSABI_NONE ELF target. */ - goto got_wrong_format_error; - } - } - } + && i_ehdrp->e_ident[EI_OSABI] != ebd->elf_osabi + && ebd->elf_osabi != ELFOSABI_NONE) + goto got_wrong_format_error; if (i_ehdrp->e_shoff != 0) { @@ -1282,6 +1222,20 @@ elf_slurp_symbol_table (bfd *abfd, asymbol **symptrs, bfd_boolean dynamic) else if (isym->st_shndx == SHN_COMMON) { sym->symbol.section = bfd_com_section_ptr; + if ((abfd->flags & BFD_PLUGIN) != 0) + { + asection *xc = bfd_get_section_by_name (abfd, "COMMON"); + + if (xc == NULL) + { + flagword flags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP + | SEC_EXCLUDE); + xc = bfd_make_section_with_flags (abfd, "COMMON", flags); + if (xc == NULL) + goto error_return; + } + sym->symbol.section = xc; + } /* Elf puts the alignment into the `value' field, and the size into the `size' field. BFD wants to see the size in the value field, and doesn't care (at the diff --git a/contrib/gdb-7/bfd/elflink.c b/contrib/gdb-7/bfd/elflink.c index 9ccc841da2..1d1ca0bce4 100644 --- a/contrib/gdb-7/bfd/elflink.c +++ b/contrib/gdb-7/bfd/elflink.c @@ -1,6 +1,6 @@ /* ELF linking support for BFD. Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008, 2009, 2010 + 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -36,7 +36,6 @@ struct elf_info_failed { struct bfd_link_info *info; - struct bfd_elf_version_tree *verdefs; bfd_boolean failed; }; @@ -111,17 +110,17 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) flags = bed->dynamic_sec_flags; - s = bfd_make_section_with_flags (abfd, - (bed->rela_plts_and_copies_p - ? ".rela.got" : ".rel.got"), - (bed->dynamic_sec_flags - | SEC_READONLY)); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.got" : ".rel.got"), + (bed->dynamic_sec_flags + | SEC_READONLY)); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; htab->srelgot = s; - s = bfd_make_section_with_flags (abfd, ".got", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".got", flags); if (s == NULL || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -129,7 +128,7 @@ _bfd_elf_create_got_section (bfd *abfd, struct bfd_link_info *info) if (bed->want_got_plt) { - s = bfd_make_section_with_flags (abfd, ".got.plt", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".got.plt", flags); if (s == NULL || !bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) @@ -207,44 +206,44 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) shared library does not. */ if (info->executable) { - s = bfd_make_section_with_flags (abfd, ".interp", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".interp", + flags | SEC_READONLY); if (s == NULL) return FALSE; } /* Create sections to hold version informations. These are removed if they are not needed. */ - s = bfd_make_section_with_flags (abfd, ".gnu.version_d", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_d", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".gnu.version", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, 1)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".gnu.version_r", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.version_r", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".dynsym", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".dynsym", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; - s = bfd_make_section_with_flags (abfd, ".dynstr", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".dynstr", + flags | SEC_READONLY); if (s == NULL) return FALSE; - s = bfd_make_section_with_flags (abfd, ".dynamic", flags); + s = bfd_make_section_anyway_with_flags (abfd, ".dynamic", flags); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -260,7 +259,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (info->emit_hash) { - s = bfd_make_section_with_flags (abfd, ".hash", flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".hash", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -269,8 +269,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (info->emit_gnu_hash) { - s = bfd_make_section_with_flags (abfd, ".gnu.hash", - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, ".gnu.hash", + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -286,7 +286,8 @@ _bfd_elf_link_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) /* Let the backend create the rest of the sections. This lets the backend set the right flags. The backend will normally create the .got and .plt sections. */ - if (! (*bed->elf_backend_create_dynamic_sections) (abfd, info)) + if (bed->elf_backend_create_dynamic_sections == NULL + || ! (*bed->elf_backend_create_dynamic_sections) (abfd, info)) return FALSE; elf_hash_table (info)->dynamic_sections_created = TRUE; @@ -320,7 +321,7 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) if (bed->plt_readonly) pltflags |= SEC_READONLY; - s = bfd_make_section_with_flags (abfd, ".plt", pltflags); + s = bfd_make_section_anyway_with_flags (abfd, ".plt", pltflags); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->plt_alignment)) return FALSE; @@ -337,10 +338,10 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) return FALSE; } - s = bfd_make_section_with_flags (abfd, - (bed->rela_plts_and_copies_p - ? ".rela.plt" : ".rel.plt"), - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.plt" : ".rel.plt"), + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -357,9 +358,8 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) image and use a R_*_COPY reloc to tell the dynamic linker to initialize them at run time. The linker script puts the .dynbss section into the .bss section of the final image. */ - s = bfd_make_section_with_flags (abfd, ".dynbss", - (SEC_ALLOC - | SEC_LINKER_CREATED)); + s = bfd_make_section_anyway_with_flags (abfd, ".dynbss", + (SEC_ALLOC | SEC_LINKER_CREATED)); if (s == NULL) return FALSE; @@ -376,10 +376,10 @@ _bfd_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) copy relocs. */ if (! info->shared) { - s = bfd_make_section_with_flags (abfd, - (bed->rela_plts_and_copies_p - ? ".rela.bss" : ".rel.bss"), - flags | SEC_READONLY); + s = bfd_make_section_anyway_with_flags (abfd, + (bed->rela_plts_and_copies_p + ? ".rela.bss" : ".rel.bss"), + flags | SEC_READONLY); if (s == NULL || ! bfd_set_section_alignment (abfd, s, bed->s->log_file_align)) return FALSE; @@ -721,9 +721,6 @@ elf_link_renumber_hash_table_dynsyms (struct elf_link_hash_entry *h, { size_t *count = (size_t *) data; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->forced_local) return TRUE; @@ -743,9 +740,6 @@ elf_link_renumber_local_hash_table_dynsyms (struct elf_link_hash_entry *h, { size_t *count = (size_t *) data; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (!h->forced_local) return TRUE; @@ -1085,11 +1079,15 @@ _bfd_elf_merge_symbol (bfd *abfd, return TRUE; } + /* Plugin symbol type isn't currently set. Stop bogus errors. */ + if (oldbfd != NULL && (oldbfd->flags & BFD_PLUGIN) != 0) + *type_change_ok = TRUE; + /* Check TLS symbol. We don't check undefined symbol introduced by "ld -u". */ - if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS) - && ELF_ST_TYPE (sym->st_info) != h->type - && oldbfd != NULL) + else if (oldbfd != NULL + && ELF_ST_TYPE (sym->st_info) != h->type + && (ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)) { bfd *ntbfd, *tbfd; bfd_boolean ntdef, tdef; @@ -1240,7 +1238,6 @@ _bfd_elf_merge_symbol (bfd *abfd, { h->def_dynamic = 0; h->ref_dynamic = 1; - h->dynamic_def = 1; } /* FIXME: Should we check type and size for protected symbol? */ h->size = 0; @@ -1361,8 +1358,7 @@ _bfd_elf_merge_symbol (bfd *abfd, symbols defined in dynamic objects. */ if (! ((*info->callbacks->multiple_common) - (info, h->root.root.string, oldbfd, bfd_link_hash_common, - h->size, abfd, bfd_link_hash_common, sym->st_size))) + (info, &h->root, abfd, bfd_link_hash_common, sym->st_size))) return FALSE; if (sym->st_size > h->size) @@ -1428,7 +1424,11 @@ _bfd_elf_merge_symbol (bfd *abfd, /* Skip weak definitions of symbols that are already defined. */ if (newdef && olddef && newweak) { - *skip = TRUE; + /* Don't skip new non-IR weak syms. */ + if (!(oldbfd != NULL + && (oldbfd->flags & BFD_PLUGIN) != 0 + && (abfd->flags & BFD_PLUGIN) == 0)) + *skip = TRUE; /* Merge st_other. If the symbol already has a dynamic index, but visibility says it should not be visible, turn it into a @@ -1513,8 +1513,7 @@ _bfd_elf_merge_symbol (bfd *abfd, common symbol, but we don't know what to use for the section or the alignment. */ if (! ((*info->callbacks->multiple_common) - (info, h->root.root.string, oldbfd, bfd_link_hash_common, - h->size, abfd, bfd_link_hash_common, sym->st_size))) + (info, &h->root, abfd, bfd_link_hash_common, sym->st_size))) return FALSE; /* If the presumed common symbol in the dynamic object is @@ -1810,32 +1809,23 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data) { struct elf_info_failed *eif = (struct elf_info_failed *) data; - /* Ignore this if we won't export it. */ - if (!eif->info->export_dynamic && !h->dynamic) - return TRUE; - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->root.type == bfd_link_hash_indirect) return TRUE; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; + /* Ignore this if we won't export it. */ + if (!eif->info->export_dynamic && !h->dynamic) + return TRUE; if (h->dynindx == -1 - && (h->def_regular - || h->ref_regular)) + && (h->def_regular || h->ref_regular) + && ! bfd_hide_sym_by_version (eif->info->version_info, + h->root.root.string)) { - bfd_boolean hide; - - if (eif->verdefs == NULL - || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide) - && !hide)) + if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) { - if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) - { - eif->failed = TRUE; - return FALSE; - } + eif->failed = TRUE; + return FALSE; } } @@ -1856,9 +1846,6 @@ _bfd_elf_link_find_version_dependencies (struct elf_link_hash_entry *h, Elf_Internal_Vernaux *a; bfd_size_type amt; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* We only care about symbols defined in shared objects with version information. */ if (!h->def_dynamic @@ -1944,9 +1931,6 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) sinfo = (struct elf_info_failed *) data; info = sinfo->info; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Fix the symbol flags. */ eif.failed = FALSE; eif.info = info; @@ -1989,7 +1973,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) } /* Look for the version. If we find it, it is no longer weak. */ - for (t = sinfo->verdefs; t != NULL; t = t->next) + for (t = sinfo->info->version_info; t != NULL; t = t->next) { if (strcmp (t->name, p) == 0) { @@ -2058,9 +2042,12 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) version_index = 1; /* Don't count anonymous version tag. */ - if (sinfo->verdefs != NULL && sinfo->verdefs->vernum == 0) + if (sinfo->info->version_info != NULL + && sinfo->info->version_info->vernum == 0) version_index = 0; - for (pp = &sinfo->verdefs; *pp != NULL; pp = &(*pp)->next) + for (pp = &sinfo->info->version_info; + *pp != NULL; + pp = &(*pp)->next) ++version_index; t->vernum = version_index; @@ -2086,12 +2073,13 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) /* If we don't have a version for this symbol, see if we can find something. */ - if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL) + if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL) { bfd_boolean hide; - h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs, - h->root.root.string, &hide); + h->verinfo.vertree + = bfd_find_version_for_sym (sinfo->info->version_info, + h->root.root.string, &hide); if (h->verinfo.vertree != NULL && hide) (*bed->elf_backend_hide_symbol) (info, h, TRUE); } @@ -2525,7 +2513,7 @@ _bfd_elf_fix_symbol_flags (struct elf_link_hash_entry *h, struct elf_link_hash_entry *weakdef; weakdef = h->u.weakdef; - if (h->root.type == bfd_link_hash_indirect) + while (h->root.type == bfd_link_hash_indirect) h = (struct elf_link_hash_entry *) h->root.u.i.link; BFD_ASSERT (h->root.type == bfd_link_hash_defined @@ -2562,17 +2550,6 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data) if (! is_elf_hash_table (eif->info->hash)) return FALSE; - if (h->root.type == bfd_link_hash_warning) - { - h->got = elf_hash_table (eif->info)->init_got_offset; - h->plt = elf_hash_table (eif->info)->init_plt_offset; - - /* When warning symbols are created, they **replace** the "real" - entry in the hash table, thus we never get to see the real - symbol in a hash traversal. So look at it now. */ - h = (struct elf_link_hash_entry *) h->root.u.i.link; - } - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->root.type == bfd_link_hash_indirect) return TRUE; @@ -2640,12 +2617,12 @@ _bfd_elf_adjust_dynamic_symbol (struct elf_link_hash_entry *h, void *data) if (h->u.weakdef != NULL) { - /* If we get to this point, we know there is an implicit - reference by a regular object file via the weak symbol H. - FIXME: Is this really true? What if the traversal finds - H->U.WEAKDEF before it finds H? */ + /* If we get to this point, there is an implicit reference to + H->U.WEAKDEF by a regular object file via the weak symbol H. */ h->u.weakdef->ref_regular = 1; + /* Ensure that the backend adjust_dynamic_symbol function sees + H->U.WEAKDEF before H by recursively calling ourselves. */ if (! _bfd_elf_adjust_dynamic_symbol (h->u.weakdef, eif)) return FALSE; } @@ -2728,9 +2705,6 @@ _bfd_elf_link_sec_merge_syms (struct elf_link_hash_entry *h, void *data) { asection *sec; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && ((sec = h->root.u.def.section)->flags & SEC_MERGE) @@ -2880,8 +2854,10 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h, return TRUE; /* Function pointer equality tests may require that STV_PROTECTED - symbols be treated as dynamic symbols, even when we know that the - dynamic linker will resolve them locally. */ + symbols be treated as dynamic symbols. If the address of a + function not defined in an executable is set to that function's + plt entry in the executable, then the address of the function in + a shared library must also be the plt entry in the executable. */ return local_protected; } @@ -3176,9 +3152,6 @@ elf_adjust_dynstr_offsets (struct elf_link_hash_entry *h, void *data) { struct elf_strtab_hash *dynstr = (struct elf_strtab_hash *) data; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->dynindx != -1) h->dynstr_index = _bfd_elf_strtab_offset (dynstr, h->dynstr_index); return TRUE; @@ -3422,7 +3395,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) .gnu.warning.SYMBOL are treated as warning symbols for the given symbol. This differs from .gnu.warning sections, which generate warnings when they are included in an output file. */ - if (info->executable) + /* PR 12761: Also generate this warning when building shared libraries. */ + if (info->executable || info->shared) { asection *s; @@ -3813,7 +3787,7 @@ error_free_dyn: /* Make a special call to the linker "notice" function to tell it that we are about to handle an as-needed lib. */ if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_as_needed)) + notice_as_needed, 0, NULL)) goto error_free_vers; /* Clone the symbol table and sym hashes. Remember some @@ -3922,7 +3896,7 @@ error_free_dyn: sec = bfd_section_from_elf_index (abfd, isym->st_shndx); if (sec == NULL) sec = bfd_abs_section_ptr; - else if (sec->kept_section) + else if (elf_discarded_section (sec)) { /* Symbols from discarded section are undefined. We keep its visibility. */ @@ -3939,18 +3913,31 @@ error_free_dyn: goto error_free_vers; if (isym->st_shndx == SHN_COMMON - && ELF_ST_TYPE (isym->st_info) == STT_TLS - && !info->relocatable) + && (abfd->flags & BFD_PLUGIN) != 0) + { + asection *xc = bfd_get_section_by_name (abfd, "COMMON"); + + if (xc == NULL) + { + flagword sflags = (SEC_ALLOC | SEC_IS_COMMON | SEC_KEEP + | SEC_EXCLUDE); + xc = bfd_make_section_with_flags (abfd, "COMMON", sflags); + if (xc == NULL) + goto error_free_vers; + } + sec = xc; + } + else if (isym->st_shndx == SHN_COMMON + && ELF_ST_TYPE (isym->st_info) == STT_TLS + && !info->relocatable) { asection *tcomm = bfd_get_section_by_name (abfd, ".tcommon"); if (tcomm == NULL) { - tcomm = bfd_make_section_with_flags (abfd, ".tcommon", - (SEC_ALLOC - | SEC_IS_COMMON - | SEC_LINKER_CREATED - | SEC_THREAD_LOCAL)); + flagword sflags = (SEC_ALLOC | SEC_THREAD_LOCAL | SEC_IS_COMMON + | SEC_LINKER_CREATED); + tcomm = bfd_make_section_with_flags (abfd, ".tcommon", sflags); if (tcomm == NULL) goto error_free_vers; } @@ -4226,10 +4213,7 @@ error_free_dyn: We need to get the alignment from the section. */ align = new_sec->alignment_power; } - if (align > old_alignment - /* Permit an alignment power of zero if an alignment of one - is specified and no other alignments have been specified. */ - || (isym->st_value == 1 && old_alignment == 0)) + if (align > old_alignment) h->root.u.c.p->alignment_power = align; else h->root.u.c.p->alignment_power = old_alignment; @@ -4368,7 +4352,6 @@ error_free_dyn: { h->def_dynamic = 0; h->ref_dynamic = 1; - h->dynamic_def = 1; } } if (! info->executable @@ -4381,7 +4364,10 @@ error_free_dyn: if (! definition) h->ref_dynamic = 1; else - h->def_dynamic = 1; + { + h->def_dynamic = 1; + h->dynamic_def = 1; + } if (h->def_regular || h->ref_regular || (h->u.weakdef != NULL @@ -4390,11 +4376,13 @@ error_free_dyn: dynsym = TRUE; } + /* We don't want to make debug symbol dynamic. */ if (definition && (sec->flags & SEC_DEBUGGING) && !info->relocatable) - { - /* We don't want to make debug symbol dynamic. */ - dynsym = FALSE; - } + dynsym = FALSE; + + /* Nor should we make plugin symbols dynamic. */ + if ((abfd->flags & BFD_PLUGIN) != 0) + dynsym = FALSE; if (definition) h->target_internal = isym->st_target_internal; @@ -4527,6 +4515,8 @@ error_free_dyn: { struct bfd_hash_entry *p; struct elf_link_hash_entry *h; + bfd_size_type size; + unsigned int alignment_power; for (p = htab->root.table.table[i]; p != NULL; p = p->next) { @@ -4536,6 +4526,20 @@ error_free_dyn: if (h->dynindx >= old_dynsymcount) _bfd_elf_strtab_delref (htab->dynstr, h->dynstr_index); + /* Preserve the maximum alignment and size for common + symbols even if this dynamic lib isn't on DT_NEEDED + since it can still be loaded at the run-time by another + dynamic lib. */ + if (h->root.type == bfd_link_hash_common) + { + size = h->root.u.c.size; + alignment_power = h->root.u.c.p->alignment_power; + } + else + { + size = 0; + alignment_power = 0; + } memcpy (p, old_ent, htab->root.table.entsize); old_ent = (char *) old_ent + htab->root.table.entsize; h = (struct elf_link_hash_entry *) p; @@ -4544,13 +4548,20 @@ error_free_dyn: memcpy (h->root.u.i.link, old_ent, htab->root.table.entsize); old_ent = (char *) old_ent + htab->root.table.entsize; } + else if (h->root.type == bfd_link_hash_common) + { + if (size > h->root.u.c.size) + h->root.u.c.size = size; + if (alignment_power > h->root.u.c.p->alignment_power) + h->root.u.c.p->alignment_power = alignment_power; + } } } /* Make a special call to the linker "notice" function to tell it that symbols added for crefs may need to be removed. */ if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_not_needed)) + notice_not_needed, 0, NULL)) goto error_free_vers; free (old_tab); @@ -4564,7 +4575,7 @@ error_free_dyn: if (old_tab != NULL) { if (!(*info->callbacks->notice) (info, NULL, abfd, NULL, - notice_needed)) + notice_needed, 0, NULL)) goto error_free_vers; free (old_tab); old_tab = NULL; @@ -4897,7 +4908,7 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd, char *p, *copy; size_t len, first; - h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, FALSE); + h = elf_link_hash_lookup (elf_hash_table (info), name, FALSE, FALSE, TRUE); if (h != NULL) return h; @@ -4920,14 +4931,14 @@ _bfd_elf_archive_symbol_lookup (bfd *abfd, memcpy (copy, name, first); memcpy (copy + first, name + first + 1, len - first); - h = elf_link_hash_lookup (elf_hash_table (info), copy, FALSE, FALSE, FALSE); + h = elf_link_hash_lookup (elf_hash_table (info), copy, FALSE, FALSE, TRUE); if (h == NULL) { /* We also need to check references to the symbol without the version. */ copy[first - 1] = '\0'; h = elf_link_hash_lookup (elf_hash_table (info), copy, - FALSE, FALSE, FALSE); + FALSE, FALSE, TRUE); } bfd_release (abfd, copy); @@ -5160,9 +5171,6 @@ elf_collect_hash_codes (struct elf_link_hash_entry *h, void *data) unsigned long ha; char *alc = NULL; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->dynindx == -1) return TRUE; @@ -5231,9 +5239,6 @@ elf_collect_gnu_hash_codes (struct elf_link_hash_entry *h, void *data) unsigned long ha; char *alc = NULL; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Ignore indirect symbols. These are added by the versioning code. */ if (h->dynindx == -1) return TRUE; @@ -5284,9 +5289,6 @@ elf_renumber_gnu_hash_syms (struct elf_link_hash_entry *h, void *data) unsigned long int bucket; unsigned long int val; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Ignore indirect symbols. */ if (h->dynindx == -1) return TRUE; @@ -5514,8 +5516,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, const char *depaudit, const char * const *auxiliary_filters, struct bfd_link_info *info, - asection **sinterpptr, - struct bfd_elf_version_tree *verdefs) + asection **sinterpptr) { bfd_size_type soname_indx; bfd *dynobj; @@ -5546,7 +5547,8 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { asection *s; - if (inputobj->flags & (DYNAMIC | EXEC_P | BFD_LINKER_CREATED)) + if (inputobj->flags + & (DYNAMIC | EXEC_P | BFD_PLUGIN | BFD_LINKER_CREATED)) continue; s = bfd_get_section_by_name (inputobj, ".note.GNU-stack"); if (s) @@ -5691,7 +5693,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } eif.info = info; - eif.verdefs = verdefs; eif.failed = FALSE; /* If we are supposed to export all symbols into the dynamic symbol @@ -5707,7 +5708,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } /* Make all global versions with definition. */ - for (t = verdefs; t != NULL; t = t->next) + for (t = info->version_info; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) if (!d->symver && d->literal) { @@ -5760,7 +5761,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* Attach all the symbols to their version information. */ asvinfo.info = info; - asvinfo.verdefs = verdefs; asvinfo.failed = FALSE; elf_link_hash_traverse (elf_hash_table (info), @@ -5773,7 +5773,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { /* Check if all global versions have a definition. */ all_defined = TRUE; - for (t = verdefs; t != NULL; t = t->next) + for (t = info->version_info; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) if (d->literal && !d->symver && !d->script) { @@ -5906,6 +5906,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (elf_hash_table (info)->dynamic_sections_created) { unsigned long section_sym_count; + struct bfd_elf_version_tree *verdefs; asection *s; /* Set up the version definition section. */ @@ -5914,7 +5915,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* We may have created additional version definitions if we are just linking a regular application. */ - verdefs = asvinfo.verdefs; + verdefs = info->version_info; /* Skip anonymous version tag. */ if (verdefs != NULL && verdefs->vernum == 0) @@ -6529,10 +6530,13 @@ bfd_elf_size_dynsym_hash_dynstr (bfd *output_bfd, struct bfd_link_info *info) } else { - unsigned long int maskwords, maskbitslog2; + unsigned long int maskwords, maskbitslog2, x; BFD_ASSERT (cinfo.min_dynindx != -1); - maskbitslog2 = bfd_log2 (cinfo.nsyms) + 1; + x = cinfo.nsyms; + maskbitslog2 = 1; + while ((x >>= 1) != 0) + ++maskbitslog2; if (maskbitslog2 < 3) maskbitslog2 = 5; else if ((1 << (maskbitslog2 - 2)) & cinfo.nsyms) @@ -8587,8 +8591,9 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, global symbols. */ static bfd_boolean -elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) +elf_link_output_extsym (struct bfd_hash_entry *bh, void *data) { + struct elf_link_hash_entry *h = (struct elf_link_hash_entry *) bh; struct elf_outext_info *eoinfo = (struct elf_outext_info *) data; struct elf_final_link_info *finfo = eoinfo->finfo; bfd_boolean strip; @@ -8654,10 +8659,11 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) /* We should also warn if a forced local symbol is referenced from shared libraries. */ - if (! finfo->info->relocatable - && (! finfo->info->shared) + if (!finfo->info->relocatable + && finfo->info->executable && h->forced_local && h->ref_dynamic + && h->def_regular && !h->dynamic_def && !h->dynamic_weak && ! elf_link_check_versioned_symbol (finfo->info, bed, h)) @@ -8699,10 +8705,17 @@ elf_link_output_extsym (struct elf_link_hash_entry *h, void *data) && bfd_hash_lookup (finfo->info->keep_hash, h->root.root.string, FALSE, FALSE) == NULL) strip = TRUE; - else if (finfo->info->strip_discarded - && (h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && elf_discarded_section (h->root.u.def.section)) + else if ((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && ((finfo->info->strip_discarded + && elf_discarded_section (h->root.u.def.section)) + || (h->root.u.def.section->owner != NULL + && (h->root.u.def.section->owner->flags & BFD_PLUGIN) != 0))) + strip = TRUE; + else if ((h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak) + && h->root.u.undef.abfd != NULL + && (h->root.u.undef.abfd->flags & BFD_PLUGIN) != 0) strip = TRUE; else strip = FALSE; @@ -9101,6 +9114,9 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) asection *o; const struct elf_backend_data *bed; struct elf_link_hash_entry **sym_hashes; + bfd_size_type address_size; + bfd_vma r_type_mask; + int r_sym_shift; output_bfd = finfo->output_bfd; bed = get_elf_backend_data (output_bfd); @@ -9271,6 +9287,19 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) *pindex = indx; } + if (bed->s->arch_size == 32) + { + r_type_mask = 0xff; + r_sym_shift = 8; + address_size = 4; + } + else + { + r_type_mask = 0xffffffff; + r_sym_shift = 32; + address_size = 8; + } + /* Relocate the contents of each section. */ sym_hashes = elf_sym_hashes (input_bfd); for (o = input_bfd->sections; o != NULL; o = o->next) @@ -9375,8 +9404,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) { Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *rel, *relend; - bfd_vma r_type_mask; - int r_sym_shift; int action_discarded; int ret; @@ -9388,15 +9415,27 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) && o->reloc_count > 0) return FALSE; - if (bed->s->arch_size == 32) - { - r_type_mask = 0xff; - r_sym_shift = 8; - } - else + /* We need to reverse-copy input .ctors/.dtors sections if + they are placed in .init_array/.finit_array for output. */ + if (o->size > address_size + && ((strncmp (o->name, ".ctors", 6) == 0 + && strcmp (o->output_section->name, + ".init_array") == 0) + || (strncmp (o->name, ".dtors", 6) == 0 + && strcmp (o->output_section->name, + ".fini_array") == 0)) + && (o->name[6] == 0 || o->name[6] == '.')) { - r_type_mask = 0xffffffff; - r_sym_shift = 32; + if (o->size != o->reloc_count * address_size) + { + (*_bfd_error_handler) + (_("error: %B: size of section %A is not " + "multiple of address size"), + input_bfd, o); + bfd_set_error (bfd_error_on_input); + return FALSE; + } + o->flags |= SEC_ELF_REVERSE_COPY; } action_discarded = -1; @@ -9857,12 +9896,34 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd) default: { /* FIXME: octets_per_byte. */ - if (! (o->flags & SEC_EXCLUDE) - && ! bfd_set_section_contents (output_bfd, o->output_section, - contents, - (file_ptr) o->output_offset, - o->size)) - return FALSE; + if (! (o->flags & SEC_EXCLUDE)) + { + file_ptr offset = (file_ptr) o->output_offset; + bfd_size_type todo = o->size; + if ((o->flags & SEC_ELF_REVERSE_COPY)) + { + /* Reverse-copy input section to output. */ + do + { + todo -= address_size; + if (! bfd_set_section_contents (output_bfd, + o->output_section, + contents + todo, + offset, + address_size)) + return FALSE; + if (todo == 0) + break; + offset += address_size; + } + while (1); + } + else if (! bfd_set_section_contents (output_bfd, + o->output_section, + contents, + offset, todo)) + return FALSE; + } } break; } @@ -10751,8 +10812,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) eoinfo.failed = FALSE; eoinfo.finfo = &finfo; eoinfo.localsyms = TRUE; - elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym, - &eoinfo); + bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; @@ -10861,8 +10921,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) eoinfo.failed = FALSE; eoinfo.localsyms = FALSE; eoinfo.finfo = &finfo; - elf_link_hash_traverse (elf_hash_table (info), elf_link_output_extsym, - &eoinfo); + bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo); if (eoinfo.failed) return FALSE; @@ -11078,6 +11137,13 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) (_("%B: could not find output section %s"), abfd, name); goto error_return; } + if (elf_section_data (o->output_section)->this_hdr.sh_type == SHT_NOTE) + { + (*_bfd_error_handler) + (_("warning: section '%s' is being made into a note"), name); + bfd_set_error (bfd_error_nonrepresentable_section); + goto error_return; + } dyn.d_un.d_ptr = o->vma; break; @@ -11122,14 +11188,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) goto error_return; /* Check for DT_TEXTREL (late, in case the backend removes it). */ - if (info->warn_shared_textrel && info->shared) + if (((info->warn_shared_textrel && info->shared) + || info->error_textrel) + && (o = bfd_get_section_by_name (dynobj, ".dynamic")) != NULL) { bfd_byte *dyncon, *dynconend; - /* Fix up .dynamic entries. */ - o = bfd_get_section_by_name (dynobj, ".dynamic"); - BFD_ASSERT (o != NULL); - dyncon = o->contents; dynconend = o->contents + o->size; for (; dyncon < dynconend; dyncon += bed->s->sizeof_dyn) @@ -11140,8 +11204,12 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) if (dyn.d_tag == DT_TEXTREL) { - info->callbacks->einfo - (_("%P: warning: creating a DT_TEXTREL in a shared object.\n")); + if (info->error_textrel) + info->callbacks->einfo + (_("%P%X: read-only segment has dynamic relocations.\n")); + else + info->callbacks->einfo + (_("%P: warning: creating a DT_TEXTREL in a shared object.\n")); break; } } @@ -11165,7 +11233,7 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) continue; if ((elf_section_data (o->output_section)->this_hdr.sh_type != SHT_STRTAB) - || strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0) + && (strcmp (bfd_get_section_name (abfd, o), ".dynstr") != 0)) { /* FIXME: octets_per_byte. */ if (! bfd_set_section_contents (abfd, o->output_section, @@ -11506,6 +11574,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_info *info, asection *sec, while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; + h->mark = 1; return (*gc_mark_hook) (sec, info, cookie->rel, h, NULL); } @@ -11597,6 +11666,50 @@ _bfd_elf_gc_mark (struct bfd_link_info *info, return ret; } +/* Keep debug and special sections. */ + +bfd_boolean +_bfd_elf_gc_mark_extra_sections (struct bfd_link_info *info, + elf_gc_mark_hook_fn mark_hook ATTRIBUTE_UNUSED) +{ + bfd *ibfd; + + for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next) + { + asection *isec; + bfd_boolean some_kept; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour) + continue; + + /* Ensure all linker created sections are kept, and see whether + any other section is already marked. */ + some_kept = FALSE; + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + { + if ((isec->flags & SEC_LINKER_CREATED) != 0) + isec->gc_mark = 1; + else if (isec->gc_mark) + some_kept = TRUE; + } + + /* If no section in this file will be kept, then we can + toss out debug sections. */ + if (!some_kept) + continue; + + /* Keep debug and special sections like .comment when they are + not part of a group, or when we have single-member groups. */ + for (isec = ibfd->sections; isec != NULL; isec = isec->next) + if ((elf_next_in_group (isec) == NULL + || elf_next_in_group (isec) == isec) + && ((isec->flags & SEC_DEBUGGING) != 0 + || (isec->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0)) + isec->gc_mark = 1; + } + return TRUE; +} + /* Sweep symbols in swept sections. Called via elf_link_hash_traverse. */ struct elf_gc_sweep_symbol_info @@ -11609,17 +11722,21 @@ struct elf_gc_sweep_symbol_info static bfd_boolean elf_gc_sweep_symbol (struct elf_link_hash_entry *h, void *data) { - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && !h->root.u.def.section->gc_mark - && !(h->root.u.def.section->owner->flags & DYNAMIC)) + if (!h->mark + && (((h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && !(h->def_regular + && h->root.u.def.section->gc_mark)) + || h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak)) { - struct elf_gc_sweep_symbol_info *inf = - (struct elf_gc_sweep_symbol_info *) data; + struct elf_gc_sweep_symbol_info *inf; + + inf = (struct elf_gc_sweep_symbol_info *) data; (*inf->hide_symbol) (inf->info, h, TRUE); + h->def_regular = 0; + h->ref_regular = 0; + h->ref_regular_nonweak = 0; } return TRUE; @@ -11657,13 +11774,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) asection *first = elf_next_in_group (o); o->gc_mark = first->gc_mark; } - else if ((o->flags & (SEC_DEBUGGING | SEC_LINKER_CREATED)) != 0 - || (o->flags & (SEC_ALLOC | SEC_LOAD | SEC_RELOC)) == 0 - || elf_section_data (o)->this_hdr.sh_type == SHT_NOTE) - { - /* Keep debug, special and SHT_NOTE sections. */ - o->gc_mark = 1; - } if (o->gc_mark) continue; @@ -11724,9 +11834,6 @@ elf_gc_sweep (bfd *abfd, struct bfd_link_info *info) static bfd_boolean elf_gc_propagate_vtable_entries_used (struct elf_link_hash_entry *h, void *okp) { - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Those that are not vtables. */ if (h->vtable == NULL || h->vtable->parent == NULL) return TRUE; @@ -11788,9 +11895,6 @@ elf_gc_smash_unused_vtentry_relocs (struct elf_link_hash_entry *h, void *okp) const struct elf_backend_data *bed; unsigned int log_file_align; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - /* Take care of both those symbols that do not describe vtables as well as those that are not loaded. */ if (h->vtable == NULL || h->vtable->parent == NULL) @@ -11838,16 +11942,16 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf) { struct bfd_link_info *info = (struct bfd_link_info *) inf; - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if ((h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && (h->ref_dynamic - || (!info->executable + || ((!info->executable || info->export_dynamic) && h->def_regular && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL - && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN))) + && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN + && (strchr (h->root.root.string, ELF_VER_CHR) != NULL + || !bfd_hide_sym_by_version (info->version_info, + h->root.root.string))))) h->root.u.def.section->flags |= SEC_KEEP; return TRUE; @@ -11943,15 +12047,23 @@ bfd_elf_gc_sections (bfd *abfd, struct bfd_link_info *info) if (bfd_get_flavour (sub) != bfd_target_elf_flavour) continue; + /* Start at sections marked with SEC_KEEP (ref _bfd_elf_gc_keep). + Also treat note sections as a root, if the section is not part + of a group. */ for (o = sub->sections; o != NULL; o = o->next) - if ((o->flags & (SEC_EXCLUDE | SEC_KEEP)) == SEC_KEEP && !o->gc_mark) - if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) - return FALSE; + if (!o->gc_mark + && (o->flags & SEC_EXCLUDE) == 0 + && ((o->flags & SEC_KEEP) != 0 + || (elf_section_data (o)->this_hdr.sh_type == SHT_NOTE + && elf_next_in_group (o) == NULL ))) + { + if (!_bfd_elf_gc_mark (info, o, gc_mark_hook)) + return FALSE; + } } /* Allow the backend to mark additional target specific sections. */ - if (bed->gc_mark_extra_sections) - bed->gc_mark_extra_sections (info, gc_mark_hook); + bed->gc_mark_extra_sections (info, gc_mark_hook); /* ... and mark SEC_EXCLUDE for those that go. */ return elf_gc_sweep (abfd, info); @@ -12094,6 +12206,83 @@ bfd_elf_gc_record_vtentry (bfd *abfd ATTRIBUTE_UNUSED, return TRUE; } +/* Map an ELF section header flag to its corresponding string. */ +typedef struct +{ + char *flag_name; + flagword flag_value; +} elf_flags_to_name_table; + +static elf_flags_to_name_table elf_flags_to_names [] = +{ + { "SHF_WRITE", SHF_WRITE }, + { "SHF_ALLOC", SHF_ALLOC }, + { "SHF_EXECINSTR", SHF_EXECINSTR }, + { "SHF_MERGE", SHF_MERGE }, + { "SHF_STRINGS", SHF_STRINGS }, + { "SHF_INFO_LINK", SHF_INFO_LINK}, + { "SHF_LINK_ORDER", SHF_LINK_ORDER}, + { "SHF_OS_NONCONFORMING", SHF_OS_NONCONFORMING}, + { "SHF_GROUP", SHF_GROUP }, + { "SHF_TLS", SHF_TLS }, + { "SHF_MASKOS", SHF_MASKOS }, + { "SHF_EXCLUDE", SHF_EXCLUDE }, +}; + +void +bfd_elf_lookup_section_flags (struct bfd_link_info *info, + struct flag_info *finfo) +{ + bfd *output_bfd = info->output_bfd; + const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); + struct flag_info_list *tf = finfo->flag_list; + int with_hex = 0; + int without_hex = 0; + + for (tf = finfo->flag_list; tf != NULL; tf = tf->next) + { + int i; + if (bed->elf_backend_lookup_section_flags_hook) + { + flagword hexval = + (*bed->elf_backend_lookup_section_flags_hook) ((char *) tf->name); + + if (hexval != 0) + { + if (tf->with == with_flags) + with_hex |= hexval; + else if (tf->with == without_flags) + without_hex |= hexval; + tf->valid = TRUE; + continue; + } + } + for (i = 0; i < 12; i++) + { + if (!strcmp (tf->name, elf_flags_to_names[i].flag_name)) + { + if (tf->with == with_flags) + with_hex |= elf_flags_to_names[i].flag_value; + else if (tf->with == without_flags) + without_hex |= elf_flags_to_names[i].flag_value; + tf->valid = TRUE; + continue; + } + } + if (tf->valid == FALSE) + { + info->callbacks->einfo + (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name); + return; + } + } + finfo->flags_initialized = TRUE; + finfo->only_with_flags |= with_hex; + finfo->not_with_flags |= without_hex; + + return; +} + struct alloc_got_off_arg { bfd_vma gotoff; struct bfd_link_info *info; @@ -12109,9 +12298,6 @@ elf_gc_allocate_got_offsets (struct elf_link_hash_entry *h, void *arg) bfd *obfd = gofarg->info->output_bfd; const struct elf_backend_data *bed = get_elf_backend_data (obfd); - if (h->root.type == bfd_link_hash_warning) - h = (struct elf_link_hash_entry *) h->root.u.i.link; - if (h->got.refcount > 0) { h->got.offset = gofarg->gotoff; @@ -12354,139 +12540,69 @@ bfd_elf_discard_info (bfd *output_bfd, struct bfd_link_info *info) return ret; } -/* For a SHT_GROUP section, return the group signature. For other - sections, return the normal section name. */ - -static const char * -section_signature (asection *sec) -{ - if ((sec->flags & SEC_GROUP) != 0 - && elf_next_in_group (sec) != NULL - && elf_group_name (elf_next_in_group (sec)) != NULL) - return elf_group_name (elf_next_in_group (sec)); - return sec->name; -} - -void -_bfd_elf_section_already_linked (bfd *abfd, asection *sec, +bfd_boolean +_bfd_elf_section_already_linked (bfd *abfd, + asection *sec, struct bfd_link_info *info) { flagword flags; - const char *name, *p; + const char *name, *key; struct bfd_section_already_linked *l; struct bfd_section_already_linked_hash_entry *already_linked_list; if (sec->output_section == bfd_abs_section_ptr) - return; + return FALSE; flags = sec->flags; /* Return if it isn't a linkonce section. A comdat group section also has SEC_LINK_ONCE set. */ if ((flags & SEC_LINK_ONCE) == 0) - return; + return FALSE; /* Don't put group member sections on our list of already linked sections. They are handled as a group via their group section. */ if (elf_sec_group (sec) != NULL) - return; - - /* FIXME: When doing a relocatable link, we may have trouble - copying relocations in other sections that refer to local symbols - in the section being discarded. Those relocations will have to - be converted somehow; as of this writing I'm not sure that any of - the backends handle that correctly. - - It is tempting to instead not discard link once sections when - doing a relocatable link (technically, they should be discarded - whenever we are building constructors). However, that fails, - because the linker winds up combining all the link once sections - into a single large link once section, which defeats the purpose - of having link once sections in the first place. - - Also, not merging link once sections in a relocatable link - causes trouble for MIPS ELF, which relies on link once semantics - to handle the .reginfo section correctly. */ - - name = section_signature (sec); + return FALSE; - if (CONST_STRNEQ (name, ".gnu.linkonce.") - && (p = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) - p++; + /* For a SHT_GROUP section, use the group signature as the key. */ + name = sec->name; + if ((flags & SEC_GROUP) != 0 + && elf_next_in_group (sec) != NULL + && elf_group_name (elf_next_in_group (sec)) != NULL) + key = elf_group_name (elf_next_in_group (sec)); else - p = name; + { + /* Otherwise we should have a .gnu.linkonce.. section. */ + if (CONST_STRNEQ (name, ".gnu.linkonce.") + && (key = strchr (name + sizeof (".gnu.linkonce.") - 1, '.')) != NULL) + key++; + else + /* Must be a user linkonce section that doesn't follow gcc's + naming convention. In this case we won't be matching + single member groups. */ + key = name; + } - already_linked_list = bfd_section_already_linked_table_lookup (p); + already_linked_list = bfd_section_already_linked_table_lookup (key); for (l = already_linked_list->entry; l != NULL; l = l->next) { /* We may have 2 different types of sections on the list: group - sections and linkonce sections. Match like sections. */ - if ((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP) - && strcmp (name, section_signature (l->sec)) == 0 - && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL) + sections with a signature of ( is some string), + and linkonce sections named .gnu.linkonce... + Match like sections. LTO plugin sections are an exception. + They are always named .gnu.linkonce.t. and match either + type of section. */ + if (((flags & SEC_GROUP) == (l->sec->flags & SEC_GROUP) + && ((flags & SEC_GROUP) != 0 + || strcmp (name, l->sec->name) == 0)) + || (l->sec->owner->flags & BFD_PLUGIN) != 0) { /* The section has already been linked. See if we should issue a warning. */ - switch (flags & SEC_LINK_DUPLICATES) - { - default: - abort (); - - case SEC_LINK_DUPLICATES_DISCARD: - break; - - case SEC_LINK_DUPLICATES_ONE_ONLY: - (*_bfd_error_handler) - (_("%B: ignoring duplicate section `%A'"), - abfd, sec); - break; - - case SEC_LINK_DUPLICATES_SAME_SIZE: - if (sec->size != l->sec->size) - (*_bfd_error_handler) - (_("%B: duplicate section `%A' has different size"), - abfd, sec); - break; - - case SEC_LINK_DUPLICATES_SAME_CONTENTS: - if (sec->size != l->sec->size) - (*_bfd_error_handler) - (_("%B: duplicate section `%A' has different size"), - abfd, sec); - else if (sec->size != 0) - { - bfd_byte *sec_contents, *l_sec_contents; - - if (!bfd_malloc_and_get_section (abfd, sec, &sec_contents)) - (*_bfd_error_handler) - (_("%B: warning: could not read contents of section `%A'"), - abfd, sec); - else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec, - &l_sec_contents)) - (*_bfd_error_handler) - (_("%B: warning: could not read contents of section `%A'"), - l->sec->owner, l->sec); - else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0) - (*_bfd_error_handler) - (_("%B: warning: duplicate section `%A' has different contents"), - abfd, sec); - - if (sec_contents) - free (sec_contents); - if (l_sec_contents) - free (l_sec_contents); - } - break; - } - - /* Set the output_section field so that lang_add_section - does not create a lang_input_section structure for this - section. Since there might be a symbol in the section - being discarded, we must retain a pointer to the section - which we are really going to use. */ - sec->output_section = bfd_abs_section_ptr; - sec->kept_section = l->sec; + if (!_bfd_handle_already_linked (sec, l, info)) + return FALSE; if (flags & SEC_GROUP) { @@ -12505,13 +12621,12 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec, } } - return; + return TRUE; } } /* A single member comdat group section may be discarded by a linkonce section and vice versa. */ - if ((flags & SEC_GROUP) != 0) { asection *first = elf_next_in_group (sec); @@ -12520,7 +12635,6 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec, /* Check this single member group against linkonce sections. */ for (l = already_linked_list->entry; l != NULL; l = l->next) if ((l->sec->flags & SEC_GROUP) == 0 - && bfd_coff_get_comdat_section (l->sec->owner, l->sec) == NULL && bfd_elf_match_symbols_in_sections (l->sec, first, info)) { first->output_section = bfd_abs_section_ptr; @@ -12569,8 +12683,9 @@ _bfd_elf_section_already_linked (bfd *abfd, asection *sec, } /* This is the first section with this name. Record it. */ - if (! bfd_section_already_linked_table_insert (already_linked_list, sec)) + if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return sec->output_section == bfd_abs_section_ptr; } bfd_boolean diff --git a/contrib/gdb-7/bfd/elfxx-target.h b/contrib/gdb-7/bfd/elfxx-target.h index fab1b04ec3..96ecce308d 100644 --- a/contrib/gdb-7/bfd/elfxx-target.h +++ b/contrib/gdb-7/bfd/elfxx-target.h @@ -1,6 +1,7 @@ /* Target definitions for NN-bit ELF Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -142,7 +143,7 @@ #define elf_backend_gc_mark_hook _bfd_elf_gc_mark_hook #endif #ifndef elf_backend_gc_mark_extra_sections -#define elf_backend_gc_mark_extra_sections NULL +#define elf_backend_gc_mark_extra_sections _bfd_elf_gc_mark_extra_sections #endif #ifndef elf_backend_gc_sweep_hook #define elf_backend_gc_sweep_hook NULL @@ -173,6 +174,10 @@ #define bfd_elfNN_bfd_define_common_symbol bfd_generic_define_common_symbol #endif +#ifndef bfd_elfNN_bfd_lookup_section_flags +#define bfd_elfNN_bfd_lookup_section_flags bfd_elf_lookup_section_flags +#endif + #ifndef bfd_elfNN_bfd_make_debug_symbol #define bfd_elfNN_bfd_make_debug_symbol \ ((asymbol * (*) (bfd *, void *, unsigned long)) bfd_nullvoidptr) @@ -305,6 +310,10 @@ #define elf_info_to_howto_rel 0 #endif +#ifndef elf_backend_arch_data +#define elf_backend_arch_data NULL +#endif + #ifndef ELF_TARGET_ID #define ELF_TARGET_ID GENERIC_ELF_DATA #endif @@ -502,7 +511,7 @@ #define elf_backend_hide_symbol _bfd_elf_link_hash_hide_symbol #endif #ifndef elf_backend_fixup_symbol -#define elf_backend_fixup_symbol NULL +#define elf_backend_fixup_symbol NULL #endif #ifndef elf_backend_merge_symbol_attribute #define elf_backend_merge_symbol_attribute NULL @@ -528,6 +537,9 @@ #ifndef elf_backend_write_core_note #define elf_backend_write_core_note NULL #endif +#ifndef elf_backend_lookup_section_flags_hook +#define elf_backend_lookup_section_flags_hook NULL +#endif #ifndef elf_backend_reloc_type_class #define elf_backend_reloc_type_class _bfd_elf_reloc_type_class #endif @@ -643,6 +655,11 @@ #define elf_backend_is_function_type _bfd_elf_is_function_type #endif +#ifndef elf_match_priority +#define elf_match_priority \ + (ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0) +#endif + extern const struct elf_size_info _bfd_elfNN_size_info; static struct elf_backend_data elfNN_bed = @@ -655,6 +672,7 @@ static struct elf_backend_data elfNN_bed = ELF_MINPAGESIZE, /* minpagesize */ ELF_COMMONPAGESIZE, /* commonpagesize */ ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */ + elf_backend_arch_data, elf_info_to_howto, elf_info_to_howto_rel, elf_backend_sym_is_global, @@ -711,6 +729,7 @@ static struct elf_backend_data elfNN_bed = elf_backend_grok_prstatus, elf_backend_grok_psinfo, elf_backend_write_core_note, + elf_backend_lookup_section_flags_hook, elf_backend_reloc_type_class, elf_backend_discard_info, elf_backend_ignore_discarded_relocs, @@ -811,6 +830,8 @@ const bfd_target TARGET_BIG_SYM = Chapter 7 (Formats & Protocols), Archive section sets this as 15. */ 15, + elf_match_priority, + /* Routines to byte-swap various sized integers from the data sections */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, @@ -907,6 +928,8 @@ const bfd_target TARGET_LITTLE_SYM = Chapter 7 (Formats & Protocols), Archive section sets this as 15. */ 15, + elf_match_priority, + /* Routines to byte-swap various sized integers from the data sections */ bfd_getl64, bfd_getl_signed_64, bfd_putl64, bfd_getl32, bfd_getl_signed_32, bfd_putl32, diff --git a/contrib/gdb-7/bfd/format.c b/contrib/gdb-7/bfd/format.c index 4d89a85e0a..66b9051efe 100644 --- a/contrib/gdb-7/bfd/format.c +++ b/contrib/gdb-7/bfd/format.c @@ -121,8 +121,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) extern const bfd_target binary_vec; const bfd_target * const *target; const bfd_target **matching_vector = NULL; - const bfd_target *save_targ, *right_targ, *ar_right_targ; - int match_count; + const bfd_target *save_targ, *right_targ, *ar_right_targ, *match_targ; + int match_count, best_count, best_match; int ar_match_index; if (matching != NULL) @@ -156,6 +156,9 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) right_targ = 0; ar_right_targ = 0; + match_targ = 0; + best_match = 256; + best_count = 0; /* Presume the answer is yes. */ abfd->format = format; @@ -194,7 +197,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) /* Don't check the default target twice. */ if (*target == &binary_vec - || (!abfd->target_defaulted && *target == save_targ)) + || (!abfd->target_defaulted && *target == save_targ) + || (*target)->match_priority > best_match) continue; abfd->xvec = *target; /* Change BFD's target temporarily. */ @@ -209,6 +213,8 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) bfd_set_error (bfd_error_wrong_format); temp = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); + if (temp) + match_targ = temp; if (temp && (abfd->format != bfd_archive || bfd_has_map (abfd))) { @@ -219,14 +225,18 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) targets might match. People who want those other targets have to set the GNUTARGET variable. */ if (temp == bfd_default_vector[0]) - { - match_count = 1; - break; - } + goto ok_ret; if (matching_vector) matching_vector[match_count] = temp; match_count++; + + if (temp->match_priority < best_match) + { + best_match = temp->match_priority; + best_count = 0; + } + best_count++; } else if (temp || (err = bfd_get_error ()) == bfd_error_wrong_object_format @@ -245,6 +255,9 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) goto err_ret; } + if (best_count == 1) + match_count = 1; + if (match_count == 0) { /* Try partial matches. */ @@ -287,9 +300,18 @@ bfd_check_format_matches (bfd *abfd, bfd_format format, char ***matching) if (match_count == 1) { - ok_ret: - abfd->xvec = right_targ; /* Change BFD's target permanently. */ + abfd->xvec = right_targ; + /* If we come out of the loop knowing that the last target that + matched is the one we want, then ABFD should still be in a usable + state (except possibly for XVEC). */ + if (match_targ != right_targ) + { + if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) + goto err_ret; + match_targ = BFD_SEND_FMT (abfd, _bfd_check_format, (abfd)); + } + ok_ret: /* If the file was opened for update, then `output_has_begun' some time ago when the file was created. Do not recompute sections sizes or alignments in _bfd_set_section_contents. diff --git a/contrib/gdb-7/bfd/hash.c b/contrib/gdb-7/bfd/hash.c index e2fa3a9138..1de2c2a85b 100644 --- a/contrib/gdb-7/bfd/hash.c +++ b/contrib/gdb-7/bfd/hash.c @@ -1,6 +1,6 @@ /* hash.c -- hash table routines for BFD Copyright 1993, 1994, 1995, 1997, 1999, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2009, 2010 Free Software Foundation, Inc. + 2006, 2007, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Steve Chamberlain This file is part of BFD, the Binary File Descriptor library. @@ -310,28 +310,37 @@ higher_prime_number (unsigned long n) { /* These are primes that are near, but slightly smaller than, a power of two. */ - static const unsigned long primes[] = { - (unsigned long) 127, - (unsigned long) 2039, - (unsigned long) 32749, - (unsigned long) 65521, - (unsigned long) 131071, - (unsigned long) 262139, - (unsigned long) 524287, - (unsigned long) 1048573, - (unsigned long) 2097143, - (unsigned long) 4194301, - (unsigned long) 8388593, - (unsigned long) 16777213, - (unsigned long) 33554393, - (unsigned long) 67108859, - (unsigned long) 134217689, - (unsigned long) 268435399, - (unsigned long) 536870909, - (unsigned long) 1073741789, - (unsigned long) 2147483647, + static const unsigned long primes[] = + { + (unsigned long) 31, + (unsigned long) 61, + (unsigned long) 127, + (unsigned long) 251, + (unsigned long) 509, + (unsigned long) 1021, + (unsigned long) 2039, + (unsigned long) 4093, + (unsigned long) 8191, + (unsigned long) 16381, + (unsigned long) 32749, + (unsigned long) 65521, + (unsigned long) 131071, + (unsigned long) 262139, + (unsigned long) 524287, + (unsigned long) 1048573, + (unsigned long) 2097143, + (unsigned long) 4194301, + (unsigned long) 8388593, + (unsigned long) 16777213, + (unsigned long) 33554393, + (unsigned long) 67108859, + (unsigned long) 134217689, + (unsigned long) 268435399, + (unsigned long) 536870909, + (unsigned long) 1073741789, + (unsigned long) 2147483647, /* 4294967291L */ - ((unsigned long) 2147483647) + ((unsigned long) 2147483644), + ((unsigned long) 2147483647) + ((unsigned long) 2147483644), }; const unsigned long *low = &primes[0]; @@ -352,7 +361,7 @@ higher_prime_number (unsigned long n) return *low; } -static size_t bfd_default_hash_table_size = DEFAULT_SIZE; +static unsigned long bfd_default_hash_table_size = DEFAULT_SIZE; /* Create a new hash table, given a number of entries. */ @@ -364,9 +373,15 @@ bfd_hash_table_init_n (struct bfd_hash_table *table, unsigned int entsize, unsigned int size) { - unsigned int alloc; + unsigned long alloc; - alloc = size * sizeof (struct bfd_hash_entry *); + alloc = size; + alloc *= sizeof (struct bfd_hash_entry *); + if (alloc / sizeof (struct bfd_hash_entry *) != size) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } table->memory = (void *) objalloc_create (); if (table->memory == NULL) @@ -645,15 +660,15 @@ bfd_hash_traverse (struct bfd_hash_table *table, table->frozen = 0; } -void -bfd_hash_set_default_size (bfd_size_type hash_size) +unsigned long +bfd_hash_set_default_size (unsigned long hash_size) { /* Extend this prime list if you want more granularity of hash table size. */ - static const bfd_size_type hash_size_primes[] = + static const unsigned long hash_size_primes[] = { - 251, 509, 1021, 2039, 4051, 8599, 16699, 32749 + 31, 61, 127, 251, 509, 1021, 2039, 4091, 8191, 16381, 32749, 65537 }; - size_t _index; + unsigned int _index; /* Work out best prime number near the hash_size. */ for (_index = 0; _index < ARRAY_SIZE (hash_size_primes) - 1; ++_index) @@ -661,6 +676,7 @@ bfd_hash_set_default_size (bfd_size_type hash_size) break; bfd_default_hash_table_size = hash_size_primes[_index]; + return bfd_default_hash_table_size; } /* A few different object file formats (a.out, COFF, ELF) use a string diff --git a/contrib/gdb-7/bfd/ihex.c b/contrib/gdb-7/bfd/ihex.c index 6a9816c0b5..09f756a1c2 100644 --- a/contrib/gdb-7/bfd/ihex.c +++ b/contrib/gdb-7/bfd/ihex.c @@ -1,6 +1,6 @@ /* BFD back-end for Intel Hex objects. Copyright 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2009 Free Software Foundation, Inc. + 2006, 2007, 2009, 2011 Free Software Foundation, Inc. Written by Ian Lance Taylor of Cygnus Support . This file is part of BFD, the Binary File Descriptor library. @@ -930,6 +930,7 @@ ihex_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED, #define ihex_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define ihex_bfd_relax_section bfd_generic_relax_section #define ihex_bfd_gc_sections bfd_generic_gc_sections +#define ihex_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define ihex_bfd_merge_sections bfd_generic_merge_sections #define ihex_bfd_is_group_section bfd_generic_is_group_section #define ihex_bfd_discard_group bfd_generic_discard_group @@ -957,6 +958,7 @@ const bfd_target ihex_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ diff --git a/contrib/gdb-7/bfd/libbfd.c b/contrib/gdb-7/bfd/libbfd.c index 8b24378456..44651cf9c3 100644 --- a/contrib/gdb-7/bfd/libbfd.c +++ b/contrib/gdb-7/bfd/libbfd.c @@ -431,9 +431,9 @@ DESCRIPTION .#define bfd_put_signed_8 \ . bfd_put_8 .#define bfd_get_8(abfd, ptr) \ -. (*(unsigned char *) (ptr) & 0xff) +. (*(const unsigned char *) (ptr) & 0xff) .#define bfd_get_signed_8(abfd, ptr) \ -. (((*(unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) +. (((*(const unsigned char *) (ptr) & 0xff) ^ 0x80) - 0x80) . .#define bfd_put_16(abfd, val, ptr) \ . BFD_SEND (abfd, bfd_putx16, ((val),(ptr))) @@ -866,7 +866,15 @@ _bfd_generic_get_section_contents (bfd *abfd, return FALSE; } - sz = section->rawsize ? section->rawsize : section->size; + /* We do allow reading of a section after bfd_final_link has + written the contents out to disk. In that situation, rawsize is + just a stale version of size, so ignore it. Otherwise we must be + reading an input section, where rawsize, if different to size, + is the on-disk size. */ + if (abfd->direction != write_direction && section->rawsize != 0) + sz = section->rawsize; + else + sz = section->size; if (offset + count < count || offset + count > sz) { @@ -919,7 +927,10 @@ _bfd_generic_get_section_contents_in_window w->data = w->i->data; return bfd_get_section_contents (abfd, section, w->data, offset, count); } - sz = section->rawsize ? section->rawsize : section->size; + if (abfd->direction != write_direction && section->rawsize != 0) + sz = section->rawsize; + else + sz = section->size; if (offset + count > sz || ! bfd_get_file_window (abfd, section->filepos + offset, count, w, TRUE)) @@ -968,8 +979,12 @@ bfd_log2 (bfd_vma x) { unsigned int result = 0; - while ((x = (x >> 1)) != 0) + if (x <= 1) + return result; + --x; + do ++result; + while ((x >>= 1) != 0); return result; } diff --git a/contrib/gdb-7/bfd/libbfd.h b/contrib/gdb-7/bfd/libbfd.h index 2e7df4f11c..d08c2ba829 100644 --- a/contrib/gdb-7/bfd/libbfd.h +++ b/contrib/gdb-7/bfd/libbfd.h @@ -8,7 +8,7 @@ Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 + 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -458,6 +458,9 @@ extern bfd_boolean _bfd_generic_set_section_contents #define _bfd_nolink_bfd_gc_sections \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) \ bfd_false) +#define _bfd_nolink_bfd_lookup_section_flags \ + ((void (*) (struct bfd_link_info *, struct flag_info *)) \ + bfd_0) #define _bfd_nolink_bfd_merge_sections \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *)) \ bfd_false) @@ -483,7 +486,8 @@ extern bfd_boolean _bfd_generic_set_section_contents #define _bfd_nolink_bfd_link_split_section \ ((bfd_boolean (*) (bfd *, struct bfd_section *)) bfd_false) #define _bfd_nolink_section_already_linked \ - ((void (*) (bfd *, struct bfd_section *, struct bfd_link_info *)) bfd_void) + ((bfd_boolean (*) (bfd *, asection *, \ + struct bfd_link_info *)) bfd_false) #define _bfd_nolink_bfd_define_common_symbol \ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, \ struct bfd_link_hash_entry *)) bfd_false) @@ -522,10 +526,21 @@ extern bfd_boolean _bfd_dwarf1_find_nearest_line (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, unsigned int *); +struct dwarf_debug_section +{ + const char *uncompressed_name; + const char *compressed_name; +}; + +/* Map of uncompressed DWARF debug section name to compressed one. It + is terminated by NULL uncompressed_name. */ + +extern const struct dwarf_debug_section dwarf_debug_sections[]; + /* Find the nearest line using DWARF 2 debugging information. */ extern bfd_boolean _bfd_dwarf2_find_nearest_line - (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, - unsigned int *, unsigned int, void **); + (bfd *, const struct dwarf_debug_section *, asection *, asymbol **, bfd_vma, + const char **, const char **, unsigned int *, unsigned int, void **); /* Find the line using DWARF 2 debugging information. */ extern bfd_boolean _bfd_dwarf2_find_line @@ -603,8 +618,8 @@ extern bfd_boolean _bfd_generic_final_link extern bfd_boolean _bfd_generic_link_split_section (bfd *, struct bfd_section *); -extern void _bfd_generic_section_already_linked - (bfd *, struct bfd_section *, struct bfd_link_info *); +extern bfd_boolean _bfd_generic_section_already_linked + (bfd *, asection *, struct bfd_link_info *); /* Generic reloc_link_order processing routine. */ extern bfd_boolean _bfd_generic_reloc_link_order @@ -812,17 +827,6 @@ extern void bfd_section_already_linked_table_traverse extern bfd_vma read_unsigned_leb128 (bfd *, bfd_byte *, unsigned int *); extern bfd_signed_vma read_signed_leb128 (bfd *, bfd_byte *, unsigned int *); - -struct dwarf_debug_section -{ - const char *uncompressed_name; - const char *compressed_name; -}; - -/* Map of uncompressed DWARF debug section name to compressed one. It - is terminated by NULL uncompressed_name. */ - -extern struct dwarf_debug_section dwarf_debug_sections[]; /* Extracted from init.c. */ /* Extracted from libbfd.c. */ bfd_boolean bfd_write_bigendian_4byte_int (bfd *, unsigned int); @@ -850,9 +854,15 @@ struct bfd_iovec int (*bclose) (struct bfd *abfd); int (*bflush) (struct bfd *abfd); int (*bstat) (struct bfd *abfd, struct stat *sb); - /* Just like mmap: (void*)-1 on failure, mmapped address on success. */ + /* Mmap a part of the files. ADDR, LEN, PROT, FLAGS and OFFSET are the usual + mmap parameter, except that LEN and OFFSET do not need to be page + aligned. Returns (void *)-1 on failure, mmapped address on success. + Also write in MAP_ADDR the address of the page aligned buffer and in + MAP_LEN the size mapped (a page multiple). Use unmap with MAP_ADDR and + MAP_LEN to unmap. */ void *(*bmmap) (struct bfd *abfd, void *addr, bfd_size_type len, - int prot, int flags, file_ptr offset); + int prot, int flags, file_ptr offset, + void **map_addr, bfd_size_type *map_len); }; extern const struct bfd_iovec _bfd_memory_iovec; /* Extracted from bfdwin.c. */ @@ -1062,6 +1072,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ALPHA_TPREL_LO16", "BFD_RELOC_ALPHA_TPREL16", "BFD_RELOC_MIPS_JMP", + "BFD_RELOC_MICROMIPS_JMP", "BFD_RELOC_MIPS16_JMP", "BFD_RELOC_MIPS16_GPREL", "BFD_RELOC_HI16", @@ -1076,40 +1087,69 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MIPS16_HI16_S", "BFD_RELOC_MIPS16_LO16", "BFD_RELOC_MIPS_LITERAL", + "BFD_RELOC_MICROMIPS_LITERAL", + "BFD_RELOC_MICROMIPS_7_PCREL_S1", + "BFD_RELOC_MICROMIPS_10_PCREL_S1", + "BFD_RELOC_MICROMIPS_16_PCREL_S1", + "BFD_RELOC_MICROMIPS_GPREL16", + "BFD_RELOC_MICROMIPS_HI16", + "BFD_RELOC_MICROMIPS_HI16_S", + "BFD_RELOC_MICROMIPS_LO16", "BFD_RELOC_MIPS_GOT16", + "BFD_RELOC_MICROMIPS_GOT16", "BFD_RELOC_MIPS_CALL16", + "BFD_RELOC_MICROMIPS_CALL16", "BFD_RELOC_MIPS_GOT_HI16", + "BFD_RELOC_MICROMIPS_GOT_HI16", "BFD_RELOC_MIPS_GOT_LO16", + "BFD_RELOC_MICROMIPS_GOT_LO16", "BFD_RELOC_MIPS_CALL_HI16", + "BFD_RELOC_MICROMIPS_CALL_HI16", "BFD_RELOC_MIPS_CALL_LO16", + "BFD_RELOC_MICROMIPS_CALL_LO16", "BFD_RELOC_MIPS_SUB", + "BFD_RELOC_MICROMIPS_SUB", "BFD_RELOC_MIPS_GOT_PAGE", + "BFD_RELOC_MICROMIPS_GOT_PAGE", "BFD_RELOC_MIPS_GOT_OFST", + "BFD_RELOC_MICROMIPS_GOT_OFST", "BFD_RELOC_MIPS_GOT_DISP", + "BFD_RELOC_MICROMIPS_GOT_DISP", "BFD_RELOC_MIPS_SHIFT5", "BFD_RELOC_MIPS_SHIFT6", "BFD_RELOC_MIPS_INSERT_A", "BFD_RELOC_MIPS_INSERT_B", "BFD_RELOC_MIPS_DELETE", "BFD_RELOC_MIPS_HIGHEST", + "BFD_RELOC_MICROMIPS_HIGHEST", "BFD_RELOC_MIPS_HIGHER", + "BFD_RELOC_MICROMIPS_HIGHER", "BFD_RELOC_MIPS_SCN_DISP", + "BFD_RELOC_MICROMIPS_SCN_DISP", "BFD_RELOC_MIPS_REL16", "BFD_RELOC_MIPS_RELGOT", "BFD_RELOC_MIPS_JALR", + "BFD_RELOC_MICROMIPS_JALR", "BFD_RELOC_MIPS_TLS_DTPMOD32", "BFD_RELOC_MIPS_TLS_DTPREL32", "BFD_RELOC_MIPS_TLS_DTPMOD64", "BFD_RELOC_MIPS_TLS_DTPREL64", "BFD_RELOC_MIPS_TLS_GD", + "BFD_RELOC_MICROMIPS_TLS_GD", "BFD_RELOC_MIPS_TLS_LDM", + "BFD_RELOC_MICROMIPS_TLS_LDM", "BFD_RELOC_MIPS_TLS_DTPREL_HI16", + "BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16", "BFD_RELOC_MIPS_TLS_DTPREL_LO16", + "BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16", "BFD_RELOC_MIPS_TLS_GOTTPREL", + "BFD_RELOC_MICROMIPS_TLS_GOTTPREL", "BFD_RELOC_MIPS_TLS_TPREL32", "BFD_RELOC_MIPS_TLS_TPREL64", "BFD_RELOC_MIPS_TLS_TPREL_HI16", + "BFD_RELOC_MICROMIPS_TLS_TPREL_HI16", "BFD_RELOC_MIPS_TLS_TPREL_LO16", + "BFD_RELOC_MICROMIPS_TLS_TPREL_LO16", "BFD_RELOC_MIPS_COPY", "BFD_RELOC_MIPS_JUMP_SLOT", @@ -1794,6 +1834,38 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_AVR_LDI", "BFD_RELOC_AVR_6", "BFD_RELOC_AVR_6_ADIW", + "BFD_RELOC_RL78_NEG8", + "BFD_RELOC_RL78_NEG16", + "BFD_RELOC_RL78_NEG24", + "BFD_RELOC_RL78_NEG32", + "BFD_RELOC_RL78_16_OP", + "BFD_RELOC_RL78_24_OP", + "BFD_RELOC_RL78_32_OP", + "BFD_RELOC_RL78_8U", + "BFD_RELOC_RL78_16U", + "BFD_RELOC_RL78_24U", + "BFD_RELOC_RL78_DIR3U_PCREL", + "BFD_RELOC_RL78_DIFF", + "BFD_RELOC_RL78_GPRELB", + "BFD_RELOC_RL78_GPRELW", + "BFD_RELOC_RL78_GPRELL", + "BFD_RELOC_RL78_SYM", + "BFD_RELOC_RL78_OP_SUBTRACT", + "BFD_RELOC_RL78_OP_NEG", + "BFD_RELOC_RL78_OP_AND", + "BFD_RELOC_RL78_OP_SHRA", + "BFD_RELOC_RL78_ABS8", + "BFD_RELOC_RL78_ABS16", + "BFD_RELOC_RL78_ABS16_REV", + "BFD_RELOC_RL78_ABS32", + "BFD_RELOC_RL78_ABS32_REV", + "BFD_RELOC_RL78_ABS16U", + "BFD_RELOC_RL78_ABS16UW", + "BFD_RELOC_RL78_ABS16UL", + "BFD_RELOC_RL78_RELAX", + "BFD_RELOC_RL78_HI16", + "BFD_RELOC_RL78_HI8", + "BFD_RELOC_RL78_LO16", "BFD_RELOC_RX_NEG8", "BFD_RELOC_RX_NEG16", "BFD_RELOC_RX_NEG24", @@ -2268,6 +2340,181 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_MICROBLAZE_64_GOTOFF", "BFD_RELOC_MICROBLAZE_32_GOTOFF", "BFD_RELOC_MICROBLAZE_COPY", + "BFD_RELOC_TILEPRO_COPY", + "BFD_RELOC_TILEPRO_GLOB_DAT", + "BFD_RELOC_TILEPRO_JMP_SLOT", + "BFD_RELOC_TILEPRO_RELATIVE", + "BFD_RELOC_TILEPRO_BROFF_X1", + "BFD_RELOC_TILEPRO_JOFFLONG_X1", + "BFD_RELOC_TILEPRO_JOFFLONG_X1_PLT", + "BFD_RELOC_TILEPRO_IMM8_X0", + "BFD_RELOC_TILEPRO_IMM8_Y0", + "BFD_RELOC_TILEPRO_IMM8_X1", + "BFD_RELOC_TILEPRO_IMM8_Y1", + "BFD_RELOC_TILEPRO_DEST_IMM8_X1", + "BFD_RELOC_TILEPRO_MT_IMM15_X1", + "BFD_RELOC_TILEPRO_MF_IMM15_X1", + "BFD_RELOC_TILEPRO_IMM16_X0", + "BFD_RELOC_TILEPRO_IMM16_X1", + "BFD_RELOC_TILEPRO_IMM16_X0_LO", + "BFD_RELOC_TILEPRO_IMM16_X1_LO", + "BFD_RELOC_TILEPRO_IMM16_X0_HI", + "BFD_RELOC_TILEPRO_IMM16_X1_HI", + "BFD_RELOC_TILEPRO_IMM16_X0_HA", + "BFD_RELOC_TILEPRO_IMM16_X1_HA", + "BFD_RELOC_TILEPRO_IMM16_X0_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X1_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X0_LO_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X1_LO_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X0_HI_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X1_HI_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X0_HA_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X1_HA_PCREL", + "BFD_RELOC_TILEPRO_IMM16_X0_GOT", + "BFD_RELOC_TILEPRO_IMM16_X1_GOT", + "BFD_RELOC_TILEPRO_IMM16_X0_GOT_LO", + "BFD_RELOC_TILEPRO_IMM16_X1_GOT_LO", + "BFD_RELOC_TILEPRO_IMM16_X0_GOT_HI", + "BFD_RELOC_TILEPRO_IMM16_X1_GOT_HI", + "BFD_RELOC_TILEPRO_IMM16_X0_GOT_HA", + "BFD_RELOC_TILEPRO_IMM16_X1_GOT_HA", + "BFD_RELOC_TILEPRO_MMSTART_X0", + "BFD_RELOC_TILEPRO_MMEND_X0", + "BFD_RELOC_TILEPRO_MMSTART_X1", + "BFD_RELOC_TILEPRO_MMEND_X1", + "BFD_RELOC_TILEPRO_SHAMT_X0", + "BFD_RELOC_TILEPRO_SHAMT_X1", + "BFD_RELOC_TILEPRO_SHAMT_Y0", + "BFD_RELOC_TILEPRO_SHAMT_Y1", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_LO", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_LO", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_HI", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_HI", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_HA", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_HA", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_LO", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_LO", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_HI", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_HI", + "BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_HA", + "BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_HA", + "BFD_RELOC_TILEPRO_TLS_DTPMOD32", + "BFD_RELOC_TILEPRO_TLS_DTPOFF32", + "BFD_RELOC_TILEPRO_TLS_TPOFF32", + "BFD_RELOC_TILEGX_HW0", + "BFD_RELOC_TILEGX_HW1", + "BFD_RELOC_TILEGX_HW2", + "BFD_RELOC_TILEGX_HW3", + "BFD_RELOC_TILEGX_HW0_LAST", + "BFD_RELOC_TILEGX_HW1_LAST", + "BFD_RELOC_TILEGX_HW2_LAST", + "BFD_RELOC_TILEGX_COPY", + "BFD_RELOC_TILEGX_GLOB_DAT", + "BFD_RELOC_TILEGX_JMP_SLOT", + "BFD_RELOC_TILEGX_RELATIVE", + "BFD_RELOC_TILEGX_BROFF_X1", + "BFD_RELOC_TILEGX_JUMPOFF_X1", + "BFD_RELOC_TILEGX_JUMPOFF_X1_PLT", + "BFD_RELOC_TILEGX_IMM8_X0", + "BFD_RELOC_TILEGX_IMM8_Y0", + "BFD_RELOC_TILEGX_IMM8_X1", + "BFD_RELOC_TILEGX_IMM8_Y1", + "BFD_RELOC_TILEGX_DEST_IMM8_X1", + "BFD_RELOC_TILEGX_MT_IMM14_X1", + "BFD_RELOC_TILEGX_MF_IMM14_X1", + "BFD_RELOC_TILEGX_MMSTART_X0", + "BFD_RELOC_TILEGX_MMEND_X0", + "BFD_RELOC_TILEGX_SHAMT_X0", + "BFD_RELOC_TILEGX_SHAMT_X1", + "BFD_RELOC_TILEGX_SHAMT_Y0", + "BFD_RELOC_TILEGX_SHAMT_Y1", + "BFD_RELOC_TILEGX_IMM16_X0_HW0", + "BFD_RELOC_TILEGX_IMM16_X1_HW0", + "BFD_RELOC_TILEGX_IMM16_X0_HW1", + "BFD_RELOC_TILEGX_IMM16_X1_HW1", + "BFD_RELOC_TILEGX_IMM16_X0_HW2", + "BFD_RELOC_TILEGX_IMM16_X1_HW2", + "BFD_RELOC_TILEGX_IMM16_X0_HW3", + "BFD_RELOC_TILEGX_IMM16_X1_HW3", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW3_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW3_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_PCREL", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_PCREL", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW3_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW3_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_GOT", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_GOT", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW3_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW3_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_TLS_GD", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X0_HW3_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW3_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_TLS_IE", + "BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_TLS_IE", + "BFD_RELOC_TILEGX_TLS_DTPMOD64", + "BFD_RELOC_TILEGX_TLS_DTPOFF64", + "BFD_RELOC_TILEGX_TLS_TPOFF64", + "BFD_RELOC_TILEGX_TLS_DTPMOD32", + "BFD_RELOC_TILEGX_TLS_DTPOFF32", + "BFD_RELOC_TILEGX_TLS_TPOFF32", + "BFD_RELOC_EPIPHANY_SIMM8", + "BFD_RELOC_EPIPHANY_SIMM24", + "BFD_RELOC_EPIPHANY_HIGH", + "BFD_RELOC_EPIPHANY_LOW", + "BFD_RELOC_EPIPHANY_SIMM11", + "BFD_RELOC_EPIPHANY_IMM11", + "BFD_RELOC_EPIPHANY_IMM8", "@@overflow: BFD_RELOC_UNUSED@@", }; #endif @@ -2284,6 +2531,9 @@ bfd_boolean bfd_generic_relax_section bfd_boolean bfd_generic_gc_sections (bfd *, struct bfd_link_info *); +void bfd_generic_lookup_section_flags + (struct bfd_link_info *, struct flag_info *); + bfd_boolean bfd_generic_merge_sections (bfd *, struct bfd_link_info *); diff --git a/contrib/gdb-7/bfd/libcoff.h b/contrib/gdb-7/bfd/libcoff.h index 4f73f109de..8aef552701 100644 --- a/contrib/gdb-7/bfd/libcoff.h +++ b/contrib/gdb-7/bfd/libcoff.h @@ -4,7 +4,7 @@ /* BFD COFF object file private structure. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -322,6 +322,9 @@ extern void coff_mangle_symbols (bfd *); extern bfd_boolean coff_write_symbols (bfd *); +extern bfd_boolean coff_write_alien_symbol + (bfd *, asymbol *, struct internal_syment *, bfd_vma *, + bfd_size_type *, asection **, bfd_size_type *); extern bfd_boolean coff_write_linenumbers (bfd *); extern alent *coff_get_lineno @@ -351,6 +354,10 @@ extern asymbol *coff_bfd_make_debug_symbol extern bfd_boolean coff_find_nearest_line (bfd *, asection *, asymbol **, bfd_vma, const char **, const char **, unsigned int *); +struct dwarf_debug_section; +extern bfd_boolean coff_find_nearest_line_with_names + (bfd *, const struct dwarf_debug_section *, asection *, asymbol **, + bfd_vma, const char **, const char **, unsigned int *); extern bfd_boolean coff_find_inliner_info (bfd *, const char **, const char **, unsigned int *); extern int coff_sizeof_headers @@ -550,6 +557,8 @@ extern struct bfd_link_hash_table *_bfd_coff_link_hash_table_create (bfd *); extern const char *_bfd_coff_internal_syment_name (bfd *, const struct internal_syment *, char *); +extern bfd_boolean _bfd_coff_section_already_linked + (bfd *, asection *, struct bfd_link_info *); extern bfd_boolean _bfd_coff_link_add_symbols (bfd *, struct bfd_link_info *); extern bfd_boolean _bfd_coff_final_link @@ -563,7 +572,7 @@ extern bfd_boolean _bfd_coff_generic_relocate_section extern struct bfd_hash_entry *_bfd_coff_debug_merge_hash_newfunc (struct bfd_hash_entry *, struct bfd_hash_table *, const char *); extern bfd_boolean _bfd_coff_write_global_sym - (struct coff_link_hash_entry *, void *); + (struct bfd_hash_entry *, void *); extern bfd_boolean _bfd_coff_write_task_globals (struct coff_link_hash_entry *, void *); extern bfd_boolean _bfd_coff_link_input_bfd diff --git a/contrib/gdb-7/bfd/linker.c b/contrib/gdb-7/bfd/linker.c index 2b52ba9651..7a01e114a2 100644 --- a/contrib/gdb-7/bfd/linker.c +++ b/contrib/gdb-7/bfd/linker.c @@ -1,6 +1,6 @@ /* linker.c -- BFD linker routines Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Steve Chamberlain and Ian Lance Taylor, Cygnus Support @@ -465,10 +465,8 @@ _bfd_link_hash_newfunc (struct bfd_hash_entry *entry, struct bfd_link_hash_entry *h = (struct bfd_link_hash_entry *) entry; /* Initialize the local fields. */ - h->type = bfd_link_hash_new; - memset (&h->u.undef.next, 0, - (sizeof (struct bfd_link_hash_entry) - - offsetof (struct bfd_link_hash_entry, u.undef.next))); + memset ((char *) &h->root + sizeof (h->root), 0, + sizeof (*h) - sizeof (h->root)); } return entry; @@ -606,21 +604,32 @@ bfd_wrapped_link_hash_lookup (bfd *abfd, return bfd_link_hash_lookup (info->hash, string, create, copy, follow); } -/* Traverse a generic link hash table. The only reason this is not a - macro is to do better type checking. This code presumes that an - argument passed as a struct bfd_hash_entry * may be caught as a - struct bfd_link_hash_entry * with no explicit cast required on the - call. */ +/* Traverse a generic link hash table. Differs from bfd_hash_traverse + in the treatment of warning symbols. When warning symbols are + created they replace the real symbol, so you don't get to see the + real symbol in a bfd_hash_travere. This traversal calls func with + the real symbol. */ void bfd_link_hash_traverse - (struct bfd_link_hash_table *table, + (struct bfd_link_hash_table *htab, bfd_boolean (*func) (struct bfd_link_hash_entry *, void *), void *info) { - bfd_hash_traverse (&table->table, - (bfd_boolean (*) (struct bfd_hash_entry *, void *)) func, - info); + unsigned int i; + + htab->table.frozen = 1; + for (i = 0; i < htab->table.size; i++) + { + struct bfd_link_hash_entry *p; + + p = (struct bfd_link_hash_entry *) htab->table.table[i]; + for (; p != NULL; p = (struct bfd_link_hash_entry *) p->root.next) + if (!(*func) (p->type == bfd_link_hash_warning ? p->u.i.link : p, info)) + goto out; + } + out: + htab->table.frozen = 0; } /* Add a symbol to the linker hash table undefs list. */ @@ -1296,7 +1305,7 @@ generic_link_check_archive_element (bfd *abfd, else h->u.c.p->section = bfd_make_section_old_way (symbfd, p->section->name); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else { @@ -1568,6 +1577,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, struct bfd_link_hash_entry *h; bfd_boolean cycle; + BFD_ASSERT (section != NULL); + if (bfd_is_ind_section (section) || (flags & BSF_INDIRECT) != 0) row = INDR_ROW; @@ -1609,8 +1620,8 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, || (info->notice_hash != NULL && bfd_hash_lookup (info->notice_hash, name, FALSE, FALSE) != NULL)) { - if (! (*info->callbacks->notice) (info, h->root.string, abfd, section, - value)) + if (! (*info->callbacks->notice) (info, h, + abfd, section, value, flags, string)) return FALSE; } @@ -1643,7 +1654,6 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* Make a new weak undefined symbol. */ h->type = bfd_link_hash_undefweak; h->u.undef.abfd = abfd; - h->u.undef.weak = abfd; break; case CDEF: @@ -1651,9 +1661,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, previously common. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, h->root.string, - h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, - abfd, bfd_link_hash_defined, 0))) + (info, h, abfd, bfd_link_hash_defined, 0))) return FALSE; /* Fall through. */ case DEF: @@ -1758,13 +1766,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, if (section == bfd_com_section_ptr) { h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON"); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else if (section->owner != abfd) { h->u.c.p->section = bfd_make_section_old_way (abfd, section->name); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else h->u.c.p->section = section; @@ -1782,9 +1790,7 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, two sizes, and use the section required by the larger symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, h->root.string, - h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, - abfd, bfd_link_hash_common, value))) + (info, h, abfd, bfd_link_hash_common, value))) return FALSE; if (value > h->u.c.size) { @@ -1807,13 +1813,13 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, { h->u.c.p->section = bfd_make_section_old_way (abfd, "COMMON"); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else if (section->owner != abfd) { h->u.c.p->section = bfd_make_section_old_way (abfd, section->name); - h->u.c.p->section->flags = SEC_ALLOC; + h->u.c.p->section->flags |= SEC_ALLOC; } else h->u.c.p->section = section; @@ -1821,23 +1827,11 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, break; case CREF: - { - bfd *obfd; - - /* We have found a common definition for a symbol which - was already defined. FIXME: It would nice if we could - report the BFD which defined an indirect symbol, but we - don't have anywhere to store the information. */ - if (h->type == bfd_link_hash_defined - || h->type == bfd_link_hash_defweak) - obfd = h->u.def.section->owner; - else - obfd = NULL; - if (! ((*info->callbacks->multiple_common) - (info, h->root.string, obfd, h->type, 0, - abfd, bfd_link_hash_common, value))) - return FALSE; - } + /* We have found a common definition for a symbol which + was already defined. */ + if (! ((*info->callbacks->multiple_common) + (info, h, abfd, bfd_link_hash_common, value))) + return FALSE; break; case MIND: @@ -1848,47 +1842,16 @@ _bfd_generic_link_add_one_symbol (struct bfd_link_info *info, /* Fall through. */ case MDEF: /* Handle a multiple definition. */ - if (!info->allow_multiple_definition) - { - asection *msec = NULL; - bfd_vma mval = 0; - - switch (h->type) - { - case bfd_link_hash_defined: - msec = h->u.def.section; - mval = h->u.def.value; - break; - case bfd_link_hash_indirect: - msec = bfd_ind_section_ptr; - mval = 0; - break; - default: - abort (); - } - - /* Ignore a redefinition of an absolute symbol to the - same value; it's harmless. */ - if (h->type == bfd_link_hash_defined - && bfd_is_abs_section (msec) - && bfd_is_abs_section (section) - && value == mval) - break; - - if (! ((*info->callbacks->multiple_definition) - (info, h->root.string, msec->owner, msec, mval, - abfd, section, value))) - return FALSE; - } + if (! ((*info->callbacks->multiple_definition) + (info, h, abfd, section, value))) + return FALSE; break; case CIND: /* Create an indirect symbol from an existing common symbol. */ BFD_ASSERT (h->type == bfd_link_hash_common); if (! ((*info->callbacks->multiple_common) - (info, h->root.string, - h->u.c.p->section->owner, bfd_link_hash_common, h->u.c.size, - abfd, bfd_link_hash_indirect, 0))) + (info, h, abfd, bfd_link_hash_indirect, 0))) return FALSE; /* Fall through. */ case IND: @@ -2490,9 +2453,6 @@ _bfd_generic_link_write_global_symbol (struct generic_link_hash_entry *h, (struct generic_write_global_symbol_info *) data; asymbol *sym; - if (h->root.type == bfd_link_hash_warning) - h = (struct generic_link_hash_entry *) h->root.u.i.link; - if (h->written) return TRUE; @@ -2928,12 +2888,13 @@ FUNCTION bfd_section_already_linked SYNOPSIS - void bfd_section_already_linked (bfd *abfd, asection *sec, - struct bfd_link_info *info); + bfd_boolean bfd_section_already_linked (bfd *abfd, + asection *sec, + struct bfd_link_info *info); DESCRIPTION - Check if @var{sec} has been already linked during a reloceatable - or final link. + Check if @var{data} has been already linked during a reloceatable + or final link. Return TRUE if it has. .#define bfd_section_already_linked(abfd, sec, info) \ . BFD_SEND (abfd, _section_already_linked, (abfd, sec, info)) @@ -3027,20 +2988,109 @@ bfd_section_already_linked_table_free (void) bfd_hash_table_free (&_bfd_section_already_linked_table); } +/* Report warnings as appropriate for duplicate section SEC. + Return FALSE if we decide to keep SEC after all. */ + +bfd_boolean +_bfd_handle_already_linked (asection *sec, + struct bfd_section_already_linked *l, + struct bfd_link_info *info) +{ + switch (sec->flags & SEC_LINK_DUPLICATES) + { + default: + abort (); + + case SEC_LINK_DUPLICATES_DISCARD: + /* If we found an LTO IR match for this comdat group on + the first pass, replace it with the LTO output on the + second pass. We can't simply choose real object + files over IR because the first pass may contain a + mix of LTO and normal objects and we must keep the + first match, be it IR or real. */ + if (info->loading_lto_outputs + && (l->sec->owner->flags & BFD_PLUGIN) != 0) + { + l->sec = sec; + return FALSE; + } + break; + + case SEC_LINK_DUPLICATES_ONE_ONLY: + info->callbacks->einfo + (_("%B: ignoring duplicate section `%A'\n"), + sec->owner, sec); + break; + + case SEC_LINK_DUPLICATES_SAME_SIZE: + if ((l->sec->owner->flags & BFD_PLUGIN) != 0) + ; + else if (sec->size != l->sec->size) + info->callbacks->einfo + (_("%B: duplicate section `%A' has different size\n"), + sec->owner, sec); + break; + + case SEC_LINK_DUPLICATES_SAME_CONTENTS: + if ((l->sec->owner->flags & BFD_PLUGIN) != 0) + ; + else if (sec->size != l->sec->size) + info->callbacks->einfo + (_("%B: duplicate section `%A' has different size\n"), + sec->owner, sec); + else if (sec->size != 0) + { + bfd_byte *sec_contents, *l_sec_contents = NULL; + + if (!bfd_malloc_and_get_section (sec->owner, sec, &sec_contents)) + info->callbacks->einfo + (_("%B: could not read contents of section `%A'\n"), + sec->owner, sec); + else if (!bfd_malloc_and_get_section (l->sec->owner, l->sec, + &l_sec_contents)) + info->callbacks->einfo + (_("%B: could not read contents of section `%A'\n"), + l->sec->owner, l->sec); + else if (memcmp (sec_contents, l_sec_contents, sec->size) != 0) + info->callbacks->einfo + (_("%B: duplicate section `%A' has different contents\n"), + sec->owner, sec); + + if (sec_contents) + free (sec_contents); + if (l_sec_contents) + free (l_sec_contents); + } + break; + } + + /* Set the output_section field so that lang_add_section + does not create a lang_input_section structure for this + section. Since there might be a symbol in the section + being discarded, we must retain a pointer to the section + which we are really going to use. */ + sec->output_section = bfd_abs_section_ptr; + sec->kept_section = l->sec; + return TRUE; +} + /* This is used on non-ELF inputs. */ -void -_bfd_generic_section_already_linked (bfd *abfd, asection *sec, +bfd_boolean +_bfd_generic_section_already_linked (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, struct bfd_link_info *info) { - flagword flags; const char *name; struct bfd_section_already_linked *l; struct bfd_section_already_linked_hash_entry *already_linked_list; - flags = sec->flags; - if ((flags & SEC_LINK_ONCE) == 0) - return; + if ((sec->flags & SEC_LINK_ONCE) == 0) + return FALSE; + + /* The generic linker doesn't handle section groups. */ + if ((sec->flags & SEC_GROUP) != 0) + return FALSE; /* FIXME: When doing a relocatable link, we may have trouble copying relocations in other sections that refer to local symbols @@ -3059,81 +3109,18 @@ _bfd_generic_section_already_linked (bfd *abfd, asection *sec, already_linked_list = bfd_section_already_linked_table_lookup (name); - for (l = already_linked_list->entry; l != NULL; l = l->next) + l = already_linked_list->entry; + if (l != NULL) { - bfd_boolean skip = FALSE; - struct coff_comdat_info *s_comdat - = bfd_coff_get_comdat_section (abfd, sec); - struct coff_comdat_info *l_comdat - = bfd_coff_get_comdat_section (l->sec->owner, l->sec); - - /* We may have 3 different sections on the list: group section, - comdat section and linkonce section. SEC may be a linkonce or - comdat section. We always ignore group section. For non-COFF - inputs, we also ignore comdat section. - - FIXME: Is that safe to match a linkonce section with a comdat - section for COFF inputs? */ - if ((l->sec->flags & SEC_GROUP) != 0) - skip = TRUE; - else if (bfd_get_flavour (abfd) == bfd_target_coff_flavour) - { - if (s_comdat != NULL - && l_comdat != NULL - && strcmp (s_comdat->name, l_comdat->name) != 0) - skip = TRUE; - } - else if (l_comdat != NULL) - skip = TRUE; - - if (!skip) - { - /* The section has already been linked. See if we should - issue a warning. */ - switch (flags & SEC_LINK_DUPLICATES) - { - default: - abort (); - - case SEC_LINK_DUPLICATES_DISCARD: - break; - - case SEC_LINK_DUPLICATES_ONE_ONLY: - (*_bfd_error_handler) - (_("%B: warning: ignoring duplicate section `%A'\n"), - abfd, sec); - break; - - case SEC_LINK_DUPLICATES_SAME_CONTENTS: - /* FIXME: We should really dig out the contents of both - sections and memcmp them. The COFF/PE spec says that - the Microsoft linker does not implement this - correctly, so I'm not going to bother doing it - either. */ - /* Fall through. */ - case SEC_LINK_DUPLICATES_SAME_SIZE: - if (sec->size != l->sec->size) - (*_bfd_error_handler) - (_("%B: warning: duplicate section `%A' has different size\n"), - abfd, sec); - break; - } - - /* Set the output_section field so that lang_add_section - does not create a lang_input_section structure for this - section. Since there might be a symbol in the section - being discarded, we must retain a pointer to the section - which we are really going to use. */ - sec->output_section = bfd_abs_section_ptr; - sec->kept_section = l->sec; - - return; - } + /* The section has already been linked. See if we should + issue a warning. */ + return _bfd_handle_already_linked (sec, l, info); } /* This is the first section with this name. Record it. */ - if (! bfd_section_already_linked_table_insert (already_linked_list, sec)) + if (!bfd_section_already_linked_table_insert (already_linked_list, sec)) info->callbacks->einfo (_("%F%P: already_linked_table: %E\n")); + return FALSE; } /* Convert symbols in excluded output sections to use a kept section. */ @@ -3143,9 +3130,6 @@ fix_syms (struct bfd_link_hash_entry *h, void *data) { bfd *obfd = (bfd *) data; - if (h->type == bfd_link_hash_warning) - h = h->u.i.link; - if (h->type == bfd_link_hash_defined || h->type == bfd_link_hash_defweak) { @@ -3396,3 +3380,26 @@ bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs, return NULL; } + +/* +FUNCTION + bfd_hide_sym_by_version + +SYNOPSIS + bfd_boolean bfd_hide_sym_by_version + (struct bfd_elf_version_tree *verdefs, const char *sym_name); + +DESCRIPTION + Search an elf version script tree for symbol versioning + info for a given symbol. Return TRUE if the symbol is hidden. + +*/ + +bfd_boolean +bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs, + const char *sym_name) +{ + bfd_boolean hidden = FALSE; + bfd_find_version_for_sym (verdefs, sym_name, &hidden); + return hidden; +} diff --git a/contrib/gdb-7/bfd/opncls.c b/contrib/gdb-7/bfd/opncls.c index 3597daee01..9d33f3974f 100644 --- a/contrib/gdb-7/bfd/opncls.c +++ b/contrib/gdb-7/bfd/opncls.c @@ -525,7 +525,9 @@ opncls_bmmap (struct bfd *abfd ATTRIBUTE_UNUSED, bfd_size_type len ATTRIBUTE_UNUSED, int prot ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, - file_ptr offset ATTRIBUTE_UNUSED) + file_ptr offset ATTRIBUTE_UNUSED, + void **map_addr ATTRIBUTE_UNUSED, + bfd_size_type *map_len ATTRIBUTE_UNUSED) { return (void *) -1; } @@ -875,7 +877,7 @@ bfd_make_readable (bfd *abfd) abfd->section_count = 0; abfd->usrdata = NULL; abfd->cacheable = FALSE; - abfd->flags = BFD_IN_MEMORY; + abfd->flags |= BFD_IN_MEMORY; abfd->mtime_set = FALSE; abfd->target_defaulted = TRUE; diff --git a/contrib/gdb-7/bfd/reloc.c b/contrib/gdb-7/bfd/reloc.c index 202a34095a..e0b5f620ea 100644 --- a/contrib/gdb-7/bfd/reloc.c +++ b/contrib/gdb-7/bfd/reloc.c @@ -2177,9 +2177,10 @@ ENUMDOC ENUM BFD_RELOC_MIPS_JMP +ENUMX + BFD_RELOC_MICROMIPS_JMP ENUMDOC - Bits 27..2 of the relocation address shifted right 2 bits; - simple reloc otherwise. + The MIPS jump instruction. ENUM BFD_RELOC_MIPS16_JMP @@ -2195,6 +2196,7 @@ ENUM BFD_RELOC_HI16 ENUMDOC High 16 bits of 32-bit value; simple reloc. + ENUM BFD_RELOC_HI16_S ENUMDOC @@ -2202,6 +2204,7 @@ ENUMDOC extended and added to form the final result. If the low 16 bits form a negative number, we need to add one to the high value to compensate for the borrow when the low bits are added. + ENUM BFD_RELOC_LO16 ENUMDOC @@ -2245,29 +2248,71 @@ ENUMDOC ENUM BFD_RELOC_MIPS_LITERAL +ENUMX + BFD_RELOC_MICROMIPS_LITERAL ENUMDOC Relocation against a MIPS literal section. +ENUM + BFD_RELOC_MICROMIPS_7_PCREL_S1 +ENUMX + BFD_RELOC_MICROMIPS_10_PCREL_S1 +ENUMX + BFD_RELOC_MICROMIPS_16_PCREL_S1 +ENUMDOC + microMIPS PC-relative relocations. + +ENUM + BFD_RELOC_MICROMIPS_GPREL16 +ENUMX + BFD_RELOC_MICROMIPS_HI16 +ENUMX + BFD_RELOC_MICROMIPS_HI16_S +ENUMX + BFD_RELOC_MICROMIPS_LO16 +ENUMDOC + microMIPS versions of generic BFD relocs. + ENUM BFD_RELOC_MIPS_GOT16 +ENUMX + BFD_RELOC_MICROMIPS_GOT16 ENUMX BFD_RELOC_MIPS_CALL16 +ENUMX + BFD_RELOC_MICROMIPS_CALL16 ENUMX BFD_RELOC_MIPS_GOT_HI16 +ENUMX + BFD_RELOC_MICROMIPS_GOT_HI16 ENUMX BFD_RELOC_MIPS_GOT_LO16 +ENUMX + BFD_RELOC_MICROMIPS_GOT_LO16 ENUMX BFD_RELOC_MIPS_CALL_HI16 +ENUMX + BFD_RELOC_MICROMIPS_CALL_HI16 ENUMX BFD_RELOC_MIPS_CALL_LO16 +ENUMX + BFD_RELOC_MICROMIPS_CALL_LO16 ENUMX BFD_RELOC_MIPS_SUB +ENUMX + BFD_RELOC_MICROMIPS_SUB ENUMX BFD_RELOC_MIPS_GOT_PAGE +ENUMX + BFD_RELOC_MICROMIPS_GOT_PAGE ENUMX BFD_RELOC_MIPS_GOT_OFST +ENUMX + BFD_RELOC_MICROMIPS_GOT_OFST ENUMX BFD_RELOC_MIPS_GOT_DISP +ENUMX + BFD_RELOC_MICROMIPS_GOT_DISP ENUMX BFD_RELOC_MIPS_SHIFT5 ENUMX @@ -2280,16 +2325,24 @@ ENUMX BFD_RELOC_MIPS_DELETE ENUMX BFD_RELOC_MIPS_HIGHEST +ENUMX + BFD_RELOC_MICROMIPS_HIGHEST ENUMX BFD_RELOC_MIPS_HIGHER +ENUMX + BFD_RELOC_MICROMIPS_HIGHER ENUMX BFD_RELOC_MIPS_SCN_DISP +ENUMX + BFD_RELOC_MICROMIPS_SCN_DISP ENUMX BFD_RELOC_MIPS_REL16 ENUMX BFD_RELOC_MIPS_RELGOT ENUMX BFD_RELOC_MIPS_JALR +ENUMX + BFD_RELOC_MICROMIPS_JALR ENUMX BFD_RELOC_MIPS_TLS_DTPMOD32 ENUMX @@ -2300,22 +2353,36 @@ ENUMX BFD_RELOC_MIPS_TLS_DTPREL64 ENUMX BFD_RELOC_MIPS_TLS_GD +ENUMX + BFD_RELOC_MICROMIPS_TLS_GD ENUMX BFD_RELOC_MIPS_TLS_LDM +ENUMX + BFD_RELOC_MICROMIPS_TLS_LDM ENUMX BFD_RELOC_MIPS_TLS_DTPREL_HI16 +ENUMX + BFD_RELOC_MICROMIPS_TLS_DTPREL_HI16 ENUMX BFD_RELOC_MIPS_TLS_DTPREL_LO16 +ENUMX + BFD_RELOC_MICROMIPS_TLS_DTPREL_LO16 ENUMX BFD_RELOC_MIPS_TLS_GOTTPREL +ENUMX + BFD_RELOC_MICROMIPS_TLS_GOTTPREL ENUMX BFD_RELOC_MIPS_TLS_TPREL32 ENUMX BFD_RELOC_MIPS_TLS_TPREL64 ENUMX BFD_RELOC_MIPS_TLS_TPREL_HI16 +ENUMX + BFD_RELOC_MICROMIPS_TLS_TPREL_HI16 ENUMX BFD_RELOC_MIPS_TLS_TPREL_LO16 +ENUMX + BFD_RELOC_MICROMIPS_TLS_TPREL_LO16 ENUMDOC MIPS ELF relocations. COMMENT @@ -4248,6 +4315,73 @@ ENUMDOC This is a 6 bit reloc for the AVR that stores offset for adiw/sbiw instructions +ENUM + BFD_RELOC_RL78_NEG8 +ENUMX + BFD_RELOC_RL78_NEG16 +ENUMX + BFD_RELOC_RL78_NEG24 +ENUMX + BFD_RELOC_RL78_NEG32 +ENUMX + BFD_RELOC_RL78_16_OP +ENUMX + BFD_RELOC_RL78_24_OP +ENUMX + BFD_RELOC_RL78_32_OP +ENUMX + BFD_RELOC_RL78_8U +ENUMX + BFD_RELOC_RL78_16U +ENUMX + BFD_RELOC_RL78_24U +ENUMX + BFD_RELOC_RL78_DIR3U_PCREL +ENUMX + BFD_RELOC_RL78_DIFF +ENUMX + BFD_RELOC_RL78_GPRELB +ENUMX + BFD_RELOC_RL78_GPRELW +ENUMX + BFD_RELOC_RL78_GPRELL +ENUMX + BFD_RELOC_RL78_SYM +ENUMX + BFD_RELOC_RL78_OP_SUBTRACT +ENUMX + BFD_RELOC_RL78_OP_NEG +ENUMX + BFD_RELOC_RL78_OP_AND +ENUMX + BFD_RELOC_RL78_OP_SHRA +ENUMX + BFD_RELOC_RL78_ABS8 +ENUMX + BFD_RELOC_RL78_ABS16 +ENUMX + BFD_RELOC_RL78_ABS16_REV +ENUMX + BFD_RELOC_RL78_ABS32 +ENUMX + BFD_RELOC_RL78_ABS32_REV +ENUMX + BFD_RELOC_RL78_ABS16U +ENUMX + BFD_RELOC_RL78_ABS16UW +ENUMX + BFD_RELOC_RL78_ABS16UL +ENUMX + BFD_RELOC_RL78_RELAX +ENUMX + BFD_RELOC_RL78_HI16 +ENUMX + BFD_RELOC_RL78_HI8 +ENUMX + BFD_RELOC_RL78_LO16 +ENUMDOC + Renesas RL78 Relocations. + ENUM BFD_RELOC_RX_NEG8 ENUMX @@ -5551,6 +5685,377 @@ ENUMDOC This is used to tell the dynamic linker to copy the value out of the dynamic object into the runtime process image. +ENUM + BFD_RELOC_TILEPRO_COPY +ENUMX + BFD_RELOC_TILEPRO_GLOB_DAT +ENUMX + BFD_RELOC_TILEPRO_JMP_SLOT +ENUMX + BFD_RELOC_TILEPRO_RELATIVE +ENUMX + BFD_RELOC_TILEPRO_BROFF_X1 +ENUMX + BFD_RELOC_TILEPRO_JOFFLONG_X1 +ENUMX + BFD_RELOC_TILEPRO_JOFFLONG_X1_PLT +ENUMX + BFD_RELOC_TILEPRO_IMM8_X0 +ENUMX + BFD_RELOC_TILEPRO_IMM8_Y0 +ENUMX + BFD_RELOC_TILEPRO_IMM8_X1 +ENUMX + BFD_RELOC_TILEPRO_IMM8_Y1 +ENUMX + BFD_RELOC_TILEPRO_DEST_IMM8_X1 +ENUMX + BFD_RELOC_TILEPRO_MT_IMM15_X1 +ENUMX + BFD_RELOC_TILEPRO_MF_IMM15_X1 +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0 +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1 +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_HA +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_HA +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_LO_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_LO_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_HI_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_HI_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_HA_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_HA_PCREL +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_GOT +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_GOT +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_GOT_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_GOT_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_GOT_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_GOT_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_GOT_HA +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_GOT_HA +ENUMX + BFD_RELOC_TILEPRO_MMSTART_X0 +ENUMX + BFD_RELOC_TILEPRO_MMEND_X0 +ENUMX + BFD_RELOC_TILEPRO_MMSTART_X1 +ENUMX + BFD_RELOC_TILEPRO_MMEND_X1 +ENUMX + BFD_RELOC_TILEPRO_SHAMT_X0 +ENUMX + BFD_RELOC_TILEPRO_SHAMT_X1 +ENUMX + BFD_RELOC_TILEPRO_SHAMT_Y0 +ENUMX + BFD_RELOC_TILEPRO_SHAMT_Y1 +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_GD_HA +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_GD_HA +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_LO +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_HI +ENUMX + BFD_RELOC_TILEPRO_IMM16_X0_TLS_IE_HA +ENUMX + BFD_RELOC_TILEPRO_IMM16_X1_TLS_IE_HA +ENUMX + BFD_RELOC_TILEPRO_TLS_DTPMOD32 +ENUMX + BFD_RELOC_TILEPRO_TLS_DTPOFF32 +ENUMX + BFD_RELOC_TILEPRO_TLS_TPOFF32 +ENUMDOC + Tilera TILEPro Relocations. + +ENUM + BFD_RELOC_TILEGX_HW0 +ENUMX + BFD_RELOC_TILEGX_HW1 +ENUMX + BFD_RELOC_TILEGX_HW2 +ENUMX + BFD_RELOC_TILEGX_HW3 +ENUMX + BFD_RELOC_TILEGX_HW0_LAST +ENUMX + BFD_RELOC_TILEGX_HW1_LAST +ENUMX + BFD_RELOC_TILEGX_HW2_LAST +ENUMX + BFD_RELOC_TILEGX_COPY +ENUMX + BFD_RELOC_TILEGX_GLOB_DAT +ENUMX + BFD_RELOC_TILEGX_JMP_SLOT +ENUMX + BFD_RELOC_TILEGX_RELATIVE +ENUMX + BFD_RELOC_TILEGX_BROFF_X1 +ENUMX + BFD_RELOC_TILEGX_JUMPOFF_X1 +ENUMX + BFD_RELOC_TILEGX_JUMPOFF_X1_PLT +ENUMX + BFD_RELOC_TILEGX_IMM8_X0 +ENUMX + BFD_RELOC_TILEGX_IMM8_Y0 +ENUMX + BFD_RELOC_TILEGX_IMM8_X1 +ENUMX + BFD_RELOC_TILEGX_IMM8_Y1 +ENUMX + BFD_RELOC_TILEGX_DEST_IMM8_X1 +ENUMX + BFD_RELOC_TILEGX_MT_IMM14_X1 +ENUMX + BFD_RELOC_TILEGX_MF_IMM14_X1 +ENUMX + BFD_RELOC_TILEGX_MMSTART_X0 +ENUMX + BFD_RELOC_TILEGX_MMEND_X0 +ENUMX + BFD_RELOC_TILEGX_SHAMT_X0 +ENUMX + BFD_RELOC_TILEGX_SHAMT_X1 +ENUMX + BFD_RELOC_TILEGX_SHAMT_Y0 +ENUMX + BFD_RELOC_TILEGX_SHAMT_Y1 +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0 +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0 +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1 +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1 +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2 +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2 +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW3 +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW3 +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW3_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW3_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_PCREL +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW3_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW3_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_GOT +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW3_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW3_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_TLS_GD +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW3_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW3_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW0_LAST_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW0_LAST_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW1_LAST_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW1_LAST_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X0_HW2_LAST_TLS_IE +ENUMX + BFD_RELOC_TILEGX_IMM16_X1_HW2_LAST_TLS_IE +ENUMX + BFD_RELOC_TILEGX_TLS_DTPMOD64 +ENUMX + BFD_RELOC_TILEGX_TLS_DTPOFF64 +ENUMX + BFD_RELOC_TILEGX_TLS_TPOFF64 +ENUMX + BFD_RELOC_TILEGX_TLS_DTPMOD32 +ENUMX + BFD_RELOC_TILEGX_TLS_DTPOFF32 +ENUMX + BFD_RELOC_TILEGX_TLS_TPOFF32 +ENUMDOC + Tilera TILE-Gx Relocations. + +ENUM + BFD_RELOC_EPIPHANY_SIMM8 +ENUMDOC + Adapteva EPIPHANY - 8 bit signed pc-relative displacement +ENUM + BFD_RELOC_EPIPHANY_SIMM24 +ENUMDOC + Adapteva EPIPHANY - 24 bit signed pc-relative displacement +ENUM + BFD_RELOC_EPIPHANY_HIGH +ENUMDOC + Adapteva EPIPHANY - 16 most-significant bits of absolute address +ENUM + BFD_RELOC_EPIPHANY_LOW +ENUMDOC + Adapteva EPIPHANY - 16 least-significant bits of absolute address +ENUM + BFD_RELOC_EPIPHANY_SIMM11 +ENUMDOC + Adapteva EPIPHANY - 11 bit signed number - add/sub immediate +ENUM + BFD_RELOC_EPIPHANY_IMM11 +ENUMDOC + Adapteva EPIPHANY - 11 bit sign-magnitude number (ld/st displacement) +ENUM + BFD_RELOC_EPIPHANY_IMM8 +ENUMDOC + Adapteva EPIPHANY - 8 bit immediate for 16 bit mov instruction. + ENDSENUM BFD_RELOC_UNUSED @@ -5700,6 +6205,30 @@ bfd_generic_gc_sections (bfd *abfd ATTRIBUTE_UNUSED, return TRUE; } +/* +INTERNAL_FUNCTION + bfd_generic_lookup_section_flags + +SYNOPSIS + void bfd_generic_lookup_section_flags + (struct bfd_link_info *, struct flag_info *); + +DESCRIPTION + Provides default handling for section flags lookup + -- i.e., does nothing. +*/ + +void +bfd_generic_lookup_section_flags (struct bfd_link_info *info ATTRIBUTE_UNUSED, + struct flag_info *finfo) +{ + if (finfo != NULL) + { + (*_bfd_error_handler) (_("INPUT_SECTION_FLAGS are not supported.\n")); + return; + } +} + /* INTERNAL_FUNCTION bfd_generic_merge_sections diff --git a/contrib/gdb-7/bfd/section.c b/contrib/gdb-7/bfd/section.c index bff8adfb07..7c1f750483 100644 --- a/contrib/gdb-7/bfd/section.c +++ b/contrib/gdb-7/bfd/section.c @@ -1,6 +1,6 @@ /* Object file "section" support for the BFD library. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -327,6 +327,11 @@ CODE_FRAGMENT . sections. *} .#define SEC_COFF_SHARED_LIBRARY 0x4000000 . +. {* This input section should be copied to output in reverse order +. as an array of pointers. This is for ELF linker internal use +. only. *} +.#define SEC_ELF_REVERSE_COPY 0x4000000 +. . {* This section contains data which may be shared with other . executables or shared objects. This is for COFF only. *} .#define SEC_COFF_SHARED 0x8000000 @@ -511,6 +516,9 @@ CODE_FRAGMENT . {* The BFD which owns the section. *} . bfd *owner; . +. {* INPUT_SECTION_FLAGS if specified in the linker script. *} +. struct flag_info *section_flag_info; +. . {* A symbol which points at this section only. *} . struct bfd_symbol *symbol; . struct bfd_symbol **symbol_ptr_ptr; @@ -689,6 +697,9 @@ CODE_FRAGMENT . {* target_index, used_by_bfd, constructor_chain, owner, *} \ . 0, NULL, NULL, NULL, \ . \ +. {* flag_info, *} \ +. NULL, \ +. \ . {* symbol, symbol_ptr_ptr, *} \ . (struct bfd_symbol *) SYM, &SEC.symbol, \ . \ @@ -1456,7 +1467,10 @@ bfd_get_section_contents (bfd *abfd, return TRUE; } - sz = section->rawsize ? section->rawsize : section->size; + if (abfd->direction != write_direction && section->rawsize != 0) + sz = section->rawsize; + else + sz = section->size; if ((bfd_size_type) offset > sz || count > sz || offset + count > sz diff --git a/contrib/gdb-7/bfd/simple.c b/contrib/gdb-7/bfd/simple.c index 03d1a15885..e5a5b58f92 100644 --- a/contrib/gdb-7/bfd/simple.c +++ b/contrib/gdb-7/bfd/simple.c @@ -1,5 +1,5 @@ /* simple.c -- BFD simple client routines - Copyright 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Copyright 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by MontaVista Software, Inc. @@ -82,10 +82,7 @@ simple_dummy_unattached_reloc (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, static bfd_boolean simple_dummy_multiple_definition (struct bfd_link_info *link_info ATTRIBUTE_UNUSED, - const char *name ATTRIBUTE_UNUSED, - bfd *obfd ATTRIBUTE_UNUSED, - asection *osec ATTRIBUTE_UNUSED, - bfd_vma oval ATTRIBUTE_UNUSED, + struct bfd_link_hash_entry *h ATTRIBUTE_UNUSED, bfd *nbfd ATTRIBUTE_UNUSED, asection *nsec ATTRIBUTE_UNUSED, bfd_vma nval ATTRIBUTE_UNUSED) diff --git a/contrib/gdb-7/bfd/srec.c b/contrib/gdb-7/bfd/srec.c index 1251a7e93c..6226773387 100644 --- a/contrib/gdb-7/bfd/srec.c +++ b/contrib/gdb-7/bfd/srec.c @@ -1,6 +1,6 @@ /* BFD back-end for s-record objects. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support . @@ -1252,6 +1252,7 @@ srec_print_symbol (bfd *abfd, #define srec_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define srec_bfd_relax_section bfd_generic_relax_section #define srec_bfd_gc_sections bfd_generic_gc_sections +#define srec_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define srec_bfd_merge_sections bfd_generic_merge_sections #define srec_bfd_is_group_section bfd_generic_is_group_section #define srec_bfd_discard_group bfd_generic_discard_group @@ -1280,6 +1281,7 @@ const bfd_target srec_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ @@ -1335,6 +1337,7 @@ const bfd_target symbolsrec_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ diff --git a/contrib/gdb-7/bfd/targets.c b/contrib/gdb-7/bfd/targets.c index e491c93ee8..4cf8e8fb32 100644 --- a/contrib/gdb-7/bfd/targets.c +++ b/contrib/gdb-7/bfd/targets.c @@ -1,6 +1,6 @@ /* Generic target-file-type support for the BFD library. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Cygnus Support. @@ -177,6 +177,9 @@ DESCRIPTION .{* Forward declaration. *} .typedef struct bfd_link_info _bfd_link_info; . +.{* Forward declaration. *} +.typedef struct flag_info flag_info; +. .typedef struct bfd_target .{ . {* Identifies the kind of target, e.g., SunOS4, Ultrix, etc. *} @@ -208,7 +211,11 @@ DESCRIPTION . char ar_pad_char; . . {* The maximum number of characters in an archive header. *} -. unsigned short ar_max_namelen; +. unsigned char ar_max_namelen; +. +. {* How well this target matches, used to select between various +. possible targets when more than one target matches. *} +. unsigned char match_priority; . . {* Entries for byte swapping for data. These are different from the . other entry points, since they don't take a BFD as the first argument. @@ -444,6 +451,7 @@ BFD_JUMP_TABLE macros. . NAME##_bfd_final_link, \ . NAME##_bfd_link_split_section, \ . NAME##_bfd_gc_sections, \ +. NAME##_bfd_lookup_section_flags, \ . NAME##_bfd_merge_sections, \ . NAME##_bfd_is_group_section, \ . NAME##_bfd_discard_group, \ @@ -488,6 +496,10 @@ BFD_JUMP_TABLE macros. . {* Remove sections that are not referenced from the output. *} . bfd_boolean (*_bfd_gc_sections) (bfd *, struct bfd_link_info *); . +. {* Sets the bitmask of allowed and disallowed section flags. *} +. void (*_bfd_lookup_section_flags) (struct bfd_link_info *, +. struct flag_info *); +. . {* Attempt to merge SEC_MERGE sections. *} . bfd_boolean (*_bfd_merge_sections) (bfd *, struct bfd_link_info *); . @@ -499,8 +511,8 @@ BFD_JUMP_TABLE macros. . . {* Check if SEC has been already linked during a reloceatable or . final link. *} -. void (*_section_already_linked) (bfd *, struct bfd_section *, -. struct bfd_link_info *); +. bfd_boolean (*_section_already_linked) (bfd *, asection *, +. struct bfd_link_info *); . . {* Define a common symbol. *} . bfd_boolean (*_bfd_define_common_symbol) (bfd *, struct bfd_link_info *, @@ -595,6 +607,7 @@ extern const bfd_target bfd_elf32_crx_vec; extern const bfd_target bfd_elf32_d10v_vec; extern const bfd_target bfd_elf32_d30v_vec; extern const bfd_target bfd_elf32_dlx_big_vec; +extern const bfd_target bfd_elf32_epiphany_vec; extern const bfd_target bfd_elf32_fr30_vec; extern const bfd_target bfd_elf32_frv_vec; extern const bfd_target bfd_elf32_frvfdpic_vec; @@ -605,6 +618,7 @@ extern const bfd_target bfd_elf32_hppa_nbsd_vec; extern const bfd_target bfd_elf32_hppa_vec; extern const bfd_target bfd_elf32_i370_vec; extern const bfd_target bfd_elf32_i386_freebsd_vec; +extern const bfd_target bfd_elf32_i386_nacl_vec; extern const bfd_target bfd_elf32_i386_sol2_vec; extern const bfd_target bfd_elf32_i386_vxworks_vec; extern const bfd_target bfd_elf32_i386_vec; @@ -654,9 +668,12 @@ extern const bfd_target bfd_elf32_pj_vec; extern const bfd_target bfd_elf32_pjl_vec; extern const bfd_target bfd_elf32_powerpc_vec; extern const bfd_target bfd_elf32_powerpcle_vec; +extern const bfd_target bfd_elf32_powerpc_freebsd_vec; extern const bfd_target bfd_elf32_powerpc_vxworks_vec; +extern const bfd_target bfd_elf32_rl78_vec; extern const bfd_target bfd_elf32_rx_le_vec; extern const bfd_target bfd_elf32_rx_be_vec; +extern const bfd_target bfd_elf32_rx_be_ns_vec; extern const bfd_target bfd_elf32_s390_vec; extern const bfd_target bfd_elf32_bigscore_vec; extern const bfd_target bfd_elf32_littlescore_vec; @@ -683,6 +700,12 @@ extern const bfd_target bfd_elf32_sparc_vxworks_vec; extern const bfd_target bfd_elf32_spu_vec; extern const bfd_target bfd_elf32_tic6x_be_vec; extern const bfd_target bfd_elf32_tic6x_le_vec; +extern const bfd_target bfd_elf32_tic6x_elf_be_vec; +extern const bfd_target bfd_elf32_tic6x_elf_le_vec; +extern const bfd_target bfd_elf32_tic6x_linux_be_vec; +extern const bfd_target bfd_elf32_tic6x_linux_le_vec; +extern const bfd_target bfd_elf32_tilegx_vec; +extern const bfd_target bfd_elf32_tilepro_vec; extern const bfd_target bfd_elf32_tradbigmips_vec; extern const bfd_target bfd_elf32_tradlittlemips_vec; extern const bfd_target bfd_elf32_tradbigmips_freebsd_vec; @@ -709,6 +732,7 @@ extern const bfd_target bfd_elf64_littlemips_vec; extern const bfd_target bfd_elf64_mmix_vec; extern const bfd_target bfd_elf64_powerpc_vec; extern const bfd_target bfd_elf64_powerpcle_vec; +extern const bfd_target bfd_elf64_powerpc_freebsd_vec; extern const bfd_target bfd_elf64_s390_vec; extern const bfd_target bfd_elf64_sh64_vec; extern const bfd_target bfd_elf64_sh64l_vec; @@ -719,6 +743,7 @@ extern const bfd_target bfd_elf64_sh64nbsd_vec; extern const bfd_target bfd_elf64_sparc_vec; extern const bfd_target bfd_elf64_sparc_freebsd_vec; extern const bfd_target bfd_elf64_sparc_sol2_vec; +extern const bfd_target bfd_elf64_tilegx_vec; extern const bfd_target bfd_elf64_tradbigmips_vec; extern const bfd_target bfd_elf64_tradlittlemips_vec; extern const bfd_target bfd_elf64_tradbigmips_freebsd_vec; @@ -729,6 +754,8 @@ extern const bfd_target bfd_elf64_x86_64_vec; extern const bfd_target bfd_elf32_x86_64_vec; extern const bfd_target bfd_elf64_l1om_freebsd_vec; extern const bfd_target bfd_elf64_l1om_vec; +extern const bfd_target bfd_elf64_k1om_freebsd_vec; +extern const bfd_target bfd_elf64_k1om_vec; extern const bfd_target bfd_mmo_vec; extern const bfd_target bfd_powerpc_pe_vec; extern const bfd_target bfd_powerpc_pei_vec; @@ -945,6 +972,7 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_d10v_vec, &bfd_elf32_d30v_vec, &bfd_elf32_dlx_big_vec, + &bfd_elf32_epiphany_vec, &bfd_elf32_fr30_vec, &bfd_elf32_frv_vec, &bfd_elf32_frvfdpic_vec, @@ -955,6 +983,7 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_hppa_vec, &bfd_elf32_i370_vec, &bfd_elf32_i386_freebsd_vec, + &bfd_elf32_i386_nacl_vec, &bfd_elf32_i386_sol2_vec, &bfd_elf32_i386_vxworks_vec, &bfd_elf32_i386_vec, @@ -1009,7 +1038,10 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_powerpc_vec, &bfd_elf32_powerpc_vxworks_vec, &bfd_elf32_powerpcle_vec, + &bfd_elf32_powerpc_freebsd_vec, + &bfd_elf32_rl78_vec, &bfd_elf32_rx_be_vec, + &bfd_elf32_rx_be_ns_vec, &bfd_elf32_rx_le_vec, &bfd_elf32_s390_vec, #ifdef BFD64 @@ -1041,6 +1073,8 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_spu_vec, &bfd_elf32_tic6x_be_vec, &bfd_elf32_tic6x_le_vec, + &bfd_elf32_tilegx_vec, + &bfd_elf32_tilepro_vec, &bfd_elf32_tradbigmips_vec, &bfd_elf32_tradlittlemips_vec, &bfd_elf32_tradbigmips_freebsd_vec, @@ -1068,6 +1102,7 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf64_mmix_vec, &bfd_elf64_powerpc_vec, &bfd_elf64_powerpcle_vec, + &bfd_elf64_powerpc_freebsd_vec, &bfd_elf64_s390_vec, &bfd_elf64_sh64_vec, &bfd_elf64_sh64l_vec, @@ -1078,6 +1113,7 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf64_sparc_vec, &bfd_elf64_sparc_freebsd_vec, &bfd_elf64_sparc_sol2_vec, + &bfd_elf64_tilegx_vec, &bfd_elf64_tradbigmips_vec, &bfd_elf64_tradlittlemips_vec, &bfd_elf64_tradbigmips_freebsd_vec, @@ -1088,6 +1124,8 @@ static const bfd_target * const _bfd_target_vector[] = &bfd_elf32_x86_64_vec, &bfd_elf64_l1om_freebsd_vec, &bfd_elf64_l1om_vec, + &bfd_elf64_k1om_freebsd_vec, + &bfd_elf64_k1om_vec, &bfd_mmo_vec, #endif &bfd_powerpc_pe_vec, diff --git a/contrib/gdb-7/bfd/tekhex.c b/contrib/gdb-7/bfd/tekhex.c index 2204ebba6e..0ed7b5032b 100644 --- a/contrib/gdb-7/bfd/tekhex.c +++ b/contrib/gdb-7/bfd/tekhex.c @@ -1,6 +1,6 @@ /* BFD backend for Extended Tektronix Hex Format objects. Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2009, 2011 Free Software Foundation, Inc. Written by Steve Chamberlain of Cygnus Support . This file is part of BFD, the Binary File Descriptor library. @@ -943,6 +943,7 @@ tekhex_print_symbol (bfd *abfd, #define tekhex_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents #define tekhex_bfd_relax_section bfd_generic_relax_section #define tekhex_bfd_gc_sections bfd_generic_gc_sections +#define tekhex_bfd_lookup_section_flags bfd_generic_lookup_section_flags #define tekhex_bfd_merge_sections bfd_generic_merge_sections #define tekhex_bfd_is_group_section bfd_generic_is_group_section #define tekhex_bfd_discard_group bfd_generic_discard_group @@ -972,6 +973,7 @@ const bfd_target tekhex_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ diff --git a/contrib/gdb-7/bfd/verilog.c b/contrib/gdb-7/bfd/verilog.c index 551e5c4280..a2d3ca7855 100644 --- a/contrib/gdb-7/bfd/verilog.c +++ b/contrib/gdb-7/bfd/verilog.c @@ -1,5 +1,5 @@ /* BFD back-end for verilog hex memory dump files. - Copyright 2009, 2010 + Copyright 2009, 2010, 2011 Free Software Foundation, Inc. Written by Anthony Green @@ -332,6 +332,7 @@ const bfd_target verilog_vec = 0, /* Leading underscore. */ ' ', /* AR_pad_char. */ 16, /* AR_max_namelen. */ + 0, /* match priority. */ bfd_getb64, bfd_getb_signed_64, bfd_putb64, bfd_getb32, bfd_getb_signed_32, bfd_putb32, bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data. */ diff --git a/contrib/gdb-7/bfd/version.h b/contrib/gdb-7/bfd/version.h index 23a04383c7..f2460949ad 100644 --- a/contrib/gdb-7/bfd/version.h +++ b/contrib/gdb-7/bfd/version.h @@ -1,4 +1,4 @@ -#define BFD_VERSION_DATE 20110403 +#define BFD_VERSION_DATE 20111213 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@ #define REPORT_BUGS_TO @report_bugs_to@ diff --git a/contrib/gdb-7/gdb/README b/contrib/gdb-7/gdb/README index 0ee97050be..999f9927f6 100644 --- a/contrib/gdb-7/gdb/README +++ b/contrib/gdb-7/gdb/README @@ -144,7 +144,7 @@ format. On its own, TeX cannot read, much less typeset a Texinfo file. `gdb-VERSION/texinfo' directory. If you have TeX and a DVI printer program installed, you can typeset -and print this manual. First switch to the the `gdb' subdirectory of +and print this manual. First switch to the `gdb' subdirectory of the main source directory (for example, to `gdb-VERSION/gdb') and then type: make doc/gdb.dvi @@ -638,6 +638,26 @@ testsuite `standalone', without it being part of the GDB source tree. See the DejaGNU documentation for further details. + +Copyright and License Notices +============================= + +Most files maintained by the GDB Project contain a copyright notice +as well as a license notice, usually at the start of the file. + +To reduce the length of copyright notices, consecutive years in the +copyright notice can be combined into a single range. For instance, +the following list of copyright years... + + 1986, 1988, 1989, 1991-1993, 1999, 2000, 2007, 2008, 2009, 2010, 2011 + +... is abbreviated into: + + 1986, 1988-1989, 1991-1993, 1999-2000, 2007-2011 + +Every year of each range, inclusive, is a copyrightable year that +could be listed individually. + (this is for editing this file with GNU emacs) Local Variables: diff --git a/contrib/gdb-7/gdb/ada-exp.y b/contrib/gdb-7/gdb/ada-exp.y index e64d1eb456..d8c21a4f11 100644 --- a/contrib/gdb-7/gdb/ada-exp.y +++ b/contrib/gdb-7/gdb/ada-exp.y @@ -1,6 +1,6 @@ /* YACC parser for Ada expressions, for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1997, 2000, 2003, 2004, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1991, 1993-1994, 1997, 2000, 2003-2004, + 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -1287,12 +1287,12 @@ write_var_or_type (struct block *block, struct stoken name0) FIXME pnh 7/20/2007. */ if (nsyms == 1) { - struct symbol *renaming = + struct symbol *ren_sym = ada_find_renaming_symbol (SYMBOL_LINKAGE_NAME (syms[0].sym), syms[0].block); - if (renaming != NULL) - syms[0].sym = renaming; + if (ren_sym != NULL) + syms[0].sym = ren_sym; } type_sym = select_possible_type_sym (syms, nsyms); @@ -1449,8 +1449,12 @@ convert_char_literal (struct type *type, LONGEST val) char name[7]; int f; - if (type == NULL || TYPE_CODE (type) != TYPE_CODE_ENUM) + if (type == NULL) return val; + type = check_typedef (type); + if (TYPE_CODE (type) != TYPE_CODE_ENUM) + return val; + xsnprintf (name, sizeof (name), "QU%02x", (int) val); for (f = 0; f < TYPE_NFIELDS (type); f += 1) { diff --git a/contrib/gdb-7/gdb/ada-lang.c b/contrib/gdb-7/gdb/ada-lang.c index d434521be7..2d81694789 100644 --- a/contrib/gdb-7/gdb/ada-lang.c +++ b/contrib/gdb-7/gdb/ada-lang.c @@ -1,7 +1,7 @@ -/* Ada language support routines for GDB, the GNU debugger. Copyright (C) +/* Ada language support routines for GDB, the GNU debugger. - 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2007, 2008, - 2009 Free Software Foundation, Inc. + Copyright (C) 1992-1994, 1997-2000, 2003-2005, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -61,6 +61,8 @@ #include "psymtab.h" #include "value.h" #include "mi/mi-common.h" +#include "arch-utils.h" +#include "exceptions.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). @@ -315,6 +317,11 @@ struct ada_inferior_data accessible through a component ("tsd") in the object tag. But this is no longer the case, so we cache it for each inferior. */ struct type *tsd_type; + + /* The exception_support_info data. This data is used to determine + how to implement support for Ada exception catchpoints in a given + inferior. */ + const struct exception_support_info *exception_info; }; /* Our key to this module's inferior data. */ @@ -714,7 +721,7 @@ ada_discrete_type_low_bound (struct type *type) non-range scalar type. */ static struct type * -base_type (struct type *type) +get_base_type (struct type *type) { while (type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE) { @@ -898,11 +905,14 @@ is_lower_alphanum (const char c) return (isdigit (c) || (isalpha (c) && islower (c))); } -/* Remove either of these suffixes: +/* ENCODED is the linkage name of a symbol and LEN contains its length. + This function saves in LEN the length of that same symbol name but + without either of these suffixes: . .{DIGIT}+ . ${DIGIT}+ . ___{DIGIT}+ . __{DIGIT}+. + These are suffixes introduced by the compiler for entities such as nested subprogram for instance, in order to avoid name clashes. They do not serve any purpose for the debugger. */ @@ -1438,7 +1448,7 @@ thin_descriptor_type (struct type *type) static struct value * thin_data_pntr (struct value *val) { - struct type *type = value_type (val); + struct type *type = ada_check_typedef (value_type (val)); struct type *data_type = desc_data_target_type (thin_descriptor_type (type)); data_type = lookup_pointer_type (data_type); @@ -2088,7 +2098,7 @@ decode_constrained_packed_array (struct value *arr) of the routine assumes that the array hasn't been decoded yet, so we use the basic "value_ind" routine to perform the dereferencing, as opposed to using "ada_value_ind". */ - if (TYPE_CODE (value_type (arr)) == TYPE_CODE_PTR) + if (TYPE_CODE (ada_check_typedef (value_type (arr))) == TYPE_CODE_PTR) arr = value_ind (arr); type = decode_constrained_packed_array_type (value_type (arr)); @@ -3320,13 +3330,13 @@ return_match (struct type *func_type, struct type *context_type) return 1; if (TYPE_CODE (func_type) == TYPE_CODE_FUNC) - return_type = base_type (TYPE_TARGET_TYPE (func_type)); + return_type = get_base_type (TYPE_TARGET_TYPE (func_type)); else - return_type = base_type (func_type); + return_type = get_base_type (func_type); if (return_type == NULL) return 1; - context_type = base_type (context_type); + context_type = get_base_type (context_type); if (TYPE_CODE (return_type) == TYPE_CODE_ENUM) return context_type == NULL || return_type == context_type; @@ -4360,6 +4370,108 @@ is_nondebugging_type (struct type *type) return (name != NULL && strcmp (name, "") == 0); } +/* Return nonzero 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, TYPE_NFIELDS (type1) == TYPE_NFIELDS (type2)). */ + +static int +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. */ + + /* All enums in the type should have an identical underlying value. */ + for (i = 0; i < TYPE_NFIELDS (type1); i++) + if (TYPE_FIELD_BITPOS (type1, i) != TYPE_FIELD_BITPOS (type2, i)) + return 0; + + /* All enumerals should also have the same name (modulo any numerical + suffix). */ + for (i = 0; i < TYPE_NFIELDS (type1); i++) + { + char *name_1 = TYPE_FIELD_NAME (type1, i); + char *name_2 = TYPE_FIELD_NAME (type2, i); + int len_1 = strlen (name_1); + int len_2 = strlen (name_2); + + ada_remove_trailing_digits (TYPE_FIELD_NAME (type1, i), &len_1); + ada_remove_trailing_digits (TYPE_FIELD_NAME (type2, i), &len_2); + if (len_1 != len_2 + || strncmp (TYPE_FIELD_NAME (type1, i), + TYPE_FIELD_NAME (type2, i), + len_1) != 0) + return 0; + } + + return 1; +} + +/* Return nonzero if all the symbols in SYMS are all enumeral symbols + that are deemed "identical" for practical purposes. Sometimes, + enumerals are not strictly identical, but their types are so similar + that they can be considered identical. + + For instance, consider the following code: + + type Color is (Black, Red, Green, Blue, White); + type RGB_Color is new Color range Red .. Blue; + + Type RGB_Color is a subrange of an implicit type which is a copy + of type Color. If we call that implicit type RGB_ColorB ("B" is + for "Base Type"), then type RGB_ColorB is a copy of type Color. + As a result, when an expression references any of the enumeral + by name (Eg. "print green"), the expression is technically + ambiguous and the user should be asked to disambiguate. But + doing so would only hinder the user, since it wouldn't matter + what choice he makes, the outcome would always be the same. + So, for practical purposes, we consider them as the same. */ + +static int +symbols_are_identical_enums (struct ada_symbol_info *syms, int nsyms) +{ + int i; + + /* Before performing a thorough comparison check of each type, + we perform a series of inexpensive checks. We expect that these + checks will quickly fail in the vast majority of cases, and thus + help prevent the unnecessary use of a more expensive comparison. + Said comparison also expects us to make some of these checks + (see ada_identical_enum_types_p). */ + + /* Quick check: All symbols should have an enum type. */ + for (i = 0; i < nsyms; i++) + if (TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) != TYPE_CODE_ENUM) + return 0; + + /* Quick check: They should all have the same value. */ + for (i = 1; i < nsyms; i++) + if (SYMBOL_VALUE (syms[i].sym) != SYMBOL_VALUE (syms[0].sym)) + return 0; + + /* Quick check: They should all have the same number of enumerals. */ + for (i = 1; i < nsyms; i++) + if (TYPE_NFIELDS (SYMBOL_TYPE (syms[i].sym)) + != TYPE_NFIELDS (SYMBOL_TYPE (syms[0].sym))) + 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. */ + for (i = 1; i < nsyms; i++) + if (!ada_identical_enum_types_p (SYMBOL_TYPE (syms[i].sym), + SYMBOL_TYPE (syms[0].sym))) + return 0; + + return 1; +} + /* Remove any non-debugging symbols in SYMS[0 .. NSYMS-1] that definitely duplicate other symbols in the list (The only case I know of where this happens is when object files containing stabs-in-ecoff are @@ -4372,10 +4484,16 @@ remove_extra_symbols (struct ada_symbol_info *syms, int nsyms) { int i, j; + /* We should never be called with less than 2 symbols, as there + cannot be any extra symbol in that case. But it's easy to + handle, since we have nothing to do in that case. */ + if (nsyms < 2) + return nsyms; + i = 0; while (i < nsyms) { - int remove = 0; + int remove_p = 0; /* If two symbols have the same name and one of them is a stub type, the get rid of the stub. */ @@ -4390,7 +4508,7 @@ remove_extra_symbols (struct ada_symbol_info *syms, int nsyms) && SYMBOL_LINKAGE_NAME (syms[j].sym) != NULL && strcmp (SYMBOL_LINKAGE_NAME (syms[i].sym), SYMBOL_LINKAGE_NAME (syms[j].sym)) == 0) - remove = 1; + remove_p = 1; } } @@ -4410,11 +4528,11 @@ remove_extra_symbols (struct ada_symbol_info *syms, int nsyms) && SYMBOL_CLASS (syms[i].sym) == SYMBOL_CLASS (syms[j].sym) && SYMBOL_VALUE_ADDRESS (syms[i].sym) == SYMBOL_VALUE_ADDRESS (syms[j].sym)) - remove = 1; + remove_p = 1; } } - if (remove) + if (remove_p) { for (j = i + 1; j < nsyms; j += 1) syms[j - 1] = syms[j]; @@ -4423,6 +4541,22 @@ remove_extra_symbols (struct ada_symbol_info *syms, int nsyms) i += 1; } + + /* If all the remaining symbols are identical enumerals, then + just keep the first one and discard the rest. + + Unlike what we did previously, we do not discard any entry + unless they are ALL identical. This is because the symbol + comparison is not a strict comparison, but rather a practical + comparison. If all symbols are considered identical, then + we can just go ahead and use the first one and discard the rest. + But if we cannot reduce the list to a single element, we have + to ask the user to disambiguate anyways. And if we have to + present a multiple-choice menu, it's less confusing if the list + isn't missing some choices that were identical and yet distinct. */ + if (symbols_are_identical_enums (syms, nsyms)) + nsyms = 1; + return nsyms; } @@ -4765,7 +4899,7 @@ compare_names (const char *string1, const char *string2) if (is_name_suffix (string1)) return 0; else - return -1; + return 1; } /* FALLTHROUGH */ default: @@ -4923,6 +5057,50 @@ done: return ndefns; } +/* If NAME is the name of an entity, return a string that should + be used to look that entity up in Ada units. This string should + be deallocated after use using xfree. + + NAME can have any form that the "break" or "print" commands might + recognize. In other words, it does not have to be the "natural" + name, or the "encoded" name. */ + +char * +ada_name_for_lookup (const char *name) +{ + char *canon; + int nlen = strlen (name); + + if (name[0] == '<' && name[nlen - 1] == '>') + { + canon = xmalloc (nlen - 1); + memcpy (canon, name + 1, nlen - 2); + canon[nlen - 2] = '\0'; + } + else + canon = xstrdup (ada_encode (ada_fold_name (name))); + return canon; +} + +/* Implementation of the la_iterate_over_symbols method. */ + +static void +ada_iterate_over_symbols (const struct block *block, + const char *name, domain_enum domain, + int (*callback) (struct symbol *, void *), + void *data) +{ + int ndefs, i; + struct ada_symbol_info *results; + + ndefs = ada_lookup_symbol_list (name, block, domain, &results); + for (i = 0; i < ndefs; ++i) + { + if (! (*callback) (results[i].sym, data)) + break; + } +} + struct symbol * ada_lookup_encoded_symbol (const char *name, const struct block *block0, domain_enum namespace, struct block **block_found) @@ -5504,7 +5682,8 @@ struct add_partial_datum /* A callback for expand_partial_symbol_names. */ static int -ada_expand_partial_symbol_name (const char *name, void *user_data) +ada_expand_partial_symbol_name (const struct language_defn *language, + const char *name, void *user_data) { struct add_partial_datum *data = user_data; @@ -8192,7 +8371,7 @@ ada_enum_name (const char *name) /* First, unqualify the enumeration name: 1. Search for the last '.' character. If we find one, then skip - all the preceeding characters, the unqualified name starts + all the preceding characters, the unqualified name starts right after that dot. 2. Otherwise, we may be debugging on a target where the compiler translates dots into "__". Search forward for double underscores, @@ -8371,8 +8550,8 @@ ada_value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) arg1 = coerce_ref (arg1); arg2 = coerce_ref (arg2); - type1 = base_type (ada_check_typedef (value_type (arg1))); - type2 = base_type (ada_check_typedef (value_type (arg2))); + type1 = get_base_type (ada_check_typedef (value_type (arg1))); + type2 = get_base_type (ada_check_typedef (value_type (arg2))); if (TYPE_CODE (type1) != TYPE_CODE_INT || TYPE_CODE (type2) != TYPE_CODE_INT) @@ -8536,8 +8715,6 @@ assign_aggregate (struct value *container, *pos += 3; if (noside != EVAL_NORMAL) { - int i; - for (i = 0; i < n; i += 1) ada_evaluate_subexp (NULL, exp, pos, noside); return container; @@ -8579,24 +8756,24 @@ assign_aggregate (struct value *container, { switch (exp->elts[*pos].opcode) { - case OP_CHOICES: - aggregate_assign_from_choices (container, lhs, exp, pos, indices, + case OP_CHOICES: + aggregate_assign_from_choices (container, lhs, exp, pos, indices, + &num_indices, max_indices, + low_index, high_index); + break; + case OP_POSITIONAL: + aggregate_assign_positional (container, lhs, exp, pos, indices, &num_indices, max_indices, low_index, high_index); - break; - case OP_POSITIONAL: - aggregate_assign_positional (container, lhs, exp, pos, indices, - &num_indices, max_indices, - low_index, high_index); - break; - case OP_OTHERS: - if (i != n-1) - error (_("Misplaced 'others' clause")); - aggregate_assign_others (container, lhs, exp, pos, indices, - num_indices, low_index, high_index); - break; - default: - error (_("Internal error: bad aggregate clause")); + break; + case OP_OTHERS: + if (i != n-1) + error (_("Misplaced 'others' clause")); + aggregate_assign_others (container, lhs, exp, pos, indices, + num_indices, low_index, high_index); + break; + default: + error (_("Internal error: bad aggregate clause")); } } @@ -9381,8 +9558,8 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, type = ada_check_typedef (value_type (argvec[0])); /* Ada allows us to implicitly dereference arrays when subscripting - them. So, if this is an typedef (encoding use for array access - types encoded as fat pointers), strip it now. */ + them. So, if this is an array typedef (encoding use for array + access types encoded as fat pointers), strip it now. */ if (TYPE_CODE (type) == TYPE_CODE_TYPEDEF) type = ada_typedef_target_type (type); @@ -9517,16 +9694,17 @@ ada_evaluate_subexp (struct type *expect_type, struct expression *exp, if (!ada_is_simple_array_type (value_type (array))) error (_("cannot take slice of non-array")); - if (TYPE_CODE (value_type (array)) == TYPE_CODE_PTR) + if (TYPE_CODE (ada_check_typedef (value_type (array))) + == TYPE_CODE_PTR) { + struct type *type0 = ada_check_typedef (value_type (array)); + if (high_bound < low_bound || noside == EVAL_AVOID_SIDE_EFFECTS) - return empty_array (TYPE_TARGET_TYPE (value_type (array)), - low_bound); + return empty_array (TYPE_TARGET_TYPE (type0), low_bound); else { struct type *arr_type0 = - to_fixed_array_type (TYPE_TARGET_TYPE (value_type (array)), - NULL, 1); + to_fixed_array_type (TYPE_TARGET_TYPE (type0), NULL, 1); return ada_value_slice_from_ptr (array, arr_type0, longest_to_int (low_bound), @@ -10323,7 +10501,7 @@ ada_is_range_type_name (const char *name) int ada_is_modular_type (struct type *type) { - struct type *subranged_type = base_type (type); + struct type *subranged_type = get_base_type (type); return (subranged_type != NULL && TYPE_CODE (type) == TYPE_CODE_RANGE && TYPE_CODE (subranged_type) == TYPE_CODE_INT @@ -10394,19 +10572,7 @@ ada_modulus (struct type *type) a few times already, and these changes affect the implementation of these catchpoints. In order to be able to support several variants of the runtime, we use a sniffer that will determine - the runtime variant used by the program being debugged. - - At this time, we do not support the use of conditions on Ada exception - catchpoints. The COND and COND_STRING fields are therefore set - to NULL (most of the time, see below). - - Conditions where EXP_STRING, COND, and COND_STRING are used: - - When a user specifies the name of a specific exception in the case - of catchpoints on Ada exceptions, we store the name of that exception - in the EXP_STRING. We then translate this request into an actual - condition stored in COND_STRING, and then parse it into an expression - stored in COND. */ + the runtime variant used by the program being debugged. */ /* The different types of catchpoints that we introduced for catching Ada exceptions. */ @@ -10480,40 +10646,83 @@ static const struct exception_support_info exception_support_info_fallback = ada_unhandled_exception_name_addr_from_raise }; -/* For each executable, we sniff which exception info structure to use - and cache it in the following global variable. */ +/* Return nonzero if we can detect the exception support routines + described in EINFO. + + This function errors out if an abnormal situation is detected + (for instance, if we find the exception support routines, but + that support is found to be incomplete). */ + +static int +ada_has_this_exception_support (const struct exception_support_info *einfo) +{ + struct symbol *sym; + + /* The symbol we're looking up is provided by a unit in the GNAT runtime + 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, VAR_DOMAIN); + if (sym == NULL) + { + /* Perhaps we did not find our symbol because the Ada runtime was + compiled without debugging info, or simply stripped of it. + It happens on some GNU/Linux distributions for instance, where + users have to install a separate debug package in order to get + the runtime's debugging info. In that situation, let the user + know why we cannot insert an Ada exception catchpoint. + + Note: Just for the purpose of inserting our Ada exception + catchpoint, we could rely purely on the associated minimal symbol. + But we would be operating in degraded mode anyway, since we are + still lacking the debugging info needed later on to extract + 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. */ + if (lookup_minimal_symbol (einfo->catch_exception_sym, NULL, NULL)) + error (_("Your Ada runtime appears to be missing some debugging " + "information.\nCannot insert Ada exception catchpoint " + "in this configuration.")); + + return 0; + } -static const struct exception_support_info *exception_info = NULL; + /* Make sure that the symbol we found corresponds to a function. */ + + if (SYMBOL_CLASS (sym) != LOC_BLOCK) + error (_("Symbol \"%s\" is not a function (class = %d)"), + SYMBOL_LINKAGE_NAME (sym), SYMBOL_CLASS (sym)); + + return 1; +} /* Inspect the Ada runtime and determine which exception info structure should be used to provide support for exception catchpoints. - This function will always set exception_info, or raise an error. */ + This function will always set the per-inferior exception_info, + or raise an error. */ static void ada_exception_support_info_sniffer (void) { + struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ()); struct symbol *sym; /* If the exception info is already known, then no need to recompute it. */ - if (exception_info != NULL) + if (data->exception_info != NULL) return; /* Check the latest (default) exception support info. */ - sym = standard_lookup (default_exception_support_info.catch_exception_sym, - NULL, VAR_DOMAIN); - if (sym != NULL) + if (ada_has_this_exception_support (&default_exception_support_info)) { - exception_info = &default_exception_support_info; + data->exception_info = &default_exception_support_info; return; } /* Try our fallback exception suport info. */ - sym = standard_lookup (exception_support_info_fallback.catch_exception_sym, - NULL, VAR_DOMAIN); - if (sym != NULL) + if (ada_has_this_exception_support (&exception_support_info_fallback)) { - exception_info = &exception_support_info_fallback; + data->exception_info = &exception_support_info_fallback; return; } @@ -10541,20 +10750,7 @@ ada_exception_support_info_sniffer (void) out by the linker... In any case, at this point it is not worth supporting this feature. */ - error (_("Cannot insert catchpoints in this configuration.")); -} - -/* An observer of "executable_changed" events. - Its role is to clear certain cached values that need to be recomputed - each time a new executable is loaded by GDB. */ - -static void -ada_executable_changed_observer (void) -{ - /* If the executable changed, then it is possible that the Ada runtime - is different. So we need to invalidate the exception support info - cache. */ - exception_info = NULL; + error (_("Cannot insert Ada exception catchpoints in this configuration.")); } /* True iff FRAME is very likely to be that of a function that is @@ -10656,6 +10852,7 @@ ada_unhandled_exception_name_addr_from_raise (void) { int frame_level; struct frame_info *fi; + struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ()); /* To determine the name of this exception, we need to select the frame corresponding to RAISE_SYM_NAME. This frame is @@ -10673,7 +10870,7 @@ ada_unhandled_exception_name_addr_from_raise (void) find_frame_funname (fi, &func_name, &func_lang, NULL); if (func_name != NULL - && strcmp (func_name, exception_info->catch_exception_sym) == 0) + && strcmp (func_name, data->exception_info->catch_exception_sym) == 0) break; /* We found the frame we were looking for... */ fi = get_prev_frame (fi); } @@ -10695,6 +10892,8 @@ static CORE_ADDR ada_exception_name_addr_1 (enum exception_catchpoint_kind ex, struct breakpoint *b) { + struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ()); + switch (ex) { case ex_catch_exception: @@ -10702,7 +10901,7 @@ ada_exception_name_addr_1 (enum exception_catchpoint_kind ex, break; case ex_catch_exception_unhandled: - return exception_info->unhandled_exception_name_addr (); + return data->exception_info->unhandled_exception_name_addr (); break; case ex_catch_assert: @@ -10743,12 +10942,226 @@ ada_exception_name_addr (enum exception_catchpoint_kind ex, return result; } +static struct symtab_and_line ada_exception_sal (enum exception_catchpoint_kind, + char *, char **, + const struct breakpoint_ops **); +static char *ada_exception_catchpoint_cond_string (const char *excep_string); + +/* Ada catchpoints. + + In the case of catchpoints on Ada exceptions, the catchpoint will + stop the target on every exception the program throws. When a user + specifies the name of a specific exception, we translate this + request into a condition expression (in text form), and then parse + it into an expression stored in each of the catchpoint's locations. + We then use this condition to check whether the exception that was + raised is the one the user is interested in. If not, then the + target is resumed again. We store the name of the requested + exception, in order to be able to re-set the condition expression + when symbols change. */ + +/* An instance of this type is used to represent an Ada catchpoint + breakpoint location. It includes a "struct bp_location" as a kind + of base class; users downcast to "struct bp_location *" when + needed. */ + +struct ada_catchpoint_location +{ + /* The base class. */ + struct bp_location base; + + /* The condition that checks whether the exception that was raised + is the specific exception the user specified on catchpoint + creation. */ + struct expression *excep_cond_expr; +}; + +/* Implement the DTOR method in the bp_location_ops structure for all + Ada exception catchpoint kinds. */ + +static void +ada_catchpoint_location_dtor (struct bp_location *bl) +{ + struct ada_catchpoint_location *al = (struct ada_catchpoint_location *) bl; + + xfree (al->excep_cond_expr); +} + +/* The vtable to be used in Ada catchpoint locations. */ + +static const struct bp_location_ops ada_catchpoint_location_ops = +{ + ada_catchpoint_location_dtor +}; + +/* An instance of this type is used to represent an Ada catchpoint. + It includes a "struct breakpoint" as a kind of base class; users + downcast to "struct breakpoint *" when needed. */ + +struct ada_catchpoint +{ + /* The base class. */ + struct breakpoint base; + + /* The name of the specific exception the user specified. */ + char *excep_string; +}; + +/* Parse the exception condition string in the context of each of the + catchpoint's locations, and store them for later evaluation. */ + +static void +create_excep_cond_exprs (struct ada_catchpoint *c) +{ + struct cleanup *old_chain; + struct bp_location *bl; + char *cond_string; + + /* Nothing to do if there's no specific exception to catch. */ + if (c->excep_string == NULL) + return; + + /* Same if there are no locations... */ + if (c->base.loc == NULL) + return; + + /* Compute the condition expression in text form, from the specific + expection we want to catch. */ + cond_string = ada_exception_catchpoint_cond_string (c->excep_string); + old_chain = make_cleanup (xfree, cond_string); + + /* Iterate over all the catchpoint's locations, and parse an + expression for each. */ + for (bl = c->base.loc; bl != NULL; bl = bl->next) + { + struct ada_catchpoint_location *ada_loc + = (struct ada_catchpoint_location *) bl; + struct expression *exp = NULL; + + if (!bl->shlib_disabled) + { + volatile struct gdb_exception e; + char *s; + + s = cond_string; + TRY_CATCH (e, RETURN_MASK_ERROR) + { + exp = parse_exp_1 (&s, block_for_pc (bl->address), 0); + } + if (e.reason < 0) + warning (_("failed to reevaluate internal exception condition " + "for catchpoint %d: %s"), + c->base.number, e.message); + } + + ada_loc->excep_cond_expr = exp; + } + + do_cleanups (old_chain); +} + +/* Implement the DTOR method in the breakpoint_ops structure for all + exception catchpoint kinds. */ + +static void +dtor_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) +{ + struct ada_catchpoint *c = (struct ada_catchpoint *) b; + + xfree (c->excep_string); + + bkpt_breakpoint_ops.dtor (b); +} + +/* Implement the ALLOCATE_LOCATION method in the breakpoint_ops + structure for all exception catchpoint kinds. */ + +static struct bp_location * +allocate_location_exception (enum exception_catchpoint_kind ex, + struct breakpoint *self) +{ + struct ada_catchpoint_location *loc; + + loc = XNEW (struct ada_catchpoint_location); + init_bp_location (&loc->base, &ada_catchpoint_location_ops, self); + loc->excep_cond_expr = NULL; + return &loc->base; +} + +/* Implement the RE_SET method in the breakpoint_ops structure for all + exception catchpoint kinds. */ + +static void +re_set_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) +{ + struct ada_catchpoint *c = (struct ada_catchpoint *) b; + + /* Call the base class's method. This updates the catchpoint's + locations. */ + bkpt_breakpoint_ops.re_set (b); + + /* Reparse the exception conditional expressions. One for each + location. */ + create_excep_cond_exprs (c); +} + +/* Returns true if we should stop for this breakpoint hit. If the + user specified a specific exception, we only want to cause a stop + if the program thrown that exception. */ + +static int +should_stop_exception (const struct bp_location *bl) +{ + struct ada_catchpoint *c = (struct ada_catchpoint *) bl->owner; + const struct ada_catchpoint_location *ada_loc + = (const struct ada_catchpoint_location *) bl; + volatile struct gdb_exception ex; + int stop; + + /* With no specific exception, should always stop. */ + if (c->excep_string == NULL) + return 1; + + if (ada_loc->excep_cond_expr == NULL) + { + /* We will have a NULL expression if back when we were creating + the expressions, this location's had failed to parse. */ + return 1; + } + + stop = 1; + TRY_CATCH (ex, RETURN_MASK_ALL) + { + struct value *mark; + + mark = value_mark (); + stop = value_true (evaluate_expression (ada_loc->excep_cond_expr)); + value_free_to_mark (mark); + } + if (ex.reason < 0) + exception_fprintf (gdb_stderr, ex, + _("Error in testing exception condition:\n")); + return stop; +} + +/* Implement the CHECK_STATUS method in the breakpoint_ops structure + for all exception catchpoint kinds. */ + +static void +check_status_exception (enum exception_catchpoint_kind ex, bpstat bs) +{ + bs->stop = should_stop_exception (bs->bp_location_at); +} + /* Implement the PRINT_IT method in the breakpoint_ops structure for all exception catchpoint kinds. */ static enum print_stop_action -print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) +print_it_exception (enum exception_catchpoint_kind ex, bpstat bs) { + struct ui_out *uiout = current_uiout; + struct breakpoint *b = bs->breakpoint_at; + annotate_catchpoint (b->number); if (ui_out_is_mi_like_p (uiout)) @@ -10758,7 +11171,9 @@ print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); } - ui_out_text (uiout, "\nCatchpoint "); + ui_out_text (uiout, + b->disposition == disp_del ? "\nTemporary catchpoint " + : "\nCatchpoint "); ui_out_field_int (uiout, "bkptno", b->number); ui_out_text (uiout, ", "); @@ -10783,7 +11198,7 @@ print_it_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) just replace the exception name by the generic string "exception" - it will read as "an exception" in the notification we are about to print. */ - sprintf (exception_name, "exception"); + memcpy (exception_name, "exception", sizeof ("exception")); } /* In the case of unhandled exception breakpoints, we print the exception name as "unhandled EXCEPTION_NAME", to make @@ -10817,6 +11232,8 @@ static void print_one_exception (enum exception_catchpoint_kind ex, struct breakpoint *b, struct bp_location **last_loc) { + struct ui_out *uiout = current_uiout; + struct ada_catchpoint *c = (struct ada_catchpoint *) b; struct value_print_options opts; get_user_print_options (&opts); @@ -10831,10 +11248,10 @@ print_one_exception (enum exception_catchpoint_kind ex, switch (ex) { case ex_catch_exception: - if (b->exp_string != NULL) + if (c->excep_string != NULL) { - char *msg = xstrprintf (_("`%s' Ada exception"), b->exp_string); - + char *msg = xstrprintf (_("`%s' Ada exception"), c->excep_string); + ui_out_field_string (uiout, "what", msg); xfree (msg); } @@ -10864,24 +11281,35 @@ static void print_mention_exception (enum exception_catchpoint_kind ex, struct breakpoint *b) { + struct ada_catchpoint *c = (struct ada_catchpoint *) b; + struct ui_out *uiout = current_uiout; + + ui_out_text (uiout, b->disposition == disp_del ? _("Temporary catchpoint ") + : _("Catchpoint ")); + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ": "); + switch (ex) { case ex_catch_exception: - if (b->exp_string != NULL) - printf_filtered (_("Catchpoint %d: `%s' Ada exception"), - b->number, b->exp_string); + if (c->excep_string != NULL) + { + char *info = xstrprintf (_("`%s' Ada exception"), c->excep_string); + struct cleanup *old_chain = make_cleanup (xfree, info); + + ui_out_text (uiout, info); + do_cleanups (old_chain); + } else - printf_filtered (_("Catchpoint %d: all Ada exceptions"), b->number); - + ui_out_text (uiout, _("all Ada exceptions")); break; case ex_catch_exception_unhandled: - printf_filtered (_("Catchpoint %d: unhandled Ada exceptions"), - b->number); + ui_out_text (uiout, _("unhandled Ada exceptions")); break; case ex_catch_assert: - printf_filtered (_("Catchpoint %d: failed Ada assertions"), b->number); + ui_out_text (uiout, _("failed Ada assertions")); break; default: @@ -10897,12 +11325,14 @@ static void print_recreate_exception (enum exception_catchpoint_kind ex, struct breakpoint *b, struct ui_file *fp) { + struct ada_catchpoint *c = (struct ada_catchpoint *) b; + switch (ex) { case ex_catch_exception: fprintf_filtered (fp, "catch exception"); - if (b->exp_string != NULL) - fprintf_filtered (fp, " %s", b->exp_string); + if (c->excep_string != NULL) + fprintf_filtered (fp, " %s", c->excep_string); break; case ex_catch_exception_unhandled: @@ -10916,14 +11346,39 @@ print_recreate_exception (enum exception_catchpoint_kind ex, default: internal_error (__FILE__, __LINE__, _("unexpected catchpoint type")); } + print_recreate_thread (b, fp); } /* Virtual table for "catch exception" breakpoints. */ +static void +dtor_catch_exception (struct breakpoint *b) +{ + dtor_exception (ex_catch_exception, b); +} + +static struct bp_location * +allocate_location_catch_exception (struct breakpoint *self) +{ + return allocate_location_exception (ex_catch_exception, self); +} + +static void +re_set_catch_exception (struct breakpoint *b) +{ + re_set_exception (ex_catch_exception, b); +} + +static void +check_status_catch_exception (bpstat bs) +{ + check_status_exception (ex_catch_exception, bs); +} + static enum print_stop_action -print_it_catch_exception (struct breakpoint *b) +print_it_catch_exception (bpstat bs) { - return print_it_exception (ex_catch_exception, b); + return print_it_exception (ex_catch_exception, bs); } static void @@ -10944,25 +11399,38 @@ print_recreate_catch_exception (struct breakpoint *b, struct ui_file *fp) print_recreate_exception (ex_catch_exception, b, fp); } -static struct breakpoint_ops catch_exception_breakpoint_ops = -{ - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ - NULL, /* resources_needed */ - print_it_catch_exception, - print_one_catch_exception, - NULL, /* print_one_detail */ - print_mention_catch_exception, - print_recreate_catch_exception -}; +static struct breakpoint_ops catch_exception_breakpoint_ops; /* Virtual table for "catch exception unhandled" breakpoints. */ +static void +dtor_catch_exception_unhandled (struct breakpoint *b) +{ + dtor_exception (ex_catch_exception_unhandled, b); +} + +static struct bp_location * +allocate_location_catch_exception_unhandled (struct breakpoint *self) +{ + return allocate_location_exception (ex_catch_exception_unhandled, self); +} + +static void +re_set_catch_exception_unhandled (struct breakpoint *b) +{ + re_set_exception (ex_catch_exception_unhandled, b); +} + +static void +check_status_catch_exception_unhandled (bpstat bs) +{ + check_status_exception (ex_catch_exception_unhandled, bs); +} + static enum print_stop_action -print_it_catch_exception_unhandled (struct breakpoint *b) +print_it_catch_exception_unhandled (bpstat bs) { - return print_it_exception (ex_catch_exception_unhandled, b); + return print_it_exception (ex_catch_exception_unhandled, bs); } static void @@ -10985,24 +11453,38 @@ print_recreate_catch_exception_unhandled (struct breakpoint *b, print_recreate_exception (ex_catch_exception_unhandled, b, fp); } -static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops = { - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ - NULL, /* resources_needed */ - print_it_catch_exception_unhandled, - print_one_catch_exception_unhandled, - NULL, /* print_one_detail */ - print_mention_catch_exception_unhandled, - print_recreate_catch_exception_unhandled -}; +static struct breakpoint_ops catch_exception_unhandled_breakpoint_ops; /* Virtual table for "catch assert" breakpoints. */ +static void +dtor_catch_assert (struct breakpoint *b) +{ + dtor_exception (ex_catch_assert, b); +} + +static struct bp_location * +allocate_location_catch_assert (struct breakpoint *self) +{ + return allocate_location_exception (ex_catch_assert, self); +} + +static void +re_set_catch_assert (struct breakpoint *b) +{ + return re_set_exception (ex_catch_assert, b); +} + +static void +check_status_catch_assert (bpstat bs) +{ + check_status_exception (ex_catch_assert, bs); +} + static enum print_stop_action -print_it_catch_assert (struct breakpoint *b) +print_it_catch_assert (bpstat bs) { - return print_it_exception (ex_catch_assert, b); + return print_it_exception (ex_catch_assert, bs); } static void @@ -11023,27 +11505,7 @@ print_recreate_catch_assert (struct breakpoint *b, struct ui_file *fp) print_recreate_exception (ex_catch_assert, b, fp); } -static struct breakpoint_ops catch_assert_breakpoint_ops = { - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ - NULL, /* resources_needed */ - print_it_catch_assert, - print_one_catch_assert, - NULL, /* print_one_detail */ - print_mention_catch_assert, - print_recreate_catch_assert -}; - -/* Return non-zero if B is an Ada exception catchpoint. */ - -int -ada_exception_catchpoint_p (struct breakpoint *b) -{ - return (b->ops == &catch_exception_breakpoint_ops - || b->ops == &catch_exception_unhandled_breakpoint_ops - || b->ops == &catch_assert_breakpoint_ops); -} +static struct breakpoint_ops catch_assert_breakpoint_ops; /* Return a newly allocated copy of the first space-separated token in ARGSP, and then adjust ARGSP to point immediately after that @@ -11087,13 +11549,13 @@ ada_get_next_arg (char **argsp) /* Split the arguments specified in a "catch exception" command. Set EX to the appropriate catchpoint type. - Set EXP_STRING to the name of the specific exception if + Set EXCEP_STRING to the name of the specific exception if specified by the user. */ static void catch_ada_exception_command_split (char *args, enum exception_catchpoint_kind *ex, - char **exp_string) + char **excep_string) { struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); char *exception_name; @@ -11116,19 +11578,19 @@ catch_ada_exception_command_split (char *args, { /* Catch all exceptions. */ *ex = ex_catch_exception; - *exp_string = NULL; + *excep_string = NULL; } else if (strcmp (exception_name, "unhandled") == 0) { /* Catch unhandled exceptions. */ *ex = ex_catch_exception_unhandled; - *exp_string = NULL; + *excep_string = NULL; } else { /* Catch a specific exception. */ *ex = ex_catch_exception; - *exp_string = exception_name; + *excep_string = exception_name; } } @@ -11138,18 +11600,20 @@ catch_ada_exception_command_split (char *args, static const char * ada_exception_sym_name (enum exception_catchpoint_kind ex) { - gdb_assert (exception_info != NULL); + struct ada_inferior_data *data = get_ada_inferior_data (current_inferior ()); + + gdb_assert (data->exception_info != NULL); switch (ex) { case ex_catch_exception: - return (exception_info->catch_exception_sym); + return (data->exception_info->catch_exception_sym); break; case ex_catch_exception_unhandled: - return (exception_info->catch_exception_unhandled_sym); + return (data->exception_info->catch_exception_unhandled_sym); break; case ex_catch_assert: - return (exception_info->catch_assert_sym); + return (data->exception_info->catch_assert_sym); break; default: internal_error (__FILE__, __LINE__, @@ -11160,7 +11624,7 @@ ada_exception_sym_name (enum exception_catchpoint_kind ex) /* Return the breakpoint ops "virtual table" used for catchpoints of the EX kind. */ -static struct breakpoint_ops * +static const struct breakpoint_ops * ada_exception_breakpoint_ops (enum exception_catchpoint_kind ex) { switch (ex) @@ -11189,13 +11653,13 @@ ada_exception_breakpoint_ops (enum exception_catchpoint_kind ex) deallocated later. */ static char * -ada_exception_catchpoint_cond_string (const char *exp_string) +ada_exception_catchpoint_cond_string (const char *excep_string) { int i; /* The standard exceptions are a special case. They are defined in runtime units that have been compiled without debugging info; if - EXP_STRING is the not-fully-qualified name of a standard + EXCEP_STRING is the not-fully-qualified name of a standard exception (e.g. "constraint_error") then, during the evaluation of the condition expression, the symbol lookup on this name would *not* return this standard exception. The catchpoint condition @@ -11214,141 +11678,123 @@ ada_exception_catchpoint_cond_string (const char *exp_string) for (i = 0; i < sizeof (standard_exc) / sizeof (char *); i++) { - if (strcmp (standard_exc [i], exp_string) == 0) + if (strcmp (standard_exc [i], excep_string) == 0) { return xstrprintf ("long_integer (e) = long_integer (&standard.%s)", - exp_string); + excep_string); } } - return xstrprintf ("long_integer (e) = long_integer (&%s)", exp_string); -} - -/* Return the expression corresponding to COND_STRING evaluated at SAL. */ - -static struct expression * -ada_parse_catchpoint_condition (char *cond_string, - struct symtab_and_line sal) -{ - return (parse_exp_1 (&cond_string, block_for_pc (sal.pc), 0)); + return xstrprintf ("long_integer (e) = long_integer (&%s)", excep_string); } /* Return the symtab_and_line that should be used to insert an exception catchpoint of the TYPE kind. - EX_STRING should contain the name of a specific exception - that the catchpoint should catch, or NULL otherwise. + EXCEP_STRING should contain the name of a specific exception that + the catchpoint should catch, or NULL otherwise. - The idea behind all the remaining parameters is that their names match - the name of certain fields in the breakpoint structure that are used to - handle exception catchpoints. This function returns the value to which - these fields should be set, depending on the type of catchpoint we need - to create. - - If COND and COND_STRING are both non-NULL, any value they might - hold will be free'ed, and then replaced by newly allocated ones. - These parameters are left untouched otherwise. */ + ADDR_STRING returns the name of the function where the real + breakpoint that implements the catchpoints is set, depending on the + type of catchpoint we need to create. */ static struct symtab_and_line -ada_exception_sal (enum exception_catchpoint_kind ex, char *exp_string, - char **addr_string, char **cond_string, - struct expression **cond, struct breakpoint_ops **ops) +ada_exception_sal (enum exception_catchpoint_kind ex, char *excep_string, + char **addr_string, const struct breakpoint_ops **ops) { const char *sym_name; struct symbol *sym; - struct symtab_and_line sal; /* First, find out which exception support info to use. */ ada_exception_support_info_sniffer (); /* Then lookup the function on which we will break in order to catch the Ada exceptions requested by the user. */ - sym_name = ada_exception_sym_name (ex); sym = standard_lookup (sym_name, NULL, VAR_DOMAIN); - /* The symbol we're looking up is provided by a unit in the GNAT runtime - that should be compiled with debugging information. As a result, we - expect to find that symbol in the symtabs. If we don't find it, then - the target most likely does not support Ada exceptions, or we cannot - insert exception breakpoints yet, because the GNAT runtime hasn't been - loaded yet. */ - - /* brobecker/2006-12-26: It is conceivable that the runtime was compiled - in such a way that no debugging information is produced for the symbol - we are looking for. In this case, we could search the minimal symbols - as a fall-back mechanism. This would still be operating in degraded - mode, however, as we would still be missing the debugging information - that is needed in order to extract 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. */ + /* We can assume that SYM is not NULL at this stage. If the symbol + did not exist, ada_exception_support_info_sniffer would have + raised an exception. - if (sym == NULL) - error (_("Unable to break on '%s' in this configuration."), sym_name); - - /* Make sure that the symbol we found corresponds to a function. */ - if (SYMBOL_CLASS (sym) != LOC_BLOCK) - error (_("Symbol \"%s\" is not a function (class = %d)"), - sym_name, SYMBOL_CLASS (sym)); - - sal = find_function_start_sal (sym, 1); + Also, ada_exception_support_info_sniffer should have already + verified that SYM is a function symbol. */ + gdb_assert (sym != NULL); + gdb_assert (SYMBOL_CLASS (sym) == LOC_BLOCK); /* Set ADDR_STRING. */ - *addr_string = xstrdup (sym_name); - /* Set the COND and COND_STRING (if not NULL). */ - - if (cond_string != NULL && cond != NULL) - { - if (*cond_string != NULL) - { - xfree (*cond_string); - *cond_string = NULL; - } - if (*cond != NULL) - { - xfree (*cond); - *cond = NULL; - } - if (exp_string != NULL) - { - *cond_string = ada_exception_catchpoint_cond_string (exp_string); - *cond = ada_parse_catchpoint_condition (*cond_string, sal); - } - } - /* Set OPS. */ *ops = ada_exception_breakpoint_ops (ex); - return sal; + return find_function_start_sal (sym, 1); } /* Parse the arguments (ARGS) of the "catch exception" command. - Set TYPE to the appropriate exception catchpoint type. If the user asked the catchpoint to catch only a specific exception, then save the exception name in ADDR_STRING. See ada_exception_sal for a description of all the remaining function arguments of this function. */ -struct symtab_and_line +static struct symtab_and_line ada_decode_exception_location (char *args, char **addr_string, - char **exp_string, char **cond_string, - struct expression **cond, - struct breakpoint_ops **ops) + char **excep_string, + const struct breakpoint_ops **ops) { enum exception_catchpoint_kind ex; - catch_ada_exception_command_split (args, &ex, exp_string); - return ada_exception_sal (ex, *exp_string, addr_string, cond_string, - cond, ops); + catch_ada_exception_command_split (args, &ex, excep_string); + return ada_exception_sal (ex, *excep_string, addr_string, ops); +} + +/* Create an Ada exception catchpoint. */ + +static void +create_ada_exception_catchpoint (struct gdbarch *gdbarch, + struct symtab_and_line sal, + char *addr_string, + char *excep_string, + const struct breakpoint_ops *ops, + int tempflag, + int from_tty) +{ + struct ada_catchpoint *c; + + c = XNEW (struct ada_catchpoint); + init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string, + ops, tempflag, from_tty); + c->excep_string = excep_string; + create_excep_cond_exprs (c); + install_breakpoint (0, &c->base, 1); } -struct symtab_and_line +/* Implement the "catch exception" command. */ + +static void +catch_ada_exception_command (char *arg, int from_tty, + struct cmd_list_element *command) +{ + struct gdbarch *gdbarch = get_current_arch (); + int tempflag; + struct symtab_and_line sal; + char *addr_string = NULL; + char *excep_string = NULL; + const struct breakpoint_ops *ops = NULL; + + tempflag = get_cmd_context (command) == CATCH_TEMPORARY; + + if (!arg) + arg = ""; + sal = ada_decode_exception_location (arg, &addr_string, &excep_string, &ops); + create_ada_exception_catchpoint (gdbarch, sal, addr_string, + excep_string, ops, tempflag, from_tty); +} + +static struct symtab_and_line ada_decode_assert_location (char *args, char **addr_string, - struct breakpoint_ops **ops) + const struct breakpoint_ops **ops) { /* Check that no argument where provided at the end of the command. */ @@ -11360,10 +11806,29 @@ ada_decode_assert_location (char *args, char **addr_string, error (_("Junk at end of arguments.")); } - return ada_exception_sal (ex_catch_assert, NULL, addr_string, NULL, NULL, - ops); + return ada_exception_sal (ex_catch_assert, NULL, addr_string, ops); } +/* Implement the "catch assert" command. */ + +static void +catch_assert_command (char *arg, int from_tty, + struct cmd_list_element *command) +{ + struct gdbarch *gdbarch = get_current_arch (); + int tempflag; + struct symtab_and_line sal; + char *addr_string = NULL; + const struct breakpoint_ops *ops = NULL; + + tempflag = get_cmd_context (command) == CATCH_TEMPORARY; + + if (!arg) + arg = ""; + sal = ada_decode_assert_location (arg, &addr_string, &ops); + create_ada_exception_catchpoint (gdbarch, sal, addr_string, + NULL, ops, tempflag, from_tty); +} /* Operators */ /* Information about operators given special treatment in functions below. */ @@ -11881,6 +12346,8 @@ const struct language_defn ada_language_defn = { ada_print_array_index, default_pass_by_reference, c_get_string, + compare_names, + ada_iterate_over_symbols, LANG_MAGIC }; @@ -11909,11 +12376,54 @@ show_ada_command (char *args, int from_tty) cmd_show_list (show_ada_list, from_tty, ""); } +static void +initialize_ada_catchpoint_ops (void) +{ + struct breakpoint_ops *ops; + + initialize_breakpoint_ops (); + + ops = &catch_exception_breakpoint_ops; + *ops = bkpt_breakpoint_ops; + ops->dtor = dtor_catch_exception; + ops->allocate_location = allocate_location_catch_exception; + ops->re_set = re_set_catch_exception; + ops->check_status = check_status_catch_exception; + ops->print_it = print_it_catch_exception; + ops->print_one = print_one_catch_exception; + ops->print_mention = print_mention_catch_exception; + ops->print_recreate = print_recreate_catch_exception; + + ops = &catch_exception_unhandled_breakpoint_ops; + *ops = bkpt_breakpoint_ops; + ops->dtor = dtor_catch_exception_unhandled; + ops->allocate_location = allocate_location_catch_exception_unhandled; + ops->re_set = re_set_catch_exception_unhandled; + ops->check_status = check_status_catch_exception_unhandled; + ops->print_it = print_it_catch_exception_unhandled; + ops->print_one = print_one_catch_exception_unhandled; + ops->print_mention = print_mention_catch_exception_unhandled; + ops->print_recreate = print_recreate_catch_exception_unhandled; + + ops = &catch_assert_breakpoint_ops; + *ops = bkpt_breakpoint_ops; + ops->dtor = dtor_catch_assert; + ops->allocate_location = allocate_location_catch_assert; + ops->re_set = re_set_catch_assert; + ops->check_status = check_status_catch_assert; + ops->print_it = print_it_catch_assert; + ops->print_one = print_one_catch_assert; + ops->print_mention = print_mention_catch_assert; + ops->print_recreate = print_recreate_catch_assert; +} + void _initialize_ada_language (void) { add_language (&ada_language_defn); + initialize_ada_catchpoint_ops (); + add_prefix_cmd ("ada", no_class, set_ada_command, _("Prefix command for changing Ada-specfic settings"), &set_ada_list, "set ada ", 0, &setlist); @@ -11936,6 +12446,21 @@ this incurs a slight performance penalty, so it is recommended to NOT change\n\ this option to \"off\" unless necessary."), NULL, NULL, &set_ada_list, &show_ada_list); + add_catch_command ("exception", _("\ +Catch Ada exceptions, when raised.\n\ +With an argument, catch only exceptions with the given name."), + catch_ada_exception_command, + NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); + add_catch_command ("assert", _("\ +Catch failed Ada assertions, when raised.\n\ +With an argument, catch only exceptions with the given name."), + catch_assert_command, + NULL, + CATCH_PERMANENT, + CATCH_TEMPORARY); + varsize_limit = 65536; obstack_init (&symbol_list_obstack); @@ -11944,8 +12469,6 @@ this option to \"off\" unless necessary."), (256, htab_hash_string, (int (*)(const void *, const void *)) streq, NULL, xcalloc, xfree); - observer_attach_executable_changed (ada_executable_changed_observer); - /* Setup per-inferior data. */ observer_attach_inferior_exit (ada_inferior_exit); ada_inferior_data diff --git a/contrib/gdb-7/gdb/ada-lang.h b/contrib/gdb-7/gdb/ada-lang.h index 7902124c07..9ab7b2dd17 100644 --- a/contrib/gdb-7/gdb/ada-lang.h +++ b/contrib/gdb-7/gdb/ada-lang.h @@ -1,7 +1,7 @@ /* Ada language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992, 1997-2005, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. @@ -22,6 +22,7 @@ #define ADA_LANG_H 1 struct frame_info; +struct inferior; #include "value.h" #include "gdbtypes.h" @@ -237,15 +238,6 @@ extern int user_select_syms (struct ada_symbol_info *, int, int); extern int get_selections (int *, int, int, int, char *); -extern char *ada_start_decode_line_1 (char *); - -extern struct symtabs_and_lines ada_finish_decode_line_1 (char **, - struct symtab *, - int, char ***); - -extern struct symtabs_and_lines ada_sals_for_line (const char*, int, - int, char***, int); - extern int ada_scan_number (const char *, int, LONGEST *, int *); extern struct type *ada_parent_type (struct type *); @@ -373,6 +365,8 @@ extern char *ada_breakpoint_rewrite (char *, int *); extern char *ada_main_name (void); +extern char *ada_name_for_lookup (const char *name); + /* Tasking-related: ada-tasks.c */ extern int valid_task_id (int); @@ -383,19 +377,10 @@ typedef void (ada_task_list_iterator_ftype) (struct ada_task_info *task); extern void iterate_over_live_ada_tasks (ada_task_list_iterator_ftype *iterator); -extern int ada_build_task_list (int warn_if_null); - -extern int ada_exception_catchpoint_p (struct breakpoint *b); - -extern struct symtab_and_line - ada_decode_exception_location (char *args, char **addr_string, - char **exp_string, char **cond_string, - struct expression **cond, - struct breakpoint_ops **ops); - -extern struct symtab_and_line - ada_decode_assert_location (char *args, char **addr_string, - struct breakpoint_ops **ops); +extern int ada_build_task_list (void); +extern void print_ada_task_info (struct ui_out *uiout, + char *taskno_str, + struct inferior *inf); #endif diff --git a/contrib/gdb-7/gdb/ada-lex.c b/contrib/gdb-7/gdb/ada-lex.c index aea4684c50..92cd92cf65 100644 --- a/contrib/gdb-7/gdb/ada-lex.c +++ b/contrib/gdb-7/gdb/ada-lex.c @@ -608,8 +608,8 @@ char *yytext; #line 1 "ada-lex.l" #define INITIAL 0 /* FLEX lexer for Ada expressions, for GDB. - Copyright (C) 1994, 1997, 1998, 2000, 2001, 2002, 2003, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1994, 1997-1998, 2000-2003, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ada-operator.def b/contrib/gdb-7/gdb/ada-operator.def index c3dc8e1716..8738250809 100644 --- a/contrib/gdb-7/gdb/ada-operator.def +++ b/contrib/gdb-7/gdb/ada-operator.def @@ -1,7 +1,7 @@ /* Ada language operator definitions for GDB, the GNU debugger. - Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992, 1997-2005, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ada-operator.inc b/contrib/gdb-7/gdb/ada-operator.inc deleted file mode 100644 index 0aa1b4c8c4..0000000000 --- a/contrib/gdb-7/gdb/ada-operator.inc +++ /dev/null @@ -1,102 +0,0 @@ -/* Ada language operator definitions for GDB, the GNU debugger. - - Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2007, 2008, 2009, 2010 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 . */ - - /* X IN A'RANGE(N). N is an immediate operand, surrounded by - BINOP_IN_BOUNDS before and after. A is an array, X an index - value. Evaluates to true iff X is within range of the Nth - dimension (1-based) of A. (A multi-dimensional array - type is represented as array of array of ...) */ - BINOP_IN_BOUNDS = OP_EXTENDED0, - - /* X IN L .. U. True iff L <= X <= U. */ - TERNOP_IN_RANGE, - - /* Ada attributes ('Foo). */ - OP_ATR_FIRST, - OP_ATR_LAST, - OP_ATR_LENGTH, - OP_ATR_IMAGE, - OP_ATR_MAX, - OP_ATR_MIN, - OP_ATR_MODULUS, - OP_ATR_POS, - OP_ATR_SIZE, - OP_ATR_TAG, - OP_ATR_VAL, - - /* Ada type qualification. It is encoded as for UNOP_CAST, above, - and denotes the TYPE'(EXPR) construct. */ - UNOP_QUAL, - - /* X IN TYPE. The `TYPE' argument is immediate, with - UNOP_IN_RANGE before and after it. True iff X is a member of - type TYPE (typically a subrange). */ - UNOP_IN_RANGE, - - /* An aggregate. A single immediate operand, N>0, gives - the number of component specifications that follow. The - immediate operand is followed by a second OP_AGGREGATE. - Next come N component specifications. A component - specification is either an OP_OTHERS (others=>...), an - OP_CHOICES (for named associations), or other expression (for - positional aggregates only). Aggregates currently - occur only as the right sides of assignments. */ - OP_AGGREGATE, - - /* An others clause. Followed by a single expression. */ - OP_OTHERS, - - /* An aggregate component association. A single immediate operand, N, - gives the number of choices that follow. This is followed by a second - OP_CHOICES operator. Next come N operands, each of which is an - expression, an OP_DISCRETE_RANGE, or an OP_NAME---the latter - for a simple name that must be a record component name and does - not correspond to a single existing symbol. After the N choice - indicators comes an expression giving the value. - - In an aggregate such as (X => E1, ...), where X is a simple - name, X could syntactically be either a component_selector_name - or an expression used as a discrete_choice, depending on the - aggregate's type context. Since this is not known at parsing - time, we don't attempt to disambiguate X if it has multiple - definitions, but instead supply an OP_NAME. If X has a single - definition, we represent it with an OP_VAR_VALUE, even though - it may turn out to be within a record aggregate. Aggregate - evaluation can use either OP_NAMEs or OP_VAR_VALUEs to get a - record field name, and can evaluate OP_VAR_VALUE normally to - get its value as an expression. Unfortunately, we lose out in - cases where X has multiple meanings and is part of an array - aggregate. I hope these are not common enough to annoy users, - who can work around the problem in any case by putting - parentheses around X. */ - OP_CHOICES, - - /* A positional aggregate component association. The operator is - followed by a single integer indicating the position in the - aggregate (0-based), followed by a second OP_POSITIONAL. Next - follows a single expression giving the component value. */ - OP_POSITIONAL, - - /* A range of values. Followed by two expressions giving the - upper and lower bounds of the range. */ - OP_DISCRETE_RANGE, - - /* End marker */ - OP_ADA_LAST, diff --git a/contrib/gdb-7/gdb/ada-tasks.c b/contrib/gdb-7/gdb/ada-tasks.c index 2cf62b9326..274d83a894 100644 --- a/contrib/gdb-7/gdb/ada-tasks.c +++ b/contrib/gdb-7/gdb/ada-tasks.c @@ -1,5 +1,5 @@ -/* Copyright (C) 1992, 1993, 1994, 1997, 1998, 1999, 2000, 2003, 2004, 2005, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +/* Copyright (C) 1992-1994, 1997-2000, 2003-2005, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -24,6 +24,8 @@ #include "gdbcore.h" #include "inferior.h" #include "gdbthread.h" +#include "progspace.h" +#include "objfiles.h" /* The name of the array in the GNAT runtime where the Ada Task Control Block of each task is stored. */ @@ -32,6 +34,11 @@ /* The maximum number of tasks known to the Ada runtime. */ static const int MAX_NUMBER_OF_KNOWN_TASKS = 1000; +/* The name of the variable in the GNAT runtime where the head of a task + chain is saved. This is an alternate mechanism to find the list of known + tasks. */ +#define KNOWN_TASKS_LIST "system__tasking__debug__first_task" + enum task_states { Unactivated, @@ -101,7 +108,7 @@ static const char *long_task_states[] = { /* The index of certain important fields in the Ada Task Control Block record and sub-records. */ -struct tcb_fieldnos +struct atcb_fieldnos { /* Fields in record Ada_Task_Control_Block. */ int common; @@ -114,6 +121,7 @@ struct tcb_fieldnos int priority; int image; int image_len; /* This field may be missing. */ + int activation_link; int call; int ll; @@ -125,37 +133,152 @@ struct tcb_fieldnos int call_self; }; -/* The type description for the ATCB record and subrecords, and - the associated tcb_fieldnos. For efficiency reasons, these are made - static globals so that we can compute them only once the first time - and reuse them later. Set to NULL if the types haven't been computed - yet, or if they may be obsolete (for instance after having loaded - a new binary). */ +/* This module's per-program-space data. */ -static struct type *atcb_type = NULL; -static struct type *atcb_common_type = NULL; -static struct type *atcb_ll_type = NULL; -static struct type *atcb_call_type = NULL; -static struct tcb_fieldnos fieldno; +struct ada_tasks_pspace_data +{ + /* Nonzero if the data has been initialized. If set to zero, + it means that the data has either not been initialized, or + has potentially become stale. */ + int initialized_p; -/* Set to 1 when the cached address of System.Tasking.Debug.Known_Tasks - might be stale and so needs to be recomputed. */ -static int ada_tasks_check_symbol_table = 1; + /* The ATCB record type. */ + struct type *atcb_type; + + /* The ATCB "Common" component type. */ + struct type *atcb_common_type; + + /* The type of the "ll" field, from the atcb_common_type. */ + struct type *atcb_ll_type; + + /* The type of the "call" field, from the atcb_common_type. */ + struct type *atcb_call_type; + + /* The index of various fields in the ATCB record and sub-records. */ + struct atcb_fieldnos atcb_fieldno; +}; + +/* Key to our per-program-space data. */ +static const struct program_space_data *ada_tasks_pspace_data_handle; -/* The list of Ada tasks. - - Note: To each task we associate a number that the user can use to - 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. */ typedef struct ada_task_info ada_task_info_s; DEF_VEC_O(ada_task_info_s); -static VEC(ada_task_info_s) *task_list = NULL; -/* When non-zero, this flag indicates that the current task_list - is obsolete, and should be recomputed before it is accessed. */ -static int stale_task_list_p = 1; +/* The kind of data structure used by the runtime to store the list + of Ada tasks. */ + +enum ada_known_tasks_kind +{ + /* Use this value when we haven't determined which kind of structure + is being used, or when we need to recompute it. + + We set the value of this enumerate to zero on purpose: This allows + us to use this enumerate in a structure where setting all fields + to zero will result in this kind being set to unknown. */ + ADA_TASKS_UNKNOWN = 0, + + /* This value means that we did not find any task list. Unless + there is a bug somewhere, this means that the inferior does not + use tasking. */ + ADA_TASKS_NOT_FOUND, + + /* This value means that the task list is stored as an array. + This is the usual method, as it causes very little overhead. + But this method is not always used, as it does use a certain + amount of memory, which might be scarse in certain environments. */ + ADA_TASKS_ARRAY, + + /* This value means that the task list is stored as a linked list. + This has more runtime overhead than the array approach, but + also require less memory when the number of tasks is small. */ + ADA_TASKS_LIST, +}; + +/* This module's per-inferior data. */ + +struct ada_tasks_inferior_data +{ + /* The type of data structure used by the runtime to store + the list of Ada tasks. The value of this field influences + the interpretation of the known_tasks_addr field below: + - ADA_TASKS_UNKNOWN: The value of known_tasks_addr hasn't + been determined yet; + - ADA_TASKS_NOT_FOUND: The program probably does not use tasking + and the known_tasks_addr is irrelevant; + - ADA_TASKS_ARRAY: The known_tasks is an array; + - ADA_TASKS_LIST: The known_tasks is a list. */ + enum ada_known_tasks_kind known_tasks_kind; + + /* The address of the known_tasks structure. This is where + the runtime stores the information for all Ada tasks. + The interpretation of this field depends on KNOWN_TASKS_KIND + above. */ + CORE_ADDR known_tasks_addr; + + /* When nonzero, this flag indicates that the task_list field + below is up to date. When set to zero, the list has either + not been initialized, or has potentially become stale. */ + int task_list_valid_p; + + /* The list of Ada tasks. + + Note: To each task we associate a number that the user can use to + 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. */ + VEC(ada_task_info_s) *task_list; +}; + +/* Key to our per-inferior data. */ +static const struct inferior_data *ada_tasks_inferior_data_handle; + +/* Return the ada-tasks module's data for the given program space (PSPACE). + If none is found, add a zero'ed one now. + + This function always returns a valid object. */ + +static struct ada_tasks_pspace_data * +get_ada_tasks_pspace_data (struct program_space *pspace) +{ + struct ada_tasks_pspace_data *data; + + data = program_space_data (pspace, ada_tasks_pspace_data_handle); + if (data == NULL) + { + data = XZALLOC (struct ada_tasks_pspace_data); + set_program_space_data (pspace, ada_tasks_pspace_data_handle, data); + } + + return data; +} + +/* Return the ada-tasks module's data for the given inferior (INF). + If none is found, add a zero'ed one now. + + This function always returns a valid object. + + Note that we could use an observer of the inferior-created event + to make sure that the ada-tasks per-inferior data always exists. + But we prefered this approach, as it avoids this entirely as long + as the user does not use any of the tasking features. This is + quite possible, particularly in the case where the inferior does + not use tasking. */ + +static struct ada_tasks_inferior_data * +get_ada_tasks_inferior_data (struct inferior *inf) +{ + struct ada_tasks_inferior_data *data; + + data = inferior_data (inf, ada_tasks_inferior_data_handle); + if (data == NULL) + { + data = XZALLOC (struct ada_tasks_inferior_data); + set_inferior_data (inf, ada_tasks_inferior_data_handle, data); + } + + return data; +} /* Return the task number of the task whose ptid is PTID, or zero if the task could not be found. */ @@ -164,26 +287,33 @@ int ada_get_task_number (ptid_t ptid) { int i; + struct inferior *inf = find_inferior_pid (ptid_get_pid (ptid)); + struct ada_tasks_inferior_data *data; + + gdb_assert (inf != NULL); + data = get_ada_tasks_inferior_data (inf); - for (i=0; i < VEC_length (ada_task_info_s, task_list); i++) - if (ptid_equal (VEC_index (ada_task_info_s, task_list, i)->ptid, ptid)) + for (i = 0; i < VEC_length (ada_task_info_s, data->task_list); i++) + if (ptid_equal (VEC_index (ada_task_info_s, data->task_list, i)->ptid, + ptid)) return i + 1; return 0; /* No matching task found. */ } -/* Return the task number of the task that matches TASK_ID, or zero - if the task could not be found. */ +/* Return the task number of the task running in inferior INF which + matches TASK_ID , or zero if the task could not be found. */ static int -get_task_number_from_id (CORE_ADDR task_id) +get_task_number_from_id (CORE_ADDR task_id, struct inferior *inf) { + struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf); int i; - for (i = 0; i < VEC_length (ada_task_info_s, task_list); i++) + for (i = 0; i < VEC_length (ada_task_info_s, data->task_list); i++) { struct ada_task_info *task_info = - VEC_index (ada_task_info_s, task_list, i); + VEC_index (ada_task_info_s, data->task_list, i); if (task_info->task_id == task_id) return i + 1; @@ -198,9 +328,12 @@ get_task_number_from_id (CORE_ADDR task_id) int valid_task_id (int task_num) { - ada_build_task_list (0); + struct ada_tasks_inferior_data *data; + + ada_build_task_list (); + data = get_ada_tasks_inferior_data (current_inferior ()); return (task_num > 0 - && task_num <= VEC_length (ada_task_info_s, task_list)); + && task_num <= VEC_length (ada_task_info_s, data->task_list)); } /* Return non-zero iff the task STATE corresponds to a non-terminated @@ -220,13 +353,15 @@ iterate_over_live_ada_tasks (ada_task_list_iterator_ftype *iterator) { int i, nb_tasks; struct ada_task_info *task; + struct ada_tasks_inferior_data *data; - ada_build_task_list (0); - nb_tasks = VEC_length (ada_task_info_s, task_list); + ada_build_task_list (); + data = get_ada_tasks_inferior_data (current_inferior ()); + nb_tasks = VEC_length (ada_task_info_s, data->task_list); for (i = 0; i < nb_tasks; i++) { - task = VEC_index (ada_task_info_s, task_list, i); + task = VEC_index (ada_task_info_s, data->task_list, i); if (!ada_task_is_alive (task)) continue; iterator (task); @@ -299,54 +434,6 @@ read_fat_string_value (char *dest, struct value *val, int max_len) dest[len] = '\0'; } -/* Return the address of the Known_Tasks array maintained in - the Ada Runtime. Return zero if the array could not be found, - meaning that the inferior program probably does not use tasking. - - In order to provide a fast response time, this function caches - the Known_Tasks array address after the lookup during the first - call. Subsequent calls will simply return this cached address. */ - -static CORE_ADDR -get_known_tasks_addr (void) -{ - static CORE_ADDR known_tasks_addr = 0; - - if (ada_tasks_check_symbol_table) - { - struct minimal_symbol *msym; - - msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL); - if (msym == NULL) - return 0; - known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym); - - /* FIXME: brobecker 2003-03-05: Here would be a much better place - to attach the ada-tasks observers, instead of doing this - unconditionaly in _initialize_tasks. This would avoid an - unecessary notification when the inferior does not use tasking - or as long as the user does not use the ada-tasks commands. - Unfortunately, this is not possible for the moment: the current - code resets ada__tasks_check_symbol_table back to 1 whenever - symbols for a new program are being loaded. If we place the - observers intialization here, we will end up adding new observers - everytime we do the check for Ada tasking-related symbols - above. This would currently have benign effects, but is still - undesirable. The cleanest approach is probably to create a new - observer to notify us when the user is debugging a new program. - We would then reset ada__tasks_check_symbol_table back to 1 - during the notification, but also detach all observers. - BTW: observers are probably not reentrant, so detaching during - a notification may not be the safest thing to do... Sigh... - But creating the new observer would be a good idea in any case, - since this allow us to make ada__tasks_check_symbol_table - static, which is a good bonus. */ - ada_tasks_check_symbol_table = 0; - } - - return known_tasks_addr; -} - /* Get from the debugging information the type description of all types related to the Ada Task Control Block that will be needed in order to read the list of known tasks in the Ada runtime. Also return the @@ -358,17 +445,14 @@ get_known_tasks_addr (void) return values will be set. */ static void -get_tcb_types_info (struct type **atcb_type, - struct type **atcb_common_type, - struct type **atcb_ll_type, - struct type **atcb_call_type, - struct tcb_fieldnos *atcb_fieldnos) +get_tcb_types_info (void) { struct type *type; struct type *common_type; struct type *ll_type; struct type *call_type; - struct tcb_fieldnos fieldnos; + struct atcb_fieldnos fieldnos; + struct ada_tasks_pspace_data *pspace_data; const char *atcb_name = "system__tasking__ada_task_control_block___XVE"; const char *atcb_name_fixed = "system__tasking__ada_task_control_block"; @@ -439,6 +523,8 @@ get_tcb_types_info (struct type **atcb_type, fieldnos.priority = ada_get_field_index (common_type, "base_priority", 0); fieldnos.image = ada_get_field_index (common_type, "task_image", 1); fieldnos.image_len = ada_get_field_index (common_type, "task_image_len", 1); + fieldnos.activation_link = ada_get_field_index (common_type, + "activation_link", 1); fieldnos.call = ada_get_field_index (common_type, "call", 1); fieldnos.ll = ada_get_field_index (common_type, "ll", 0); fieldnos.ll_thread = ada_get_field_index (ll_type, "thread", 0); @@ -456,11 +542,13 @@ get_tcb_types_info (struct type **atcb_type, /* Set all the out parameters all at once, now that we are certain that there are no potential error() anymore. */ - *atcb_type = type; - *atcb_common_type = common_type; - *atcb_ll_type = ll_type; - *atcb_call_type = call_type; - *atcb_fieldnos = fieldnos; + pspace_data = get_ada_tasks_pspace_data (current_program_space); + pspace_data->initialized_p = 1; + pspace_data->atcb_type = type; + pspace_data->atcb_common_type = common_type; + pspace_data->atcb_ll_type = ll_type; + pspace_data->atcb_call_type = call_type; + pspace_data->atcb_fieldno = fieldnos; } /* Build the PTID of the task from its COMMON_VALUE, which is the "Common" @@ -474,12 +562,16 @@ ptid_from_atcb_common (struct value *common_value) CORE_ADDR lwp = 0; struct value *ll_value; ptid_t ptid; + const struct ada_tasks_pspace_data *pspace_data + = get_ada_tasks_pspace_data (current_program_space); - ll_value = value_field (common_value, fieldno.ll); + ll_value = value_field (common_value, pspace_data->atcb_fieldno.ll); - if (fieldno.ll_lwp >= 0) - lwp = value_as_address (value_field (ll_value, fieldno.ll_lwp)); - thread = value_as_long (value_field (ll_value, fieldno.ll_thread)); + if (pspace_data->atcb_fieldno.ll_lwp >= 0) + lwp = value_as_address (value_field (ll_value, + pspace_data->atcb_fieldno.ll_lwp)); + thread = value_as_long (value_field (ll_value, + pspace_data->atcb_fieldno.ll_thread)); ptid = target_get_ada_task_ptid (lwp, thread); @@ -499,14 +591,16 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) struct value *entry_calls_value; struct value *entry_calls_value_element; int called_task_fieldno = -1; - const char ravenscar_task_name[] = "Ravenscar task"; + static const char ravenscar_task_name[] = "Ravenscar task"; + const struct ada_tasks_pspace_data *pspace_data + = get_ada_tasks_pspace_data (current_program_space); - if (atcb_type == NULL) - get_tcb_types_info (&atcb_type, &atcb_common_type, &atcb_ll_type, - &atcb_call_type, &fieldno); + if (!pspace_data->initialized_p) + get_tcb_types_info (); - tcb_value = value_from_contents_and_address (atcb_type, NULL, task_id); - common_value = value_field (tcb_value, fieldno.common); + tcb_value = value_from_contents_and_address (pspace_data->atcb_type, + NULL, task_id); + common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common); /* Fill in the task_id. */ @@ -527,35 +621,68 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) we may want to get it from the first user frame of the stack. For now, we just give a dummy name. */ - if (fieldno.image_len == -1) + if (pspace_data->atcb_fieldno.image_len == -1) { - if (fieldno.image >= 0) + if (pspace_data->atcb_fieldno.image >= 0) read_fat_string_value (task_info->name, - value_field (common_value, fieldno.image), + value_field (common_value, + pspace_data->atcb_fieldno.image), sizeof (task_info->name) - 1); else - strcpy (task_info->name, ravenscar_task_name); + { + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol_by_pc (task_id); + if (msym) + { + const char *full_name = SYMBOL_LINKAGE_NAME (msym); + const char *task_name = full_name; + const char *p; + + /* Strip the prefix. */ + for (p = full_name; *p; p++) + if (p[0] == '_' && p[1] == '_') + task_name = p + 2; + + /* Copy the task name. */ + strncpy (task_info->name, task_name, sizeof (task_info->name)); + task_info->name[sizeof (task_info->name) - 1] = 0; + } + else + { + /* No symbol found. Use a default name. */ + strcpy (task_info->name, ravenscar_task_name); + } + } } else { - int len = value_as_long (value_field (common_value, fieldno.image_len)); + int len = value_as_long + (value_field (common_value, + pspace_data->atcb_fieldno.image_len)); value_as_string (task_info->name, - value_field (common_value, fieldno.image), len); + value_field (common_value, + pspace_data->atcb_fieldno.image), + len); } /* Compute the task state and priority. */ - task_info->state = value_as_long (value_field (common_value, fieldno.state)); + task_info->state = + value_as_long (value_field (common_value, + pspace_data->atcb_fieldno.state)); task_info->priority = - value_as_long (value_field (common_value, fieldno.priority)); + value_as_long (value_field (common_value, + pspace_data->atcb_fieldno.priority)); /* If the ATCB contains some information about the parent task, then compute it as well. Otherwise, zero. */ - if (fieldno.parent >= 0) + if (pspace_data->atcb_fieldno.parent >= 0) task_info->parent = - value_as_address (value_field (common_value, fieldno.parent)); + value_as_address (value_field (common_value, + pspace_data->atcb_fieldno.parent)); else task_info->parent = 0; @@ -563,16 +690,17 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) /* If the ATCB contains some information about entry calls, then compute the "called_task" as well. Otherwise, zero. */ - if (fieldno.atc_nesting_level > 0 && fieldno.entry_calls > 0) + if (pspace_data->atcb_fieldno.atc_nesting_level > 0 + && pspace_data->atcb_fieldno.entry_calls > 0) { /* Let My_ATCB be the Ada task control block of a task calling the entry of another task; then the Task_Id of the called task is in My_ATCB.Entry_Calls (My_ATCB.ATC_Nesting_Level).Called_Task. */ - atc_nesting_level_value = value_field (tcb_value, - fieldno.atc_nesting_level); + atc_nesting_level_value = + value_field (tcb_value, pspace_data->atcb_fieldno.atc_nesting_level); entry_calls_value = - ada_coerce_to_simple_array_ptr (value_field (tcb_value, - fieldno.entry_calls)); + ada_coerce_to_simple_array_ptr + (value_field (tcb_value, pspace_data->atcb_fieldno.entry_calls)); entry_calls_value_element = value_subscript (entry_calls_value, value_as_long (atc_nesting_level_value)); @@ -592,20 +720,23 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) then compute the "caller_task". Otherwise, zero. */ task_info->caller_task = 0; - if (fieldno.call >= 0) + if (pspace_data->atcb_fieldno.call >= 0) { /* Get the ID of the caller task from Common_ATCB.Call.all.Self. If Common_ATCB.Call is null, then there is no caller. */ const CORE_ADDR call = - value_as_address (value_field (common_value, fieldno.call)); + value_as_address (value_field (common_value, + pspace_data->atcb_fieldno.call)); struct value *call_val; if (call != 0) { call_val = - value_from_contents_and_address (atcb_call_type, NULL, call); + value_from_contents_and_address (pspace_data->atcb_call_type, + NULL, call); task_info->caller_task = - value_as_address (value_field (call_val, fieldno.call_self)); + value_as_address + (value_field (call_val, pspace_data->atcb_fieldno.call_self)); } } @@ -627,43 +758,32 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info) } /* Read the ATCB info of the given task (identified by TASK_ID), and - add the result to the TASK_LIST. */ + add the result to the given inferior's TASK_LIST. */ static void -add_ada_task (CORE_ADDR task_id) +add_ada_task (CORE_ADDR task_id, struct inferior *inf) { struct ada_task_info task_info; + struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf); read_atcb (task_id, &task_info); - VEC_safe_push (ada_task_info_s, task_list, &task_info); + VEC_safe_push (ada_task_info_s, data->task_list, &task_info); } /* Read the Known_Tasks array from the inferior memory, and store - it in TASK_LIST. Return non-zero upon success. */ + it in the current inferior's TASK_LIST. Return non-zero upon success. */ static int -read_known_tasks_array (void) +read_known_tasks_array (CORE_ADDR known_tasks_addr) { const int target_ptr_byte = gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT; - const CORE_ADDR known_tasks_addr = get_known_tasks_addr (); const int known_tasks_size = target_ptr_byte * MAX_NUMBER_OF_KNOWN_TASKS; gdb_byte *known_tasks = alloca (known_tasks_size); int i; - /* Step 1: Clear the current list, if necessary. */ - VEC_truncate (ada_task_info_s, task_list, 0); - - /* If the application does not use task, then no more needs to be done. - It is important to have the task list cleared (see above) before we - return, as we don't want a stale task list to be used... This can - happen for instance when debugging a non-multitasking program after - having debugged a multitasking one. */ - if (known_tasks_addr == 0) - return 0; - - /* Step 2: Build a new list by reading the ATCBs from the Known_Tasks - array in the Ada runtime. */ + /* Build a new list by reading the ATCBs from the Known_Tasks array + in the Ada runtime. */ read_memory (known_tasks_addr, known_tasks, known_tasks_size); for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++) { @@ -674,117 +794,337 @@ read_known_tasks_array (void) data_ptr_type); if (task_id != 0) - add_ada_task (task_id); + add_ada_task (task_id, current_inferior ()); } - /* Step 3: Unset stale_task_list_p, to avoid re-reading the Known_Tasks - array unless needed. Then report a success. */ - stale_task_list_p = 0; - return 1; } -/* Builds the task_list by reading the Known_Tasks array from - the inferior. Prints an appropriate message and returns non-zero - if it failed to build this list. */ +/* Read the known tasks from the inferior memory, and store it in + the current inferior's TASK_LIST. Return non-zero upon success. */ -int -ada_build_task_list (int warn_if_null) +static int +read_known_tasks_list (CORE_ADDR known_tasks_addr) { - if (!target_has_stack) - error (_("Cannot inspect Ada tasks when program is not running")); - - if (stale_task_list_p) - read_known_tasks_array (); + const int target_ptr_byte = + gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT; + gdb_byte *known_tasks = alloca (target_ptr_byte); + struct type *data_ptr_type = + builtin_type (target_gdbarch)->builtin_data_ptr; + CORE_ADDR task_id; + const struct ada_tasks_pspace_data *pspace_data + = get_ada_tasks_pspace_data (current_program_space); + + /* Sanity check. */ + if (pspace_data->atcb_fieldno.activation_link < 0) + return 0; - if (task_list == NULL) + /* Build a new list by reading the ATCBs. Read head of the list. */ + read_memory (known_tasks_addr, known_tasks, target_ptr_byte); + task_id = extract_typed_address (known_tasks, data_ptr_type); + while (task_id != 0) { - if (warn_if_null) - printf_filtered (_("Your application does not use any Ada tasks.\n")); - return 0; + struct value *tcb_value; + struct value *common_value; + + add_ada_task (task_id, current_inferior ()); + + /* Read the chain. */ + tcb_value = value_from_contents_and_address (pspace_data->atcb_type, + NULL, task_id); + common_value = value_field (tcb_value, pspace_data->atcb_fieldno.common); + task_id = value_as_address + (value_field (common_value, + pspace_data->atcb_fieldno.activation_link)); } return 1; } -/* Print a one-line description of the task whose number is TASKNO. - The formatting should fit the "info tasks" array. */ +/* Return the address of the variable NAME that contains all the known + tasks maintained in the Ada Runtime. Return NULL if the variable + could not be found, meaning that the inferior program probably does + not use tasking. */ + +static CORE_ADDR +get_known_tasks_addr (const char *name) +{ + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol (name, NULL, NULL); + if (msym == NULL) + return 0; + + return SYMBOL_VALUE_ADDRESS (msym); +} + +/* Assuming DATA is the ada-tasks' data for the current inferior, + set the known_tasks_kind and known_tasks_addr fields. Do nothing + if those fields are already set and still up to date. */ static void -short_task_info (int taskno) +ada_set_current_inferior_known_tasks_addr (struct ada_tasks_inferior_data *data) { - const struct ada_task_info *const task_info = - VEC_index (ada_task_info_s, task_list, taskno - 1); - int active_task_p; + CORE_ADDR known_tasks_addr; - gdb_assert (task_info != NULL); + if (data->known_tasks_kind != ADA_TASKS_UNKNOWN) + return; - /* Print a star if this task is the current task (or the task currently - selected). */ + known_tasks_addr = get_known_tasks_addr (KNOWN_TASKS_NAME); + if (known_tasks_addr != 0) + { + data->known_tasks_kind = ADA_TASKS_ARRAY; + data->known_tasks_addr = known_tasks_addr; + return; + } - active_task_p = ptid_equal (task_info->ptid, inferior_ptid); - if (active_task_p) - printf_filtered ("*"); - else - printf_filtered (" "); + known_tasks_addr = get_known_tasks_addr (KNOWN_TASKS_LIST); + if (known_tasks_addr != 0) + { + data->known_tasks_kind = ADA_TASKS_LIST; + data->known_tasks_addr = known_tasks_addr; + return; + } - /* Print the task number. */ - printf_filtered ("%3d", taskno); + data->known_tasks_kind = ADA_TASKS_NOT_FOUND; + data->known_tasks_addr = 0; +} - /* Print the Task ID. */ - printf_filtered (" %9lx", (long) task_info->task_id); +/* Read the known tasks from the current inferior's memory, and store it + in the current inferior's data TASK_LIST. + Return non-zero upon success. */ - /* Print the Task ID of the task parent. */ - printf_filtered (" %4d", get_task_number_from_id (task_info->parent)); +static int +read_known_tasks (void) +{ + struct ada_tasks_inferior_data *data = + get_ada_tasks_inferior_data (current_inferior ()); - /* Print the base priority of the task. */ - printf_filtered (" %3d", task_info->priority); + /* Step 1: Clear the current list, if necessary. */ + VEC_truncate (ada_task_info_s, data->task_list, 0); - /* Print the task current state. */ - if (task_info->caller_task) - printf_filtered (_(" Accepting RV with %-4d"), - get_task_number_from_id (task_info->caller_task)); - else if (task_info->state == Entry_Caller_Sleep && task_info->called_task) - printf_filtered (_(" Waiting on RV with %-3d"), - get_task_number_from_id (task_info->called_task)); - else - printf_filtered (" %-22s", _(task_states[task_info->state])); + /* Step 2: do the real work. + If the application does not use task, then no more needs to be done. + It is important to have the task list cleared (see above) before we + return, as we don't want a stale task list to be used... This can + happen for instance when debugging a non-multitasking program after + having debugged a multitasking one. */ + ada_set_current_inferior_known_tasks_addr (data); + gdb_assert (data->known_tasks_kind != ADA_TASKS_UNKNOWN); - /* Finally, print the task name. */ - if (task_info->name[0] != '\0') - printf_filtered (" %s\n", task_info->name); - else - printf_filtered (_(" \n")); + switch (data->known_tasks_kind) + { + case ADA_TASKS_NOT_FOUND: /* Tasking not in use in inferior. */ + return 0; + case ADA_TASKS_ARRAY: + return read_known_tasks_array (data->known_tasks_addr); + case ADA_TASKS_LIST: + return read_known_tasks_list (data->known_tasks_addr); + } + + /* Step 3: Set task_list_valid_p, to avoid re-reading the Known_Tasks + array unless needed. Then report a success. */ + data->task_list_valid_p = 1; + + return 1; } -/* Print a list containing a short description of all Ada tasks. */ -/* FIXME: Shouldn't we be using ui_out??? */ +/* Build the task_list by reading the Known_Tasks array from + the inferior, and return the number of tasks in that list + (zero means that the program is not using tasking at all). */ -static void -info_tasks (int from_tty) +int +ada_build_task_list (void) { - int taskno; - const int nb_tasks = VEC_length (ada_task_info_s, task_list); + struct ada_tasks_inferior_data *data; - printf_filtered (_(" ID TID P-ID Pri State Name\n")); - - for (taskno = 1; taskno <= nb_tasks; taskno++) - short_task_info (taskno); + if (!target_has_stack) + error (_("Cannot inspect Ada tasks when program is not running")); + + data = get_ada_tasks_inferior_data (current_inferior ()); + if (!data->task_list_valid_p) + read_known_tasks (); + + return VEC_length (ada_task_info_s, data->task_list); } -/* Print a detailed description of the Ada task whose ID is TASKNO_STR. */ +/* Print a table providing a short description of all Ada tasks + running inside inferior INF. If ARG_STR is set, it will be + interpreted as a task number, and the table will be limited to + that task only. */ + +void +print_ada_task_info (struct ui_out *uiout, + char *arg_str, + struct inferior *inf) +{ + struct ada_tasks_inferior_data *data; + int taskno, nb_tasks; + int taskno_arg = 0; + struct cleanup *old_chain; + int nb_columns; + + if (ada_build_task_list () == 0) + { + ui_out_message (uiout, 0, + _("Your application does not use any Ada tasks.\n")); + return; + } + + if (arg_str != NULL && arg_str[0] != '\0') + taskno_arg = value_as_long (parse_and_eval (arg_str)); + + if (ui_out_is_mi_like_p (uiout)) + /* In GDB/MI mode, we want to provide the thread ID corresponding + to each task. This allows clients to quickly find the thread + associated to any task, which is helpful for commands that + take a --thread argument. However, in order to be able to + provide that thread ID, the thread list must be up to date + first. */ + target_find_new_threads (); + + data = get_ada_tasks_inferior_data (inf); + + /* Compute the number of tasks that are going to be displayed + in the output. If an argument was given, there will be + at most 1 entry. Otherwise, there will be as many entries + as we have tasks. */ + if (taskno_arg) + { + if (taskno_arg > 0 + && taskno_arg <= VEC_length (ada_task_info_s, data->task_list)) + nb_tasks = 1; + else + nb_tasks = 0; + } + else + nb_tasks = VEC_length (ada_task_info_s, data->task_list); + + nb_columns = ui_out_is_mi_like_p (uiout) ? 8 : 7; + old_chain = make_cleanup_ui_out_table_begin_end (uiout, nb_columns, + nb_tasks, "tasks"); + ui_out_table_header (uiout, 1, ui_left, "current", ""); + ui_out_table_header (uiout, 3, ui_right, "id", "ID"); + ui_out_table_header (uiout, 9, ui_right, "task-id", "TID"); + /* The following column is provided in GDB/MI mode only because + it is only really useful in that mode, and also because it + allows us to keep the CLI output shorter and more compact. */ + if (ui_out_is_mi_like_p (uiout)) + ui_out_table_header (uiout, 4, ui_right, "thread-id", ""); + ui_out_table_header (uiout, 4, ui_right, "parent-id", "P-ID"); + ui_out_table_header (uiout, 3, ui_right, "priority", "Pri"); + ui_out_table_header (uiout, 22, ui_left, "state", "State"); + /* Use ui_noalign for the last column, to prevent the CLI uiout + from printing an extra space at the end of each row. This + is a bit of a hack, but does get the job done. */ + ui_out_table_header (uiout, 1, ui_noalign, "name", "Name"); + ui_out_table_body (uiout); + + for (taskno = 1; + taskno <= VEC_length (ada_task_info_s, data->task_list); + taskno++) + { + const struct ada_task_info *const task_info = + VEC_index (ada_task_info_s, data->task_list, taskno - 1); + int parent_id; + struct cleanup *chain2; + + gdb_assert (task_info != NULL); + + /* If the user asked for the output to be restricted + to one task only, and this is not the task, skip + to the next one. */ + if (taskno_arg && taskno != taskno_arg) + continue; + + chain2 = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + /* Print a star if this task is the current task (or the task + currently selected). */ + if (ptid_equal (task_info->ptid, inferior_ptid)) + ui_out_field_string (uiout, "current", "*"); + else + ui_out_field_skip (uiout, "current"); + + /* Print the task number. */ + ui_out_field_int (uiout, "id", taskno); + + /* Print the Task ID. */ + ui_out_field_fmt (uiout, "task-id", "%9lx", (long) task_info->task_id); + + /* Print the associated Thread ID. */ + if (ui_out_is_mi_like_p (uiout)) + { + const int thread_id = pid_to_thread_id (task_info->ptid); + + if (thread_id != 0) + ui_out_field_int (uiout, "thread-id", thread_id); + else + /* This should never happen unless there is a bug somewhere, + but be resilient when that happens. */ + ui_out_field_skip (uiout, "thread-id"); + } + + /* Print the ID of the parent task. */ + parent_id = get_task_number_from_id (task_info->parent, inf); + if (parent_id) + ui_out_field_int (uiout, "parent-id", parent_id); + else + ui_out_field_skip (uiout, "parent-id"); + + /* Print the base priority of the task. */ + ui_out_field_int (uiout, "priority", task_info->priority); + + /* Print the task current state. */ + if (task_info->caller_task) + ui_out_field_fmt (uiout, "state", + _("Accepting RV with %-4d"), + get_task_number_from_id (task_info->caller_task, + inf)); + else if (task_info->state == Entry_Caller_Sleep + && task_info->called_task) + ui_out_field_fmt (uiout, "state", + _("Waiting on RV with %-3d"), + get_task_number_from_id (task_info->called_task, + inf)); + else + ui_out_field_string (uiout, "state", task_states[task_info->state]); + + /* Finally, print the task name. */ + ui_out_field_fmt (uiout, "name", + "%s", + task_info->name[0] != '\0' ? task_info->name + : _("")); + + ui_out_text (uiout, "\n"); + do_cleanups (chain2); + } + + do_cleanups (old_chain); +} + +/* Print a detailed description of the Ada task whose ID is TASKNO_STR + for the given inferior (INF). */ static void -info_task (char *taskno_str, int from_tty) +info_task (struct ui_out *uiout, char *taskno_str, struct inferior *inf) { const int taskno = value_as_long (parse_and_eval (taskno_str)); struct ada_task_info *task_info; int parent_taskno = 0; + struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf); - if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, task_list)) + if (ada_build_task_list () == 0) + { + ui_out_message (uiout, 0, + _("Your application does not use any Ada tasks.\n")); + return; + } + + if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, data->task_list)) error (_("Task ID %d not known. Use the \"info tasks\" command to\n" "see the IDs of currently known tasks"), taskno); - task_info = VEC_index (ada_task_info_s, task_list, taskno - 1); + task_info = VEC_index (ada_task_info_s, data->task_list, taskno - 1); /* Print the Ada task ID. */ printf_filtered (_("Ada Task: %s\n"), @@ -802,11 +1142,11 @@ info_task (char *taskno_str, int from_tty) /* Print who is the parent (if any). */ if (task_info->parent != 0) - parent_taskno = get_task_number_from_id (task_info->parent); + parent_taskno = get_task_number_from_id (task_info->parent, inf); if (parent_taskno) { struct ada_task_info *parent = - VEC_index (ada_task_info_s, task_list, parent_taskno - 1); + VEC_index (ada_task_info_s, data->task_list, parent_taskno - 1); printf_filtered (_("Parent: %d"), parent_taskno); if (parent->name[0] != '\0') @@ -825,13 +1165,13 @@ info_task (char *taskno_str, int from_tty) if (task_info->caller_task) { - target_taskno = get_task_number_from_id (task_info->caller_task); + target_taskno = get_task_number_from_id (task_info->caller_task, inf); printf_filtered (_("State: Accepting rendezvous with %d"), target_taskno); } else if (task_info->state == Entry_Caller_Sleep && task_info->called_task) { - target_taskno = get_task_number_from_id (task_info->called_task); + target_taskno = get_task_number_from_id (task_info->called_task, inf); printf_filtered (_("State: Waiting on task %d's entry"), target_taskno); } @@ -841,7 +1181,7 @@ info_task (char *taskno_str, int from_tty) if (target_taskno) { struct ada_task_info *target_task_info = - VEC_index (ada_task_info_s, task_list, target_taskno - 1); + VEC_index (ada_task_info_s, data->task_list, target_taskno - 1); if (target_task_info->name[0] != '\0') printf_filtered (" (%s)", target_task_info->name); @@ -860,15 +1200,12 @@ info_task (char *taskno_str, int from_tty) static void info_tasks_command (char *arg, int from_tty) { - const int task_list_built = ada_build_task_list (1); - - if (!task_list_built) - return; + struct ui_out *uiout = current_uiout; if (arg == NULL || *arg == '\0') - info_tasks (from_tty); + print_ada_task_info (uiout, NULL, current_inferior ()); else - info_task (arg, from_tty); + info_task (uiout, arg, current_inferior ()); } /* Print a message telling the user id of the current task. @@ -889,15 +1226,16 @@ display_current_task_id (void) that task. Print an error message if the task switch failed. */ static void -task_command_1 (char *taskno_str, int from_tty) +task_command_1 (char *taskno_str, int from_tty, struct inferior *inf) { const int taskno = value_as_long (parse_and_eval (taskno_str)); struct ada_task_info *task_info; + struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf); - if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, task_list)) + if (taskno <= 0 || taskno > VEC_length (ada_task_info_s, data->task_list)) error (_("Task ID %d not known. Use the \"info tasks\" command to\n" "see the IDs of currently known tasks"), taskno); - task_info = VEC_index (ada_task_info_s, task_list, taskno - 1); + task_info = VEC_index (ada_task_info_s, data->task_list, taskno - 1); if (!ada_task_is_alive (task_info)) error (_("Cannot switch to task %d: Task is no longer running"), taskno); @@ -938,10 +1276,14 @@ task_command_1 (char *taskno_str, int from_tty) static void task_command (char *taskno_str, int from_tty) { - const int task_list_built = ada_build_task_list (1); + struct ui_out *uiout = current_uiout; - if (!task_list_built) - return; + if (ada_build_task_list () == 0) + { + ui_out_message (uiout, 0, + _("Your application does not use any Ada tasks.\n")); + return; + } if (taskno_str == NULL || taskno_str[0] == '\0') display_current_task_id (); @@ -961,16 +1303,38 @@ task_command (char *taskno_str, int from_tty) error (_("\ Task switching not supported when debugging from core files\n\ (use thread support instead)")); - task_command_1 (taskno_str, from_tty); + task_command_1 (taskno_str, from_tty, current_inferior ()); } } -/* Indicate that the task list may have changed, so invalidate the cache. */ +/* Indicate that the given inferior's task list may have changed, + so invalidate the cache. */ static void -ada_task_list_changed (void) +ada_task_list_changed (struct inferior *inf) { - stale_task_list_p = 1; + struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf); + + data->task_list_valid_p = 0; +} + +/* Invalidate the per-program-space data. */ + +static void +ada_tasks_invalidate_pspace_data (struct program_space *pspace) +{ + get_ada_tasks_pspace_data (pspace)->initialized_p = 0; +} + +/* Invalidate the per-inferior data. */ + +static void +ada_tasks_invalidate_inferior_data (struct inferior *inf) +{ + struct ada_tasks_inferior_data *data = get_ada_tasks_inferior_data (inf); + + data->known_tasks_kind = ADA_TASKS_UNKNOWN; + data->task_list_valid_p = 0; } /* The 'normal_stop' observer notification callback. */ @@ -980,7 +1344,7 @@ ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2) { /* The inferior has been resumed, and just stopped. This means that our task_list needs to be recomputed before it can be used again. */ - ada_task_list_changed (); + ada_task_list_changed (current_inferior ()); } /* A routine to be called when the objfiles have changed. */ @@ -988,14 +1352,35 @@ ada_normal_stop_observer (struct bpstats *unused_args, int unused_args2) static void ada_new_objfile_observer (struct objfile *objfile) { - /* Invalidate all cached data that were extracted from an objfile. */ + struct inferior *inf; + + /* Invalidate the relevant data in our program-space data. */ + + if (objfile == NULL) + { + /* All objfiles are being cleared, so we should clear all + our caches for all program spaces. */ + struct program_space *pspace; + + for (pspace = program_spaces; pspace != NULL; pspace = pspace->next) + ada_tasks_invalidate_pspace_data (pspace); + } + else + { + /* The associated program-space data might have changed after + this objfile was added. Invalidate all cached data. */ + ada_tasks_invalidate_pspace_data (objfile->pspace); + } - atcb_type = NULL; - atcb_common_type = NULL; - atcb_ll_type = NULL; - atcb_call_type = NULL; + /* Invalidate the per-inferior cache for all inferiors using + this objfile (or, in other words, for all inferiors who have + the same program-space as the objfile's program space). + If all objfiles are being cleared (OBJFILE is NULL), then + clear the caches for all inferiors. */ - ada_tasks_check_symbol_table = 1; + for (inf = inferior_list; inf != NULL; inf = inf->next) + if (objfile == NULL || inf->pspace == objfile->pspace) + ada_tasks_invalidate_inferior_data (inf); } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -1004,6 +1389,9 @@ extern initialize_file_ftype _initialize_tasks; void _initialize_tasks (void) { + ada_tasks_pspace_data_handle = register_program_space_data (); + ada_tasks_inferior_data_handle = register_inferior_data (); + /* Attach various observers. */ observer_attach_normal_stop (ada_normal_stop_observer); observer_attach_new_objfile (ada_new_objfile_observer); diff --git a/contrib/gdb-7/gdb/ada-typeprint.c b/contrib/gdb-7/gdb/ada-typeprint.c index 737e09730f..97ab937d1c 100644 --- a/contrib/gdb-7/gdb/ada-typeprint.c +++ b/contrib/gdb-7/gdb/ada-typeprint.c @@ -1,6 +1,6 @@ /* Support for printing Ada types for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991, 1997-2004, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -340,57 +340,52 @@ print_array_type (struct type *type, struct ui_file *stream, int show, } n_indices = -1; - if (show < 0) - fprintf_filtered (stream, "..."); - else + if (ada_is_simple_array_type (type)) { - if (ada_is_simple_array_type (type)) - { - struct type *range_desc_type; - struct type *arr_type; + struct type *range_desc_type; + struct type *arr_type; - range_desc_type = ada_find_parallel_type (type, "___XA"); - ada_fixup_array_indexes_type (range_desc_type); + range_desc_type = ada_find_parallel_type (type, "___XA"); + ada_fixup_array_indexes_type (range_desc_type); - bitsize = 0; - if (range_desc_type == NULL) - { - for (arr_type = type; TYPE_CODE (arr_type) == TYPE_CODE_ARRAY; - arr_type = TYPE_TARGET_TYPE (arr_type)) - { - if (arr_type != type) - fprintf_filtered (stream, ", "); - print_range (TYPE_INDEX_TYPE (arr_type), stream); - if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0) - bitsize = TYPE_FIELD_BITSIZE (arr_type, 0); - } - } - else + bitsize = 0; + if (range_desc_type == NULL) + { + for (arr_type = type; TYPE_CODE (arr_type) == TYPE_CODE_ARRAY; + arr_type = TYPE_TARGET_TYPE (arr_type)) { - int k; - - n_indices = TYPE_NFIELDS (range_desc_type); - for (k = 0, arr_type = type; - k < n_indices; - k += 1, arr_type = TYPE_TARGET_TYPE (arr_type)) - { - if (k > 0) - fprintf_filtered (stream, ", "); - print_range_type (TYPE_FIELD_TYPE (range_desc_type, k), - stream); - if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0) - bitsize = TYPE_FIELD_BITSIZE (arr_type, 0); - } + if (arr_type != type) + fprintf_filtered (stream, ", "); + print_range (TYPE_INDEX_TYPE (arr_type), stream); + if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0) + bitsize = TYPE_FIELD_BITSIZE (arr_type, 0); } } else { - int i, i0; + int k; - for (i = i0 = ada_array_arity (type); i > 0; i -= 1) - fprintf_filtered (stream, "%s<>", i == i0 ? "" : ", "); + n_indices = TYPE_NFIELDS (range_desc_type); + for (k = 0, arr_type = type; + k < n_indices; + k += 1, arr_type = TYPE_TARGET_TYPE (arr_type)) + { + if (k > 0) + fprintf_filtered (stream, ", "); + print_range_type (TYPE_FIELD_TYPE (range_desc_type, k), + stream); + if (TYPE_FIELD_BITSIZE (arr_type, 0) > 0) + bitsize = TYPE_FIELD_BITSIZE (arr_type, 0); + } } } + else + { + int i, i0; + + for (i = i0 = ada_array_arity (type); i > 0; i -= 1) + fprintf_filtered (stream, "%s<>", i == i0 ? "" : ", "); + } fprintf_filtered (stream, ") of "); wrap_here (""); @@ -626,8 +621,17 @@ print_record_type (struct type *type0, struct ui_file *stream, int show, parent_type = ada_parent_type (type); if (ada_type_name (parent_type) != NULL) - fprintf_filtered (stream, "new %s with record", - decoded_type_name (parent_type)); + { + const char *parent_name = decoded_type_name (parent_type); + + /* If we fail to decode the parent type name, then use the parent + type name as is. Not pretty, but should never happen except + when the debugging info is incomplete or incorrect. This + prevents a crash trying to print a NULL pointer. */ + if (parent_name == NULL) + parent_name = ada_type_name (parent_type); + fprintf_filtered (stream, "new %s with record", parent_name); + } else if (parent_type == NULL && ada_is_tagged_type (type, 0)) fprintf_filtered (stream, "tagged record"); else @@ -766,7 +770,7 @@ ada_print_type (struct type *type0, const char *varstring, fprintf_filtered (stream, "%.*s: ", ada_name_prefix_len (varstring), varstring); - if (type_name != NULL && show <= 0) + if (type_name != NULL && show <= 0 && !ada_is_aligner_type (type)) { fprintf_filtered (stream, "%.*s", ada_name_prefix_len (type_name), type_name); @@ -775,18 +779,9 @@ ada_print_type (struct type *type0, const char *varstring, if (ada_is_aligner_type (type)) ada_print_type (ada_aligned_type (type), "", stream, show, level); - else if (ada_is_constrained_packed_array_type (type)) - { - if (TYPE_CODE (type) == TYPE_CODE_PTR) - { - fprintf_filtered (stream, "access "); - print_array_type (TYPE_TARGET_TYPE (type), stream, show, level); - } - else - { - print_array_type (type, stream, show, level); - } - } + else if (ada_is_constrained_packed_array_type (type) + && TYPE_CODE (type) != TYPE_CODE_PTR) + print_array_type (type, stream, show, level); else switch (TYPE_CODE (type)) { diff --git a/contrib/gdb-7/gdb/ada-valprint.c b/contrib/gdb-7/gdb/ada-valprint.c index 09266ceb6b..f43f3e3be5 100644 --- a/contrib/gdb-7/gdb/ada-valprint.c +++ b/contrib/gdb-7/gdb/ada-valprint.c @@ -1,8 +1,7 @@ /* Support for printing Ada values for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1997, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-1994, 1997, 2001-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -682,7 +681,8 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr, type = ada_check_typedef (type); if (ada_is_array_descriptor_type (type) - || ada_is_constrained_packed_array_type (type)) + || (ada_is_constrained_packed_array_type (type) + && TYPE_CODE (type) != TYPE_CODE_PTR)) { int retn; struct value *mark = value_mark (); @@ -897,9 +897,18 @@ ada_val_print_1 (struct type *type, const gdb_byte *valaddr, if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF) { - CORE_ADDR deref_val_int - = unpack_pointer (type, valaddr + offset_aligned); + CORE_ADDR deref_val_int; + struct value *deref_val; + deref_val = coerce_ref_if_computed (original_value); + if (deref_val) + { + common_val_print (deref_val, stream, recurse + 1, options, + current_language); + break; + } + + deref_val_int = unpack_pointer (type, valaddr + offset_aligned); if (deref_val_int != 0) { struct value *deref_val = @@ -956,7 +965,7 @@ ada_value_print (struct value *val0, struct ui_file *stream, { struct value *val = ada_to_fixed_value (val0); CORE_ADDR address = value_address (val); - struct type *type = value_type (val); + struct type *type = ada_check_typedef (value_type (val)); struct value_print_options opts; /* If it is a pointer, indicate what it points to. */ diff --git a/contrib/gdb-7/gdb/addrmap.c b/contrib/gdb-7/gdb/addrmap.c index 917790e2f3..b06e4f62a1 100644 --- a/contrib/gdb-7/gdb/addrmap.c +++ b/contrib/gdb-7/gdb/addrmap.c @@ -1,6 +1,6 @@ /* addrmap.c --- implementation of address map data structure. - Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/addrmap.h b/contrib/gdb-7/gdb/addrmap.h index 2169e30f08..1552941d05 100644 --- a/contrib/gdb-7/gdb/addrmap.h +++ b/contrib/gdb-7/gdb/addrmap.h @@ -1,6 +1,6 @@ /* addrmap.h --- interface to address map data structure. - Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/amd64-nat.c b/contrib/gdb-7/gdb/amd64-nat.c index db72ee1069..68654568a4 100644 --- a/contrib/gdb-7/gdb/amd64-nat.c +++ b/contrib/gdb-7/gdb/amd64-nat.c @@ -1,7 +1,6 @@ /* Native-dependent code for AMD64. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/amd64-nat.h b/contrib/gdb-7/gdb/amd64-nat.h index 84e13c47aa..a0f84885c3 100644 --- a/contrib/gdb-7/gdb/amd64-nat.h +++ b/contrib/gdb-7/gdb/amd64-nat.h @@ -1,7 +1,6 @@ /* Native-dependent code for AMD64. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/amd64-tdep.c b/contrib/gdb-7/gdb/amd64-tdep.c index 9b5d5bb43a..ea65d0d55b 100644 --- a/contrib/gdb-7/gdb/amd64-tdep.c +++ b/contrib/gdb-7/gdb/amd64-tdep.c @@ -1,7 +1,6 @@ /* Target-dependent code for AMD64. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 2001-2012 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -45,6 +44,9 @@ #include "features/i386/amd64.c" #include "features/i386/amd64-avx.c" +#include "ax.h" +#include "ax-gdb.h" + /* Note that the AMD64 architecture was previously known as x86-64. The latter is (forever) engraved into the canonical system name as returned by config.guess, and used as the name for the AMD64 port @@ -275,14 +277,21 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) return i386_pseudo_register_name (gdbarch, regnum); } -static enum register_status -amd64_pseudo_register_read (struct gdbarch *gdbarch, - struct regcache *regcache, - int regnum, gdb_byte *buf) +static struct value * +amd64_pseudo_register_read_value (struct gdbarch *gdbarch, + struct regcache *regcache, + int regnum) { gdb_byte raw_buf[MAX_REGISTER_SIZE]; struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum register_status status; + struct value *result_value; + gdb_byte *buf; + + result_value = allocate_value (register_type (gdbarch, regnum)); + VALUE_LVAL (result_value) = lval_register; + VALUE_REGNUM (result_value) = regnum; + buf = value_contents_raw (result_value); if (i386_byte_regnum_p (gdbarch, regnum)) { @@ -297,15 +306,19 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch, raw_buf); if (status == REG_VALID) memcpy (buf, raw_buf + 1, 1); + else + mark_value_bytes_unavailable (result_value, 0, + TYPE_LENGTH (value_type (result_value))); } else { status = regcache_raw_read (regcache, gpnum, raw_buf); if (status == REG_VALID) memcpy (buf, raw_buf, 1); + else + mark_value_bytes_unavailable (result_value, 0, + TYPE_LENGTH (value_type (result_value))); } - - return status; } else if (i386_dword_regnum_p (gdbarch, regnum)) { @@ -314,11 +327,15 @@ amd64_pseudo_register_read (struct gdbarch *gdbarch, status = regcache_raw_read (regcache, gpnum, raw_buf); if (status == REG_VALID) memcpy (buf, raw_buf, 4); - - return status; + else + mark_value_bytes_unavailable (result_value, 0, + TYPE_LENGTH (value_type (result_value))); } else - return i386_pseudo_register_read (gdbarch, regcache, regnum, buf); + i386_pseudo_register_read_into_value (gdbarch, regcache, regnum, + result_value); + + return result_value; } static void @@ -518,7 +535,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class class[2]) if (class[0] == AMD64_MEMORY || class[1] == AMD64_MEMORY) class[0] = class[1] = AMD64_MEMORY; - /* Rule (b): If SSEUP is not preceeded by SSE, it is converted to + /* Rule (b): If SSEUP is not preceded by SSE, it is converted to SSE. */ if (class[0] == AMD64_SSEUP) class[0] = AMD64_SSE; @@ -860,7 +877,6 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Pass "hidden" argument". */ if (struct_return) { - struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); /* The "hidden" argument is passed throught the first argument register. */ const int arg_regnum = tdep->call_dummy_integer_regs[0]; @@ -1064,9 +1080,9 @@ amd64_get_unused_input_int_reg (const struct amd64_insn *details) if (have_sib) { int base = SIB_BASE_FIELD (details->raw_insn[details->modrm_offset + 1]); - int index = SIB_INDEX_FIELD (details->raw_insn[details->modrm_offset + 1]); + int idx = SIB_INDEX_FIELD (details->raw_insn[details->modrm_offset + 1]); used_regs_mask |= 1 << base; - used_regs_mask |= 1 << index; + used_regs_mask |= 1 << idx; } else { @@ -1533,7 +1549,7 @@ append_insns (CORE_ADDR *to, ULONGEST len, const gdb_byte *buf) *to += len; } -void +static void amd64_relocate_instruction (struct gdbarch *gdbarch, CORE_ADDR *to, CORE_ADDR oldloc) { @@ -1895,6 +1911,86 @@ amd64_analyze_prologue (struct gdbarch *gdbarch, return pc; } +/* Work around false termination of prologue - GCC PR debug/48827. + + START_PC is the first instruction of a function, PC is its minimal already + determined advanced address. Function returns PC if it has nothing to do. + + 84 c0 test %al,%al + 74 23 je after + <-- here is 0 lines advance - the false prologue end marker. + 0f 29 85 70 ff ff ff movaps %xmm0,-0x90(%rbp) + 0f 29 4d 80 movaps %xmm1,-0x80(%rbp) + 0f 29 55 90 movaps %xmm2,-0x70(%rbp) + 0f 29 5d a0 movaps %xmm3,-0x60(%rbp) + 0f 29 65 b0 movaps %xmm4,-0x50(%rbp) + 0f 29 6d c0 movaps %xmm5,-0x40(%rbp) + 0f 29 75 d0 movaps %xmm6,-0x30(%rbp) + 0f 29 7d e0 movaps %xmm7,-0x20(%rbp) + after: */ + +static CORE_ADDR +amd64_skip_xmm_prologue (CORE_ADDR pc, CORE_ADDR start_pc) +{ + struct symtab_and_line start_pc_sal, next_sal; + gdb_byte buf[4 + 8 * 7]; + int offset, xmmreg; + + if (pc == start_pc) + return pc; + + start_pc_sal = find_pc_sect_line (start_pc, NULL, 0); + if (start_pc_sal.symtab == NULL + || producer_is_gcc_ge_4 (start_pc_sal.symtab->producer) < 6 + || start_pc_sal.pc != start_pc || pc >= start_pc_sal.end) + return pc; + + next_sal = find_pc_sect_line (start_pc_sal.end, NULL, 0); + if (next_sal.line != start_pc_sal.line) + return pc; + + /* START_PC can be from overlayed memory, ignored here. */ + if (target_read_memory (next_sal.pc - 4, buf, sizeof (buf)) != 0) + return pc; + + /* test %al,%al */ + if (buf[0] != 0x84 || buf[1] != 0xc0) + return pc; + /* je AFTER */ + if (buf[2] != 0x74) + return pc; + + offset = 4; + for (xmmreg = 0; xmmreg < 8; xmmreg++) + { + /* 0x0f 0x29 0b??000101 movaps %xmmreg?,-0x??(%rbp) */ + if (buf[offset] != 0x0f || buf[offset + 1] != 0x29 + || (buf[offset + 2] & 0x3f) != (xmmreg << 3 | 0x5)) + return pc; + + /* 0b01?????? */ + if ((buf[offset + 2] & 0xc0) == 0x40) + { + /* 8-bit displacement. */ + offset += 4; + } + /* 0b10?????? */ + else if ((buf[offset + 2] & 0xc0) == 0x80) + { + /* 32-bit displacement. */ + offset += 7; + } + else + return pc; + } + + /* je AFTER */ + if (offset - 4 != buf[3]) + return pc; + + return next_sal.end; +} + /* Return PC of first real instruction. */ static CORE_ADDR @@ -1909,7 +2005,7 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) if (cache.frameless_p) return start_pc; - return pc; + return amd64_skip_xmm_prologue (pc, start_pc); } @@ -2070,6 +2166,22 @@ static const struct frame_unwind amd64_frame_unwind = default_frame_sniffer }; +/* Generate a bytecode expression to get the value of the saved PC. */ + +static void +amd64_gen_return_address (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + CORE_ADDR scope) +{ + /* The following sequence assumes the traditional use of the base + register. */ + ax_reg (ax, AMD64_RBP_REGNUM); + ax_const_l (ax, 8); + ax_simple (ax, aop_add); + value->type = register_type (gdbarch, AMD64_RIP_REGNUM); + value->kind = axs_lvalue_memory; +} + /* Signal trampolines. */ @@ -2219,6 +2331,11 @@ static int amd64_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc) { gdb_byte insn; + struct symtab *symtab; + + symtab = find_pc_symtab (pc); + if (symtab && symtab->epilogue_unwind_valid) + return 0; if (target_read_memory (pc, &insn, 1)) return 0; /* Can't read memory at pc. */ @@ -2489,8 +2606,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Avoid wiring in the MMX registers for now. */ tdep->num_mmx_regs = 0; - set_gdbarch_pseudo_register_read (gdbarch, - amd64_pseudo_register_read); + set_gdbarch_pseudo_register_read_value (gdbarch, + amd64_pseudo_register_read_value); set_gdbarch_pseudo_register_write (gdbarch, amd64_pseudo_register_write); @@ -2569,6 +2686,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target); set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction); + + set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address); } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -2662,7 +2781,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum, } } -/* Similar to amd64_collect_fxsave, but but use XSAVE extended state. */ +/* Similar to amd64_collect_fxsave, but use XSAVE extended state. */ void amd64_collect_xsave (const struct regcache *regcache, int regnum, diff --git a/contrib/gdb-7/gdb/amd64-tdep.h b/contrib/gdb-7/gdb/amd64-tdep.h index b96a58abb5..1ed109cdd0 100644 --- a/contrib/gdb-7/gdb/amd64-tdep.h +++ b/contrib/gdb-7/gdb/amd64-tdep.h @@ -1,7 +1,7 @@ /* Target-dependent definitions for AMD64. - Copyright (C) 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001, 2003-2004, 2007-2012 Free Software Foundation, + Inc. Contributed by Jiri Smid, SuSE Labs. This file is part of GDB. @@ -101,7 +101,7 @@ extern void amd64_supply_xsave (struct regcache *regcache, int regnum, extern void amd64_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave); -/* Similar to amd64_collect_fxsave, but but use XSAVE extended state. */ +/* Similar to amd64_collect_fxsave, but use XSAVE extended state. */ extern void amd64_collect_xsave (const struct regcache *regcache, int regnum, void *xsave, int gcore); diff --git a/contrib/gdb-7/gdb/amd64bsd-nat.c b/contrib/gdb-7/gdb/amd64bsd-nat.c index 7821f2b5d6..b7283e9f61 100644 --- a/contrib/gdb-7/gdb/amd64bsd-nat.c +++ b/contrib/gdb-7/gdb/amd64bsd-nat.c @@ -1,7 +1,6 @@ /* Native-dependent code for AMD64 BSD's. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/annotate.c b/contrib/gdb-7/gdb/annotate.c index d24120cf12..cd0a94aeda 100644 --- a/contrib/gdb-7/gdb/annotate.c +++ b/contrib/gdb-7/gdb/annotate.c @@ -1,6 +1,6 @@ /* Annotation routines for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1998, 1999, - 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1992, 1994-1996, 1998-2000, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -32,7 +32,7 @@ extern void _initialize_annotate (void); static void print_value_flags (struct type *); -static void breakpoint_changed (int); +static void breakpoint_changed (struct breakpoint *b); void (*deprecated_annotate_signalled_hook) (void); @@ -522,11 +522,11 @@ annotate_frame_end (void) } void -annotate_array_section_begin (int index, struct type *elttype) +annotate_array_section_begin (int idx, struct type *elttype) { if (annotation_level == 2) { - printf_filtered (("\n\032\032array-section-begin %d "), index); + printf_filtered (("\n\032\032array-section-begin %d "), idx); print_value_flags (elttype); printf_filtered (("\n")); } @@ -561,7 +561,7 @@ annotate_array_section_end (void) } static void -breakpoint_changed (int bpno) +breakpoint_changed (struct breakpoint *b) { breakpoints_changed (); } diff --git a/contrib/gdb-7/gdb/annotate.h b/contrib/gdb-7/gdb/annotate.h index 9aa6c62dec..0eae524870 100644 --- a/contrib/gdb-7/gdb/annotate.h +++ b/contrib/gdb-7/gdb/annotate.h @@ -1,6 +1,6 @@ /* Annotation routines for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1994, 1998, 1999, 2000, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1992, 1994, 1998-2000, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/arch-utils.c b/contrib/gdb-7/gdb/arch-utils.c index db79b9ab3d..45dccad059 100644 --- a/contrib/gdb-7/gdb/arch-utils.c +++ b/contrib/gdb-7/gdb/arch-utils.c @@ -1,7 +1,6 @@ /* Dynamic architecture support for GDB, the GNU debugger. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1998-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -786,6 +785,14 @@ default_remote_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr, gdbarch_breakpoint_from_pc (gdbarch, pcptr, kindptr); } +void +default_gen_return_address (struct gdbarch *gdbarch, + struct agent_expr *ax, struct axs_value *value, + CORE_ADDR scope) +{ + error (_("This architecture has no method to collect a return address.")); +} + /* */ /* -Wmissing-prototypes */ diff --git a/contrib/gdb-7/gdb/arch-utils.h b/contrib/gdb-7/gdb/arch-utils.h index 5d05535828..45ddf6483b 100644 --- a/contrib/gdb-7/gdb/arch-utils.h +++ b/contrib/gdb-7/gdb/arch-utils.h @@ -1,7 +1,7 @@ /* Dynamic architecture support for GDB, the GNU debugger. - Copyright (C) 1998, 1999, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1998-2000, 2002-2004, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -164,6 +164,11 @@ extern int default_fast_tracepoint_valid_at (struct gdbarch *gdbarch, extern void default_remote_breakpoint_from_pc (struct gdbarch *, CORE_ADDR *pcptr, int *kindptr); +extern void default_gen_return_address (struct gdbarch *gdbarch, + struct agent_expr *ax, + struct axs_value *value, + CORE_ADDR scope); + extern const char *default_auto_charset (void); extern const char *default_auto_wide_charset (void); diff --git a/contrib/gdb-7/gdb/auxv.c b/contrib/gdb-7/gdb/auxv.c index 28196b4e27..23d1480689 100644 --- a/contrib/gdb-7/gdb/auxv.c +++ b/contrib/gdb-7/gdb/auxv.c @@ -1,7 +1,6 @@ /* Auxiliary vector support for GDB, the GNU debugger. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -26,6 +25,7 @@ #include "valprint.h" #include "gdb_assert.h" #include "gdbcore.h" +#include "observer.h" #include "auxv.h" #include "elf/common.h" @@ -277,6 +277,78 @@ target_auxv_parse (struct target_ops *ops, gdb_byte **readptr, return default_auxv_parse (ops, readptr, endptr, typep, valp); } + +/* Per-inferior data key for auxv. */ +static const struct inferior_data *auxv_inferior_data; + +/* 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. */ +struct auxv_info +{ + LONGEST length; + gdb_byte *data; +}; + +/* Handles the cleanup of the auxv cache for inferior INF. ARG is ignored. + Frees whatever allocated space there is to be freed and sets INF's auxv cache + data pointer to NULL. + + This function is called when the following events occur: inferior_appeared, + inferior_exit and executable_changed. */ + +static void +auxv_inferior_data_cleanup (struct inferior *inf, void *arg) +{ + struct auxv_info *info; + + info = inferior_data (inf, auxv_inferior_data); + if (info != NULL) + { + xfree (info->data); + xfree (info); + set_inferior_data (inf, auxv_inferior_data, NULL); + } +} + +/* Invalidate INF's auxv cache. */ + +static void +invalidate_auxv_cache_inf (struct inferior *inf) +{ + auxv_inferior_data_cleanup (inf, NULL); +} + +/* Invalidate current inferior's auxv cache. */ + +static void +invalidate_auxv_cache (void) +{ + invalidate_auxv_cache_inf (current_inferior ()); +} + +/* Fetch the auxv object from inferior INF. If auxv is cached already, + return a pointer to the cache. If not, fetch the auxv object from the + target and cache it. This function always returns a valid INFO pointer. */ + +static struct auxv_info * +get_auxv_inferior_data (struct target_ops *ops) +{ + struct auxv_info *info; + struct inferior *inf = current_inferior (); + + info = inferior_data (inf, auxv_inferior_data); + if (info == NULL) + { + info = XZALLOC (struct auxv_info); + info->length = target_read_alloc (ops, TARGET_OBJECT_AUXV, + NULL, &info->data); + set_inferior_data (inf, auxv_inferior_data, info); + } + + return info; +} + /* Extract the auxiliary vector entry with a_type matching MATCH. Return zero if no such entry was found, or -1 if there was an error getting the information. On success, return 1 after @@ -286,28 +358,30 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp) { CORE_ADDR type, val; gdb_byte *data; - LONGEST n = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, &data); - gdb_byte *ptr = data; + gdb_byte *ptr; + struct auxv_info *info; + + info = get_auxv_inferior_data (ops); + + data = info->data; + ptr = data; - if (n <= 0) - return n; + if (info->length <= 0) + return info->length; while (1) - switch (target_auxv_parse (ops, &ptr, data + n, &type, &val)) + switch (target_auxv_parse (ops, &ptr, data + info->length, &type, &val)) { case 1: /* Here's an entry, check it. */ if (type == match) { - xfree (data); *valp = val; return 1; } break; case 0: /* End of the vector. */ - xfree (data); return 0; default: /* Bogosity. */ - xfree (data); return -1; } @@ -321,15 +395,18 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) { CORE_ADDR type, val; gdb_byte *data; - LONGEST len = target_read_alloc (ops, TARGET_OBJECT_AUXV, NULL, - &data); - gdb_byte *ptr = data; + gdb_byte *ptr; + struct auxv_info *info; int ents = 0; - if (len <= 0) - return len; + info = get_auxv_inferior_data (ops); - while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0) + data = info->data; + ptr = data; + if (info->length <= 0) + return info->length; + + while (target_auxv_parse (ops, &ptr, data + info->length, &type, &val) > 0) { const char *name = "???"; const char *description = ""; @@ -418,8 +495,6 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops) break; } - xfree (data); - return ents; } @@ -448,4 +523,13 @@ _initialize_auxv (void) add_info ("auxv", info_auxv_command, _("Display the inferior's auxiliary vector.\n\ This is information provided by the operating system at program startup.")); + + /* Set an auxv cache per-inferior. */ + auxv_inferior_data + = register_inferior_data_with_cleanup (auxv_inferior_data_cleanup); + + /* Observers used to invalidate the auxv cache when needed. */ + observer_attach_inferior_exit (invalidate_auxv_cache_inf); + observer_attach_inferior_appeared (invalidate_auxv_cache_inf); + observer_attach_executable_changed (invalidate_auxv_cache); } diff --git a/contrib/gdb-7/gdb/auxv.h b/contrib/gdb-7/gdb/auxv.h index 02cc0b9c77..cba5fe067d 100644 --- a/contrib/gdb-7/gdb/auxv.h +++ b/contrib/gdb-7/gdb/auxv.h @@ -1,7 +1,6 @@ /* Auxiliary vector support for GDB, the GNU debugger. - Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ax-gdb.c b/contrib/gdb-7/gdb/ax-gdb.c index d1736e144c..31e91b9315 100644 --- a/contrib/gdb-7/gdb/ax-gdb.c +++ b/contrib/gdb-7/gdb/ax-gdb.c @@ -1,7 +1,7 @@ /* GDB-specific functions for operating on agent expressions. - Copyright (C) 1998, 1999, 2000, 2001, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1998-2001, 2003, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. @@ -40,6 +40,10 @@ #include "breakpoint.h" #include "tracepoint.h" #include "cp-support.h" +#include "arch-utils.h" + +#include "valprint.h" +#include "c-lang.h" /* To make sense of this file, you should read doc/agentexpr.texi. Then look at the types and enums in ax-gdb.h. For the code itself, @@ -334,6 +338,11 @@ maybe_const_expr (union exp_element **pc) emits the trace bytecodes at the appropriate points. */ int trace_kludge; +/* Inspired by trace_kludge, this indicates that pointers to chars + should get an added tracenz bytecode to record nonzero bytes, up to + a length that is the value of trace_string_kludge. */ +int trace_string_kludge; + /* Scan for all static fields in the given class, including any base classes, and generate tracing bytecodes for each. */ @@ -392,19 +401,35 @@ static void gen_traced_pop (struct gdbarch *gdbarch, struct agent_expr *ax, struct axs_value *value) { + int string_trace = 0; + if (trace_string_kludge + && TYPE_CODE (value->type) == TYPE_CODE_PTR + && c_textual_element_type (check_typedef (TYPE_TARGET_TYPE (value->type)), + 's')) + string_trace = 1; + if (trace_kludge) switch (value->kind) { case axs_rvalue: - /* We don't trace rvalues, just the lvalues necessary to - produce them. So just dispose of this value. */ - ax_simple (ax, aop_pop); + if (string_trace) + { + ax_const_l (ax, trace_string_kludge); + ax_simple (ax, aop_tracenz); + } + else + /* We don't trace rvalues, just the lvalues necessary to + produce them. So just dispose of this value. */ + ax_simple (ax, aop_pop); break; case axs_lvalue_memory: { int length = TYPE_LENGTH (check_typedef (value->type)); + if (string_trace) + ax_simple (ax, aop_dup); + /* There's no point in trying to use a trace_quick bytecode here, since "trace_quick SIZE pop" is three bytes, whereas "const8 SIZE trace" is also three bytes, does the same @@ -412,6 +437,13 @@ gen_traced_pop (struct gdbarch *gdbarch, work correctly for objects with large sizes. */ ax_const_l (ax, length); ax_simple (ax, aop_trace); + + if (string_trace) + { + ax_simple (ax, aop_ref32); + ax_const_l (ax, trace_string_kludge); + ax_simple (ax, aop_tracenz); + } } break; @@ -421,6 +453,15 @@ gen_traced_pop (struct gdbarch *gdbarch, larger than will fit in a stack, so just mark it for collection and be done with it. */ ax_reg_mask (ax, value->u.reg); + + /* But if the register points to a string, assume the value + will fit on the stack and push it anyway. */ + if (string_trace) + { + ax_reg (ax, value->u.reg); + ax_const_l (ax, trace_string_kludge); + ax_simple (ax, aop_tracenz); + } break; } else @@ -1549,7 +1590,7 @@ gen_static_field (struct gdbarch *gdbarch, } else { - char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); + const char *phys_name = TYPE_FIELD_STATIC_PHYSNAME (type, fieldno); struct symbol *sym = lookup_symbol (phys_name, 0, VAR_DOMAIN, 0); if (sym) @@ -2138,18 +2179,17 @@ gen_expr (struct expression *exp, union exp_element **pc, case OP_THIS: { char *this_name; - struct symbol *func, *sym; + struct symbol *sym, *func; struct block *b; + const struct language_defn *lang; - func = block_linkage_function (block_for_pc (ax->scope)); - this_name = language_def (SYMBOL_LANGUAGE (func))->la_name_of_this; - b = SYMBOL_BLOCK_VALUE (func); + b = block_for_pc (ax->scope); + func = block_linkage_function (b); + lang = language_def (SYMBOL_LANGUAGE (func)); - /* Calling lookup_block_symbol is necessary to get the LOC_REGISTER - symbol instead of the LOC_ARG one (if both exist). */ - sym = lookup_block_symbol (b, this_name, VAR_DOMAIN); + sym = lookup_language_this (lang, b); if (!sym) - error (_("no `%s' found"), this_name); + error (_("no `%s' found"), lang->la_name_of_this); gen_var_ref (exp->gdbarch, ax, value, sym); @@ -2445,6 +2485,32 @@ gen_eval_for_expr (CORE_ADDR scope, struct expression *expr) return ax; } +struct agent_expr * +gen_trace_for_return_address (CORE_ADDR scope, struct gdbarch *gdbarch) +{ + struct cleanup *old_chain = 0; + struct agent_expr *ax = new_agent_expr (gdbarch, scope); + struct axs_value value; + + old_chain = make_cleanup_free_agent_expr (ax); + + trace_kludge = 1; + + gdbarch_gen_return_address (gdbarch, ax, &value, scope); + + /* Make sure we record the final object, and get rid of it. */ + gen_traced_pop (gdbarch, ax, &value); + + /* Oh, and terminate. */ + ax_simple (ax, aop_end); + + /* We have successfully built the agent expr, so cancel the cleanup + request. If we add more cleanups that we always want done, this + will have to get more complicated. */ + discard_cleanups (old_chain); + return ax; +} + static void agent_command (char *exp, int from_tty) { @@ -2463,10 +2529,26 @@ agent_command (char *exp, int from_tty) if (exp == 0) error_no_arg (_("expression to translate")); - expr = parse_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); - agent = gen_trace_for_expr (get_frame_pc (fi), expr); - make_cleanup_free_agent_expr (agent); + trace_string_kludge = 0; + if (*exp == '/') + exp = decode_agent_options (exp); + + /* Recognize the return address collection directive specially. Note + that it is not really an expression of any sort. */ + if (strcmp (exp, "$_ret") == 0) + { + agent = gen_trace_for_return_address (get_frame_pc (fi), + get_current_arch ()); + old_chain = make_cleanup_free_agent_expr (agent); + } + else + { + expr = parse_expression (exp); + old_chain = make_cleanup (free_current_contents, &expr); + agent = gen_trace_for_expr (get_frame_pc (fi), expr); + make_cleanup_free_agent_expr (agent); + } + ax_reqs (agent); ax_print (gdb_stdout, agent); diff --git a/contrib/gdb-7/gdb/ax-gdb.h b/contrib/gdb-7/gdb/ax-gdb.h index a2367a67e3..48c35a4a67 100644 --- a/contrib/gdb-7/gdb/ax-gdb.h +++ b/contrib/gdb-7/gdb/ax-gdb.h @@ -1,6 +1,5 @@ /* GDB-specific functions for operating on agent expressions - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1998-2000, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -106,8 +105,12 @@ extern struct agent_expr *gen_trace_for_expr (CORE_ADDR, struct expression *); extern struct agent_expr *gen_trace_for_var (CORE_ADDR, struct gdbarch *, struct symbol *); +extern struct agent_expr *gen_trace_for_return_address (CORE_ADDR, + struct gdbarch *); + extern struct agent_expr *gen_eval_for_expr (CORE_ADDR, struct expression *); extern int trace_kludge; +extern int trace_string_kludge; #endif /* AX_GDB_H */ diff --git a/contrib/gdb-7/gdb/ax-general.c b/contrib/gdb-7/gdb/ax-general.c index 889fac9f0d..4f1ea207af 100644 --- a/contrib/gdb-7/gdb/ax-general.c +++ b/contrib/gdb-7/gdb/ax-general.c @@ -1,6 +1,5 @@ /* Functions for manipulating expressions designed to be executed on the agent - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1998-2000, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ax.h b/contrib/gdb-7/gdb/ax.h index a124575010..a25a3d158a 100644 --- a/contrib/gdb-7/gdb/ax.h +++ b/contrib/gdb-7/gdb/ax.h @@ -1,6 +1,5 @@ /* Definitions for expressions designed to be executed on the agent - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1998-2000, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bcache.c b/contrib/gdb-7/gdb/bcache.c index 76e3893647..2a180af605 100644 --- a/contrib/gdb-7/gdb/bcache.c +++ b/contrib/gdb-7/gdb/bcache.c @@ -2,8 +2,8 @@ Written by Fred Fish Rewritten by Jim Blandy - Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2002-2003, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -209,9 +209,9 @@ expand_hash_table (struct bcache *bcache) never seen those bytes before, add a copy of them to BCACHE. In either case, return a pointer to BCACHE's copy of that string. */ const void * -bcache (const void *addr, int length, struct bcache *bcache) +bcache (const void *addr, int length, struct bcache *cache) { - return bcache_full (addr, length, bcache, NULL); + return bcache_full (addr, length, cache, NULL); } /* Find a copy of the LENGTH bytes at ADDR in BCACHE. If BCACHE has diff --git a/contrib/gdb-7/gdb/bcache.h b/contrib/gdb-7/gdb/bcache.h index 66106e767d..a52f932f21 100644 --- a/contrib/gdb-7/gdb/bcache.h +++ b/contrib/gdb-7/gdb/bcache.h @@ -2,8 +2,8 @@ Written by Fred Fish Rewritten by Jim Blandy - Copyright (C) 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2002-2003, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bfd-target.c b/contrib/gdb-7/gdb/bfd-target.c index cfeb0b12f6..6728800461 100644 --- a/contrib/gdb-7/gdb/bfd-target.c +++ b/contrib/gdb-7/gdb/bfd-target.c @@ -1,7 +1,6 @@ /* Very simple "bfd" target, for GDB, the GNU debugger. - Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -78,14 +77,14 @@ target_bfd_xclose (struct target_ops *t, int quitting) } struct target_ops * -target_bfd_reopen (struct bfd *bfd) +target_bfd_reopen (struct bfd *abfd) { struct target_ops *t; struct target_bfd_data *data; data = XZALLOC (struct target_bfd_data); - data->bfd = bfd; - build_section_table (bfd, &data->table.sections, &data->table.sections_end); + data->bfd = abfd; + build_section_table (abfd, &data->table.sections, &data->table.sections_end); t = XZALLOC (struct target_ops); t->to_shortname = "bfd"; diff --git a/contrib/gdb-7/gdb/bfd-target.h b/contrib/gdb-7/gdb/bfd-target.h index 9771151052..71001c5f34 100644 --- a/contrib/gdb-7/gdb/bfd-target.h +++ b/contrib/gdb-7/gdb/bfd-target.h @@ -1,7 +1,6 @@ /* Very simple "bfd" target, for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/block.c b/contrib/gdb-7/gdb/block.c index 776ae53f5a..57ab4c2024 100644 --- a/contrib/gdb-7/gdb/block.c +++ b/contrib/gdb-7/gdb/block.c @@ -1,7 +1,6 @@ /* Block-related functions for the GNU debugger, GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -25,6 +24,8 @@ #include "gdb_obstack.h" #include "cp-support.h" #include "addrmap.h" +#include "gdbtypes.h" +#include "exceptions.h" /* This is used by struct block to store namespace-related info for C++ files, namely using declarations and the current namespace in @@ -80,6 +81,20 @@ block_linkage_function (const struct block *bl) return BLOCK_FUNCTION (bl); } +/* Return the symbol for the function which contains a specified + block, described by a struct block BL. The return value will be + the closest enclosing function, which might be an inline + function. */ + +struct symbol * +block_containing_function (const struct block *bl) +{ + while (BLOCK_FUNCTION (bl) == NULL && BLOCK_SUPERBLOCK (bl) != NULL) + bl = BLOCK_SUPERBLOCK (bl); + + return BLOCK_FUNCTION (bl); +} + /* Return one if BL represents an inlined function. */ int @@ -160,6 +175,38 @@ blockvector_for_pc_sect (CORE_ADDR pc, struct obj_section *section, return 0; } +/* Return call_site for specified PC in GDBARCH. PC must match exactly, it + must be the next instruction after call (or after tail call jump). Throw + NO_ENTRY_VALUE_ERROR otherwise. This function never returns NULL. */ + +struct call_site * +call_site_for_pc (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + struct symtab *symtab; + void **slot = NULL; + + /* -1 as tail call PC can be already after the compilation unit range. */ + symtab = find_pc_symtab (pc - 1); + + if (symtab != NULL && symtab->call_site_htab != NULL) + slot = htab_find_slot (symtab->call_site_htab, &pc, NO_INSERT); + + if (slot == NULL) + { + struct 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. */ + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_OP_GNU_entry_value resolving cannot find " + "DW_TAG_GNU_call_site %s in %s"), + paddress (gdbarch, pc), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + } + + return *slot; +} + /* Return the blockvector immediately containing the innermost lexical block containing the specified pc value, or 0 if there is none. Backward compatibility, no section. */ diff --git a/contrib/gdb-7/gdb/block.h b/contrib/gdb-7/gdb/block.h index 07d5bc7220..2cbcc1b847 100644 --- a/contrib/gdb-7/gdb/block.h +++ b/contrib/gdb-7/gdb/block.h @@ -1,7 +1,6 @@ /* Code dealing with blocks for GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -129,12 +128,10 @@ struct blockvector #define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n] #define BLOCKVECTOR_MAP(blocklist) ((blocklist)->map) -/* Special block numbers */ - -enum { GLOBAL_BLOCK = 0, STATIC_BLOCK = 1, FIRST_LOCAL_BLOCK = 2 }; - extern struct symbol *block_linkage_function (const struct block *); +extern struct symbol *block_containing_function (const struct block *); + extern int block_inlined_p (const struct block *block); extern int contained_in (const struct block *, const struct block *); @@ -146,6 +143,9 @@ extern struct blockvector *blockvector_for_pc_sect (CORE_ADDR, struct block **, struct symtab *); +extern struct call_site *call_site_for_pc (struct gdbarch *gdbarch, + CORE_ADDR pc); + extern struct block *block_for_pc (CORE_ADDR); extern struct block *block_for_pc_sect (CORE_ADDR, struct obj_section *); diff --git a/contrib/gdb-7/gdb/blockframe.c b/contrib/gdb-7/gdb/blockframe.c index 3b546a7875..38973667cd 100644 --- a/contrib/gdb-7/gdb/blockframe.c +++ b/contrib/gdb-7/gdb/blockframe.c @@ -1,9 +1,7 @@ /* Get info from stack frames; convert between frames, blocks, functions and pc values. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -358,7 +356,7 @@ find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address, if there is no such frame. If BLOCK is NULL, just return NULL. */ struct frame_info * -block_innermost_frame (struct block *block) +block_innermost_frame (const struct block *block) { struct frame_info *frame; CORE_ADDR start; diff --git a/contrib/gdb-7/gdb/breakpoint.c b/contrib/gdb-7/gdb/breakpoint.c index 3ec99416d4..5a8c29ce28 100644 --- a/contrib/gdb-7/gdb/breakpoint.c +++ b/contrib/gdb-7/gdb/breakpoint.c @@ -1,8 +1,6 @@ /* Everything about breakpoints, for GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -38,7 +36,7 @@ #include "target.h" #include "language.h" #include "gdb_string.h" -#include "demangle.h" +#include "gdb-demangle.h" #include "filenames.h" #include "annotate.h" #include "symfile.h" @@ -64,6 +62,10 @@ #include "xml-syscall.h" #include "parser-defs.h" #include "cli/cli-utils.h" +#include "continuations.h" +#include "stack.h" +#include "skip.h" +#include "record.h" /* readline include files */ #include "readline/readline.h" @@ -75,10 +77,6 @@ #include "mi/mi-common.h" #include "python/python.h" -/* Arguments to pass as context to some catch command handlers. */ -#define CATCH_PERMANENT ((void *) (uintptr_t) 0) -#define CATCH_TEMPORARY ((void *) (uintptr_t) 1) - /* Prototypes for local functions. */ static void enable_delete_command (char *, int); @@ -97,21 +95,35 @@ static void ignore_command (char *, int); static int breakpoint_re_set_one (void *); +static void breakpoint_re_set_default (struct breakpoint *); + static void clear_command (char *, int); static void catch_command (char *, int); -static int can_use_hardware_watchpoint (struct value *, int); +static int can_use_hardware_watchpoint (struct value *); static void break_command_1 (char *, int, int); static void mention (struct breakpoint *); +static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *, + enum bptype, + const struct breakpoint_ops *); +static struct bp_location *add_location_to_breakpoint (struct breakpoint *, + const struct symtab_and_line *); + /* This function is used in gdbtk sources and thus can not be made static. */ struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch, - struct symtab_and_line, - enum bptype); + struct symtab_and_line, + enum bptype, + const struct breakpoint_ops *); + +static struct breakpoint * + momentary_breakpoint_from_master (struct breakpoint *orig, + enum bptype type, + const struct breakpoint_ops *ops); static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int); @@ -160,8 +172,6 @@ insertion_state_t; static int remove_breakpoint (struct bp_location *, insertion_state_t); static int remove_breakpoint_1 (struct bp_location *, insertion_state_t); -static enum print_stop_action print_it_typical (bpstat); - static enum print_stop_action print_bp_stop_message (bpstat bs); static int watchpoint_check (void *); @@ -170,13 +180,17 @@ static void maintenance_info_breakpoints (char *, int); static int hw_breakpoint_used_count (void); -static int hw_watchpoint_used_count (enum bptype, int *); +static int hw_watchpoint_use_count (struct breakpoint *); + +static int hw_watchpoint_used_count_others (struct breakpoint *except, + enum bptype type, + int *other_type_used); static void hbreak_command (char *, int); static void thbreak_command (char *, int); -static void do_enable_breakpoint (struct breakpoint *, enum bpdisp); +static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp); static void stop_command (char *arg, int from_tty); @@ -208,8 +222,6 @@ static void update_global_location_list_nothrow (int); static int is_hardware_watchpoint (const struct breakpoint *bpt); -static int is_watchpoint (const struct breakpoint *bpt); - static void insert_breakpoint_locations (void); static int syscall_catchpoint_p (struct breakpoint *b); @@ -224,11 +236,32 @@ static void disable_trace_command (char *, int); static void trace_pass_command (char *, int); +static int is_masked_watchpoint (const struct breakpoint *b); + /* Assuming we're creating a static tracepoint, does S look like a static tracepoint marker spec ("-m MARKER_ID")? */ #define is_marker_spec(s) \ (s != NULL && strncmp (s, "-m", 2) == 0 && ((s)[2] == ' ' || (s)[2] == '\t')) +/* The abstract base class all breakpoint_ops structures inherit + from. */ +static struct breakpoint_ops base_breakpoint_ops; + +/* The breakpoint_ops structure to be inherited by all breakpoint_ops + that are implemented on top of software or hardware breakpoints + (user breakpoints, internal and momentary breakpoints, etc.). */ +static struct breakpoint_ops bkpt_base_breakpoint_ops; + +/* Internal breakpoints class type. */ +static struct breakpoint_ops internal_breakpoint_ops; + +/* Momentary breakpoints class type. */ +static struct breakpoint_ops momentary_breakpoint_ops; + +/* The breakpoint_ops structure to be used in regular user created + breakpoints. */ +struct breakpoint_ops bkpt_breakpoint_ops; + /* A reference-counted struct command_line. This lets multiple breakpoints share a single command list. */ struct counted_command_line @@ -343,8 +376,9 @@ show_always_inserted_mode (struct ui_file *file, int from_tty, int breakpoints_always_inserted_mode (void) { - return (always_inserted_mode == always_inserted_on - || (always_inserted_mode == always_inserted_auto && non_stop)); + return ((always_inserted_mode == always_inserted_on + || (always_inserted_mode == always_inserted_auto && non_stop)) + && !RECORD_IS_USED); } void _initialize_breakpoint (void); @@ -359,7 +393,7 @@ static int overlay_events_enabled; int target_exact_watchpoints = 0; /* Walk the following statement or block through all breakpoints. - ALL_BREAKPOINTS_SAFE does so even if the statment deletes the + ALL_BREAKPOINTS_SAFE does so even if the statement deletes the current breakpoint. */ #define ALL_BREAKPOINTS(B) for (B = breakpoint_chain; B; B = B->next) @@ -543,19 +577,6 @@ make_cleanup_decref_counted_command_line (struct counted_command_line **cmdp) return make_cleanup (do_cleanup_counted_command_line, cmdp); } -/* Default address, symtab and line to put a breakpoint at - for "break" command with no arg. - If default_breakpoint_valid is zero, the other three are - not valid, and "break" with no arg is an error. - - This set by print_stack_frame, which calls set_default_breakpoint. */ - -int default_breakpoint_valid; -CORE_ADDR default_breakpoint_address; -struct symtab *default_breakpoint_symtab; -int default_breakpoint_line; -struct program_space *default_breakpoint_pspace; - /* Return the breakpoint with the specified number, or NULL if the number does not refer to an existing breakpoint. */ @@ -578,17 +599,26 @@ void set_breakpoint_condition (struct breakpoint *b, char *exp, int from_tty) { - struct bp_location *loc = b->loc; + xfree (b->cond_string); + b->cond_string = NULL; - for (; loc; loc = loc->next) + if (is_watchpoint (b)) { - xfree (loc->cond); - loc->cond = NULL; + struct watchpoint *w = (struct watchpoint *) b; + + xfree (w->cond_exp); + w->cond_exp = NULL; + } + else + { + struct bp_location *loc; + + for (loc = b->loc; loc; loc = loc->next) + { + xfree (loc->cond); + loc->cond = NULL; + } } - xfree (b->cond_string); - b->cond_string = NULL; - xfree (b->cond_exp); - b->cond_exp = NULL; if (*exp == 0) { @@ -606,15 +636,19 @@ set_breakpoint_condition (struct breakpoint *b, char *exp, if (is_watchpoint (b)) { + struct watchpoint *w = (struct watchpoint *) b; + innermost_block = NULL; arg = exp; - b->cond_exp = parse_exp_1 (&arg, 0, 0); + w->cond_exp = parse_exp_1 (&arg, 0, 0); if (*arg) error (_("Junk at end of expression")); - b->cond_exp_valid_block = innermost_block; + w->cond_exp_valid_block = innermost_block; } else { + struct bp_location *loc; + for (loc = b->loc; loc; loc = loc->next) { arg = exp; @@ -626,7 +660,7 @@ set_breakpoint_condition (struct breakpoint *b, char *exp, } } breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* condition N EXP -- set break condition of breakpoint N to EXP. */ @@ -697,15 +731,21 @@ check_no_tracepoint_commands (struct command_line *commands) /* Encapsulate tests for different types of tracepoints. */ +static int +is_tracepoint_type (enum bptype type) +{ + return (type == bp_tracepoint + || type == bp_fast_tracepoint + || type == bp_static_tracepoint); +} + int is_tracepoint (const struct breakpoint *b) { - return (b->type == bp_tracepoint - || b->type == bp_fast_tracepoint - || b->type == bp_static_tracepoint); + return is_tracepoint_type (b->type); } - -/* A helper function that validsates that COMMANDS are valid for a + +/* A helper function that validates that COMMANDS are valid for a breakpoint. This function will throw an exception if a problem is found. */ @@ -791,7 +831,7 @@ breakpoint_set_commands (struct breakpoint *b, decref_counted_command_line (&b->commands); b->commands = alloc_counted_command_line (commands); breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* Set the internal `silent' flag on the breakpoint. Note that this @@ -805,7 +845,7 @@ breakpoint_set_silent (struct breakpoint *b, int silent) b->silent = silent; if (old_silent != silent) - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* Set the thread for this breakpoint. If THREAD is -1, make the @@ -818,7 +858,7 @@ breakpoint_set_thread (struct breakpoint *b, int thread) b->thread = thread; if (old_thread != thread) - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } /* Set the task for this breakpoint. If TASK is 0, make the @@ -831,7 +871,7 @@ breakpoint_set_task (struct breakpoint *b, int task) b->task = task; if (old_task != task) - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } void @@ -908,7 +948,7 @@ do_map_commands_command (struct breakpoint *b, void *data) decref_counted_command_line (&b->commands); b->commands = info->cmd; breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); } } @@ -987,7 +1027,7 @@ bp_location_has_shadow (struct bp_location *bl) if (!bl->inserted) return 0; if (bl->target_info.shadow_len == 0) - /* bp isn't valid, or doesn't shadow memory. */ + /* BL isn't valid, or doesn't shadow memory. */ return 0; return 1; } @@ -1007,7 +1047,9 @@ bp_location_has_shadow (struct bp_location *bl) bl->address + bp_location_shadow_len_after_address_max <= memaddr */ void -breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) +breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, + const gdb_byte *writebuf_org, + ULONGEST memaddr, LONGEST len) { /* Left boundary, right boundary and median element of our binary search. */ @@ -1075,7 +1117,7 @@ breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) warning (_("reading through apparently deleted breakpoint #%d?"), bl->owner->number); - /* Performance optimization: any futher element can no longer affect BUF + /* Performance optimization: any further element can no longer affect BUF content. */ if (bl->address >= bp_location_placed_address_before_address_max @@ -1119,8 +1161,32 @@ breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, LONGEST len) bp_size -= (bp_addr + bp_size) - (memaddr + len); } - memcpy (buf + bp_addr - memaddr, - bl->target_info.shadow_contents + bptoffset, bp_size); + if (readbuf != NULL) + { + /* Update the read buffer with this inserted breakpoint's + shadow. */ + memcpy (readbuf + bp_addr - memaddr, + bl->target_info.shadow_contents + bptoffset, bp_size); + } + else + { + struct gdbarch *gdbarch = bl->gdbarch; + const unsigned char *bp; + CORE_ADDR placed_address = bl->target_info.placed_address; + unsigned placed_size = bl->target_info.placed_size; + + /* Update the shadow with what we want to write to memory. */ + memcpy (bl->target_info.shadow_contents + bptoffset, + writebuf_org + bp_addr - memaddr, bp_size); + + /* Determine appropriate breakpoint contents and size for this + address. */ + bp = gdbarch_breakpoint_from_pc (gdbarch, &placed_address, &placed_size); + + /* Update the final write buffer with this inserted + breakpoint's INSN. */ + memcpy (writebuf + bp_addr - memaddr, bp + bptoffset, bp_size); + } } } @@ -1138,25 +1204,24 @@ is_hardware_watchpoint (const struct breakpoint *bpt) /* Return true if BPT is of any watchpoint kind, hardware or software. */ -static int +int is_watchpoint (const struct breakpoint *bpt) { return (is_hardware_watchpoint (bpt) || bpt->type == bp_watchpoint); } -/* Assuming that B is a watchpoint: returns true if the current thread - and its running state are safe to evaluate or update watchpoint B. - Watchpoints on local expressions need to be evaluated in the - context of the thread that was current when the watchpoint was - created, and, that thread needs to be stopped to be able to select - the correct frame context. Watchpoints on global expressions can - be evaluated on any thread, and in any state. It is presently left - to the target allowing memory accesses when threads are - running. */ +/* Returns true if the current thread and its running state are safe + to evaluate or update watchpoint B. Watchpoints on local + expressions need to be evaluated in the context of the thread that + was current when the watchpoint was created, and, that thread needs + to be stopped to be able to select the correct frame context. + Watchpoints on global expressions can be evaluated on any thread, + and in any state. It is presently left to the target allowing + memory accesses when threads are running. */ static int -watchpoint_in_thread_scope (struct breakpoint *b) +watchpoint_in_thread_scope (struct watchpoint *b) { return (ptid_equal (b->watchpoint_thread, null_ptid) || (ptid_equal (inferior_ptid, b->watchpoint_thread) @@ -1167,9 +1232,9 @@ watchpoint_in_thread_scope (struct breakpoint *b) associated bp_watchpoint_scope breakpoint. */ static void -watchpoint_del_at_next_stop (struct breakpoint *b) +watchpoint_del_at_next_stop (struct watchpoint *w) { - gdb_assert (is_watchpoint (b)); + struct breakpoint *b = &w->base; if (b->related_breakpoint != b) { @@ -1235,21 +1300,19 @@ watchpoint_del_at_next_stop (struct breakpoint *b) watchpoint removal from inferior. */ static void -update_watchpoint (struct breakpoint *b, int reparse) +update_watchpoint (struct watchpoint *b, int reparse) { int within_current_scope; struct frame_id saved_frame_id; int frame_saved; - gdb_assert (is_watchpoint (b)); - /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread that was used to create the watchpoint. */ if (!watchpoint_in_thread_scope (b)) return; - if (b->disposition == disp_del_at_next_stop) + if (b->base.disposition == disp_del_at_next_stop) return; frame_saved = 0; @@ -1286,7 +1349,7 @@ update_watchpoint (struct breakpoint *b, int reparse) /* We don't free locations. They are stored in the bp_location array and update_global_location_list will eventually delete them and remove breakpoints if needed. */ - b->loc = NULL; + b->base.loc = NULL; if (within_current_scope && reparse) { @@ -1310,7 +1373,7 @@ update_watchpoint (struct breakpoint *b, int reparse) /* Note that unlike with breakpoints, the watchpoint's condition expression is stored in the breakpoint object, not in the locations (re)created below. */ - if (b->cond_string != NULL) + if (b->base.cond_string != NULL) { if (b->cond_exp != NULL) { @@ -1318,7 +1381,7 @@ update_watchpoint (struct breakpoint *b, int reparse) b->cond_exp = NULL; } - s = b->cond_string; + s = b->base.cond_string; b->cond_exp = parse_exp_1 (&s, b->cond_exp_valid_block, 0); } } @@ -1345,8 +1408,10 @@ update_watchpoint (struct breakpoint *b, int reparse) /* Avoid setting b->val if it's already set. The meaning of b->val is 'the last value' user saw, and we should update it only if we reported that last value to user. As it - happens, the code that reports it updates b->val directly. */ - if (!b->val_valid) + happens, the code that reports it updates b->val directly. + We don't keep track of the memory value for masked + watchpoints. */ + if (!b->val_valid && !is_masked_watchpoint (&b->base)) { b->val = v; b->val_valid = 1; @@ -1381,13 +1446,13 @@ update_watchpoint (struct breakpoint *b, int reparse) addr = value_address (v); len = TYPE_LENGTH (value_type (v)); type = hw_write; - if (b->type == bp_read_watchpoint) + if (b->base.type == bp_read_watchpoint) type = hw_read; - else if (b->type == bp_access_watchpoint) + else if (b->base.type == bp_access_watchpoint) type = hw_access; - - loc = allocate_bp_location (b); - for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next)) + + loc = allocate_bp_location (&b->base); + for (tmp = &(b->base.loc); *tmp != NULL; tmp = &((*tmp)->next)) ; *tmp = loc; loc->gdbarch = get_type_arch (value_type (v)); @@ -1404,51 +1469,81 @@ update_watchpoint (struct breakpoint *b, int reparse) an ordinary watchpoint depending on the hardware support and free hardware slots. REPARSE is set when the inferior is started. */ - if ((b->type == bp_watchpoint || b->type == bp_hardware_watchpoint) - && reparse) + if (reparse) { int reg_cnt; enum bp_loc_type loc_type; struct bp_location *bl; - reg_cnt = can_use_hardware_watchpoint (val_chain, b->exact); + reg_cnt = can_use_hardware_watchpoint (val_chain); if (reg_cnt) { int i, target_resources_ok, other_type_used; - enum enable_state orig_enable_state; + enum bptype type; + + /* Use an exact watchpoint when there's only one memory region to be + watched, and only one debug register is needed to watch it. */ + b->exact = target_exact_watchpoints && reg_cnt == 1; /* We need to determine how many resources are already used for all other hardware watchpoints plus this one to see if we still have enough resources to also fit - this watchpoint in as well. To guarantee the - hw_watchpoint_used_count call below counts this - watchpoint, make sure that it is marked as a hardware - watchpoint. */ - b->type = bp_hardware_watchpoint; + this watchpoint in as well. */ - /* hw_watchpoint_used_count ignores disabled watchpoints, - and b might be disabled if we're being called from - do_enable_breakpoint. */ - orig_enable_state = b->enable_state; - b->enable_state = bp_enabled; + /* If this is a software watchpoint, we try to turn it + to a hardware one -- count resources as if B was of + hardware watchpoint type. */ + type = b->base.type; + if (type == bp_watchpoint) + type = bp_hardware_watchpoint; - i = hw_watchpoint_used_count (bp_hardware_watchpoint, - &other_type_used); + /* This watchpoint may or may not have been placed on + the list yet at this point (it won't be in the list + if we're trying to create it for the first time, + through watch_command), so always account for it + manually. */ - b->enable_state = orig_enable_state; + /* Count resources used by all watchpoints except B. */ + i = hw_watchpoint_used_count_others (&b->base, type, &other_type_used); - target_resources_ok = target_can_use_hardware_watchpoint - (bp_hardware_watchpoint, i, other_type_used); + /* Add in the resources needed for B. */ + i += hw_watchpoint_use_count (&b->base); + + target_resources_ok + = target_can_use_hardware_watchpoint (type, i, other_type_used); if (target_resources_ok <= 0) - b->type = bp_watchpoint; + { + int sw_mode = b->base.ops->works_in_software_mode (&b->base); + + if (target_resources_ok == 0 && !sw_mode) + error (_("Target does not support this type of " + "hardware watchpoint.")); + else if (target_resources_ok < 0 && !sw_mode) + error (_("There are not enough available hardware " + "resources for this watchpoint.")); + + /* Downgrade to software watchpoint. */ + b->base.type = bp_watchpoint; + } + else + { + /* If this was a software watchpoint, we've just + found we have enough resources to turn it to a + hardware watchpoint. Otherwise, this is a + nop. */ + b->base.type = type; + } } + else if (!b->base.ops->works_in_software_mode (&b->base)) + error (_("Expression cannot be implemented with " + "read/access watchpoint.")); else - b->type = bp_watchpoint; + b->base.type = bp_watchpoint; - loc_type = (b->type == bp_watchpoint? bp_loc_other + loc_type = (b->base.type == bp_watchpoint? bp_loc_other : bp_loc_hardware_watchpoint); - for (bl = b->loc; bl; bl = bl->next) + for (bl = b->base.loc; bl; bl = bl->next) bl->loc_type = loc_type; } @@ -1463,13 +1558,14 @@ update_watchpoint (struct breakpoint *b, int reparse) above left it without any location set up. But, bpstat_stop_status requires a location to be able to report stops, so make sure there's at least a dummy one. */ - if (b->type == bp_watchpoint && b->loc == NULL) + if (b->base.type == bp_watchpoint && b->base.loc == NULL) { - b->loc = allocate_bp_location (b); - b->loc->pspace = frame_pspace; - b->loc->address = -1; - b->loc->length = -1; - b->loc->watchpoint_type = -1; + struct breakpoint *base = &b->base; + base->loc = allocate_bp_location (base); + base->loc->pspace = frame_pspace; + base->loc->address = -1; + base->loc->length = -1; + base->loc->watchpoint_type = -1; } } else if (!within_current_scope) @@ -1477,7 +1573,7 @@ update_watchpoint (struct breakpoint *b, int reparse) printf_filtered (_("\ Watchpoint %d deleted because the program has left the block\n\ in which its expression is valid.\n"), - b->number); + b->base.number); watchpoint_del_at_next_stop (b); } @@ -1488,7 +1584,10 @@ in which its expression is valid.\n"), /* Returns 1 iff breakpoint location should be - inserted in the inferior. */ + inserted in the inferior. We don't differentiate the type of BL's owner + (breakpoint vs. tracepoint), although insert_location in tracepoint's + breakpoint_ops is not defined, because in insert_bp_location, + tracepoint's insert_location will not be called. */ static int should_be_inserted (struct bp_location *bl) { @@ -1501,6 +1600,9 @@ should_be_inserted (struct bp_location *bl) if (!bl->enabled || bl->shlib_disabled || bl->duplicate) return 0; + if (user_breakpoint_p (bl->owner) && bl->pspace->executing_startup) + return 0; + /* This is set for example, when we're attached to the parent of a vfork, and have detached from the child. The child is running free, and we expect it to do an exec or exit, at which point the @@ -1512,17 +1614,29 @@ should_be_inserted (struct bp_location *bl) if (bl->pspace->breakpoints_not_allowed) return 0; - /* Tracepoints are inserted by the target at a time of its choosing, - not by us. */ - if (is_tracepoint (bl->owner)) - return 0; - return 1; } +/* Same as should_be_inserted but does the check assuming + that the location is not duplicated. */ + +static int +unduplicated_should_be_inserted (struct bp_location *bl) +{ + int result; + const int save_duplicate = bl->duplicate; + + bl->duplicate = 0; + result = should_be_inserted (bl); + bl->duplicate = save_duplicate; + return result; +} + /* Insert a low-level "breakpoint" of some type. BL is the breakpoint location. Any error messages are printed to TMP_ERROR_STREAM; and DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems. + Returns 0 for success, 1 if the bp_location type is not supported or + -1 for failure. NOTE drow/2003-09-09: This routine could be broken down to an object-style method for each breakpoint or catchpoint type. */ @@ -1610,12 +1724,7 @@ insert_bp_location (struct bp_location *bl, { /* No overlay handling: just set the breakpoint. */ - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (bl->gdbarch, - &bl->target_info); - else - val = target_insert_breakpoint (bl->gdbarch, - &bl->target_info); + val = bl->owner->ops->insert_location (bl); } else { @@ -1649,12 +1758,7 @@ insert_bp_location (struct bp_location *bl, if (section_is_mapped (bl->section)) { /* Yes. This overlay section is mapped into memory. */ - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_insert_hw_breakpoint (bl->gdbarch, - &bl->target_info); - else - val = target_insert_breakpoint (bl->gdbarch, - &bl->target_info); + val = bl->owner->ops->insert_location (bl); } else { @@ -1672,6 +1776,7 @@ insert_bp_location (struct bp_location *bl, /* See also: disable_breakpoints_in_shlibs. */ val = 0; bl->shlib_disabled = 1; + observer_notify_breakpoint_modified (bl->owner); if (!*disabled_breaks) { fprintf_unfiltered (tmp_error_stream, @@ -1845,7 +1950,11 @@ insert_breakpoints (void) ALL_BREAKPOINTS (bpt) if (is_hardware_watchpoint (bpt)) - update_watchpoint (bpt, 0 /* don't reparse. */); + { + struct watchpoint *w = (struct watchpoint *) bpt; + + update_watchpoint (w, 0 /* don't reparse. */); + } update_global_location_list (1); @@ -1856,17 +1965,14 @@ insert_breakpoints (void) insert_breakpoint_locations (); } -/* insert_breakpoints is used when starting or continuing the program. - remove_breakpoints is used when the program stops. - Both return zero if successful, - or an `errno' value if could not write the inferior. */ +/* Used when starting or continuing the program. */ static void insert_breakpoint_locations (void) { struct breakpoint *bpt; struct bp_location *bl, **blp_tmp; - int error = 0; + int error_flag = 0; int val = 0; int disabled_breaks = 0; int hw_breakpoint_error = 0; @@ -1905,7 +2011,7 @@ insert_breakpoint_locations (void) val = insert_bp_location (bl, tmp_error_stream, &disabled_breaks, &hw_breakpoint_error); if (val) - error = val; + error_flag = val; } /* If we failed to insert all locations of a watchpoint, remove @@ -1940,11 +2046,11 @@ insert_breakpoint_locations (void) fprintf_unfiltered (tmp_error_stream, "Could not insert hardware watchpoint %d.\n", bpt->number); - error = -1; + error_flag = -1; } } - if (error) + if (error_flag) { /* If a hardware breakpoint or watchpoint was inserted, add a message about possibly exhausted resources. */ @@ -1961,6 +2067,10 @@ You may have requested too many hardware breakpoints/watchpoints.\n"); do_cleanups (cleanups); } +/* Used when the program stops. + Returns zero if successful, or non-zero if there was a problem + removing a breakpoint location. */ + int remove_breakpoints (void) { @@ -1969,7 +2079,7 @@ remove_breakpoints (void) ALL_BP_LOCATIONS (bl, blp_tmp) { - if (bl->inserted) + if (bl->inserted && !is_tracepoint (bl->owner)) val |= remove_breakpoint (bl, mark_uninserted); } return val; @@ -1999,20 +2109,6 @@ remove_breakpoints_pid (int pid) return 0; } -int -remove_hw_watchpoints (void) -{ - struct bp_location *bl, **blp_tmp; - int val = 0; - - ALL_BP_LOCATIONS (bl, blp_tmp) - { - if (bl->inserted && bl->loc_type == bp_loc_hardware_watchpoint) - val |= remove_breakpoint (bl, mark_uninserted); - } - return val; -} - int reattach_breakpoints (int pid) { @@ -2061,7 +2157,7 @@ static int internal_breakpoint_number = -1; /* Set the breakpoint number of B, depending on the value of INTERNAL. If INTERNAL is non-zero, the breakpoint number will be populated from internal_breakpoint_number and that variable decremented. - Otherwis the breakpoint number will be populated from + Otherwise the breakpoint number will be populated from breakpoint_count and that value incremented. Internal breakpoints do not set the internal var bpnum. */ static void @@ -2078,7 +2174,8 @@ set_breakpoint_number (int internal, struct breakpoint *b) static struct breakpoint * create_internal_breakpoint (struct gdbarch *gdbarch, - CORE_ADDR address, enum bptype type) + CORE_ADDR address, enum bptype type, + const struct breakpoint_ops *ops) { struct symtab_and_line sal; struct breakpoint *b; @@ -2089,7 +2186,7 @@ create_internal_breakpoint (struct gdbarch *gdbarch, sal.section = find_pc_overlay (sal.pc); sal.pspace = current_program_space; - b = set_raw_breakpoint (gdbarch, sal, type); + b = set_raw_breakpoint (gdbarch, sal, type, ops); b->number = internal_breakpoint_number--; b->disposition = disp_donttouch; @@ -2184,7 +2281,8 @@ create_overlay_event_breakpoint (void) addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym); b = create_internal_breakpoint (get_objfile_arch (objfile), addr, - bp_overlay_event); + bp_overlay_event, + &internal_breakpoint_ops); b->addr_string = xstrdup (func_name); if (overlay_debugging == ovly_auto) @@ -2252,7 +2350,8 @@ create_longjmp_master_breakpoint (void) } addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]); - b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master); + b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master, + &internal_breakpoint_ops); b->addr_string = xstrdup (func_name); b->enable_state = bp_disabled; } @@ -2307,7 +2406,8 @@ create_std_terminate_master_breakpoint (void) addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym); b = create_internal_breakpoint (get_objfile_arch (objfile), addr, - bp_std_terminate_master); + bp_std_terminate_master, + &internal_breakpoint_ops); b->addr_string = xstrdup (func_name); b->enable_state = bp_disabled; } @@ -2357,7 +2457,8 @@ create_exception_master_breakpoint (void) addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym); addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, ¤t_target); - b = create_internal_breakpoint (gdbarch, addr, bp_exception_master); + b = create_internal_breakpoint (gdbarch, addr, bp_exception_master, + &internal_breakpoint_ops); b->addr_string = xstrdup (func_name); b->enable_state = bp_disabled; } @@ -2413,7 +2514,7 @@ update_breakpoints_after_exec (void) } /* Step-resume breakpoints are meaningless after an exec(). */ - if (b->type == bp_step_resume) + if (b->type == bp_step_resume || b->type == bp_hp_step_resume) { delete_breakpoint (b); continue; @@ -2452,7 +2553,7 @@ update_breakpoints_after_exec (void) gets 'round to deleting the "use to be a bp_finish" breakpoint. We really must allow finish_command to delete a bp_finish. - In the absense of a general solution for the "how do we know + In the absence of a general solution for the "how do we know it's safe to delete something others may have handles to?" problem, what we'll do here is just uninsert the bp_finish, and let finish_command delete it. @@ -2548,11 +2649,7 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) || !(section_is_overlay (bl->section))) { /* No overlay handling: just remove the breakpoint. */ - - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); - else - val = target_remove_breakpoint (bl->gdbarch, &bl->target_info); + val = bl->owner->ops->remove_location (bl); } else { @@ -2580,16 +2677,13 @@ remove_breakpoint_1 (struct bp_location *bl, insertion_state_t is) remove the breakpoint if the section had been unmapped, but let's not rely on that being safe. We don't know what the overlay manager might do. */ - if (bl->loc_type == bp_loc_hardware_breakpoint) - val = target_remove_hw_breakpoint (bl->gdbarch, - &bl->target_info); /* However, we should remove *software* breakpoints only if the section is still mapped, or else we overwrite wrong code with the saved shadow contents. */ - else if (section_is_mapped (bl->section)) - val = target_remove_breakpoint (bl->gdbarch, - &bl->target_info); + if (bl->loc_type == bp_loc_hardware_breakpoint + || section_is_mapped (bl->section)) + val = bl->owner->ops->remove_location (bl); else val = 0; } @@ -2752,19 +2846,22 @@ breakpoint_init_inferior (enum inf_context context) case bp_hardware_watchpoint: case bp_read_watchpoint: case bp_access_watchpoint: + { + struct watchpoint *w = (struct watchpoint *) b; - /* Likewise for watchpoints on local expressions. */ - if (b->exp_valid_block != NULL) - delete_breakpoint (b); - else if (context == inf_starting) - { - /* Reset val field to force reread of starting value in - insert_breakpoints. */ - if (b->val) - value_free (b->val); - b->val = NULL; - b->val_valid = 0; + /* Likewise for watchpoints on local expressions. */ + if (w->exp_valid_block != NULL) + delete_breakpoint (b); + else if (context == inf_starting) + { + /* Reset val field to force reread of starting value in + insert_breakpoints. */ + if (w->val) + value_free (w->val); + w->val = NULL; + w->val_valid = 0; } + } break; default: break; @@ -2788,7 +2885,7 @@ breakpoint_init_inferior (enum inf_context context) permanent breakpoint. - When continuing from a location with an ordinary breakpoint, we actually single step once before calling insert_breakpoints. - - When continuing from a localion with a permanent breakpoint, we + - When continuing from a location with a permanent breakpoint, we need to use the `SKIP_PERMANENT_BREAKPOINT' macro, provided by the target, to advance the PC past the breakpoint. */ @@ -3135,15 +3232,25 @@ bpstat_num (bpstat *bsp, int *num) return 1; } -/* Modify BS so that the actions will not be performed. */ +/* See breakpoint.h. */ void -bpstat_clear_actions (bpstat bs) +bpstat_clear_actions (void) { - for (; bs != NULL; bs = bs->next) + struct thread_info *tp; + bpstat bs; + + if (ptid_equal (inferior_ptid, null_ptid)) + return; + + tp = find_thread_ptid (inferior_ptid); + if (tp == NULL) + return; + + for (bs = tp->control.stop_bpstat; bs != NULL; bs = bs->next) { decref_counted_command_line (&bs->commands); - bs->commands_left = NULL; + if (bs->old_val != NULL) { value_free (bs->old_val); @@ -3180,6 +3287,16 @@ cleanup_executing_breakpoints (void *ignore) executing_breakpoint_commands = 0; } +/* Return non-zero iff CMD as the first line of a command sequence is `silent' + or its equivalent. */ + +static int +command_line_is_silent (struct command_line *cmd) +{ + return cmd && (strcmp ("silent", cmd->line) == 0 + || (xdb_commands && strcmp ("Q", cmd->line) == 0)); +} + /* Execute all the commands associated with all the breakpoints at this location. Any of these commands could cause the process to proceed beyond this point, etc. We look out for such changes by @@ -3204,6 +3321,8 @@ bpstat_do_actions_1 (bpstat *bsp) executing_breakpoint_commands = 1; old_chain = make_cleanup (cleanup_executing_breakpoints, 0); + prevent_dont_repeat (); + /* This pointer will iterate over the list of bpstat's. */ bs = *bsp; @@ -3226,10 +3345,13 @@ bpstat_do_actions_1 (bpstat *bsp) the tree when we're done. */ ccmd = bs->commands; bs->commands = NULL; - this_cmd_tree_chain - = make_cleanup_decref_counted_command_line (&ccmd); - cmd = bs->commands_left; - bs->commands_left = NULL; + this_cmd_tree_chain = make_cleanup_decref_counted_command_line (&ccmd); + cmd = ccmd ? ccmd->commands : NULL; + if (command_line_is_silent (cmd)) + { + /* The action has been already done by bpstat_stop_status. */ + cmd = cmd->next; + } while (cmd != NULL) { @@ -3276,6 +3398,8 @@ bpstat_do_actions_1 (bpstat *bsp) void bpstat_do_actions (void) { + struct cleanup *cleanup_if_error = make_bpstat_clear_actions_cleanup (); + /* Do any commands attached to breakpoint we are stopped at. */ while (!ptid_equal (inferior_ptid, null_ptid) && target_has_execution @@ -3287,6 +3411,8 @@ bpstat_do_actions (void) indicate the inferior was not resumed. */ if (!bpstat_do_actions_1 (&inferior_thread ()->control.stop_bpstat)) break; + + discard_cleanups (cleanup_if_error); } /* Print out the (old or new) value associated with a watchpoint. */ @@ -3304,289 +3430,74 @@ watchpoint_value_print (struct value *val, struct ui_file *stream) } } -/* This is the normal print function for a bpstat. In the future, - much of this logic could (should?) be moved to bpstat_stop_status, - by having it set different print_it values. - - Current scheme: When we stop, bpstat_print() is called. It loops - through the bpstat list of things causing this stop, calling the - print_bp_stop_message function on each one. The behavior of the - print_bp_stop_message function depends on the print_it field of - bpstat. If such field so indicates, call this function here. - - Return values from this routine (ultimately used by bpstat_print() - and normal_stop() to decide what to do): - PRINT_NOTHING: Means we already printed all we needed to print, - don't print anything else. - PRINT_SRC_ONLY: Means we printed something, and we do *not* desire - that something to be followed by a location. - PRINT_SCR_AND_LOC: Means we printed something, and we *do* desire - that something to be followed by a location. - PRINT_UNKNOWN: Means we printed nothing or we need to do some more - analysis. */ +/* Generic routine for printing messages indicating why we + stopped. The behavior of this function depends on the value + 'print_it' in the bpstat structure. Under some circumstances we + may decide not to print anything here and delegate the task to + normal_stop(). */ static enum print_stop_action -print_it_typical (bpstat bs) +print_bp_stop_message (bpstat bs) { - struct cleanup *old_chain; - struct breakpoint *b; - const struct bp_location *bl; - struct ui_stream *stb; - int bp_temp = 0; - enum print_stop_action result; - - gdb_assert (bs->bp_location_at != NULL); - - bl = bs->bp_location_at; - b = bs->breakpoint_at; - - stb = ui_out_stream_new (uiout); - old_chain = make_cleanup_ui_out_stream_delete (stb); - - switch (b->type) + switch (bs->print_it) { - case bp_breakpoint: - case bp_hardware_breakpoint: - bp_temp = b->disposition == disp_del; - if (bl->address != bl->requested_address) - breakpoint_adjustment_warning (bl->requested_address, - bl->address, - b->number, 1); - annotate_breakpoint (b->number); - if (bp_temp) - ui_out_text (uiout, "\nTemporary breakpoint "); - else - ui_out_text (uiout, "\nBreakpoint "); - if (ui_out_is_mi_like_p (uiout)) - { - ui_out_field_string (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); - ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); - } - ui_out_field_int (uiout, "bkptno", b->number); - ui_out_text (uiout, ", "); - result = PRINT_SRC_AND_LOC; + case print_it_noop: + /* Nothing should be printed for this bpstat entry. */ + return PRINT_UNKNOWN; break; - case bp_shlib_event: - /* Did we stop because the user set the stop_on_solib_events - variable? (If so, we report this as a generic, "Stopped due - to shlib event" message.) */ - printf_filtered (_("Stopped due to shared library event\n")); - result = PRINT_NOTHING; + case print_it_done: + /* We still want to print the frame, but we already printed the + relevant messages. */ + return PRINT_SRC_AND_LOC; break; - case bp_thread_event: - /* Not sure how we will get here. - GDB should not stop for these breakpoints. */ - printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n")); - result = PRINT_NOTHING; - break; + case print_it_normal: + { + struct breakpoint *b = bs->breakpoint_at; - case bp_overlay_event: - /* By analogy with the thread event, GDB should not stop for these. */ - printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n")); - result = PRINT_NOTHING; - break; + /* bs->breakpoint_at can be NULL if it was a momentary breakpoint + which has since been deleted. */ + if (b == NULL) + return PRINT_UNKNOWN; - case bp_longjmp_master: - /* These should never be enabled. */ - printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n")); - result = PRINT_NOTHING; + /* Normal case. Call the breakpoint's print_it method. */ + return b->ops->print_it (bs); + } break; - case bp_std_terminate_master: - /* These should never be enabled. */ - printf_filtered (_("std::terminate Master Breakpoint: " - "gdb should not stop!\n")); - result = PRINT_NOTHING; + default: + internal_error (__FILE__, __LINE__, + _("print_bp_stop_message: unrecognized enum value")); break; + } +} - case bp_exception_master: - /* These should never be enabled. */ - printf_filtered (_("Exception Master Breakpoint: " - "gdb should not stop!\n")); - result = PRINT_NOTHING; - break; +/* Print a message indicating what happened. This is called from + normal_stop(). The input to this routine is the head of the bpstat + list - a list of the eventpoints that caused this stop. KIND is + the target_waitkind for the stopping event. This + routine calls the generic print routine for printing a message + about reasons for stopping. This will print (for example) the + "Breakpoint n," part of the output. The return value of this + routine is one of: - case bp_watchpoint: - case bp_hardware_watchpoint: - annotate_watchpoint (b->number); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER)); - mention (b); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nOld value = "); - watchpoint_value_print (bs->old_val, stb->stream); - ui_out_field_stream (uiout, "old", stb); - ui_out_text (uiout, "\nNew value = "); - watchpoint_value_print (b->val, stb->stream); - ui_out_field_stream (uiout, "new", stb); - ui_out_text (uiout, "\n"); - /* More than one watchpoint may have been triggered. */ - result = PRINT_UNKNOWN; - break; + PRINT_UNKNOWN: Means we printed nothing. + PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent + code to print the location. An example is + "Breakpoint 1, " which should be followed by + the location. + PRINT_SRC_ONLY: Means we printed something, but there is no need + to also print the location part of the message. + An example is the catch/throw messages, which + don't require a location appended to the end. + PRINT_NOTHING: We have done some printing and we don't need any + further info to be printed. */ - case bp_read_watchpoint: - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER)); - mention (b); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nValue = "); - watchpoint_value_print (b->val, stb->stream); - ui_out_field_stream (uiout, "value", stb); - ui_out_text (uiout, "\n"); - result = PRINT_UNKNOWN; - break; - - case bp_access_watchpoint: - if (bs->old_val != NULL) - { - annotate_watchpoint (b->number); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); - mention (b); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nOld value = "); - watchpoint_value_print (bs->old_val, stb->stream); - ui_out_field_stream (uiout, "old", stb); - ui_out_text (uiout, "\nNew value = "); - } - else - { - mention (b); - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); - make_cleanup_ui_out_tuple_begin_end (uiout, "value"); - ui_out_text (uiout, "\nValue = "); - } - watchpoint_value_print (b->val, stb->stream); - ui_out_field_stream (uiout, "new", stb); - ui_out_text (uiout, "\n"); - result = PRINT_UNKNOWN; - break; - - /* Fall through, we don't deal with these types of breakpoints - here. */ - - case bp_finish: - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED)); - result = PRINT_UNKNOWN; - break; - - case bp_until: - if (ui_out_is_mi_like_p (uiout)) - ui_out_field_string - (uiout, "reason", - async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED)); - result = PRINT_UNKNOWN; - break; - - case bp_none: - case bp_longjmp: - case bp_longjmp_resume: - case bp_exception: - case bp_exception_resume: - case bp_step_resume: - case bp_watchpoint_scope: - case bp_call_dummy: - case bp_std_terminate: - case bp_tracepoint: - case bp_fast_tracepoint: - case bp_jit_event: - case bp_gnu_ifunc_resolver: - case bp_gnu_ifunc_resolver_return: - default: - result = PRINT_UNKNOWN; - break; - } - - do_cleanups (old_chain); - return result; -} - -/* Generic routine for printing messages indicating why we - stopped. The behavior of this function depends on the value - 'print_it' in the bpstat structure. Under some circumstances we - may decide not to print anything here and delegate the task to - normal_stop(). */ - -static enum print_stop_action -print_bp_stop_message (bpstat bs) -{ - switch (bs->print_it) - { - case print_it_noop: - /* Nothing should be printed for this bpstat entry. */ - return PRINT_UNKNOWN; - break; - - case print_it_done: - /* We still want to print the frame, but we already printed the - relevant messages. */ - return PRINT_SRC_AND_LOC; - break; - - case print_it_normal: - { - struct breakpoint *b = bs->breakpoint_at; - - /* bs->breakpoint_at can be NULL if it was a momentary breakpoint - which has since been deleted. */ - if (b == NULL) - return PRINT_UNKNOWN; - - /* Normal case. Call the breakpoint's print_it method, or - print_it_typical. */ - if (b->ops != NULL && b->ops->print_it != NULL) - return b->ops->print_it (b); - else - return print_it_typical (bs); - } - break; - - default: - internal_error (__FILE__, __LINE__, - _("print_bp_stop_message: unrecognized enum value")); - break; - } -} - -/* Print a message indicating what happened. This is called from - normal_stop(). The input to this routine is the head of the bpstat - list - a list of the eventpoints that caused this stop. This - routine calls the generic print routine for printing a message - about reasons for stopping. This will print (for example) the - "Breakpoint n," part of the output. The return value of this - routine is one of: - - PRINT_UNKNOWN: Means we printed nothing. - PRINT_SRC_AND_LOC: Means we printed something, and expect subsequent - code to print the location. An example is - "Breakpoint 1, " which should be followed by - the location. - PRINT_SRC_ONLY: Means we printed something, but there is no need - to also print the location part of the message. - An example is the catch/throw messages, which - don't require a location appended to the end. - PRINT_NOTHING: We have done some printing and we don't need any - further info to be printed. */ - -enum print_stop_action -bpstat_print (bpstat bs) -{ - int val; +enum print_stop_action +bpstat_print (bpstat bs, int kind) +{ + int val; /* Maybe another breakpoint in the chain caused us to stop. (Currently all watchpoints go on the bpstat whether hit or not. @@ -3601,6 +3512,18 @@ bpstat_print (bpstat bs) return val; } + /* If we had hit a shared library event breakpoint, + print_bp_stop_message would print out this message. If we hit an + OS-level shared library event, do the same thing. */ + if (kind == TARGET_WAITKIND_LOADED) + { + ui_out_text (current_uiout, _("Stopped due to shared library event\n")); + if (ui_out_is_mi_like_p (current_uiout)) + ui_out_field_string (current_uiout, "reason", + async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT)); + return PRINT_NOTHING; + } + /* We reached the end of the chain, or we got a null BS to start with and nothing was printed. */ return PRINT_UNKNOWN; @@ -3637,7 +3560,6 @@ bpstat_alloc (struct bp_location *bl, bpstat **bs_link_pointer) incref_bp_location (bl); /* If the condition is false, etc., don't do the commands. */ bs->commands = NULL; - bs->commands_left = NULL; bs->old_val = NULL; bs->print_it = print_it_normal; return bs; @@ -3659,7 +3581,11 @@ watchpoints_triggered (struct target_waitstatus *ws) as not triggered. */ ALL_BREAKPOINTS (b) if (is_hardware_watchpoint (b)) - b->watchpoint_triggered = watch_triggered_no; + { + struct watchpoint *w = (struct watchpoint *) b; + + w->watchpoint_triggered = watch_triggered_no; + } return 0; } @@ -3670,7 +3596,11 @@ watchpoints_triggered (struct target_waitstatus *ws) Mark all watchpoints as unknown. */ ALL_BREAKPOINTS (b) if (is_hardware_watchpoint (b)) - b->watchpoint_triggered = watch_triggered_unknown; + { + struct watchpoint *w = (struct watchpoint *) b; + + w->watchpoint_triggered = watch_triggered_unknown; + } return stopped_by_watchpoint; } @@ -3682,19 +3612,32 @@ watchpoints_triggered (struct target_waitstatus *ws) ALL_BREAKPOINTS (b) if (is_hardware_watchpoint (b)) { + struct watchpoint *w = (struct watchpoint *) b; struct bp_location *loc; - b->watchpoint_triggered = watch_triggered_no; + w->watchpoint_triggered = watch_triggered_no; for (loc = b->loc; loc; loc = loc->next) - /* Exact match not required. Within range is - sufficient. */ - if (target_watchpoint_addr_within_range (¤t_target, - addr, loc->address, - loc->length)) - { - b->watchpoint_triggered = watch_triggered_yes; - break; - } + { + if (is_masked_watchpoint (b)) + { + CORE_ADDR newaddr = addr & w->hw_wp_mask; + CORE_ADDR start = loc->address & w->hw_wp_mask; + + if (newaddr == start) + { + w->watchpoint_triggered = watch_triggered_yes; + break; + } + } + /* Exact match not required. Within range is sufficient. */ + else if (target_watchpoint_addr_within_range (¤t_target, + addr, loc->address, + loc->length)) + { + w->watchpoint_triggered = watch_triggered_yes; + break; + } + } } return 1; @@ -3724,15 +3667,13 @@ static int watchpoint_check (void *p) { bpstat bs = (bpstat) p; - struct breakpoint *b; + struct watchpoint *b; struct frame_info *fr; int within_current_scope; /* BS is built from an existing struct breakpoint. */ gdb_assert (bs->breakpoint_at != NULL); - b = bs->breakpoint_at; - - gdb_assert (is_watchpoint (b)); + b = (struct watchpoint *) bs->breakpoint_at; /* If this is a local watchpoint, we only want to check if the watchpoint frame is in scope if the current thread is the thread @@ -3791,9 +3732,16 @@ watchpoint_check (void *p) might be in the middle of evaluating a function call. */ int pc = 0; - struct value *mark = value_mark (); + struct value *mark; struct value *new_val; + if (is_masked_watchpoint (&b->base)) + /* Since we don't know the exact trigger address (from + stopped_data_address), just tell the user we've triggered + a mask watchpoint. */ + return WP_VALUE_CHANGED; + + mark = value_mark (); fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL); /* We use value_equal_contents instead of value_equal because @@ -3822,6 +3770,8 @@ watchpoint_check (void *p) } else { + struct ui_out *uiout = current_uiout; + /* This seems like the only logical thing to do because if we temporarily ignored the watchpoint, then when we reenter the block in which it is valid it contains @@ -3830,19 +3780,22 @@ watchpoint_check (void *p) So we can't even detect the first assignment to it and watch after that (since the garbage may or may not equal the first value assigned). */ - /* We print all the stop information in print_it_typical(), but - in this case, by the time we call print_it_typical() this bp - will be deleted already. So we have no choice but print the - information here. */ + /* We print all the stop information in + breakpoint_ops->print_it, but in this case, by the time we + call breakpoint_ops->print_it this bp will be deleted + already. So we have no choice but print the information + here. */ if (ui_out_is_mi_like_p (uiout)) ui_out_field_string (uiout, "reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_SCOPE)); ui_out_text (uiout, "\nWatchpoint "); - ui_out_field_int (uiout, "wpnum", b->number); + ui_out_field_int (uiout, "wpnum", b->base.number); ui_out_text (uiout, " deleted because the program has left the block in\n\ which its expression is valid.\n"); + /* Make sure the watchpoint's commands aren't executed. */ + decref_counted_command_line (&b->base.commands); watchpoint_del_at_next_stop (b); return WP_DELETED; @@ -3850,82 +3803,40 @@ which its expression is valid.\n"); } /* Return true if it looks like target has stopped due to hitting - breakpoint location BL. This function does not check if we - should stop, only if BL explains the stop. */ + breakpoint location BL. This function does not check if we should + stop, only if BL explains the stop. */ + static int bpstat_check_location (const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr) { struct breakpoint *b = bl->owner; - /* BL is from existing struct breakpoint. */ + /* BL is from an existing breakpoint. */ gdb_assert (b != NULL); - if (b->ops && b->ops->breakpoint_hit) - return b->ops->breakpoint_hit (bl, aspace, bp_addr); - - /* By definition, the inferior does not report stops at - tracepoints. */ - if (is_tracepoint (b)) - return 0; - - if (!is_watchpoint (b) - && b->type != bp_hardware_breakpoint - && b->type != bp_catchpoint) /* a non-watchpoint bp */ - { - if (!breakpoint_address_match (bl->pspace->aspace, bl->address, - aspace, bp_addr)) - return 0; - if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - return 0; - } - - /* Continuable hardware watchpoints are treated as non-existent if the - reason we stopped wasn't a hardware watchpoint (we didn't stop on - some data address). Otherwise gdb won't stop on a break instruction - in the code (not from a breakpoint) when a hardware watchpoint has - been defined. Also skip watchpoints which we know did not trigger - (did not match the data address). */ - - if (is_hardware_watchpoint (b) - && b->watchpoint_triggered == watch_triggered_no) - return 0; - - if (b->type == bp_hardware_breakpoint) - { - if (bl->address != bp_addr) - return 0; - if (overlay_debugging /* unmapped overlay section */ - && section_is_overlay (bl->section) - && !section_is_mapped (bl->section)) - return 0; - } - - return 1; + return b->ops->breakpoint_hit (bl, aspace, bp_addr); } -/* If BS refers to a watchpoint, determine if the watched values - has actually changed, and we should stop. If not, set BS->stop - to 0. */ +/* Determine if the watched values have actually changed, and we + should stop. If not, set BS->stop to 0. */ + static void bpstat_check_watchpoint (bpstat bs) { const struct bp_location *bl; - struct breakpoint *b; + struct watchpoint *b; /* BS is built for existing struct breakpoint. */ bl = bs->bp_location_at; gdb_assert (bl != NULL); - b = bs->breakpoint_at; + b = (struct watchpoint *) bs->breakpoint_at; gdb_assert (b != NULL); - if (is_watchpoint (b)) { int must_check_value = 0; - if (b->type == bp_watchpoint) + if (b->base.type == bp_watchpoint) /* For a software watchpoint, we must always check the watched value. */ must_check_value = 1; @@ -3935,18 +3846,18 @@ bpstat_check_watchpoint (bpstat bs) this watchpoint. */ must_check_value = 1; else if (b->watchpoint_triggered == watch_triggered_unknown - && b->type == bp_hardware_watchpoint) + && b->base.type == bp_hardware_watchpoint) /* We were stopped by a hardware watchpoint, but the target could not report the data address. We must check the watchpoint's value. Access and read watchpoints are out of luck; without a data address, we can't figure it out. */ must_check_value = 1; - + if (must_check_value) { char *message = xstrprintf ("Error evaluating expression for watchpoint %d\n", - b->number); + b->base.number); struct cleanup *cleanups = make_cleanup (xfree, message); int e = catch_errors (watchpoint_check, bs, message, RETURN_MASK_ALL); @@ -3963,7 +3874,7 @@ bpstat_check_watchpoint (bpstat bs) bs->stop = 0; break; case WP_VALUE_CHANGED: - if (b->type == bp_read_watchpoint) + if (b->base.type == bp_read_watchpoint) { /* There are two cases to consider here: @@ -4006,13 +3917,18 @@ bpstat_check_watchpoint (bpstat bs) struct breakpoint *other_b; ALL_BREAKPOINTS (other_b) - if ((other_b->type == bp_hardware_watchpoint - || other_b->type == bp_access_watchpoint) - && (other_b->watchpoint_triggered - == watch_triggered_yes)) + if (other_b->type == bp_hardware_watchpoint + || other_b->type == bp_access_watchpoint) { - other_write_watchpoint = 1; - break; + struct watchpoint *other_w = + (struct watchpoint *) other_b; + + if (other_w->watchpoint_triggered + == watch_triggered_yes) + { + other_write_watchpoint = 1; + break; + } } } @@ -4029,8 +3945,8 @@ bpstat_check_watchpoint (bpstat bs) } break; case WP_VALUE_NOT_CHANGED: - if (b->type == bp_hardware_watchpoint - || b->type == bp_watchpoint) + if (b->base.type == bp_hardware_watchpoint + || b->base.type == bp_watchpoint) { /* Don't stop: write watchpoints shouldn't fire if the value hasn't changed. */ @@ -4043,7 +3959,7 @@ bpstat_check_watchpoint (bpstat bs) /* Can't happen. */ case 0: /* Error from catch_errors. */ - printf_filtered (_("Watchpoint %d deleted.\n"), b->number); + printf_filtered (_("Watchpoint %d deleted.\n"), b->base.number); watchpoint_del_at_next_stop (b); /* We've already printed what needs to be printed. */ bs->print_it = print_it_done; @@ -4094,13 +4010,18 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) bs->stop = gdbpy_should_stop (b->py_bp_object); if (is_watchpoint (b)) - cond = b->cond_exp; + { + struct watchpoint *w = (struct watchpoint *) b; + + cond = w->cond_exp; + } else cond = bl->cond; if (cond && b->disposition != disp_del_at_next_stop) { int within_current_scope = 1; + struct watchpoint * w; /* We use value_mark and value_free_to_mark because it could be a long time before we return to the command level and @@ -4109,13 +4030,18 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) function call. */ struct value *mark = value_mark (); + if (is_watchpoint (b)) + w = (struct watchpoint *) b; + else + w = NULL; + /* Need to select the frame, with all that implies so that the conditions will have the right context. Because we use the frame, we will not see an inlined function's variables when we arrive at a breakpoint at the start of the inlined function; the current frame will be the call site. */ - if (!is_watchpoint (b) || b->cond_exp_valid_block == NULL) + if (w == NULL || w->cond_exp_valid_block == NULL) select_frame (get_current_frame ()); else { @@ -4135,7 +4061,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) the innermost frame that's executing where it makes sense to evaluate the condition. It seems intuitive. */ - frame = block_innermost_frame (b->cond_exp_valid_block); + frame = block_innermost_frame (w->cond_exp_valid_block); if (frame != NULL) select_frame (frame); else @@ -4173,6 +4099,7 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) bs->stop = 0; /* Increase the hit count even though we don't stop. */ ++(b->hit_count); + observer_notify_breakpoint_modified (b); } } } @@ -4256,7 +4183,11 @@ bpstat_stop_status (struct address_space *aspace, out-of-scope event. We'll get to the watchpoint next iteration. */ if (b->type == bp_watchpoint_scope && b->related_breakpoint != b) - b->related_breakpoint->watchpoint_triggered = watch_triggered_yes; + { + struct watchpoint *w = (struct watchpoint *) b->related_breakpoint; + + w->watchpoint_triggered = watch_triggered_yes; + } } } @@ -4283,24 +4214,16 @@ bpstat_stop_status (struct address_space *aspace, if (!bs->stop) continue; - bpstat_check_watchpoint (bs); - if (!bs->stop) - continue; - b = bs->breakpoint_at; - - if (b->type == bp_thread_event || b->type == bp_overlay_event - || b->type == bp_longjmp_master - || b->type == bp_std_terminate_master - || b->type == bp_exception_master) - /* We do not stop for these. */ - bs->stop = 0; - else - bpstat_check_breakpoint_conditions (bs, ptid); + b->ops->check_status (bs); + if (bs->stop) + { + bpstat_check_breakpoint_conditions (bs, ptid); if (bs->stop) { ++(b->hit_count); + observer_notify_breakpoint_modified (b); /* We will stop here. */ if (b->disposition == disp_disable) @@ -4313,21 +4236,15 @@ bpstat_stop_status (struct address_space *aspace, bs->print = 0; bs->commands = b->commands; incref_counted_command_line (bs->commands); - bs->commands_left = bs->commands ? bs->commands->commands : NULL; - if (bs->commands_left - && (strcmp ("silent", bs->commands_left->line) == 0 - || (xdb_commands - && strcmp ("Q", - bs->commands_left->line) == 0))) - { - bs->commands_left = bs->commands_left->next; - bs->print = 0; - } + if (command_line_is_silent (bs->commands + ? bs->commands->commands : NULL)) + bs->print = 0; } - /* Print nothing for this entry if we dont stop or dont print. */ + /* Print nothing for this entry if we don't stop or don't print. */ if (bs->stop == 0 || bs->print == 0) bs->print_it = print_it_noop; + } } /* If we aren't stopping, the value of some hardware watchpoint may @@ -4341,7 +4258,9 @@ bpstat_stop_status (struct address_space *aspace, && bs->breakpoint_at && is_hardware_watchpoint (bs->breakpoint_at)) { - update_watchpoint (bs->breakpoint_at, 0 /* don't reparse. */); + struct watchpoint *w = (struct watchpoint *) bs->breakpoint_at; + + update_watchpoint (w, 0 /* don't reparse. */); need_remove_insert = 1; } @@ -4403,8 +4322,6 @@ bpstat_what (bpstat bs_head) breakpoint which has since been deleted. */ bptype = bp_none; } - else if (bs->breakpoint_at == NULL) - bptype = bp_none; else bptype = bs->breakpoint_at->type; @@ -4462,6 +4379,15 @@ bpstat_what (bpstat bs_head) this_action = BPSTAT_WHAT_SINGLE; } break; + case bp_hp_step_resume: + if (bs->stop) + this_action = BPSTAT_WHAT_HP_STEP_RESUME; + else + { + /* It is for the wrong frame. */ + this_action = BPSTAT_WHAT_SINGLE; + } + break; case bp_watchpoint_scope: case bp_thread_event: case bp_overlay_event: @@ -4652,6 +4578,7 @@ static void print_breakpoint_location (struct breakpoint *b, struct bp_location *loc) { + struct ui_out *uiout = current_uiout; struct cleanup *old_chain = save_current_program_space (); if (loc != NULL && loc->shlib_disabled) @@ -4662,7 +4589,7 @@ print_breakpoint_location (struct breakpoint *b, if (b->display_canonical) ui_out_field_string (uiout, "what", b->addr_string); - else if (b->source_file && loc) + else if (loc && loc->source_file) { struct symbol *sym = find_pc_sect_function (loc->address, loc->section); @@ -4675,7 +4602,7 @@ print_breakpoint_location (struct breakpoint *b, ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what")); ui_out_text (uiout, "at "); } - ui_out_field_string (uiout, "file", b->source_file); + ui_out_field_string (uiout, "file", loc->source_file); ui_out_text (uiout, ":"); if (ui_out_is_mi_like_p (uiout)) @@ -4687,7 +4614,7 @@ print_breakpoint_location (struct breakpoint *b, ui_out_field_string (uiout, "fullname", fullname); } - ui_out_field_int (uiout, "line", b->line_number); + ui_out_field_int (uiout, "line", loc->line_number); } else if (loc) { @@ -4730,6 +4657,7 @@ bptype_string (enum bptype type) {bp_exception, "exception"}, {bp_exception_resume, "exception resume"}, {bp_step_resume, "step resume"}, + {bp_hp_step_resume, "high-priority step resume"}, {bp_watchpoint_scope, "watchpoint scope"}, {bp_call_dummy, "call dummy"}, {bp_std_terminate, "std::terminate"}, @@ -4768,8 +4696,8 @@ print_one_breakpoint_location (struct breakpoint *b, { struct command_line *l; static char bpenables[] = "nynny"; - struct cleanup *bkpt_chain; + struct ui_out *uiout = current_uiout; int header_of_multiple = 0; int part_of_multiple = (loc != NULL); struct value_print_options opts; @@ -4787,7 +4715,6 @@ print_one_breakpoint_location (struct breakpoint *b, loc = b->loc; annotate_record (); - bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt"); /* 1 */ annotate_field (0); @@ -4849,13 +4776,17 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_hardware_watchpoint: case bp_read_watchpoint: case bp_access_watchpoint: - /* Field 4, the address, is omitted (which makes the columns - not line up too nicely with the headers, but the effect - is relatively readable). */ - if (opts.addressprint) - ui_out_field_skip (uiout, "addr"); - annotate_field (5); - ui_out_field_string (uiout, "what", b->exp_string); + { + struct watchpoint *w = (struct watchpoint *) b; + + /* Field 4, the address, is omitted (which makes the columns + not line up too nicely with the headers, but the effect + is relatively readable). */ + if (opts.addressprint) + ui_out_field_skip (uiout, "addr"); + annotate_field (5); + ui_out_field_string (uiout, "what", w->exp_string); + } break; case bp_breakpoint: @@ -4867,6 +4798,7 @@ print_one_breakpoint_location (struct breakpoint *b, case bp_exception: case bp_exception_resume: case bp_step_resume: + case bp_hp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: case bp_std_terminate: @@ -4951,35 +4883,22 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_text (uiout, "\n"); - if (!part_of_multiple && b->ops && b->ops->print_one_detail) + if (!part_of_multiple) b->ops->print_one_detail (b, uiout); - if (!part_of_multiple && b->static_trace_marker_id) - { - gdb_assert (b->type == bp_static_tracepoint); - - ui_out_text (uiout, "\tmarker id is "); - ui_out_field_string (uiout, "static-tracepoint-marker-string-id", - b->static_trace_marker_id); - ui_out_text (uiout, "\n"); - } - if (part_of_multiple && frame_id_p (b->frame_id)) { annotate_field (6); ui_out_text (uiout, "\tstop only in stack frame at "); - /* FIXME: cagney/2002-12-01: Shouldn't be poeking around inside + /* FIXME: cagney/2002-12-01: Shouldn't be poking around inside the frame ID. */ ui_out_field_core_addr (uiout, "frame", b->gdbarch, b->frame_id.stack_addr); ui_out_text (uiout, "\n"); } - if (!part_of_multiple && b->cond_string && !ada_exception_catchpoint_p (b)) + if (!part_of_multiple && b->cond_string) { - /* We do not print the condition for Ada exception catchpoints - because the condition is an internal implementation detail - that we do not want to expose to the user. */ annotate_field (7); if (is_tracepoint (b)) ui_out_text (uiout, "\ttrace only if "); @@ -5002,6 +4921,8 @@ print_one_breakpoint_location (struct breakpoint *b, /* FIXME should make an annotation for this. */ if (ep_is_catchpoint (b)) ui_out_text (uiout, "\tcatchpoint"); + else if (is_tracepoint (b)) + ui_out_text (uiout, "\ttracepoint"); else ui_out_text (uiout, "\tbreakpoint"); ui_out_text (uiout, " already hit "); @@ -5026,6 +4947,18 @@ print_one_breakpoint_location (struct breakpoint *b, ui_out_text (uiout, " hits\n"); } + if (!part_of_multiple && is_tracepoint (b)) + { + struct tracepoint *tp = (struct tracepoint *) b; + + if (tp->traceframe_usage) + { + ui_out_text (uiout, "\ttrace buffer usage "); + ui_out_field_int (uiout, "traceframe-usage", tp->traceframe_usage); + ui_out_text (uiout, " bytes\n"); + } + } + l = b->commands ? b->commands->commands : NULL; if (!part_of_multiple && l) { @@ -5037,23 +4970,30 @@ print_one_breakpoint_location (struct breakpoint *b, do_cleanups (script_chain); } - if (!part_of_multiple && b->pass_count) + if (is_tracepoint (b)) { - annotate_field (10); - ui_out_text (uiout, "\tpass count "); - ui_out_field_int (uiout, "pass", b->pass_count); - ui_out_text (uiout, " \n"); + struct tracepoint *t = (struct tracepoint *) b; + + if (!part_of_multiple && t->pass_count) + { + annotate_field (10); + ui_out_text (uiout, "\tpass count "); + ui_out_field_int (uiout, "pass", t->pass_count); + ui_out_text (uiout, " \n"); + } } if (ui_out_is_mi_like_p (uiout) && !part_of_multiple) { - if (b->addr_string) + if (is_watchpoint (b)) + { + struct watchpoint *w = (struct watchpoint *) b; + + ui_out_field_string (uiout, "original-location", w->exp_string); + } + else if (b->addr_string) ui_out_field_string (uiout, "original-location", b->addr_string); - else if (b->exp_string) - ui_out_field_string (uiout, "original-location", b->exp_string); } - - do_cleanups (bkpt_chain); } static void @@ -5061,7 +5001,13 @@ print_one_breakpoint (struct breakpoint *b, struct bp_location **last_loc, int allflag) { + struct cleanup *bkpt_chain; + struct ui_out *uiout = current_uiout; + + bkpt_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "bkpt"); + print_one_breakpoint_location (b, NULL, 0, last_loc, allflag); + do_cleanups (bkpt_chain); /* If this breakpoint has custom print function, it's already printed. Otherwise, print individual @@ -5077,13 +5023,18 @@ print_one_breakpoint (struct breakpoint *b, internally, that's not a property exposed to user. */ if (b->loc && !is_hardware_watchpoint (b) - && (b->loc->next || !b->loc->enabled) - && !ui_out_is_mi_like_p (uiout)) + && (b->loc->next || !b->loc->enabled)) { struct bp_location *loc; int n = 1; + for (loc = b->loc; loc; loc = loc->next, ++n) - print_one_breakpoint_location (b, loc, n, last_loc, allflag); + { + struct cleanup *inner2 = + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + print_one_breakpoint_location (b, loc, n, last_loc, allflag); + do_cleanups (inner2); + } } } } @@ -5150,27 +5101,13 @@ gdb_breakpoint_query (struct ui_out *uiout, int bnum, return GDB_RC_OK; } -/* Return non-zero if B is user settable (breakpoints, watchpoints, - catchpoints, et.al.). */ - -static int -user_settable_breakpoint (const struct breakpoint *b) -{ - return (b->type == bp_breakpoint - || b->type == bp_catchpoint - || b->type == bp_hardware_breakpoint - || is_tracepoint (b) - || is_watchpoint (b) - || b->type == bp_gnu_ifunc_resolver); -} - -/* Return true if this breakpoint was set by the user, false if it is - internal or momentary. */ +/* Return true if this breakpoint was set by the user, false if it is + internal or momentary. */ int user_breakpoint_p (struct breakpoint *b) { - return user_settable_breakpoint (b) && b->number > 0; + return b->number > 0; } /* Print information on user settable breakpoint (watchpoint, etc) @@ -5191,6 +5128,7 @@ breakpoint_1 (char *args, int allflag, struct value_print_options opts; int print_address_bits = 0; int print_type_col_width = 14; + struct ui_out *uiout = current_uiout; get_user_print_options (&opts); @@ -5337,6 +5275,8 @@ breakpoint_1 (char *args, int allflag, static void default_collect_info (void) { + struct ui_out *uiout = current_uiout; + /* If it has no value (which is frequently the case), say nothing; a message like "No default-collect." gets in user's face when it's not wanted. */ @@ -5362,6 +5302,7 @@ static void watchpoints_info (char *args, int from_tty) { int num_printed = breakpoint_1 (args, 0, is_watchpoint); + struct ui_out *uiout = current_uiout; if (num_printed == 0) { @@ -5397,7 +5338,7 @@ breakpoint_has_pc (struct breakpoint *b, return 0; } -/* Print a message describing any breakpoints set at PC. This +/* Print a message describing any user-breakpoints set at PC. This concerns with logical breakpoints, so we match program spaces, not address spaces. */ @@ -5410,7 +5351,8 @@ describe_other_breakpoints (struct gdbarch *gdbarch, struct breakpoint *b; ALL_BREAKPOINTS (b) - others += breakpoint_has_pc (b, pspace, pc, section); + others += (user_breakpoint_p (b) + && breakpoint_has_pc (b, pspace, pc, section)); if (others > 0) { if (others == 1) @@ -5418,7 +5360,7 @@ describe_other_breakpoints (struct gdbarch *gdbarch, else /* if (others == ???) */ printf_filtered (_("Note: breakpoints ")); ALL_BREAKPOINTS (b) - if (breakpoint_has_pc (b, pspace, pc, section)) + if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section)) { others--; printf_filtered ("%d", b->number); @@ -5428,8 +5370,7 @@ describe_other_breakpoints (struct gdbarch *gdbarch, printf_filtered (" (thread %d)", b->thread); printf_filtered ("%s%s ", ((b->enable_state == bp_disabled - || b->enable_state == bp_call_disabled - || b->enable_state == bp_startup_disabled) + || b->enable_state == bp_call_disabled) ? " (disabled)" : b->enable_state == bp_permanent ? " (permanent)" @@ -5443,20 +5384,6 @@ describe_other_breakpoints (struct gdbarch *gdbarch, } } -/* Set the default place to put a breakpoint - for the `break' command with no arguments. */ - -void -set_default_breakpoint (int valid, struct program_space *pspace, - CORE_ADDR addr, struct symtab *symtab, - int line) -{ - default_breakpoint_valid = valid; - default_breakpoint_pspace = pspace; - default_breakpoint_address = addr; - default_breakpoint_symtab = symtab; - default_breakpoint_line = line; -} /* Return true iff it is meaningful to use the address member of BPT. For some breakpoint types, the address member is irrelevant @@ -5488,9 +5415,12 @@ static int watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2) { - /* Both of them must not be in moribund_locations. */ - gdb_assert (loc1->owner != NULL); - gdb_assert (loc2->owner != NULL); + struct watchpoint *w1 = (struct watchpoint *) loc1->owner; + struct watchpoint *w2 = (struct watchpoint *) loc2->owner; + + /* Both of them must exist. */ + gdb_assert (w1 != NULL); + gdb_assert (w2 != NULL); /* If the target can evaluate the condition expression in hardware, then we we need to insert both watchpoints even if they are at @@ -5498,16 +5428,16 @@ watchpoint_locations_match (struct bp_location *loc1, the condition of whichever watchpoint was inserted evaluates to true, not giving a chance for GDB to check the condition of the other watchpoint. */ - if ((loc1->owner->cond_exp + if ((w1->cond_exp && target_can_accel_watchpoint_condition (loc1->address, loc1->length, loc1->watchpoint_type, - loc1->owner->cond_exp)) - || (loc2->owner->cond_exp + w1->cond_exp)) + || (w2->cond_exp && target_can_accel_watchpoint_condition (loc2->address, loc2->length, loc2->watchpoint_type, - loc2->owner->cond_exp))) + w2->cond_exp))) return 0; /* Note that this checks the owner's type, not the location's. In @@ -5569,6 +5499,23 @@ breakpoint_location_address_match (struct bp_location *bl, aspace, addr))); } +/* If LOC1 and LOC2's owners are not tracepoints, returns false directly. + Then, if LOC1 and LOC2 represent the same tracepoint location, returns + true, otherwise returns false. */ + +static int +tracepoint_locations_match (struct bp_location *loc1, + struct bp_location *loc2) +{ + if (is_tracepoint (loc1->owner) && is_tracepoint (loc2->owner)) + /* Since tracepoint locations are never duplicated with others', tracepoint + locations at the same address of different tracepoints are regarded as + different locations. */ + return (loc1->address == loc2->address && loc1->owner == loc2->owner); + else + return 0; +} + /* Assuming LOC1 and LOC2's types' have meaningful target addresses (breakpoint_address_is_meaningful), returns true if LOC1 and LOC2 represent the same location. */ @@ -5590,6 +5537,8 @@ breakpoint_locations_match (struct bp_location *loc1, return 0; else if (hw_point1) return watchpoint_locations_match (loc1, loc2); + else if (is_tracepoint (loc1->owner) || is_tracepoint (loc2->owner)) + return tracepoint_locations_match (loc1, loc2); else /* We compare bp_location.length in order to cover ranged breakpoints. */ return (breakpoint_address_match (loc1->pspace->aspace, loc1->address, @@ -5657,22 +5606,21 @@ adjust_breakpoint_address (struct gdbarch *gdbarch, } } -/* Allocate a struct bp_location. */ - -static struct bp_location * -allocate_bp_location (struct breakpoint *bpt) +void +init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops, + struct breakpoint *owner) { - struct bp_location *loc; - - loc = xmalloc (sizeof (struct bp_location)); memset (loc, 0, sizeof (*loc)); - loc->owner = bpt; + gdb_assert (ops != NULL); + + loc->ops = ops; + loc->owner = owner; loc->cond = NULL; loc->shlib_disabled = 0; loc->enabled = 1; - switch (bpt->type) + switch (owner->type) { case bp_breakpoint: case bp_until: @@ -5682,6 +5630,7 @@ allocate_bp_location (struct breakpoint *bpt) case bp_exception: case bp_exception_resume: case bp_step_resume: + case bp_hp_step_resume: case bp_watchpoint_scope: case bp_call_dummy: case bp_std_terminate: @@ -5716,18 +5665,20 @@ allocate_bp_location (struct breakpoint *bpt) } loc->refc = 1; - return loc; +} + +/* Allocate a struct bp_location. */ + +static struct bp_location * +allocate_bp_location (struct breakpoint *bpt) +{ + return bpt->ops->allocate_location (bpt); } static void free_bp_location (struct bp_location *loc) { - if (loc->cond) - xfree (loc->cond); - - if (loc->function_name) - xfree (loc->function_name); - + loc->ops->dtor (loc); xfree (loc); } @@ -5752,20 +5703,40 @@ decref_bp_location (struct bp_location **blp) *blp = NULL; } -/* Helper to set_raw_breakpoint below. Creates a breakpoint that has - type BPTYPE and has no locations as yet. */ -/* This function is used in gdbtk sources and thus can not be made - static. */ +/* Add breakpoint B at the end of the global breakpoint chain. */ -static struct breakpoint * -set_raw_breakpoint_without_location (struct gdbarch *gdbarch, - enum bptype bptype) +static void +add_to_breakpoint_chain (struct breakpoint *b) { - struct breakpoint *b, *b1; + struct breakpoint *b1; + + /* Add this breakpoint to the end of the chain so that a list of + breakpoints will come out in order of increasing numbers. */ - b = (struct breakpoint *) xmalloc (sizeof (struct breakpoint)); + b1 = breakpoint_chain; + if (b1 == 0) + breakpoint_chain = b; + else + { + while (b1->next) + b1 = b1->next; + b1->next = b; + } +} + +/* Initializes breakpoint B with type BPTYPE and no locations yet. */ + +static void +init_raw_breakpoint_without_location (struct breakpoint *b, + struct gdbarch *gdbarch, + enum bptype bptype, + const struct breakpoint_ops *ops) +{ memset (b, 0, sizeof (*b)); + gdb_assert (ops != NULL); + + b->ops = ops; b->type = bptype; b->gdbarch = gdbarch; b->language = current_language->la_language; @@ -5777,26 +5748,23 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, b->ignore_count = 0; b->commands = NULL; b->frame_id = null_frame_id; - b->forked_inferior_pid = null_ptid; - b->exec_pathname = NULL; - b->syscalls_to_be_caught = NULL; - b->ops = NULL; b->condition_not_parsed = 0; b->py_bp_object = NULL; b->related_breakpoint = b; +} - /* Add this breakpoint to the end of the chain so that a list of - breakpoints will come out in order of increasing numbers. */ +/* Helper to set_raw_breakpoint below. Creates a breakpoint + that has type BPTYPE and has no locations as yet. */ - b1 = breakpoint_chain; - if (b1 == 0) - breakpoint_chain = b; - else - { - while (b1->next) - b1 = b1->next; - b1->next = b; - } +static struct breakpoint * +set_raw_breakpoint_without_location (struct gdbarch *gdbarch, + enum bptype bptype, + const struct breakpoint_ops *ops) +{ + struct breakpoint *b = XNEW (struct breakpoint); + + init_raw_breakpoint_without_location (b, gdbarch, bptype, ops); + add_to_breakpoint_chain (b); return b; } @@ -5846,7 +5814,7 @@ set_breakpoint_location_function (struct bp_location *loc, int explicit_loc) } /* Attempt to determine architecture of location identified by SAL. */ -static struct gdbarch * +struct gdbarch * get_sal_arch (struct symtab_and_line sal) { if (sal.section) @@ -5857,6 +5825,35 @@ get_sal_arch (struct symtab_and_line sal) return NULL; } +/* Low level routine for partially initializing a breakpoint of type + BPTYPE. The newly created breakpoint's address, section, source + file name, and line number are provided by SAL. + + It is expected that the caller will complete the initialization of + the newly created breakpoint struct as well as output any status + information regarding the creation of a new breakpoint. */ + +static void +init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch, + struct symtab_and_line sal, enum bptype bptype, + const struct breakpoint_ops *ops) +{ + init_raw_breakpoint_without_location (b, gdbarch, bptype, ops); + + add_location_to_breakpoint (b, &sal); + + if (bptype != bp_catchpoint) + gdb_assert (sal.pspace != NULL); + + /* Store the program space that was used to set the breakpoint, + except for ordinary breakpoints, which are independent of the + program space. */ + if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint) + b->pspace = sal.pspace; + + breakpoints_changed (); +} + /* set_raw_breakpoint is a low level routine for allocating and partially initializing a breakpoint of type BPTYPE. The newly created breakpoint's address, section, source file name, and line @@ -5874,51 +5871,13 @@ get_sal_arch (struct symtab_and_line sal) struct breakpoint * set_raw_breakpoint (struct gdbarch *gdbarch, - struct symtab_and_line sal, enum bptype bptype) + struct symtab_and_line sal, enum bptype bptype, + const struct breakpoint_ops *ops) { - struct breakpoint *b = set_raw_breakpoint_without_location (gdbarch, - bptype); - CORE_ADDR adjusted_address; - struct gdbarch *loc_gdbarch; - - loc_gdbarch = get_sal_arch (sal); - if (!loc_gdbarch) - loc_gdbarch = b->gdbarch; - - if (bptype != bp_catchpoint) - gdb_assert (sal.pspace != NULL); - - /* Adjust the breakpoint's address prior to allocating a location. - Once we call allocate_bp_location(), that mostly uninitialized - location will be placed on the location chain. Adjustment of the - breakpoint may cause target_read_memory() to be called and we do - not want its scan of the location chain to find a breakpoint and - location that's only been partially initialized. */ - adjusted_address = adjust_breakpoint_address (loc_gdbarch, - sal.pc, b->type); - - b->loc = allocate_bp_location (b); - b->loc->gdbarch = loc_gdbarch; - b->loc->requested_address = sal.pc; - b->loc->address = adjusted_address; - b->loc->pspace = sal.pspace; - - /* Store the program space that was used to set the breakpoint, for - breakpoint resetting. */ - b->pspace = sal.pspace; - - if (sal.symtab == NULL) - b->source_file = NULL; - else - b->source_file = xstrdup (sal.symtab->filename); - b->loc->section = sal.section; - b->line_number = sal.line; - - set_breakpoint_location_function (b->loc, - sal.explicit_pc || sal.explicit_line); - - breakpoints_changed (); + struct breakpoint *b = XNEW (struct breakpoint); + init_raw_breakpoint (b, gdbarch, sal, bptype, ops); + add_to_breakpoint_chain (b); return b; } @@ -5936,7 +5895,7 @@ make_breakpoint_permanent (struct breakpoint *b) code. Mark all locations as inserted. For now, make_breakpoint_permanent is called in just one place, so it's hard to say if it's reasonable to have permanent breakpoint with - multiple locations or not, but it's easy to implmement. */ + multiple locations or not, but it's easy to implement. */ for (bl = b->loc; bl; bl = bl->next) bl->inserted = 1; } @@ -5960,9 +5919,11 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame) && (b->type == bp_longjmp_master || b->type == bp_exception_master)) { - struct breakpoint *clone = clone_momentary_breakpoint (b); + enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception; + struct breakpoint *clone; - clone->type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception; + clone = momentary_breakpoint_from_master (b, type, + &momentary_breakpoint_ops); clone->thread = thread; } @@ -6022,8 +5983,8 @@ set_std_terminate_breakpoint (void) if (b->pspace == current_program_space && b->type == bp_std_terminate_master) { - struct breakpoint *clone = clone_momentary_breakpoint (b); - clone->type = bp_std_terminate; + momentary_breakpoint_from_master (b, bp_std_terminate, + &momentary_breakpoint_ops); } } @@ -6043,8 +6004,9 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) { struct breakpoint *b; - b = create_internal_breakpoint (gdbarch, address, bp_thread_event); - + b = create_internal_breakpoint (gdbarch, address, bp_thread_event, + &internal_breakpoint_ops); + b->enable_state = bp_enabled; /* addr_string has to be used or breakpoint_re_set will delete me. */ b->addr_string @@ -6066,13 +6028,6 @@ remove_thread_event_breakpoints (void) delete_breakpoint (b); } -struct captured_parse_breakpoint_args - { - char **arg_p; - struct symtabs_and_lines *sals_p; - struct linespec_result *canonical_p; - }; - struct lang_and_radix { enum language lang; @@ -6086,7 +6041,8 @@ create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) { struct breakpoint *b; - b = create_internal_breakpoint (gdbarch, address, bp_jit_event); + b = create_internal_breakpoint (gdbarch, address, bp_jit_event, + &internal_breakpoint_ops); update_global_location_list_nothrow (1); return b; } @@ -6120,7 +6076,8 @@ create_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address) { struct breakpoint *b; - b = create_internal_breakpoint (gdbarch, address, bp_shlib_event); + b = create_internal_breakpoint (gdbarch, address, bp_shlib_event, + &internal_breakpoint_ops); update_global_location_list_nothrow (1); return b; } @@ -6161,8 +6118,8 @@ disable_breakpoints_in_shlibs (void) } } -/* Disable any breakpoints that are in in an unloaded shared library. - Only apply to enabled breakpoints, disabled ones can just stay +/* Disable any breakpoints and tracepoints that are in an unloaded shared + library. Only apply to enabled breakpoints, disabled ones can just stay disabled. */ static void @@ -6184,13 +6141,14 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */ struct breakpoint *b = loc->owner; - if ((loc->loc_type == bp_loc_hardware_breakpoint - || loc->loc_type == bp_loc_software_breakpoint) - && solib->pspace == loc->pspace + if (solib->pspace == loc->pspace && !loc->shlib_disabled - && (b->type == bp_breakpoint - || b->type == bp_jit_event - || b->type == bp_hardware_breakpoint) + && (((b->type == bp_breakpoint + || b->type == bp_jit_event + || b->type == bp_hardware_breakpoint) + && (loc->loc_type == bp_loc_hardware_breakpoint + || loc->loc_type == bp_loc_software_breakpoint)) + || is_tracepoint (b)) && solib_contains_address_p (solib, loc->address)) { loc->shlib_disabled = 1; @@ -6198,6 +6156,10 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) succeeding so we must mark the breakpoint as not inserted to prevent future errors occurring in remove_breakpoints. */ loc->inserted = 0; + + /* This may cause duplicate notifications for the same breakpoint. */ + observer_notify_breakpoint_modified (b); + if (!disabled_shlib_breaks) { target_terminal_ours_for_output (); @@ -6212,6 +6174,23 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib) /* FORK & VFORK catchpoints. */ +/* An instance of this type is used to represent a fork or vfork + catchpoint. It includes a "struct breakpoint" as a kind of base + class; users downcast to "struct breakpoint *" when needed. A + breakpoint is really of this type iff its ops pointer points to + CATCH_FORK_BREAKPOINT_OPS. */ + +struct fork_catchpoint +{ + /* The base class. */ + struct breakpoint base; + + /* Process id of a child process whose forking triggered this + catchpoint. This field is only valid immediately after this + catchpoint has triggered. */ + ptid_t forked_inferior_pid; +}; + /* Implement the "insert" breakpoint_ops method for fork catchpoints. */ @@ -6237,18 +6216,36 @@ static int breakpoint_hit_catch_fork (const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_forked (inferior_ptid, &bl->owner->forked_inferior_pid); + struct fork_catchpoint *c = (struct fork_catchpoint *) bl->owner; + + return inferior_has_forked (inferior_ptid, &c->forked_inferior_pid); } /* Implement the "print_it" breakpoint_ops method for fork catchpoints. */ static enum print_stop_action -print_it_catch_fork (struct breakpoint *b) +print_it_catch_fork (bpstat bs) { + struct ui_out *uiout = current_uiout; + struct breakpoint *b = bs->breakpoint_at; + struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at; + annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (forked process %d), "), - b->number, ptid_get_pid (b->forked_inferior_pid)); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); + else + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_FORK)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, " (forked process "); + ui_out_field_int (uiout, "newpid", ptid_get_pid (c->forked_inferior_pid)); + ui_out_text (uiout, "), "); return PRINT_SRC_AND_LOC; } @@ -6258,7 +6255,9 @@ print_it_catch_fork (struct breakpoint *b) static void print_one_catch_fork (struct breakpoint *b, struct bp_location **last_loc) { + struct fork_catchpoint *c = (struct fork_catchpoint *) b; struct value_print_options opts; + struct ui_out *uiout = current_uiout; get_user_print_options (&opts); @@ -6269,11 +6268,11 @@ print_one_catch_fork (struct breakpoint *b, struct bp_location **last_loc) ui_out_field_skip (uiout, "addr"); annotate_field (5); ui_out_text (uiout, "fork"); - if (!ptid_equal (b->forked_inferior_pid, null_ptid)) + if (!ptid_equal (c->forked_inferior_pid, null_ptid)) { ui_out_text (uiout, ", process "); ui_out_field_int (uiout, "what", - ptid_get_pid (b->forked_inferior_pid)); + ptid_get_pid (c->forked_inferior_pid)); ui_out_spaces (uiout, 1); } } @@ -6294,22 +6293,12 @@ static void print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp) { fprintf_unfiltered (fp, "catch fork"); + print_recreate_thread (b, fp); } /* The breakpoint_ops structure to be used in fork catchpoints. */ -static struct breakpoint_ops catch_fork_breakpoint_ops = -{ - insert_catch_fork, - remove_catch_fork, - breakpoint_hit_catch_fork, - NULL, /* resources_needed */ - print_it_catch_fork, - print_one_catch_fork, - NULL, /* print_one_detail */ - print_mention_catch_fork, - print_recreate_catch_fork -}; +static struct breakpoint_ops catch_fork_breakpoint_ops; /* Implement the "insert" breakpoint_ops method for vfork catchpoints. */ @@ -6336,18 +6325,36 @@ static int breakpoint_hit_catch_vfork (const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_vforked (inferior_ptid, &bl->owner->forked_inferior_pid); + struct fork_catchpoint *c = (struct fork_catchpoint *) bl->owner; + + return inferior_has_vforked (inferior_ptid, &c->forked_inferior_pid); } /* Implement the "print_it" breakpoint_ops method for vfork catchpoints. */ static enum print_stop_action -print_it_catch_vfork (struct breakpoint *b) +print_it_catch_vfork (bpstat bs) { + struct ui_out *uiout = current_uiout; + struct breakpoint *b = bs->breakpoint_at; + struct fork_catchpoint *c = (struct fork_catchpoint *) b; + annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (vforked process %d), "), - b->number, ptid_get_pid (b->forked_inferior_pid)); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); + else + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_VFORK)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, " (vforked process "); + ui_out_field_int (uiout, "newpid", ptid_get_pid (c->forked_inferior_pid)); + ui_out_text (uiout, "), "); return PRINT_SRC_AND_LOC; } @@ -6357,7 +6364,9 @@ print_it_catch_vfork (struct breakpoint *b) static void print_one_catch_vfork (struct breakpoint *b, struct bp_location **last_loc) { + struct fork_catchpoint *c = (struct fork_catchpoint *) b; struct value_print_options opts; + struct ui_out *uiout = current_uiout; get_user_print_options (&opts); /* Field 4, the address, is omitted (which makes the columns not @@ -6367,11 +6376,11 @@ print_one_catch_vfork (struct breakpoint *b, struct bp_location **last_loc) ui_out_field_skip (uiout, "addr"); annotate_field (5); ui_out_text (uiout, "vfork"); - if (!ptid_equal (b->forked_inferior_pid, null_ptid)) + if (!ptid_equal (c->forked_inferior_pid, null_ptid)) { ui_out_text (uiout, ", process "); ui_out_field_int (uiout, "what", - ptid_get_pid (b->forked_inferior_pid)); + ptid_get_pid (c->forked_inferior_pid)); ui_out_spaces (uiout, 1); } } @@ -6392,40 +6401,62 @@ static void print_recreate_catch_vfork (struct breakpoint *b, struct ui_file *fp) { fprintf_unfiltered (fp, "catch vfork"); + print_recreate_thread (b, fp); } /* The breakpoint_ops structure to be used in vfork catchpoints. */ -static struct breakpoint_ops catch_vfork_breakpoint_ops = -{ - insert_catch_vfork, - remove_catch_vfork, - breakpoint_hit_catch_vfork, - NULL, /* resources_needed */ - print_it_catch_vfork, - print_one_catch_vfork, - NULL, /* print_one_detail */ - print_mention_catch_vfork, - print_recreate_catch_vfork +static struct breakpoint_ops catch_vfork_breakpoint_ops; + +/* An instance of this type is used to represent a syscall catchpoint. + It includes a "struct breakpoint" as a kind of base class; users + downcast to "struct breakpoint *" when needed. A breakpoint is + really of this type iff its ops pointer points to + CATCH_SYSCALL_BREAKPOINT_OPS. */ + +struct syscall_catchpoint +{ + /* The base class. */ + struct breakpoint base; + + /* Syscall numbers used for the 'catch syscall' feature. If no + syscall has been specified for filtering, its value is NULL. + Otherwise, it holds a list of all syscalls to be caught. The + list elements are allocated with xmalloc. */ + VEC(int) *syscalls_to_be_caught; }; +/* Implement the "dtor" breakpoint_ops method for syscall + catchpoints. */ + +static void +dtor_catch_syscall (struct breakpoint *b) +{ + struct syscall_catchpoint *c = (struct syscall_catchpoint *) b; + + VEC_free (int, c->syscalls_to_be_caught); + + base_breakpoint_ops.dtor (b); +} + /* Implement the "insert" breakpoint_ops method for syscall catchpoints. */ static int insert_catch_syscall (struct bp_location *bl) { + struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner; struct inferior *inf = current_inferior (); ++inf->total_syscalls_count; - if (!bl->owner->syscalls_to_be_caught) + if (!c->syscalls_to_be_caught) ++inf->any_syscall_count; else { int i, iter; for (i = 0; - VEC_iterate (int, bl->owner->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) { int elem; @@ -6460,17 +6491,18 @@ insert_catch_syscall (struct bp_location *bl) static int remove_catch_syscall (struct bp_location *bl) { + struct syscall_catchpoint *c = (struct syscall_catchpoint *) bl->owner; struct inferior *inf = current_inferior (); --inf->total_syscalls_count; - if (!bl->owner->syscalls_to_be_caught) + if (!c->syscalls_to_be_caught) --inf->any_syscall_count; else { int i, iter; for (i = 0; - VEC_iterate (int, bl->owner->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) { int elem; @@ -6501,18 +6533,19 @@ breakpoint_hit_catch_syscall (const struct bp_location *bl, breakpoint. If we are, then we must guarantee that the called syscall is the same syscall we are catching. */ int syscall_number = 0; - const struct breakpoint *b = bl->owner; + const struct syscall_catchpoint *c + = (const struct syscall_catchpoint *) bl->owner; if (!inferior_has_called_syscall (inferior_ptid, &syscall_number)) return 0; /* Now, checking if the syscall is the same. */ - if (b->syscalls_to_be_caught) + if (c->syscalls_to_be_caught) { int i, iter; for (i = 0; - VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) if (syscall_number == iter) break; @@ -6528,8 +6561,10 @@ breakpoint_hit_catch_syscall (const struct bp_location *bl, catchpoints. */ static enum print_stop_action -print_it_catch_syscall (struct breakpoint *b) +print_it_catch_syscall (bpstat bs) { + struct ui_out *uiout = current_uiout; + struct breakpoint *b = bs->breakpoint_at; /* These are needed because we want to know in which state a syscall is. It can be in the TARGET_WAITKIND_SYSCALL_ENTRY or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we @@ -6537,7 +6572,6 @@ print_it_catch_syscall (struct breakpoint *b) ptid_t ptid; struct target_waitstatus last; struct syscall s; - struct cleanup *old_chain; char *syscall_id; get_last_target_status (&ptid, &last); @@ -6546,21 +6580,31 @@ print_it_catch_syscall (struct breakpoint *b) annotate_catchpoint (b->number); - if (s.name == NULL) - syscall_id = xstrprintf ("%d", last.value.syscall_number); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); else - syscall_id = xstrprintf ("'%s'", s.name); - - old_chain = make_cleanup (xfree, syscall_id); + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY + ? EXEC_ASYNC_SYSCALL_ENTRY + : EXEC_ASYNC_SYSCALL_RETURN)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); if (last.kind == TARGET_WAITKIND_SYSCALL_ENTRY) - printf_filtered (_("\nCatchpoint %d (call to syscall %s), "), - b->number, syscall_id); - else if (last.kind == TARGET_WAITKIND_SYSCALL_RETURN) - printf_filtered (_("\nCatchpoint %d (returned from syscall %s), "), - b->number, syscall_id); + ui_out_text (uiout, " (call to syscall "); + else + ui_out_text (uiout, " (returned from syscall "); - do_cleanups (old_chain); + if (s.name == NULL || ui_out_is_mi_like_p (uiout)) + ui_out_field_int (uiout, "syscall-number", last.value.syscall_number); + if (s.name != NULL) + ui_out_field_string (uiout, "syscall-name", s.name); + + ui_out_text (uiout, "), "); return PRINT_SRC_AND_LOC; } @@ -6572,7 +6616,9 @@ static void print_one_catch_syscall (struct breakpoint *b, struct bp_location **last_loc) { + struct syscall_catchpoint *c = (struct syscall_catchpoint *) b; struct value_print_options opts; + struct ui_out *uiout = current_uiout; get_user_print_options (&opts); /* Field 4, the address, is omitted (which makes the columns not @@ -6582,19 +6628,19 @@ print_one_catch_syscall (struct breakpoint *b, ui_out_field_skip (uiout, "addr"); annotate_field (5); - if (b->syscalls_to_be_caught - && VEC_length (int, b->syscalls_to_be_caught) > 1) + if (c->syscalls_to_be_caught + && VEC_length (int, c->syscalls_to_be_caught) > 1) ui_out_text (uiout, "syscalls \""); else ui_out_text (uiout, "syscall \""); - if (b->syscalls_to_be_caught) + if (c->syscalls_to_be_caught) { int i, iter; char *text = xstrprintf ("%s", ""); for (i = 0; - VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) { char *x = text; @@ -6607,7 +6653,7 @@ print_one_catch_syscall (struct breakpoint *b, text = xstrprintf ("%s%d, ", text, iter); /* We have to xfree the last 'text' (now stored at 'x') - because xstrprintf dinamically allocates new space for it + because xstrprintf dynamically allocates new space for it on every call. */ xfree (x); } @@ -6626,17 +6672,19 @@ print_one_catch_syscall (struct breakpoint *b, static void print_mention_catch_syscall (struct breakpoint *b) { - if (b->syscalls_to_be_caught) + struct syscall_catchpoint *c = (struct syscall_catchpoint *) b; + + if (c->syscalls_to_be_caught) { int i, iter; - if (VEC_length (int, b->syscalls_to_be_caught) > 1) + if (VEC_length (int, c->syscalls_to_be_caught) > 1) printf_filtered (_("Catchpoint %d (syscalls"), b->number); else printf_filtered (_("Catchpoint %d (syscall"), b->number); for (i = 0; - VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) { struct syscall s; @@ -6660,14 +6708,16 @@ print_mention_catch_syscall (struct breakpoint *b) static void print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp) { + struct syscall_catchpoint *c = (struct syscall_catchpoint *) b; + fprintf_unfiltered (fp, "catch syscall"); - if (b->syscalls_to_be_caught) + if (c->syscalls_to_be_caught) { int i, iter; for (i = 0; - VEC_iterate (int, b->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) { struct syscall s; @@ -6679,22 +6729,12 @@ print_recreate_catch_syscall (struct breakpoint *b, struct ui_file *fp) fprintf_unfiltered (fp, " %d", s.number); } } + print_recreate_thread (b, fp); } /* The breakpoint_ops structure to be used in syscall catchpoints. */ -static struct breakpoint_ops catch_syscall_breakpoint_ops = -{ - insert_catch_syscall, - remove_catch_syscall, - breakpoint_hit_catch_syscall, - NULL, /* resources_needed */ - print_it_catch_syscall, - print_one_catch_syscall, - NULL, /* print_one_detail */ - print_mention_catch_syscall, - print_recreate_catch_syscall -}; +static struct breakpoint_ops catch_syscall_breakpoint_ops; /* Returns non-zero if 'b' is a syscall catchpoint. */ @@ -6704,76 +6744,87 @@ syscall_catchpoint_p (struct breakpoint *b) return (b->ops == &catch_syscall_breakpoint_ops); } -/* Create a new breakpoint of the bp_catchpoint kind and return it, - but does NOT mention it nor update the global location list. - This is useful if you need to fill more fields in the - struct breakpoint before calling mention. - - If TEMPFLAG is non-zero, then make the breakpoint temporary. - If COND_STRING is not NULL, then store it in the breakpoint. - OPS, if not NULL, is the breakpoint_ops structure associated - to the catchpoint. */ +/* Initialize a new breakpoint of the bp_catchpoint kind. If TEMPFLAG + is non-zero, then make the breakpoint temporary. If COND_STRING is + not NULL, then store it in the breakpoint. OPS, if not NULL, is + the breakpoint_ops structure associated to the catchpoint. */ -static struct breakpoint * -create_catchpoint_without_mention (struct gdbarch *gdbarch, int tempflag, - char *cond_string, - struct breakpoint_ops *ops) +static void +init_catchpoint (struct breakpoint *b, + struct gdbarch *gdbarch, int tempflag, + char *cond_string, + const struct breakpoint_ops *ops) { struct symtab_and_line sal; - struct breakpoint *b; init_sal (&sal); sal.pspace = current_program_space; - b = set_raw_breakpoint (gdbarch, sal, bp_catchpoint); - set_breakpoint_count (breakpoint_count + 1); - b->number = breakpoint_count; + init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops); b->cond_string = (cond_string == NULL) ? NULL : xstrdup (cond_string); - b->thread = -1; - b->addr_string = NULL; - b->enable_state = bp_enabled; b->disposition = tempflag ? disp_del : disp_donttouch; - b->ops = ops; - - return b; } -/* Create a new breakpoint of the bp_catchpoint kind and return it. - - If TEMPFLAG is non-zero, then make the breakpoint temporary. - If COND_STRING is not NULL, then store it in the breakpoint. - OPS, if not NULL, is the breakpoint_ops structure associated - to the catchpoint. */ - -static struct breakpoint * -create_catchpoint (struct gdbarch *gdbarch, int tempflag, - char *cond_string, struct breakpoint_ops *ops) +void +install_breakpoint (int internal, struct breakpoint *b, int update_gll) { - struct breakpoint *b = - create_catchpoint_without_mention (gdbarch, tempflag, cond_string, ops); - - mention (b); - update_global_location_list (1); + add_to_breakpoint_chain (b); + set_breakpoint_number (internal, b); + if (!internal) + mention (b); + observer_notify_breakpoint_created (b); - return b; + if (update_gll) + update_global_location_list (1); } static void create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch, int tempflag, char *cond_string, - struct breakpoint_ops *ops) + const struct breakpoint_ops *ops) { - struct breakpoint *b - = create_catchpoint (gdbarch, tempflag, cond_string, ops); + struct fork_catchpoint *c = XNEW (struct fork_catchpoint); + + init_catchpoint (&c->base, gdbarch, tempflag, cond_string, ops); - /* FIXME: We should put this information in a breakpoint private data - area. */ - b->forked_inferior_pid = null_ptid; + c->forked_inferior_pid = null_ptid; + + install_breakpoint (0, &c->base, 1); } /* Exec catchpoints. */ +/* An instance of this type is used to represent an exec catchpoint. + It includes a "struct breakpoint" as a kind of base class; users + downcast to "struct breakpoint *" when needed. A breakpoint is + really of this type iff its ops pointer points to + CATCH_EXEC_BREAKPOINT_OPS. */ + +struct exec_catchpoint +{ + /* The base class. */ + struct breakpoint base; + + /* Filename of a program whose exec triggered this catchpoint. + This field is only valid immediately after this catchpoint has + triggered. */ + char *exec_pathname; +}; + +/* Implement the "dtor" breakpoint_ops method for exec + catchpoints. */ + +static void +dtor_catch_exec (struct breakpoint *b) +{ + struct exec_catchpoint *c = (struct exec_catchpoint *) b; + + xfree (c->exec_pathname); + + base_breakpoint_ops.dtor (b); +} + static int insert_catch_exec (struct bp_location *bl) { @@ -6790,22 +6841,43 @@ static int breakpoint_hit_catch_exec (const struct bp_location *bl, struct address_space *aspace, CORE_ADDR bp_addr) { - return inferior_has_execd (inferior_ptid, &bl->owner->exec_pathname); + struct exec_catchpoint *c = (struct exec_catchpoint *) bl->owner; + + return inferior_has_execd (inferior_ptid, &c->exec_pathname); } static enum print_stop_action -print_it_catch_exec (struct breakpoint *b) +print_it_catch_exec (bpstat bs) { + struct ui_out *uiout = current_uiout; + struct breakpoint *b = bs->breakpoint_at; + struct exec_catchpoint *c = (struct exec_catchpoint *) b; + annotate_catchpoint (b->number); - printf_filtered (_("\nCatchpoint %d (exec'd %s), "), b->number, - b->exec_pathname); + if (b->disposition == disp_del) + ui_out_text (uiout, "\nTemporary catchpoint "); + else + ui_out_text (uiout, "\nCatchpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_EXEC)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, " (exec'd "); + ui_out_field_string (uiout, "new-exec", c->exec_pathname); + ui_out_text (uiout, "), "); + return PRINT_SRC_AND_LOC; } static void print_one_catch_exec (struct breakpoint *b, struct bp_location **last_loc) { + struct exec_catchpoint *c = (struct exec_catchpoint *) b; struct value_print_options opts; + struct ui_out *uiout = current_uiout; get_user_print_options (&opts); @@ -6816,10 +6888,10 @@ print_one_catch_exec (struct breakpoint *b, struct bp_location **last_loc) ui_out_field_skip (uiout, "addr"); annotate_field (5); ui_out_text (uiout, "exec"); - if (b->exec_pathname != NULL) + if (c->exec_pathname != NULL) { ui_out_text (uiout, ", program \""); - ui_out_field_string (uiout, "what", b->exec_pathname); + ui_out_field_string (uiout, "what", c->exec_pathname); ui_out_text (uiout, "\" "); } } @@ -6837,35 +6909,23 @@ static void print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp) { fprintf_unfiltered (fp, "catch exec"); + print_recreate_thread (b, fp); } -static struct breakpoint_ops catch_exec_breakpoint_ops = -{ - insert_catch_exec, - remove_catch_exec, - breakpoint_hit_catch_exec, - NULL, /* resources_needed */ - print_it_catch_exec, - print_one_catch_exec, - NULL, /* print_one_detail */ - print_mention_catch_exec, - print_recreate_catch_exec -}; +static struct breakpoint_ops catch_exec_breakpoint_ops; static void create_syscall_event_catchpoint (int tempflag, VEC(int) *filter, - struct breakpoint_ops *ops) + const struct breakpoint_ops *ops) { + struct syscall_catchpoint *c; struct gdbarch *gdbarch = get_current_arch (); - struct breakpoint *b = - create_catchpoint_without_mention (gdbarch, tempflag, NULL, ops); - b->syscalls_to_be_caught = filter; + c = XNEW (struct syscall_catchpoint); + init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops); + c->syscalls_to_be_caught = filter; - /* Now, we have to mention the breakpoint and update the global - location list. */ - mention (b); - update_global_location_list (1); + install_breakpoint (0, &c->base, 1); } static int @@ -6882,41 +6942,59 @@ hw_breakpoint_used_count (void) { /* Special types of hardware breakpoints may use more than one register. */ - if (b->ops && b->ops->resources_needed) - i += b->ops->resources_needed (bl); - else - i++; + i += b->ops->resources_needed (bl); } } return i; } +/* Returns the resources B would use if it were a hardware + watchpoint. */ + static int -hw_watchpoint_used_count (enum bptype type, int *other_type_used) +hw_watchpoint_use_count (struct breakpoint *b) { int i = 0; - struct breakpoint *b; struct bp_location *bl; + if (!breakpoint_enabled (b)) + return 0; + + for (bl = b->loc; bl; bl = bl->next) + { + /* Special types of hardware watchpoints may use more than + one register. */ + i += b->ops->resources_needed (bl); + } + + return i; +} + +/* Returns the sum the used resources of all hardware watchpoints of + type TYPE in the breakpoints list. Also returns in OTHER_TYPE_USED + the sum of the used resources of all hardware watchpoints of other + types _not_ TYPE. */ + +static int +hw_watchpoint_used_count_others (struct breakpoint *except, + enum bptype type, int *other_type_used) +{ + int i = 0; + struct breakpoint *b; + *other_type_used = 0; ALL_BREAKPOINTS (b) { + if (b == except) + continue; if (!breakpoint_enabled (b)) continue; - if (b->type == type) - for (bl = b->loc; bl; bl = bl->next) - { - /* Special types of hardware watchpoints may use more than - one register. */ - if (b->ops && b->ops->resources_needed) - i += b->ops->resources_needed (bl); - else - i++; - } - else if (is_hardware_watchpoint (b)) - *other_type_used = 1; + if (b->type == type) + i += hw_watchpoint_use_count (b); + else if (is_hardware_watchpoint (b)) + *other_type_used = 1; } return i; @@ -6955,53 +7033,15 @@ enable_watchpoints_after_interactive_call_stop (void) void disable_breakpoints_before_startup (void) { - struct breakpoint *b; - int found = 0; - - ALL_BREAKPOINTS (b) - { - if (b->pspace != current_program_space) - continue; - - if ((b->type == bp_breakpoint - || b->type == bp_hardware_breakpoint) - && breakpoint_enabled (b)) - { - b->enable_state = bp_startup_disabled; - found = 1; - } - } - - if (found) - update_global_location_list (0); - - current_program_space->executing_startup = 1; -} + current_program_space->executing_startup = 1; + update_global_location_list (0); +} void enable_breakpoints_after_startup (void) { - struct breakpoint *b; - int found = 0; - current_program_space->executing_startup = 0; - - ALL_BREAKPOINTS (b) - { - if (b->pspace != current_program_space) - continue; - - if ((b->type == bp_breakpoint - || b->type == bp_hardware_breakpoint) - && b->enable_state == bp_startup_disabled) - { - b->enable_state = bp_enabled; - found = 1; - } - } - - if (found) - breakpoint_re_set (); + breakpoint_re_set (); } @@ -7019,7 +7059,7 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, one. */ gdb_assert (!frame_id_inlined_p (frame_id)); - b = set_raw_breakpoint (gdbarch, sal, type); + b = set_raw_breakpoint (gdbarch, sal, type, &momentary_breakpoint_ops); b->enable_state = bp_enabled; b->disposition = disp_donttouch; b->frame_id = frame_id; @@ -7035,19 +7075,18 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, return b; } -/* Make a deep copy of momentary breakpoint ORIG. Returns NULL if - ORIG is NULL. */ +/* Make a momentary breakpoint based on the master breakpoint ORIG. + The new breakpoint will have type TYPE, and use OPS as it + breakpoint_ops. */ -struct breakpoint * -clone_momentary_breakpoint (struct breakpoint *orig) +static struct breakpoint * +momentary_breakpoint_from_master (struct breakpoint *orig, + enum bptype type, + const struct breakpoint_ops *ops) { struct breakpoint *copy; - /* If there's nothing to clone, then return nothing. */ - if (orig == NULL) - return NULL; - - copy = set_raw_breakpoint_without_location (orig->gdbarch, orig->type); + copy = set_raw_breakpoint_without_location (orig->gdbarch, type, ops); copy->loc = allocate_bp_location (copy); set_breakpoint_location_function (copy->loc, 1); @@ -7057,12 +7096,10 @@ clone_momentary_breakpoint (struct breakpoint *orig) copy->loc->section = orig->loc->section; copy->loc->pspace = orig->loc->pspace; - if (orig->source_file == NULL) - copy->source_file = NULL; - else - copy->source_file = xstrdup (orig->source_file); + if (orig->loc->source_file != NULL) + copy->loc->source_file = xstrdup (orig->loc->source_file); - copy->line_number = orig->line_number; + copy->loc->line_number = orig->loc->line_number; copy->frame_id = orig->frame_id; copy->thread = orig->thread; copy->pspace = orig->pspace; @@ -7075,6 +7112,19 @@ clone_momentary_breakpoint (struct breakpoint *orig) return copy; } +/* Make a deep copy of momentary breakpoint ORIG. Returns NULL if + ORIG is NULL. */ + +struct breakpoint * +clone_momentary_breakpoint (struct breakpoint *orig) +{ + /* If there's nothing to clone, then return nothing. */ + if (orig == NULL) + return NULL; + + return momentary_breakpoint_from_master (orig, orig->type, orig->ops); +} + struct breakpoint * set_momentary_breakpoint_at_pc (struct gdbarch *gdbarch, CORE_ADDR pc, enum bptype type) @@ -7095,168 +7145,8 @@ set_momentary_breakpoint_at_pc (struct gdbarch *gdbarch, CORE_ADDR pc, static void mention (struct breakpoint *b) { - int say_where = 0; - struct cleanup *ui_out_chain; - struct value_print_options opts; - - get_user_print_options (&opts); - - /* FIXME: This is misplaced; mention() is called by things (like - hitting a watchpoint) other than breakpoint creation. It should - be possible to clean this up and at the same time replace the - random calls to breakpoint_changed with this hook. */ - observer_notify_breakpoint_created (b->number); - - if (b->ops != NULL && b->ops->print_mention != NULL) - b->ops->print_mention (b); - else - switch (b->type) - { - case bp_none: - printf_filtered (_("(apparently deleted?) Eventpoint %d: "), - b->number); - break; - case bp_watchpoint: - ui_out_text (uiout, "Watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_hardware_watchpoint: - ui_out_text (uiout, "Hardware watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_read_watchpoint: - ui_out_text (uiout, "Hardware read watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_access_watchpoint: - ui_out_text (uiout, "Hardware access (read/write) watchpoint "); - ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt"); - ui_out_field_int (uiout, "number", b->number); - ui_out_text (uiout, ": "); - ui_out_field_string (uiout, "exp", b->exp_string); - do_cleanups (ui_out_chain); - break; - case bp_breakpoint: - case bp_gnu_ifunc_resolver: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - if (b->disposition == disp_del) - printf_filtered (_("Temporary breakpoint")); - else - printf_filtered (_("Breakpoint")); - printf_filtered (_(" %d"), b->number); - if (b->type == bp_gnu_ifunc_resolver) - printf_filtered (_(" at gnu-indirect-function resolver")); - say_where = 1; - break; - case bp_hardware_breakpoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Hardware assisted breakpoint %d"), b->number); - say_where = 1; - break; - case bp_tracepoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Tracepoint")); - printf_filtered (_(" %d"), b->number); - say_where = 1; - break; - case bp_fast_tracepoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Fast tracepoint")); - printf_filtered (_(" %d"), b->number); - say_where = 1; - break; - case bp_static_tracepoint: - if (ui_out_is_mi_like_p (uiout)) - { - say_where = 0; - break; - } - printf_filtered (_("Static tracepoint")); - printf_filtered (_(" %d"), b->number); - say_where = 1; - break; - - case bp_until: - case bp_finish: - case bp_longjmp: - case bp_longjmp_resume: - case bp_exception: - case bp_exception_resume: - case bp_step_resume: - case bp_call_dummy: - case bp_std_terminate: - case bp_watchpoint_scope: - case bp_shlib_event: - case bp_thread_event: - case bp_overlay_event: - case bp_jit_event: - case bp_longjmp_master: - case bp_std_terminate_master: - case bp_exception_master: - case bp_gnu_ifunc_resolver_return: - break; - } - - if (say_where) - { - /* i18n: cagney/2005-02-11: Below needs to be merged into a - single string. */ - if (b->loc == NULL) - { - printf_filtered (_(" (%s) pending."), b->addr_string); - } - else - { - if (opts.addressprint || b->source_file == NULL) - { - printf_filtered (" at "); - fputs_filtered (paddress (b->loc->gdbarch, b->loc->address), - gdb_stdout); - } - if (b->source_file) - printf_filtered (": file %s, line %d.", - b->source_file, b->line_number); - - if (b->loc->next) - { - struct bp_location *loc = b->loc; - int n = 0; - for (; loc; loc = loc->next) - ++n; - printf_filtered (" (%d locations)", n); - } - - } - } - if (ui_out_is_mi_like_p (uiout)) + b->ops->print_mention (b); + if (ui_out_is_mi_like_p (current_uiout)) return; printf_filtered ("\n"); } @@ -7267,20 +7157,36 @@ add_location_to_breakpoint (struct breakpoint *b, const struct symtab_and_line *sal) { struct bp_location *loc, **tmp; + CORE_ADDR adjusted_address; + struct gdbarch *loc_gdbarch = get_sal_arch (*sal); + + if (loc_gdbarch == NULL) + loc_gdbarch = b->gdbarch; + + /* Adjust the breakpoint's address prior to allocating a location. + Once we call allocate_bp_location(), that mostly uninitialized + location will be placed on the location chain. Adjustment of the + breakpoint may cause target_read_memory() to be called and we do + not want its scan of the location chain to find a breakpoint and + location that's only been partially initialized. */ + adjusted_address = adjust_breakpoint_address (loc_gdbarch, + sal->pc, b->type); loc = allocate_bp_location (b); for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next)) ; *tmp = loc; - loc->gdbarch = get_sal_arch (*sal); - if (!loc->gdbarch) - loc->gdbarch = b->gdbarch; + loc->requested_address = sal->pc; - loc->address = adjust_breakpoint_address (loc->gdbarch, - loc->requested_address, b->type); + loc->address = adjusted_address; loc->pspace = sal->pspace; gdb_assert (loc->pspace != NULL); loc->section = sal->section; + loc->gdbarch = loc_gdbarch; + + if (sal->symtab != NULL) + loc->source_file = xstrdup (sal->symtab->filename); + loc->line_number = sal->line; set_breakpoint_location_function (loc, sal->explicit_pc || sal->explicit_line); @@ -7296,7 +7202,7 @@ bp_loc_is_permanent (struct bp_location *loc) { int len; CORE_ADDR addr; - const gdb_byte *brk; + const gdb_byte *bpoint; gdb_byte *target_mem; struct cleanup *cleanup; int retval = 0; @@ -7304,10 +7210,10 @@ bp_loc_is_permanent (struct bp_location *loc) gdb_assert (loc != NULL); addr = loc->address; - brk = gdbarch_breakpoint_from_pc (loc->gdbarch, &addr, &len); + bpoint = gdbarch_breakpoint_from_pc (loc->gdbarch, &addr, &len); /* Software breakpoints unsupported? */ - if (brk == NULL) + if (bpoint == NULL) return 0; target_mem = alloca (len); @@ -7321,7 +7227,7 @@ bp_loc_is_permanent (struct bp_location *loc) make_show_memory_breakpoints_cleanup (0); if (target_read_memory (loc->address, target_mem, len) == 0 - && memcmp (target_mem, brk, len) == 0) + && memcmp (target_mem, bpoint, len) == 0) retval = 1; do_cleanups (cleanup); @@ -7336,22 +7242,24 @@ bp_loc_is_permanent (struct bp_location *loc) as condition expression. */ static void -create_breakpoint_sal (struct gdbarch *gdbarch, - struct symtabs_and_lines sals, char *addr_string, - char *cond_string, - enum bptype type, enum bpdisp disposition, - int thread, int task, int ignore_count, - struct breakpoint_ops *ops, int from_tty, - int enabled, int internal, int display_canonical) +init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch, + struct symtabs_and_lines sals, char *addr_string, + char *filter, char *cond_string, + enum bptype type, enum bpdisp disposition, + int thread, int task, int ignore_count, + const struct breakpoint_ops *ops, int from_tty, + int enabled, int internal, unsigned flags, + int display_canonical) { - struct breakpoint *b = NULL; int i; if (type == bp_hardware_breakpoint) { - int i = hw_breakpoint_used_count (); - int target_resources_ok = - target_can_use_hardware_watchpoint (bp_hardware_breakpoint, + int target_resources_ok; + + i = hw_breakpoint_used_count (); + target_resources_ok = + target_can_use_hardware_watchpoint (bp_hardware_breakpoint, i + 1, 0); if (target_resources_ok == 0) error (_("No hardware breakpoint support in the target.")); @@ -7378,8 +7286,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch, if (i == 0) { - b = set_raw_breakpoint (gdbarch, sal, type); - set_breakpoint_number (internal, b); + init_raw_breakpoint (b, gdbarch, sal, type, ops); b->thread = thread; b->task = task; @@ -7387,10 +7294,13 @@ create_breakpoint_sal (struct gdbarch *gdbarch, b->ignore_count = ignore_count; b->enable_state = enabled ? bp_enabled : bp_disabled; b->disposition = disposition; - b->pspace = sals.sals[0].pspace; + + if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0) + b->loc->inserted = 1; if (type == bp_static_tracepoint) { + struct tracepoint *t = (struct tracepoint *) b; struct static_tracepoint_marker marker; if (is_marker_spec (addr_string)) @@ -7400,43 +7310,39 @@ create_breakpoint_sal (struct gdbarch *gdbarch, char *p = &addr_string[3]; char *endp; char *marker_str; - int i; p = skip_spaces (p); endp = skip_to_space (p); marker_str = savestring (p, endp - p); - b->static_trace_marker_id = marker_str; + t->static_trace_marker_id = marker_str; printf_filtered (_("Probed static tracepoint " "marker \"%s\"\n"), - b->static_trace_marker_id); + t->static_trace_marker_id); } else if (target_static_tracepoint_marker_at (sal.pc, &marker)) { - b->static_trace_marker_id = xstrdup (marker.str_id); + t->static_trace_marker_id = xstrdup (marker.str_id); release_static_tracepoint_marker (&marker); printf_filtered (_("Probed static tracepoint " "marker \"%s\"\n"), - b->static_trace_marker_id); + t->static_trace_marker_id); } else warning (_("Couldn't determine the static " "tracepoint marker to probe")); } - if (enabled && b->pspace->executing_startup - && (b->type == bp_breakpoint - || b->type == bp_hardware_breakpoint)) - b->enable_state = bp_startup_disabled; - loc = b->loc; } else { loc = add_location_to_breakpoint (b, &sal); + if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0) + loc->inserted = 1; } if (bp_loc_is_permanent (loc)) @@ -7459,146 +7365,45 @@ create_breakpoint_sal (struct gdbarch *gdbarch, me. */ b->addr_string = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address)); - - b->ops = ops; - if (internal) - /* Do not mention breakpoints with a negative number, but do - notify observers. */ - observer_notify_breakpoint_created (b->number); - else - mention (b); + b->filter = filter; } -/* Remove element at INDEX_TO_REMOVE from SAL, shifting other - elements to fill the void space. */ static void -remove_sal (struct symtabs_and_lines *sal, int index_to_remove) -{ - int i = index_to_remove+1; - int last_index = sal->nelts-1; - - for (;i <= last_index; ++i) - sal->sals[i-1] = sal->sals[i]; - - --(sal->nelts); -} - -/* If appropriate, obtains all sals that correspond to the same file - and line as SAL, in all program spaces. Users debugging with IDEs, - will want to set a breakpoint at foo.c:line, and not really care - about program spaces. This is done only if SAL does not have - explicit PC and has line and file information. If we got just a - single expanded sal, return the original. - - Otherwise, if SAL.explicit_line is not set, filter out all sals for - which the name of enclosing function is different from SAL. This - makes sure that if we have breakpoint originally set in template - instantiation, say foo(), we won't expand SAL to locations at - the same line in all existing instantiations of 'foo'. */ - -static struct symtabs_and_lines -expand_line_sal_maybe (struct symtab_and_line sal) +create_breakpoint_sal (struct gdbarch *gdbarch, + struct symtabs_and_lines sals, char *addr_string, + char *filter, char *cond_string, + enum bptype type, enum bpdisp disposition, + int thread, int task, int ignore_count, + const struct breakpoint_ops *ops, int from_tty, + int enabled, int internal, unsigned flags, + int display_canonical) { - struct symtabs_and_lines expanded; - CORE_ADDR original_pc = sal.pc; - char *original_function = NULL; - int found; - int i; + struct breakpoint *b; struct cleanup *old_chain; - /* If we have explicit pc, don't expand. - If we have no line number, we can't expand. */ - if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL) - { - expanded.nelts = 1; - expanded.sals = xmalloc (sizeof (struct symtab_and_line)); - expanded.sals[0] = sal; - return expanded; - } - - sal.pc = 0; - - old_chain = save_current_space_and_thread (); - - switch_to_program_space_and_thread (sal.pspace); - - find_pc_partial_function (original_pc, &original_function, NULL, NULL); - - /* Note that expand_line_sal visits *all* program spaces. */ - expanded = expand_line_sal (sal); - - if (expanded.nelts == 1) - { - /* We had one sal, we got one sal. Return that sal, adjusting it - past the function prologue if necessary. */ - xfree (expanded.sals); - expanded.nelts = 1; - expanded.sals = xmalloc (sizeof (struct symtab_and_line)); - sal.pc = original_pc; - expanded.sals[0] = sal; - skip_prologue_sal (&expanded.sals[0]); - do_cleanups (old_chain); - return expanded; - } - - if (!sal.explicit_line) + if (is_tracepoint_type (type)) { - CORE_ADDR func_addr, func_end; - for (i = 0; i < expanded.nelts; ++i) - { - CORE_ADDR pc = expanded.sals[i].pc; - char *this_function; + struct tracepoint *t; - /* We need to switch threads as well since we're about to - read memory. */ - switch_to_program_space_and_thread (expanded.sals[i].pspace); - - if (find_pc_partial_function (pc, &this_function, - &func_addr, &func_end)) - { - if (this_function - && strcmp (this_function, original_function) != 0) - { - remove_sal (&expanded, i); - --i; - } - } - } + t = XCNEW (struct tracepoint); + b = &t->base; } + else + b = XNEW (struct breakpoint); - /* Skip the function prologue if necessary. */ - for (i = 0; i < expanded.nelts; ++i) - skip_prologue_sal (&expanded.sals[i]); - - do_cleanups (old_chain); - - if (expanded.nelts <= 1) - { - /* This is un ugly workaround. If we get zero expanded sals - then something is really wrong. Fix that by returning the - original sal. */ - - xfree (expanded.sals); - expanded.nelts = 1; - expanded.sals = xmalloc (sizeof (struct symtab_and_line)); - sal.pc = original_pc; - expanded.sals[0] = sal; - return expanded; - } + old_chain = make_cleanup (xfree, b); - if (original_pc) - { - found = 0; - for (i = 0; i < expanded.nelts; ++i) - if (expanded.sals[i].pc == original_pc) - { - found = 1; - break; - } - gdb_assert (found); - } + init_breakpoint_sal (b, gdbarch, + sals, addr_string, + filter, cond_string, + type, disposition, + thread, task, ignore_count, + ops, from_tty, + enabled, internal, flags, + display_canonical); + discard_cleanups (old_chain); - return expanded; + install_breakpoint (internal, b, 0); } /* Add SALS.nelts breakpoints to the breakpoint table. For each @@ -7618,26 +7423,38 @@ expand_line_sal_maybe (struct symtab_and_line sal) static void create_breakpoints_sal (struct gdbarch *gdbarch, - struct symtabs_and_lines sals, struct linespec_result *canonical, char *cond_string, enum bptype type, enum bpdisp disposition, int thread, int task, int ignore_count, - struct breakpoint_ops *ops, int from_tty, - int enabled, int internal) + const struct breakpoint_ops *ops, int from_tty, + int enabled, int internal, unsigned flags) { int i; + struct linespec_sals *lsal; - for (i = 0; i < sals.nelts; ++i) + if (canonical->pre_expanded) + gdb_assert (VEC_length (linespec_sals, canonical->sals) == 1); + + for (i = 0; VEC_iterate (linespec_sals, canonical->sals, i, lsal); ++i) { - struct symtabs_and_lines expanded = - expand_line_sal_maybe (sals.sals[i]); + /* Note that 'addr_string' can be NULL in the case of a plain + 'break', without arguments. */ + char *addr_string = (canonical->addr_string + ? xstrdup (canonical->addr_string) + : NULL); + char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL; + struct cleanup *inner = make_cleanup (xfree, addr_string); - create_breakpoint_sal (gdbarch, expanded, canonical->canonical[i], + make_cleanup (xfree, filter_string); + create_breakpoint_sal (gdbarch, lsal->sals, + addr_string, + filter_string, cond_string, type, disposition, thread, task, ignore_count, ops, - from_tty, enabled, internal, + from_tty, enabled, internal, flags, canonical->special_display); + discard_cleanups (inner); } } @@ -7651,7 +7468,6 @@ create_breakpoints_sal (struct gdbarch *gdbarch, static void parse_breakpoint_sals (char **address, - struct symtabs_and_lines *sals, struct linespec_result *canonical) { char *addr_start = *address; @@ -7661,28 +7477,34 @@ parse_breakpoint_sals (char **address, if ((*address) == NULL || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2]))) { - if (default_breakpoint_valid) + /* The last displayed codepoint, if it's valid, is our default breakpoint + address. */ + if (last_displayed_sal_is_valid ()) { + struct linespec_sals lsal; struct symtab_and_line sal; init_sal (&sal); /* Initialize to zeroes. */ - sals->sals = (struct symtab_and_line *) + lsal.sals.sals = (struct symtab_and_line *) xmalloc (sizeof (struct symtab_and_line)); - sal.pc = default_breakpoint_address; - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pspace = default_breakpoint_pspace; - sal.section = find_pc_overlay (sal.pc); + + /* Set sal's pspace, pc, symtab, and line to the values + corresponding to the last call to print_frame_info. */ + get_last_displayed_sal (&sal); + sal.section = find_pc_overlay (sal.pc); /* "break" without arguments is equivalent to "break *PC" - where PC is the default_breakpoint_address. So make sure - to set sal.explicit_pc to prevent GDB from trying to - expand the list of sals to include all other instances - with the same symtab and line. */ + where PC is the last displayed codepoint's address. So + make sure to set sal.explicit_pc to prevent GDB from + trying to expand the list of sals to include all other + instances with the same symtab and line. */ sal.explicit_pc = 1; - sals->sals[0] = sal; - sals->nelts = 1; + lsal.sals.sals[0] = sal; + lsal.sals.nelts = 1; + lsal.canonical = NULL; + + VEC_safe_push (linespec_sals, canonical->sals, &lsal); } else error (_("No default breakpoint address now.")); @@ -7692,37 +7514,16 @@ parse_breakpoint_sals (char **address, /* Force almost all breakpoints to be in terms of the current_source_symtab (which is decode_line_1's default). This should produce the results we want almost all of the - time while leaving default_breakpoint_* alone. - - ObjC: However, don't match an Objective-C method name which - may have a '+' or '-' succeeded by a '[' */ - - struct symtab_and_line cursal = get_current_source_symtab_and_line (); - - if (default_breakpoint_valid - && (!cursal.symtab - || ((strchr ("+-", (*address)[0]) != NULL) - && ((*address)[1] != '[')))) - *sals = decode_line_1 (address, 1, default_breakpoint_symtab, - default_breakpoint_line, canonical); + time while leaving default_breakpoint_* alone. */ + if (last_displayed_sal_is_valid ()) + decode_line_full (address, DECODE_LINE_FUNFIRSTLINE, + get_last_displayed_symtab (), + get_last_displayed_line (), + canonical, NULL, NULL); else - *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0, - canonical); - } - /* For any SAL that didn't have a canonical string, fill one in. */ - if (sals->nelts > 0 && canonical->canonical == NULL) - canonical->canonical = xcalloc (sals->nelts, sizeof (char **)); - if (addr_start != (*address)) - { - int i; - - for (i = 0; i < sals->nelts; i++) - { - /* Add the string if not present. */ - if (canonical->canonical[i] == NULL) - canonical->canonical[i] = savestring (addr_start, - (*address) - addr_start); - } + decode_line_full (address, DECODE_LINE_FUNFIRSTLINE, + (struct symtab *) NULL, 0, + canonical, NULL, NULL); } } @@ -7757,28 +7558,27 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch, for (i = 0; i < sals->nelts; i++) { + struct gdbarch *sarch; + sal = &sals->sals[i]; - rslt = gdbarch_fast_tracepoint_valid_at (gdbarch, sal->pc, + sarch = get_sal_arch (*sal); + /* We fall back to GDBARCH if there is no architecture + associated with SAL. */ + if (sarch == NULL) + sarch = gdbarch; + rslt = gdbarch_fast_tracepoint_valid_at (sarch, sal->pc, NULL, &msg); old_chain = make_cleanup (xfree, msg); if (!rslt) error (_("May not have a fast tracepoint at 0x%s%s"), - paddress (gdbarch, sal->pc), (msg ? msg : "")); + paddress (sarch, sal->pc), (msg ? msg : "")); do_cleanups (old_chain); } } -static void -do_captured_parse_breakpoint (struct ui_out *ui, void *data) -{ - struct captured_parse_breakpoint_args *args = data; - - parse_breakpoint_sals (args->arg_p, args->sals_p, args->canonical_p); -} - /* Given TOK, a string specification of condition and thread, as accepted by the 'break' command, extract the condition string and thread number and set *COND_STRING and *THREAD. @@ -7911,46 +7711,45 @@ create_breakpoint (struct gdbarch *gdbarch, int tempflag, enum bptype type_wanted, int ignore_count, enum auto_boolean pending_break_support, - struct breakpoint_ops *ops, - int from_tty, int enabled, int internal) + const struct breakpoint_ops *ops, + int from_tty, int enabled, int internal, + unsigned flags) { - struct gdb_exception e; - struct symtabs_and_lines sals; - struct symtab_and_line pending_sal; - char *copy_arg; + volatile struct gdb_exception e; + char *copy_arg = NULL; char *addr_start = arg; struct linespec_result canonical; struct cleanup *old_chain; struct cleanup *bkpt_chain = NULL; - struct captured_parse_breakpoint_args parse_args; int i; int pending = 0; int task = 0; int prev_bkpt_count = breakpoint_count; - sals.sals = NULL; - sals.nelts = 0; - init_linespec_result (&canonical); + gdb_assert (ops != NULL); - parse_args.arg_p = &arg; - parse_args.sals_p = &sals; - parse_args.canonical_p = &canonical; + init_linespec_result (&canonical); if (type_wanted == bp_static_tracepoint && is_marker_spec (arg)) { int i; + struct linespec_sals lsal; - sals = decode_static_tracepoint_spec (&arg); + lsal.sals = decode_static_tracepoint_spec (&arg); copy_arg = savestring (addr_start, arg - addr_start); - canonical.canonical = xcalloc (sals.nelts, sizeof (char **)); - for (i = 0; i < sals.nelts; i++) - canonical.canonical[i] = xstrdup (copy_arg); + + canonical.addr_string = xstrdup (copy_arg); + lsal.canonical = xstrdup (copy_arg); + VEC_safe_push (linespec_sals, canonical.sals, &lsal); + goto done; } - e = catch_exception (uiout, do_captured_parse_breakpoint, - &parse_args, RETURN_MASK_ALL); + TRY_CATCH (e, RETURN_MASK_ALL) + { + parse_breakpoint_sals (&arg, &canonical); + } /* If caller is interested in rc value from parse, set value. */ switch (e.reason) @@ -7973,43 +7772,39 @@ create_breakpoint (struct gdbarch *gdbarch, /* If pending breakpoint support is auto query and the user selects no, then simply return the error code. */ if (pending_break_support == AUTO_BOOLEAN_AUTO - && !nquery (_("Make breakpoint pending on " - "future shared library load? "))) + && !nquery (_("Make %s pending on future shared library load? "), + bptype_string (type_wanted))) return 0; /* At this point, either the user was queried about setting a pending breakpoint and selected yes, or pending breakpoint behavior is on and thus a pending breakpoint is defaulted on behalf of the user. */ - copy_arg = xstrdup (addr_start); - canonical.canonical = ©_arg; - sals.nelts = 1; - sals.sals = &pending_sal; - pending_sal.pc = 0; - pending = 1; + { + struct linespec_sals lsal; + + copy_arg = xstrdup (addr_start); + lsal.canonical = xstrdup (copy_arg); + lsal.sals.nelts = 1; + lsal.sals.sals = XNEW (struct symtab_and_line); + init_sal (&lsal.sals.sals[0]); + pending = 1; + VEC_safe_push (linespec_sals, canonical.sals, &lsal); + } break; default: throw_exception (e); } break; default: - if (!sals.nelts) + if (VEC_empty (linespec_sals, canonical.sals)) return 0; } done: /* Create a chain of things that always need to be cleaned up. */ - old_chain = make_cleanup (null_cleanup, 0); - - if (!pending) - { - /* Make sure that all storage allocated to SALS gets freed. */ - make_cleanup (xfree, sals.sals); - - /* Cleanup the canonical array but not its contents. */ - make_cleanup (xfree, canonical.canonical); - } + old_chain = make_cleanup_destroy_linespec_result (&canonical); /* ----------------------------- SNIP ----------------------------- Anything added to the cleanup chain beyond this point is assumed @@ -8017,28 +7812,36 @@ create_breakpoint (struct gdbarch *gdbarch, then the memory is not reclaimed. */ bkpt_chain = make_cleanup (null_cleanup, 0); - /* Mark the contents of the canonical for cleanup. These go on - the bkpt_chain and only occur if the breakpoint create fails. */ - for (i = 0; i < sals.nelts; i++) - { - if (canonical.canonical[i] != NULL) - make_cleanup (xfree, canonical.canonical[i]); - } - /* Resolve all line numbers to PC's and verify that the addresses are ok for the target. */ if (!pending) - breakpoint_sals_to_pc (&sals); + { + int ix; + struct linespec_sals *iter; + + for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix) + breakpoint_sals_to_pc (&iter->sals); + } /* Fast tracepoints may have additional restrictions on location. */ - if (type_wanted == bp_fast_tracepoint) - check_fast_tracepoint_sals (gdbarch, &sals); + if (!pending && type_wanted == bp_fast_tracepoint) + { + int ix; + struct linespec_sals *iter; + + for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix) + check_fast_tracepoint_sals (gdbarch, &iter->sals); + } /* Verify that condition can be parsed, before setting any breakpoints. Allocate a separate condition expression for each breakpoint. */ if (!pending) { + struct linespec_sals *lsal; + + lsal = VEC_index (linespec_sals, canonical.sals, 0); + if (parse_condition_and_thread) { /* Here we only parse 'arg' to separate condition @@ -8047,7 +7850,7 @@ create_breakpoint (struct gdbarch *gdbarch, re-parse it in context of each sal. */ cond_string = NULL; thread = -1; - find_condition_and_thread (arg, sals.sals[0].pc, &cond_string, + find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string, &thread, &task); if (cond_string) make_cleanup (xfree, cond_string); @@ -8069,37 +7872,31 @@ create_breakpoint (struct gdbarch *gdbarch, expand multiple locations for each sal, given than SALS already should contain all sals for MARKER_ID. */ if (type_wanted == bp_static_tracepoint - && is_marker_spec (canonical.canonical[0])) + && is_marker_spec (copy_arg)) { int i; - for (i = 0; i < sals.nelts; ++i) + for (i = 0; i < lsal->sals.nelts; ++i) { struct symtabs_and_lines expanded; - struct breakpoint *tp; + struct tracepoint *tp; struct cleanup *old_chain; + char *addr_string; expanded.nelts = 1; - expanded.sals = xmalloc (sizeof (struct symtab_and_line)); - expanded.sals[0] = sals.sals[i]; - old_chain = make_cleanup (xfree, expanded.sals); - - create_breakpoint_sal (gdbarch, expanded, canonical.canonical[i], - cond_string, type_wanted, - tempflag ? disp_del : disp_donttouch, - thread, task, ignore_count, ops, - from_tty, enabled, internal, - canonical.special_display); - - do_cleanups (old_chain); - - /* Get the tracepoint we just created. */ - if (internal) - tp = get_breakpoint (internal_breakpoint_number); - else - tp = get_breakpoint (breakpoint_count); - gdb_assert (tp != NULL); - + expanded.sals = &lsal->sals.sals[i]; + + addr_string = xstrdup (canonical.addr_string); + old_chain = make_cleanup (xfree, addr_string); + + tp = XCNEW (struct tracepoint); + init_breakpoint_sal (&tp->base, gdbarch, expanded, + addr_string, NULL, + cond_string, type_wanted, + tempflag ? disp_del : disp_donttouch, + thread, task, ignore_count, ops, + from_tty, enabled, internal, flags, + canonical.special_display); /* Given that its possible to have multiple markers with the same string id, if the user is creating a static tracepoint by marker id ("strace -m MARKER_ID"), then @@ -8107,14 +7904,18 @@ create_breakpoint (struct gdbarch *gdbarch, try to match up which of the newly found markers corresponds to this one */ tp->static_trace_marker_id_idx = i; + + install_breakpoint (internal, &tp->base, 0); + + discard_cleanups (old_chain); } } else - create_breakpoints_sal (gdbarch, sals, &canonical, cond_string, + create_breakpoints_sal (gdbarch, &canonical, cond_string, type_wanted, tempflag ? disp_del : disp_donttouch, thread, task, ignore_count, ops, from_tty, - enabled, internal); + enabled, internal, flags); } else { @@ -8122,33 +7923,32 @@ create_breakpoint (struct gdbarch *gdbarch, make_cleanup (xfree, copy_arg); - b = set_raw_breakpoint_without_location (gdbarch, type_wanted); - set_breakpoint_number (internal, b); - b->thread = -1; - b->addr_string = canonical.canonical[0]; + if (is_tracepoint_type (type_wanted)) + { + struct tracepoint *t; + + t = XCNEW (struct tracepoint); + b = &t->base; + } + else + b = XNEW (struct breakpoint); + + init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops); + + b->addr_string = copy_arg; b->cond_string = NULL; b->ignore_count = ignore_count; b->disposition = tempflag ? disp_del : disp_donttouch; b->condition_not_parsed = 1; - b->ops = ops; b->enable_state = enabled ? bp_enabled : bp_disabled; - b->pspace = current_program_space; - b->py_bp_object = NULL; - - if (enabled && b->pspace->executing_startup - && (b->type == bp_breakpoint - || b->type == bp_hardware_breakpoint)) - b->enable_state = bp_startup_disabled; - - if (internal) - /* Do not mention breakpoints with a negative number, - but do notify observers. */ - observer_notify_breakpoint_created (b->number); - else - mention (b); + if ((type_wanted != bp_breakpoint + && type_wanted != bp_hardware_breakpoint) || thread != -1) + b->pspace = current_program_space; + + install_breakpoint (internal, b, 0); } - if (sals.nelts > 1) + if (VEC_length (linespec_sals, canonical.sals) > 1) { warning (_("Multiple breakpoints were set.\nUse the " "\"delete\" command to delete unwanted breakpoints.")); @@ -8167,13 +7967,13 @@ create_breakpoint (struct gdbarch *gdbarch, return 1; } -/* Set a breakpoint. +/* Set a breakpoint. ARG is a string describing breakpoint address, condition, and thread. FLAG specifies if a breakpoint is hardware on, and if breakpoint is temporary, using BP_HARDWARE_FLAG and BP_TEMPFLAG. */ - + static void break_command_1 (char *arg, int flag, int from_tty) { @@ -8188,13 +7988,13 @@ break_command_1 (char *arg, int flag, int from_tty) tempflag, type_wanted, 0 /* Ignore count */, pending_break_support, - NULL /* breakpoint_ops */, + &bkpt_breakpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */); + 0 /* internal */, + 0); } - /* Helper function for break_command_1 and disassemble_command. */ void @@ -8374,9 +8174,11 @@ resources_needed_ranged_breakpoint (const struct bp_location *bl) ranged breakpoints. */ static enum print_stop_action -print_it_ranged_breakpoint (struct breakpoint *b) +print_it_ranged_breakpoint (bpstat bs) { + struct breakpoint *b = bs->breakpoint_at; struct bp_location *bl = b->loc; + struct ui_out *uiout = current_uiout; gdb_assert (b->type == bp_hardware_breakpoint); @@ -8409,6 +8211,7 @@ print_one_ranged_breakpoint (struct breakpoint *b, { struct bp_location *bl = b->loc; struct value_print_options opts; + struct ui_out *uiout = current_uiout; /* Ranged breakpoints have only one location. */ gdb_assert (bl && bl->next == NULL); @@ -8458,6 +8261,7 @@ static void print_mention_ranged_breakpoint (struct breakpoint *b) { struct bp_location *bl = b->loc; + struct ui_out *uiout = current_uiout; gdb_assert (bl); gdb_assert (b->type == bp_hardware_breakpoint); @@ -8478,22 +8282,12 @@ print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp) { fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string, b->addr_string_range_end); + print_recreate_thread (b, fp); } /* The breakpoint_ops structure to be used in ranged breakpoints. */ -static struct breakpoint_ops ranged_breakpoint_ops = -{ - NULL, /* insert */ - NULL, /* remove */ - breakpoint_hit_ranged_breakpoint, - resources_needed_ranged_breakpoint, - print_it_ranged_breakpoint, - print_one_ranged_breakpoint, - print_one_detail_ranged_breakpoint, - print_mention_ranged_breakpoint, - print_recreate_ranged_breakpoint -}; +static struct breakpoint_ops ranged_breakpoint_ops; /* Find the address where the end of the breakpoint range should be placed, given the SAL of the end of the range. This is so that if @@ -8536,8 +8330,8 @@ break_range_command (char *arg, int from_tty) CORE_ADDR end; struct breakpoint *b; struct symtab_and_line sal_start, sal_end; - struct symtabs_and_lines sals_start, sals_end; struct cleanup *cleanup_bkpt; + struct linespec_sals *lsal_start, *lsal_end; /* We don't support software ranged breakpoints. */ if (target_ranged_break_num_registers () < 0) @@ -8550,75 +8344,66 @@ break_range_command (char *arg, int from_tty) if (can_use_bp < 0) error (_("Hardware breakpoints used exceeds limit.")); + arg = skip_spaces (arg); if (arg == NULL || arg[0] == '\0') error(_("No address range specified.")); - sals_start.sals = NULL; - sals_start.nelts = 0; init_linespec_result (&canonical_start); - while (*arg == ' ' || *arg == '\t') - arg++; - - parse_breakpoint_sals (&arg, &sals_start, &canonical_start); + arg_start = arg; + parse_breakpoint_sals (&arg, &canonical_start); - sal_start = sals_start.sals[0]; - addr_string_start = canonical_start.canonical[0]; - cleanup_bkpt = make_cleanup (xfree, addr_string_start); - xfree (sals_start.sals); - xfree (canonical_start.canonical); + cleanup_bkpt = make_cleanup_destroy_linespec_result (&canonical_start); if (arg[0] != ',') error (_("Too few arguments.")); - else if (sals_start.nelts == 0) + else if (VEC_empty (linespec_sals, canonical_start.sals)) error (_("Could not find location of the beginning of the range.")); - else if (sals_start.nelts != 1) + + lsal_start = VEC_index (linespec_sals, canonical_start.sals, 0); + + if (VEC_length (linespec_sals, canonical_start.sals) > 1 + || lsal_start->sals.nelts != 1) error (_("Cannot create a ranged breakpoint with multiple locations.")); - resolve_sal_pc (&sal_start); + sal_start = lsal_start->sals.sals[0]; + addr_string_start = savestring (arg_start, arg - arg_start); + make_cleanup (xfree, addr_string_start); arg++; /* Skip the comma. */ - while (*arg == ' ' || *arg == '\t') - arg++; + arg = skip_spaces (arg); /* Parse the end location. */ - sals_end.sals = NULL; - sals_end.nelts = 0; init_linespec_result (&canonical_end); arg_start = arg; - /* We call decode_line_1 directly here instead of using + /* We call decode_line_full directly here instead of using parse_breakpoint_sals because we need to specify the start location's symtab and line as the default symtab and line for the end of the range. This makes it possible to have ranges like "foo.c:27, +14", where +14 means 14 lines from the start location. */ - sals_end = decode_line_1 (&arg, 1, sal_start.symtab, sal_start.line, - &canonical_end); - - /* canonical_end can be NULL if it was of the form "*0xdeadbeef". */ - if (canonical_end.canonical == NULL) - canonical_end.canonical = xcalloc (1, sizeof (char **)); - /* Add the string if not present. */ - if (arg_start != arg && canonical_end.canonical[0] == NULL) - canonical_end.canonical[0] = savestring (arg_start, arg - arg_start); - - sal_end = sals_end.sals[0]; - addr_string_end = canonical_end.canonical[0]; - make_cleanup (xfree, addr_string_end); - xfree (sals_end.sals); - xfree (canonical_end.canonical); + decode_line_full (&arg, DECODE_LINE_FUNFIRSTLINE, + sal_start.symtab, sal_start.line, + &canonical_end, NULL, NULL); + + make_cleanup_destroy_linespec_result (&canonical_end); - if (sals_end.nelts == 0) + if (VEC_empty (linespec_sals, canonical_end.sals)) error (_("Could not find location of the end of the range.")); - else if (sals_end.nelts != 1) + + lsal_end = VEC_index (linespec_sals, canonical_end.sals, 0); + if (VEC_length (linespec_sals, canonical_end.sals) > 1 + || lsal_end->sals.nelts != 1) error (_("Cannot create a ranged breakpoint with multiple locations.")); - resolve_sal_pc (&sal_end); + sal_end = lsal_end->sals.sals[0]; + addr_string_end = savestring (arg_start, arg - arg_start); + make_cleanup (xfree, addr_string_end); end = find_breakpoint_range_end (sal_end); if (sal_start.pc > end) - error (_("Invalid address range, end preceeds start.")); + error (_("Invalid address range, end precedes start.")); length = end - sal_start.pc + 1; if (length < 0) @@ -8637,18 +8422,18 @@ break_range_command (char *arg, int from_tty) /* Now set up the breakpoint. */ b = set_raw_breakpoint (get_current_arch (), sal_start, - bp_hardware_breakpoint); + bp_hardware_breakpoint, &ranged_breakpoint_ops); set_breakpoint_count (breakpoint_count + 1); b->number = breakpoint_count; b->disposition = disp_donttouch; - b->addr_string = addr_string_start; - b->addr_string_range_end = addr_string_end; - b->ops = &ranged_breakpoint_ops; + b->addr_string = xstrdup (addr_string_start); + b->addr_string_range_end = xstrdup (addr_string_end); b->loc->length = length; - discard_cleanups (cleanup_bkpt); + do_cleanups (cleanup_bkpt); mention (b); + observer_notify_breakpoint_created (b); update_global_location_list (1); } @@ -8761,15 +8546,67 @@ watchpoint_exp_is_const (const struct expression *exp) return 1; } +/* Implement the "dtor" breakpoint_ops method for watchpoints. */ + +static void +dtor_watchpoint (struct breakpoint *self) +{ + struct watchpoint *w = (struct watchpoint *) self; + + xfree (w->cond_exp); + xfree (w->exp); + xfree (w->exp_string); + xfree (w->exp_string_reparse); + value_free (w->val); + + base_breakpoint_ops.dtor (self); +} + +/* Implement the "re_set" breakpoint_ops method for watchpoints. */ + +static void +re_set_watchpoint (struct breakpoint *b) +{ + struct watchpoint *w = (struct watchpoint *) b; + + /* Watchpoint can be either on expression using entirely global + variables, or it can be on local variables. + + Watchpoints of the first kind are never auto-deleted, and even + persist across program restarts. Since they can use variables + from shared libraries, we need to reparse expression as libraries + are loaded and unloaded. + + Watchpoints on local variables can also change meaning as result + of solib event. For example, if a watchpoint uses both a local + and a global variables in expression, it's a local watchpoint, + but unloading of a shared library will make the expression + invalid. This is not a very common use case, but we still + re-evaluate expression, to avoid surprises to the user. + + Note that for local watchpoints, we re-evaluate it only if + watchpoints frame id is still valid. If it's not, it means the + watchpoint is out of scope and will be deleted soon. In fact, + I'm not sure we'll ever be called in this case. + + If a local watchpoint's frame id is still valid, then + w->exp_valid_block is likewise valid, and we can safely use it. + + Don't do anything about disabled watchpoints, since they will be + reevaluated again when enabled. */ + update_watchpoint (w, 1 /* reparse */); +} + /* Implement the "insert" breakpoint_ops method for hardware watchpoints. */ static int insert_watchpoint (struct bp_location *bl) { - int length = bl->owner->exact? 1 : bl->length; + struct watchpoint *w = (struct watchpoint *) bl->owner; + int length = w->exact ? 1 : bl->length; return target_insert_watchpoint (bl->address, length, bl->watchpoint_type, - bl->owner->cond_exp); + w->cond_exp); } /* Implement the "remove" breakpoint_ops method for hardware watchpoints. */ @@ -8777,10 +8614,39 @@ insert_watchpoint (struct bp_location *bl) static int remove_watchpoint (struct bp_location *bl) { - int length = bl->owner->exact? 1 : bl->length; + struct watchpoint *w = (struct watchpoint *) bl->owner; + int length = w->exact ? 1 : bl->length; return target_remove_watchpoint (bl->address, length, bl->watchpoint_type, - bl->owner->cond_exp); + w->cond_exp); +} + +static int +breakpoint_hit_watchpoint (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) +{ + struct breakpoint *b = bl->owner; + struct watchpoint *w = (struct watchpoint *) b; + + /* Continuable hardware watchpoints are treated as non-existent if the + reason we stopped wasn't a hardware watchpoint (we didn't stop on + some data address). Otherwise gdb won't stop on a break instruction + in the code (not from a breakpoint) when a hardware watchpoint has + been defined. Also skip watchpoints which we know did not trigger + (did not match the data address). */ + if (is_hardware_watchpoint (b) + && w->watchpoint_triggered == watch_triggered_no) + return 0; + + return 1; +} + +static void +check_status_watchpoint (bpstat bs) +{ + gdb_assert (is_watchpoint (bs->breakpoint_at)); + + bpstat_check_watchpoint (bs); } /* Implement the "resources_needed" breakpoint_ops method for @@ -8789,197 +8655,561 @@ remove_watchpoint (struct bp_location *bl) static int resources_needed_watchpoint (const struct bp_location *bl) { - int length = bl->owner->exact? 1 : bl->length; + struct watchpoint *w = (struct watchpoint *) bl->owner; + int length = w->exact? 1 : bl->length; return target_region_ok_for_hw_watchpoint (bl->address, length); } -/* The breakpoint_ops structure to be used in hardware watchpoints. */ - -static struct breakpoint_ops watchpoint_breakpoint_ops = -{ - insert_watchpoint, - remove_watchpoint, - NULL, /* breakpoint_hit */ - resources_needed_watchpoint, - NULL, /* print_it */ - NULL, /* print_one */ - NULL, /* print_one_detail */ - NULL, /* print_mention */ - NULL /* print_recreate */ -}; +/* Implement the "works_in_software_mode" breakpoint_ops method for + hardware watchpoints. */ -/* accessflag: hw_write: watch write, - hw_read: watch read, - hw_access: watch access (read or write) */ -static void -watch_command_1 (char *arg, int accessflag, int from_tty, - int just_location, int internal) +static int +works_in_software_mode_watchpoint (const struct breakpoint *b) { - struct breakpoint *b, *scope_breakpoint = NULL; - struct expression *exp; - struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL; - struct value *val, *mark, *result; - struct frame_info *frame; - char *exp_start = NULL; - char *exp_end = NULL; - char *tok, *id_tok_start, *end_tok; - int toklen; - char *cond_start = NULL; - char *cond_end = NULL; - int i, other_type_used, target_resources_ok = 0; - enum bptype bp_type; - int reg_cnt = 0; - int thread = -1; - int pc = 0; + /* Read and access watchpoints only work with hardware support. */ + return b->type == bp_watchpoint || b->type == bp_hardware_watchpoint; +} - /* Make sure that we actually have parameters to parse. */ - if (arg != NULL && arg[0] != '\0') - { - toklen = strlen (arg); /* Size of argument list. */ +static enum print_stop_action +print_it_watchpoint (bpstat bs) +{ + struct cleanup *old_chain; + struct breakpoint *b; + const struct bp_location *bl; + struct ui_stream *stb; + enum print_stop_action result; + struct watchpoint *w; + struct ui_out *uiout = current_uiout; - /* Points tok to the end of the argument list. */ - tok = arg + toklen - 1; + gdb_assert (bs->bp_location_at != NULL); - /* Go backwards in the parameters list. Skip the last - parameter. If we're expecting a 'thread ' - parameter, this should be the thread identifier. */ - while (tok > arg && (*tok == ' ' || *tok == '\t')) - tok--; - while (tok > arg && (*tok != ' ' && *tok != '\t')) - tok--; + bl = bs->bp_location_at; + b = bs->breakpoint_at; + w = (struct watchpoint *) b; - /* Points end_tok to the beginning of the last token. */ - id_tok_start = tok + 1; + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); - /* Go backwards in the parameters list. Skip one more - parameter. If we're expecting a 'thread ' - parameter, we should reach a "thread" token. */ - while (tok > arg && (*tok == ' ' || *tok == '\t')) - tok--; + switch (b->type) + { + case bp_watchpoint: + case bp_hardware_watchpoint: + annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER)); + mention (b); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nOld value = "); + watchpoint_value_print (bs->old_val, stb->stream); + ui_out_field_stream (uiout, "old", stb); + ui_out_text (uiout, "\nNew value = "); + watchpoint_value_print (w->val, stb->stream); + ui_out_field_stream (uiout, "new", stb); + ui_out_text (uiout, "\n"); + /* More than one watchpoint may have been triggered. */ + result = PRINT_UNKNOWN; + break; - end_tok = tok; + case bp_read_watchpoint: + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER)); + mention (b); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nValue = "); + watchpoint_value_print (w->val, stb->stream); + ui_out_field_stream (uiout, "value", stb); + ui_out_text (uiout, "\n"); + result = PRINT_UNKNOWN; + break; - while (tok > arg && (*tok != ' ' && *tok != '\t')) - tok--; + case bp_access_watchpoint: + if (bs->old_val != NULL) + { + annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); + mention (b); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nOld value = "); + watchpoint_value_print (bs->old_val, stb->stream); + ui_out_field_stream (uiout, "old", stb); + ui_out_text (uiout, "\nNew value = "); + } + else + { + mention (b); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); + make_cleanup_ui_out_tuple_begin_end (uiout, "value"); + ui_out_text (uiout, "\nValue = "); + } + watchpoint_value_print (w->val, stb->stream); + ui_out_field_stream (uiout, "new", stb); + ui_out_text (uiout, "\n"); + result = PRINT_UNKNOWN; + break; + default: + result = PRINT_UNKNOWN; + } - /* Move the pointer forward to skip the whitespace and - calculate the length of the token. */ - tok++; - toklen = end_tok - tok; + do_cleanups (old_chain); + return result; +} - if (toklen >= 1 && strncmp (tok, "thread", toklen) == 0) - { - /* At this point we've found a "thread" token, which means - the user is trying to set a watchpoint that triggers - only in a specific thread. */ - char *endp; - - /* Extract the thread ID from the next token. */ - thread = strtol (id_tok_start, &endp, 0); - - /* Check if the user provided a valid numeric value for the - thread ID. */ - if (*endp != ' ' && *endp != '\t' && *endp != '\0') - error (_("Invalid thread ID specification %s."), id_tok_start); - - /* Check if the thread actually exists. */ - if (!valid_thread_id (thread)) - error (_("Unknown thread %d."), thread); - - /* Truncate the string and get rid of the thread - parameter before the parameter list is parsed by the - evaluate_expression() function. */ - *tok = '\0'; - } - } +/* Implement the "print_mention" breakpoint_ops method for hardware + watchpoints. */ - /* Parse the rest of the arguments. */ - innermost_block = NULL; - exp_start = arg; - exp = parse_exp_1 (&arg, 0, 0); - exp_end = arg; - /* Remove trailing whitespace from the expression before saving it. - This makes the eventual display of the expression string a bit - prettier. */ - while (exp_end > exp_start && (exp_end[-1] == ' ' || exp_end[-1] == '\t')) - --exp_end; +static void +print_mention_watchpoint (struct breakpoint *b) +{ + struct cleanup *ui_out_chain; + struct watchpoint *w = (struct watchpoint *) b; + struct ui_out *uiout = current_uiout; - /* Checking if the expression is not constant. */ - if (watchpoint_exp_is_const (exp)) + switch (b->type) { - int len; - - len = exp_end - exp_start; - while (len > 0 && isspace (exp_start[len - 1])) - len--; - error (_("Cannot watch constant value `%.*s'."), len, exp_start); + case bp_watchpoint: + ui_out_text (uiout, "Watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); + break; + case bp_hardware_watchpoint: + ui_out_text (uiout, "Hardware watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); + break; + case bp_read_watchpoint: + ui_out_text (uiout, "Hardware read watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt"); + break; + case bp_access_watchpoint: + ui_out_text (uiout, "Hardware access (read/write) watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt"); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid hardware watchpoint type.")); } - exp_valid_block = innermost_block; - mark = value_mark (); - fetch_subexp_value (exp, &pc, &val, &result, NULL); + ui_out_field_int (uiout, "number", b->number); + ui_out_text (uiout, ": "); + ui_out_field_string (uiout, "exp", w->exp_string); + do_cleanups (ui_out_chain); +} - if (just_location) +/* Implement the "print_recreate" breakpoint_ops method for + watchpoints. */ + +static void +print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp) +{ + struct watchpoint *w = (struct watchpoint *) b; + + switch (b->type) { - exp_valid_block = NULL; - val = value_addr (result); - release_value (val); - value_free_to_mark (mark); + case bp_watchpoint: + case bp_hardware_watchpoint: + fprintf_unfiltered (fp, "watch"); + break; + case bp_read_watchpoint: + fprintf_unfiltered (fp, "rwatch"); + break; + case bp_access_watchpoint: + fprintf_unfiltered (fp, "awatch"); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid watchpoint type.")); } - else if (val != NULL) - release_value (val); - tok = skip_spaces (arg); - end_tok = skip_to_space (tok); + fprintf_unfiltered (fp, " %s", w->exp_string); + print_recreate_thread (b, fp); +} - toklen = end_tok - tok; - if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) - { - struct expression *cond; +/* The breakpoint_ops structure to be used in hardware watchpoints. */ - innermost_block = NULL; - tok = cond_start = end_tok + 1; - cond = parse_exp_1 (&tok, 0, 0); +static struct breakpoint_ops watchpoint_breakpoint_ops; - /* The watchpoint expression may not be local, but the condition - may still be. E.g.: `watch global if local > 0'. */ - cond_exp_valid_block = innermost_block; +/* Implement the "insert" breakpoint_ops method for + masked hardware watchpoints. */ - xfree (cond); - cond_end = tok; - } - if (*tok) - error (_("Junk at end of command.")); +static int +insert_masked_watchpoint (struct bp_location *bl) +{ + struct watchpoint *w = (struct watchpoint *) bl->owner; - if (accessflag == hw_read) - bp_type = bp_read_watchpoint; - else if (accessflag == hw_access) - bp_type = bp_access_watchpoint; - else - bp_type = bp_hardware_watchpoint; + return target_insert_mask_watchpoint (bl->address, w->hw_wp_mask, + bl->watchpoint_type); +} + +/* Implement the "remove" breakpoint_ops method for + masked hardware watchpoints. */ + +static int +remove_masked_watchpoint (struct bp_location *bl) +{ + struct watchpoint *w = (struct watchpoint *) bl->owner; + + return target_remove_mask_watchpoint (bl->address, w->hw_wp_mask, + bl->watchpoint_type); +} + +/* Implement the "resources_needed" breakpoint_ops method for + masked hardware watchpoints. */ + +static int +resources_needed_masked_watchpoint (const struct bp_location *bl) +{ + struct watchpoint *w = (struct watchpoint *) bl->owner; + + return target_masked_watch_num_registers (bl->address, w->hw_wp_mask); +} + +/* Implement the "works_in_software_mode" breakpoint_ops method for + masked hardware watchpoints. */ + +static int +works_in_software_mode_masked_watchpoint (const struct breakpoint *b) +{ + return 0; +} + +/* Implement the "print_it" breakpoint_ops method for + masked hardware watchpoints. */ + +static enum print_stop_action +print_it_masked_watchpoint (bpstat bs) +{ + struct breakpoint *b = bs->breakpoint_at; + struct ui_out *uiout = current_uiout; - reg_cnt = can_use_hardware_watchpoint (val, target_exact_watchpoints); - if (reg_cnt == 0 && bp_type != bp_hardware_watchpoint) - error (_("Expression cannot be implemented with read/access watchpoint.")); - if (reg_cnt != 0) + /* Masked watchpoints have only one location. */ + gdb_assert (b->loc && b->loc->next == NULL); + + switch (b->type) { - i = hw_watchpoint_used_count (bp_type, &other_type_used); - target_resources_ok = - target_can_use_hardware_watchpoint (bp_type, i + reg_cnt, - other_type_used); - if (target_resources_ok == 0 && bp_type != bp_hardware_watchpoint) - error (_("Target does not support this type of hardware watchpoint.")); + case bp_hardware_watchpoint: + annotate_watchpoint (b->number); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER)); + break; + + case bp_read_watchpoint: + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER)); + break; + + case bp_access_watchpoint: + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER)); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid hardware watchpoint type.")); + } + + mention (b); + ui_out_text (uiout, _("\n\ +Check the underlying instruction at PC for the memory\n\ +address and value which triggered this watchpoint.\n")); + ui_out_text (uiout, "\n"); + + /* More than one watchpoint may have been triggered. */ + return PRINT_UNKNOWN; +} + +/* Implement the "print_one_detail" breakpoint_ops method for + masked hardware watchpoints. */ + +static void +print_one_detail_masked_watchpoint (const struct breakpoint *b, + struct ui_out *uiout) +{ + struct watchpoint *w = (struct watchpoint *) b; + + /* Masked watchpoints have only one location. */ + gdb_assert (b->loc && b->loc->next == NULL); + + ui_out_text (uiout, "\tmask "); + ui_out_field_core_addr (uiout, "mask", b->loc->gdbarch, w->hw_wp_mask); + ui_out_text (uiout, "\n"); +} + +/* Implement the "print_mention" breakpoint_ops method for + masked hardware watchpoints. */ + +static void +print_mention_masked_watchpoint (struct breakpoint *b) +{ + struct watchpoint *w = (struct watchpoint *) b; + struct ui_out *uiout = current_uiout; + struct cleanup *ui_out_chain; + + switch (b->type) + { + case bp_hardware_watchpoint: + ui_out_text (uiout, "Masked hardware watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "wpt"); + break; + case bp_read_watchpoint: + ui_out_text (uiout, "Masked hardware read watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-rwpt"); + break; + case bp_access_watchpoint: + ui_out_text (uiout, "Masked hardware access (read/write) watchpoint "); + ui_out_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "hw-awpt"); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid hardware watchpoint type.")); + } + + ui_out_field_int (uiout, "number", b->number); + ui_out_text (uiout, ": "); + ui_out_field_string (uiout, "exp", w->exp_string); + do_cleanups (ui_out_chain); +} + +/* Implement the "print_recreate" breakpoint_ops method for + masked hardware watchpoints. */ + +static void +print_recreate_masked_watchpoint (struct breakpoint *b, struct ui_file *fp) +{ + struct watchpoint *w = (struct watchpoint *) b; + char tmp[40]; + + switch (b->type) + { + case bp_hardware_watchpoint: + fprintf_unfiltered (fp, "watch"); + break; + case bp_read_watchpoint: + fprintf_unfiltered (fp, "rwatch"); + break; + case bp_access_watchpoint: + fprintf_unfiltered (fp, "awatch"); + break; + default: + internal_error (__FILE__, __LINE__, + _("Invalid hardware watchpoint type.")); + } + + sprintf_vma (tmp, w->hw_wp_mask); + fprintf_unfiltered (fp, " %s mask 0x%s", w->exp_string, tmp); + print_recreate_thread (b, fp); +} + +/* The breakpoint_ops structure to be used in masked hardware watchpoints. */ + +static struct breakpoint_ops masked_watchpoint_breakpoint_ops; + +/* Tell whether the given watchpoint is a masked hardware watchpoint. */ + +static int +is_masked_watchpoint (const struct breakpoint *b) +{ + return b->ops == &masked_watchpoint_breakpoint_ops; +} + +/* accessflag: hw_write: watch write, + hw_read: watch read, + hw_access: watch access (read or write) */ +static void +watch_command_1 (char *arg, int accessflag, int from_tty, + int just_location, int internal) +{ + volatile struct gdb_exception e; + struct breakpoint *b, *scope_breakpoint = NULL; + struct expression *exp; + struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL; + struct value *val, *mark, *result; + struct frame_info *frame; + char *exp_start = NULL; + char *exp_end = NULL; + char *tok, *end_tok; + int toklen = -1; + char *cond_start = NULL; + char *cond_end = NULL; + enum bptype bp_type; + int thread = -1; + int pc = 0; + /* Flag to indicate whether we are going to use masks for + the hardware watchpoint. */ + int use_mask = 0; + CORE_ADDR mask = 0; + struct watchpoint *w; + + /* Make sure that we actually have parameters to parse. */ + if (arg != NULL && arg[0] != '\0') + { + char *value_start; + + /* Look for "parameter value" pairs at the end + of the arguments string. */ + for (tok = arg + strlen (arg) - 1; tok > arg; tok--) + { + /* Skip whitespace at the end of the argument list. */ + while (tok > arg && (*tok == ' ' || *tok == '\t')) + tok--; + + /* Find the beginning of the last token. + This is the value of the parameter. */ + while (tok > arg && (*tok != ' ' && *tok != '\t')) + tok--; + value_start = tok + 1; + + /* Skip whitespace. */ + while (tok > arg && (*tok == ' ' || *tok == '\t')) + tok--; + + end_tok = tok; + + /* Find the beginning of the second to last token. + This is the parameter itself. */ + while (tok > arg && (*tok != ' ' && *tok != '\t')) + tok--; + tok++; + toklen = end_tok - tok + 1; + + if (toklen == 6 && !strncmp (tok, "thread", 6)) + { + /* At this point we've found a "thread" token, which means + the user is trying to set a watchpoint that triggers + only in a specific thread. */ + char *endp; + + if (thread != -1) + error(_("You can specify only one thread.")); + + /* Extract the thread ID from the next token. */ + thread = strtol (value_start, &endp, 0); + + /* Check if the user provided a valid numeric value for the + thread ID. */ + if (*endp != ' ' && *endp != '\t' && *endp != '\0') + error (_("Invalid thread ID specification %s."), value_start); + + /* Check if the thread actually exists. */ + if (!valid_thread_id (thread)) + error (_("Unknown thread %d."), thread); + } + else if (toklen == 4 && !strncmp (tok, "mask", 4)) + { + /* We've found a "mask" token, which means the user wants to + create a hardware watchpoint that is going to have the mask + facility. */ + struct value *mask_value, *mark; + + if (use_mask) + error(_("You can specify only one mask.")); + + use_mask = just_location = 1; + + mark = value_mark (); + mask_value = parse_to_comma_and_eval (&value_start); + mask = value_as_address (mask_value); + value_free_to_mark (mark); + } + else + /* We didn't recognize what we found. We should stop here. */ + break; + + /* Truncate the string and get rid of the "parameter value" pair before + the arguments string is parsed by the parse_exp_1 function. */ + *tok = '\0'; + } + } + + /* Parse the rest of the arguments. */ + innermost_block = NULL; + exp_start = arg; + exp = parse_exp_1 (&arg, 0, 0); + exp_end = arg; + /* Remove trailing whitespace from the expression before saving it. + This makes the eventual display of the expression string a bit + prettier. */ + while (exp_end > exp_start && (exp_end[-1] == ' ' || exp_end[-1] == '\t')) + --exp_end; + + /* Checking if the expression is not constant. */ + if (watchpoint_exp_is_const (exp)) + { + int len; + + len = exp_end - exp_start; + while (len > 0 && isspace (exp_start[len - 1])) + len--; + error (_("Cannot watch constant value `%.*s'."), len, exp_start); + } + + exp_valid_block = innermost_block; + mark = value_mark (); + fetch_subexp_value (exp, &pc, &val, &result, NULL); + + if (just_location) + { + int ret; + + exp_valid_block = NULL; + val = value_addr (result); + release_value (val); + value_free_to_mark (mark); + + if (use_mask) + { + ret = target_masked_watch_num_registers (value_as_address (val), + mask); + if (ret == -1) + error (_("This target does not support masked watchpoints.")); + else if (ret == -2) + error (_("Invalid mask or memory region.")); + } + } + else if (val != NULL) + release_value (val); + + tok = skip_spaces (arg); + end_tok = skip_to_space (tok); + + toklen = end_tok - tok; + if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) + { + struct expression *cond; - if (target_resources_ok < 0 && bp_type != bp_hardware_watchpoint) - error (_("Target can only support one kind " - "of HW watchpoint at a time.")); + innermost_block = NULL; + tok = cond_start = end_tok + 1; + cond = parse_exp_1 (&tok, 0, 0); + + /* The watchpoint expression may not be local, but the condition + may still be. E.g.: `watch global if local > 0'. */ + cond_exp_valid_block = innermost_block; + + xfree (cond); + cond_end = tok; } + if (*tok) + error (_("Junk at end of command.")); - /* Change the type of breakpoint to an ordinary watchpoint if a - hardware watchpoint could not be set. */ - if (!reg_cnt || target_resources_ok <= 0) - bp_type = bp_watchpoint; + if (accessflag == hw_read) + bp_type = bp_read_watchpoint; + else if (accessflag == hw_access) + bp_type = bp_access_watchpoint; + else + bp_type = bp_hardware_watchpoint; frame = block_innermost_frame (exp_valid_block); @@ -8994,7 +9224,8 @@ watch_command_1 (char *arg, int accessflag, int from_tty, scope_breakpoint = create_internal_breakpoint (frame_unwind_caller_arch (frame), frame_unwind_caller_pc (frame), - bp_watchpoint_scope); + bp_watchpoint_scope, + &momentary_breakpoint_ops); scope_breakpoint->enable_state = bp_enabled; @@ -9017,13 +9248,21 @@ watch_command_1 (char *arg, int accessflag, int from_tty, } /* Now set up the breakpoint. */ - b = set_raw_breakpoint_without_location (NULL, bp_type); - set_breakpoint_number (internal, b); + + w = XCNEW (struct watchpoint); + b = &w->base; + if (use_mask) + init_raw_breakpoint_without_location (b, NULL, bp_type, + &masked_watchpoint_breakpoint_ops); + else + init_raw_breakpoint_without_location (b, NULL, bp_type, + &watchpoint_breakpoint_ops); b->thread = thread; b->disposition = disp_donttouch; - b->exp = exp; - b->exp_valid_block = exp_valid_block; - b->cond_exp_valid_block = cond_exp_valid_block; + b->pspace = current_program_space; + w->exp = exp; + w->exp_valid_block = exp_valid_block; + w->cond_exp_valid_block = cond_exp_valid_block; if (just_location) { struct type *t = value_type (val); @@ -9033,25 +9272,28 @@ watch_command_1 (char *arg, int accessflag, int from_tty, t = check_typedef (TYPE_TARGET_TYPE (check_typedef (t))); name = type_to_string (t); - b->exp_string_reparse = xstrprintf ("* (%s *) %s", name, + w->exp_string_reparse = xstrprintf ("* (%s *) %s", name, core_addr_to_string (addr)); xfree (name); - b->exp_string = xstrprintf ("-location %.*s", + w->exp_string = xstrprintf ("-location %.*s", (int) (exp_end - exp_start), exp_start); /* The above expression is in C. */ b->language = language_c; } else - b->exp_string = savestring (exp_start, exp_end - exp_start); - b->val = val; - b->val_valid = 1; - b->ops = &watchpoint_breakpoint_ops; + w->exp_string = savestring (exp_start, exp_end - exp_start); - /* Use an exact watchpoint when there's only one memory region to be - watched, and only one debug register is needed to watch it. */ - b->exact = target_exact_watchpoints && reg_cnt == 1; + if (use_mask) + { + w->hw_wp_mask = mask; + } + else + { + w->val = val; + w->val_valid = 1; + } if (cond_start) b->cond_string = savestring (cond_start, cond_end - cond_start); @@ -9060,13 +9302,13 @@ watch_command_1 (char *arg, int accessflag, int from_tty, if (frame) { - b->watchpoint_frame = get_frame_id (frame); - b->watchpoint_thread = inferior_ptid; + w->watchpoint_frame = get_frame_id (frame); + w->watchpoint_thread = inferior_ptid; } else { - b->watchpoint_frame = null_frame_id; - b->watchpoint_thread = null_ptid; + w->watchpoint_frame = null_frame_id; + w->watchpoint_thread = null_ptid; } if (scope_breakpoint != NULL) @@ -9080,27 +9322,26 @@ watch_command_1 (char *arg, int accessflag, int from_tty, if (!just_location) value_free_to_mark (mark); - /* Finally update the new watchpoint. This creates the locations - that should be inserted. */ - update_watchpoint (b, 1); - if (internal) - /* Do not mention breakpoints with a negative number, but do - notify observers. */ - observer_notify_breakpoint_created (b->number); - else - mention (b); - update_global_location_list (1); + TRY_CATCH (e, RETURN_MASK_ALL) + { + /* Finally update the new watchpoint. This creates the locations + that should be inserted. */ + update_watchpoint (w, 1); + } + if (e.reason < 0) + { + delete_breakpoint (b); + throw_exception (e); + } + + install_breakpoint (internal, b, 1); } /* Return count of debug registers needed to watch the given expression. - If EXACT_WATCHPOINTS is 1, then consider that only the address of - the start of the watched region will be monitored (i.e., all accesses - will be aligned). This uses less debug registers on some targets. - If the watchpoint cannot be handled in hardware return zero. */ static int -can_use_hardware_watchpoint (struct value *v, int exact_watchpoints) +can_use_hardware_watchpoint (struct value *v) { int found_memory_cnt = 0; struct value *head = v; @@ -9156,7 +9397,7 @@ can_use_hardware_watchpoint (struct value *v, int exact_watchpoints) int len; int num_regs; - len = (exact_watchpoints + len = (target_exact_watchpoints && is_scalar_type_recursive (vtype))? 1 : TYPE_LENGTH (value_type (v)); @@ -9268,7 +9509,7 @@ struct until_break_command_continuation_args care of cleaning up the temporary breakpoints set up by the until command. */ static void -until_break_command_continuation (void *arg) +until_break_command_continuation (void *arg, int err) { struct until_break_command_continuation_args *a = arg; @@ -9295,11 +9536,13 @@ until_break_command (char *arg, int from_tty, int anywhere) /* Set a breakpoint where the user wants it and at return from this function. */ - if (default_breakpoint_valid) - sals = decode_line_1 (&arg, 1, default_breakpoint_symtab, - default_breakpoint_line, NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE, + get_last_displayed_symtab (), + get_last_displayed_line ()); else - sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL); + sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE, + (struct symtab *) NULL, 0); if (sals.nelts != 1) error (_("Couldn't get information on specified line.")); @@ -9463,6 +9706,7 @@ static void catch_exec_command_1 (char *arg, int from_tty, struct cmd_list_element *command) { + struct exec_catchpoint *c; struct gdbarch *gdbarch = get_current_arch (); int tempflag; char *cond_string = NULL; @@ -9483,15 +9727,19 @@ catch_exec_command_1 (char *arg, int from_tty, if ((*arg != '\0') && !isspace (*arg)) error (_("Junk at end of arguments.")); - /* If this target supports it, create an exec catchpoint - and enable reporting of such events. */ - create_catchpoint (gdbarch, tempflag, cond_string, - &catch_exec_breakpoint_ops); + c = XNEW (struct exec_catchpoint); + init_catchpoint (&c->base, gdbarch, tempflag, cond_string, + &catch_exec_breakpoint_ops); + c->exec_pathname = NULL; + + install_breakpoint (0, &c->base, 1); } static enum print_stop_action -print_exception_catchpoint (struct breakpoint *b) +print_it_exception_catchpoint (bpstat bs) { + struct ui_out *uiout = current_uiout; + struct breakpoint *b = bs->breakpoint_at; int bp_temp, bp_throw; annotate_catchpoint (b->number); @@ -9525,6 +9773,7 @@ print_one_exception_catchpoint (struct breakpoint *b, struct bp_location **last_loc) { struct value_print_options opts; + struct ui_out *uiout = current_uiout; get_user_print_options (&opts); if (opts.addressprint) @@ -9548,6 +9797,7 @@ print_one_exception_catchpoint (struct breakpoint *b, static void print_mention_exception_catchpoint (struct breakpoint *b) { + struct ui_out *uiout = current_uiout; int bp_temp; int bp_throw; @@ -9574,19 +9824,10 @@ print_recreate_exception_catchpoint (struct breakpoint *b, bp_throw = strstr (b->addr_string, "throw") != NULL; fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch "); fprintf_unfiltered (fp, bp_throw ? "throw" : "catch"); + print_recreate_thread (b, fp); } -static struct breakpoint_ops gnu_v3_exception_catchpoint_ops = { - NULL, /* insert */ - NULL, /* remove */ - NULL, /* breakpoint_hit */ - NULL, /* resources_needed */ - print_exception_catchpoint, - print_one_exception_catchpoint, - NULL, /* print_one_detail */ - print_mention_exception_catchpoint, - print_recreate_exception_catchpoint -}; +static struct breakpoint_ops gnu_v3_exception_catchpoint_ops; static int handle_gnu_v3_exceptions (int tempflag, char *cond_string, @@ -9607,7 +9848,8 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string, AUTO_BOOLEAN_TRUE /* pending */, &gnu_v3_exception_catchpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */); + 0 /* internal */, + 0); return 1; } @@ -9659,21 +9901,15 @@ catch_throw_command (char *arg, int from_tty, struct cmd_list_element *command) catch_exception_command_1 (EX_EVENT_THROW, arg, tempflag, from_tty); } -/* Create a breakpoint struct for Ada exception catchpoints. */ - -static void -create_ada_exception_breakpoint (struct gdbarch *gdbarch, - struct symtab_and_line sal, - char *addr_string, - char *exp_string, - char *cond_string, - struct expression *cond, - struct breakpoint_ops *ops, - int tempflag, - int from_tty) +void +init_ada_exception_breakpoint (struct breakpoint *b, + struct gdbarch *gdbarch, + struct symtab_and_line sal, + char *addr_string, + const struct breakpoint_ops *ops, + int tempflag, + int from_tty) { - struct breakpoint *b; - if (from_tty) { struct gdbarch *loc_gdbarch = get_sal_arch (sal); @@ -9687,62 +9923,17 @@ create_ada_exception_breakpoint (struct gdbarch *gdbarch, used for different exception names will use the same address. In this case, a "breakpoint ... also set at..." warning is unproductive. Besides, the warning phrasing is also a bit - inapropriate, we should use the word catchpoint, and tell + inappropriate, we should use the word catchpoint, and tell the user what type of catchpoint it is. The above is good enough for now, though. */ } - b = set_raw_breakpoint (gdbarch, sal, bp_breakpoint); - set_breakpoint_count (breakpoint_count + 1); + init_raw_breakpoint (b, gdbarch, sal, bp_breakpoint, ops); b->enable_state = bp_enabled; b->disposition = tempflag ? disp_del : disp_donttouch; - b->number = breakpoint_count; - b->ignore_count = 0; - b->loc->cond = cond; b->addr_string = addr_string; b->language = language_ada; - b->cond_string = cond_string; - b->exp_string = exp_string; - b->thread = -1; - b->ops = ops; - - mention (b); - update_global_location_list (1); -} - -/* Implement the "catch exception" command. */ - -static void -catch_ada_exception_command (char *arg, int from_tty, - struct cmd_list_element *command) -{ - struct gdbarch *gdbarch = get_current_arch (); - int tempflag; - struct symtab_and_line sal; - char *addr_string = NULL; - char *exp_string = NULL; - char *cond_string = NULL; - struct expression *cond = NULL; - struct breakpoint_ops *ops = NULL; - - tempflag = get_cmd_context (command) == CATCH_TEMPORARY; - - if (!arg) - arg = ""; - sal = ada_decode_exception_location (arg, &addr_string, &exp_string, - &cond_string, &cond, &ops); - create_ada_exception_breakpoint (gdbarch, sal, addr_string, exp_string, - cond_string, cond, ops, tempflag, - from_tty); -} - -/* Cleanup function for a syscall filter list. */ -static void -clean_up_filters (void *arg) -{ - VEC(int) *iter = *(VEC(int) **) arg; - VEC_free (int, iter); } /* Splits the argument using space as delimiter. Returns an xmalloc'd @@ -9751,7 +9942,7 @@ static VEC(int) * catch_syscall_split_args (char *arg) { VEC(int) *result = NULL; - struct cleanup *cleanup = make_cleanup (clean_up_filters, &result); + struct cleanup *cleanup = make_cleanup (VEC_cleanup (int), &result); while (*arg != '\0') { @@ -9835,27 +10026,6 @@ this architecture yet.")); &catch_syscall_breakpoint_ops); } -/* Implement the "catch assert" command. */ - -static void -catch_assert_command (char *arg, int from_tty, - struct cmd_list_element *command) -{ - struct gdbarch *gdbarch = get_current_arch (); - int tempflag; - struct symtab_and_line sal; - char *addr_string = NULL; - struct breakpoint_ops *ops = NULL; - - tempflag = get_cmd_context (command) == CATCH_TEMPORARY; - - if (!arg) - arg = ""; - sal = ada_decode_assert_location (arg, &addr_string, &ops); - create_ada_exception_breakpoint (gdbarch, sal, addr_string, NULL, NULL, NULL, - ops, tempflag, from_tty); -} - static void catch_command (char *arg, int from_tty) { @@ -9869,22 +10039,46 @@ tcatch_command (char *arg, int from_tty) error (_("Catch requires an event name.")); } +/* A qsort comparison function that sorts breakpoints in order. */ + +static int +compare_breakpoints (const void *a, const void *b) +{ + const breakpoint_p *ba = a; + uintptr_t ua = (uintptr_t) *ba; + const breakpoint_p *bb = b; + uintptr_t ub = (uintptr_t) *bb; + + if ((*ba)->number < (*bb)->number) + return -1; + else if ((*ba)->number > (*bb)->number) + return 1; + + /* Now sort by address, in case we see, e..g, two breakpoints with + the number 0. */ + if (ua < ub) + return -1; + return ub > ub ? 1 : 0; +} + /* Delete breakpoints by address or line. */ static void clear_command (char *arg, int from_tty) { - struct breakpoint *b; + struct breakpoint *b, *prev; VEC(breakpoint_p) *found = 0; int ix; int default_match; struct symtabs_and_lines sals; struct symtab_and_line sal; int i; + struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); if (arg) { - sals = decode_line_spec (arg, 1); + sals = decode_line_spec (arg, (DECODE_LINE_FUNFIRSTLINE + | DECODE_LINE_LIST_MODE)); default_match = 0; } else @@ -9893,10 +10087,11 @@ clear_command (char *arg, int from_tty) xmalloc (sizeof (struct symtab_and_line)); make_cleanup (xfree, sals.sals); init_sal (&sal); /* Initialize to zeroes. */ - sal.line = default_breakpoint_line; - sal.symtab = default_breakpoint_symtab; - sal.pc = default_breakpoint_address; - sal.pspace = default_breakpoint_pspace; + + /* Set sal's line, symtab, pc, and pspace to the values + corresponding to the last call to print_frame_info. If the + codepoint is not valid, this will set all the fields to 0. */ + get_last_displayed_sal (&sal); if (sal.symtab == 0) error (_("No source file specified.")); @@ -9929,6 +10124,7 @@ clear_command (char *arg, int from_tty) breakpoint. */ found = NULL; + make_cleanup (VEC_cleanup (breakpoint_p), &found); for (i = 0; i < sals.nelts; i++) { /* If exact pc given, clear bpts at that pc. @@ -9955,18 +10151,21 @@ clear_command (char *arg, int from_tty) struct bp_location *loc = b->loc; for (; loc; loc = loc->next) { - int pc_match = sal.pc - && (loc->pspace == sal.pspace) - && (loc->address == sal.pc) - && (!section_is_overlay (loc->section) - || loc->section == sal.section); - int line_match = ((default_match || (0 == sal.pc)) - && b->source_file != NULL + /* If the user specified file:line, don't allow a PC + match. This matches historical gdb behavior. */ + int pc_match = (!sal.explicit_line + && sal.pc + && (loc->pspace == sal.pspace) + && (loc->address == sal.pc) + && (!section_is_overlay (loc->section) + || loc->section == sal.section)); + int line_match = ((default_match || sal.explicit_line) + && loc->source_file != NULL && sal.symtab != NULL && sal.pspace == loc->pspace - && filename_cmp (b->source_file, + && filename_cmp (loc->source_file, sal.symtab->filename) == 0 - && b->line_number == sal.line); + && loc->line_number == sal.line); if (pc_match || line_match) { match = 1; @@ -9979,6 +10178,7 @@ clear_command (char *arg, int from_tty) VEC_safe_push(breakpoint_p, found, b); } } + /* Now go thru the 'found' chain and delete them. */ if (VEC_empty(breakpoint_p, found)) { @@ -9988,6 +10188,21 @@ clear_command (char *arg, int from_tty) error (_("No breakpoint at this line.")); } + /* Remove duplicates from the vec. */ + qsort (VEC_address (breakpoint_p, found), + VEC_length (breakpoint_p, found), + sizeof (breakpoint_p), + compare_breakpoints); + prev = VEC_index (breakpoint_p, found, 0); + for (ix = 1; VEC_iterate (breakpoint_p, found, ix, b); ++ix) + { + if (b == prev) + { + VEC_ordered_remove (breakpoint_p, found, ix); + --ix; + } + } + if (VEC_length(breakpoint_p, found) > 1) from_tty = 1; /* Always report if deleted more than one. */ if (from_tty) @@ -10007,6 +10222,8 @@ clear_command (char *arg, int from_tty) } if (from_tty) putchar_unfiltered ('\n'); + + do_cleanups (cleanups); } /* Delete breakpoint in BS if they are `delete' breakpoints and @@ -10036,7 +10253,7 @@ breakpoint_auto_delete (bpstat bs) does breakpoint_address_is_meaningful say for its OWNER), secondarily by ordering first bp_permanent OWNERed elements and terciarily just ensuring the array is sorted stable way despite - qsort being an instable algorithm. */ + qsort being an unstable algorithm. */ static int bp_location_compare (const void *ap, const void *bp) @@ -10100,6 +10317,72 @@ bp_location_target_extensions_update (void) } } +/* Download tracepoint locations if they haven't been. */ + +static void +download_tracepoint_locations (void) +{ + struct bp_location *bl, **blp_tmp; + struct cleanup *old_chain; + + if (!target_can_download_tracepoint ()) + return; + + old_chain = save_current_space_and_thread (); + + ALL_BP_LOCATIONS (bl, blp_tmp) + { + struct tracepoint *t; + + if (!is_tracepoint (bl->owner)) + continue; + + if ((bl->owner->type == bp_fast_tracepoint + ? !may_insert_fast_tracepoints + : !may_insert_tracepoints)) + continue; + + /* In tracepoint, locations are _never_ duplicated, so + should_be_inserted is equivalent to + unduplicated_should_be_inserted. */ + if (!should_be_inserted (bl) || bl->inserted) + continue; + + switch_to_program_space_and_thread (bl->pspace); + + target_download_tracepoint (bl); + + bl->inserted = 1; + t = (struct tracepoint *) bl->owner; + t->number_on_target = bl->owner->number; + } + + do_cleanups (old_chain); +} + +/* Swap the insertion/duplication state between two locations. */ + +static void +swap_insertion (struct bp_location *left, struct bp_location *right) +{ + const int left_inserted = left->inserted; + const int left_duplicate = left->duplicate; + const struct bp_target_info left_target_info = left->target_info; + + /* Locations of tracepoints can never be duplicated. */ + if (is_tracepoint (left->owner)) + gdb_assert (!left->duplicate); + if (is_tracepoint (right->owner)) + gdb_assert (!right->duplicate); + + left->inserted = right->inserted; + left->duplicate = right->duplicate; + left->target_info = right->target_info; + right->inserted = left_inserted; + right->duplicate = left_duplicate; + right->target_info = left_target_info; +} + /* If SHOULD_INSERT is false, do not insert any breakpoint locations into the inferior, only remove already-inserted locations that no longer should be inserted. Functions that delete a breakpoint or @@ -10175,7 +10458,7 @@ update_global_location_list (int should_insert) struct bp_location *old_loc = *old_locp; struct bp_location **loc2p; - /* Tells if 'old_loc' is found amoung the new locations. If + /* Tells if 'old_loc' is found among the new locations. If not, we have to free it. */ int found_object = 0; /* Tells if the location should remain inserted in the target. */ @@ -10236,11 +10519,6 @@ update_global_location_list (int should_insert) if (breakpoint_locations_match (loc2, old_loc)) { - /* For the sake of should_be_inserted. - Duplicates check below will fix up this - later. */ - loc2->duplicate = 0; - /* Read watchpoint locations are switched to access watchpoints, if the former are not supported, but the latter are. */ @@ -10250,10 +10528,13 @@ update_global_location_list (int should_insert) loc2->watchpoint_type = old_loc->watchpoint_type; } - if (loc2 != old_loc && should_be_inserted (loc2)) + /* loc2 is a duplicated location. We need to check + if it should be inserted in case it will be + unduplicated. */ + if (loc2 != old_loc + && unduplicated_should_be_inserted (loc2)) { - loc2->inserted = 1; - loc2->target_info = old_loc->target_info; + swap_insertion (old_loc, loc2); keep_in_target = 1; break; } @@ -10364,15 +10645,14 @@ update_global_location_list (int should_insert) { /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL. */ - struct breakpoint *b = loc->owner; struct bp_location **loc_first_p; + b = loc->owner; - if (b->enable_state == bp_disabled - || b->enable_state == bp_call_disabled - || b->enable_state == bp_startup_disabled - || !loc->enabled - || loc->shlib_disabled + if (!should_be_inserted (loc) || !breakpoint_address_is_meaningful (b) + /* Don't detect duplicate for tracepoint locations because they are + never duplicated. See the comments in field `duplicate' of + `struct bp_location'. */ || is_tracepoint (b)) continue; @@ -10400,6 +10680,12 @@ update_global_location_list (int should_insert) continue; } + + /* This and the above ensure the invariant that the first location + is not duplicated, and is the inserted one. + All following are marked as duplicated, and are not inserted. */ + if (loc->inserted) + swap_insertion (loc, *loc_first_p); loc->duplicate = 1; if ((*loc_first_p)->owner->enable_state == bp_permanent && loc->inserted @@ -10414,6 +10700,9 @@ update_global_location_list (int should_insert) || (gdbarch_has_global_breakpoints (target_gdbarch)))) insert_breakpoint_locations (); + if (should_insert) + download_tracepoint_locations (); + do_cleanups (cleanups); } @@ -10467,6 +10756,561 @@ bpstat_remove_breakpoint_callback (struct thread_info *th, void *data) return 0; } +/* Helper for breakpoint and tracepoint breakpoint_ops->mention + callbacks. */ + +static void +say_where (struct breakpoint *b) +{ + struct ui_out *uiout = current_uiout; + struct value_print_options opts; + + get_user_print_options (&opts); + + /* i18n: cagney/2005-02-11: Below needs to be merged into a + single string. */ + if (b->loc == NULL) + { + printf_filtered (_(" (%s) pending."), b->addr_string); + } + else + { + if (opts.addressprint || b->loc->source_file == NULL) + { + printf_filtered (" at "); + fputs_filtered (paddress (b->loc->gdbarch, b->loc->address), + gdb_stdout); + } + if (b->loc->source_file) + { + /* If there is a single location, we can print the location + more nicely. */ + if (b->loc->next == NULL) + printf_filtered (": file %s, line %d.", + b->loc->source_file, b->loc->line_number); + else + /* This is not ideal, but each location may have a + different file name, and this at least reflects the + real situation somewhat. */ + printf_filtered (": %s.", b->addr_string); + } + + if (b->loc->next) + { + struct bp_location *loc = b->loc; + int n = 0; + for (; loc; loc = loc->next) + ++n; + printf_filtered (" (%d locations)", n); + } + } +} + +/* Default bp_location_ops methods. */ + +static void +bp_location_dtor (struct bp_location *self) +{ + xfree (self->cond); + xfree (self->function_name); + xfree (self->source_file); +} + +static const struct bp_location_ops bp_location_ops = +{ + bp_location_dtor +}; + +/* Default breakpoint_ops methods all breakpoint_ops ultimately + inherit from. */ + +static void +base_breakpoint_dtor (struct breakpoint *self) +{ + decref_counted_command_line (&self->commands); + xfree (self->cond_string); + xfree (self->addr_string); + xfree (self->filter); + xfree (self->addr_string_range_end); +} + +static struct bp_location * +base_breakpoint_allocate_location (struct breakpoint *self) +{ + struct bp_location *loc; + + loc = XNEW (struct bp_location); + init_bp_location (loc, &bp_location_ops, self); + return loc; +} + +static void +base_breakpoint_re_set (struct breakpoint *b) +{ + /* Nothing to re-set. */ +} + +#define internal_error_pure_virtual_called() \ + gdb_assert_not_reached ("pure virtual function called") + +static int +base_breakpoint_insert_location (struct bp_location *bl) +{ + internal_error_pure_virtual_called (); +} + +static int +base_breakpoint_remove_location (struct bp_location *bl) +{ + internal_error_pure_virtual_called (); +} + +static int +base_breakpoint_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, + CORE_ADDR bp_addr) +{ + internal_error_pure_virtual_called (); +} + +static void +base_breakpoint_check_status (bpstat bs) +{ + /* Always stop. */ +} + +/* A "works_in_software_mode" breakpoint_ops method that just internal + errors. */ + +static int +base_breakpoint_works_in_software_mode (const struct breakpoint *b) +{ + internal_error_pure_virtual_called (); +} + +/* A "resources_needed" breakpoint_ops method that just internal + errors. */ + +static int +base_breakpoint_resources_needed (const struct bp_location *bl) +{ + internal_error_pure_virtual_called (); +} + +static enum print_stop_action +base_breakpoint_print_it (bpstat bs) +{ + internal_error_pure_virtual_called (); +} + +static void +base_breakpoint_print_one_detail (const struct breakpoint *self, + struct ui_out *uiout) +{ + /* nothing */ +} + +static void +base_breakpoint_print_mention (struct breakpoint *b) +{ + internal_error_pure_virtual_called (); +} + +static void +base_breakpoint_print_recreate (struct breakpoint *b, struct ui_file *fp) +{ + internal_error_pure_virtual_called (); +} + +static struct breakpoint_ops base_breakpoint_ops = +{ + base_breakpoint_dtor, + base_breakpoint_allocate_location, + base_breakpoint_re_set, + base_breakpoint_insert_location, + base_breakpoint_remove_location, + base_breakpoint_breakpoint_hit, + base_breakpoint_check_status, + base_breakpoint_resources_needed, + base_breakpoint_works_in_software_mode, + base_breakpoint_print_it, + NULL, + base_breakpoint_print_one_detail, + base_breakpoint_print_mention, + base_breakpoint_print_recreate +}; + +/* Default breakpoint_ops methods. */ + +static void +bkpt_re_set (struct breakpoint *b) +{ + /* FIXME: is this still reachable? */ + if (b->addr_string == NULL) + { + /* Anything without a string can't be re-set. */ + delete_breakpoint (b); + return; + } + + breakpoint_re_set_default (b); +} + +static int +bkpt_insert_location (struct bp_location *bl) +{ + if (bl->loc_type == bp_loc_hardware_breakpoint) + return target_insert_hw_breakpoint (bl->gdbarch, + &bl->target_info); + else + return target_insert_breakpoint (bl->gdbarch, + &bl->target_info); +} + +static int +bkpt_remove_location (struct bp_location *bl) +{ + if (bl->loc_type == bp_loc_hardware_breakpoint) + return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info); + else + return target_remove_breakpoint (bl->gdbarch, &bl->target_info); +} + +static int +bkpt_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) +{ + struct breakpoint *b = bl->owner; + + if (!breakpoint_address_match (bl->pspace->aspace, bl->address, + aspace, bp_addr)) + return 0; + + if (overlay_debugging /* unmapped overlay section */ + && section_is_overlay (bl->section) + && !section_is_mapped (bl->section)) + return 0; + + return 1; +} + +static int +bkpt_resources_needed (const struct bp_location *bl) +{ + gdb_assert (bl->owner->type == bp_hardware_breakpoint); + + return 1; +} + +static enum print_stop_action +bkpt_print_it (bpstat bs) +{ + struct breakpoint *b; + const struct bp_location *bl; + int bp_temp; + struct ui_out *uiout = current_uiout; + + gdb_assert (bs->bp_location_at != NULL); + + bl = bs->bp_location_at; + b = bs->breakpoint_at; + + bp_temp = b->disposition == disp_del; + if (bl->address != bl->requested_address) + breakpoint_adjustment_warning (bl->requested_address, + bl->address, + b->number, 1); + annotate_breakpoint (b->number); + if (bp_temp) + ui_out_text (uiout, "\nTemporary breakpoint "); + else + ui_out_text (uiout, "\nBreakpoint "); + if (ui_out_is_mi_like_p (uiout)) + { + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT)); + ui_out_field_string (uiout, "disp", bpdisp_text (b->disposition)); + } + ui_out_field_int (uiout, "bkptno", b->number); + ui_out_text (uiout, ", "); + + return PRINT_SRC_AND_LOC; +} + +static void +bkpt_print_mention (struct breakpoint *b) +{ + if (ui_out_is_mi_like_p (current_uiout)) + return; + + switch (b->type) + { + case bp_breakpoint: + case bp_gnu_ifunc_resolver: + if (b->disposition == disp_del) + printf_filtered (_("Temporary breakpoint")); + else + printf_filtered (_("Breakpoint")); + printf_filtered (_(" %d"), b->number); + if (b->type == bp_gnu_ifunc_resolver) + printf_filtered (_(" at gnu-indirect-function resolver")); + break; + case bp_hardware_breakpoint: + printf_filtered (_("Hardware assisted breakpoint %d"), b->number); + break; + } + + say_where (b); +} + +static void +bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp) +{ + if (tp->type == bp_breakpoint && tp->disposition == disp_del) + fprintf_unfiltered (fp, "tbreak"); + else if (tp->type == bp_breakpoint) + fprintf_unfiltered (fp, "break"); + else if (tp->type == bp_hardware_breakpoint + && tp->disposition == disp_del) + fprintf_unfiltered (fp, "thbreak"); + else if (tp->type == bp_hardware_breakpoint) + fprintf_unfiltered (fp, "hbreak"); + else + internal_error (__FILE__, __LINE__, + _("unhandled breakpoint type %d"), (int) tp->type); + + fprintf_unfiltered (fp, " %s", tp->addr_string); + print_recreate_thread (tp, fp); +} + +/* Virtual table for internal breakpoints. */ + +static void +internal_bkpt_re_set (struct breakpoint *b) +{ + switch (b->type) + { + /* Delete overlay event and longjmp master breakpoints; they + will be reset later by breakpoint_re_set. */ + case bp_overlay_event: + case bp_longjmp_master: + case bp_std_terminate_master: + case bp_exception_master: + delete_breakpoint (b); + break; + + /* This breakpoint is special, it's set up when the inferior + starts and we really don't want to touch it. */ + case bp_shlib_event: + + /* Like bp_shlib_event, this breakpoint type is special. Once + it is set up, we do not want to touch it. */ + case bp_thread_event: + break; + } +} + +static void +internal_bkpt_check_status (bpstat bs) +{ + /* We do not stop for these. */ + bs->stop = 0; +} + +static enum print_stop_action +internal_bkpt_print_it (bpstat bs) +{ + struct ui_out *uiout = current_uiout; + struct breakpoint *b; + + b = bs->breakpoint_at; + + switch (b->type) + { + case bp_shlib_event: + /* Did we stop because the user set the stop_on_solib_events + variable? (If so, we report this as a generic, "Stopped due + to shlib event" message.) */ + ui_out_text (uiout, _("Stopped due to shared library event\n")); + if (ui_out_is_mi_like_p (uiout)) + ui_out_field_string (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_SOLIB_EVENT)); + break; + + case bp_thread_event: + /* Not sure how we will get here. + GDB should not stop for these breakpoints. */ + printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n")); + break; + + case bp_overlay_event: + /* By analogy with the thread event, GDB should not stop for these. */ + printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n")); + break; + + case bp_longjmp_master: + /* These should never be enabled. */ + printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n")); + break; + + case bp_std_terminate_master: + /* These should never be enabled. */ + printf_filtered (_("std::terminate Master Breakpoint: " + "gdb should not stop!\n")); + break; + + case bp_exception_master: + /* These should never be enabled. */ + printf_filtered (_("Exception Master Breakpoint: " + "gdb should not stop!\n")); + break; + } + + return PRINT_NOTHING; +} + +static void +internal_bkpt_print_mention (struct breakpoint *b) +{ + /* Nothing to mention. These breakpoints are internal. */ +} + +/* Virtual table for momentary breakpoints */ + +static void +momentary_bkpt_re_set (struct breakpoint *b) +{ + /* Keep temporary breakpoints, which can be encountered when we step + over a dlopen call and SOLIB_ADD is resetting the breakpoints. + Otherwise these should have been blown away via the cleanup chain + or by breakpoint_init_inferior when we rerun the executable. */ +} + +static void +momentary_bkpt_check_status (bpstat bs) +{ + /* Nothing. The point of these breakpoints is causing a stop. */ +} + +static enum print_stop_action +momentary_bkpt_print_it (bpstat bs) +{ + struct ui_out *uiout = current_uiout; + + if (ui_out_is_mi_like_p (uiout)) + { + struct breakpoint *b = bs->breakpoint_at; + + switch (b->type) + { + case bp_finish: + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_FUNCTION_FINISHED)); + break; + + case bp_until: + ui_out_field_string + (uiout, "reason", + async_reason_lookup (EXEC_ASYNC_LOCATION_REACHED)); + break; + } + } + + return PRINT_UNKNOWN; +} + +static void +momentary_bkpt_print_mention (struct breakpoint *b) +{ + /* Nothing to mention. These breakpoints are internal. */ +} + +/* The breakpoint_ops structure to be used in tracepoints. */ + +static void +tracepoint_re_set (struct breakpoint *b) +{ + breakpoint_re_set_default (b); +} + +static int +tracepoint_breakpoint_hit (const struct bp_location *bl, + struct address_space *aspace, CORE_ADDR bp_addr) +{ + /* By definition, the inferior does not report stops at + tracepoints. */ + return 0; +} + +static void +tracepoint_print_one_detail (const struct breakpoint *self, + struct ui_out *uiout) +{ + struct tracepoint *tp = (struct tracepoint *) self; + if (tp->static_trace_marker_id) + { + gdb_assert (self->type == bp_static_tracepoint); + + ui_out_text (uiout, "\tmarker id is "); + ui_out_field_string (uiout, "static-tracepoint-marker-string-id", + tp->static_trace_marker_id); + ui_out_text (uiout, "\n"); + } +} + +static void +tracepoint_print_mention (struct breakpoint *b) +{ + if (ui_out_is_mi_like_p (current_uiout)) + return; + + switch (b->type) + { + case bp_tracepoint: + printf_filtered (_("Tracepoint")); + printf_filtered (_(" %d"), b->number); + break; + case bp_fast_tracepoint: + printf_filtered (_("Fast tracepoint")); + printf_filtered (_(" %d"), b->number); + break; + case bp_static_tracepoint: + printf_filtered (_("Static tracepoint")); + printf_filtered (_(" %d"), b->number); + break; + default: + internal_error (__FILE__, __LINE__, + _("unhandled tracepoint type %d"), (int) b->type); + } + + say_where (b); +} + +static void +tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp) +{ + struct tracepoint *tp = (struct tracepoint *) self; + + if (self->type == bp_fast_tracepoint) + fprintf_unfiltered (fp, "ftrace"); + if (self->type == bp_static_tracepoint) + fprintf_unfiltered (fp, "strace"); + else if (self->type == bp_tracepoint) + fprintf_unfiltered (fp, "trace"); + else + internal_error (__FILE__, __LINE__, + _("unhandled tracepoint type %d"), (int) self->type); + + fprintf_unfiltered (fp, " %s", self->addr_string); + print_recreate_thread (self, fp); + + if (tp->pass_count) + fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count); +} + +struct breakpoint_ops tracepoint_breakpoint_ops; + /* Delete a breakpoint and clean up all traces of it in the data structures. */ @@ -10501,11 +11345,16 @@ delete_breakpoint (struct breakpoint *bpt) if (bpt->related_breakpoint != bpt) { struct breakpoint *related; + struct watchpoint *w; if (bpt->type == bp_watchpoint_scope) - watchpoint_del_at_next_stop (bpt->related_breakpoint); + w = (struct watchpoint *) bpt->related_breakpoint; else if (bpt->related_breakpoint->type == bp_watchpoint_scope) - watchpoint_del_at_next_stop (bpt); + w = (struct watchpoint *) bpt; + else + w = NULL; + if (w != NULL) + watchpoint_del_at_next_stop (w); /* Unlink bpt from the bpt->related_breakpoint ring. */ for (related = bpt; related->related_breakpoint != bpt; @@ -10514,7 +11363,12 @@ delete_breakpoint (struct breakpoint *bpt) bpt->related_breakpoint = bpt; } - observer_notify_breakpoint_deleted (bpt->number); + /* watch_command_1 creates a watchpoint but only sets its number if + update_watchpoint succeeds in creating its bp_locations. If there's + a problem in that process, we'll be asked to delete the half-created + watchpoint. In that case, don't announce the deletion. */ + if (bpt->number) + observer_notify_breakpoint_deleted (bpt); if (breakpoint_chain == bpt) breakpoint_chain = bpt->next; @@ -10526,24 +11380,10 @@ delete_breakpoint (struct breakpoint *bpt) break; } - decref_counted_command_line (&bpt->commands); - xfree (bpt->cond_string); - xfree (bpt->cond_exp); - xfree (bpt->addr_string); - xfree (bpt->addr_string_range_end); - xfree (bpt->exp); - xfree (bpt->exp_string); - xfree (bpt->exp_string_reparse); - value_free (bpt->val); - xfree (bpt->source_file); - xfree (bpt->exec_pathname); - clean_up_filters (&bpt->syscalls_to_be_caught); - - /* Be sure no bpstat's are pointing at the breakpoint after it's been freed. */ /* FIXME, how can we find all bpstat's? We just check stop_bpstat - in all threeds for now. Note that we cannot just remove bpstats + in all threads for now. Note that we cannot just remove bpstats pointing at bpt from the stop_bpstat list entirely, as breakpoint commands are associated with the bpstat; if we remove it here, then the later call to bpstat_do_actions (&stop_bpstat); in @@ -10560,11 +11400,10 @@ delete_breakpoint (struct breakpoint *bpt) self-contained, but it's not the case now. */ update_global_location_list (0); - + bpt->ops->dtor (bpt); /* On the chance that someone will soon try again to delete this same bp, we mark it as deleted before freeing its storage. */ bpt->type = bp_none; - xfree (bpt); } @@ -10580,8 +11419,42 @@ make_cleanup_delete_breakpoint (struct breakpoint *b) return make_cleanup (do_delete_breakpoint_cleanup, b); } -/* A callback for map_breakpoint_numbers that calls - delete_breakpoint. */ +/* Iterator function to call a user-provided callback function once + for each of B and its related breakpoints. */ + +static void +iterate_over_related_breakpoints (struct breakpoint *b, + void (*function) (struct breakpoint *, + void *), + void *data) +{ + struct breakpoint *related; + + related = b; + do + { + struct breakpoint *next; + + /* FUNCTION may delete RELATED. */ + next = related->related_breakpoint; + + if (next == related) + { + /* RELATED is the last ring entry. */ + function (related, data); + + /* FUNCTION may have deleted it, so we'd never reach back to + B. There's nothing left to do anyway, so just break + out. */ + break; + } + else + function (related, data); + + related = next; + } + while (related != b); +} static void do_delete_breakpoint (struct breakpoint *b, void *ignore) @@ -10589,6 +11462,15 @@ do_delete_breakpoint (struct breakpoint *b, void *ignore) delete_breakpoint (b); } +/* A callback for map_breakpoint_numbers that calls + delete_breakpoint. */ + +static void +do_map_delete_breakpoint (struct breakpoint *b, void *ignore) +{ + iterate_over_related_breakpoints (b, do_delete_breakpoint, NULL); +} + void delete_command (char *arg, int from_tty) { @@ -10600,56 +11482,35 @@ delete_command (char *arg, int from_tty) { int breaks_to_delete = 0; - /* Delete all breakpoints if no argument. - Do not delete internal or call-dummy breakpoints, these have - to be deleted with an explicit breakpoint number argument. */ + /* Delete all breakpoints if no argument. Do not delete + internal breakpoints, these have to be deleted with an + explicit breakpoint number argument. */ ALL_BREAKPOINTS (b) - { - if (b->type != bp_call_dummy - && b->type != bp_std_terminate - && b->type != bp_shlib_event - && b->type != bp_jit_event - && b->type != bp_thread_event - && b->type != bp_overlay_event - && b->type != bp_longjmp_master - && b->type != bp_std_terminate_master - && b->type != bp_exception_master - && b->number >= 0) + if (user_breakpoint_p (b)) { breaks_to_delete = 1; break; } - } /* Ask user only if there are some breakpoints to delete. */ if (!from_tty || (breaks_to_delete && query (_("Delete all breakpoints? ")))) { ALL_BREAKPOINTS_SAFE (b, b_tmp) - { - if (b->type != bp_call_dummy - && b->type != bp_std_terminate - && b->type != bp_shlib_event - && b->type != bp_thread_event - && b->type != bp_jit_event - && b->type != bp_overlay_event - && b->type != bp_longjmp_master - && b->type != bp_std_terminate_master - && b->type != bp_exception_master - && b->number >= 0) + if (user_breakpoint_p (b)) delete_breakpoint (b); - } } } else - map_breakpoint_numbers (arg, do_delete_breakpoint, NULL); + map_breakpoint_numbers (arg, do_map_delete_breakpoint, NULL); } static int all_locations_are_pending (struct bp_location *loc) { for (; loc; loc = loc->next) - if (!loc->shlib_disabled) + if (!loc->shlib_disabled + && !loc->pspace->executing_startup) return 0; return 1; } @@ -10728,6 +11589,7 @@ ambiguous_names_p (struct bp_location *loc) static struct symtab_and_line update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) { + struct tracepoint *tp = (struct tracepoint *) b; struct static_tracepoint_marker marker; CORE_ADDR pc; int i; @@ -10738,13 +11600,13 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) if (target_static_tracepoint_marker_at (pc, &marker)) { - if (strcmp (b->static_trace_marker_id, marker.str_id) != 0) + if (strcmp (tp->static_trace_marker_id, marker.str_id) != 0) warning (_("static tracepoint %d changed probed marker from %s to %s"), b->number, - b->static_trace_marker_id, marker.str_id); + tp->static_trace_marker_id, marker.str_id); - xfree (b->static_trace_marker_id); - b->static_trace_marker_id = xstrdup (marker.str_id); + xfree (tp->static_trace_marker_id); + tp->static_trace_marker_id = xstrdup (marker.str_id); release_static_tracepoint_marker (&marker); return sal; @@ -10755,34 +11617,35 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) if (!sal.explicit_pc && sal.line != 0 && sal.symtab != NULL - && b->static_trace_marker_id != NULL) + && tp->static_trace_marker_id != NULL) { VEC(static_tracepoint_marker_p) *markers; markers - = target_static_tracepoint_markers_by_strid (b->static_trace_marker_id); + = target_static_tracepoint_markers_by_strid (tp->static_trace_marker_id); if (!VEC_empty(static_tracepoint_marker_p, markers)) { - struct symtab_and_line sal; + struct symtab_and_line sal2; struct symbol *sym; - struct static_tracepoint_marker *marker; + struct static_tracepoint_marker *tpmarker; + struct ui_out *uiout = current_uiout; - marker = VEC_index (static_tracepoint_marker_p, markers, 0); + tpmarker = VEC_index (static_tracepoint_marker_p, markers, 0); - xfree (b->static_trace_marker_id); - b->static_trace_marker_id = xstrdup (marker->str_id); + xfree (tp->static_trace_marker_id); + tp->static_trace_marker_id = xstrdup (tpmarker->str_id); warning (_("marker for static tracepoint %d (%s) not " "found at previous line number"), - b->number, b->static_trace_marker_id); + b->number, tp->static_trace_marker_id); - init_sal (&sal); + init_sal (&sal2); - sal.pc = marker->address; + sal2.pc = tpmarker->address; - sal = find_pc_line (marker->address, 0); - sym = find_pc_sect_function (marker->address, NULL); + sal2 = find_pc_line (tpmarker->address, 0); + sym = find_pc_sect_function (tpmarker->address, NULL); ui_out_text (uiout, "Now in "); if (sym) { @@ -10790,41 +11653,69 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal) SYMBOL_PRINT_NAME (sym)); ui_out_text (uiout, " at "); } - ui_out_field_string (uiout, "file", sal.symtab->filename); + ui_out_field_string (uiout, "file", sal2.symtab->filename); ui_out_text (uiout, ":"); if (ui_out_is_mi_like_p (uiout)) { - char *fullname = symtab_to_fullname (sal.symtab); + char *fullname = symtab_to_fullname (sal2.symtab); if (fullname) ui_out_field_string (uiout, "fullname", fullname); } - ui_out_field_int (uiout, "line", sal.line); + ui_out_field_int (uiout, "line", sal2.line); ui_out_text (uiout, "\n"); - b->line_number = sal.line; + b->loc->line_number = sal2.line; - xfree (b->source_file); + xfree (b->loc->source_file); if (sym) - b->source_file = xstrdup (sal.symtab->filename); + b->loc->source_file = xstrdup (sal2.symtab->filename); else - b->source_file = NULL; + b->loc->source_file = NULL; xfree (b->addr_string); b->addr_string = xstrprintf ("%s:%d", - sal.symtab->filename, b->line_number); + sal2.symtab->filename, + b->loc->line_number); /* Might be nice to check if function changed, and warn if so. */ - release_static_tracepoint_marker (marker); + release_static_tracepoint_marker (tpmarker); } } return sal; } +/* Returns 1 iff locations A and B are sufficiently same that + we don't need to report breakpoint as changed. */ + +static int +locations_are_equal (struct bp_location *a, struct bp_location *b) +{ + while (a && b) + { + if (a->address != b->address) + return 0; + + if (a->shlib_disabled != b->shlib_disabled) + return 0; + + if (a->enabled != b->enabled) + return 0; + + a = a->next; + b = b->next; + } + + if ((a == NULL) != (b == NULL)) + return 0; + + return 1; +} + /* Create new breakpoint locations for B (a hardware or software breakpoint) based on SALS and SALS_END. If SALS_END.NELTS is not zero, then B is a ranged breakpoint. */ @@ -10837,8 +11728,17 @@ update_breakpoint_locations (struct breakpoint *b, int i; struct bp_location *existing_locations = b->loc; - /* Ranged breakpoints have only one start location and one end location. */ - gdb_assert (sals_end.nelts == 0 || (sals.nelts == 1 && sals_end.nelts == 1)); + if (sals_end.nelts != 0 && (sals.nelts != 1 || sals_end.nelts != 1)) + { + /* Ranged breakpoints have only one start location and one end + location. */ + b->enable_state = bp_disabled; + update_global_location_list (1); + printf_unfiltered (_("Could not reset ranged breakpoint %d: " + "multiple locations found\n"), + b->number); + return; + } /* If there's no new locations, and all existing locations are pending, don't do anything. This optimizes the common case where @@ -10853,8 +11753,11 @@ update_breakpoint_locations (struct breakpoint *b, for (i = 0; i < sals.nelts; ++i) { - struct bp_location *new_loc = - add_location_to_breakpoint (b, &(sals.sals[i])); + struct bp_location *new_loc; + + switch_to_program_space_and_thread (sals.sals[i].pspace); + + new_loc = add_location_to_breakpoint (b, &(sals.sals[i])); /* Reparse conditions, they might contain references to the old symtab. */ @@ -10878,16 +11781,6 @@ update_breakpoint_locations (struct breakpoint *b, } } - if (b->source_file != NULL) - xfree (b->source_file); - if (sals.sals[i].symtab == NULL) - b->source_file = NULL; - else - b->source_file = xstrdup (sals.sals[i].symtab->filename); - - if (b->line_number == 0) - b->line_number = sals.sals[i].line; - if (sals_end.nelts) { CORE_ADDR end = find_breakpoint_range_end (sals_end.sals[0]); @@ -10939,6 +11832,9 @@ update_breakpoint_locations (struct breakpoint *b, } } + if (!locations_are_equal (existing_locations, b->loc)) + observer_notify_breakpoint_modified (b); + update_global_location_list (1); } @@ -10951,7 +11847,7 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) char *s; int marker_spec; struct symtabs_and_lines sals = {0}; - struct gdb_exception e; + volatile struct gdb_exception e; s = addr_string; marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s); @@ -10960,17 +11856,43 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) { if (marker_spec) { + struct tracepoint *tp = (struct tracepoint *) b; + sals = decode_static_tracepoint_spec (&s); - if (sals.nelts > b->static_trace_marker_id_idx) + if (sals.nelts > tp->static_trace_marker_id_idx) + { + sals.sals[0] = sals.sals[tp->static_trace_marker_id_idx]; + sals.nelts = 1; + } + else + error (_("marker %s not found"), tp->static_trace_marker_id); + } + else + { + struct linespec_result canonical; + + init_linespec_result (&canonical); + decode_line_full (&s, DECODE_LINE_FUNFIRSTLINE, + (struct symtab *) NULL, 0, + &canonical, multiple_symbols_all, + b->filter); + + /* We should get 0 or 1 resulting SALs. */ + gdb_assert (VEC_length (linespec_sals, canonical.sals) < 2); + + if (VEC_length (linespec_sals, canonical.sals) > 0) { - sals.sals[0] = sals.sals[b->static_trace_marker_id_idx]; - sals.nelts = 1; + struct linespec_sals *lsal; + + lsal = VEC_index (linespec_sals, canonical.sals, 0); + sals = lsal->sals; + /* Arrange it so the destructor does not free the + contents. */ + lsal->sals.sals = NULL; } - else - error (_("marker %s not found"), b->static_trace_marker_id); + + destroy_linespec_result (&canonical); } - else - sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, NULL); } if (e.reason < 0) { @@ -10985,6 +11907,7 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) if (e.error == NOT_FOUND_ERROR && (b->condition_not_parsed || (b->loc && b->loc->shlib_disabled) + || (b->loc && b->loc->pspace->executing_startup) || b->enable_state == bp_disabled)) not_found_and_ok = 1; @@ -11003,9 +11926,10 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) if (e.reason == 0 || e.error != NOT_FOUND_ERROR) { - gdb_assert (sals.nelts == 1); + int i; - resolve_sal_pc (&sals.sals[0]); + for (i = 0; i < sals.nelts; ++i) + resolve_sal_pc (&sals.sals[i]); if (b->condition_not_parsed && s && s[0]) { char *cond_string = 0; @@ -11032,29 +11956,23 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found) return sals; } -/* Reevaluate a hardware or software breakpoint and recreate its locations. - This is necessary after symbols are read (e.g., an executable or DSO - was loaded, or the inferior just started). */ +/* The default re_set method, for typical hardware or software + breakpoints. Reevaluate the breakpoint and recreate its + locations. */ static void -re_set_breakpoint (struct breakpoint *b) +breakpoint_re_set_default (struct breakpoint *b) { int found; struct symtabs_and_lines sals, sals_end; struct symtabs_and_lines expanded = {0}; struct symtabs_and_lines expanded_end = {0}; - struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); - - input_radix = b->input_radix; - save_current_space_and_thread (); - switch_to_program_space_and_thread (b->pspace); - set_language (b->language); sals = addr_string_to_sals (b, b->addr_string, &found); if (found) { make_cleanup (xfree, sals.sals); - expanded = expand_line_sal_maybe (sals.sals[0]); + expanded = sals; } if (b->addr_string_range_end) @@ -11063,12 +11981,27 @@ re_set_breakpoint (struct breakpoint *b) if (found) { make_cleanup (xfree, sals_end.sals); - expanded_end = expand_line_sal_maybe (sals_end.sals[0]); + expanded_end = sals_end; } } update_breakpoint_locations (b, expanded, expanded_end); - do_cleanups (cleanups); +} + +/* Prepare the global context for a re-set of breakpoint B. */ + +static struct cleanup * +prepare_re_set_context (struct breakpoint *b) +{ + struct cleanup *cleanups; + + input_radix = b->input_radix; + cleanups = save_current_space_and_thread (); + if (b->pspace != NULL) + switch_to_program_space_and_thread (b->pspace); + set_language (b->language); + + return cleanups; } /* Reset a breakpoint given it's struct breakpoint * BINT. @@ -11080,111 +12013,11 @@ breakpoint_re_set_one (void *bint) { /* Get past catch_errs. */ struct breakpoint *b = (struct breakpoint *) bint; + struct cleanup *cleanups; - switch (b->type) - { - case bp_none: - warning (_("attempted to reset apparently deleted breakpoint #%d?"), - b->number); - return 0; - case bp_breakpoint: - case bp_hardware_breakpoint: - case bp_tracepoint: - case bp_fast_tracepoint: - case bp_static_tracepoint: - case bp_gnu_ifunc_resolver: - /* Do not attempt to re-set breakpoints disabled during startup. */ - if (b->enable_state == bp_startup_disabled) - return 0; - - if (b->addr_string == NULL) - { - /* Anything without a string can't be re-set. */ - delete_breakpoint (b); - return 0; - } - - re_set_breakpoint (b); - break; - - case bp_watchpoint: - case bp_hardware_watchpoint: - case bp_read_watchpoint: - case bp_access_watchpoint: - /* Watchpoint can be either on expression using entirely global - variables, or it can be on local variables. - - Watchpoints of the first kind are never auto-deleted, and - even persist across program restarts. Since they can use - variables from shared libraries, we need to reparse - expression as libraries are loaded and unloaded. - - Watchpoints on local variables can also change meaning as - result of solib event. For example, if a watchpoint uses - both a local and a global variables in expression, it's a - local watchpoint, but unloading of a shared library will make - the expression invalid. This is not a very common use case, - but we still re-evaluate expression, to avoid surprises to - the user. - - Note that for local watchpoints, we re-evaluate it only if - watchpoints frame id is still valid. If it's not, it means - the watchpoint is out of scope and will be deleted soon. In - fact, I'm not sure we'll ever be called in this case. - - If a local watchpoint's frame id is still valid, then - b->exp_valid_block is likewise valid, and we can safely use it. - - Don't do anything about disabled watchpoints, since they will - be reevaluated again when enabled. */ - update_watchpoint (b, 1 /* reparse */); - break; - /* We needn't really do anything to reset these, since the mask - that requests them is unaffected by e.g., new libraries being - loaded. */ - case bp_catchpoint: - break; - - default: - printf_filtered (_("Deleting unknown breakpoint type %d\n"), b->type); - /* fall through */ - /* Delete overlay event and longjmp master breakpoints; they will be - reset later by breakpoint_re_set. */ - case bp_overlay_event: - case bp_longjmp_master: - case bp_std_terminate_master: - case bp_exception_master: - delete_breakpoint (b); - break; - - /* This breakpoint is special, it's set up when the inferior - starts and we really don't want to touch it. */ - case bp_shlib_event: - - /* Like bp_shlib_event, this breakpoint type is special. - Once it is set up, we do not want to touch it. */ - case bp_thread_event: - - /* Keep temporary breakpoints, which can be encountered when we - step over a dlopen call and SOLIB_ADD is resetting the - breakpoints. Otherwise these should have been blown away via - the cleanup chain or by breakpoint_init_inferior when we - rerun the executable. */ - case bp_until: - case bp_finish: - case bp_watchpoint_scope: - case bp_call_dummy: - case bp_std_terminate: - case bp_step_resume: - case bp_longjmp: - case bp_longjmp_resume: - case bp_exception: - case bp_exception_resume: - case bp_jit_event: - case bp_gnu_ifunc_resolver_return: - break; - } - + cleanups = prepare_re_set_context (b); + b->ops->re_set (b); + do_cleanups (cleanups); return 0; } @@ -11221,6 +12054,9 @@ breakpoint_re_set (void) create_longjmp_master_breakpoint (); create_std_terminate_master_breakpoint (); create_exception_master_breakpoint (); + + /* While we're at it, reset the skip list too. */ + skip_re_set (); } /* Reset the thread number of this breakpoint: @@ -11282,7 +12118,7 @@ set_ignore_count (int bptnum, int count, int from_tty) count, bptnum); } breakpoints_changed (); - observer_notify_breakpoint_modified (b->number); + observer_notify_breakpoint_modified (b); return; } @@ -11347,25 +12183,8 @@ map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, ALL_BREAKPOINTS_SAFE (b, tmp) if (b->number == num) { - struct breakpoint *related_breakpoint; - match = 1; - related_breakpoint = b; - do - { - struct breakpoint *next_related_b; - - /* FUNCTION can be also delete_breakpoint. */ - next_related_b = related_breakpoint->related_breakpoint; - function (related_breakpoint, data); - - /* For delete_breakpoint of the last entry of the ring we - were traversing we would never get back to B. */ - if (next_related_b == related_breakpoint) - break; - related_breakpoint = next_related_b; - } - while (related_breakpoint != b); + function (b, data); break; } if (match == 0) @@ -11435,9 +12254,26 @@ disable_breakpoint (struct breakpoint *bpt) bpt->enable_state = bp_disabled; + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && is_tracepoint (bpt)) + { + struct bp_location *location; + + for (location = bpt->loc; location; location = location->next) + target_disable_tracepoint (location); + } + update_global_location_list (0); - observer_notify_breakpoint_modified (bpt->number); + observer_notify_breakpoint_modified (bpt); +} + +/* A callback for iterate_over_related_breakpoints. */ + +static void +do_disable_breakpoint (struct breakpoint *b, void *ignore) +{ + disable_breakpoint (b); } /* A callback for map_breakpoint_numbers that calls @@ -11446,42 +12282,31 @@ disable_breakpoint (struct breakpoint *bpt) static void do_map_disable_breakpoint (struct breakpoint *b, void *ignore) { - disable_breakpoint (b); + iterate_over_related_breakpoints (b, do_disable_breakpoint, NULL); } static void disable_command (char *args, int from_tty) { - struct breakpoint *bpt; - if (args == 0) - ALL_BREAKPOINTS (bpt) - switch (bpt->type) - { - case bp_none: - warning (_("attempted to disable apparently deleted breakpoint #%d?"), - bpt->number); - break; - case bp_breakpoint: - case bp_tracepoint: - case bp_fast_tracepoint: - case bp_static_tracepoint: - case bp_catchpoint: - case bp_hardware_breakpoint: - case bp_watchpoint: - case bp_hardware_watchpoint: - case bp_read_watchpoint: - case bp_access_watchpoint: - disable_breakpoint (bpt); - break; - default: - break; - } + { + struct breakpoint *bpt; + + ALL_BREAKPOINTS (bpt) + if (user_breakpoint_p (bpt)) + disable_breakpoint (bpt); + } else if (strchr (args, '.')) { struct bp_location *loc = find_location_by_number (args); if (loc) - loc->enabled = 0; + { + loc->enabled = 0; + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_disable_tracepoint (loc); + } update_global_location_list (0); } else @@ -11489,7 +12314,7 @@ disable_command (char *args, int from_tty) } static void -do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) +enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition) { int target_resources_ok; @@ -11508,14 +12333,21 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) if (is_watchpoint (bpt)) { + /* Initialize it just to avoid a GCC false warning. */ + enum enable_state orig_enable_state = 0; struct gdb_exception e; TRY_CATCH (e, RETURN_MASK_ALL) { - update_watchpoint (bpt, 1 /* reparse */); + struct watchpoint *w = (struct watchpoint *) bpt; + + orig_enable_state = bpt->enable_state; + bpt->enable_state = bp_enabled; + update_watchpoint (w, 1 /* reparse */); } if (e.reason < 0) { + bpt->enable_state = orig_enable_state; exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "), bpt->number); return; @@ -11524,18 +12356,34 @@ do_enable_breakpoint (struct breakpoint *bpt, enum bpdisp disposition) if (bpt->enable_state != bp_permanent) bpt->enable_state = bp_enabled; + + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && is_tracepoint (bpt)) + { + struct bp_location *location; + + for (location = bpt->loc; location; location = location->next) + target_enable_tracepoint (location); + } + bpt->disposition = disposition; update_global_location_list (1); breakpoints_changed (); - observer_notify_breakpoint_modified (bpt->number); + observer_notify_breakpoint_modified (bpt); } void enable_breakpoint (struct breakpoint *bpt) { - do_enable_breakpoint (bpt, bpt->disposition); + enable_breakpoint_disp (bpt, bpt->disposition); +} + +static void +do_enable_breakpoint (struct breakpoint *bpt, void *arg) +{ + enable_breakpoint (bpt); } /* A callback for map_breakpoint_numbers that calls @@ -11544,7 +12392,7 @@ enable_breakpoint (struct breakpoint *bpt) static void do_map_enable_breakpoint (struct breakpoint *b, void *ignore) { - enable_breakpoint (b); + iterate_over_related_breakpoints (b, do_enable_breakpoint, NULL); } /* The enable command enables the specified breakpoints (or all defined @@ -11554,36 +12402,25 @@ do_map_enable_breakpoint (struct breakpoint *b, void *ignore) static void enable_command (char *args, int from_tty) { - struct breakpoint *bpt; - if (args == 0) - ALL_BREAKPOINTS (bpt) - switch (bpt->type) - { - case bp_none: - warning (_("attempted to enable apparently deleted breakpoint #%d?"), - bpt->number); - break; - case bp_breakpoint: - case bp_tracepoint: - case bp_fast_tracepoint: - case bp_static_tracepoint: - case bp_catchpoint: - case bp_hardware_breakpoint: - case bp_watchpoint: - case bp_hardware_watchpoint: - case bp_read_watchpoint: - case bp_access_watchpoint: - enable_breakpoint (bpt); - break; - default: - break; - } + { + struct breakpoint *bpt; + + ALL_BREAKPOINTS (bpt) + if (user_breakpoint_p (bpt)) + enable_breakpoint (bpt); + } else if (strchr (args, '.')) { struct bp_location *loc = find_location_by_number (args); if (loc) - loc->enabled = 1; + { + loc->enabled = 1; + if (target_supports_enable_disable_tracepoint () + && current_trace_status ()->running && loc->owner + && is_tracepoint (loc->owner)) + target_enable_tracepoint (loc); + } update_global_location_list (1); } else @@ -11591,27 +12428,39 @@ enable_command (char *args, int from_tty) } static void -enable_once_breakpoint (struct breakpoint *bpt, void *ignore) +do_enable_breakpoint_disp (struct breakpoint *bpt, void *arg) +{ + enum bpdisp disp = *(enum bpdisp *) arg; + + enable_breakpoint_disp (bpt, disp); +} + +static void +do_map_enable_once_breakpoint (struct breakpoint *bpt, void *ignore) { - do_enable_breakpoint (bpt, disp_disable); + enum bpdisp disp = disp_disable; + + iterate_over_related_breakpoints (bpt, do_enable_breakpoint_disp, &disp); } static void enable_once_command (char *args, int from_tty) { - map_breakpoint_numbers (args, enable_once_breakpoint, NULL); + map_breakpoint_numbers (args, do_map_enable_once_breakpoint, NULL); } static void -enable_delete_breakpoint (struct breakpoint *bpt, void *ignore) +do_map_enable_delete_breakpoint (struct breakpoint *bpt, void *ignore) { - do_enable_breakpoint (bpt, disp_del); + enum bpdisp disp = disp_del; + + iterate_over_related_breakpoints (bpt, do_enable_breakpoint_disp, &disp); } static void enable_delete_command (char *args, int from_tty) { - map_breakpoint_numbers (args, enable_delete_breakpoint, NULL); + map_breakpoint_numbers (args, do_map_enable_delete_breakpoint, NULL); } static void @@ -11636,40 +12485,43 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len, ALL_BREAKPOINTS (bp) if (bp->enable_state == bp_enabled - && bp->type == bp_hardware_watchpoint - && bp->val_valid && bp->val) + && bp->type == bp_hardware_watchpoint) { - struct bp_location *loc; + struct watchpoint *wp = (struct watchpoint *) bp; - for (loc = bp->loc; loc != NULL; loc = loc->next) - if (loc->loc_type == bp_loc_hardware_watchpoint - && loc->address + loc->length > addr - && addr + len > loc->address) - { - value_free (bp->val); - bp->val = NULL; - bp->val_valid = 0; - } + if (wp->val_valid && wp->val) + { + struct bp_location *loc; + + for (loc = bp->loc; loc != NULL; loc = loc->next) + if (loc->loc_type == bp_loc_hardware_watchpoint + && loc->address + loc->length > addr + && addr + len > loc->address) + { + value_free (wp->val); + wp->val = NULL; + wp->val_valid = 0; + } + } } } -/* Use default_breakpoint_'s, or nothing if they aren't valid. */ +/* Use the last displayed codepoint's values, or nothing + if they aren't valid. */ struct symtabs_and_lines -decode_line_spec_1 (char *string, int funfirstline) +decode_line_spec_1 (char *string, int flags) { struct symtabs_and_lines sals; if (string == 0) error (_("Empty line specification.")); - if (default_breakpoint_valid) - sals = decode_line_1 (&string, funfirstline, - default_breakpoint_symtab, - default_breakpoint_line, - NULL); + if (last_displayed_sal_is_valid ()) + sals = decode_line_1 (&string, flags, + get_last_displayed_symtab (), + get_last_displayed_line ()); else - sals = decode_line_1 (&string, funfirstline, - (struct symtab *) NULL, 0, NULL); + sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0); if (*string) error (_("Junk at end of line specification: %s"), string); return sals; @@ -11874,11 +12726,13 @@ catching_syscall_number (int syscall_number) ALL_BREAKPOINTS (bp) if (is_syscall_catchpoint_enabled (bp)) { - if (bp->syscalls_to_be_caught) + struct syscall_catchpoint *c = (struct syscall_catchpoint *) bp; + + if (c->syscalls_to_be_caught) { int i, iter; for (i = 0; - VEC_iterate (int, bp->syscalls_to_be_caught, i, iter); + VEC_iterate (int, c->syscalls_to_be_caught, i, iter); i++) if (syscall_number == iter) return 1; @@ -11923,10 +12777,10 @@ trace_command (char *arg, int from_tty) bp_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */)) + 0 /* internal */, 0)) set_tracepoint_count (breakpoint_count); } @@ -11940,10 +12794,10 @@ ftrace_command (char *arg, int from_tty) bp_fast_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */)) + 0 /* internal */, 0)) set_tracepoint_count (breakpoint_count); } @@ -11959,10 +12813,10 @@ strace_command (char *arg, int from_tty) bp_static_tracepoint /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, from_tty, 1 /* enabled */, - 0 /* internal */)) + 0 /* internal */, 0)) set_tracepoint_count (breakpoint_count); } @@ -11990,11 +12844,11 @@ read_uploaded_action (void) the target does not necessarily have all the information used when the tracepoint was originally defined. */ -struct breakpoint * +struct tracepoint * create_tracepoint_from_upload (struct uploaded_tp *utp) { char *addr_str, small_buf[100]; - struct breakpoint *tp; + struct tracepoint *tp; if (utp->at_string) addr_str = utp->at_string; @@ -12024,10 +12878,11 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) utp->type /* type_wanted */, 0 /* Ignore count */, pending_break_support, - NULL, + &tracepoint_breakpoint_ops, 0 /* from_tty */, utp->enabled /* enabled */, - 0 /* internal */)) + 0 /* internal */, + CREATE_BREAKPOINT_FLAGS_INSERTED)) return NULL; set_tracepoint_count (breakpoint_count); @@ -12038,7 +12893,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) if (utp->pass > 0) { - sprintf (small_buf, "%d %d", utp->pass, tp->number); + sprintf (small_buf, "%d %d", utp->pass, tp->base.number); trace_pass_command (small_buf, 0); } @@ -12056,7 +12911,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL); - breakpoint_set_commands (tp, cmd_list); + breakpoint_set_commands (&tp->base, cmd_list); } else if (!VEC_empty (char_ptr, utp->actions) || !VEC_empty (char_ptr, utp->step_actions)) @@ -12064,8 +12919,12 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) "have no source form, ignoring them"), utp->number); + /* Copy any status information that might be available. */ + tp->base.hit_count = utp->hit_count; + tp->traceframe_usage = utp->traceframe_usage; + return tp; - } +} /* Print information on tracepoint number TPNUM_EXP, or all if omitted. */ @@ -12073,6 +12932,7 @@ create_tracepoint_from_upload (struct uploaded_tp *utp) static void tracepoints_info (char *args, int from_tty) { + struct ui_out *uiout = current_uiout; int num_printed; num_printed = breakpoint_1 (args, 0, is_tracepoint); @@ -12121,40 +12981,35 @@ delete_trace_command (char *arg, int from_tty) have to be deleted with an explicit breakpoint number argument. */ ALL_TRACEPOINTS (b) - { - if (b->number >= 0) + if (is_tracepoint (b) && user_breakpoint_p (b)) { breaks_to_delete = 1; break; } - } /* Ask user only if there are some breakpoints to delete. */ if (!from_tty || (breaks_to_delete && query (_("Delete all tracepoints? ")))) { ALL_BREAKPOINTS_SAFE (b, b_tmp) - { - if (is_tracepoint (b) - && b->number >= 0) + if (is_tracepoint (b) && user_breakpoint_p (b)) delete_breakpoint (b); - } } } else - map_breakpoint_numbers (arg, do_delete_breakpoint, NULL); + map_breakpoint_numbers (arg, do_map_delete_breakpoint, NULL); } /* Helper function for trace_pass_command. */ static void -trace_pass_set_count (struct breakpoint *bp, int count, int from_tty) +trace_pass_set_count (struct tracepoint *tp, int count, int from_tty) { - bp->pass_count = count; - observer_notify_tracepoint_modified (bp->number); + tp->pass_count = count; + observer_notify_tracepoint_modified (tp->base.number); if (from_tty) printf_filtered (_("Setting tracepoint %d's passcount to %d\n"), - bp->number, count); + tp->base.number, count); } /* Set passcount for tracepoint. @@ -12166,7 +13021,7 @@ trace_pass_set_count (struct breakpoint *bp, int count, int from_tty) static void trace_pass_command (char *args, int from_tty) { - struct breakpoint *t1; + struct tracepoint *t1; unsigned int count; if (args == 0 || *args == 0) @@ -12180,12 +13035,15 @@ trace_pass_command (char *args, int from_tty) if (*args && strncasecmp (args, "all", 3) == 0) { + struct breakpoint *b; + args += 3; /* Skip special argument "all". */ if (*args) error (_("Junk at end of arguments.")); - ALL_TRACEPOINTS (t1) + ALL_TRACEPOINTS (b) { + t1 = (struct tracepoint *) b; trace_pass_set_count (t1, count, from_tty); } } @@ -12209,14 +13067,14 @@ trace_pass_command (char *args, int from_tty) } } -struct breakpoint * +struct tracepoint * get_tracepoint (int num) { struct breakpoint *t; ALL_TRACEPOINTS (t) if (t->number == num) - return t; + return (struct tracepoint *) t; return NULL; } @@ -12225,14 +13083,18 @@ get_tracepoint (int num) different from the tracepoint number after disconnecting and reconnecting). */ -struct breakpoint * +struct tracepoint * get_tracepoint_by_number_on_target (int num) { - struct breakpoint *t; + struct breakpoint *b; - ALL_TRACEPOINTS (t) - if (t->number_on_target == num) - return t; + ALL_TRACEPOINTS (b) + { + struct tracepoint *t = (struct tracepoint *) b; + + if (t->number_on_target == num) + return t; + } return NULL; } @@ -12241,7 +13103,7 @@ get_tracepoint_by_number_on_target (int num) If STATE is not NULL, use, get_number_or_range_state and ignore ARG. If OPTIONAL_P is true, then if the argument is missing, the most recent tracepoint (tracepoint_count) is returned. */ -struct breakpoint * +struct tracepoint * get_tracepoint_by_number (char **arg, struct get_number_or_range_state *state, int optional_p) @@ -12280,13 +13142,25 @@ get_tracepoint_by_number (char **arg, ALL_TRACEPOINTS (t) if (t->number == tpnum) { - return t; + return (struct tracepoint *) t; } printf_unfiltered ("No tracepoint number %d.\n", tpnum); return NULL; } +void +print_recreate_thread (struct breakpoint *b, struct ui_file *fp) +{ + if (b->thread != -1) + fprintf_unfiltered (fp, " thread %d", b->thread); + + if (b->task != 0) + fprintf_unfiltered (fp, " task %d", b->task); + + fprintf_unfiltered (fp, "\n"); +} + /* Save information on user settable breakpoints (watchpoints, etc) to a new script file named FILENAME. If FILTER is non-NULL, call it on each breakpoint and only include the ones for which it returns @@ -12355,57 +13229,7 @@ save_breakpoints (char *filename, int from_tty, if (filter && !filter (tp)) continue; - if (tp->ops != NULL && tp->ops->print_recreate != NULL) - (tp->ops->print_recreate) (tp, fp); - else - { - if (tp->type == bp_fast_tracepoint) - fprintf_unfiltered (fp, "ftrace"); - if (tp->type == bp_static_tracepoint) - fprintf_unfiltered (fp, "strace"); - else if (tp->type == bp_tracepoint) - fprintf_unfiltered (fp, "trace"); - else if (tp->type == bp_breakpoint && tp->disposition == disp_del) - fprintf_unfiltered (fp, "tbreak"); - else if (tp->type == bp_breakpoint) - fprintf_unfiltered (fp, "break"); - else if (tp->type == bp_hardware_breakpoint - && tp->disposition == disp_del) - fprintf_unfiltered (fp, "thbreak"); - else if (tp->type == bp_hardware_breakpoint) - fprintf_unfiltered (fp, "hbreak"); - else if (tp->type == bp_watchpoint) - fprintf_unfiltered (fp, "watch"); - else if (tp->type == bp_hardware_watchpoint) - fprintf_unfiltered (fp, "watch"); - else if (tp->type == bp_read_watchpoint) - fprintf_unfiltered (fp, "rwatch"); - else if (tp->type == bp_access_watchpoint) - fprintf_unfiltered (fp, "awatch"); - else - internal_error (__FILE__, __LINE__, - _("unhandled breakpoint type %d"), (int) tp->type); - - if (tp->exp_string) - fprintf_unfiltered (fp, " %s", tp->exp_string); - else if (tp->addr_string) - fprintf_unfiltered (fp, " %s", tp->addr_string); - else - { - char tmp[40]; - - sprintf_vma (tmp, tp->loc->address); - fprintf_unfiltered (fp, " *0x%s", tmp); - } - } - - if (tp->thread != -1) - fprintf_unfiltered (fp, " thread %d", tp->thread); - - if (tp->task != 0) - fprintf_unfiltered (fp, " task %d", tp->task); - - fprintf_unfiltered (fp, "\n"); + tp->ops->print_recreate (tp, fp); /* Note, we can't rely on tp->number for anything, as we can't assume the recreated breakpoint numbers will match. Use $bpnum @@ -12417,21 +13241,18 @@ save_breakpoints (char *filename, int from_tty, if (tp->ignore_count) fprintf_unfiltered (fp, " ignore $bpnum %d\n", tp->ignore_count); - if (tp->pass_count) - fprintf_unfiltered (fp, " passcount %d\n", tp->pass_count); - if (tp->commands) { volatile struct gdb_exception ex; fprintf_unfiltered (fp, " commands\n"); - ui_out_redirect (uiout, fp); + ui_out_redirect (current_uiout, fp); TRY_CATCH (ex, RETURN_MASK_ALL) { - print_command_lines (uiout, tp->commands->commands, 2); + print_command_lines (current_uiout, tp->commands->commands, 2); } - ui_out_redirect (uiout, NULL); + ui_out_redirect (current_uiout, NULL); if (ex.reason < 0) throw_exception (ex); @@ -12524,9 +13345,7 @@ static struct cmd_list_element *catch_cmdlist; /* List of subcommands for "tcatch". */ static struct cmd_list_element *tcatch_cmdlist; -/* Like add_cmd, but add the command to both the "catch" and "tcatch" - lists, and pass some additional user data to the command function. */ -static void +void add_catch_command (char *name, char *docstring, void (*sfunc) (char *args, int from_tty, struct cmd_list_element *command), @@ -12581,11 +13400,200 @@ iterate_over_breakpoints (int (*callback) (struct breakpoint *, void *), return NULL; } +/* Zero if any of the breakpoint's locations could be a location where + functions have been inlined, nonzero otherwise. */ + +static int +is_non_inline_function (struct breakpoint *b) +{ + /* The shared library event breakpoint is set on the address of a + non-inline function. */ + if (b->type == bp_shlib_event) + return 1; + + return 0; +} + +/* Nonzero if the specified PC cannot be a location where functions + have been inlined. */ + +int +pc_at_non_inline_function (struct address_space *aspace, CORE_ADDR pc) +{ + struct breakpoint *b; + struct bp_location *bl; + + ALL_BREAKPOINTS (b) + { + if (!is_non_inline_function (b)) + continue; + + for (bl = b->loc; bl != NULL; bl = bl->next) + { + if (!bl->shlib_disabled + && bpstat_check_location (bl, aspace, pc)) + return 1; + } + } + + return 0; +} + +void +initialize_breakpoint_ops (void) +{ + static int initialized = 0; + + struct breakpoint_ops *ops; + + if (initialized) + return; + initialized = 1; + + /* The breakpoint_ops structure to be inherit by all kinds of + breakpoints (real breakpoints, i.e., user "break" breakpoints, + internal and momentary breakpoints, etc.). */ + ops = &bkpt_base_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->re_set = bkpt_re_set; + ops->insert_location = bkpt_insert_location; + ops->remove_location = bkpt_remove_location; + ops->breakpoint_hit = bkpt_breakpoint_hit; + + /* The breakpoint_ops structure to be used in regular breakpoints. */ + ops = &bkpt_breakpoint_ops; + *ops = bkpt_base_breakpoint_ops; + ops->re_set = bkpt_re_set; + ops->resources_needed = bkpt_resources_needed; + ops->print_it = bkpt_print_it; + ops->print_mention = bkpt_print_mention; + ops->print_recreate = bkpt_print_recreate; + + /* Ranged breakpoints. */ + ops = &ranged_breakpoint_ops; + *ops = bkpt_breakpoint_ops; + ops->breakpoint_hit = breakpoint_hit_ranged_breakpoint; + ops->resources_needed = resources_needed_ranged_breakpoint; + ops->print_it = print_it_ranged_breakpoint; + ops->print_one = print_one_ranged_breakpoint; + ops->print_one_detail = print_one_detail_ranged_breakpoint; + ops->print_mention = print_mention_ranged_breakpoint; + ops->print_recreate = print_recreate_ranged_breakpoint; + + /* Internal breakpoints. */ + ops = &internal_breakpoint_ops; + *ops = bkpt_base_breakpoint_ops; + ops->re_set = internal_bkpt_re_set; + ops->check_status = internal_bkpt_check_status; + ops->print_it = internal_bkpt_print_it; + ops->print_mention = internal_bkpt_print_mention; + + /* Momentary breakpoints. */ + ops = &momentary_breakpoint_ops; + *ops = bkpt_base_breakpoint_ops; + ops->re_set = momentary_bkpt_re_set; + ops->check_status = momentary_bkpt_check_status; + ops->print_it = momentary_bkpt_print_it; + ops->print_mention = momentary_bkpt_print_mention; + + /* GNU v3 exception catchpoints. */ + ops = &gnu_v3_exception_catchpoint_ops; + *ops = bkpt_breakpoint_ops; + ops->print_it = print_it_exception_catchpoint; + ops->print_one = print_one_exception_catchpoint; + ops->print_mention = print_mention_exception_catchpoint; + ops->print_recreate = print_recreate_exception_catchpoint; + + /* Watchpoints. */ + ops = &watchpoint_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->dtor = dtor_watchpoint; + ops->re_set = re_set_watchpoint; + ops->insert_location = insert_watchpoint; + ops->remove_location = remove_watchpoint; + ops->breakpoint_hit = breakpoint_hit_watchpoint; + ops->check_status = check_status_watchpoint; + ops->resources_needed = resources_needed_watchpoint; + ops->works_in_software_mode = works_in_software_mode_watchpoint; + ops->print_it = print_it_watchpoint; + ops->print_mention = print_mention_watchpoint; + ops->print_recreate = print_recreate_watchpoint; + + /* Masked watchpoints. */ + ops = &masked_watchpoint_breakpoint_ops; + *ops = watchpoint_breakpoint_ops; + ops->insert_location = insert_masked_watchpoint; + ops->remove_location = remove_masked_watchpoint; + ops->resources_needed = resources_needed_masked_watchpoint; + ops->works_in_software_mode = works_in_software_mode_masked_watchpoint; + ops->print_it = print_it_masked_watchpoint; + ops->print_one_detail = print_one_detail_masked_watchpoint; + ops->print_mention = print_mention_masked_watchpoint; + ops->print_recreate = print_recreate_masked_watchpoint; + + /* Tracepoints. */ + ops = &tracepoint_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->re_set = tracepoint_re_set; + ops->breakpoint_hit = tracepoint_breakpoint_hit; + ops->print_one_detail = tracepoint_print_one_detail; + ops->print_mention = tracepoint_print_mention; + ops->print_recreate = tracepoint_print_recreate; + + /* Fork catchpoints. */ + ops = &catch_fork_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->insert_location = insert_catch_fork; + ops->remove_location = remove_catch_fork; + ops->breakpoint_hit = breakpoint_hit_catch_fork; + ops->print_it = print_it_catch_fork; + ops->print_one = print_one_catch_fork; + ops->print_mention = print_mention_catch_fork; + ops->print_recreate = print_recreate_catch_fork; + + /* Vfork catchpoints. */ + ops = &catch_vfork_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->insert_location = insert_catch_vfork; + ops->remove_location = remove_catch_vfork; + ops->breakpoint_hit = breakpoint_hit_catch_vfork; + ops->print_it = print_it_catch_vfork; + ops->print_one = print_one_catch_vfork; + ops->print_mention = print_mention_catch_vfork; + ops->print_recreate = print_recreate_catch_vfork; + + /* Exec catchpoints. */ + ops = &catch_exec_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->dtor = dtor_catch_exec; + ops->insert_location = insert_catch_exec; + ops->remove_location = remove_catch_exec; + ops->breakpoint_hit = breakpoint_hit_catch_exec; + ops->print_it = print_it_catch_exec; + ops->print_one = print_one_catch_exec; + ops->print_mention = print_mention_catch_exec; + ops->print_recreate = print_recreate_catch_exec; + + /* Syscall catchpoints. */ + ops = &catch_syscall_breakpoint_ops; + *ops = base_breakpoint_ops; + ops->dtor = dtor_catch_syscall; + ops->insert_location = insert_catch_syscall; + ops->remove_location = remove_catch_syscall; + ops->breakpoint_hit = breakpoint_hit_catch_syscall; + ops->print_it = print_it_catch_syscall; + ops->print_one = print_one_catch_syscall; + ops->print_mention = print_mention_catch_syscall; + ops->print_recreate = print_recreate_catch_syscall; +} + void _initialize_breakpoint (void) { struct cmd_list_element *c; + initialize_breakpoint_ops (); + observer_attach_solib_unloaded (disable_breakpoints_in_unloaded_shlib); observer_attach_inferior_exit (clear_syscall_counts); observer_attach_memory_changed (invalidate_bp_value_on_memory_change); @@ -12692,7 +13700,7 @@ If a breakpoint is hit while enabled in this fashion, it becomes disabled."), Disable some breakpoints.\n\ Arguments are breakpoint numbers with spaces in between.\n\ To disable all breakpoints, give no argument.\n\ -A disabled breakpoint is not forgotten, but has no effect until reenabled."), +A disabled breakpoint is not forgotten, but has no effect until re-enabled."), &disablelist, "disable ", 1, &cmdlist); add_com_alias ("dis", "disable", class_breakpoint, 1); add_com_alias ("disa", "disable", class_breakpoint, 1); @@ -12701,13 +13709,13 @@ A disabled breakpoint is not forgotten, but has no effect until reenabled."), Disable some breakpoints.\n\ Arguments are breakpoint numbers with spaces in between.\n\ To disable all breakpoints, give no argument.\n\ -A disabled breakpoint is not forgotten, but has no effect until reenabled.")); +A disabled breakpoint is not forgotten, but has no effect until re-enabled.")); add_cmd ("breakpoints", class_alias, disable_command, _("\ Disable some breakpoints.\n\ Arguments are breakpoint numbers with spaces in between.\n\ To disable all breakpoints, give no argument.\n\ -A disabled breakpoint is not forgotten, but has no effect until reenabled.\n\ +A disabled breakpoint is not forgotten, but has no effect until re-enabled.\n\ This command may be abbreviated \"disable\"."), &disablelist); @@ -12892,20 +13900,6 @@ Arguments, if given, should be one or more system call names\n\ catch_syscall_completer, CATCH_PERMANENT, CATCH_TEMPORARY); - add_catch_command ("exception", _("\ -Catch Ada exceptions, when raised.\n\ -With an argument, catch only exceptions with the given name."), - catch_ada_exception_command, - NULL, - CATCH_PERMANENT, - CATCH_TEMPORARY); - add_catch_command ("assert", _("\ -Catch failed Ada assertions, when raised.\n\ -With an argument, catch only exceptions with the given name."), - catch_assert_command, - NULL, - CATCH_PERMANENT, - CATCH_TEMPORARY); c = add_com ("watch", class_breakpoint, watch_command, _("\ Set a watchpoint for an expression.\n\ diff --git a/contrib/gdb-7/gdb/breakpoint.h b/contrib/gdb-7/gdb/breakpoint.h index 7a9c2d4729..3548d13a67 100644 --- a/contrib/gdb-7/gdb/breakpoint.h +++ b/contrib/gdb-7/gdb/breakpoint.h @@ -1,7 +1,5 @@ /* Data structures associated with breakpoints in GDB. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -29,6 +27,9 @@ struct value; struct block; struct breakpoint_object; struct get_number_or_range_state; +struct thread_info; +struct bpstats; +struct bp_location; /* This is the maximum number of bytes a breakpoint instruction can take. Feel free to increase it. It's just used in a few places to @@ -68,10 +69,13 @@ enum bptype bp_exception_resume, /* Used by wait_for_inferior for stepping over subroutine calls, - for stepping over signal handlers, and for skipping - prologues. */ + and for skipping prologues. */ bp_step_resume, + /* Used by wait_for_inferior for stepping over signal + handlers. */ + bp_hp_step_resume, + /* Used to detect when a watchpoint expression has gone out of scope. These breakpoints are usually not visible to the user. @@ -180,14 +184,6 @@ enum enable_state automatically enabled and reset when the call "lands" (either completes, or stops at another eventpoint). */ - bp_startup_disabled, /* The eventpoint has been disabled during - inferior startup. This is necessary on - some targets where the main executable - will get relocated during startup, making - breakpoint addresses invalid. The - eventpoint will be automatically enabled - and reset once inferior startup is - complete. */ bp_permanent /* There is a breakpoint instruction hard-wired into the target's code. Don't try to write another breakpoint @@ -274,12 +270,26 @@ enum bp_loc_type bp_loc_other /* Miscellaneous... */ }; +/* This structure is a collection of function pointers that, if + available, will be called instead of performing the default action + for this bp_loc_type. */ + +struct bp_location_ops +{ + /* Destructor. Releases everything from SELF (but not SELF + itself). */ + void (*dtor) (struct bp_location *self); +}; + struct bp_location { /* Chain pointer to the next breakpoint location for the same parent breakpoint. */ struct bp_location *next; + /* Methods associated with this location. */ + const struct bp_location_ops *ops; + /* The reference count. */ int refc; @@ -315,7 +325,11 @@ struct bp_location char inserted; /* Nonzero if this is not the first breakpoint in the list - for the given address. */ + for the given address. location of tracepoint can _never_ + be duplicated with other locations of tracepoints and other + kinds of breakpoints, because two locations at the same + address may have different actions, so both of these locations + should be downloaded and so that `tfind N' always works. */ char duplicate; /* If we someday support real thread-specific breakpoints, then @@ -381,6 +395,14 @@ struct bp_location This variable keeps a number of events still to go, when it becomes 0 this location is retired. */ int events_till_retirement; + + /* Line number of this address. */ + + int line_number; + + /* Source file name of this address. */ + + char *source_file; }; /* This structure is a collection of function pointers that, if available, @@ -389,9 +411,21 @@ struct bp_location struct breakpoint_ops { + /* Destructor. Releases everything from SELF (but not SELF + itself). */ + void (*dtor) (struct breakpoint *self); + + /* Allocate a location for this breakpoint. */ + struct bp_location * (*allocate_location) (struct breakpoint *); + + /* Reevaluate a breakpoint. This is necessary after symbols change + (e.g., an executable or DSO was loaded, or the inferior just + started). */ + void (*re_set) (struct breakpoint *self); + /* Insert the breakpoint or watchpoint or activate the catchpoint. - Return 0 for success, 1 if the breakpoint, watchpoint or catchpoint - type is not supported, -1 for failure. */ + Return 0 for success, 1 if the breakpoint, watchpoint or + catchpoint type is not supported, -1 for failure. */ int (*insert_location) (struct bp_location *); /* Remove the breakpoint/catchpoint that was previously inserted @@ -400,19 +434,29 @@ struct breakpoint_ops -1 for failure. */ int (*remove_location) (struct bp_location *); - /* Return non-zero if the debugger should tell the user that this - breakpoint was hit. */ - int (*breakpoint_hit) (const struct bp_location *, struct address_space *, + /* Return true if it the target has stopped due to hitting + breakpoint location BL. This function does not check if we + should stop, only if BL explains the stop. */ + int (*breakpoint_hit) (const struct bp_location *bl, struct address_space *, CORE_ADDR); + /* Check internal conditions of the breakpoint referred to by BS. + If we should not stop for this breakpoint, set BS->stop to 0. */ + void (*check_status) (struct bpstats *bs); + /* Tell how many hardware resources (debug registers) are needed for this breakpoint. If this function is not provided, then the breakpoint or watchpoint needs one debug register. */ int (*resources_needed) (const struct bp_location *); + /* Tell whether we can downgrade from a hardware watchpoint to a software + one. If not, the user will not be able to enable the watchpoint when + there are not enough hardware resources available. */ + int (*works_in_software_mode) (const struct breakpoint *); + /* The normal print routine for this breakpoint, called when we hit it. */ - enum print_stop_action (*print_it) (struct breakpoint *); + enum print_stop_action (*print_it) (struct bpstats *bs); /* Display information about this breakpoint, for "info breakpoints". */ @@ -440,6 +484,15 @@ struct breakpoint_ops void (*print_recreate) (struct breakpoint *, struct ui_file *fp); }; +/* Helper for breakpoint_ops->print_recreate implementations. Prints + the "thread" or "task" condition of B, and then a newline. + + Necessary because most breakpoint implementations accept + thread/task conditions at the end of the spec line, like "break foo + thread 1", which needs outputting before any breakpoint-type + specific extra command necessary for B's recreation. */ +extern void print_recreate_thread (struct breakpoint *b, struct ui_file *fp); + enum watchpoint_triggered { /* This watchpoint definitely did not trigger. */ @@ -477,10 +530,13 @@ extern int target_exact_watchpoints; useful for a hack I had to put in; I'm going to leave it in because I can see how there might be times when it would indeed be useful */ -/* This is for a breakpoint or a watchpoint. */ +/* This is for all kinds of breakpoints. */ struct breakpoint { + /* Methods associated with this breakpoint. */ + const struct breakpoint_ops *ops; + struct breakpoint *next; /* Type of breakpoint. */ enum bptype type; @@ -494,14 +550,6 @@ struct breakpoint /* Location(s) associated with this high-level breakpoint. */ struct bp_location *loc; - /* Line number of this address. */ - - int line_number; - - /* Source file name of this address. */ - - char *source_file; - /* Non-zero means a silent breakpoint (don't print frame info if we stop here). */ unsigned char silent; @@ -517,12 +565,19 @@ struct breakpoint equals this. */ struct frame_id frame_id; - /* The program space used to set the breakpoint. */ + /* 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. */ struct program_space *pspace; /* String we used to set the breakpoint (malloc'd). */ char *addr_string; + /* The filter that should be passed to decode_line_full when + re-setting this breakpoint. This may be NULL, but otherwise is + allocated with xmalloc. */ + char *filter; + /* For a ranged breakpoint, the string we used to find the end of the range (malloc'd). */ char *addr_string_range_end; @@ -538,27 +593,6 @@ struct breakpoint char *cond_string; /* String form of exp to use for displaying to the user (malloc'd), or NULL if none. */ - char *exp_string; - /* String form to use for reparsing of EXP (malloc'd) or NULL. */ - char *exp_string_reparse; - - /* The expression we are watching, or NULL if not a watchpoint. */ - struct expression *exp; - /* The largest block within which it is valid, or NULL if it is - valid anywhere (e.g. consists just of global symbols). */ - struct block *exp_valid_block; - /* The conditional expression if any. NULL if not a watchpoint. */ - struct expression *cond_exp; - /* The largest block within which it is valid, or NULL if it is - valid anywhere (e.g. consists just of global symbols). */ - struct block *cond_exp_valid_block; - /* Value of the watchpoint the last time we checked it, or NULL - when we do not know the value yet or the value was not - readable. VAL is never lazy. */ - struct value *val; - /* Nonzero if VAL is valid. If VAL_VALID is set but VAL is NULL, - then an error occurred reading the value. */ - int val_valid; /* Holds the address of the related watchpoint_scope breakpoint when using watchpoints on local variables (might the concept of @@ -567,20 +601,6 @@ struct breakpoint FIXME). */ struct breakpoint *related_breakpoint; - /* Holds the frame address which identifies the frame this - watchpoint should be evaluated in, or `null' if the watchpoint - should be evaluated on the outermost frame. */ - struct frame_id watchpoint_frame; - - /* Holds the thread which identifies the frame this watchpoint - should be considered in scope for, or `null_ptid' if the - watchpoint should be evaluated in all threads. */ - ptid_t watchpoint_thread; - - /* For hardware watchpoints, the triggered status according to the - hardware. */ - enum watchpoint_triggered watchpoint_triggered; - /* Thread number for thread-specific breakpoint, or -1 if don't care. */ int thread; @@ -595,64 +615,114 @@ struct breakpoint aborting, so you can back up to just before the abort. */ int hit_count; - /* Process id of a child process whose forking triggered this - catchpoint. This field is only valid immediately after this - catchpoint has triggered. */ - ptid_t forked_inferior_pid; - - /* Filename of a program whose exec triggered this catchpoint. - This field is only valid immediately after this catchpoint has - triggered. */ - char *exec_pathname; - - /* Syscall numbers used for the 'catch syscall' feature. If no - syscall has been specified for filtering, its value is NULL. - Otherwise, it holds a list of all syscalls to be caught. The - list elements are allocated with xmalloc. */ - VEC(int) *syscalls_to_be_caught; - - /* Methods associated with this breakpoint. */ - struct breakpoint_ops *ops; - /* Is breakpoint's condition not yet parsed because we found no location initially so had no context to parse the condition in. */ int condition_not_parsed; - /* Number of times this tracepoint should single-step - and collect additional data. */ - long step_count; - - /* Number of times this tracepoint should be hit before - disabling/ending. */ - int pass_count; - - /* The number of the tracepoint on the target. */ - int number_on_target; - - /* The static tracepoint marker id, if known. */ - char *static_trace_marker_id; - - /* LTTng/UST allow more than one marker with the same ID string, - although it unadvised because it confuses tools. When setting - static tracepoints by marker ID, this will record the index in - the array of markers we found for the given marker ID for which - this static tracepoint corresponds. When resetting - breakpoints, we will use this index to try to find the same - marker again. */ - int static_trace_marker_id_idx; - /* With a Python scripting enabled GDB, store a reference to the Python object that has been associated with this breakpoint. This is always NULL for a GDB that is not script enabled. It can sometimes be NULL for enabled GDBs as not all breakpoint types are tracked by the Python scripting API. */ struct breakpoint_object *py_bp_object; - - /* Whether this watchpoint is exact (see target_exact_watchpoints). */ - int exact; }; +/* An instance of this type is used to represent a watchpoint. It + includes a "struct breakpoint" as a kind of base class; users + downcast to "struct breakpoint *" when needed. */ + +struct watchpoint +{ + /* The base class. */ + struct breakpoint base; + + /* String form of exp to use for displaying to the user (malloc'd), + or NULL if none. */ + char *exp_string; + /* String form to use for reparsing of EXP (malloc'd) or NULL. */ + char *exp_string_reparse; + + /* The expression we are watching, or NULL if not a watchpoint. */ + struct expression *exp; + /* The largest block within which it is valid, or NULL if it is + valid anywhere (e.g. consists just of global symbols). */ + struct block *exp_valid_block; + /* The conditional expression if any. */ + struct expression *cond_exp; + /* The largest block within which it is valid, or NULL if it is + valid anywhere (e.g. consists just of global symbols). */ + struct block *cond_exp_valid_block; + /* Value of the watchpoint the last time we checked it, or NULL when + we do not know the value yet or the value was not readable. VAL + is never lazy. */ + struct value *val; + /* Nonzero if VAL is valid. If VAL_VALID is set but VAL is NULL, + then an error occurred reading the value. */ + int val_valid; + + /* Holds the frame address which identifies the frame this + watchpoint should be evaluated in, or `null' if the watchpoint + should be evaluated on the outermost frame. */ + struct frame_id watchpoint_frame; + + /* Holds the thread which identifies the frame this watchpoint + should be considered in scope for, or `null_ptid' if the + watchpoint should be evaluated in all threads. */ + ptid_t watchpoint_thread; + + /* For hardware watchpoints, the triggered status according to the + hardware. */ + enum watchpoint_triggered watchpoint_triggered; + + /* Whether this watchpoint is exact (see + target_exact_watchpoints). */ + int exact; + + /* The mask address for a masked hardware watchpoint. */ + CORE_ADDR hw_wp_mask; +}; + +/* Returns true if BPT is really a watchpoint. */ + +extern int is_watchpoint (const struct breakpoint *bpt); + +/* An instance of this type is used to represent all kinds of + tracepoints. It includes a "struct breakpoint" as a kind of base + class; users downcast to "struct breakpoint *" when needed. */ + +struct tracepoint +{ + /* The base class. */ + struct breakpoint base; + + /* Number of times this tracepoint should single-step and collect + additional data. */ + long step_count; + + /* Number of times this tracepoint should be hit before + disabling/ending. */ + int pass_count; + + /* The number of the tracepoint on the target. */ + int number_on_target; + + /* The total space taken by all the trace frames for this + tracepoint. */ + ULONGEST traceframe_usage; + + /* The static tracepoint marker id, if known. */ + char *static_trace_marker_id; + + /* LTTng/UST allow more than one marker with the same ID string, + although it unadvised because it confuses tools. When setting + static tracepoints by marker ID, this will record the index in + the array of markers we found for the given marker ID for which + this static tracepoint corresponds. When resetting breakpoints, + we will use this index to try to find the same marker again. */ + int static_trace_marker_id_idx; +}; + typedef struct breakpoint *breakpoint_p; DEF_VEC_P(breakpoint_p); @@ -713,6 +783,9 @@ enum bpstat_what_main_action BPSTAT_WHAT_KEEP_CHECKING. */ BPSTAT_WHAT_CLEAR_LONGJMP_RESUME, + /* Clear step resume breakpoint, and keep checking. */ + BPSTAT_WHAT_STEP_RESUME, + /* Rather than distinguish between noisy and silent stops here, it might be cleaner to have bpstat_print make that decision (also taking into account stop_print_frame and source_only). But the @@ -725,8 +798,14 @@ enum bpstat_what_main_action /* Stop and print. */ BPSTAT_WHAT_STOP_NOISY, - /* Clear step resume breakpoint, and keep checking. */ - BPSTAT_WHAT_STEP_RESUME, + /* Clear step resume breakpoint, and keep checking. High-priority + step-resume breakpoints are used when even if there's a user + breakpoint at the current PC when we set the step-resume + breakpoint, we don't want to re-handle any breakpoint other + than the step-resume when it's hit; instead we want to move + past the breakpoint. This is used in the case of skipping + signal handlers. */ + BPSTAT_WHAT_HP_STEP_RESUME, }; /* An enum indicating the kind of "stack dummy" stop. This is a bit @@ -763,9 +842,19 @@ struct bpstat_what print_it_done, print_it_noop. */ enum print_stop_action { + /* We printed nothing or we need to do some more analysis. */ PRINT_UNKNOWN = -1, + + /* We printed something, and we *do* desire that something to be + followed by a location. */ PRINT_SRC_AND_LOC, + + /* We printed something, and we do *not* desire that something to + be followed by a location. */ PRINT_SRC_ONLY, + + /* We already printed all we needed to print, don't print anything + else. */ PRINT_NOTHING }; @@ -792,7 +881,7 @@ extern int bpstat_should_step (void); /* Print a message indicating what happened. Returns nonzero to say that only the source line should be printed after this (zero return means print the frame as well as the source line). */ -extern enum print_stop_action bpstat_print (bpstat); +extern enum print_stop_action bpstat_print (bpstat, int); /* Put in *NUM the breakpoint number of the first breakpoint we are stopped at. *BSP upon return is a bpstat which points to the @@ -811,8 +900,9 @@ extern int bpstat_num (bpstat *, int *); command loop). */ extern void bpstat_do_actions (void); -/* Modify BS so that the actions will not be performed. */ -extern void bpstat_clear_actions (bpstat); +/* Modify all entries of STOP_BPSTAT of INFERIOR_PTID so that the actions will + not be performed. */ +extern void bpstat_clear_actions (void); /* Implementation: */ @@ -866,10 +956,6 @@ struct bpstats /* The associated command list. */ struct counted_command_line *commands; - /* Commands left to be done. This points somewhere in - base_command. */ - struct command_line *commands_left; - /* Old value associated with a watchpoint. */ struct value *old_val; @@ -928,6 +1014,12 @@ extern int breakpoint_thread_match (struct address_space *, extern void until_break_command (char *, int, int); +/* Initialize a struct bp_location. */ + +extern void init_bp_location (struct bp_location *loc, + const struct bp_location_ops *ops, + struct breakpoint *owner); + extern void update_breakpoint_locations (struct breakpoint *b, struct symtabs_and_lines sals, struct symtabs_and_lines sals_end); @@ -946,9 +1038,6 @@ extern struct breakpoint *clone_momentary_breakpoint (struct breakpoint *bpkt); extern void set_ignore_count (int, int, int); -extern void set_default_breakpoint (int, struct program_space *, - CORE_ADDR, struct symtab *, int); - extern void breakpoint_init_inferior (enum inf_context); extern struct cleanup *make_cleanup_delete_breakpoint (struct breakpoint *); @@ -975,16 +1064,67 @@ extern void awatch_command_wrapper (char *, int, int); extern void rwatch_command_wrapper (char *, int, int); extern void tbreak_command (char *, int); +extern struct breakpoint_ops bkpt_breakpoint_ops; + +extern void initialize_breakpoint_ops (void); + +/* Arguments to pass as context to some catch command handlers. */ +#define CATCH_PERMANENT ((void *) (uintptr_t) 0) +#define CATCH_TEMPORARY ((void *) (uintptr_t) 1) + +/* Like add_cmd, but add the command to both the "catch" and "tcatch" + lists, and pass some additional user data to the command + function. */ + +extern void + add_catch_command (char *name, char *docstring, + void (*sfunc) (char *args, int from_tty, + struct cmd_list_element *command), + char **(*completer) (struct cmd_list_element *cmd, + char *text, char *word), + void *user_data_catch, + void *user_data_tcatch); + +/* Initialize a breakpoint struct for Ada exception catchpoints. */ + +extern void + init_ada_exception_breakpoint (struct breakpoint *b, + struct gdbarch *gdbarch, + struct symtab_and_line sal, + char *addr_string, + const struct breakpoint_ops *ops, + int tempflag, + int from_tty); + +/* Add breakpoint B on the breakpoint list, and notify the user, the + target and breakpoint_created observers of its existence. If + INTERNAL is non-zero, the breakpoint number will be allocated from + the internal breakpoint count. If UPDATE_GLL is non-zero, + update_global_location_list will be called. */ + +extern void install_breakpoint (int internal, struct breakpoint *b, + int update_gll); + +/* Flags that can be passed down to create_breakpoint, etc., to affect + breakpoint creation in several ways. */ + +enum breakpoint_create_flags + { + /* We're adding a breakpoint to our tables that is already + inserted in the target. */ + CREATE_BREAKPOINT_FLAGS_INSERTED = 1 << 0 + }; + extern int create_breakpoint (struct gdbarch *gdbarch, char *arg, char *cond_string, int thread, int parse_condition_and_thread, int tempflag, enum bptype wanted_type, int ignore_count, enum auto_boolean pending_break_support, - struct breakpoint_ops *ops, + const struct breakpoint_ops *ops, int from_tty, int enabled, - int internal); + int internal, unsigned flags); extern void insert_breakpoints (void); @@ -1044,7 +1184,7 @@ extern void delete_std_terminate_breakpoint (void); /* These functions respectively disable or reenable all currently enabled watchpoints. When disabled, the watchpoints are marked - call_disabled. When reenabled, they are marked enabled. + call_disabled. When re-enabled, they are marked enabled. The intended client of these functions is call_function_by_hand. @@ -1058,7 +1198,7 @@ extern void delete_std_terminate_breakpoint (void); and that can cause execution control to become very confused. Note that if a user sets breakpoints in an interactively called - function, the call_disabled watchpoints will have been reenabled + function, the call_disabled watchpoints will have been re-enabled when the first such breakpoint is reached. However, on targets that are unable to unwind through the call dummy frame, watches of stack-based storage may then be deleted, because gdb will @@ -1143,10 +1283,6 @@ extern int ep_is_catchpoint (struct breakpoint *); deletes all breakpoints. */ extern void delete_command (char *arg, int from_tty); -/* Pull all H/W watchpoints from the target. Return non-zero if the - remove fails. */ -extern int remove_hw_watchpoints (void); - /* Manage a software single step breakpoint (or two). Insert may be called twice before remove is called. */ extern void insert_single_step_breakpoint (struct gdbarch *, @@ -1168,10 +1304,17 @@ extern int deprecated_remove_raw_breakpoint (struct gdbarch *, void *); target. */ int watchpoints_triggered (struct target_waitstatus *); -/* Update BUF, which is LEN bytes read from the target address MEMADDR, - by replacing any memory breakpoints with their shadowed contents. */ -void breakpoint_restore_shadows (gdb_byte *buf, ULONGEST memaddr, - LONGEST len); +/* Helper for transparent breakpoint hiding for memory read and write + routines. + + Update one of READBUF or WRITEBUF with either the shadows + (READBUF), or the breakpoint instructions (WRITEBUF) of inserted + breakpoints at the memory range defined by MEMADDR and extending + for LEN bytes. If writing, then WRITEBUF is a copy of WRITEBUF_ORG + on entry.*/ +extern void breakpoint_xfer_memory (gdb_byte *readbuf, gdb_byte *writebuf, + const gdb_byte *writebuf_org, + ULONGEST memaddr, LONGEST len); extern int breakpoints_always_inserted_mode (void); @@ -1194,12 +1337,12 @@ extern int catch_syscall_enabled (void); extern int catching_syscall_number (int syscall_number); /* Return a tracepoint with the given number if found. */ -extern struct breakpoint *get_tracepoint (int num); +extern struct tracepoint *get_tracepoint (int num); -extern struct breakpoint *get_tracepoint_by_number_on_target (int num); +extern struct tracepoint *get_tracepoint_by_number_on_target (int num); /* Find a tracepoint by parsing a number in the supplied string. */ -extern struct breakpoint * +extern struct tracepoint * get_tracepoint_by_number (char **arg, struct get_number_or_range_state *state, int optional_p); @@ -1235,6 +1378,15 @@ extern void end_rbreak_breakpoints (void); extern struct breakpoint *iterate_over_breakpoints (int (*) (struct breakpoint *, void *), void *); +/* Nonzero if the specified PC cannot be a location where functions + have been inlined. */ + +extern int pc_at_non_inline_function (struct address_space *aspace, + CORE_ADDR pc); + extern int user_breakpoint_p (struct breakpoint *); +/* Attempt to determine architecture of location identified by SAL. */ +extern struct gdbarch *get_sal_arch (struct symtab_and_line sal); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/contrib/gdb-7/gdb/bsd-kvm.c b/contrib/gdb-7/gdb/bsd-kvm.c index f224835f66..39bd39639d 100644 --- a/contrib/gdb-7/gdb/bsd-kvm.c +++ b/contrib/gdb-7/gdb/bsd-kvm.c @@ -1,7 +1,6 @@ /* BSD Kernel Data Access Library (libkvm) interface. - Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bsd-kvm.h b/contrib/gdb-7/gdb/bsd-kvm.h index 4af3927c0a..d06e26ab1a 100644 --- a/contrib/gdb-7/gdb/bsd-kvm.h +++ b/contrib/gdb-7/gdb/bsd-kvm.h @@ -1,7 +1,6 @@ /* BSD Kernel Data Access Library (libkvm) interface. - Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bsd-uthread.c b/contrib/gdb-7/gdb/bsd-uthread.c index 1f09415521..ea9831be9b 100644 --- a/contrib/gdb-7/gdb/bsd-uthread.c +++ b/contrib/gdb-7/gdb/bsd-uthread.c @@ -1,7 +1,6 @@ /* BSD user-level threads support. - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/bsd-uthread.h b/contrib/gdb-7/gdb/bsd-uthread.h index a282fde1ea..9145507f21 100644 --- a/contrib/gdb-7/gdb/bsd-uthread.h +++ b/contrib/gdb-7/gdb/bsd-uthread.h @@ -1,7 +1,6 @@ /* BSD user-level threads support. - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/buildsym.c b/contrib/gdb-7/gdb/buildsym.c index cd159a71cd..38bde22e20 100644 --- a/contrib/gdb-7/gdb/buildsym.c +++ b/contrib/gdb-7/gdb/buildsym.c @@ -1,7 +1,5 @@ /* Support routines for building symbol tables in GDB's internal format. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -112,11 +110,8 @@ add_free_pendings (struct pending *list) free_pendings = list; } } - -/* Add a symbol to one of the lists of symbols. While we're at it, if - we're in the C++ case and don't have full namespace debugging info, - check to see if it references an anonymous namespace; if so, add an - appropriate using directive. */ + +/* Add a symbol to one of the lists of symbols. */ void add_symbol_to_list (struct symbol *symbol, struct pending **listhead) @@ -1100,8 +1095,6 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) { symtab->dirname = NULL; } - symtab->free_code = free_linetable; - symtab->free_func = NULL; /* Use whatever language we have been using for this subfile, not the one that was deduced in allocate_symtab @@ -1112,18 +1105,10 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) symtab->language = subfile->language; /* Save the debug format string (if any) in the symtab. */ - if (subfile->debugformat != NULL) - { - symtab->debugformat = obsavestring (subfile->debugformat, - strlen (subfile->debugformat), - &objfile->objfile_obstack); - } + symtab->debugformat = subfile->debugformat; /* Similarly for the producer. */ - if (subfile->producer != NULL) - symtab->producer = obsavestring (subfile->producer, - strlen (subfile->producer), - &objfile->objfile_obstack); + symtab->producer = subfile->producer; /* All symtabs for the main file and the subfiles share a blockvector, so we need to clear primary for everything @@ -1169,12 +1154,6 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section) { xfree ((void *) subfile->line_vector); } - if (subfile->debugformat != NULL) - { - xfree ((void *) subfile->debugformat); - } - if (subfile->producer != NULL) - xfree (subfile->producer); nextsub = subfile->next; xfree ((void *) subfile); @@ -1279,20 +1258,15 @@ hashname (char *name) void -record_debugformat (char *format) +record_debugformat (const char *format) { - current_subfile->debugformat = xstrdup (format); + current_subfile->debugformat = format; } void record_producer (const char *producer) { - /* The producer is not always provided in the debugging info. - Do nothing if PRODUCER is NULL. */ - if (producer == NULL) - return; - - current_subfile->producer = xstrdup (producer); + current_subfile->producer = producer; } /* Merge the first symbol list SRCLIST into the second symbol list diff --git a/contrib/gdb-7/gdb/buildsym.h b/contrib/gdb-7/gdb/buildsym.h index 37fe69cd9b..1604ef51fb 100644 --- a/contrib/gdb-7/gdb/buildsym.h +++ b/contrib/gdb-7/gdb/buildsym.h @@ -1,7 +1,6 @@ /* Build symbol tables in GDB's internal format. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1996, - 1997, 1998, 1999, 2000, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986-1993, 1995-2000, 2002-2003, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -70,8 +69,8 @@ struct subfile struct linetable *line_vector; int line_vector_length; enum language language; - char *producer; - char *debugformat; + const char *producer; + const char *debugformat; struct symtab *symtab; }; @@ -292,7 +291,15 @@ extern void record_pending_block (struct objfile *objfile, struct block *block, struct pending_block *opblock); -extern void record_debugformat (char *format); +/* Record the name of the debug format in the current pending symbol + table. FORMAT must be a string with a lifetime at least as long as + the symtab's objfile. */ + +extern void record_debugformat (const char *format); + +/* Record the name of the debuginfo producer (usually the compiler) in + the current pending symbol table. PRODUCER must be a string with a + lifetime at least as long as the symtab's objfile. */ extern void record_producer (const char *producer); diff --git a/contrib/gdb-7/gdb/c-exp.y b/contrib/gdb-7/gdb/c-exp.y index 3a02e9d973..bdcae3310b 100644 --- a/contrib/gdb-7/gdb/c-exp.y +++ b/contrib/gdb-7/gdb/c-exp.y @@ -1,7 +1,6 @@ /* YACC parser for C expressions, for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1989-2000, 2003-2004, 2006-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -208,6 +207,7 @@ static struct stoken operator_stoken (const char *); %token NEW DELETE %type operator %token REINTERPRET_CAST DYNAMIC_CAST STATIC_CAST CONST_CAST +%token ENTRY /* Special type cases, put in to allow the parser to distinguish different legal basetypes. */ @@ -756,6 +756,21 @@ block : block COLONCOLON name $$ = SYMBOL_BLOCK_VALUE (tem); } ; +variable: name_not_typename ENTRY + { struct symbol *sym = $1.sym; + + if (sym == NULL || !SYMBOL_IS_ARGUMENT (sym) + || !symbol_read_needs_frame (sym)) + error (_("@entry can be used only for function " + "parameters, not for \"%s\""), + copy_name ($1.stoken)); + + write_exp_elt_opcode (OP_VAR_ENTRY_VALUE); + write_exp_elt_sym (sym); + write_exp_elt_opcode (OP_VAR_ENTRY_VALUE); + } + ; + variable: block COLONCOLON name { struct symbol *sym; sym = lookup_symbol (copy_name ($3), $1, @@ -804,7 +819,7 @@ qualified_name: TYPENAME COLONCOLON name tmp_token.ptr[tmp_token.length] = 0; /* Check for valid destructor name. */ - destructor_name_p (tmp_token.ptr, type); + destructor_name_p (tmp_token.ptr, $1.type); write_exp_elt_opcode (OP_SCOPE); write_exp_elt_type (type); write_exp_string (tmp_token); @@ -2224,6 +2239,21 @@ lex_one_token (void) return toktype; } + case '@': + { + char *p = &tokstart[1]; + size_t len = strlen ("entry"); + + while (isspace (*p)) + p++; + if (strncmp (p, "entry", len) == 0 && !isalnum (p[len]) + && p[len] != '_') + { + lexptr = &p[len]; + return ENTRY; + } + } + /* FALLTHRU */ case '+': case '-': case '*': @@ -2234,7 +2264,6 @@ lex_one_token (void) case '^': case '~': case '!': - case '@': case '<': case '>': case '?': @@ -2486,7 +2515,7 @@ classify_inner_name (struct block *block, int first_name) return NAME; copy = copy_name (yylval.tsym.stoken); - new_type = cp_lookup_nested_type (type, copy, block); + new_type = cp_lookup_nested_type (yylval.tsym.type, copy, block); if (new_type == NULL) /* We know the caller won't expect us to update yylval. */ diff --git a/contrib/gdb-7/gdb/c-lang.c b/contrib/gdb-7/gdb/c-lang.c index 255fabe2bf..c4d841fa9d 100644 --- a/contrib/gdb-7/gdb/c-lang.c +++ b/contrib/gdb-7/gdb/c-lang.c @@ -1,7 +1,7 @@ /* C language support routines for GDB, the GNU debugger. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2002, 2003, - 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998-2000, 2002-2005, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -140,123 +140,6 @@ classify_type (struct type *elttype, struct gdbarch *gdbarch, return result; } -/* Return true if print_wchar can display W without resorting to a - numeric escape, false otherwise. */ - -static int -wchar_printable (gdb_wchar_t w) -{ - return (gdb_iswprint (w) - || w == LCST ('\a') || w == LCST ('\b') - || w == LCST ('\f') || w == LCST ('\n') - || w == LCST ('\r') || w == LCST ('\t') - || w == LCST ('\v')); -} - -/* A helper function that converts the contents of STRING to wide - characters and then appends them to OUTPUT. */ - -static void -append_string_as_wide (const char *string, - struct obstack *output) -{ - for (; *string; ++string) - { - gdb_wchar_t w = gdb_btowc (*string); - obstack_grow (output, &w, sizeof (gdb_wchar_t)); - } -} - -/* Print a wide character W to OUTPUT. ORIG is a pointer to the - original (target) bytes representing the character, ORIG_LEN is the - number of valid bytes. WIDTH is the number of bytes in a base - characters of the type. OUTPUT is an obstack to which wide - characters are emitted. QUOTER is a (narrow) character indicating - the style of quotes surrounding the character to be printed. - NEED_ESCAPE is an in/out flag which is used to track numeric - escapes across calls. */ - -static void -print_wchar (gdb_wint_t w, const gdb_byte *orig, - int orig_len, int width, - enum bfd_endian byte_order, - struct obstack *output, - int quoter, int *need_escapep) -{ - int need_escape = *need_escapep; - - *need_escapep = 0; - if (gdb_iswprint (w) && (!need_escape || (!gdb_iswdigit (w) - && w != LCST ('8') - && w != LCST ('9')))) - { - gdb_wchar_t wchar = w; - - if (w == gdb_btowc (quoter) || w == LCST ('\\')) - obstack_grow_wstr (output, LCST ("\\")); - obstack_grow (output, &wchar, sizeof (gdb_wchar_t)); - } - else - { - switch (w) - { - case LCST ('\a'): - obstack_grow_wstr (output, LCST ("\\a")); - break; - case LCST ('\b'): - obstack_grow_wstr (output, LCST ("\\b")); - break; - case LCST ('\f'): - obstack_grow_wstr (output, LCST ("\\f")); - break; - case LCST ('\n'): - obstack_grow_wstr (output, LCST ("\\n")); - break; - case LCST ('\r'): - obstack_grow_wstr (output, LCST ("\\r")); - break; - case LCST ('\t'): - obstack_grow_wstr (output, LCST ("\\t")); - break; - case LCST ('\v'): - obstack_grow_wstr (output, LCST ("\\v")); - break; - default: - { - int i; - - for (i = 0; i + width <= orig_len; i += width) - { - char octal[30]; - ULONGEST value; - - value = extract_unsigned_integer (&orig[i], width, - byte_order); - /* If the value fits in 3 octal digits, print it that - way. Otherwise, print it as a hex escape. */ - if (value <= 0777) - sprintf (octal, "\\%.3o", (int) (value & 0777)); - else - sprintf (octal, "\\x%lx", (long) value); - append_string_as_wide (octal, output); - } - /* If we somehow have extra bytes, print them now. */ - while (i < orig_len) - { - char octal[5]; - - sprintf (octal, "\\%.3o", orig[i] & 0xff); - append_string_as_wide (octal, output); - ++i; - } - - *need_escapep = 1; - } - break; - } - } -} - /* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. Note that that format for printing characters and strings is language specific. */ @@ -265,85 +148,10 @@ void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) { - enum bfd_endian byte_order - = gdbarch_byte_order (get_type_arch (type)); - struct obstack wchar_buf, output; - struct cleanup *cleanups; const char *encoding; - gdb_byte *buf; - struct wchar_iterator *iter; - int need_escape = 0; classify_type (type, get_type_arch (type), &encoding); - - buf = alloca (TYPE_LENGTH (type)); - pack_long (buf, type, c); - - iter = make_wchar_iterator (buf, TYPE_LENGTH (type), - encoding, TYPE_LENGTH (type)); - cleanups = make_cleanup_wchar_iterator (iter); - - /* This holds the printable form of the wchar_t data. */ - obstack_init (&wchar_buf); - make_cleanup_obstack_free (&wchar_buf); - - while (1) - { - int num_chars; - gdb_wchar_t *chars; - const gdb_byte *buf; - size_t buflen; - int print_escape = 1; - enum wchar_iterate_result result; - - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); - if (num_chars < 0) - break; - if (num_chars > 0) - { - /* If all characters are printable, print them. Otherwise, - we're going to have to print an escape sequence. We - check all characters because we want to print the target - bytes in the escape sequence, and we don't know character - boundaries there. */ - int i; - - print_escape = 0; - for (i = 0; i < num_chars; ++i) - if (!wchar_printable (chars[i])) - { - print_escape = 1; - break; - } - - if (!print_escape) - { - for (i = 0; i < num_chars; ++i) - print_wchar (chars[i], buf, buflen, - TYPE_LENGTH (type), byte_order, - &wchar_buf, quoter, &need_escape); - } - } - - /* This handles the NUM_CHARS == 0 case as well. */ - if (print_escape) - print_wchar (gdb_WEOF, buf, buflen, TYPE_LENGTH (type), - byte_order, &wchar_buf, quoter, &need_escape); - } - - /* The output in the host encoding. */ - obstack_init (&output); - make_cleanup_obstack_free (&output); - - convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (), - obstack_base (&wchar_buf), - obstack_object_size (&wchar_buf), - 1, &output, translit_char); - obstack_1grow (&output, '\0'); - - fputs_filtered (obstack_base (&output), stream); - - do_cleanups (cleanups); + generic_emit_char (c, type, stream, quoter, encoding); } void @@ -385,6 +193,10 @@ c_printstr (struct ui_file *stream, struct type *type, const char *user_encoding, int force_ellipses, const struct value_print_options *options) { + enum c_string_type str_type; + const char *type_encoding; + const char *encoding; + enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); unsigned int i; unsigned int things_printed = 0; @@ -393,35 +205,10 @@ c_printstr (struct ui_file *stream, struct type *type, int width = TYPE_LENGTH (type); struct obstack wchar_buf, output; struct cleanup *cleanup; - enum c_string_type str_type; - const char *type_encoding; - const char *encoding; struct wchar_iterator *iter; int finished = 0; int need_escape = 0; - if (length == -1) - { - unsigned long current_char = 1; - - for (i = 0; current_char; ++i) - { - QUIT; - current_char = extract_unsigned_integer (string + i * width, - width, byte_order); - } - length = i; - } - - /* If the string was not truncated due to `set print elements', and - the last byte of it is a null, we don't print that, in - traditional C style. */ - if (!force_ellipses - && length > 0 - && (extract_unsigned_integer (string + (length - 1) * width, - width, byte_order) == 0)) - length--; - str_type = (classify_type (type, get_type_arch (type), &type_encoding) & ~C_CHAR); switch (str_type) @@ -439,193 +226,10 @@ c_printstr (struct ui_file *stream, struct type *type, break; } - encoding = (user_encoding && *user_encoding) - ? user_encoding : type_encoding; - - if (length == 0) - { - fputs_filtered ("\"\"", stream); - return; - } - - /* Arrange to iterate over the characters, in wchar_t form. */ - iter = make_wchar_iterator (string, length * width, encoding, width); - cleanup = make_cleanup_wchar_iterator (iter); - - /* WCHAR_BUF is the obstack we use to represent the string in - wchar_t form. */ - obstack_init (&wchar_buf); - make_cleanup_obstack_free (&wchar_buf); - - while (!finished && things_printed < options->print_max) - { - int num_chars; - enum wchar_iterate_result result; - gdb_wchar_t *chars; - const gdb_byte *buf; - size_t buflen; - - QUIT; - - if (need_comma) - { - obstack_grow_wstr (&wchar_buf, LCST (", ")); - need_comma = 0; - } - - num_chars = wchar_iterate (iter, &result, &chars, &buf, &buflen); - /* We only look at repetitions when we were able to convert a - single character in isolation. This makes the code simpler - and probably does the sensible thing in the majority of - cases. */ - while (num_chars == 1 && things_printed < options->print_max) - { - /* Count the number of repetitions. */ - unsigned int reps = 0; - gdb_wchar_t current_char = chars[0]; - const gdb_byte *orig_buf = buf; - int orig_len = buflen; - - if (need_comma) - { - obstack_grow_wstr (&wchar_buf, LCST (", ")); - need_comma = 0; - } - - while (num_chars == 1 && current_char == chars[0]) - { - num_chars = wchar_iterate (iter, &result, &chars, - &buf, &buflen); - ++reps; - } - - /* Emit CURRENT_CHAR according to the repetition count and - options. */ - if (reps > options->repeat_count_threshold) - { - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\", ")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\", ")); - in_quotes = 0; - } - obstack_grow_wstr (&wchar_buf, LCST ("'")); - need_escape = 0; - print_wchar (current_char, orig_buf, orig_len, width, - byte_order, &wchar_buf, '\'', &need_escape); - obstack_grow_wstr (&wchar_buf, LCST ("'")); - { - /* Painful gyrations. */ - int j; - char *s = xstrprintf (_(" "), reps); - - for (j = 0; s[j]; ++j) - { - gdb_wchar_t w = gdb_btowc (s[j]); - obstack_grow (&wchar_buf, &w, sizeof (gdb_wchar_t)); - } - xfree (s); - } - things_printed += options->repeat_count_threshold; - need_comma = 1; - } - else - { - /* Saw the character one or more times, but fewer than - the repetition threshold. */ - if (!in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\"")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\"")); - in_quotes = 1; - need_escape = 0; - } - - while (reps-- > 0) - { - print_wchar (current_char, orig_buf, - orig_len, width, - byte_order, &wchar_buf, - '"', &need_escape); - ++things_printed; - } - } - } - - /* NUM_CHARS and the other outputs from wchar_iterate are valid - here regardless of which branch was taken above. */ - if (num_chars < 0) - { - /* Hit EOF. */ - finished = 1; - break; - } - - switch (result) - { - case wchar_iterate_invalid: - if (!in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\"")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\"")); - in_quotes = 1; - } - need_escape = 0; - print_wchar (gdb_WEOF, buf, buflen, width, byte_order, - &wchar_buf, '"', &need_escape); - break; - - case wchar_iterate_incomplete: - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\",")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\",")); - in_quotes = 0; - } - obstack_grow_wstr (&wchar_buf, - LCST (" ")); - finished = 1; - break; - } - } - - /* Terminate the quotes if necessary. */ - if (in_quotes) - { - if (options->inspect_it) - obstack_grow_wstr (&wchar_buf, LCST ("\\\"")); - else - obstack_grow_wstr (&wchar_buf, LCST ("\"")); - } - - if (force_ellipses || !finished) - obstack_grow_wstr (&wchar_buf, LCST ("...")); - - /* OUTPUT is where we collect `char's for printing. */ - obstack_init (&output); - make_cleanup_obstack_free (&output); - - convert_between_encodings (INTERMEDIATE_ENCODING, host_charset (), - obstack_base (&wchar_buf), - obstack_object_size (&wchar_buf), - 1, &output, translit_char); - obstack_1grow (&output, '\0'); - - fputs_filtered (obstack_base (&output), stream); + encoding = (user_encoding && *user_encoding) ? user_encoding : type_encoding; - do_cleanups (cleanup); + generic_printstr (stream, type, string, length, encoding, force_ellipses, + '"', 1, options); } /* Obtain a C string from the inferior storing it in a newly allocated @@ -1259,6 +863,8 @@ const struct language_defn c_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; @@ -1380,6 +986,8 @@ const struct language_defn cplus_language_defn = default_print_array_index, cp_pass_by_reference, c_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; @@ -1419,6 +1027,8 @@ const struct language_defn asm_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; @@ -1463,6 +1073,8 @@ const struct language_defn minimal_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; diff --git a/contrib/gdb-7/gdb/c-lang.h b/contrib/gdb-7/gdb/c-lang.h index 747d079c48..e8c632f4ce 100644 --- a/contrib/gdb-7/gdb/c-lang.h +++ b/contrib/gdb-7/gdb/c-lang.h @@ -1,7 +1,7 @@ /* C language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 2000, 2002, 2005, 2006, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992, 1994-1998, 2000, 2002, 2005-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/c-typeprint.c b/contrib/gdb-7/gdb/c-typeprint.c index 2e23dd7f9f..db254dce29 100644 --- a/contrib/gdb-7/gdb/c-typeprint.c +++ b/contrib/gdb-7/gdb/c-typeprint.c @@ -1,7 +1,6 @@ /* Support for printing C and C++ types for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1998, - 1999, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-1996, 1998-2003, 2006-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -719,9 +718,6 @@ c_type_print_base (struct type *type, struct ui_file *stream, int i; int len, real_len; int lastval; - char *mangled_name; - char *demangled_name; - char *demangled_no_static; enum { s_none, s_public, s_private, s_protected @@ -1001,7 +997,10 @@ c_type_print_base (struct type *type, struct ui_file *stream, for (j = 0; j < len2; j++) { - char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); + const char *mangled_name; + char *demangled_name; + struct cleanup *inner_cleanup; + const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); int is_full_physname_constructor = is_constructor_name (physname) || is_destructor_name (physname) @@ -1011,6 +1010,8 @@ c_type_print_base (struct type *type, struct ui_file *stream, if (TYPE_FN_FIELD_ARTIFICIAL (f, j)) continue; + inner_cleanup = make_cleanup (null_cleanup, NULL); + QUIT; if (TYPE_FN_FIELD_PROTECTED (f, j)) { @@ -1064,8 +1065,14 @@ c_type_print_base (struct type *type, struct ui_file *stream, fputs_filtered (" ", stream); } if (TYPE_FN_FIELD_STUB (f, j)) - /* Build something we can demangle. */ - mangled_name = gdb_mangle_name (type, i, j); + { + char *tem; + + /* Build something we can demangle. */ + tem = gdb_mangle_name (type, i, j); + make_cleanup (xfree, tem); + mangled_name = tem; + } else mangled_name = TYPE_FN_FIELD_PHYSNAME (f, j); @@ -1107,6 +1114,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, if (p != NULL) { int length = p - demangled_no_class; + char *demangled_no_static; demangled_no_static = (char *) xmalloc (length + 1); @@ -1121,8 +1129,7 @@ c_type_print_base (struct type *type, struct ui_file *stream, xfree (demangled_name); } - if (TYPE_FN_FIELD_STUB (f, j)) - xfree (mangled_name); + do_cleanups (inner_cleanup); fprintf_filtered (stream, ";\n"); } diff --git a/contrib/gdb-7/gdb/c-valprint.c b/contrib/gdb-7/gdb/c-valprint.c index 76579d2116..9949015d86 100644 --- a/contrib/gdb-7/gdb/c-valprint.c +++ b/contrib/gdb-7/gdb/c-valprint.c @@ -1,8 +1,7 @@ /* Support for printing C values for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-2001, 2003, 2005-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -380,10 +379,19 @@ c_val_print (struct type *type, const gdb_byte *valaddr, { if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF) { - struct value *deref_val = - value_at - (TYPE_TARGET_TYPE (type), - unpack_pointer (type, valaddr + embedded_offset)); + struct value *deref_val; + + deref_val = coerce_ref_if_computed (original_value); + if (deref_val != NULL) + { + /* More complicated computed references are not supported. */ + gdb_assert (embedded_offset == 0); + } + else + deref_val = value_at (TYPE_TARGET_TYPE (type), + unpack_pointer (type, + (valaddr + + embedded_offset))); common_val_print (deref_val, stream, recurse, options, current_language); diff --git a/contrib/gdb-7/gdb/call-cmds.h b/contrib/gdb-7/gdb/call-cmds.h index f0c41fc12e..e98585b950 100644 --- a/contrib/gdb-7/gdb/call-cmds.h +++ b/contrib/gdb-7/gdb/call-cmds.h @@ -6,8 +6,8 @@ 2000-12-01 fnasser@redhat.com */ /* Prototypes for GDB commands that are called internally by other functions. - Copyright (C) 1992, 2000, 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992, 2000-2001, 2007-2012 Free Software Foundation, + Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/cc-with-index.sh b/contrib/gdb-7/gdb/cc-with-index.sh index 9c95bef907..22eefaacbf 100644 --- a/contrib/gdb-7/gdb/cc-with-index.sh +++ b/contrib/gdb-7/gdb/cc-with-index.sh @@ -1,7 +1,7 @@ #! /bin/sh # Wrapper around gcc to add the .gdb_index section when running the testsuite. -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or @@ -16,8 +16,8 @@ # along with this program. If not, see . # This program requires gdb and objcopy in addition to gcc. -# The default values are gdb from the build tree and objdump from $PATH. -# They may be overridden by setting environment variables GDB and OBJDUMP +# The default values are gdb from the build tree and objcopy from $PATH. +# They may be overridden by setting environment variables GDB and OBJCOPY # respectively. # We assume the current directory is either $obj/gdb or $obj/gdb/testsuite. # @@ -40,6 +40,9 @@ then elif [ -f ../gdb ] then GDB="../gdb" + elif [ -f ../../gdb ] + then + GDB="../../gdb" else echo "$myname: unable to find usable gdb" >&2 exit 1 diff --git a/contrib/gdb-7/gdb/charset-list.h b/contrib/gdb-7/gdb/charset-list.h index e6aea21f19..d0eff82906 100644 --- a/contrib/gdb-7/gdb/charset-list.h +++ b/contrib/gdb-7/gdb/charset-list.h @@ -1,6 +1,6 @@ /* List of character set names for GDB. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/charset.c b/contrib/gdb-7/gdb/charset.c index a84085ac3a..f32736a5f7 100644 --- a/contrib/gdb-7/gdb/charset.c +++ b/contrib/gdb-7/gdb/charset.c @@ -1,7 +1,6 @@ /* Character set conversion support for GDB. - Copyright (C) 2001, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001, 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -799,7 +798,9 @@ find_charset_names (void) char *args[3]; int err, status; int fail = 1; + int flags; struct gdb_environ *iconv_env; + char *iconv_program; /* Older iconvs, e.g. 2.2.2, don't omit the intro text if stdout is not a tty. We need to recognize it and ignore it. This text is @@ -811,12 +812,26 @@ find_charset_names (void) child = pex_init (PEX_USE_PIPES, "iconv", NULL); - args[0] = "iconv"; +#ifdef ICONV_BIN + { + char *iconv_dir = relocate_gdb_directory (ICONV_BIN, + ICONV_BIN_RELOCATABLE); + iconv_program = concat (iconv_dir, SLASH_STRING, "iconv", NULL); + xfree (iconv_dir); + } +#else + iconv_program = xstrdup ("iconv"); +#endif + args[0] = iconv_program; args[1] = "-l"; args[2] = NULL; + flags = PEX_STDERR_TO_STDOUT; +#ifndef ICONV_BIN + flags |= PEX_SEARCH; +#endif /* Note that we simply ignore errors here. */ - if (!pex_run_in_environment (child, PEX_SEARCH | PEX_STDERR_TO_STDOUT, - "iconv", args, environ_vector (iconv_env), + if (!pex_run_in_environment (child, flags, + args[0], args, environ_vector (iconv_env), NULL, NULL, &err)) { FILE *in = pex_read_output (child, 0); @@ -888,6 +903,7 @@ find_charset_names (void) } + xfree (iconv_program); pex_free (child); free_environ (iconv_env); diff --git a/contrib/gdb-7/gdb/charset.h b/contrib/gdb-7/gdb/charset.h index 72f4dd70e3..0bfdd807ce 100644 --- a/contrib/gdb-7/gdb/charset.h +++ b/contrib/gdb-7/gdb/charset.h @@ -1,6 +1,5 @@ /* Character set conversion support for GDB. - Copyright (C) 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/cli-out.c b/contrib/gdb-7/gdb/cli-out.c index 9a8515d985..925206c535 100644 --- a/contrib/gdb-7/gdb/cli-out.c +++ b/contrib/gdb-7/gdb/cli-out.c @@ -1,7 +1,7 @@ /* Output generating routines for GDB CLI. - Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2002-2003, 2005, 2007-2012 Free Software + Foundation, Inc. Contributed by Cygnus Solutions. Written by Fernando Nasser for Cygnus. @@ -342,7 +342,7 @@ out_field_fmt (struct ui_out *uiout, int fldno, static void field_separator (void) { - cli_out_data *data = ui_out_data (uiout); + cli_out_data *data = ui_out_data (current_uiout); struct ui_file *stream = VEC_last (ui_filep, data->streams); fputc_filtered (' ', stream); diff --git a/contrib/gdb-7/gdb/cli-out.h b/contrib/gdb-7/gdb/cli-out.h index befa624eb3..b066b7e721 100644 --- a/contrib/gdb-7/gdb/cli-out.h +++ b/contrib/gdb-7/gdb/cli-out.h @@ -1,6 +1,5 @@ /* Output generating routines for GDB CLI. - Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/cli/cli-cmds.c b/contrib/gdb-7/gdb/cli/cli-cmds.c index 7fd2f50398..c38167a175 100644 --- a/contrib/gdb-7/gdb/cli/cli-cmds.c +++ b/contrib/gdb-7/gdb/cli/cli-cmds.c @@ -1,7 +1,6 @@ /* GDB CLI commands. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 2000-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -21,6 +20,7 @@ #include "defs.h" #include "exceptions.h" #include "arch-utils.h" +#include "dyn-string.h" #include "readline/readline.h" #include "readline/tilde.h" #include "completer.h" @@ -91,6 +91,9 @@ void apropos_command (char *, int); /* Prototypes for local utility functions */ static void ambiguous_line_spec (struct symtabs_and_lines *); + +static void filter_sals (struct symtabs_and_lines *); + /* Limit the call depth of user-defined commands */ int max_user_call_depth; @@ -185,6 +188,8 @@ struct cmd_list_element *setchecklist; struct cmd_list_element *showchecklist; +struct cmd_list_element *skiplist; + /* Command tracing state. */ int source_verbose = 0; @@ -243,16 +248,6 @@ help_command (char *command, int from_tty) help_cmd (command, gdb_stdout); } -/* String compare function for qsort. */ -static int -compare_strings (const void *arg1, const void *arg2) -{ - const char **s1 = (const char **) arg1; - const char **s2 = (const char **) arg2; - - return strcmp (*s1, *s2); -} - /* The "complete" command is used by Emacs to implement completion. */ static void @@ -534,7 +529,9 @@ source_script_from_stream (FILE *stream, const char *file) TRY_CATCH (e, RETURN_MASK_ERROR) { - source_python_script (stream, file); + /* The python support reopens the file using python functions, + so there's no point in passing STREAM here. */ + source_python_script (file); } if (e.reason < 0) { @@ -576,7 +573,7 @@ source_script_with_search (const char *file, int from_tty, int search_path) if (!find_and_open_script (file, search_path, &stream, &full_path)) { - /* The script wasn't found, or was otherwise inaccessible. + /* The script wasn't found, or was otherwise inaccessible. If the source command was invoked interactively, throw an error. Otherwise (e.g. if it was invoked by a script), silently ignore the error. */ @@ -587,7 +584,12 @@ source_script_with_search (const char *file, int from_tty, int search_path) } old_cleanups = make_cleanup (xfree, full_path); - source_script_from_stream (stream, file); + /* The python support reopens the file, so we need to pass full_path here + in case the file was found on the search path. It's useful to do this + anyway so that error messages show the actual file used. But only do + this if we (may have) used search_path, as printing the full path in + errors for the non-search case can be more noise than signal. */ + source_script_from_stream (stream, search_path ? full_path : file); do_cleanups (old_cleanups); } @@ -726,7 +728,7 @@ shell_escape (char *arg, int from_tty) chdir (current_directory); #endif #else /* Can fork. */ - int rc, status, pid; + int status, pid; if ((pid = vfork ()) == 0) { @@ -750,8 +752,7 @@ shell_escape (char *arg, int from_tty) } if (pid != -1) - while ((rc = wait (&status)) != pid && rc != -1) - ; + waitpid (pid, &status, 0); else error (_("Fork failed")); #endif /* Can fork. */ @@ -787,8 +788,9 @@ edit_command (char *arg, int from_tty) /* Now should only be one argument -- decode it in SAL. */ arg1 = arg; - sals = decode_line_1 (&arg1, 0, 0, 0, 0); + sals = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0); + filter_sals (&sals); if (! sals.nelts) { /* C++ */ @@ -917,8 +919,9 @@ list_command (char *arg, int from_tty) dummy_beg = 1; else { - sals = decode_line_1 (&arg1, 0, 0, 0, 0); + sals = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0); + filter_sals (&sals); if (!sals.nelts) return; /* C++ */ if (sals.nelts > 1) @@ -950,9 +953,11 @@ list_command (char *arg, int from_tty) else { if (dummy_beg) - sals_end = decode_line_1 (&arg1, 0, 0, 0, 0); + sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0); else - sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0); + sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, + sal.symtab, sal.line); + filter_sals (&sals); if (sals_end.nelts == 0) return; if (sals_end.nelts > 1) @@ -1064,7 +1069,7 @@ print_disassembly (struct gdbarch *gdbarch, const char *name, paddress (gdbarch, low), paddress (gdbarch, high)); /* Dump the specified range. */ - gdb_disassembly (gdbarch, uiout, 0, flags, -1, low, high); + gdb_disassembly (gdbarch, current_uiout, 0, flags, -1, low, high); printf_filtered ("End of assembler dump.\n"); gdb_flush (gdb_stdout); @@ -1273,6 +1278,180 @@ apropos_command (char *searchstr, int from_tty) error (_("Error in regular expression: %s"), err); } } + +/* Subroutine of alias_command to simplify it. + Return the first N elements of ARGV flattened back to a string + with a space separating each element. + ARGV may not be NULL. + This does not take care of quoting elements in case they contain spaces + on purpose. */ + +static dyn_string_t +argv_to_dyn_string (char **argv, int n) +{ + int i; + dyn_string_t result = dyn_string_new (10); + + gdb_assert (argv != NULL); + gdb_assert (n >= 0 && n <= countargv (argv)); + + for (i = 0; i < n; ++i) + { + if (i > 0) + dyn_string_append_char (result, ' '); + dyn_string_append_cstr (result, argv[i]); + } + + return result; +} + +/* Subroutine of alias_command to simplify it. + Return TRUE if COMMAND exists, unambiguously. Otherwise FALSE. */ + +static int +valid_command_p (char *command) +{ + struct cmd_list_element *c; + + c = lookup_cmd_1 (& command, cmdlist, NULL, 1); + + if (c == NULL || c == (struct cmd_list_element *) -1) + return FALSE; + + /* This is the slightly tricky part. + lookup_cmd_1 will return a pointer to the last part of COMMAND + to match, leaving COMMAND pointing at the remainder. */ + while (*command == ' ' || *command == '\t') + ++command; + return *command == '\0'; +} + +/* Make an alias of an existing command. */ + +static void +alias_command (char *args, int from_tty) +{ + int i, alias_argc, command_argc; + int abbrev_flag = 0; + char *args2, *equals, *alias, *command; + char **alias_argv, **command_argv; + dyn_string_t alias_dyn_string, command_dyn_string; + struct cmd_list_element *c; + static const char usage[] = N_("Usage: alias [-a] [--] ALIAS = COMMAND"); + + if (args == NULL || strchr (args, '=') == NULL) + error (_(usage)); + + args2 = xstrdup (args); + make_cleanup (xfree, args2); + equals = strchr (args2, '='); + *equals = '\0'; + alias_argv = gdb_buildargv (args2); + make_cleanup_freeargv (alias_argv); + command_argv = gdb_buildargv (equals + 1); + make_cleanup_freeargv (command_argv); + + for (i = 0; alias_argv[i] != NULL; ) + { + if (strcmp (alias_argv[i], "-a") == 0) + { + ++alias_argv; + abbrev_flag = 1; + } + else if (strcmp (alias_argv[i], "--") == 0) + { + ++alias_argv; + break; + } + else + break; + } + + if (alias_argv[0] == NULL || command_argv[0] == NULL + || *alias_argv[0] == '\0' || *command_argv[0] == '\0') + error (_(usage)); + + for (i = 0; alias_argv[i] != NULL; ++i) + { + if (! valid_user_defined_cmd_name_p (alias_argv[i])) + { + if (i == 0) + error (_("Invalid command name: %s"), alias_argv[i]); + else + error (_("Invalid command element name: %s"), alias_argv[i]); + } + } + + alias_argc = countargv (alias_argv); + command_argc = countargv (command_argv); + + /* COMMAND must exist. + Reconstruct the command to remove any extraneous spaces, + for better error messages. */ + command_dyn_string = argv_to_dyn_string (command_argv, command_argc); + make_cleanup_dyn_string_delete (command_dyn_string); + command = dyn_string_buf (command_dyn_string); + if (! valid_command_p (command)) + error (_("Invalid command to alias to: %s"), command); + + /* ALIAS must not exist. */ + alias_dyn_string = argv_to_dyn_string (alias_argv, alias_argc); + make_cleanup_dyn_string_delete (alias_dyn_string); + alias = dyn_string_buf (alias_dyn_string); + if (valid_command_p (alias)) + error (_("Alias already exists: %s"), alias); + + /* If ALIAS is one word, it is an alias for the entire COMMAND. + Example: alias spe = set print elements + + Otherwise ALIAS and COMMAND must have the same number of words, + and every word except the last must match; and the last word of + ALIAS is made an alias of the last word of COMMAND. + Example: alias set print elms = set pr elem + Note that unambiguous abbreviations are allowed. */ + + if (alias_argc == 1) + { + /* add_cmd requires *we* allocate space for name, hence the xstrdup. */ + add_com_alias (xstrdup (alias_argv[0]), command, class_alias, + abbrev_flag); + } + else + { + int i; + dyn_string_t alias_prefix_dyn_string, command_prefix_dyn_string; + char *alias_prefix, *command_prefix; + struct cmd_list_element *c_alias, *c_command; + + if (alias_argc != command_argc) + error (_("Mismatched command length between ALIAS and COMMAND.")); + + /* Create copies of ALIAS and COMMAND without the last word, + and use that to verify the leading elements match. */ + alias_prefix_dyn_string = + argv_to_dyn_string (alias_argv, alias_argc - 1); + make_cleanup_dyn_string_delete (alias_prefix_dyn_string); + command_prefix_dyn_string = + argv_to_dyn_string (alias_argv, command_argc - 1); + make_cleanup_dyn_string_delete (command_prefix_dyn_string); + alias_prefix = dyn_string_buf (alias_prefix_dyn_string); + command_prefix = dyn_string_buf (command_prefix_dyn_string); + + c_command = lookup_cmd_1 (& command_prefix, cmdlist, NULL, 1); + /* We've already tried to look up COMMAND. */ + gdb_assert (c_command != NULL + && c_command != (struct cmd_list_element *) -1); + gdb_assert (c_command->prefixlist != NULL); + c_alias = lookup_cmd_1 (& alias_prefix, cmdlist, NULL, 1); + if (c_alias != c_command) + error (_("ALIAS and COMMAND prefixes do not match.")); + + /* add_cmd requires *we* allocate space for name, hence the xstrdup. */ + add_alias_cmd (xstrdup (alias_argv[alias_argc - 1]), + command_argv[command_argc - 1], + class_alias, abbrev_flag, c_command->prefixlist); + } +} /* Print a list of files and line numbers which a user may choose from in order to list a function which was specified ambiguously (as @@ -1289,6 +1468,85 @@ ambiguous_line_spec (struct symtabs_and_lines *sals) sals->sals[i].symtab->filename, sals->sals[i].line); } +/* Sort function for filter_sals. */ + +static int +compare_symtabs (const void *a, const void *b) +{ + const struct symtab_and_line *sala = a; + const struct symtab_and_line *salb = b; + int r; + + if (!sala->symtab->dirname) + { + if (salb->symtab->dirname) + return -1; + } + else if (!salb->symtab->dirname) + { + if (sala->symtab->dirname) + return 1; + } + else + { + r = filename_cmp (sala->symtab->dirname, salb->symtab->dirname); + if (r) + return r; + } + + r = filename_cmp (sala->symtab->filename, salb->symtab->filename); + if (r) + return r; + + if (sala->line < salb->line) + return -1; + return sala->line == salb->line ? 0 : 1; +} + +/* Remove any SALs that do not match the current program space, or + which appear to be "file:line" duplicates. */ + +static void +filter_sals (struct symtabs_and_lines *sals) +{ + int i, out, prev; + + out = 0; + for (i = 0; i < sals->nelts; ++i) + { + if (sals->sals[i].pspace == current_program_space + && sals->sals[i].symtab != NULL) + { + sals->sals[out] = sals->sals[i]; + ++out; + } + } + sals->nelts = out; + + qsort (sals->sals, sals->nelts, sizeof (struct symtab_and_line), + compare_symtabs); + + out = 1; + prev = 0; + for (i = 1; i < sals->nelts; ++i) + { + if (compare_symtabs (&sals->sals[prev], &sals->sals[i])) + { + /* Symtabs differ. */ + sals->sals[out] = sals->sals[i]; + prev = out; + ++out; + } + } + sals->nelts = out; + + if (sals->nelts == 0) + { + xfree (sals->sals); + sals->sals = NULL; + } +} + static void set_debug (char *arg, int from_tty) { @@ -1330,6 +1588,7 @@ init_cmd_lists (void) showprintlist = NULL; setchecklist = NULL; showchecklist = NULL; + skiplist = NULL; } static void @@ -1395,7 +1654,7 @@ init_cli_cmds (void) char *source_help_text; /* Define the classes of commands. - They will appear in the help list in the reverse of this order. */ + They will appear in the help list in alphabetical order. */ add_cmd ("internals", class_maintenance, NULL, _("\ Maintenance commands.\n\ @@ -1641,14 +1900,7 @@ Two arguments (separated by a comma) are taken as a range of memory to dump,\n\ if (xdb_commands) add_com_alias ("va", "disassemble", class_xdb, 0); - /* NOTE: cagney/2000-03-20: Being able to enter ``(gdb) !ls'' would - be a really useful feature. Unfortunately, the below wont do - this. Instead it adds support for the form ``(gdb) ! ls'' - (i.e. the space is required). If the ``!'' command below is - added the complains about no ``!'' command would be replaced by - complains about how the ``!'' command is broken :-) */ - if (xdb_commands) - add_com_alias ("!", "shell", class_support, 0); + add_com_alias ("!", "shell", class_support, 0); c = add_com ("make", class_support, make_command, _("\ Run the ``make'' program using the rest of the line as arguments.")); @@ -1675,4 +1927,18 @@ When 'on', each command is displayed as it is executed."), NULL, NULL, &setlist, &showlist); + + c = add_com ("alias", class_support, alias_command, _("\ +Define a new command that is an alias of an existing command.\n\ +Usage: alias [-a] [--] ALIAS = COMMAND\n\ +ALIAS is the name of the alias command to create.\n\ +COMMAND is the command being aliased to.\n\ +If \"-a\" is specified, the command is an abbreviation,\n\ +and will not appear in help command list output.\n\ +\n\ +Examples:\n\ +Make \"spe\" an alias of \"set print elements\":\n\ + alias spe = set print elements\n\ +Make \"elms\" an alias of \"elements\" in the \"set print\" command:\n\ + alias -a set print elms = set print elements")); } diff --git a/contrib/gdb-7/gdb/cli/cli-cmds.h b/contrib/gdb-7/gdb/cli/cli-cmds.h index e79dcf05d6..4b4e74cc66 100644 --- a/contrib/gdb-7/gdb/cli/cli-cmds.h +++ b/contrib/gdb-7/gdb/cli/cli-cmds.h @@ -1,6 +1,5 @@ /* Header file for GDB CLI command implementation library. - Copyright (c) 2000,2006,2007,2008,2009,2010,2011 - Free Software Foundation, Inc. + Copyright (c) 2000, 2006-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,6 +105,8 @@ extern struct cmd_list_element *setchecklist; extern struct cmd_list_element *showchecklist; +extern struct cmd_list_element *skiplist; + /* Exported to gdb/top.c */ void init_cmd_lists (void); diff --git a/contrib/gdb-7/gdb/cli/cli-decode.c b/contrib/gdb-7/gdb/cli/cli-decode.c index 093fec0355..f168ff19d4 100644 --- a/contrib/gdb-7/gdb/cli/cli-decode.c +++ b/contrib/gdb-7/gdb/cli/cli-decode.c @@ -1,7 +1,7 @@ /* Handle lists of commands, their decoding and documentation, for GDB. - Copyright (c) 1986, 1989, 1990, 1991, 1998, 2000, 2001, 2002, 2004, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (c) 1986, 1989-1991, 1998, 2000-2002, 2004, 2007-2012 Free + Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -126,8 +126,8 @@ set_cmd_completer (struct cmd_list_element *cmd, cmd->completer = completer; /* Ok. */ } - /* Add element named NAME. + Space for NAME and DOC must be allocated by the caller. CLASS is the top level category into which commands are broken down for "help" purposes. FUN should be the function to execute the command; @@ -1018,7 +1018,7 @@ print_doc_line (struct ui_file *stream, char *str) line_buffer[p - str] = '\0'; if (islower (line_buffer[0])) line_buffer[0] = toupper (line_buffer[0]); - ui_out_text (uiout, line_buffer); + ui_out_text (current_uiout, line_buffer); } /* Print one-line help for command C. @@ -1127,16 +1127,49 @@ find_command_name_length (const char *text) Note that this is larger than the character set allowed when creating user-defined commands. */ + /* Recognize '!' as a single character command so that, e.g., "!ls" + works as expected. */ + if (*p == '!') + return 1; + while (isalnum (*p) || *p == '-' || *p == '_' /* Characters used by TUI specific commands. */ || *p == '+' || *p == '<' || *p == '>' || *p == '$' /* Characters used for XDB compatibility. */ - || (xdb_commands && (*p == '!' || *p == '/' || *p == '?'))) + || (xdb_commands && (*p == '/' || *p == '?'))) p++; return p - text; } +/* Return TRUE if NAME is a valid user-defined command name. + This is a stricter subset of all gdb commands, + see find_command_name_length. */ + +int +valid_user_defined_cmd_name_p (const char *name) +{ + const char *p; + + if (*name == '\0') + return FALSE; + + /* Alas "42" is a legitimate user-defined command. + In the interests of not breaking anything we preserve that. */ + + for (p = name; *p != '\0'; ++p) + { + if (isalnum (*p) + || *p == '-' + || *p == '_') + ; /* Ok. */ + else + return FALSE; + } + + return TRUE; +} + /* This routine takes a line of TEXT and a CLIST in which to start the lookup. When it returns it will have incremented the text pointer past the section of text it matched, set *RESULT_LIST to point to the list in @@ -1500,7 +1533,7 @@ deprecated_cmd_warning (char **text) If LINE refers to an alias, *alias will point to that alias. - If LINE is a postfix command (i.e. one that is preceeded by a prefix + If LINE is a postfix command (i.e. one that is preceded by a prefix command) set *prefix_cmd. Set *cmd to point to the command LINE indicates. @@ -1528,7 +1561,7 @@ lookup_cmd_composition (char *text, while (1) { - /* Go through as many command lists as we need to + /* Go through as many command lists as we need to, to find the command TEXT refers to. */ prev_cmd = *cmd; diff --git a/contrib/gdb-7/gdb/cli/cli-decode.h b/contrib/gdb-7/gdb/cli/cli-decode.h index e9749681cb..56ef3ae70a 100644 --- a/contrib/gdb-7/gdb/cli/cli-decode.h +++ b/contrib/gdb-7/gdb/cli/cli-decode.h @@ -1,7 +1,6 @@ /* Header file for GDB command decoding library. - Copyright (c) 2000, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2000, 2003, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/cli/cli-dump.c b/contrib/gdb-7/gdb/cli/cli-dump.c index ac6270e645..4a8b5d13b2 100644 --- a/contrib/gdb-7/gdb/cli/cli-dump.c +++ b/contrib/gdb-7/gdb/cli/cli-dump.c @@ -1,7 +1,6 @@ /* Dump-to-file commands, for GDB, the GNU debugger. - Copyright (c) 2002, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2002, 2005, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat. @@ -174,7 +173,7 @@ append_command (char *cmd, int from_tty) static void dump_binary_file (const char *filename, const char *mode, - const bfd_byte *buf, int len) + const bfd_byte *buf, ULONGEST len) { FILE *file; int status; @@ -188,7 +187,7 @@ dump_binary_file (const char *filename, const char *mode, static void dump_bfd_file (const char *filename, const char *mode, const char *target, CORE_ADDR vaddr, - const bfd_byte *buf, int len) + const bfd_byte *buf, ULONGEST len) { bfd *obfd; asection *osection; @@ -679,7 +678,7 @@ _initialize_cli_dump (void) add_dump_command ("memory", dump_memory_command, "\ Write contents of memory to a raw binary file.\n\ Arguments are FILE START STOP. Writes the contents of memory within the\n\ -range [START .. STOP) to the specifed FILE in raw target ordered bytes."); +range [START .. STOP) to the specified FILE in raw target ordered bytes."); add_dump_command ("value", dump_value_command, "\ Write the value of an expression to a raw binary file.\n\ @@ -719,7 +718,7 @@ the specified FILE in raw target ordered bytes."); add_cmd ("memory", all_commands, dump_srec_memory, _("\ Write contents of memory to an srec file.\n\ Arguments are FILE START STOP. Writes the contents of memory\n\ -within the range [START .. STOP) to the specifed FILE in srec format."), +within the range [START .. STOP) to the specified FILE in srec format."), &srec_cmdlist); add_cmd ("value", all_commands, dump_srec_value, _("\ @@ -731,7 +730,7 @@ to the specified FILE in srec format."), add_cmd ("memory", all_commands, dump_ihex_memory, _("\ Write contents of memory to an ihex file.\n\ Arguments are FILE START STOP. Writes the contents of memory within\n\ -the range [START .. STOP) to the specifed FILE in intel hex format."), +the range [START .. STOP) to the specified FILE in intel hex format."), &ihex_cmdlist); add_cmd ("value", all_commands, dump_ihex_value, _("\ @@ -743,7 +742,7 @@ to the specified FILE in intel hex format."), add_cmd ("memory", all_commands, dump_tekhex_memory, _("\ Write contents of memory to a tekhex file.\n\ Arguments are FILE START STOP. Writes the contents of memory\n\ -within the range [START .. STOP) to the specifed FILE in tekhex format."), +within the range [START .. STOP) to the specified FILE in tekhex format."), &tekhex_cmdlist); add_cmd ("value", all_commands, dump_tekhex_value, _("\ @@ -755,7 +754,7 @@ to the specified FILE in tekhex format."), add_cmd ("memory", all_commands, dump_binary_memory, _("\ Write contents of memory to a raw binary file.\n\ Arguments are FILE START STOP. Writes the contents of memory\n\ -within the range [START .. STOP) to the specifed FILE in binary format."), +within the range [START .. STOP) to the specified FILE in binary format."), &binary_dump_cmdlist); add_cmd ("value", all_commands, dump_binary_value, _("\ @@ -767,7 +766,7 @@ to the specified FILE in raw target ordered bytes."), add_cmd ("memory", all_commands, append_binary_memory, _("\ Append contents of memory to a raw binary file.\n\ Arguments are FILE START STOP. Writes the contents of memory within the\n\ -range [START .. STOP) to the specifed FILE in raw target ordered bytes."), +range [START .. STOP) to the specified FILE in raw target ordered bytes."), &binary_append_cmdlist); add_cmd ("value", all_commands, append_binary_value, _("\ diff --git a/contrib/gdb-7/gdb/cli/cli-dump.h b/contrib/gdb-7/gdb/cli/cli-dump.h index 384aa488c3..9ca1d88870 100644 --- a/contrib/gdb-7/gdb/cli/cli-dump.h +++ b/contrib/gdb-7/gdb/cli/cli-dump.h @@ -1,7 +1,6 @@ /* Dump-to-file commands, for GDB, the GNU debugger. - Copyright (c) 2001, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2001, 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/cli/cli-interp.c b/contrib/gdb-7/gdb/cli/cli-interp.c index 7a517e9e48..9c44b24070 100644 --- a/contrib/gdb-7/gdb/cli/cli-interp.c +++ b/contrib/gdb-7/gdb/cli/cli-interp.c @@ -1,7 +1,6 @@ /* CLI Definitions for GDB, the GNU debugger. - Copyright (c) 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2002-2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -37,16 +36,10 @@ struct ui_out *cli_uiout; static struct gdb_exception safe_execute_command (struct ui_out *uiout, char *command, int from_tty); -struct captured_execute_command_args -{ - char *command; - int from_tty; -}; - /* These implement the cli out interpreter: */ static void * -cli_interpreter_init (int top_level) +cli_interpreter_init (struct interp *self, int top_level) { return NULL; } @@ -117,31 +110,35 @@ cli_interpreter_exec (void *data, const char *command_str) return result; } -static void -do_captured_execute_command (struct ui_out *uiout, void *data) +static struct gdb_exception +safe_execute_command (struct ui_out *command_uiout, char *command, int from_tty) { - struct captured_execute_command_args *args = - (struct captured_execute_command_args *) data; + volatile struct gdb_exception e; + struct ui_out *saved_uiout; - execute_command (args->command, args->from_tty); -} + /* Save and override the global ``struct ui_out'' builder. */ + saved_uiout = current_uiout; + current_uiout = command_uiout; -static struct gdb_exception -safe_execute_command (struct ui_out *uiout, char *command, int from_tty) -{ - struct gdb_exception e; - struct captured_execute_command_args args; + TRY_CATCH (e, RETURN_MASK_ALL) + { + execute_command (command, from_tty); + } + + /* Restore the global builder. */ + current_uiout = saved_uiout; - args.command = command; - args.from_tty = from_tty; - e = catch_exception (uiout, do_captured_execute_command, &args, - RETURN_MASK_ALL); /* FIXME: cagney/2005-01-13: This shouldn't be needed. Instead the caller should print the exception. */ exception_print (gdb_stderr, e); return e; } +static struct ui_out * +cli_ui_out (struct interp *self) +{ + return cli_uiout; +} /* Standard gdb initialization hook. */ extern initialize_file_ftype _initialize_cli_interp; /* -Wmissing-prototypes */ @@ -154,13 +151,14 @@ _initialize_cli_interp (void) cli_interpreter_resume, /* resume_proc */ cli_interpreter_suspend, /* suspend_proc */ cli_interpreter_exec, /* exec_proc */ - cli_interpreter_display_prompt_p /* prompt_proc_p */ + cli_interpreter_display_prompt_p, /* prompt_proc_p */ + cli_ui_out /* ui_out_proc */ }; struct interp *cli_interp; /* Create a default uiout builder for the CLI. */ cli_uiout = cli_out_new (gdb_stdout); - cli_interp = interp_new (INTERP_CONSOLE, NULL, cli_uiout, &procs); + cli_interp = interp_new (INTERP_CONSOLE, &procs); interp_add (cli_interp); } diff --git a/contrib/gdb-7/gdb/cli/cli-logging.c b/contrib/gdb-7/gdb/cli/cli-logging.c index d0e25ea555..0c5bda8797 100644 --- a/contrib/gdb-7/gdb/cli/cli-logging.c +++ b/contrib/gdb-7/gdb/cli/cli-logging.c @@ -1,7 +1,6 @@ /* Command-line output logging for GDB, the GNU debugger. - Copyright (c) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2003-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -81,6 +80,7 @@ set_logging_redirect (char *args, int from_tty, struct cmd_list_element *c) { struct cleanup *cleanups = NULL; struct ui_file *output, *new_logging_no_redirect_file; + struct ui_out *uiout = current_uiout; if (saved_filename == NULL || (logging_redirect != 0 && logging_no_redirect_file == NULL) @@ -166,7 +166,7 @@ pop_output_files (void) saved_output.targ = NULL; saved_output.targerr = NULL; - ui_out_redirect (uiout, NULL); + ui_out_redirect (current_uiout, NULL); } /* This is a helper for the `set logging' command. */ @@ -226,7 +226,7 @@ handle_redirections (int from_tty) gdb_stdtarg = output; gdb_stdtargerr = output; - if (ui_out_redirect (uiout, output) < 0) + if (ui_out_redirect (current_uiout, output) < 0) warning (_("Current output protocol does not support redirection")); } diff --git a/contrib/gdb-7/gdb/cli/cli-script.c b/contrib/gdb-7/gdb/cli/cli-script.c index 5903015be3..c8da8c83e1 100644 --- a/contrib/gdb-7/gdb/cli/cli-script.c +++ b/contrib/gdb-7/gdb/cli/cli-script.c @@ -1,8 +1,6 @@ /* GDB CLI command scripting. - Copyright (c) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (c) 1986-2002, 2004-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -35,6 +33,7 @@ #include "gdb_assert.h" #include "python/python.h" +#include "interps.h" /* Prototypes for local functions. */ @@ -317,13 +316,13 @@ execute_user_command (struct cmd_list_element *c, char *args) static int user_call_depth = 0; extern int max_user_call_depth; - old_chain = setup_user_args (args); - cmdlines = c->user_commands; if (cmdlines == 0) /* Null command */ return; + old_chain = setup_user_args (args); + if (++user_call_depth > max_user_call_depth) error (_("Max user call depth exceeded -- command aborted.")); @@ -338,6 +337,9 @@ execute_user_command (struct cmd_list_element *c, char *args) not confused with Insight. */ in_user_command = 1; + make_cleanup_restore_integer (&interpreter_async); + interpreter_async = 0; + command_nest_depth++; while (cmdlines) { @@ -598,6 +600,7 @@ void while_command (char *arg, int from_tty) { struct command_line *command = NULL; + struct cleanup *old_chain; control_level = 1; command = get_command_line (while_control, arg); @@ -605,8 +608,13 @@ while_command (char *arg, int from_tty) if (command == NULL) return; + old_chain = make_cleanup_restore_integer (&interpreter_async); + interpreter_async = 0; + execute_control_command_untraced (command); free_command_lines (&command); + + do_cleanups (old_chain); } /* "if" command support. Execute either the true or false arm depending @@ -616,6 +624,7 @@ void if_command (char *arg, int from_tty) { struct command_line *command = NULL; + struct cleanup *old_chain; control_level = 1; command = get_command_line (if_control, arg); @@ -623,8 +632,13 @@ if_command (char *arg, int from_tty) if (command == NULL) return; + old_chain = make_cleanup_restore_integer (&interpreter_async); + interpreter_async = 0; + execute_control_command_untraced (command); free_command_lines (&command); + + do_cleanups (old_chain); } /* Cleanup */ @@ -1589,19 +1603,6 @@ source_cleanup_lines (void *args) source_file_name = p->old_file; } -struct wrapped_read_command_file_args -{ - FILE *stream; -}; - -static void -wrapped_read_command_file (struct ui_out *uiout, void *data) -{ - struct wrapped_read_command_file_args *args = data; - - read_command_file (args->stream); -} - /* Used to implement source_command. */ void @@ -1625,12 +1626,12 @@ script_from_file (FILE *stream, const char *file) error_pre_print = ""; { - struct gdb_exception e; - struct wrapped_read_command_file_args args; + volatile struct gdb_exception e; - args.stream = stream; - e = catch_exception (uiout, wrapped_read_command_file, &args, - RETURN_MASK_ERROR); + TRY_CATCH (e, RETURN_MASK_ERROR) + { + read_command_file (stream); + } switch (e.reason) { case 0: @@ -1674,7 +1675,7 @@ show_user_1 (struct cmd_list_element *c, char *prefix, char *name, return; fprintf_filtered (stream, "User command \"%s%s\":\n", prefix, name); - print_command_lines (uiout, cmdlines, 1); + print_command_lines (current_uiout, cmdlines, 1); fputs_filtered ("\n", stream); } diff --git a/contrib/gdb-7/gdb/cli/cli-script.h b/contrib/gdb-7/gdb/cli/cli-script.h index 9567f6e9a0..999c4e8a92 100644 --- a/contrib/gdb-7/gdb/cli/cli-script.h +++ b/contrib/gdb-7/gdb/cli/cli-script.h @@ -1,6 +1,5 @@ /* Header file for GDB CLI command implementation library. - Copyright (c) 2000, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2000, 2002, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/cli/cli-setshow.c b/contrib/gdb-7/gdb/cli/cli-setshow.c index 6acdd9156c..14fef7c1ec 100644 --- a/contrib/gdb-7/gdb/cli/cli-setshow.c +++ b/contrib/gdb-7/gdb/cli/cli-setshow.c @@ -1,7 +1,6 @@ /* Handle set and show GDB commands. - Copyright (c) 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2000-2003, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -125,6 +124,8 @@ deprecated_show_value_hack (struct ui_file *ignore_file, void do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) { + struct ui_out *uiout = current_uiout; + if (c->type == set_cmd) { switch (c->var_type) @@ -358,21 +359,18 @@ do_setshow_command (char *arg, int from_tty, struct cmd_list_element *c) } break; case var_uinteger: - if (*(unsigned int *) c->var == UINT_MAX) - { - fputs_filtered ("unlimited", stb->stream); - break; - } - /* else fall through */ case var_zuinteger: - case var_zinteger: - fprintf_filtered (stb->stream, "%u", *(unsigned int *) c->var); + if (c->var_type == var_uinteger + && *(unsigned int *) c->var == UINT_MAX) + fputs_filtered ("unlimited", stb->stream); + else + fprintf_filtered (stb->stream, "%u", *(unsigned int *) c->var); break; case var_integer: - if (*(int *) c->var == INT_MAX) - { - fputs_filtered ("unlimited", stb->stream); - } + case var_zinteger: + if (c->var_type == var_integer + && *(int *) c->var == INT_MAX) + fputs_filtered ("unlimited", stb->stream); else fprintf_filtered (stb->stream, "%d", *(int *) c->var); break; @@ -414,6 +412,7 @@ void cmd_show_list (struct cmd_list_element *list, int from_tty, char *prefix) { struct cleanup *showlist_chain; + struct ui_out *uiout = current_uiout; showlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "showlist"); for (; list != NULL; list = list->next) diff --git a/contrib/gdb-7/gdb/cli/cli-setshow.h b/contrib/gdb-7/gdb/cli/cli-setshow.h index 3cace8bd9b..cb8d2c5b42 100644 --- a/contrib/gdb-7/gdb/cli/cli-setshow.h +++ b/contrib/gdb-7/gdb/cli/cli-setshow.h @@ -1,6 +1,5 @@ /* Header file for GDB CLI set and show commands implementation. - Copyright (c) 2000, 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (c) 2000-2001, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/cli/cli-utils.c b/contrib/gdb-7/gdb/cli/cli-utils.c index 62a2f12c49..a7b27187ec 100644 --- a/contrib/gdb-7/gdb/cli/cli-utils.c +++ b/contrib/gdb-7/gdb/cli/cli-utils.c @@ -1,6 +1,6 @@ /* CLI utilities. - Copyright (c) 2011 Free Software Foundation, Inc. + Copyright (c) 2011-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/cli/cli-utils.h b/contrib/gdb-7/gdb/cli/cli-utils.h index 8a6e5b35dd..e23c7d82b9 100644 --- a/contrib/gdb-7/gdb/cli/cli-utils.h +++ b/contrib/gdb-7/gdb/cli/cli-utils.h @@ -1,6 +1,6 @@ /* CLI utilities. - Copyright (c) 2011 Free Software Foundation, Inc. + Copyright (c) 2011-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/coff-pe-read.c b/contrib/gdb-7/gdb/coff-pe-read.c index ca87b726d7..66c7c82e82 100644 --- a/contrib/gdb-7/gdb/coff-pe-read.c +++ b/contrib/gdb-7/gdb/coff-pe-read.c @@ -2,8 +2,7 @@ convert to internal format, for GDB. Used as a last resort if no debugging symbols recognized. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -24,9 +23,8 @@ #include "coff-pe-read.h" -#include "bfd.h" - #include "defs.h" +#include "bfd.h" #include "gdbtypes.h" #include "symtab.h" diff --git a/contrib/gdb-7/gdb/coff-pe-read.h b/contrib/gdb-7/gdb/coff-pe-read.h index a8b41d3768..5dbe8781ec 100644 --- a/contrib/gdb-7/gdb/coff-pe-read.h +++ b/contrib/gdb-7/gdb/coff-pe-read.h @@ -1,7 +1,6 @@ /* Interface to coff-pe-read.c (portable-executable-specific symbol reader). - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/coffread.c b/contrib/gdb-7/gdb/coffread.c index b11dd7387c..c727228b8f 100644 --- a/contrib/gdb-7/gdb/coffread.c +++ b/contrib/gdb-7/gdb/coffread.c @@ -1,7 +1,5 @@ /* Read coff symbol tables and convert to internal format, for GDB. - Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1987-2005, 2007-2012 Free Software Foundation, Inc. Contributed by David D. Johnson, Brown University (ddj@cs.brown.edu). This file is part of GDB. @@ -49,6 +47,10 @@ extern void _initialize_coffread (void); +/* The objfile we are currently reading. */ + +static struct objfile *coffread_objfile; + struct coff_symfile_info { file_ptr min_lineno_offset; /* Where in file lowest line#s are. */ @@ -355,7 +357,7 @@ coff_alloc_type (int index) We will fill it in later if we find out how. */ if (type == NULL) { - type = alloc_type (current_objfile); + type = alloc_type (coffread_objfile); *type_addr = type; } return type; @@ -637,7 +639,7 @@ coff_symfile_read (struct objfile *objfile, int symfile_flags) info->stabsects, info->stabstrsect->filepos, stabstrsize); } - if (dwarf2_has_info (objfile)) + if (dwarf2_has_info (objfile, NULL)) { /* DWARF2 sections. */ dwarf2_build_psymtabs (objfile); @@ -745,7 +747,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, if (val < 0) perror_with_name (objfile->name); - current_objfile = objfile; + coffread_objfile = objfile; nlist_bfd_global = objfile->obfd; nlist_nsyms_global = nsyms; last_source_file = NULL; @@ -1132,7 +1134,7 @@ coff_symtab_read (long symtab_offset, unsigned int nsyms, ALL_OBJFILE_SYMTABS (objfile, s) patch_opaque_types (s); - current_objfile = NULL; + coffread_objfile = NULL; } /* Routines for reading headers and symbols from executable. */ @@ -1153,14 +1155,14 @@ read_one_sym (struct coff_symbol *cs, cs->c_symnum = symnum; bytes = bfd_bread (temp_sym, local_symesz, nlist_bfd_global); if (bytes != local_symesz) - error (_("%s: error reading symbols"), current_objfile->name); + error (_("%s: error reading symbols"), coffread_objfile->name); bfd_coff_swap_sym_in (symfile_bfd, temp_sym, (char *) sym); cs->c_naux = sym->n_numaux & 0xff; if (cs->c_naux >= 1) { bytes = bfd_bread (temp_aux, local_auxesz, nlist_bfd_global); if (bytes != local_auxesz) - error (_("%s: error reading symbols"), current_objfile->name); + error (_("%s: error reading symbols"), coffread_objfile->name); bfd_coff_swap_aux_in (symfile_bfd, temp_aux, sym->n_type, sym->n_sclass, 0, cs->c_naux, (char *) aux); @@ -1170,7 +1172,7 @@ read_one_sym (struct coff_symbol *cs, { bytes = bfd_bread (temp_aux, local_auxesz, nlist_bfd_global); if (bytes != local_auxesz) - error (_("%s: error reading symbols"), current_objfile->name); + error (_("%s: error reading symbols"), coffread_objfile->name); } } cs->c_name = getsymname (sym); diff --git a/contrib/gdb-7/gdb/command.h b/contrib/gdb-7/gdb/command.h index 0e2547e7e3..d32e98e515 100644 --- a/contrib/gdb-7/gdb/command.h +++ b/contrib/gdb-7/gdb/command.h @@ -1,7 +1,7 @@ /* Header file for command-reading library command.c. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1999, 2000, - 2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1995, 1999-2000, 2002, 2004, 2007-2012 Free + Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -106,6 +106,8 @@ struct cmd_list_element; /* Forward-declarations of the entry-points of cli/cli-decode.c. */ +extern int valid_user_defined_cmd_name_p (const char *name); + extern struct cmd_list_element *add_cmd (char *, enum command_class, void (*fun) (char *, int), char *, struct cmd_list_element **); diff --git a/contrib/gdb-7/gdb/common/ax.def b/contrib/gdb-7/gdb/common/ax.def index 5fe2ebfdd2..fdc043fdb4 100644 --- a/contrib/gdb-7/gdb/common/ax.def +++ b/contrib/gdb-7/gdb/common/ax.def @@ -1,6 +1,5 @@ /* Definition of agent opcode values. -*- c -*- - Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1998-2000, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -86,8 +85,7 @@ DEFOP (swap, 0, 0, 2, 2, 0x2b) DEFOP (getv, 2, 0, 0, 1, 0x2c) DEFOP (setv, 2, 0, 0, 1, 0x2d) DEFOP (tracev, 2, 0, 0, 1, 0x2e) -/* We need something here just to make the tables come out ok. */ -DEFOP (invalid, 0, 0, 0, 0, 0x2f) +DEFOP (tracenz, 0, 0, 2, 0, 0x2f) DEFOP (trace16, 2, 0, 1, 1, 0x30) /* We need something here just to make the tables come out ok. */ DEFOP (invalid2, 0, 0, 0, 0, 0x31) diff --git a/contrib/gdb-7/gdb/common/buffer.c b/contrib/gdb-7/gdb/common/buffer.c new file mode 100644 index 0000000000..37b7b55f74 --- /dev/null +++ b/contrib/gdb-7/gdb/common/buffer.c @@ -0,0 +1,144 @@ +/* A simple growing buffer for GDB. + + Copyright (C) 2009-2012 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 . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "xml-utils.h" +#include "buffer.h" + +#include +#include +#include + +void +buffer_grow (struct buffer *buffer, const char *data, size_t size) +{ + char *new_buffer; + size_t new_buffer_size; + + if (size == 0) + return; + + new_buffer_size = buffer->buffer_size; + + if (new_buffer_size == 0) + new_buffer_size = 1; + + while (buffer->used_size + size > new_buffer_size) + new_buffer_size *= 2; + new_buffer = xrealloc (buffer->buffer, new_buffer_size); + if (!new_buffer) + abort (); + memcpy (new_buffer + buffer->used_size, data, size); + buffer->buffer = new_buffer; + buffer->buffer_size = new_buffer_size; + buffer->used_size += size; +} + +void +buffer_free (struct buffer *buffer) +{ + if (!buffer) + return; + + xfree (buffer->buffer); + buffer->buffer = NULL; + buffer->buffer_size = 0; + buffer->used_size = 0; +} + +void +buffer_init (struct buffer *buffer) +{ + memset (buffer, 0, sizeof (*buffer)); +} + +char* +buffer_finish (struct buffer *buffer) +{ + char *ret = buffer->buffer; + buffer->buffer = NULL; + buffer->buffer_size = 0; + buffer->used_size = 0; + return ret; +} + +void +buffer_xml_printf (struct buffer *buffer, const char *format, ...) +{ + va_list ap; + const char *f; + const char *prev; + int percent = 0; + + va_start (ap, format); + + prev = format; + for (f = format; *f; f++) + { + if (percent) + { + char buf[32]; + char *p; + char *str = buf; + + switch (*f) + { + case 's': + str = va_arg (ap, char *); + break; + case 'd': + sprintf (str, "%d", va_arg (ap, int)); + break; + case 'u': + sprintf (str, "%u", va_arg (ap, unsigned int)); + break; + case 'x': + sprintf (str, "%x", va_arg (ap, unsigned int)); + break; + case 'o': + sprintf (str, "%o", va_arg (ap, unsigned int)); + break; + default: + str = 0; + break; + } + + if (str) + { + buffer_grow (buffer, prev, f - prev - 1); + p = xml_escape_text (str); + buffer_grow_str (buffer, p); + xfree (p); + prev = f + 1; + } + percent = 0; + } + else if (*f == '%') + percent = 1; + } + + buffer_grow_str (buffer, prev); + va_end (ap); +} + diff --git a/contrib/gdb-7/gdb/common/buffer.h b/contrib/gdb-7/gdb/common/buffer.h new file mode 100644 index 0000000000..e4bad09238 --- /dev/null +++ b/contrib/gdb-7/gdb/common/buffer.h @@ -0,0 +1,63 @@ +/* A simple growing buffer for GDB. + + Copyright (C) 2009-2012 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 . */ + +#ifndef BUFFER_H +#define BUFFER_H + +#include +#include +#include "ansidecl.h" + +struct buffer +{ + char *buffer; + size_t buffer_size; /* allocated size */ + size_t used_size; /* actually used size */ +}; + +/* Append DATA of size SIZE to the end of BUFFER. Grows the buffer to + accommodate the new data. */ +void buffer_grow (struct buffer *buffer, const char *data, size_t size); + +/* Release any memory held by BUFFER. */ +void buffer_free (struct buffer *buffer); + +/* Initialize BUFFER. BUFFER holds no memory afterwards. */ +void buffer_init (struct buffer *buffer); + +/* Return a pointer into BUFFER data, effectivelly transfering + ownership of the buffer memory to the caller. Calling buffer_free + afterwards has no effect on the returned data. */ +char* buffer_finish (struct buffer *buffer); + +/* Simple printf to buffer function. Current implemented formatters: + %s - grow an xml escaped text in BUFFER. + %d - grow an signed integer in BUFFER. + %u - grow an unsigned integer in BUFFER. + %x - grow an unsigned integer formatted in hexadecimal in BUFFER. + %o - grow an unsigned integer formatted in octal in BUFFER. */ +void buffer_xml_printf (struct buffer *buffer, const char *format, ...) + ATTRIBUTE_PRINTF (2, 3); + +#define buffer_grow_str(BUFFER,STRING) \ + buffer_grow (BUFFER, STRING, strlen (STRING)) +#define buffer_grow_str0(BUFFER,STRING) \ + buffer_grow (BUFFER, STRING, strlen (STRING) + 1) + +#endif diff --git a/contrib/gdb-7/gdb/common/common-utils.c b/contrib/gdb-7/gdb/common/common-utils.c new file mode 100644 index 0000000000..ad01ed658d --- /dev/null +++ b/contrib/gdb-7/gdb/common/common-utils.c @@ -0,0 +1,168 @@ +/* Shared general utility routines for GDB, the GNU debugger. + + Copyright (C) 1986, 1988-2012 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 . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "gdb_assert.h" + +#include +#include + +/* The xmalloc() (libiberty.h) family of memory management routines. + + These are like the ISO-C malloc() family except that they implement + consistent semantics and guard against typical memory management + problems. */ + +/* NOTE: These are declared using PTR to ensure consistency with + "libiberty.h". xfree() is GDB local. */ + +PTR /* ARI: PTR */ +xmalloc (size_t size) +{ + void *val; + + /* See libiberty/xmalloc.c. This function need's to match that's + semantics. It never returns NULL. */ + if (size == 0) + size = 1; + + val = malloc (size); /* ARI: malloc */ + if (val == NULL) + malloc_failure (size); + + return val; +} + +PTR /* ARI: PTR */ +xrealloc (PTR ptr, size_t size) /* ARI: PTR */ +{ + void *val; + + /* See libiberty/xmalloc.c. This function need's to match that's + semantics. It never returns NULL. */ + if (size == 0) + size = 1; + + if (ptr != NULL) + val = realloc (ptr, size); /* ARI: realloc */ + else + val = malloc (size); /* ARI: malloc */ + if (val == NULL) + malloc_failure (size); + + return val; +} + +PTR /* ARI: PTR */ +xcalloc (size_t number, size_t size) +{ + void *mem; + + /* See libiberty/xmalloc.c. This function need's to match that's + semantics. It never returns NULL. */ + if (number == 0 || size == 0) + { + number = 1; + size = 1; + } + + mem = calloc (number, size); /* ARI: xcalloc */ + if (mem == NULL) + malloc_failure (number * size); + + return mem; +} + +void * +xzalloc (size_t size) +{ + return xcalloc (1, size); +} + +void +xfree (void *ptr) +{ + if (ptr != NULL) + free (ptr); /* ARI: free */ +} + +/* Like asprintf/vasprintf but get an internal_error if the call + fails. */ + +char * +xstrprintf (const char *format, ...) +{ + char *ret; + va_list args; + + va_start (args, format); + ret = xstrvprintf (format, args); + va_end (args); + return ret; +} + +char * +xstrvprintf (const char *format, va_list ap) +{ + char *ret = NULL; + int status = vasprintf (&ret, format, ap); + + /* NULL is returned when there was a memory allocation problem, or + any other error (for instance, a bad format string). A negative + status (the printed length) with a non-NULL buffer should never + happen, but just to be sure. */ + if (ret == NULL || status < 0) + internal_error (__FILE__, __LINE__, _("vasprintf call failed")); + return ret; +} + +void +xasprintf (char **ret, const char *format, ...) +{ + va_list args; + + va_start (args, format); + (*ret) = xstrvprintf (format, args); + va_end (args); +} + +void +xvasprintf (char **ret, const char *format, va_list ap) +{ + (*ret) = xstrvprintf (format, ap); +} + +int +xsnprintf (char *str, size_t size, const char *format, ...) +{ + va_list args; + int ret; + + va_start (args, format); + ret = vsnprintf (str, size, format, args); + gdb_assert (ret < size); + va_end (args); + + return ret; +} diff --git a/contrib/gdb-7/gdb/common/common-utils.h b/contrib/gdb-7/gdb/common/common-utils.h new file mode 100644 index 0000000000..030bcc5305 --- /dev/null +++ b/contrib/gdb-7/gdb/common/common-utils.h @@ -0,0 +1,57 @@ +/* Shared general utility routines for GDB, the GNU debugger. + + Copyright (C) 1986, 1988-2012 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 . */ + +#ifndef COMMON_UTILS_H +#define COMMON_UTILS_H + +#include "config.h" +#include "ansidecl.h" +#include +#include + +extern void malloc_failure (long size) ATTRIBUTE_NORETURN; +extern void internal_error (const char *file, int line, const char *, ...) + ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 4); + +/* xmalloc(), xrealloc() and xcalloc() have already been declared in + "libiberty.h". */ + +/* Like xmalloc, but zero the memory. */ +void *xzalloc (size_t); + +void xfree (void *); + +/* Like asprintf and vasprintf, but return the string, throw an error + if no memory. */ +char *xstrprintf (const char *format, ...) ATTRIBUTE_PRINTF (1, 2); +char *xstrvprintf (const char *format, va_list ap) + ATTRIBUTE_PRINTF (1, 0); + +/* Like asprintf/vasprintf but get an internal_error if the call + fails. */ +void xasprintf (char **ret, const char *format, ...) + ATTRIBUTE_PRINTF (2, 3); +void xvasprintf (char **ret, const char *format, va_list ap) + ATTRIBUTE_PRINTF (2, 0); + +/* Like snprintf, but throw an error if the output buffer is too small. */ +int xsnprintf (char *str, size_t size, const char *format, ...) + ATTRIBUTE_PRINTF (3, 4); + +#endif diff --git a/contrib/gdb-7/gdb/gdb_assert.h b/contrib/gdb-7/gdb/common/gdb_assert.h similarity index 89% rename from contrib/gdb-7/gdb/gdb_assert.h rename to contrib/gdb-7/gdb/common/gdb_assert.h index 634049e803..351f55877e 100644 --- a/contrib/gdb-7/gdb/gdb_assert.h +++ b/contrib/gdb-7/gdb/common/gdb_assert.h @@ -1,6 +1,5 @@ /* GDB-friendly replacement for . - Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -20,6 +19,12 @@ #ifndef GDB_ASSERT_H #define GDB_ASSERT_H +/* A static assertion. This will cause a compile-time error if EXPR, + which must be a compile-time constant, is false. */ + +#define static_assert(expr) \ + extern int never_defined_just_used_for_checking[(expr) ? 1 : -1] + /* PRAGMATICS: "gdb_assert.h":gdb_assert() is a lower case (rather than upper case) macro since that provides the closest fit to the existing lower case macro :assert() that it is diff --git a/contrib/gdb-7/gdb/gdb_regex.h b/contrib/gdb-7/gdb/common/gdb_dirent.h similarity index 52% copy from contrib/gdb-7/gdb/gdb_regex.h copy to contrib/gdb-7/gdb/common/gdb_dirent.h index 835cb09694..183dfe47e2 100644 --- a/contrib/gdb-7/gdb/gdb_regex.h +++ b/contrib/gdb-7/gdb/common/gdb_dirent.h @@ -1,6 +1,5 @@ -/* Portable . - Copyright (C) 2000, 2001, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. +/* Portable . + Copyright (C) 2000, 2002, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -17,19 +16,25 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef GDB_REGEX_H -#define GDB_REGEX_H 1 +#ifndef GDB_DIRENT_H +#define GDB_DIRENT_H 1 -#ifdef USE_INCLUDED_REGEX -# include "xregex.h" +/* See description of `AC_HEADER_DIRENT' in the Autoconf manual. */ +#ifdef HAVE_DIRENT_H +# include /* ARI: dirent.h */ +# define NAMELEN(dirent) strlen ((dirent)->d_name) /* ARI: strlen d_name */ #else -/* Request 4.2 BSD regex functions. */ -# define _REGEX_RE_COMP -# include +# define dirent direct +# define NAMELEN(dirent) (dirent)->d_namelen /* ARI: d_namelen */ +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif #endif -/* From utils.c. */ -struct cleanup *make_regfree_cleanup (regex_t *); -char *get_regcomp_error (int, regex_t *); - -#endif /* not GDB_REGEX_H */ +#endif /* not GDB_DIRENT_H */ diff --git a/contrib/gdb-7/gdb/gdb_locale.h b/contrib/gdb-7/gdb/common/gdb_locale.h similarity index 94% rename from contrib/gdb-7/gdb/gdb_locale.h rename to contrib/gdb-7/gdb/common/gdb_locale.h index 93f2f8c7c2..41e95c8efb 100644 --- a/contrib/gdb-7/gdb/gdb_locale.h +++ b/contrib/gdb-7/gdb/common/gdb_locale.h @@ -1,6 +1,5 @@ /* GDB-friendly replacement for . - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/common/gdb_signals.h b/contrib/gdb-7/gdb/common/gdb_signals.h index c04d795279..1cc629775d 100644 --- a/contrib/gdb-7/gdb/common/gdb_signals.h +++ b/contrib/gdb-7/gdb/common/gdb_signals.h @@ -1,7 +1,5 @@ /* Target signal translation functions for GDB. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-2003, 2006-2012 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/gdb_thread_db.h b/contrib/gdb-7/gdb/common/gdb_thread_db.h similarity index 96% rename from contrib/gdb-7/gdb/gdb_thread_db.h rename to contrib/gdb-7/gdb/common/gdb_thread_db.h index 957ed2cb42..3f6b6c1adb 100644 --- a/contrib/gdb-7/gdb/gdb_thread_db.h +++ b/contrib/gdb-7/gdb/common/gdb_thread_db.h @@ -6,13 +6,15 @@ #endif #ifndef LIBTHREAD_DB_SEARCH_PATH -#define LIBTHREAD_DB_SEARCH_PATH "" +/* $sdir appears before $pdir for some minimal security protection: + we trust the system libthread_db.so a bit more than some random + libthread_db associated with whatever libpthread the app is using. */ +#define LIBTHREAD_DB_SEARCH_PATH "$sdir:$pdir" #endif #else -/* Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010, 2011 -Free Software Foundation, Inc. +/* Copyright (C) 1999-2000, 2007-2012 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -200,16 +202,6 @@ typedef struct td_notify } u; } td_notify_t; -/* Some people still have libc5 or old glibc with no uintptr_t. - They lose. glibc 2.1.3 was released on 2000-02-25, and it has - uintptr_t, so it's reasonable to force these people to upgrade. */ - -#ifndef HAVE_UINTPTR_T -#error No uintptr_t available; your C library is too old. -/* Inhibit further compilation errors after this error. */ -#define uintptr_t void * -#endif - /* Structure used to report event. */ typedef struct td_event_msg { diff --git a/contrib/gdb-7/gdb/common/i386-xstate.h b/contrib/gdb-7/gdb/common/i386-xstate.h index 5a081f4d63..56a4d8fb6b 100644 --- a/contrib/gdb-7/gdb/common/i386-xstate.h +++ b/contrib/gdb-7/gdb/common/i386-xstate.h @@ -1,6 +1,6 @@ /* Common code for i386 XSAVE extended state. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/common/linux-osdata.c b/contrib/gdb-7/gdb/common/linux-osdata.c new file mode 100644 index 0000000000..4f97a22ea5 --- /dev/null +++ b/contrib/gdb-7/gdb/common/linux-osdata.c @@ -0,0 +1,588 @@ +/* Linux-specific functions to retrieve OS data. + + Copyright (C) 2009-2012 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 . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "linux-osdata.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xml-utils.h" +#include "buffer.h" +#include "gdb_assert.h" +#include "gdb_dirent.h" + +int +linux_common_core_of_thread (ptid_t ptid) +{ + char filename[sizeof ("/proc//task//stat") + + 2 * 20 /* decimal digits for 2 numbers, max 2^64 bit each */ + + 1]; + FILE *f; + char *content = NULL; + char *p; + char *ts = 0; + int content_read = 0; + int i; + int core; + + sprintf (filename, "/proc/%d/task/%ld/stat", + ptid_get_pid (ptid), ptid_get_lwp (ptid)); + f = fopen (filename, "r"); + if (!f) + return -1; + + for (;;) + { + int n; + content = xrealloc (content, content_read + 1024); + n = fread (content + content_read, 1, 1024, f); + content_read += n; + if (n < 1024) + { + content[content_read] = '\0'; + break; + } + } + + p = strchr (content, '('); + + /* Skip ")". */ + if (p != NULL) + p = strchr (p, ')'); + if (p != NULL) + p++; + + /* If the first field after program name has index 0, then core number is + the field with index 36. There's no constant for that anywhere. */ + if (p != NULL) + p = strtok_r (p, " ", &ts); + for (i = 0; p != NULL && i != 36; ++i) + p = strtok_r (NULL, " ", &ts); + + if (p == NULL || sscanf (p, "%d", &core) == 0) + core = -1; + + xfree (content); + fclose (f); + + return core; +} + +static void +command_from_pid (char *command, int maxlen, pid_t pid) +{ + char *stat_path = xstrprintf ("/proc/%d/stat", pid); + FILE *fp = fopen (stat_path, "r"); + + command[0] = '\0'; + + if (fp) + { + /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in + include/linux/sched.h in the Linux kernel sources) plus two + (for the brackets). */ + char cmd[32]; + pid_t stat_pid; + int items_read = fscanf (fp, "%d %32s", &stat_pid, cmd); + + if (items_read == 2 && pid == stat_pid) + { + cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */ + strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */ + } + + fclose (fp); + } + else + { + /* Return the PID if a /proc entry for the process cannot be found. */ + snprintf (command, maxlen, "%d", pid); + } + + command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */ + + xfree (stat_path); +} + +/* Returns the command-line of the process with the given PID. The returned + string needs to be freed using xfree after use. */ + +static char * +commandline_from_pid (pid_t pid) +{ + char *pathname = xstrprintf ("/proc/%d/cmdline", pid); + char *commandline = NULL; + FILE *f = fopen (pathname, "r"); + + if (f) + { + size_t len = 0; + + while (!feof (f)) + { + char buf[1024]; + size_t read_bytes = fread (buf, 1, sizeof (buf), f); + + if (read_bytes) + { + commandline = (char *) xrealloc (commandline, len + read_bytes + 1); + memcpy (commandline + len, buf, read_bytes); + len += read_bytes; + } + } + + fclose (f); + + if (commandline) + { + size_t i; + + /* Replace null characters with spaces. */ + for (i = 0; i < len; ++i) + if (commandline[i] == '\0') + commandline[i] = ' '; + + commandline[len] = '\0'; + } + else + { + /* Return the command in square brackets if the command-line is empty. */ + commandline = (char *) xmalloc (32); + commandline[0] = '['; + command_from_pid (commandline + 1, 31, pid); + + len = strlen (commandline); + if (len < 31) + strcat (commandline, "]"); + } + } + + xfree (pathname); + + return commandline; +} + +static void +user_from_uid (char *user, int maxlen, uid_t uid) +{ + struct passwd *pwentry = getpwuid (uid); + + if (pwentry) + { + strncpy (user, pwentry->pw_name, maxlen); + user[maxlen - 1] = '\0'; /* Ensure that the user name is null-terminated. */ + } + else + user[0] = '\0'; +} + +static int +get_process_owner (uid_t *owner, pid_t pid) +{ + struct stat statbuf; + char procentry[sizeof ("/proc/4294967295")]; + + sprintf (procentry, "/proc/%d", pid); + + if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + { + *owner = statbuf.st_uid; + return 0; + } + else + return -1; +} + +static int +get_number_of_cpu_cores (void) +{ + int cores = 0; + FILE *f = fopen ("/proc/cpuinfo", "r"); + + while (!feof (f)) + { + char buf[512]; + char *p = fgets (buf, sizeof (buf), f); + + if (p && strncmp (buf, "processor", 9) == 0) + ++cores; + } + + fclose (f); + + return cores; +} + +/* CORES points to an array of at least get_number_of_cpu_cores () elements. */ + +static int +get_cores_used_by_process (pid_t pid, int *cores) +{ + char taskdir[sizeof ("/proc/4294967295/task")]; + DIR *dir; + struct dirent *dp; + int task_count = 0; + + sprintf (taskdir, "/proc/%d/task", pid); + dir = opendir (taskdir); + if (dir) + { + while ((dp = readdir (dir)) != NULL) + { + pid_t tid; + int core; + + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; + + tid = atoi (dp->d_name); + core = linux_common_core_of_thread (ptid_build (pid, tid, 0)); + + if (core >= 0) + { + ++cores[core]; + ++task_count; + } + } + + closedir (dir); + } + + return task_count; +} + +static LONGEST +linux_xfer_osdata_processes (gdb_byte *readbuf, + ULONGEST offset, LONGEST len) +{ + /* We make the process list snapshot when the object starts to be read. */ + static const char *buf; + static LONGEST len_avail = -1; + static struct buffer buffer; + + if (offset == 0) + { + DIR *dirp; + + if (len_avail != -1 && len_avail != 0) + buffer_free (&buffer); + len_avail = 0; + buf = NULL; + buffer_init (&buffer); + buffer_grow_str (&buffer, "\n"); + + dirp = opendir ("/proc"); + if (dirp) + { + const int num_cores = get_number_of_cpu_cores (); + struct dirent *dp; + + while ((dp = readdir (dirp)) != NULL) + { + pid_t pid; + uid_t owner; + char user[UT_NAMESIZE]; + char *command_line; + int *cores; + int task_count; + char *cores_str; + int i; + + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; + + sscanf (dp->d_name, "%d", &pid); + command_line = commandline_from_pid (pid); + + if (get_process_owner (&owner, pid) == 0) + user_from_uid (user, sizeof (user), owner); + else + strcpy (user, "?"); + + /* Find CPU cores used by the process. */ + cores = (int *) xcalloc (num_cores, sizeof (int)); + task_count = get_cores_used_by_process (pid, cores); + cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1); + + for (i = 0; i < num_cores && task_count > 0; ++i) + if (cores[i]) + { + char core_str[sizeof ("4294967205")]; + + sprintf (core_str, "%d", i); + strcat (cores_str, core_str); + + task_count -= cores[i]; + if (task_count > 0) + strcat (cores_str, ","); + } + + xfree (cores); + + buffer_xml_printf ( + &buffer, + "" + "%d" + "%s" + "%s" + "%s" + "", + pid, + user, + command_line ? command_line : "", + cores_str); + + xfree (command_line); + xfree (cores_str); + } + + closedir (dirp); + } + + buffer_grow_str0 (&buffer, "\n"); + buf = buffer_finish (&buffer); + len_avail = strlen (buf); + } + + if (offset >= len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&buffer); + buf = NULL; + len_avail = 0; + return 0; + } + + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + return len; +} + +static LONGEST +linux_xfer_osdata_threads (gdb_byte *readbuf, + ULONGEST offset, LONGEST len) +{ + /* We make the process list snapshot when the object starts to be read. */ + static const char *buf; + static LONGEST len_avail = -1; + static struct buffer buffer; + + if (offset == 0) + { + DIR *dirp; + + if (len_avail != -1 && len_avail != 0) + buffer_free (&buffer); + len_avail = 0; + buf = NULL; + buffer_init (&buffer); + buffer_grow_str (&buffer, "\n"); + + dirp = opendir ("/proc"); + if (dirp) + { + struct dirent *dp; + + while ((dp = readdir (dirp)) != NULL) + { + struct stat statbuf; + char procentry[sizeof ("/proc/4294967295")]; + + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; + + sprintf (procentry, "/proc/%s", dp->d_name); + if (stat (procentry, &statbuf) == 0 + && S_ISDIR (statbuf.st_mode)) + { + DIR *dirp2; + char *pathname; + pid_t pid; + char command[32]; + + pathname = xstrprintf ("/proc/%s/task", dp->d_name); + + pid = atoi (dp->d_name); + command_from_pid (command, sizeof (command), pid); + + dirp2 = opendir (pathname); + + if (dirp2) + { + struct dirent *dp2; + + while ((dp2 = readdir (dirp2)) != NULL) + { + pid_t tid; + int core; + + if (!isdigit (dp2->d_name[0]) + || NAMELEN (dp2) > sizeof ("4294967295") - 1) + continue; + + tid = atoi (dp2->d_name); + core = linux_common_core_of_thread (ptid_build (pid, tid, 0)); + + buffer_xml_printf ( + &buffer, + "" + "%d" + "%s" + "%d" + "%d" + "", + pid, + command, + tid, + core); + } + + closedir (dirp2); + } + + xfree (pathname); + } + } + + closedir (dirp); + } + + buffer_grow_str0 (&buffer, "\n"); + buf = buffer_finish (&buffer); + len_avail = strlen (buf); + } + + if (offset >= len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&buffer); + buf = NULL; + len_avail = 0; + return 0; + } + + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + return len; +} + +struct osdata_type { + char *type; + char *description; + LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, LONGEST len); +} osdata_table[] = { + { "processes", "Listing of all processes", linux_xfer_osdata_processes }, + { "threads", "Listing of all threads", linux_xfer_osdata_threads }, + { NULL, NULL, NULL } +}; + +LONGEST +linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, + ULONGEST offset, LONGEST len) +{ + if (!annex || *annex == '\0') + { + static const char *buf; + static LONGEST len_avail = -1; + static struct buffer buffer; + + if (offset == 0) + { + int i; + + if (len_avail != -1 && len_avail != 0) + buffer_free (&buffer); + len_avail = 0; + buf = NULL; + buffer_init (&buffer); + buffer_grow_str (&buffer, "\n"); + + for (i = 0; osdata_table[i].type; ++i) + buffer_xml_printf ( + &buffer, + "" + "%s" + "%s" + "", + osdata_table[i].type, + osdata_table[i].description); + + buffer_grow_str0 (&buffer, "\n"); + buf = buffer_finish (&buffer); + len_avail = strlen (buf); + } + + if (offset >= len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&buffer); + buf = NULL; + len_avail = 0; + return 0; + } + + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + return len; + } + else + { + int i; + + for (i = 0; osdata_table[i].type; ++i) + { + if (strcmp (annex, osdata_table[i].type) == 0) + { + gdb_assert (readbuf); + + return (osdata_table[i].getter) (readbuf, offset, len); + } + } + + return 0; + } +} + diff --git a/contrib/gdb-7/gdb/ser-unix.h b/contrib/gdb-7/gdb/common/linux-osdata.h similarity index 65% copy from contrib/gdb-7/gdb/ser-unix.h copy to contrib/gdb-7/gdb/common/linux-osdata.h index 398b5d3565..b99c0e4276 100644 --- a/contrib/gdb-7/gdb/ser-unix.h +++ b/contrib/gdb-7/gdb/common/linux-osdata.h @@ -1,7 +1,6 @@ -/* Serial interface for UN*X file-descriptor based connection. - - Copyright (C) 1999, 2000, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. +/* Linux-specific functions to retrieve OS data. + + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -18,11 +17,13 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef SER_UNIX_H -#define SER_UNIX_H +#ifndef COMMON_LINUX_OSDATA_H +#define COMMON_LINUX_OSDATA_H + +#include "ptid.h" -extern int ser_unix_read_prim (struct serial *scb, size_t count); -extern int ser_unix_write_prim (struct serial *scb, const void *buf, - size_t count); +extern int linux_common_core_of_thread (ptid_t ptid); +extern LONGEST linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, + ULONGEST offset, LONGEST len); #endif diff --git a/contrib/gdb-7/gdb/tui/tui-main.c b/contrib/gdb-7/gdb/common/linux-procfs.c similarity index 50% copy from contrib/gdb-7/gdb/tui/tui-main.c copy to contrib/gdb-7/gdb/common/linux-procfs.c index 1401957e21..421f36edb4 100644 --- a/contrib/gdb-7/gdb/tui/tui-main.c +++ b/contrib/gdb-7/gdb/common/linux-procfs.c @@ -1,7 +1,5 @@ -/* Main function for TUI gdb. - - Copyright (C) 2002, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. +/* Linux-specific PROCFS manipulation routines. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -18,20 +16,40 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#ifdef GDBSERVER +#include "server.h" +#else #include "defs.h" -#include "main.h" #include "gdb_string.h" -#include "interps.h" +#endif + +#include "linux-procfs.h" + +/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not + found. */ int -main (int argc, char **argv) +linux_proc_get_tgid (int lwpid) { - struct captured_main_args args; - - memset (&args, 0, sizeof args); - args.argc = argc; - args.argv = argv; - args.use_windows = 0; - args.interpreter_p = INTERP_TUI; - return gdb_main (&args); + FILE *status_file; + char buf[100]; + int tgid = -1; + + snprintf (buf, sizeof (buf), "/proc/%d/status", (int) lwpid); + status_file = fopen (buf, "r"); + if (status_file != NULL) + { + while (fgets (buf, sizeof (buf), status_file)) + { + if (strncmp (buf, "Tgid:", 5) == 0) + { + tgid = strtoul (buf + strlen ("Tgid:"), NULL, 10); + break; + } + } + + fclose (status_file); + } + + return tgid; } diff --git a/contrib/gdb-7/gdb/tui/tui-command.h b/contrib/gdb-7/gdb/common/linux-procfs.h similarity index 66% copy from contrib/gdb-7/gdb/tui/tui-command.h copy to contrib/gdb-7/gdb/common/linux-procfs.h index bc2aaa1acd..a4ba4a1b48 100644 --- a/contrib/gdb-7/gdb/tui/tui-command.h +++ b/contrib/gdb-7/gdb/common/linux-procfs.h @@ -1,9 +1,5 @@ -/* Specific command window processing. - - Copyright (C) 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - - Contributed by Hewlett-Packard Company. +/* Linux-specific PROCFS manipulation routines. + Copyright (C) 2011-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -20,9 +16,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef TUI_COMMAND_H -#define TUI_COMMAND_H +#ifndef COMMON_LINUX_PROCFS_H +#define COMMON_LINUX_PROCFS_H + +#include + +/* Return the TGID of LWPID from /proc/pid/status. Returns -1 if not + found. */ -extern unsigned int tui_dispatch_ctrl_char (unsigned int); +extern int linux_proc_get_tgid (int lwpid); -#endif +#endif /* COMMON_LINUX_PROCFS_H */ diff --git a/contrib/gdb-7/gdb/common/linux-ptrace.h b/contrib/gdb-7/gdb/common/linux-ptrace.h new file mode 100644 index 0000000000..96ac3fb8b7 --- /dev/null +++ b/contrib/gdb-7/gdb/common/linux-ptrace.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2011-2012 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 . */ + +#ifndef COMMON_LINUX_PTRACE_H +#define COMMON_LINUX_PTRACE_H + +#include + +#ifndef PTRACE_GETSIGINFO +# define PTRACE_GETSIGINFO 0x4202 +# define PTRACE_SETSIGINFO 0x4203 +#endif /* PTRACE_GETSIGINF */ + +/* If the system headers did not provide the constants, hard-code the normal + values. */ +#ifndef PTRACE_EVENT_FORK + +#define PTRACE_SETOPTIONS 0x4200 +#define PTRACE_GETEVENTMSG 0x4201 + +/* options set using PTRACE_SETOPTIONS */ +#define PTRACE_O_TRACESYSGOOD 0x00000001 +#define PTRACE_O_TRACEFORK 0x00000002 +#define PTRACE_O_TRACEVFORK 0x00000004 +#define PTRACE_O_TRACECLONE 0x00000008 +#define PTRACE_O_TRACEEXEC 0x00000010 +#define PTRACE_O_TRACEVFORKDONE 0x00000020 +#define PTRACE_O_TRACEEXIT 0x00000040 + +/* Wait extended result codes for the above trace options. */ +#define PTRACE_EVENT_FORK 1 +#define PTRACE_EVENT_VFORK 2 +#define PTRACE_EVENT_CLONE 3 +#define PTRACE_EVENT_EXEC 4 +#define PTRACE_EVENT_VFORK_DONE 5 +#define PTRACE_EVENT_EXIT 6 + +#endif /* PTRACE_EVENT_FORK */ + +#if (defined __bfin__ || defined __frv__ || defined __sh__) \ + && !defined PTRACE_GETFDPIC +#define PTRACE_GETFDPIC 31 +#define PTRACE_GETFDPIC_EXEC 0 +#define PTRACE_GETFDPIC_INTERP 1 +#endif + +/* We can't always assume that this flag is available, but all systems + with the ptrace event handlers also have __WALL, so it's safe to use + in some contexts. */ +#ifndef __WALL +#define __WALL 0x40000000 /* Wait for any child. */ +#endif + +#endif /* COMMON_LINUX_PTRACE_H */ diff --git a/contrib/gdb-7/gdb/common/ptid.c b/contrib/gdb-7/gdb/common/ptid.c new file mode 100644 index 0000000000..f5add4d606 --- /dev/null +++ b/contrib/gdb-7/gdb/common/ptid.c @@ -0,0 +1,92 @@ +/* The ptid_t type and common functions operating on it. + + Copyright (C) 1986, 1988-2012 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 . */ + +#include "ptid.h" + +/* Oft used ptids */ +ptid_t null_ptid = { 0, 0, 0 }; +ptid_t minus_one_ptid = { -1, 0, 0 }; + +/* Create a ptid given the necessary PID, LWP, and TID components. */ + +ptid_t +ptid_build (int pid, long lwp, long tid) +{ + ptid_t ptid; + + ptid.pid = pid; + ptid.lwp = lwp; + ptid.tid = tid; + return ptid; +} + +/* Create a ptid from just a pid. */ + +ptid_t +pid_to_ptid (int pid) +{ + return ptid_build (pid, 0, 0); +} + +/* Fetch the pid (process id) component from a ptid. */ + +int +ptid_get_pid (ptid_t ptid) +{ + return ptid.pid; +} + +/* Fetch the lwp (lightweight process) component from a ptid. */ + +long +ptid_get_lwp (ptid_t ptid) +{ + return ptid.lwp; +} + +/* Fetch the tid (thread id) component from a ptid. */ + +long +ptid_get_tid (ptid_t ptid) +{ + return ptid.tid; +} + +/* ptid_equal() is used to test equality of two ptids. */ + +int +ptid_equal (ptid_t ptid1, ptid_t ptid2) +{ + return (ptid1.pid == ptid2.pid + && ptid1.lwp == ptid2.lwp + && ptid1.tid == ptid2.tid); +} + +/* Returns true if PTID represents a process. */ + +int +ptid_is_pid (ptid_t ptid) +{ + if (ptid_equal (minus_one_ptid, ptid)) + return 0; + if (ptid_equal (null_ptid, ptid)) + return 0; + + return (ptid_get_lwp (ptid) == 0 && ptid_get_tid (ptid) == 0); +} diff --git a/contrib/gdb-7/gdb/common/ptid.h b/contrib/gdb-7/gdb/common/ptid.h new file mode 100644 index 0000000000..243f4ab775 --- /dev/null +++ b/contrib/gdb-7/gdb/common/ptid.h @@ -0,0 +1,85 @@ +/* The ptid_t type and common functions operating on it. + + Copyright (C) 1986, 1988-2012 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 . */ + +#ifndef PTID_H +#define PTID_H + +/* The ptid struct is a collection of the various "ids" necessary + for identifying the inferior. This consists of the process id + (pid), thread id (tid), and other fields necessary for uniquely + identifying the inferior process/thread being debugged. When + manipulating ptids, the constructors, accessors, and predicate + declared in server.h should be used. These are as follows: + + ptid_build - Make a new ptid from a pid, lwp, and tid. + pid_to_ptid - Make a new ptid from just a pid. + ptid_get_pid - Fetch the pid component of a ptid. + ptid_get_lwp - Fetch the lwp component of a ptid. + ptid_get_tid - Fetch the tid component of a ptid. + ptid_equal - Test to see if two ptids are equal. + + Please do NOT access the struct ptid members directly (except, of + course, in the implementation of the above ptid manipulation + functions). */ + +struct ptid + { + /* Process id */ + int pid; + + /* Lightweight process id */ + long lwp; + + /* Thread id */ + long tid; + }; + +typedef struct ptid ptid_t; + +/* The null or zero ptid, often used to indicate no process. */ +extern ptid_t null_ptid; + +/* The -1 ptid, often used to indicate either an error condition + or a "don't care" condition, i.e, "run all threads." */ +extern ptid_t minus_one_ptid; + +/* Attempt to find and return an existing ptid with the given PID, LWP, + and TID components. If none exists, create a new one and return + that. */ +ptid_t ptid_build (int pid, long lwp, long tid); + +/* Find/Create a ptid from just a pid. */ +ptid_t pid_to_ptid (int pid); + +/* Fetch the pid (process id) component from a ptid. */ +int ptid_get_pid (ptid_t ptid); + +/* Fetch the lwp (lightweight process) component from a ptid. */ +long ptid_get_lwp (ptid_t ptid); + +/* Fetch the tid (thread id) component from a ptid. */ +long ptid_get_tid (ptid_t ptid); + +/* Compare two ptids to see if they are equal */ +int ptid_equal (ptid_t p1, ptid_t p2); + +/* Return true if PTID represents a process id. */ +int ptid_is_pid (ptid_t ptid); + +#endif diff --git a/contrib/gdb-7/gdb/common/signals.c b/contrib/gdb-7/gdb/common/signals.c index 55f708493d..75699dbd5a 100644 --- a/contrib/gdb-7/gdb/common/signals.c +++ b/contrib/gdb-7/gdb/common/signals.c @@ -1,7 +1,5 @@ /* Target signal translation functions for GDB. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-2003, 2006-2012 Free Software Foundation, Inc. Contributed by Cygnus Support. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/common/xml-utils.c b/contrib/gdb-7/gdb/common/xml-utils.c new file mode 100644 index 0000000000..c486220201 --- /dev/null +++ b/contrib/gdb-7/gdb/common/xml-utils.c @@ -0,0 +1,90 @@ +/* Shared helper routines for manipulating XML. + + Copyright (C) 2006-2012 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 . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "xml-utils.h" + +#include + +/* Return a malloc allocated string with special characters from TEXT + replaced by entity references. */ + +char * +xml_escape_text (const char *text) +{ + char *result; + int i, special; + + /* Compute the length of the result. */ + for (i = 0, special = 0; text[i] != '\0'; i++) + switch (text[i]) + { + case '\'': + case '\"': + special += 5; + break; + case '&': + special += 4; + break; + case '<': + case '>': + special += 3; + break; + default: + break; + } + + /* Expand the result. */ + result = xmalloc (i + special + 1); + for (i = 0, special = 0; text[i] != '\0'; i++) + switch (text[i]) + { + case '\'': + strcpy (result + i + special, "'"); + special += 5; + break; + case '\"': + strcpy (result + i + special, """); + special += 5; + break; + case '&': + strcpy (result + i + special, "&"); + special += 4; + break; + case '<': + strcpy (result + i + special, "<"); + special += 3; + break; + case '>': + strcpy (result + i + special, ">"); + special += 3; + break; + default: + result[i + special] = text[i]; + break; + } + result[i + special] = '\0'; + + return result; +} diff --git a/contrib/gdb-7/gdb/tui/tui-command.h b/contrib/gdb-7/gdb/common/xml-utils.h similarity index 69% copy from contrib/gdb-7/gdb/tui/tui-command.h copy to contrib/gdb-7/gdb/common/xml-utils.h index bc2aaa1acd..8d38ea1cb1 100644 --- a/contrib/gdb-7/gdb/tui/tui-command.h +++ b/contrib/gdb-7/gdb/common/xml-utils.h @@ -1,9 +1,6 @@ -/* Specific command window processing. +/* Shared helper routines for manipulating XML. - Copyright (C) 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - - Contributed by Hewlett-Packard Company. + Copyright (C) 2006-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -20,9 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef TUI_COMMAND_H -#define TUI_COMMAND_H +#ifndef XML_UTILS_H +#define XML_UTILS_H + +/* Return a malloc allocated string with special characters from TEXT + replaced by entity references. */ -extern unsigned int tui_dispatch_ctrl_char (unsigned int); +extern char *xml_escape_text (const char *text); #endif diff --git a/contrib/gdb-7/gdb/complaints.c b/contrib/gdb-7/gdb/complaints.c index 9129b98a6e..4df36ada86 100644 --- a/contrib/gdb-7/gdb/complaints.c +++ b/contrib/gdb-7/gdb/complaints.c @@ -1,7 +1,7 @@ /* Support for complaint handling during symbol reading in GDB. - Copyright (C) 1990, 1991, 1992, 1993, 1995, 1998, 1999, 2000, 2002, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1990-1993, 1995, 1998-2000, 2002, 2004-2012 Free + Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/complaints.h b/contrib/gdb-7/gdb/complaints.h index c18ec69b6b..67ede19856 100644 --- a/contrib/gdb-7/gdb/complaints.h +++ b/contrib/gdb-7/gdb/complaints.h @@ -1,7 +1,7 @@ /* Definitions for complaint handling during symbol reading in GDB. - Copyright (C) 1990, 1991, 1992, 1995, 1998, 2000, 2002, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1990-1992, 1995, 1998, 2000, 2002, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/completer.c b/contrib/gdb-7/gdb/completer.c index 606f78b38a..48a4e463a7 100644 --- a/contrib/gdb-7/gdb/completer.c +++ b/contrib/gdb-7/gdb/completer.c @@ -1,6 +1,5 @@ /* Line completion stuff for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/completer.h b/contrib/gdb-7/gdb/completer.h index 18367e53ff..0f522459b1 100644 --- a/contrib/gdb-7/gdb/completer.h +++ b/contrib/gdb-7/gdb/completer.h @@ -1,6 +1,5 @@ /* Header for GDB line completion. - Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/config.in b/contrib/gdb-7/gdb/config.in index 01ba750ebd..4aff10db69 100644 --- a/contrib/gdb-7/gdb/config.in +++ b/contrib/gdb-7/gdb/config.in @@ -158,6 +158,9 @@ */ #undef HAVE_DIRENT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + /* Define if ELF support should be included. */ #undef HAVE_ELF @@ -716,9 +719,22 @@ /* Define to 1 if you have the `_mcleanup' function. */ #undef HAVE__MCLEANUP +/* Path of directory of iconv program. */ +#undef ICONV_BIN + +/* Define if the iconv directory should be relocated when GDB is moved. */ +#undef ICONV_BIN_RELOCATABLE + /* Define as const if the declaration of iconv() needs const. */ #undef ICONV_CONST +/* directory to load the JIT readers from */ +#undef JIT_READER_DIR + +/* Define if the jit-reader-dir directory should be relocated when GDB is + moved. */ +#undef JIT_READER_DIR_RELOCATABLE + /* Define to a substitute value for mmap()'s MAP_ANONYMOUS flag. */ #undef MAP_ANONYMOUS @@ -804,6 +820,15 @@ /* The size of `long', as computed by sizeof. */ #undef SIZEOF_LONG +/* The size of `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* The size of `unsigned long long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG_LONG + +/* The size of `unsigned __int128', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED___INT128 + /* Define to l, ll, u, ul, ull, etc., as suitable for constants of type 'size_t'. */ #undef SIZE_T_SUFFIX @@ -947,9 +972,6 @@ /* Define to `int' if does not define. */ #undef pid_t -/* readline-6.0 started to use different name. */ -#undef readline_echoing_p - /* Define to the equivalent of the C99 'restrict' keyword, or to nothing if this is not supported. Do not define if restrict is supported directly. */ diff --git a/contrib/gdb-7/gdb/configure.ac b/contrib/gdb-7/gdb/configure.ac index f51a567a61..2fc39ff954 100644 --- a/contrib/gdb-7/gdb/configure.ac +++ b/contrib/gdb-7/gdb/configure.ac @@ -1,7 +1,5 @@ dnl Autoconf configure script for GDB, the GNU debugger. -dnl Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, -dnl 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 -dnl Free Software Foundation, Inc. +dnl Copyright (C) 1995-2012 Free Software Foundation, Inc. dnl dnl This file is part of GDB. dnl @@ -87,6 +85,26 @@ PACKAGE=gdb AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of this package. ]) AC_SUBST(PACKAGE) +# We never need to detect it in this sub-configure. +# But preserve it for config.status --recheck. +AC_ARG_VAR(MAKEINFO, + [Parent configure detects if it is of sufficient version.]) +AC_ARG_VAR(MAKEINFOFLAGS, + [Parameters for MAKEINFO.]) + +MAKEINFO_EXTRA_FLAGS="" +AC_CACHE_CHECK([whether $MAKEINFO supports @click], gdb_cv_have_makeinfo_click, + [echo '@clicksequence{a @click{} b}' >conftest.texinfo + if eval "$MAKEINFO conftest.texinfo >&5 2>&5"; then + gdb_cv_have_makeinfo_click=yes + else + gdb_cv_have_makeinfo_click=no + fi]) +if test x"$gdb_cv_have_makeinfo_click" = xyes; then + MAKEINFO_EXTRA_FLAGS="$MAKEINFO_EXTRA_FLAGS -DHAVE_MAKEINFO_CLICK" +fi +AC_SUBST(MAKEINFO_EXTRA_FLAGS) + # GDB does not use automake, but gnulib does. This line lets us # generate its Makefile.in. AM_INIT_AUTOMAKE(gdb, UNUSED-VERSION, [no-define]) @@ -433,6 +451,29 @@ AC_SEARCH_LIBS(dlgetmodinfo, [dl xpdl]) AM_ICONV +# GDB may fork/exec the iconv program to get the list of supported character +# sets. Allow the user to specify where to find it. +# There are several factors affecting the choice of option name: +# - There is already --with-libiconv-prefix but we can't use it, it specifies +# the build-time location of libiconv files. +# - The program we need to find is iconv, which comes with glibc. The user +# doesn't necessarily have libiconv installed. Therefore naming this +# --with-libiconv-foo feels wrong. +# - We want the path to be relocatable, but GDB_AC_DEFINE_RELOCATABLE is +# defined to work on directories not files (though it really doesn't know +# the difference). +# - Calling this --with-iconv-prefix is perceived to cause too much confusion +# with --with-libiconv-prefix. +# Putting these together is why the option name is --with-iconv-bin. + +AC_ARG_WITH(iconv-bin, +AS_HELP_STRING([--with-iconv-bin=PATH], [specify where to find the iconv program]), +[iconv_bin="${withval}" + AC_DEFINE_UNQUOTED([ICONV_BIN], ["${iconv_bin}"], + [Path of directory of iconv program.]) + GDB_AC_DEFINE_RELOCATABLE(ICONV_BIN, iconv, ${iconv_bin}) +]) + # On alpha-osf, it appears that libtermcap and libcurses are not compatible. # There is a very specific comment in /usr/include/curses.h explaining that # termcap routines built into libcurses must not be used. @@ -539,21 +580,6 @@ if test "$with_system_readline" = yes; then READLINE_DEPS= READLINE_CFLAGS= READLINE_TEXI_INCFLAG= - - # readline-6.0 started to use the name `_rl_echoing_p'. - # `$(READLINE_DIR)/' of bundled readline would not resolve in configure. - - AC_MSG_CHECKING([for readline_echoing_p]) - save_LIBS=$LIBS - LIBS="$LIBS $READLINE" - AC_LINK_IFELSE(AC_LANG_PROGRAM(,[[extern int readline_echoing_p; - return readline_echoing_p;]]), - [READLINE_ECHOING_P=yes], - [READLINE_ECHOING_P=no - AC_DEFINE([readline_echoing_p], [_rl_echoing_p], - [readline-6.0 started to use different name.])]) - LIBS="$save_LIBS" - AC_MSG_RESULT([$READLINE_ECHOING_P]) else READLINE='$(READLINE_DIR)/libreadline.a' READLINE_DEPS='$(READLINE)' @@ -565,6 +591,34 @@ AC_SUBST(READLINE_DEPS) AC_SUBST(READLINE_CFLAGS) AC_SUBST(READLINE_TEXI_INCFLAG) +# Generate jit-reader.h + +# This is typedeffed to GDB_CORE_ADDR in jit-reader.h +TARGET_PTR= + +AC_CHECK_SIZEOF(unsigned long long) +AC_CHECK_SIZEOF(unsigned long) +AC_CHECK_SIZEOF(unsigned __int128) + +if test "x${ac_cv_sizeof_unsigned_long}" = "x8"; then + TARGET_PTR="unsigned long" +elif test "x${ac_cv_sizeof_unsigned_long_long}" = "x8"; then + TARGET_PTR="unsigned long long" +elif test "x${ac_cv_sizeof_unsigned___int128}" = "x16"; then + TARGET_PTR="unsigned __int128" +else + TARGET_PTR="unsigned long" +fi + +AC_SUBST(TARGET_PTR) +AC_CONFIG_FILES([jit-reader.h:jit-reader.in]) + +AC_SEARCH_LIBS(dlopen, dl) + +GDB_AC_WITH_DIR([JIT_READER_DIR], [jit-reader-dir], + [directory to load the JIT readers from], + [${libdir}/gdb]) + AC_ARG_WITH(expat, AS_HELP_STRING([--with-expat], [include expat support (auto/yes/no)]), [], [with_expat=auto]) @@ -915,7 +969,8 @@ AC_CHECK_HEADERS([nlist.h machine/reg.h poll.h sys/poll.h proc_service.h \ sys/resource.h sys/procfs.h sys/ptrace.h ptrace.h \ sys/reg.h sys/debugreg.h sys/select.h sys/syscall.h \ sys/types.h sys/wait.h wait.h termios.h termio.h \ - sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h]) + sgtty.h unistd.h elf_hp.h ctype.h time.h locale.h \ + dlfcn.h]) AC_CHECK_HEADERS(link.h, [], [], [#if HAVE_SYS_TYPES_H # include diff --git a/contrib/gdb-7/gdb/configure.host b/contrib/gdb-7/gdb/configure.host index bcebdafdc6..531f4587c0 100644 --- a/contrib/gdb-7/gdb/configure.host +++ b/contrib/gdb-7/gdb/configure.host @@ -51,7 +51,6 @@ sparcv9 | sparc64) gdb_host_cpu=sparc ;; s390*) gdb_host_cpu=s390 ;; sh*) gdb_host_cpu=sh ;; x86_64*) gdb_host_cpu=i386 ;; -xscale*) gdb_host_cpu=arm ;; m32r*) gdb_host_cpu=m32r ;; xtensa*) gdb_host_cpu=xtensa ;; *) gdb_host_cpu=$host_cpu ;; diff --git a/contrib/gdb-7/gdb/configure.tgt b/contrib/gdb-7/gdb/configure.tgt index 5ab1554df7..137debae6f 100644 --- a/contrib/gdb-7/gdb/configure.tgt +++ b/contrib/gdb-7/gdb/configure.tgt @@ -94,7 +94,7 @@ arm*-*-symbianelf*) # Target: SymbianOS/arm gdb_target_obs="arm-tdep.o solib-target.o arm-symbian-tdep.o" ;; -arm*-*-* | thumb*-*-* | strongarm*-*-* | xscale-*-*) +arm*-*-*) # Target: ARM embedded system gdb_target_obs="arm-tdep.o" gdb_sim=../sim/arm/libsim.a @@ -552,6 +552,17 @@ spu*-*-*) build_gdbserver=yes ;; +tic6x-*-*linux) + # Target: GNU/Linux TI C6x + gdb_target_obs="tic6x-tdep.o tic6x-linux-tdep.o solib-dsbt.o \ + glibc-tdep.o corelow.o linux-tdep.o" + ;; + +tic6x-*-*) + # Target: TI C6X + gdb_target_obs="tic6x-tdep.o" + ;; + xstormy16-*-*) # Target: Sanyo Xstormy16a processor gdb_target_obs="xstormy16-tdep.o" diff --git a/contrib/gdb-7/gdb/continuations.c b/contrib/gdb-7/gdb/continuations.c new file mode 100644 index 0000000000..95e934e59e --- /dev/null +++ b/contrib/gdb-7/gdb/continuations.c @@ -0,0 +1,326 @@ +/* Continuations for GDB, the GNU debugger. + + Copyright (C) 1986, 1988-2012 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 . */ + +#include "defs.h" +#include "gdbthread.h" +#include "inferior.h" +#include "continuations.h" + +struct continuation +{ + struct continuation *next; + continuation_ftype *function; + continuation_free_arg_ftype *free_arg; + void *arg; +}; + +/* Add a new continuation to the continuation chain. Args are + FUNCTION to run the continuation up with, and ARG to pass to + it. */ + +static void +make_continuation (struct continuation **pmy_chain, + continuation_ftype *function, + void *arg, void (*free_arg) (void *)) +{ + struct continuation *new = XNEW (struct continuation); + + new->next = *pmy_chain; + new->function = function; + new->free_arg = free_arg; + new->arg = arg; + *pmy_chain = new; +} + +static void +do_my_continuations_1 (struct continuation **pmy_chain, int err) +{ + struct continuation *ptr; + + while ((ptr = *pmy_chain) != NULL) + { + *pmy_chain = ptr->next; /* Do this first in case of recursion. */ + (*ptr->function) (ptr->arg, err); + if (ptr->free_arg) + (*ptr->free_arg) (ptr->arg); + xfree (ptr); + } +} + +static void +do_my_continuations (struct continuation **list, int err) +{ + struct continuation *continuations; + + if (*list == NULL) + return; + + /* Copy the list header into another pointer, and set the global + list header to null, so that the global list can change as a side + effect of invoking the continuations and the processing of the + preexisting continuations will not be affected. */ + + continuations = *list; + *list = NULL; + + /* Work now on the list we have set aside. */ + do_my_continuations_1 (&continuations, err); +} + +static void +discard_my_continuations_1 (struct continuation **pmy_chain) +{ + struct continuation *ptr; + + while ((ptr = *pmy_chain) != NULL) + { + *pmy_chain = ptr->next; + if (ptr->free_arg) + (*ptr->free_arg) (ptr->arg); + xfree (ptr); + } +} + +static void +discard_my_continuations (struct continuation **list) +{ + struct continuation *continuation_ptr = *list; + + discard_my_continuations_1 (list); + *list = NULL; +} + +/* Add a continuation to the continuation list of INFERIOR. The new + continuation will be added at the front. */ + +void +add_inferior_continuation (continuation_ftype *hook, void *args, + continuation_free_arg_ftype *free_arg) +{ + struct inferior *inf = current_inferior (); + + make_continuation (&inf->continuations, hook, args, free_arg); +} + +/* Do all continuations of the current inferior. */ + +void +do_all_inferior_continuations (int err) +{ + struct inferior *inf = current_inferior (); + do_my_continuations (&inf->continuations, err); +} + +/* Get rid of all the inferior-wide continuations of INF. */ + +void +discard_all_inferior_continuations (struct inferior *inf) +{ + discard_my_continuations (&inf->continuations); +} + +/* Add a continuation to the continuation list of THREAD. The new + continuation will be added at the front. */ + +void +add_continuation (struct thread_info *thread, + continuation_ftype *hook, void *args, + continuation_free_arg_ftype *free_arg) +{ + make_continuation (&thread->continuations, hook, args, free_arg); +} + +static void +restore_thread_cleanup (void *arg) +{ + ptid_t *ptid_p = arg; + + switch_to_thread (*ptid_p); +} + +/* Walk down the continuation list of PTID, and execute all the + continuations. There is a problem though. In some cases new + continuations may be added while we are in the middle of this loop. + If this happens they will be added in the front, and done before we + have a chance of exhausting those that were already there. We need + to then save the beginning of the list in a pointer and do the + continuations from there on, instead of using the global beginning + of list as our iteration pointer. */ + +static void +do_all_continuations_ptid (ptid_t ptid, + struct continuation **continuations_p, + int err) +{ + struct cleanup *old_chain; + ptid_t current_thread; + + if (*continuations_p == NULL) + return; + + current_thread = inferior_ptid; + + /* Restore selected thread on exit. Don't try to restore the frame + as well, because: + + - When running continuations, the selected frame is always #0. + + - The continuations may trigger symbol file loads, which may + change the frame layout (frame ids change), which would trigger + a warning if we used make_cleanup_restore_current_thread. */ + + old_chain = make_cleanup (restore_thread_cleanup, ¤t_thread); + + /* Let the continuation see this thread as selected. */ + switch_to_thread (ptid); + + do_my_continuations (continuations_p, err); + + do_cleanups (old_chain); +} + +/* Callback for iterate over threads. */ + +static int +do_all_continuations_thread_callback (struct thread_info *thread, void *data) +{ + int err = * (int *) data; + do_all_continuations_ptid (thread->ptid, &thread->continuations, err); + return 0; +} + +/* Do all continuations of thread THREAD. */ + +void +do_all_continuations_thread (struct thread_info *thread, int err) +{ + do_all_continuations_thread_callback (thread, &err); +} + +/* Do all continuations of all threads. */ + +void +do_all_continuations (int err) +{ + iterate_over_threads (do_all_continuations_thread_callback, &err); +} + +/* Callback for iterate over threads. */ + +static int +discard_all_continuations_thread_callback (struct thread_info *thread, + void *data) +{ + discard_my_continuations (&thread->continuations); + return 0; +} + +/* Get rid of all the continuations of THREAD. */ + +void +discard_all_continuations_thread (struct thread_info *thread) +{ + discard_all_continuations_thread_callback (thread, NULL); +} + +/* Get rid of all the continuations of all threads. */ + +void +discard_all_continuations (void) +{ + iterate_over_threads (discard_all_continuations_thread_callback, NULL); +} + + +/* Add a continuation to the intermediate continuation list of THREAD. + The new continuation will be added at the front. */ + +void +add_intermediate_continuation (struct thread_info *thread, + continuation_ftype *hook, + void *args, + continuation_free_arg_ftype *free_arg) +{ + make_continuation (&thread->intermediate_continuations, hook, + args, free_arg); +} + +/* Walk down the cmd_continuation list, and execute all the + continuations. There is a problem though. In some cases new + continuations may be added while we are in the middle of this + loop. If this happens they will be added in the front, and done + before we have a chance of exhausting those that were already + there. We need to then save the beginning of the list in a pointer + and do the continuations from there on, instead of using the + global beginning of list as our iteration pointer. */ + +static int +do_all_intermediate_continuations_thread_callback (struct thread_info *thread, + void *data) +{ + int err = * (int *) data; + + do_all_continuations_ptid (thread->ptid, + &thread->intermediate_continuations, err); + return 0; +} + +/* Do all intermediate continuations of thread THREAD. */ + +void +do_all_intermediate_continuations_thread (struct thread_info *thread, int err) +{ + do_all_intermediate_continuations_thread_callback (thread, &err); +} + +/* Do all intermediate continuations of all threads. */ + +void +do_all_intermediate_continuations (int err) +{ + iterate_over_threads (do_all_intermediate_continuations_thread_callback, + &err); +} + +/* Callback for iterate over threads. */ + +static int +discard_all_intermediate_continuations_thread_callback (struct thread_info *thread, + void *data) +{ + discard_my_continuations (&thread->intermediate_continuations); + return 0; +} + +/* Get rid of all the intermediate continuations of THREAD. */ + +void +discard_all_intermediate_continuations_thread (struct thread_info *thread) +{ + discard_all_intermediate_continuations_thread_callback (thread, NULL); +} + +/* Get rid of all the intermediate continuations of all threads. */ + +void +discard_all_intermediate_continuations (void) +{ + iterate_over_threads (discard_all_intermediate_continuations_thread_callback, + NULL); +} diff --git a/contrib/gdb-7/gdb/continuations.h b/contrib/gdb-7/gdb/continuations.h new file mode 100644 index 0000000000..1c7d1d9540 --- /dev/null +++ b/contrib/gdb-7/gdb/continuations.h @@ -0,0 +1,74 @@ +/* Continuations for GDB, the GNU debugger. + + Copyright (C) 1999-2005, 2007-2012 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 . */ + +#ifndef CONTINUATIONS_H +#define CONTINUATIONS_H + +struct thread_info; +struct inferior; + +/* To continue the execution commands when running gdb asynchronously. + A continuation structure contains a pointer to a function to be called + to finish the command, once the target has stopped. Such mechanism is + used by the finish and until commands, and in the remote protocol + when opening an extended-remote connection. */ + +/* Prototype of the continuation callback functions. ARG is the + continuation argument registered in the corresponding + add_*_continuation call. ERR is true when the command should be + cancelled instead of finished normally. In that case, the + continuation should clean up whatever state had been set up for the + command in question (e.g., remove momentary breakpoints). This + happens e.g., when an error was thrown while handling a target + event, or when the inferior thread the command was being executed + on exits. */ +typedef void (continuation_ftype) (void *arg, int err); + +/* Prototype of the function responsible for releasing the argument + passed to the continuation callback functions, either when the + continuation is called, or discarded. */ +typedef void (continuation_free_arg_ftype) (void *); + +/* Thread specific continuations. */ + +extern void add_continuation (struct thread_info *, + continuation_ftype *, void *, + continuation_free_arg_ftype *); +extern void do_all_continuations (int err); +extern void do_all_continuations_thread (struct thread_info *, int err); +extern void discard_all_continuations (void); +extern void discard_all_continuations_thread (struct thread_info *); + +extern void add_intermediate_continuation (struct thread_info *, + continuation_ftype *, void *, + continuation_free_arg_ftype *); +extern void do_all_intermediate_continuations (int err); +extern void do_all_intermediate_continuations_thread (struct thread_info *, int err); +extern void discard_all_intermediate_continuations (void); +extern void discard_all_intermediate_continuations_thread (struct thread_info *); + +/* Inferior specific (any thread) continuations. */ + +extern void add_inferior_continuation (continuation_ftype *, + void *, + continuation_free_arg_ftype *); +extern void do_all_inferior_continuations (int err); +extern void discard_all_inferior_continuations (struct inferior *inf); + +#endif diff --git a/contrib/gdb-7/gdb/corefile.c b/contrib/gdb-7/gdb/corefile.c index ce3b755680..c07447b209 100644 --- a/contrib/gdb-7/gdb/corefile.c +++ b/contrib/gdb-7/gdb/corefile.c @@ -1,7 +1,6 @@ /* Core dump and executable file functions above target vector, for GDB. - Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1996, 1997, 1998, - 1999, 2000, 2001, 2003, 2006, 2007, 2008, 2009, 2010, 2011 + Copyright (C) 1986-1987, 1989, 1991-1994, 1996-2001, 2003, 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/corelow.c b/contrib/gdb-7/gdb/corelow.c index f34b8e1b9d..bbfb8ee51f 100644 --- a/contrib/gdb-7/gdb/corelow.c +++ b/contrib/gdb-7/gdb/corelow.c @@ -1,8 +1,7 @@ /* Core dump and executable file functions below target vector, for GDB. - Copyright (C) 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1986-1987, 1989, 1991-2001, 2003-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -47,6 +46,7 @@ #include "filenames.h" #include "progspace.h" #include "objfiles.h" +#include "wrapper.h" #ifndef O_LARGEFILE @@ -428,7 +428,7 @@ core_open (char *filename, int from_tty) may be a thread_stratum target loaded on top of target core by now. The layer above should claim threads found in the BFD sections. */ - target_find_new_threads (); + gdb_target_find_new_threads (); p = bfd_core_file_failing_command (core_bfd); if (p) diff --git a/contrib/gdb-7/gdb/cp-abi.c b/contrib/gdb-7/gdb/cp-abi.c index 040962eba2..cdc4a139cf 100644 --- a/contrib/gdb-7/gdb/cp-abi.c +++ b/contrib/gdb-7/gdb/cp-abi.c @@ -1,7 +1,6 @@ /* Generic code for supporting multiple C++ ABI's - Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -262,6 +261,7 @@ find_cp_abi (const char *short_name) static void list_cp_abis (int from_tty) { + struct ui_out *uiout = current_uiout; struct cleanup *cleanup_chain; int i; @@ -309,6 +309,8 @@ set_cp_abi_cmd (char *args, int from_tty) static void show_cp_abi_cmd (char *args, int from_tty) { + struct ui_out *uiout = current_uiout; + ui_out_text (uiout, "The currently selected C++ ABI is \""); ui_out_field_string (uiout, "cp-abi", current_cp_abi.shortname); diff --git a/contrib/gdb-7/gdb/cp-abi.h b/contrib/gdb-7/gdb/cp-abi.h index 9bfa1b0356..0f24e9a975 100644 --- a/contrib/gdb-7/gdb/cp-abi.h +++ b/contrib/gdb-7/gdb/cp-abi.h @@ -3,8 +3,7 @@ Contributed by Daniel Berlin - Copyright (C) 2001, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001, 2005-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/cp-name-parser.y b/contrib/gdb-7/gdb/cp-name-parser.y index 87367779a0..8b4a1b946c 100644 --- a/contrib/gdb-7/gdb/cp-name-parser.y +++ b/contrib/gdb-7/gdb/cp-name-parser.y @@ -1,7 +1,6 @@ /* YACC parser for C++ names, for GDB. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2005, 2007-2012 Free Software Foundation, Inc. Parts of the lexer are based on c-exp.y from GDB. @@ -41,6 +40,7 @@ #include "libiberty.h" #include "demangle.h" #include "cp-support.h" +#include "gdb_assert.h" /* Bison does not make it easy to create a parser without global state, unfortunately. Here are all the global variables used @@ -60,7 +60,7 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg; struct demangle_info { int used; - struct demangle_info *prev, *next; + struct demangle_info *next; struct demangle_component comps[ALLOC_CHUNK]; }; @@ -76,7 +76,6 @@ d_grab (void) if (demangle_info->next == NULL) { more = malloc (sizeof (struct demangle_info)); - more->prev = demangle_info; more->next = NULL; demangle_info->next = more; } @@ -1935,20 +1934,14 @@ yyerror (char *msg) generally allocate too many components, but the extra memory usage doesn't hurt because the trees are temporary and the storage is reused. More may be allocated later, by d_grab. */ -static void +static struct demangle_info * allocate_info (void) { - if (demangle_info == NULL) - { - demangle_info = malloc (sizeof (struct demangle_info)); - demangle_info->prev = NULL; - demangle_info->next = NULL; - } - else - while (demangle_info->prev) - demangle_info = demangle_info->prev; + struct demangle_info *info = malloc (sizeof (struct demangle_info)); - demangle_info->used = 0; + info->next = NULL; + info->used = 0; + return info; } /* Convert RESULT to a string. The return value is allocated @@ -1966,23 +1959,99 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len) &err); } +/* A convenience function to allocate and initialize a new struct + demangled_parse_info. */ + +struct demangle_parse_info * +cp_new_demangle_parse_info (void) +{ + struct demangle_parse_info *info; + + info = malloc (sizeof (struct demangle_parse_info)); + info->info = NULL; + info->tree = NULL; + obstack_init (&info->obstack); + + return info; +} + +/* Free any memory associated with the given PARSE_INFO. */ + +void +cp_demangled_name_parse_free (struct demangle_parse_info *parse_info) +{ + struct demangle_info *info = parse_info->info; + + /* Free any allocated chunks of memory for the parse. */ + while (info != NULL) + { + struct demangle_info *next = info->next; + + free (info); + info = next; + } + + /* Free any memory allocated during typedef replacement. */ + obstack_free (&parse_info->obstack, NULL); + + /* Free the parser info. */ + free (parse_info); +} + +/* Merge the two parse trees given by DEST and SRC. The parse tree + in SRC is attached to DEST at the node represented by TARGET. + SRC is then freed. + + NOTE 1: Since there is no API to merge obstacks, this function does + even attempt to try it. Fortunately, we do not (yet?) need this ability. + The code will assert if SRC->obstack is not empty. + + NOTE 2: The string from which SRC was parsed must not be freed, since + this function will place pointers to that string into DEST. */ + +void +cp_merge_demangle_parse_infos (struct demangle_parse_info *dest, + struct demangle_component *target, + struct demangle_parse_info *src) + +{ + struct demangle_info *di; + + /* Copy the SRC's parse data into DEST. */ + *target = *src->tree; + di = dest->info; + while (di->next != NULL) + di = di->next; + di->next = src->info; + + /* Clear the (pointer to) SRC's parse data so that it is not freed when + cp_demangled_parse_info_free is called. */ + src->info = NULL; + + /* Free SRC. */ + cp_demangled_name_parse_free (src); +} + /* Convert a demangled name to a demangle_component tree. On success, - the root of the new tree is returned; it is valid until the next - call to this function and should not be freed. On error, NULL is + a structure containing the root of the new tree is returned; it must + be freed by calling cp_demangled_name_parse_free. On error, NULL is returned, and an error message will be set in *ERRMSG (which does not need to be freed). */ -struct demangle_component * +struct demangle_parse_info * cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg) { static char errbuf[60]; - struct demangle_component *result; + struct demangle_parse_info *result; prev_lexptr = lexptr = demangled_name; error_lexptr = NULL; global_errmsg = NULL; - allocate_info (); + demangle_info = allocate_info (); + + result = cp_new_demangle_parse_info (); + result->info = demangle_info; if (yyparse ()) { @@ -1993,10 +2062,11 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg) strcat (errbuf, "'"); *errmsg = errbuf; } + cp_demangled_name_parse_free (result); return NULL; } - result = global_result; + result->tree = global_result; global_result = NULL; return result; @@ -2042,7 +2112,24 @@ void xfree (void *ptr) { if (ptr != NULL) - free (ptr); + { + /* Literal `free' would get translated back to xfree again. */ + CONCAT2 (fr,ee) (ptr); + } +} + +/* GDB normally defines internal_error itself, but when this file is built + as a standalone program, we must also provide an implementation. */ + +void +internal_error (const char *file, int line, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + fprintf (stderr, "%s:%d: internal error: ", file, line); + vfprintf (stderr, fmt, ap); + exit (1); } int @@ -2052,7 +2139,7 @@ main (int argc, char **argv) char buf[65536]; int arg; const char *errmsg; - struct demangle_component *result; + struct demangle_parse_info *result; arg = 1; if (argv[arg] && strcmp (argv[arg], "--debug") == 0) @@ -2071,7 +2158,7 @@ main (int argc, char **argv) str2 = cplus_demangle (buf, DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE); if (str2 == NULL) { - /* printf ("Demangling error\n"); */ + printf ("Demangling error\n"); if (c) printf ("%s%c%s\n", buf, c, extra_chars); else @@ -2086,7 +2173,8 @@ main (int argc, char **argv) continue; } - cp_print (result); + cp_print (result->tree); + cp_demangled_name_parse_free (result); free (str2); if (c) @@ -2105,7 +2193,8 @@ main (int argc, char **argv) fputc ('\n', stderr); return 0; } - cp_print (result); + cp_print (result->tree); + cp_demangled_name_parse_free (result); putchar ('\n'); } return 0; diff --git a/contrib/gdb-7/gdb/cp-namespace.c b/contrib/gdb-7/gdb/cp-namespace.c index cc761c8cd1..170dd5f82f 100644 --- a/contrib/gdb-7/gdb/cp-namespace.c +++ b/contrib/gdb-7/gdb/cp-namespace.c @@ -1,6 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. @@ -49,29 +48,12 @@ static struct type *cp_lookup_transparent_type_loop (const char *name, const char *scope, int scope_len); -static void initialize_namespace_symtab (struct objfile *objfile); - -static struct block *get_possible_namespace_block (struct objfile *objfile); - -static void free_namespace_block (struct symtab *symtab); - -static int check_possible_namespace_symbols_loop (const char *name, - int len, - struct objfile *objfile); - -static int check_one_possible_namespace_symbol (const char *name, - int len, - struct objfile *objfile); - -static struct symbol *lookup_possible_namespace_symbol (const char *name); - -static void maintenance_cplus_namespace (char *args, int from_tty); - /* Check to see if SYMBOL refers to an object contained within an anonymous namespace; if so, add an appropriate using directive. */ void -cp_scan_for_anonymous_namespaces (const struct symbol *symbol) +cp_scan_for_anonymous_namespaces (const struct symbol *const symbol, + struct objfile *const objfile) { if (SYMBOL_DEMANGLED_NAME (symbol) != NULL) { @@ -113,8 +95,8 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol) anonymous namespace. So add symbols in it to the namespace given by the previous component if there is one, or to the global namespace if there isn't. */ - cp_add_using_directive (dest, src, NULL, NULL, - &SYMBOL_SYMTAB (symbol)->objfile->objfile_obstack); + cp_add_using_directive (dest, src, NULL, NULL, NULL, + &objfile->objfile_obstack); } /* The "+ 2" is for the "::". */ previous_component = next_component + 2; @@ -134,14 +116,17 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol) in the current scope. If ALIAS is NULL then the namespace is known by its original name. DECLARATION is the name if the imported varable if this is a declaration import (Eg. using A::x), otherwise - it is NULL. The arguments are copied into newly allocated memory - so they can be temporaries. */ + it is NULL. EXCLUDES is a list of names not to import from an imported + module or NULL. The arguments are copied into newly allocated memory so + they can be temporaries. For EXCLUDES the VEC pointers are copied but the + pointed to characters are not copied. */ void cp_add_using_directive (const char *dest, const char *src, const char *alias, const char *declaration, + VEC (const_char_ptr) *excludes, struct obstack *obstack) { struct using_direct *current; @@ -151,18 +136,41 @@ cp_add_using_directive (const char *dest, for (current = using_directives; current != NULL; current = current->next) { - if (strcmp (current->import_src, src) == 0 - && strcmp (current->import_dest, dest) == 0 - && ((alias == NULL && current->alias == NULL) - || (alias != NULL && current->alias != NULL - && strcmp (alias, current->alias) == 0)) - && ((declaration == NULL && current->declaration == NULL) - || (declaration != NULL && current->declaration != NULL - && strcmp (declaration, current->declaration) == 0))) - return; + int ix; + const char *param; + + if (strcmp (current->import_src, src) != 0) + continue; + if (strcmp (current->import_dest, dest) != 0) + continue; + if ((alias == NULL && current->alias != NULL) + || (alias != NULL && current->alias == NULL) + || (alias != NULL && current->alias != NULL + && strcmp (alias, current->alias) != 0)) + continue; + if ((declaration == NULL && current->declaration != NULL) + || (declaration != NULL && current->declaration == NULL) + || (declaration != NULL && current->declaration != NULL + && strcmp (declaration, current->declaration) != 0)) + continue; + + /* Compare the contents of EXCLUDES. */ + for (ix = 0; VEC_iterate (const_char_ptr, excludes, ix, param); ix++) + if (current->excludes[ix] == NULL + || strcmp (param, current->excludes[ix]) != 0) + break; + if (ix < VEC_length (const_char_ptr, excludes) + || current->excludes[ix] != NULL) + continue; + + /* Parameters exactly match CURRENT. */ + return; } - new = OBSTACK_ZALLOC (obstack, struct using_direct); + new = obstack_alloc (obstack, (sizeof (*new) + + (VEC_length (const_char_ptr, excludes) + * sizeof (*new->excludes)))); + memset (new, 0, sizeof (*new)); new->import_src = obsavestring (src, strlen (src), obstack); new->import_dest = obsavestring (dest, strlen (dest), obstack); @@ -174,6 +182,10 @@ cp_add_using_directive (const char *dest, new->declaration = obsavestring (declaration, strlen (declaration), obstack); + memcpy (new->excludes, VEC_address (const_char_ptr, excludes), + VEC_length (const_char_ptr, excludes) * sizeof (*new->excludes)); + new->excludes[VEC_length (const_char_ptr, excludes)] = NULL; + new->next = using_directives; using_directives = new; } @@ -342,6 +354,8 @@ cp_lookup_symbol_imports (const char *scope, current != NULL; current = current->next) { + const char **excludep; + len = strlen (current->import_dest); directive_match = (search_parents ? (strncmp (scope, current->import_dest, @@ -355,62 +369,72 @@ cp_lookup_symbol_imports (const char *scope, ancestors then it is applicable. */ if (directive_match && !current->searched) { - /* Mark this import as searched so that the recursive call - does not search it again. */ - current->searched = 1; - searched_cleanup = make_cleanup (reset_directive_searched, - current); - - /* If there is an import of a single declaration, compare the - imported declaration (after optional renaming by its alias) - with the sought out name. If there is a match pass - current->import_src as NAMESPACE to direct the search - towards the imported namespace. */ - if (current->declaration - && strcmp (name, current->alias - ? current->alias : current->declaration) == 0) - sym = cp_lookup_symbol_in_namespace (current->import_src, - current->declaration, - block, domain); - - /* If this is a DECLARATION_ONLY search or a symbol was found - or this import statement was an import declaration, the - search of this import is complete. */ - if (declaration_only || sym != NULL || current->declaration) - { - current->searched = 0; - discard_cleanups (searched_cleanup); - - if (sym != NULL) - return sym; - - continue; - } - - if (current->alias != NULL - && strcmp (name, current->alias) == 0) - /* If the import is creating an alias and the alias matches - the sought name. Pass current->import_src as the NAME to - direct the search towards the aliased namespace. */ - { - sym = cp_lookup_symbol_in_namespace (scope, - current->import_src, + /* Mark this import as searched so that the recursive call + does not search it again. */ + current->searched = 1; + searched_cleanup = make_cleanup (reset_directive_searched, + current); + + /* If there is an import of a single declaration, compare the + imported declaration (after optional renaming by its alias) + with the sought out name. If there is a match pass + current->import_src as NAMESPACE to direct the search + towards the imported namespace. */ + if (current->declaration + && strcmp (name, current->alias + ? current->alias : current->declaration) == 0) + sym = cp_lookup_symbol_in_namespace (current->import_src, + current->declaration, block, domain); - } - else if (current->alias == NULL) - { - /* If this import statement creates no alias, pass - current->inner as NAMESPACE to direct the search - towards the imported namespace. */ - sym = cp_lookup_symbol_imports (current->import_src, - name, block, - domain, 0, 0); - } - current->searched = 0; - discard_cleanups (searched_cleanup); - - if (sym != NULL) - return sym; + + /* If this is a DECLARATION_ONLY search or a symbol was found + or this import statement was an import declaration, the + search of this import is complete. */ + if (declaration_only || sym != NULL || current->declaration) + { + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; + + continue; + } + + /* Do not follow CURRENT if NAME matches its EXCLUDES. */ + for (excludep = current->excludes; *excludep; excludep++) + if (strcmp (name, *excludep) == 0) + break; + if (*excludep) + { + discard_cleanups (searched_cleanup); + continue; + } + + if (current->alias != NULL + && strcmp (name, current->alias) == 0) + /* If the import is creating an alias and the alias matches + the sought name. Pass current->import_src as the NAME to + direct the search towards the aliased namespace. */ + { + sym = cp_lookup_symbol_in_namespace (scope, + current->import_src, + block, domain); + } + else if (current->alias == NULL) + { + /* If this import statement creates no alias, pass + current->inner as NAMESPACE to direct the search + towards the imported namespace. */ + sym = cp_lookup_symbol_imports (current->import_src, + name, block, + domain, 0, 0); + } + current->searched = 0; + discard_cleanups (searched_cleanup); + + if (sym != NULL) + return sym; } } @@ -633,27 +657,7 @@ lookup_symbol_file (const char *name, sym = lookup_symbol_global (name, block, domain); } - if (sym != NULL) - return sym; - - /* Now call "lookup_possible_namespace_symbol". Symbols in here - claim to be associated to namespaces, but this claim might be - incorrect: the names in question might actually correspond to - classes instead of namespaces. But if they correspond to - classes, then we should have found a match for them above. So if - we find them now, they should be genuine. */ - - /* FIXME: carlton/2003-06-12: This is a hack and should eventually - be deleted: see comments below. */ - - if (domain == VAR_DOMAIN) - { - sym = lookup_possible_namespace_symbol (name); - if (sym != NULL) - return sym; - } - - return NULL; + return sym; } /* Look up a type named NESTED_NAME that is nested inside the C++ @@ -665,6 +669,12 @@ cp_lookup_nested_type (struct type *parent_type, const char *nested_name, const struct block *block) { + /* type_name_no_tag_required provides better error reporting using the + original type. */ + struct type *saved_parent_type = parent_type; + + CHECK_TYPEDEF (parent_type); + switch (TYPE_CODE (parent_type)) { case TYPE_CODE_STRUCT: @@ -678,7 +688,7 @@ cp_lookup_nested_type (struct type *parent_type, just like members of namespaces; in particular, lookup_symbol_namespace works when looking them up. */ - const char *parent_name = TYPE_TAG_NAME (parent_type); + const char *parent_name = type_name_no_tag_or_error (saved_parent_type); struct symbol *sym = cp_lookup_symbol_in_namespace (parent_name, nested_name, block, VAR_DOMAIN); @@ -781,243 +791,13 @@ cp_lookup_transparent_type_loop (const char *name, return basic_lookup_transparent_type (full_name); } -/* Now come functions for dealing with symbols associated to - namespaces. (They're used to store the namespaces themselves, not - objects that live in the namespaces.) These symbols come in two - varieties: if we run into a DW_TAG_namespace DIE, then we know that - we have a namespace, so dwarf2read.c creates a symbol for it just - like normal. But, unfortunately, versions of GCC through at least - 3.3 don't generate those DIE's. Our solution is to try to guess - their existence by looking at demangled names. This might cause us - to misidentify classes as namespaces, however. So we put those - symbols in a special block (one per objfile), and we only search - that block as a last resort. */ - -/* FIXME: carlton/2003-06-12: Once versions of GCC that generate - DW_TAG_namespace have been out for a year or two, we should get rid - of all of this "possible namespace" nonsense. */ - -/* Allocate everything necessary for the possible namespace block - associated to OBJFILE. */ - -static void -initialize_namespace_symtab (struct objfile *objfile) -{ - struct symtab *namespace_symtab; - struct blockvector *bv; - struct block *bl; - - namespace_symtab = allocate_symtab ("<>", objfile); - namespace_symtab->language = language_cplus; - namespace_symtab->free_code = free_nothing; - namespace_symtab->dirname = NULL; - - bv = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct blockvector) - + FIRST_LOCAL_BLOCK * sizeof (struct block *)); - BLOCKVECTOR_NBLOCKS (bv) = FIRST_LOCAL_BLOCK + 1; - BLOCKVECTOR (namespace_symtab) = bv; - - /* Allocate empty GLOBAL_BLOCK and STATIC_BLOCK. */ - - bl = allocate_block (&objfile->objfile_obstack); - BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack, - NULL); - BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = bl; - bl = allocate_block (&objfile->objfile_obstack); - BLOCK_DICT (bl) = dict_create_linear (&objfile->objfile_obstack, - NULL); - BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = bl; - - /* Allocate the possible namespace block; we put it where the first - local block will live, though I don't think there's any need to - pretend that it's actually a local block (e.g. by setting - BLOCK_SUPERBLOCK appropriately). We don't use the global or - static block because we don't want it searched during the normal - search of all global/static blocks in lookup_symbol: we only want - it used as a last resort. */ - - /* NOTE: carlton/2003-09-11: I considered not associating the fake - symbols to a block/symtab at all. But that would cause problems - with lookup_symbol's SYMTAB argument and with block_found, so - having a symtab/block for this purpose seems like the best - solution for now. */ - - bl = allocate_block (&objfile->objfile_obstack); - BLOCK_DICT (bl) = dict_create_hashed_expandable (); - BLOCKVECTOR_BLOCK (bv, FIRST_LOCAL_BLOCK) = bl; - - namespace_symtab->free_func = free_namespace_block; - - objfile->cp_namespace_symtab = namespace_symtab; -} - -/* Locate the possible namespace block associated to OBJFILE, - allocating it if necessary. */ - -static struct block * -get_possible_namespace_block (struct objfile *objfile) -{ - if (objfile->cp_namespace_symtab == NULL) - initialize_namespace_symtab (objfile); - - return BLOCKVECTOR_BLOCK (BLOCKVECTOR (objfile->cp_namespace_symtab), - FIRST_LOCAL_BLOCK); -} - -/* Free the dictionary associated to the possible namespace block. */ - -static void -free_namespace_block (struct symtab *symtab) -{ - struct block *possible_namespace_block; - - possible_namespace_block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), - FIRST_LOCAL_BLOCK); - gdb_assert (possible_namespace_block != NULL); - dict_free (BLOCK_DICT (possible_namespace_block)); -} - -/* Ensure that there are symbols in the possible namespace block - associated to OBJFILE for all initial substrings of NAME that look - like namespaces or classes. NAME should end in a member variable: - it shouldn't consist solely of namespaces. */ - -void -cp_check_possible_namespace_symbols (const char *name, - struct objfile *objfile) -{ - check_possible_namespace_symbols_loop (name, - cp_find_first_component (name), - objfile); -} - -/* This is a helper loop for cp_check_possible_namespace_symbols; it - ensures that there are symbols in the possible namespace block - associated to OBJFILE for all namespaces that are initial - substrings of NAME of length at least LEN. It returns 1 if a - previous loop had already created the shortest such symbol and 0 - otherwise. - - This function assumes that if there is already a symbol associated - to a substring of NAME of a given length, then there are already - symbols associated to all substrings of NAME whose length is less - than that length. So if cp_check_possible_namespace_symbols has - been called once with argument "A::B::C::member", then that will - create symbols "A", "A::B", and "A::B::C". If it is then later - called with argument "A::B::D::member", then the new call will - generate a new symbol for "A::B::D", but once it sees that "A::B" - has already been created, it doesn't bother checking to see if "A" - has also been created. */ - -static int -check_possible_namespace_symbols_loop (const char *name, int len, - struct objfile *objfile) -{ - if (name[len] == ':') - { - int done; - int next_len = len + 2; - - next_len += cp_find_first_component (name + next_len); - done = check_possible_namespace_symbols_loop (name, next_len, - objfile); - - if (!done) - done = check_one_possible_namespace_symbol (name, len, - objfile); - - return done; - } - else - return 0; -} - -/* Check to see if there's already a possible namespace symbol in - OBJFILE whose name is the initial substring of NAME of length LEN. - If not, create one and return 0; otherwise, return 1. */ - -static int -check_one_possible_namespace_symbol (const char *name, int len, - struct objfile *objfile) -{ - struct block *block = get_possible_namespace_block (objfile); - char *name_copy = alloca (len + 1); - struct symbol *sym; - - memcpy (name_copy, name, len); - name_copy[len] = '\0'; - sym = lookup_block_symbol (block, name_copy, VAR_DOMAIN); - - if (sym == NULL) - { - struct type *type; - - type = init_type (TYPE_CODE_NAMESPACE, 0, 0, - name_copy, objfile); - - TYPE_TAG_NAME (type) = TYPE_NAME (type); - - sym = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct symbol)); - memset (sym, 0, sizeof (struct symbol)); - SYMBOL_SET_LANGUAGE (sym, language_cplus); - /* Note that init_type copied the name to the objfile's - obstack. */ - SYMBOL_SET_NAMES (sym, TYPE_NAME (type), len, 0, objfile); - SYMBOL_CLASS (sym) = LOC_TYPEDEF; - SYMBOL_TYPE (sym) = type; - SYMBOL_DOMAIN (sym) = VAR_DOMAIN; - - dict_add_symbol (BLOCK_DICT (block), sym); - - return 0; - } - else - return 1; -} - -/* Look for a symbol named NAME in all the possible namespace blocks. - If one is found, return it. */ - -static struct symbol * -lookup_possible_namespace_symbol (const char *name) -{ - struct objfile *objfile; - - ALL_OBJFILES (objfile) - { - struct symbol *sym; - - sym = lookup_block_symbol (get_possible_namespace_block (objfile), - name, VAR_DOMAIN); - - if (sym != NULL) - return sym; - } - - return NULL; -} - -/* Print out all the possible namespace symbols. */ +/* This used to do something but was removed when it became + obsolete. */ static void maintenance_cplus_namespace (char *args, int from_tty) { - struct objfile *objfile; - - printf_unfiltered (_("Possible namespaces:\n")); - ALL_OBJFILES (objfile) - { - struct dict_iterator iter; - struct symbol *sym; - - ALL_BLOCK_SYMBOLS (get_possible_namespace_block (objfile), - iter, sym) - { - printf_unfiltered ("%s\n", SYMBOL_PRINT_NAME (sym)); - } - } + printf_unfiltered (_("The `maint namespace' command was removed.\n")); } /* Provide a prototype to silence -Wmissing-prototypes. */ @@ -1026,8 +806,11 @@ extern initialize_file_ftype _initialize_cp_namespace; void _initialize_cp_namespace (void) { - add_cmd ("namespace", class_maintenance, - maintenance_cplus_namespace, - _("Print the list of possible C++ namespaces."), - &maint_cplus_cmd_list); + struct cmd_list_element *cmd; + + cmd = add_cmd ("namespace", class_maintenance, + maintenance_cplus_namespace, + _("Deprecated placeholder for removed functionality."), + &maint_cplus_cmd_list); + deprecate_cmd (cmd, NULL); } diff --git a/contrib/gdb-7/gdb/cp-support.c b/contrib/gdb-7/gdb/cp-support.c index a479067189..8cea2c5ce3 100644 --- a/contrib/gdb-7/gdb/cp-support.c +++ b/contrib/gdb-7/gdb/cp-support.c @@ -1,6 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2005, 2007-2012 Free Software Foundation, Inc. Contributed by MontaVista Software. @@ -86,6 +85,47 @@ static const char *operator_tokens[] = /* new[] and delete[] require special whitespace handling */ }; +/* A list of typedefs which should not be substituted by replace_typedefs. */ +static const char * const ignore_typedefs[] = + { + "std::istream", "std::iostream", "std::ostream", "std::string" + }; + +static void + replace_typedefs (struct demangle_parse_info *info, + struct demangle_component *ret_comp); + +/* A convenience function to copy STRING into OBSTACK, returning a pointer + to the newly allocated string and saving the number of bytes saved in LEN. + + It does not copy the terminating '\0' byte! */ + +static char * +copy_string_to_obstack (struct obstack *obstack, const char *string, + long *len) +{ + *len = strlen (string); + return obstack_copy (obstack, string, *len); +} + +/* A cleanup wrapper for cp_demangled_name_parse_free. */ + +static void +do_demangled_name_parse_free_cleanup (void *data) +{ + struct demangle_parse_info *info = (struct demangle_parse_info *) data; + + cp_demangled_name_parse_free (info); +} + +/* Create a cleanup for C++ name parsing. */ + +struct cleanup * +make_cleanup_cp_demangled_name_parse_free (struct demangle_parse_info *info) +{ + return make_cleanup (do_demangled_name_parse_free_cleanup, info); +} + /* Return 1 if STRING is clearly already in canonical form. This function is conservative; things which it does not recognize are assumed to be non-canonical, and the parser will sort them out @@ -117,6 +157,355 @@ cp_already_canonical (const char *string) return 0; } +/* Inspect the given RET_COMP for its type. If it is a typedef, + replace the node with the typedef's tree. + + Returns 1 if any typedef substitutions were made, 0 otherwise. */ + +static int +inspect_type (struct demangle_parse_info *info, + struct demangle_component *ret_comp) +{ + int i; + char *name; + struct symbol *sym; + volatile struct gdb_exception except; + + /* Copy the symbol's name from RET_COMP and look it up + in the symbol table. */ + name = (char *) alloca (ret_comp->u.s_name.len + 1); + memcpy (name, ret_comp->u.s_name.s, ret_comp->u.s_name.len); + name[ret_comp->u.s_name.len] = '\0'; + + /* Ignore any typedefs that should not be substituted. */ + for (i = 0; i < ARRAY_SIZE (ignore_typedefs); ++i) + { + if (strcmp (name, ignore_typedefs[i]) == 0) + return 0; + } + + sym = NULL; + TRY_CATCH (except, RETURN_MASK_ALL) + { + sym = lookup_symbol (name, 0, VAR_DOMAIN, 0); + } + + if (except.reason >= 0 && sym != NULL) + { + struct type *otype = SYMBOL_TYPE (sym); + + /* If the type is a typedef, replace it. */ + if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF) + { + long len; + int is_anon; + struct type *type; + struct demangle_parse_info *i; + struct ui_file *buf; + + /* Get the real type of the typedef. */ + type = check_typedef (otype); + + is_anon = (TYPE_TAG_NAME (type) == NULL + && (TYPE_CODE (type) == TYPE_CODE_ENUM + || TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION)); + if (is_anon) + { + struct type *last = otype; + + /* Find the last typedef for the type. */ + while (TYPE_TARGET_TYPE (last) != NULL + && (TYPE_CODE (TYPE_TARGET_TYPE (last)) + == TYPE_CODE_TYPEDEF)) + last = TYPE_TARGET_TYPE (last); + + /* If there is only one typedef for this anonymous type, + do not substitute it. */ + if (type == otype) + return 0; + else + /* Use the last typedef seen as the type for this + anonymous type. */ + type = last; + } + + buf = mem_fileopen (); + TRY_CATCH (except, RETURN_MASK_ERROR) + { + type_print (type, "", buf, -1); + } + + /* If type_print threw an exception, there is little point + in continuing, so just bow out gracefully. */ + if (except.reason < 0) + { + ui_file_delete (buf); + return 0; + } + + name = ui_file_obsavestring (buf, &info->obstack, &len); + ui_file_delete (buf); + + /* Turn the result into a new tree. Note that this + tree will contain pointers into NAME, so NAME cannot + be free'd until all typedef conversion is done and + the final result is converted into a string. */ + i = cp_demangled_name_to_comp (name, NULL); + if (i != NULL) + { + /* Merge the two trees. */ + cp_merge_demangle_parse_infos (info, ret_comp, i); + + /* Replace any newly introduced typedefs -- but not + if the type is anonymous (that would lead to infinite + looping). */ + if (!is_anon) + replace_typedefs (info, ret_comp); + } + else + { + /* This shouldn't happen unless the type printer has + output something that the name parser cannot grok. + Nonetheless, an ounce of prevention... + + Canonicalize the name again, and store it in the + current node (RET_COMP). */ + char *canon = cp_canonicalize_string_no_typedefs (name); + + if (canon != NULL) + { + /* Copy the canonicalization into the obstack and + free CANON. */ + name = copy_string_to_obstack (&info->obstack, canon, &len); + xfree (canon); + } + + ret_comp->u.s_name.s = name; + ret_comp->u.s_name.len = len; + } + + return 1; + } + } + + return 0; +} + +/* Replace any typedefs appearing in the qualified name + (DEMANGLE_COMPONENT_QUAL_NAME) represented in RET_COMP for the name parse + given in INFO. */ + +static void +replace_typedefs_qualified_name (struct demangle_parse_info *info, + struct demangle_component *ret_comp) +{ + long len; + char *name; + struct ui_file *buf = mem_fileopen (); + struct demangle_component *comp = ret_comp; + + /* Walk each node of the qualified name, reconstructing the name of + this element. With every node, check for any typedef substitutions. + If a substitution has occurred, replace the qualified name node + with a DEMANGLE_COMPONENT_NAME node representing the new, typedef- + substituted name. */ + while (comp->type == DEMANGLE_COMPONENT_QUAL_NAME) + { + if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME) + { + struct demangle_component new; + + ui_file_write (buf, d_left (comp)->u.s_name.s, + d_left (comp)->u.s_name.len); + name = ui_file_obsavestring (buf, &info->obstack, &len); + new.type = DEMANGLE_COMPONENT_NAME; + new.u.s_name.s = name; + new.u.s_name.len = len; + if (inspect_type (info, &new)) + { + char *n, *s; + long slen; + + /* A typedef was substituted in NEW. Convert it to a + string and replace the top DEMANGLE_COMPONENT_QUAL_NAME + node. */ + + ui_file_rewind (buf); + n = cp_comp_to_string (&new, 100); + if (n == NULL) + { + /* If something went astray, abort typedef substitutions. */ + ui_file_delete (buf); + return; + } + + s = copy_string_to_obstack (&info->obstack, n, &slen); + xfree (n); + + d_left (ret_comp)->type = DEMANGLE_COMPONENT_NAME; + d_left (ret_comp)->u.s_name.s = s; + d_left (ret_comp)->u.s_name.len = slen; + d_right (ret_comp) = d_right (comp); + comp = ret_comp; + continue; + } + } + else + { + /* The current node is not a name, so simply replace any + typedefs in it. Then print it to the stream to continue + checking for more typedefs in the tree. */ + replace_typedefs (info, d_left (comp)); + name = cp_comp_to_string (d_left (comp), 100); + if (name == NULL) + { + /* If something went astray, abort typedef substitutions. */ + ui_file_delete (buf); + return; + } + fputs_unfiltered (name, buf); + xfree (name); + } + ui_file_write (buf, "::", 2); + comp = d_right (comp); + } + + /* If the next component is DEMANGLE_COMPONENT_NAME, save the qualified + name assembled above and append the name given by COMP. Then use this + reassembled name to check for a typedef. */ + + if (comp->type == DEMANGLE_COMPONENT_NAME) + { + ui_file_write (buf, comp->u.s_name.s, comp->u.s_name.len); + name = ui_file_obsavestring (buf, &info->obstack, &len); + + /* Replace the top (DEMANGLE_COMPONENT_QUAL_NAME) node + with a DEMANGLE_COMPONENT_NAME node containing the whole + name. */ + ret_comp->type = DEMANGLE_COMPONENT_NAME; + ret_comp->u.s_name.s = name; + ret_comp->u.s_name.len = len; + inspect_type (info, ret_comp); + } + else + replace_typedefs (info, comp); + + ui_file_delete (buf); +} + + +/* A function to check const and volatile qualifiers for argument types. + + "Parameter declarations that differ only in the presence + or absence of `const' and/or `volatile' are equivalent." + C++ Standard N3290, clause 13.1.3 #4. */ + +static void +check_cv_qualifiers (struct demangle_component *ret_comp) +{ + while (d_left (ret_comp) != NULL + && (d_left (ret_comp)->type == DEMANGLE_COMPONENT_CONST + || d_left (ret_comp)->type == DEMANGLE_COMPONENT_VOLATILE)) + { + d_left (ret_comp) = d_left (d_left (ret_comp)); + } +} + +/* Walk the parse tree given by RET_COMP, replacing any typedefs with + their basic types. */ + +static void +replace_typedefs (struct demangle_parse_info *info, + struct demangle_component *ret_comp) +{ + if (ret_comp) + { + switch (ret_comp->type) + { + case DEMANGLE_COMPONENT_ARGLIST: + check_cv_qualifiers (ret_comp); + /* Fall through */ + + case DEMANGLE_COMPONENT_FUNCTION_TYPE: + case DEMANGLE_COMPONENT_TEMPLATE: + case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + case DEMANGLE_COMPONENT_TYPED_NAME: + replace_typedefs (info, d_left (ret_comp)); + replace_typedefs (info, d_right (ret_comp)); + break; + + case DEMANGLE_COMPONENT_NAME: + inspect_type (info, ret_comp); + break; + + case DEMANGLE_COMPONENT_QUAL_NAME: + replace_typedefs_qualified_name (info, ret_comp); + break; + + case DEMANGLE_COMPONENT_LOCAL_NAME: + case DEMANGLE_COMPONENT_CTOR: + case DEMANGLE_COMPONENT_ARRAY_TYPE: + case DEMANGLE_COMPONENT_PTRMEM_TYPE: + replace_typedefs (info, d_right (ret_comp)); + break; + + case DEMANGLE_COMPONENT_CONST: + case DEMANGLE_COMPONENT_RESTRICT: + case DEMANGLE_COMPONENT_VOLATILE: + case DEMANGLE_COMPONENT_VOLATILE_THIS: + case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_RESTRICT_THIS: + case DEMANGLE_COMPONENT_POINTER: + case DEMANGLE_COMPONENT_REFERENCE: + replace_typedefs (info, d_left (ret_comp)); + break; + + default: + break; + } + } +} + +/* Parse STRING and convert it to canonical form, resolving any typedefs. + If parsing fails, or if STRING is already canonical, return NULL. + Otherwise return the canonical form. The return value is allocated via + xmalloc. */ + +char * +cp_canonicalize_string_no_typedefs (const char *string) +{ + char *ret; + unsigned int estimated_len; + struct demangle_parse_info *info; + + ret = NULL; + estimated_len = strlen (string) * 2; + info = cp_demangled_name_to_comp (string, NULL); + if (info != NULL) + { + /* Replace all the typedefs in the tree. */ + replace_typedefs (info, info->tree); + + /* Convert the tree back into a string. */ + ret = cp_comp_to_string (info->tree, estimated_len); + gdb_assert (ret != NULL); + + /* Free the parse information. */ + cp_demangled_name_parse_free (info); + + /* Finally, compare the original string with the computed + name, returning NULL if they are the same. */ + if (strcmp (string, ret) == 0) + { + xfree (ret); + return NULL; + } + } + + return ret; +} + /* Parse STRING and convert it to canonical form. If parsing fails, or if STRING is already canonical, return NULL. Otherwise return the canonical form. The return value is allocated via xmalloc. */ @@ -124,19 +513,20 @@ cp_already_canonical (const char *string) char * cp_canonicalize_string (const char *string) { - struct demangle_component *ret_comp; + struct demangle_parse_info *info; unsigned int estimated_len; char *ret; if (cp_already_canonical (string)) return NULL; - ret_comp = cp_demangled_name_to_comp (string, NULL); - if (ret_comp == NULL) + info = cp_demangled_name_to_comp (string, NULL); + if (info == NULL) return NULL; estimated_len = strlen (string) * 2; - ret = cp_comp_to_string (ret_comp, estimated_len); + ret = cp_comp_to_string (info->tree, estimated_len); + cp_demangled_name_parse_free (info); if (strcmp (string, ret) == 0) { @@ -153,23 +543,27 @@ cp_canonicalize_string (const char *string) freed when finished with the tree, or NULL if none was needed. OPTIONS will be passed to the demangler. */ -static struct demangle_component * +static struct demangle_parse_info * mangled_name_to_comp (const char *mangled_name, int options, void **memory, char **demangled_p) { - struct demangle_component *ret; char *demangled_name; + struct demangle_parse_info *info; /* If it looks like a v3 mangled name, then try to go directly to trees. */ if (mangled_name[0] == '_' && mangled_name[1] == 'Z') { + struct demangle_component *ret; + ret = cplus_demangle_v3_components (mangled_name, options, memory); if (ret) { + info = cp_new_demangle_parse_info (); + info->tree = ret; *demangled_p = NULL; - return ret; + return info; } } @@ -181,16 +575,16 @@ mangled_name_to_comp (const char *mangled_name, int options, /* If we could demangle the name, parse it to build the component tree. */ - ret = cp_demangled_name_to_comp (demangled_name, NULL); + info = cp_demangled_name_to_comp (demangled_name, NULL); - if (ret == NULL) + if (info == NULL) { xfree (demangled_name); return NULL; } *demangled_p = demangled_name; - return ret; + return info; } /* Return the name of the class containing method PHYSNAME. */ @@ -201,14 +595,16 @@ cp_class_name_from_physname (const char *physname) void *storage = NULL; char *demangled_name = NULL, *ret; struct demangle_component *ret_comp, *prev_comp, *cur_comp; + struct demangle_parse_info *info; int done; - ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, - &storage, &demangled_name); - if (ret_comp == NULL) + info = mangled_name_to_comp (physname, DMGL_ANSI, + &storage, &demangled_name); + if (info == NULL) return NULL; done = 0; + ret_comp = info->tree; /* First strip off any qualifiers, if we have a function or method. */ @@ -277,8 +673,8 @@ cp_class_name_from_physname (const char *physname) } xfree (storage); - if (demangled_name) - xfree (demangled_name); + xfree (demangled_name); + cp_demangled_name_parse_free (info); return ret; } @@ -348,13 +744,14 @@ method_name_from_physname (const char *physname) void *storage = NULL; char *demangled_name = NULL, *ret; struct demangle_component *ret_comp; + struct demangle_parse_info *info; - ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, - &storage, &demangled_name); - if (ret_comp == NULL) + info = mangled_name_to_comp (physname, DMGL_ANSI, + &storage, &demangled_name); + if (info == NULL) return NULL; - ret_comp = unqualified_name_from_comp (ret_comp); + ret_comp = unqualified_name_from_comp (info->tree); ret = NULL; if (ret_comp != NULL) @@ -363,8 +760,8 @@ method_name_from_physname (const char *physname) ret = cp_comp_to_string (ret_comp, 10); xfree (storage); - if (demangled_name) - xfree (demangled_name); + xfree (demangled_name); + cp_demangled_name_parse_free (info); return ret; } @@ -379,17 +776,19 @@ cp_func_name (const char *full_name) { char *ret; struct demangle_component *ret_comp; + struct demangle_parse_info *info; - ret_comp = cp_demangled_name_to_comp (full_name, NULL); - if (!ret_comp) + info = cp_demangled_name_to_comp (full_name, NULL); + if (!info) return NULL; - ret_comp = unqualified_name_from_comp (ret_comp); + ret_comp = unqualified_name_from_comp (info->tree); ret = NULL; if (ret_comp != NULL) ret = cp_comp_to_string (ret_comp, 10); + cp_demangled_name_parse_free (info); return ret; } @@ -402,16 +801,18 @@ cp_remove_params (const char *demangled_name) { int done = 0; struct demangle_component *ret_comp; + struct demangle_parse_info *info; char *ret = NULL; if (demangled_name == NULL) return NULL; - ret_comp = cp_demangled_name_to_comp (demangled_name, NULL); - if (ret_comp == NULL) + info = cp_demangled_name_to_comp (demangled_name, NULL); + if (info == NULL) return NULL; /* First strip off any qualifiers, if we have a function or method. */ + ret_comp = info->tree; while (!done) switch (ret_comp->type) { @@ -433,6 +834,7 @@ cp_remove_params (const char *demangled_name) if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME) ret = cp_comp_to_string (d_left (ret_comp), 10); + cp_demangled_name_parse_free (info); return ret; } diff --git a/contrib/gdb-7/gdb/cp-support.h b/contrib/gdb-7/gdb/cp-support.h index bb0ba398f0..8898807bfa 100644 --- a/contrib/gdb-7/gdb/cp-support.h +++ b/contrib/gdb-7/gdb/cp-support.h @@ -1,6 +1,5 @@ /* Helper routines for C++ support in GDB. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2005, 2007-2012 Free Software Foundation, Inc. Contributed by MontaVista Software. Namespace support contributed by David Carlton. @@ -26,11 +25,12 @@ /* We need this for 'domain_enum', alas... */ #include "symtab.h" +#include "vec.h" +#include "gdb_obstack.h" /* Opaque declarations. */ struct symbol; -struct obstack; struct block; struct objfile; struct type; @@ -44,6 +44,20 @@ struct demangle_component; #define CP_ANONYMOUS_NAMESPACE_LEN 21 +/* The result of parsing a name. */ + +struct demangle_parse_info +{ + /* The memory used during the parse. */ + struct demangle_info *info; + + /* The result of the parse. */ + struct demangle_component *tree; + + /* Any temporary memory used during typedef replacement. */ + struct obstack obstack; +}; + /* This struct is designed to store data from using directives. It says that names from namespace IMPORT_SRC should be visible within namespace IMPORT_DEST. These form a linked list; NEXT is the next @@ -60,6 +74,7 @@ struct demangle_component; import_dest = local scope of the import statement even such as "" alias = NULL declaration = NULL + excludes = NULL C++: using A::x; Fortran: use A, only: x @@ -67,14 +82,32 @@ struct demangle_component; import_dest = local scope of the import statement even such as "" alias = NULL declaration = "x" + excludes = NULL The declaration will get imported as import_dest::x. + C++ has no way to import all names except those listed ones. + Fortran: use A, localname => x + import_src = "A" + import_dest = local scope of the import statement even such as "" + alias = "localname" + declaration = "x" + excludes = NULL + + + import_src = "A" + import_dest = local scope of the import statement even such as "" + alias = NULL + declaration = NULL + excludes = ["x"] + All the entries of A get imported except of "x". "x" gets imported as + "localname". "x" is not defined as a local name by this statement. + C++: namespace LOCALNS = A; Fortran has no way to address non-local namespace/module. import_src = "A" import_dest = local scope of the import statement even such as "" alias = "LOCALNS" declaration = NULL + excludes = NULL The namespace will get imported as the import_dest::LOCALNS namespace. @@ -85,6 +118,7 @@ struct demangle_component; import_dest = local scope of the import statement even such as "" alias = "localname" declaration = "x" + excludes = NULL The declaration will get imported as localname or `import_dest`localname. */ @@ -101,6 +135,10 @@ struct using_direct /* Used during import search to temporarily mark this node as searched. */ int searched; + + /* USING_DIRECT has variable allocation size according to the number of + EXCLUDES entries, the last entry is NULL. */ + const char *excludes[1]; }; @@ -108,6 +146,8 @@ struct using_direct extern char *cp_canonicalize_string (const char *string); +extern char *cp_canonicalize_string_no_typedefs (const char *string); + extern char *cp_class_name_from_physname (const char *physname); extern char *method_name_from_physname (const char *physname); @@ -136,10 +176,13 @@ extern int cp_validate_operator (const char *input); extern int cp_is_anonymous (const char *namespace); +DEF_VEC_P (const_char_ptr); + extern void cp_add_using_directive (const char *dest, const char *src, const char *alias, const char *declaration, + VEC (const_char_ptr) *excludes, struct obstack *obstack); extern void cp_initialize_namespace (void); @@ -153,7 +196,8 @@ extern void cp_set_block_scope (const struct symbol *symbol, const char *processing_current_prefix, int processing_has_namespace_info); -extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol); +extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol, + struct objfile *objfile); extern struct symbol *cp_lookup_symbol_nonlocal (const char *name, const struct block *block, @@ -181,19 +225,25 @@ extern struct type *cp_lookup_nested_type (struct type *parent_type, const char *nested_name, const struct block *block); -extern void cp_check_possible_namespace_symbols (const char *name, - struct objfile *objfile); - struct type *cp_lookup_transparent_type (const char *name); /* Functions from cp-name-parser.y. */ -extern struct demangle_component *cp_demangled_name_to_comp - (const char *demangled_name, const char **errmsg); +extern struct demangle_parse_info *cp_demangled_name_to_comp + (const char *demangled_name, const char **errmsg); extern char *cp_comp_to_string (struct demangle_component *result, int estimated_len); +extern void cp_demangled_name_parse_free (struct demangle_parse_info *); +extern struct cleanup *make_cleanup_cp_demangled_name_parse_free + (struct demangle_parse_info *); +extern void cp_merge_demangle_parse_infos (struct demangle_parse_info *, + struct demangle_component *, + struct demangle_parse_info *); + +extern struct demangle_parse_info *cp_new_demangle_parse_info (void); + /* The list of "maint cplus" commands. */ extern struct cmd_list_element *maint_cplus_cmd_list; diff --git a/contrib/gdb-7/gdb/cp-valprint.c b/contrib/gdb-7/gdb/cp-valprint.c index 255e9ce223..7df9adfba4 100644 --- a/contrib/gdb-7/gdb/cp-valprint.c +++ b/contrib/gdb-7/gdb/cp-valprint.c @@ -1,8 +1,7 @@ /* Support for printing C++ values for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-1997, 2000-2003, 2005-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -340,9 +339,19 @@ cp_print_value_fields (struct type *type, struct type *real_type, } else if (field_is_static (&TYPE_FIELD (type, i))) { - struct value *v = value_static_field (type, i); - - if (v == NULL) + volatile struct gdb_exception ex; + struct value *v = NULL; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + v = value_static_field (type, i); + } + + if (ex.reason < 0) + fprintf_filtered (stream, + _(""), + ex.message); + else if (v == NULL) val_print_optimized_out (stream); else cp_print_static_field (TYPE_FIELD_TYPE (type, i), diff --git a/contrib/gdb-7/gdb/d-lang.c b/contrib/gdb-7/gdb/d-lang.c index c0599a5aa7..da2785c90c 100644 --- a/contrib/gdb-7/gdb/d-lang.c +++ b/contrib/gdb-7/gdb/d-lang.c @@ -1,7 +1,6 @@ /* D language support routines for GDB, the GNU debugger. - Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -273,6 +272,8 @@ static const struct language_defn d_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + strcmp_iw_ordered, + NULL, LANG_MAGIC }; diff --git a/contrib/gdb-7/gdb/d-lang.h b/contrib/gdb-7/gdb/d-lang.h index 69883ecae3..67ca14cb47 100644 --- a/contrib/gdb-7/gdb/d-lang.h +++ b/contrib/gdb-7/gdb/d-lang.h @@ -1,7 +1,6 @@ /* D language support definitions for GDB, the GNU debugger. - Copyright (C) 2005, 2006, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005-2006, 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/d-valprint.c b/contrib/gdb-7/gdb/d-valprint.c index e8430995e9..527c08784e 100644 --- a/contrib/gdb-7/gdb/d-valprint.c +++ b/contrib/gdb-7/gdb/d-valprint.c @@ -1,6 +1,6 @@ /* Support for printing D values for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/data-directory/Makefile.in b/contrib/gdb-7/gdb/data-directory/Makefile.in index 11cf2e6736..4296e5ada7 100644 --- a/contrib/gdb-7/gdb/data-directory/Makefile.in +++ b/contrib/gdb-7/gdb/data-directory/Makefile.in @@ -1,4 +1,4 @@ -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # Makefile for building a staged copy of the data-directory. # This file is part of GDB. @@ -55,8 +55,10 @@ PYTHON_FILES = \ gdb/__init__.py \ gdb/types.py \ gdb/printing.py \ + gdb/prompt.py \ gdb/command/__init__.py \ - gdb/command/pretty_printers.py + gdb/command/pretty_printers.py \ + gdb/command/prompt.py FLAGS_TO_PASS = \ "prefix=$(prefix)" \ diff --git a/contrib/gdb-7/gdb/dbxread.c b/contrib/gdb-7/gdb/dbxread.c index 51ddd9da87..adf8315759 100644 --- a/contrib/gdb-7/gdb/dbxread.c +++ b/contrib/gdb-7/gdb/dbxread.c @@ -1,7 +1,5 @@ /* Read dbx symbol tables and convert to internal format, for GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009, 2010. - Free Software Foundation, Inc. + Copyright (C) 1986-2004, 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -105,6 +103,10 @@ struct symloc #define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset) +/* 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; @@ -343,10 +345,10 @@ add_this_object_header_file (int i) static void add_old_header_file (char *name, int instance) { - struct header_file *p = HEADER_FILES (current_objfile); + struct header_file *p = HEADER_FILES (dbxread_objfile); int i; - for (i = 0; i < N_HEADER_FILES (current_objfile); 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); @@ -374,30 +376,30 @@ add_new_header_file (char *name, int instance) /* Make sure there is room for one more header file. */ - i = N_ALLOCATED_HEADER_FILES (current_objfile); + i = N_ALLOCATED_HEADER_FILES (dbxread_objfile); - if (N_HEADER_FILES (current_objfile) == i) + if (N_HEADER_FILES (dbxread_objfile) == i) { if (i == 0) { - N_ALLOCATED_HEADER_FILES (current_objfile) = 10; - HEADER_FILES (current_objfile) = (struct header_file *) + 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 (current_objfile) = i; - HEADER_FILES (current_objfile) = (struct header_file *) - xrealloc ((char *) HEADER_FILES (current_objfile), + 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 (current_objfile)++; - hfile = HEADER_FILES (current_objfile) + i; + i = N_HEADER_FILES (dbxread_objfile)++; + hfile = HEADER_FILES (dbxread_objfile) + i; hfile->name = xstrdup (name); hfile->instance = instance; hfile->length = 10; @@ -412,7 +414,7 @@ add_new_header_file (char *name, int instance) static struct type ** explicit_lookup_type (int real_filenum, int index) { - struct header_file *f = &HEADER_FILES (current_objfile)[real_filenum]; + struct header_file *f = &HEADER_FILES (dbxread_objfile)[real_filenum]; if (index >= f->length) { @@ -2533,7 +2535,7 @@ read_ofile_symtab (struct partial_symtab *pst) objfile->section_offsets. */ section_offsets = pst->section_offsets; - current_objfile = objfile; + dbxread_objfile = objfile; subfile_stack = NULL; stringtab_global = DBX_STRINGTAB (objfile); @@ -2698,7 +2700,7 @@ read_ofile_symtab (struct partial_symtab *pst) end_stabs (); - current_objfile = NULL; + dbxread_objfile = NULL; } @@ -3429,7 +3431,7 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, bfd *sym_bfd = objfile->obfd; char *name = bfd_get_filename (sym_bfd); struct dbx_symfile_info *info; - struct cleanup *back_to = NULL; + struct cleanup *back_to = make_cleanup (null_cleanup, NULL); /* There is already a dbx_symfile_info allocated by our caller. It might even contain some info from the ELF symtab to help us. */ @@ -3473,7 +3475,7 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, symbuf_left = bfd_section_size (objfile->obfd, stabsect); stabs_data = symfile_relocate_debug_section (objfile, stabsect, NULL); if (stabs_data) - back_to = make_cleanup (free_current_contents, (void *) &stabs_data); + make_cleanup (free_current_contents, (void *) &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 @@ -3483,8 +3485,7 @@ elfstab_build_psymtabs (struct objfile *objfile, asection *stabsect, case it does, it will install them itself. */ dbx_symfile_read (objfile, 0); - if (back_to) - do_cleanups (back_to); + do_cleanups (back_to); } /* Scan and build partial symbols for a file with special sections for stabs diff --git a/contrib/gdb-7/gdb/dcache.c b/contrib/gdb-7/gdb/dcache.c index 0f034705a0..652cfab9e0 100644 --- a/contrib/gdb-7/gdb/dcache.c +++ b/contrib/gdb-7/gdb/dcache.c @@ -1,7 +1,7 @@ /* Caching code for GDB, the GNU debugger. - Copyright (C) 1992, 1993, 1995, 1996, 1998, 1999, 2000, 2001, 2003, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1993, 1995-1996, 1998-2001, 2003, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -27,6 +27,10 @@ #include "inferior.h" #include "splay-tree.h" +/* Commands with a prefix of `{set,show} dcache'. */ +static struct cmd_list_element *dcache_set_list = NULL; +static struct cmd_list_element *dcache_show_list = NULL; + /* The data cache could lead to incorrect results because it doesn't know about volatile variables, thus making it impossible to debug functions which use memory mapped I/O devices. Set the nocache @@ -71,20 +75,21 @@ /* The maximum number of lines stored. The total size of the cache is equal to DCACHE_SIZE times LINE_SIZE. */ -#define DCACHE_SIZE 4096 +#define DCACHE_DEFAULT_SIZE 4096 +static unsigned dcache_size = DCACHE_DEFAULT_SIZE; -/* The size of a cache line. Smaller values reduce the time taken to +/* The default size of a cache line. Smaller values reduce the time taken to read a single byte and make the cache more granular, but increase overhead and reduce the effectiveness of the cache as a prefetcher. */ -#define LINE_SIZE_POWER 6 -#define LINE_SIZE (1 << LINE_SIZE_POWER) +#define DCACHE_DEFAULT_LINE_SIZE 64 +static unsigned dcache_line_size = DCACHE_DEFAULT_LINE_SIZE; /* Each cache block holds LINE_SIZE bytes of data starting at a multiple-of-LINE_SIZE address. */ -#define LINE_SIZE_MASK ((LINE_SIZE - 1)) -#define XFORM(x) ((x) & LINE_SIZE_MASK) -#define MASK(x) ((x) & ~LINE_SIZE_MASK) +#define LINE_SIZE_MASK(dcache) ((dcache->line_size - 1)) +#define XFORM(dcache, x) ((x) & LINE_SIZE_MASK (dcache)) +#define MASK(dcache, x) ((x) & ~LINE_SIZE_MASK (dcache)) struct dcache_block { @@ -93,8 +98,8 @@ struct dcache_block struct dcache_block *next; CORE_ADDR addr; /* address of data */ - gdb_byte data[LINE_SIZE]; /* bytes at given address */ int refs; /* # hits */ + gdb_byte data[1]; /* line_size bytes at given address */ }; struct dcache_struct @@ -108,6 +113,7 @@ struct dcache_struct /* The number of in-use lines in the cache. */ int size; + CORE_ADDR line_size; /* current line_size. */ /* The ptid of last inferior to use cache or null_ptid. */ ptid_t ptid; @@ -207,6 +213,29 @@ for_each_block (struct dcache_block **blist, block_func *func, void *param) while (*blist && db != *blist); } +/* BLOCK_FUNC routine for dcache_free. */ + +static void +free_block (struct dcache_block *block, void *param) +{ + xfree (block); +} + +/* Free a data cache. */ + +void +dcache_free (DCACHE *dcache) +{ + if (last_cache == dcache) + last_cache = NULL; + + splay_tree_delete (dcache->tree); + for_each_block (&dcache->oldest, free_block, NULL); + for_each_block (&dcache->freelist, free_block, NULL); + xfree (dcache); +} + + /* BLOCK_FUNC function for dcache_invalidate. This doesn't remove the block from the oldest list on purpose. dcache_invalidate will do it later. */ @@ -230,6 +259,16 @@ dcache_invalidate (DCACHE *dcache) dcache->oldest = NULL; dcache->size = 0; dcache->ptid = null_ptid; + + if (dcache->line_size != dcache_line_size) + { + /* We've been asked to use a different line size. + All of our freelist blocks are now the wrong size, so free them. */ + + for_each_block (&dcache->freelist, free_block, dcache); + dcache->freelist = NULL; + dcache->line_size = dcache_line_size; + } } /* Invalidate the line associated with ADDR. */ @@ -257,7 +296,7 @@ dcache_hit (DCACHE *dcache, CORE_ADDR addr) struct dcache_block *db; splay_tree_node node = splay_tree_lookup (dcache->tree, - (splay_tree_key) MASK (addr)); + (splay_tree_key) MASK (dcache, addr)); if (!node) return NULL; @@ -281,7 +320,7 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db) int reg_len; struct mem_region *region; - len = LINE_SIZE; + len = dcache->line_size; memaddr = db->addr; myaddr = db->data; @@ -325,7 +364,7 @@ dcache_alloc (DCACHE *dcache, CORE_ADDR addr) { struct dcache_block *db; - if (dcache->size >= DCACHE_SIZE) + if (dcache->size >= dcache_size) { /* Evict the least recently allocated line. */ db = dcache->oldest; @@ -339,12 +378,13 @@ dcache_alloc (DCACHE *dcache, CORE_ADDR addr) if (db) remove_block (&dcache->freelist, db); else - db = xmalloc (sizeof (struct dcache_block)); + db = xmalloc (offsetof (struct dcache_block, data) + + dcache->line_size); dcache->size++; } - db->addr = MASK (addr); + db->addr = MASK (dcache, addr); db->refs = 0; /* Put DB at the end of the list, it's the newest. */ @@ -374,7 +414,7 @@ dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr) return 0; } - *ptr = db->data[XFORM (addr)]; + *ptr = db->data[XFORM (dcache, addr)]; return 1; } @@ -395,7 +435,7 @@ dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr) struct dcache_block *db = dcache_hit (dcache, addr); if (db) - db->data[XFORM (addr)] = *ptr; + db->data[XFORM (dcache, addr)] = *ptr; return 1; } @@ -427,33 +467,13 @@ dcache_init (void) dcache->oldest = NULL; dcache->freelist = NULL; dcache->size = 0; + dcache->line_size = dcache_line_size; dcache->ptid = null_ptid; last_cache = dcache; return dcache; } -/* BLOCK_FUNC routine for dcache_free. */ - -static void -free_block (struct dcache_block *block, void *param) -{ - free (block); -} - -/* Free a data cache. */ - -void -dcache_free (DCACHE *dcache) -{ - if (last_cache == dcache) - last_cache = NULL; - - splay_tree_delete (dcache->tree); - for_each_block (&dcache->oldest, free_block, NULL); - for_each_block (&dcache->freelist, free_block, NULL); - xfree (dcache); -} /* Read or write LEN bytes from inferior memory at MEMADDR, transferring to or from debugger address MYADDR. Write to inferior if SHOULD_WRITE is @@ -571,12 +591,12 @@ dcache_print_line (int index) printf_filtered (_("Line %d: address %s [%d hits]\n"), index, paddress (target_gdbarch, db->addr), db->refs); - for (j = 0; j < LINE_SIZE; j++) + for (j = 0; j < last_cache->line_size; j++) { printf_filtered ("%02x ", db->data[j]); /* Print a newline every 16 bytes (48 characters). */ - if ((j % 16 == 15) && (j != LINE_SIZE - 1)) + if ((j % 16 == 15) && (j != last_cache->line_size - 1)) printf_filtered ("\n"); } printf_filtered ("\n"); @@ -603,8 +623,10 @@ dcache_info (char *exp, int tty) return; } - printf_filtered (_("Dcache line width %d, maximum size %d\n"), - LINE_SIZE, DCACHE_SIZE); + printf_filtered (_("Dcache %u lines of %u bytes each.\n"), + dcache_size, + last_cache ? (unsigned) last_cache->line_size + : dcache_line_size); if (!last_cache || ptid_equal (last_cache->ptid, null_ptid)) { @@ -635,6 +657,48 @@ dcache_info (char *exp, int tty) printf_filtered (_("Cache state: %d active lines, %d hits\n"), i, refcount); } +static void +set_dcache_size (char *args, int from_tty, + struct cmd_list_element *c) +{ + if (dcache_size == 0) + { + dcache_size = DCACHE_DEFAULT_SIZE; + error (_("Dcache size must be greater than 0.")); + } + if (last_cache) + dcache_invalidate (last_cache); +} + +static void +set_dcache_line_size (char *args, int from_tty, + struct cmd_list_element *c) +{ + if (dcache_line_size < 2 + || (dcache_line_size & (dcache_line_size - 1)) != 0) + { + unsigned d = dcache_line_size; + dcache_line_size = DCACHE_DEFAULT_LINE_SIZE; + error (_("Invalid dcache line size: %u (must be power of 2)."), d); + } + if (last_cache) + dcache_invalidate (last_cache); +} + +static void +set_dcache_command (char *arg, int from_tty) +{ + printf_unfiltered ( + "\"set dcache\" must be followed by the name of a subcommand.\n"); + help_list (dcache_set_list, "set dcache ", -1, gdb_stdout); +} + +static void +show_dcache_command (char *args, int from_tty) +{ + cmd_show_list (dcache_show_list, from_tty, ""); +} + void _initialize_dcache (void) { @@ -656,4 +720,28 @@ Print information on the dcache performance.\n\ With no arguments, this command prints the cache configuration and a\n\ summary of each line in the cache. Use \"info dcache to dump\"\n\ the contents of a given line.")); + + add_prefix_cmd ("dcache", class_obscure, set_dcache_command, _("\ +Use this command to set number of lines in dcache and line-size."), + &dcache_set_list, "set dcache ", /*allow_unknown*/0, &setlist); + add_prefix_cmd ("dcache", class_obscure, show_dcache_command, _("\ +Show dcachesettings."), + &dcache_show_list, "show dcache ", /*allow_unknown*/0, &showlist); + + add_setshow_uinteger_cmd ("line-size", class_obscure, + &dcache_line_size, _("\ +Set dcache line size in bytes (must be power of 2)."), _("\ +Show dcache line size."), + NULL, + set_dcache_line_size, + NULL, + &dcache_set_list, &dcache_show_list); + add_setshow_uinteger_cmd ("size", class_obscure, + &dcache_size, _("\ +Set number of dcache lines."), _("\ +Show number of dcache lines."), + NULL, + set_dcache_size, + NULL, + &dcache_set_list, &dcache_show_list); } diff --git a/contrib/gdb-7/gdb/dcache.h b/contrib/gdb-7/gdb/dcache.h index fb581066f2..7e07e20986 100644 --- a/contrib/gdb-7/gdb/dcache.h +++ b/contrib/gdb-7/gdb/dcache.h @@ -1,8 +1,8 @@ /* Declarations for caching. Typically used by remote back ends for caching remote memory. - Copyright (C) 1992, 1993, 1995, 1999, 2000, 2001, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1993, 1995, 1999-2001, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/defs.h b/contrib/gdb-7/gdb/defs.h index 9531c5adad..e4c24830db 100644 --- a/contrib/gdb-7/gdb/defs.h +++ b/contrib/gdb-7/gdb/defs.h @@ -1,9 +1,8 @@ /* *INDENT-OFF* */ /* ATTRIBUTE_PRINTF confuses indent, avoid running it for now. */ /* Basic, host-specific, and target-specific definitions for GDB. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-2005, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. @@ -23,6 +22,10 @@ #ifndef DEFS_H #define DEFS_H +#ifdef GDBSERVER +# error gdbserver should not include gdb/defs.h +#endif + #include "config.h" /* Generated by configure. */ #include @@ -89,6 +92,7 @@ #include /* For va_list. */ #include "libiberty.h" +#include "hashtab.h" /* Rather than duplicate all the logic in BFD for figuring out what types to use (which can be pretty complicated), symply define them @@ -142,8 +146,7 @@ typedef bfd_vma CORE_ADDR; #define max(a, b) ((a) > (b) ? (a) : (b)) #endif -/* Check if a character is one of the commonly used C++ marker characters. */ -extern int is_cplus_marker (int); +#include "ptid.h" /* Enable xdb commands if set. */ extern int xdb_commands; @@ -258,7 +261,7 @@ enum return_value_convention point in the chain. Use discard_cleanups to remove cleanups from the chain back to a given point, not doing them. - If the argument is pointer to allocated memory, then you need to + If the argument is pointer to allocated memory, then you need to additionally set the 'free_arg' member to a function that will free that memory. This function will be called both when the cleanup is executed and when it's discarded. */ @@ -271,18 +274,10 @@ struct cleanup void *arg; }; -/* Be conservative and use enum bitfields only with GCC. - This is copied from gcc 3.3.1, system.h. */ - -#if defined(__GNUC__) && (__GNUC__ >= 2) -#define ENUM_BITFIELD(TYPE) enum TYPE -#else -#define ENUM_BITFIELD(TYPE) unsigned int -#endif - -/* vec.h-style vectors of strings want a typedef for char * . */ +/* vec.h-style vectors of strings want a typedef for char * or const char *. */ typedef char * char_ptr; +typedef const char * const_char_ptr; /* Needed for various prototypes */ @@ -290,6 +285,13 @@ struct symtab; struct breakpoint; struct frame_info; struct gdbarch; +struct value; + +/* From main.c. */ + +/* This really belong in utils.c (path-utils.c?), but it references some + globals that are currently only available to main.c. */ +extern char *relocate_gdb_directory (const char *initial, int flag); /* From utils.c */ @@ -334,6 +336,9 @@ extern struct cleanup *make_cleanup_dtor (make_cleanup_ftype *, void *, extern struct cleanup *make_cleanup_freeargv (char **); +struct dyn_string; +extern struct cleanup *make_cleanup_dyn_string_delete (struct dyn_string *); + struct ui_file; extern struct cleanup *make_cleanup_ui_file_delete (struct ui_file *); @@ -363,11 +368,19 @@ extern struct cleanup *make_cleanup_unpush_target (struct target_ops *ops); extern struct cleanup * make_cleanup_restore_ui_file (struct ui_file **variable); +extern struct cleanup *make_cleanup_value_free_to_mark (struct value *); +extern struct cleanup *make_cleanup_value_free (struct value *); + +struct so_list; +extern struct cleanup *make_cleanup_free_so (struct so_list *so); + extern struct cleanup *make_final_cleanup (make_cleanup_ftype *, void *); extern struct cleanup *make_my_cleanup (struct cleanup **, make_cleanup_ftype *, void *); +extern struct cleanup *make_cleanup_htab_delete (htab_t htab); + extern struct cleanup *make_my_cleanup2 (struct cleanup **, make_cleanup_ftype *, void *, void (*free_arg) (void *)); @@ -411,6 +424,7 @@ char *ldirname (const char *filename); char **gdb_buildargv (const char *); int compare_positive_ints (const void *ap, const void *bp); +int compare_strings (const void *ap, const void *bp); /* A wrapper for bfd_errmsg to produce a more helpful error message in the case of bfd_error_file_ambiguously recognized. @@ -421,9 +435,9 @@ extern const char *gdb_bfd_errmsg (bfd_error_type error_tag, char **matching); extern int parse_pid_to_attach (char *args); -/* From demangle.c */ +extern struct cleanup *make_bpstat_clear_actions_cleanup (void); -extern void set_demangling_style (char *); +extern int producer_is_gcc_ge_4 (const char *producer); /* Annotation stuff. */ @@ -538,6 +552,11 @@ extern const char *paddress (struct gdbarch *gdbarch, CORE_ADDR addr); extern const char *print_core_address (struct gdbarch *gdbarch, CORE_ADDR address); +/* Callback hash_f and eq_f for htab_create_alloc or htab_create_alloc_ex. */ + +extern hashval_t core_addr_hash (const void *ap); +extern int core_addr_eq (const void *ap, const void *bp); + /* %d for LONGEST */ extern char *plongest (LONGEST l); /* %u for ULONGEST */ @@ -729,44 +748,6 @@ extern struct command_line *read_command_lines_1 (char * (*) (void), int, extern void free_command_lines (struct command_line **); -/* To continue the execution commands when running gdb asynchronously. - A continuation structure contains a pointer to a function to be called - to finish the command, once the target has stopped. Such mechanism is - used by the finish and until commands, and in the remote protocol - when opening an extended-remote connection. */ - -struct continuation; -struct thread_info; -struct inferior; - -/* From utils.c */ - -/* Thread specific continuations. */ - -extern void add_continuation (struct thread_info *, - void (*)(void *), void *, - void (*)(void *)); -extern void do_all_continuations (void); -extern void do_all_continuations_thread (struct thread_info *); -extern void discard_all_continuations (void); -extern void discard_all_continuations_thread (struct thread_info *); - -extern void add_intermediate_continuation (struct thread_info *, - void (*)(void *), void *, - void (*)(void *)); -extern void do_all_intermediate_continuations (void); -extern void do_all_intermediate_continuations_thread (struct thread_info *); -extern void discard_all_intermediate_continuations (void); -extern void discard_all_intermediate_continuations_thread (struct thread_info *); - -/* Inferior specific (any thread) continuations. */ - -extern void add_inferior_continuation (void (*) (void *), - void *, - void (*) (void *)); -extern void do_all_inferior_continuations (void); -extern void discard_all_inferior_continuations (struct inferior *inf); - /* String containing the current directory (what getwd would return). */ extern char *current_directory; @@ -789,41 +770,6 @@ enum val_prettyprint Val_pretty_default }; -/* The ptid struct is a collection of the various "ids" necessary - for identifying the inferior. This consists of the process id - (pid), thread id (tid), and other fields necessary for uniquely - identifying the inferior process/thread being debugged. When - manipulating ptids, the constructors, accessors, and predicate - declared in inferior.h should be used. These are as follows: - - ptid_build - Make a new ptid from a pid, lwp, and tid. - pid_to_ptid - Make a new ptid from just a pid. - ptid_get_pid - Fetch the pid component of a ptid. - ptid_get_lwp - Fetch the lwp component of a ptid. - ptid_get_tid - Fetch the tid component of a ptid. - ptid_equal - Test to see if two ptids are equal. - ptid_is_pid - Test to see if this ptid represents a process id. - - Please do NOT access the struct ptid members directly (except, of - course, in the implementation of the above ptid manipulation - functions). */ - -struct ptid - { - /* Process id */ - int pid; - - /* Lightweight process id */ - long lwp; - - /* Thread id */ - long tid; - }; - -typedef struct ptid ptid_t; - - - /* Optional native machine support. Non-native (and possibly pure multi-arch) targets do not need a "nm.h" file. This will be a symlink to one of the nm-*.h files, built by the `configure' @@ -887,13 +833,6 @@ extern int longest_to_int (LONGEST); extern char *savestring (const char *, size_t); -/* xmalloc(), xrealloc() and xcalloc() have already been declared in - "libiberty.h". */ -extern void xfree (void *); - -/* Like xmalloc, but zero the memory. */ -extern void *xzalloc (size_t); - /* Utility macros to allocate typed memory. Avoids errors like: struct foo *foo = xmalloc (sizeof struct bar); and memset (foo, sizeof (struct foo), 0). */ @@ -901,22 +840,7 @@ extern void *xzalloc (size_t); #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) #define XCALLOC(NMEMB, TYPE) ((TYPE*) xcalloc ((NMEMB), sizeof (TYPE))) -/* Like asprintf/vasprintf but get an internal_error if the call - fails. */ -extern void xasprintf (char **ret, const char *format, ...) - ATTRIBUTE_PRINTF (2, 3); -extern void xvasprintf (char **ret, const char *format, va_list ap) - ATTRIBUTE_PRINTF (2, 0); - -/* Like asprintf and vasprintf, but return the string, throw an error - if no memory. */ -extern char *xstrprintf (const char *format, ...) ATTRIBUTE_PRINTF (1, 2); -extern char *xstrvprintf (const char *format, va_list ap) - ATTRIBUTE_PRINTF (1, 0); - -/* Like snprintf, but throw an error if the output buffer is too small. */ -extern int xsnprintf (char *str, size_t size, const char *format, ...) - ATTRIBUTE_PRINTF (3, 4); +#include "common-utils.h" extern int parse_escape (struct gdbarch *, char **); @@ -950,9 +874,6 @@ extern void internal_verror (const char *file, int line, const char *, va_list ap) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0); -extern void internal_error (const char *file, int line, const char *, ...) - ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 4); - extern void internal_vwarning (const char *file, int line, const char *, va_list ap) ATTRIBUTE_PRINTF (3, 0); @@ -960,8 +881,6 @@ extern void internal_vwarning (const char *file, int line, extern void internal_warning (const char *file, int line, const char *, ...) ATTRIBUTE_PRINTF (3, 4); -extern void nomem (long) ATTRIBUTE_NORETURN; - extern void warning (const char *, ...) ATTRIBUTE_PRINTF (1, 2); extern void vwarning (const char *, va_list args) ATTRIBUTE_PRINTF (1, 0); @@ -1256,4 +1175,13 @@ void dummy_obstack_deallocate (void *object, void *data); extern void initialize_progspace (void); extern void initialize_inferiors (void); +/* Special block numbers */ + +enum block_enum +{ + GLOBAL_BLOCK = 0, + STATIC_BLOCK = 1, + FIRST_LOCAL_BLOCK = 2 +}; + #endif /* #ifndef DEFS_H */ diff --git a/contrib/gdb-7/gdb/demangle.c b/contrib/gdb-7/gdb/demangle.c index 5600692aab..fa6f4a635d 100644 --- a/contrib/gdb-7/gdb/demangle.c +++ b/contrib/gdb-7/gdb/demangle.c @@ -1,7 +1,7 @@ /* Basic C++ demangling support for GDB. - Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, - 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1991-1996, 1998-2001, 2003, 2007-2012 Free Software + Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -28,6 +28,7 @@ #include "command.h" #include "gdbcmd.h" #include "demangle.h" +#include "gdb-demangle.h" #include "gdb_string.h" /* Select the default C++ demangling style to use. The default is "auto", @@ -42,7 +43,31 @@ #define DEFAULT_DEMANGLING_STYLE AUTO_DEMANGLING_STYLE_STRING #endif -extern void _initialize_demangler (void); +/* See documentation in gdb-demangle.h. */ +int demangle = 1; + +static void +show_demangle (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("Demangling of encoded C++/ObjC names " + "when displaying symbols is %s.\n"), + value); +} + +/* See documentation in gdb-demangle.h. */ +int asm_demangle = 0; + +static void +show_asm_demangle (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("Demangling of C++/ObjC names in " + "disassembly listings is %s.\n"), + value); +} /* String name for the current demangling style. Set by the "set demangle-style" command, printed as part of the output by the @@ -62,9 +87,6 @@ show_demangling_style_names(struct ui_file *file, int from_tty, value); } - -static void set_demangling_command (char *, int, struct cmd_list_element *); - /* Set current demangling style. Called by the "set demangle-style" command after it has updated the current_demangling_style_string to match what the user has entered. @@ -142,7 +164,7 @@ set_demangling_command (char *ignore, int from_tty, struct cmd_list_element *c) } } -/* Fake a "set demangle-style" command. */ +/* See documentation in gdb-demangle.h. */ void set_demangling_style (char *style) @@ -168,12 +190,16 @@ set_demangling_style (char *style) static char cplus_markers[] = {'$', '.', '\0'}; +/* See documentation in gdb-demangle.h. */ + int is_cplus_marker (int c) { return c && strchr (cplus_markers, c) != NULL; } +extern initialize_file_ftype _initialize_demangler; /* -Wmissing-prototypes */ + void _initialize_demangler (void) { @@ -191,6 +217,20 @@ _initialize_demangler (void) demangling_style_names[i] = xstrdup (libiberty_demanglers[i].demangling_style_name); + add_setshow_boolean_cmd ("demangle", class_support, &demangle, _("\ +Set demangling of encoded C++/ObjC names when displaying symbols."), _("\ +Show demangling of encoded C++/ObjC names when displaying symbols."), NULL, + NULL, + show_demangle, + &setprintlist, &showprintlist); + + add_setshow_boolean_cmd ("asm-demangle", class_support, &asm_demangle, _("\ +Set demangling of C++/ObjC names in disassembly listings."), _("\ +Show demangling of C++/ObjC names in disassembly listings."), NULL, + NULL, + show_asm_demangle, + &setprintlist, &showprintlist); + /* FIXME: cagney/2005-02-20: The code implementing this variable are malloc-ing and free-ing current_demangling_style_string when it should instead just point to an element of diff --git a/contrib/gdb-7/gdb/dfp.c b/contrib/gdb-7/gdb/dfp.c index 0ca1ed3c4a..ae6204b562 100644 --- a/contrib/gdb-7/gdb/dfp.c +++ b/contrib/gdb-7/gdb/dfp.c @@ -1,6 +1,6 @@ /* Decimal floating point support for GDB. - Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/dfp.h b/contrib/gdb-7/gdb/dfp.h index 9c6ce20553..2789b31da6 100644 --- a/contrib/gdb-7/gdb/dfp.h +++ b/contrib/gdb-7/gdb/dfp.h @@ -1,6 +1,6 @@ /* Decimal floating point support for GDB. - Copyright 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/dictionary.c b/contrib/gdb-7/gdb/dictionary.c index 29816921d9..00c72e8a8a 100644 --- a/contrib/gdb-7/gdb/dictionary.c +++ b/contrib/gdb-7/gdb/dictionary.c @@ -1,7 +1,6 @@ /* Routines for name->symbol lookups in GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. @@ -826,7 +825,7 @@ dict_hash (const char *string0) } /* FALL THROUGH */ default: - hash = hash * 67 + *string - 113; + hash = SYMBOL_HASH_NEXT (hash, *string); string += 1; break; } diff --git a/contrib/gdb-7/gdb/dictionary.h b/contrib/gdb-7/gdb/dictionary.h index 944a5a11e2..1d58fabfe9 100644 --- a/contrib/gdb-7/gdb/dictionary.h +++ b/contrib/gdb-7/gdb/dictionary.h @@ -1,7 +1,6 @@ /* Routines for name->symbol lookups in GDB. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. Contributed by David Carlton and by Kealia, Inc. diff --git a/contrib/gdb-7/gdb/disasm.c b/contrib/gdb-7/gdb/disasm.c index ee19f70c03..89bd82918c 100644 --- a/contrib/gdb-7/gdb/disasm.c +++ b/contrib/gdb-7/gdb/disasm.c @@ -1,7 +1,6 @@ /* Disassemble support for GDB. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 2000-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/disasm.h b/contrib/gdb-7/gdb/disasm.h index 32ffd0b71f..646ee8eeb3 100644 --- a/contrib/gdb-7/gdb/disasm.h +++ b/contrib/gdb-7/gdb/disasm.h @@ -1,6 +1,5 @@ /* Disassemble support for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/doc/GDBvn.texi b/contrib/gdb-7/gdb/doc/GDBvn.texi deleted file mode 100644 index e67af2ec43..0000000000 --- a/contrib/gdb-7/gdb/doc/GDBvn.texi +++ /dev/null @@ -1,4 +0,0 @@ -@set GDBVN 7.2 -@set VERSION_PACKAGE (GDB) -@set BUGURL @uref{http://www.gnu.org/software/gdb/bugs/} -@set BUGURL_DEFAULT diff --git a/contrib/gdb-7/gdb/doc/agentexpr.texi b/contrib/gdb-7/gdb/doc/agentexpr.texi index f2d51b7405..d0f6f15cc3 100644 --- a/contrib/gdb-7/gdb/doc/agentexpr.texi +++ b/contrib/gdb-7/gdb/doc/agentexpr.texi @@ -7,8 +7,7 @@ @c This file is part of the GDB manual. @c -@c Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010, 2011 -@c Free Software Foundation, Inc. +@c Copyright (C) 2003-2006, 2009-2012 Free Software Foundation, Inc. @c @c See the file gdb.texinfo for copying conditions. @@ -489,6 +488,11 @@ named @code{trace_quick16}, for consistency. Record the value of trace state variable number @var{n} in the trace buffer. The handling of @var{n} is as described for @code{getv}. +@item @code{tracenz} (0x2f) @var{addr} @var{size} @result{} +Record the bytes at @var{addr} in a trace buffer, for later retrieval +by GDB. Stop at either the first zero byte, or when @var{size} bytes +have been recorded, whichever occurs first. + @item @code{end} (0x27): @result{} Stop executing bytecode; the result should be the top element of the stack. If the purpose of the expression was to compute an lvalue or a diff --git a/contrib/gdb-7/gdb/doc/all-cfg.texi b/contrib/gdb-7/gdb/doc/all-cfg.texi index d469fa47a9..4f5a65e97c 100644 --- a/contrib/gdb-7/gdb/doc/all-cfg.texi +++ b/contrib/gdb-7/gdb/doc/all-cfg.texi @@ -1,6 +1,7 @@ @c GDB MANUAL configuration file. @c -@c Copyright (C) 1993, 1995, 1999, 2002, 2011 Free Software Foundation, Inc. +@c Copyright (C) 1993, 1995, 1999, 2002, 2011-2012 Free Software +@c Foundation, Inc. @c @c NOTE: While the GDB manual is configurable (by changing these @c switches), its configuration is ***NOT*** automatically tied in to diff --git a/contrib/gdb-7/gdb/doc/annotate.texinfo b/contrib/gdb-7/gdb/doc/annotate.texinfo index 01928b7ec0..20f6eb6abb 100644 --- a/contrib/gdb-7/gdb/doc/annotate.texinfo +++ b/contrib/gdb-7/gdb/doc/annotate.texinfo @@ -27,8 +27,8 @@ @c cost. Having a smaller cheaper manual helps the GNU Press with its sales. @copying -Copyright @copyright{} 1994, 1995, 2000, 2001, 2003, 2004, 2005, 2007, -2008, 2009, 2010, 2011 Free Software Foundation, Inc. +Copyright @copyright{} 1994-1995, 2000-2001, 2003-2005, 2007-2012 Free +Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or diff --git a/contrib/gdb-7/gdb/doc/gdb.texinfo b/contrib/gdb-7/gdb/doc/gdb.texinfo index b6bec6a13a..95ae000485 100644 --- a/contrib/gdb-7/gdb/doc/gdb.texinfo +++ b/contrib/gdb-7/gdb/doc/gdb.texinfo @@ -1,7 +1,5 @@ \input texinfo @c -*-texinfo-*- -@c Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, -@c 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, -@c 2010, 2011 Free Software Foundation, Inc. +@c Copyright (C) 1988-1996, 1998-2012 Free Software Foundation, Inc. @c @c %**start of header @c makeinfo ignores cmds prev to setfilename, so its arg cannot make use @@ -30,7 +28,7 @@ @c !!set GDB manual's edition---not the same as GDB version! @c This is updated by GNU Press. -@set EDITION Ninth +@set EDITION Tenth @c !!set GDB edit command default editor @set EDITOR /bin/ex @@ -97,12 +95,9 @@ Version @value{GDBVN}. Published by the Free Software Foundation @* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA@* -ISBN 1-882114-77-9 @* +ISBN 978-0-9831592-3-0 @* @insertcopying -@page -@value{GDBN} version 7.3 is dedicated to the memory of long-standing -contributor Michael Snyder. @end titlepage @page @@ -181,6 +176,7 @@ software in general. We will miss him. * Operating System Information:: Getting additional information from the operating system * Trace File Format:: GDB trace file format +* Index Section Format:: .gdb_index section format * Copying:: GNU General Public License says how you can copy and share GDB * GNU Free Documentation License:: The license for this documentation @@ -1349,9 +1345,12 @@ just use the @code{shell} command. @table @code @kindex shell +@kindex ! @cindex shell escape -@item shell @var{command string} -Invoke a standard shell to execute @var{command string}. +@item shell @var{command-string} +@itemx !@var{command-string} +Invoke a standard shell to execute @var{command-string}. +Note that no space is needed between @code{!} and @var{command-string}. If it exists, the environment variable @code{SHELL} determines which shell to run. Otherwise @value{GDBN} uses the default shell (@file{/bin/sh} on Unix systems, @file{COMMAND.COM} on MS-DOS, etc.). @@ -1594,8 +1593,10 @@ left-hand-side: @smallexample (@value{GDBP}) p gdb_stdout.@kbd{M-?} -magic to_delete to_fputs to_put to_rewind -to_data to_flush to_isatty to_read to_write +magic to_fputs to_rewind +to_data to_isatty to_write +to_delete to_put to_write_async_safe +to_flush to_read @end smallexample @noindent @@ -1609,6 +1610,7 @@ struct ui_file int *magic; ui_file_flush_ftype *to_flush; ui_file_write_ftype *to_write; + ui_file_write_async_safe_ftype *to_write_async_safe; ui_file_fputs_ftype *to_fputs; ui_file_read_ftype *to_read; ui_file_delete_ftype *to_delete; @@ -1872,14 +1874,18 @@ format; if your @sc{gnu} C compiler has this option, do not use it. @value{GDBN} knows about preprocessor macros and can show you their expansion (@pxref{Macros}). Most compilers do not include information about preprocessor macros in the debugging information if you specify -the @option{-g} flag alone, because this information is rather large. -Version 3.1 and later of @value{NGCC}, the @sc{gnu} C compiler, -provides macro information if you specify the options -@option{-gdwarf-2} and @option{-g3}; the former option requests -debugging information in the Dwarf 2 format, and the latter requests -``extra information''. In the future, we hope to find more compact -ways to represent macro information, so that it can be included with -@option{-g} alone. +the @option{-g} flag alone. Version 3.1 and later of @value{NGCC}, +the @sc{gnu} C compiler, provides macro information if you are using +the DWARF debugging format, and specify the option @option{-g3}. + +@xref{Debugging Options,,Options for Debugging Your Program or GCC, +gcc.info, Using the @sc{gnu} Compiler Collection (GCC)}, for more +information on @value{NGCC} options affecting debug information. + +You will have the best debugging experience if you use the latest +version of the DWARF debugging format that your compiler supports. +DWARF is currently the most expressive and best supported debugging +format in @value{GDBN}. @need 2000 @node Starting @@ -2043,8 +2049,8 @@ randomization of the virtual address space of the started program. This option is useful for multiple debugging sessions to make the execution better reproducible and memory addresses reusable across debugging sessions. -This feature is implemented only on @sc{gnu}/Linux. You can get the same -behavior using +This feature is implemented only on certain targets, including @sc{gnu}/Linux. +On @sc{gnu}/Linux you can get the same behavior using @smallexample (@value{GDBP}) set exec-wrapper setarch `uname -m` -R @@ -2058,8 +2064,8 @@ disappears when you run the program under @value{GDBN}, that might be because as @sc{gnu}/Linux, which do that for stand-alone programs. Use @kbd{set disable-randomization off} to try to reproduce such elusive bugs. -The virtual address space randomization is implemented only on @sc{gnu}/Linux. -It protects the programs against some kinds of security attacks. In these +On targets where it is available, virtual address space randomization +protects the programs against certain kinds of security attacks. In these cases the attacker needs to know the exact location of a concrete executable code. Randomizing its location makes it impossible to inject jumps misusing a code at its expected addresses. @@ -2857,14 +2863,22 @@ watchpoints in programs with multiple threads. If this variable is set, @var{path} is a colon-separated list of directories @value{GDBN} will use to search for @code{libthread_db}. If you omit @var{path}, @samp{libthread-db-search-path} will be reset to -an empty list. +its default value (@code{$sdir:$pdir} on @sc{gnu}/Linux and Solaris systems). +Internally, the default value comes from the @code{LIBTHREAD_DB_SEARCH_PATH} +macro. On @sc{gnu}/Linux and Solaris systems, @value{GDBN} uses a ``helper'' @code{libthread_db} library to obtain information about threads in the inferior process. @value{GDBN} will use @samp{libthread-db-search-path} -to find @code{libthread_db}. If that fails, @value{GDBN} will continue -with default system shared library directories, and finally the directory -from which @code{libpthread} was loaded in the inferior process. +to find @code{libthread_db}. + +A special entry @samp{$sdir} for @samp{libthread-db-search-path} +refers to the default system directories that are +normally searched for loading shared libraries. + +A special entry @samp{$pdir} for @samp{libthread-db-search-path} +refers to the directory from which @code{libpthread} +was loaded in the inferior process. For any @code{libthread_db} library @value{GDBN} finds in above directories, @value{GDBN} attempts to initialize it with the current inferior process. @@ -3207,6 +3221,8 @@ running or not, what process it is, and why it stopped. @menu * Breakpoints:: Breakpoints, watchpoints, and catchpoints * Continuing and Stepping:: Resuming execution +* Skipping Over Functions and Files:: + Skipping over functions and files * Signals:: Signals * Thread Stops:: Stopping and starting multi-thread programs @end menu @@ -3503,6 +3519,9 @@ It is possible that a breakpoint corresponds to several locations in your program. Examples of this situation are: @itemize @bullet +@item +Multiple functions in the program may have the same name. + @item For a C@t{++} constructor, the @value{NGCC} compiler generates several instances of the function body, used in different cases. @@ -3517,11 +3536,7 @@ several places where that function is inlined. @end itemize In all those cases, @value{GDBN} will insert a breakpoint at all -the relevant locations@footnote{ -As of this writing, multiple-location breakpoints work only if there's -line number information for all the locations. This means that they -will generally not work in system libraries, unless you have debug -info with line numbers for them.}. +the relevant locations. A breakpoint with multiple locations is displayed in the breakpoint table using several rows---one header row, followed by one row for @@ -3727,7 +3742,7 @@ watchpoints, which do not slow down the running of your program. @table @code @kindex watch -@item watch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} +@item watch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} @r{[}mask @var{maskvalue}@r{]} Set a watchpoint for an expression. @value{GDBN} will break when the expression @var{expr} is written into by the program and its value changes. The simplest (and the most popular) use of this command is @@ -3738,7 +3753,7 @@ to watch the value of a single variable: @end smallexample If the command includes a @code{@r{[}thread @var{threadnum}@r{]}} -clause, @value{GDBN} breaks only when the thread identified by +argument, @value{GDBN} breaks only when the thread identified by @var{threadnum} changes the value of @var{expr}. If any other threads change the value of @var{expr}, @value{GDBN} will not break. Note that watchpoints restricted to a single thread in this way only work @@ -3753,13 +3768,30 @@ to determine the size of the watched memory. If the expression's result does not have an address, then @value{GDBN} will print an error. +The @code{@r{[}mask @var{maskvalue}@r{]}} argument allows creation +of masked watchpoints, if the current architecture supports this +feature (e.g., PowerPC Embedded architecture, see @ref{PowerPC +Embedded}.) A @dfn{masked watchpoint} specifies a mask in addition +to an address to watch. The mask specifies that some bits of an address +(the bits which are reset in the mask) should be ignored when matching +the address accessed by the inferior against the watchpoint address. +Thus, a masked watchpoint watches many addresses simultaneously---those +addresses whose unmasked bits are identical to the unmasked bits in the +watchpoint address. The @code{mask} argument implies @code{-location}. +Examples: + +@smallexample +(@value{GDBP}) watch foo mask 0xffff00ff +(@value{GDBP}) watch *0xdeadbeef mask 0xffffff00 +@end smallexample + @kindex rwatch -@item rwatch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} +@item rwatch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} @r{[}mask @var{maskvalue}@r{]} Set a watchpoint that will break when the value of @var{expr} is read by the program. @kindex awatch -@item awatch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} +@item awatch @r{[}-l@r{|}-location@r{]} @var{expr} @r{[}thread @var{threadnum}@r{]} @r{[}mask @var{maskvalue}@r{]} Set a watchpoint that will break when @var{expr} is either read from or written into by the program. @@ -4828,6 +4860,111 @@ proceed until the function returns. An argument is a repeat count, as in @code{next}. @end table +@node Skipping Over Functions and Files +@section Skipping Over Functions and Files +@cindex skipping over functions and files + +The program you are debugging may contain some functions which are +uninteresting to debug. The @code{skip} comand lets you tell @value{GDBN} to +skip a function or all functions in a file when stepping. + +For example, consider the following C function: + +@smallexample +101 int func() +102 @{ +103 foo(boring()); +104 bar(boring()); +105 @} +@end smallexample + +@noindent +Suppose you wish to step into the functions @code{foo} and @code{bar}, but you +are not interested in stepping through @code{boring}. If you run @code{step} +at line 103, you'll enter @code{boring()}, but if you run @code{next}, you'll +step over both @code{foo} and @code{boring}! + +One solution is to @code{step} into @code{boring} and use the @code{finish} +command to immediately exit it. But this can become tedious if @code{boring} +is called from many places. + +A more flexible solution is to execute @kbd{skip boring}. This instructs +@value{GDBN} never to step into @code{boring}. Now when you execute +@code{step} at line 103, you'll step over @code{boring} and directly into +@code{foo}. + +You can also instruct @value{GDBN} to skip all functions in a file, with, for +example, @code{skip file boring.c}. + +@table @code +@kindex skip function +@item skip @r{[}@var{linespec}@r{]} +@itemx skip function @r{[}@var{linespec}@r{]} +After running this command, the function named by @var{linespec} or the +function containing the line named by @var{linespec} will be skipped over when +stepping. @xref{Specify Location}. + +If you do not specify @var{linespec}, the function you're currently debugging +will be skipped. + +(If you have a function called @code{file} that you want to skip, use +@kbd{skip function file}.) + +@kindex skip file +@item skip file @r{[}@var{filename}@r{]} +After running this command, any function whose source lives in @var{filename} +will be skipped over when stepping. + +If you do not specify @var{filename}, functions whose source lives in the file +you're currently debugging will be skipped. +@end table + +Skips can be listed, deleted, disabled, and enabled, much like breakpoints. +These are the commands for managing your list of skips: + +@table @code +@kindex info skip +@item info skip @r{[}@var{range}@r{]} +Print details about the specified skip(s). If @var{range} is not specified, +print a table with details about all functions and files marked for skipping. +@code{info skip} prints the following information about each skip: + +@table @emph +@item Identifier +A number identifying this skip. +@item Type +The type of this skip, either @samp{function} or @samp{file}. +@item Enabled or Disabled +Enabled skips are marked with @samp{y}. Disabled skips are marked with @samp{n}. +@item Address +For function skips, this column indicates the address in memory of the function +being skipped. If you've set a function skip on a function which has not yet +been loaded, this field will contain @samp{}. Once a shared library +which has the function is loaded, @code{info skip} will show the function's +address here. +@item What +For file skips, this field contains the filename being skipped. For functions +skips, this field contains the function name and its line number in the file +where it is defined. +@end table + +@kindex skip delete +@item skip delete @r{[}@var{range}@r{]} +Delete the specified skip(s). If @var{range} is not specified, delete all +skips. + +@kindex skip enable +@item skip enable @r{[}@var{range}@r{]} +Enable the specified skip(s). If @var{range} is not specified, enable all +skips. + +@kindex skip disable +@item skip disable @r{[}@var{range}@r{]} +Disable the specified skip(s). If @var{range} is not specified, disable all +skips. + +@end table + @node Signals @section Signals @cindex signals @@ -7236,21 +7373,32 @@ No symbol "foo" in current context. To solve such problems, either recompile without optimizations, or use a different debug info format, if the compiler supports several such -formats. For example, @value{NGCC}, the @sc{gnu} C/C@t{++} compiler, -usually supports the @option{-gstabs+} option. @option{-gstabs+} -produces debug info in a format that is superior to formats such as -COFF. You may be able to use DWARF 2 (@option{-gdwarf-2}), which is also -an effective form for debug info. @xref{Debugging Options,,Options -for Debugging Your Program or GCC, gcc.info, Using the @sc{gnu} -Compiler Collection (GCC)}. -@xref{C, ,C and C@t{++}}, for more information about debug info formats -that are best suited to C@t{++} programs. +formats. @xref{Compilation}, for more information on choosing compiler +options. @xref{C, ,C and C@t{++}}, for more information about debug +info formats that are best suited to C@t{++} programs. If you ask to print an object whose contents are unknown to @value{GDBN}, e.g., because its data type is not completely specified by the debug information, @value{GDBN} will say @samp{}. @xref{Symbols, incomplete type}, for more about this. +If you append @kbd{@@entry} string to a function parameter name you get its +value at the time the function got called. If the value is not available an +error message is printed. Entry values are available only with some compilers. +Entry values are normally also printed at the function parameter list according +to @ref{set print entry-values}. + +@smallexample +Breakpoint 1, d (i=30) at gdb.base/entry-value.c:29 +29 i++; +(gdb) next +30 e (i); +(gdb) print i +$1 = 31 +(gdb) print i@@entry +$2 = 30 +@end smallexample + Strings are identified as arrays of @code{char} values without specified signedness. Arrays of either @code{signed char} or @code{unsigned char} get printed as arrays of 1 byte sized integers. @code{-fsigned-char} or @@ -7915,6 +8063,121 @@ thus speeding up the display of each Ada frame. @item show print frame-arguments Show how the value of arguments should be displayed when printing a frame. +@anchor{set print entry-values} +@item set print entry-values @var{value} +@kindex set print entry-values +Set printing of frame argument values at function entry. In some cases +@value{GDBN} can determine the value of function argument which was passed by +the function caller, even if the value was modified inside the called function +and therefore is different. With optimized code, the current value could be +unavailable, but the entry value may still be known. + +The default value is @code{default} (see below for its description). Older +@value{GDBN} behaved as with the setting @code{no}. Compilers not supporting +this feature will behave in the @code{default} setting the same way as with the +@code{no} setting. + +This functionality is currently supported only by DWARF 2 debugging format and +the compiler has to produce @samp{DW_TAG_GNU_call_site} tags. With +@value{NGCC}, you need to specify @option{-O -g} during compilation, to get +this information. + +The @var{value} parameter can be one of the following: + +@table @code +@item no +Print only actual parameter values, never print values from function entry +point. +@smallexample +#0 equal (val=5) +#0 different (val=6) +#0 lost (val=) +#0 born (val=10) +#0 invalid (val=) +@end smallexample + +@item only +Print only parameter values from function entry point. The actual parameter +values are never printed. +@smallexample +#0 equal (val@@entry=5) +#0 different (val@@entry=5) +#0 lost (val@@entry=5) +#0 born (val@@entry=) +#0 invalid (val@@entry=) +@end smallexample + +@item preferred +Print only parameter values from function entry point. If value from function +entry point is not known while the actual value is known, print the actual +value for such parameter. +@smallexample +#0 equal (val@@entry=5) +#0 different (val@@entry=5) +#0 lost (val@@entry=5) +#0 born (val=10) +#0 invalid (val@@entry=) +@end smallexample + +@item if-needed +Print actual parameter values. If actual parameter value is not known while +value from function entry point is known, print the entry point value for such +parameter. +@smallexample +#0 equal (val=5) +#0 different (val=6) +#0 lost (val@@entry=5) +#0 born (val=10) +#0 invalid (val=) +@end smallexample + +@item both +Always print both the actual parameter value and its value from function entry +point, even if values of one or both are not available due to compiler +optimizations. +@smallexample +#0 equal (val=5, val@@entry=5) +#0 different (val=6, val@@entry=5) +#0 lost (val=, val@@entry=5) +#0 born (val=10, val@@entry=) +#0 invalid (val=, val@@entry=) +@end smallexample + +@item compact +Print the actual parameter value if it is known and also its value from +function entry point if it is known. If neither is known, print for the actual +value @code{}. If not in MI mode (@pxref{GDB/MI}) and if both +values are known and identical, print the shortened +@code{param=param@@entry=VALUE} notation. +@smallexample +#0 equal (val=val@@entry=5) +#0 different (val=6, val@@entry=5) +#0 lost (val@@entry=5) +#0 born (val=10) +#0 invalid (val=) +@end smallexample + +@item default +Always print the actual parameter value. Print also its value from function +entry point, but only if it is known. If not in MI mode (@pxref{GDB/MI}) and +if both values are known and identical, print the shortened +@code{param=param@@entry=VALUE} notation. +@smallexample +#0 equal (val=val@@entry=5) +#0 different (val=6, val@@entry=5) +#0 lost (val=, val@@entry=5) +#0 born (val=10) +#0 invalid (val=) +@end smallexample +@end table + +For analysis messages on possible failures of frame argument values at function +entry resolution see @ref{set debug entry-values}. + +@item show print entry-values +Show the method being used for printing of frame argument values at function +entry. + @item set print repeats @cindex repeated array elements Set the threshold for suppressing display of repeated array @@ -8107,7 +8370,10 @@ Display the encoding style currently in use for decoding C@t{++} symbols. @cindex display derived types When displaying a pointer to an object, identify the @emph{actual} (derived) type of the object rather than the @emph{declared} type, using -the virtual function table. +the virtual function table. Note that the virtual function table is +required---this feature can only work for objects that have run-time +type identification; a single virtual method in the object's declared +type is sufficient. @item set print object off Display only the declared type of objects, without reference to the @@ -9306,6 +9572,26 @@ operation. If a line number is specified, the contents of that line will be printed in hex. + +@item set dcache size @var{size} +@cindex dcache size +@kindex set dcache size +Set maximum number of entries in dcache (dcache depth above). + +@item set dcache line-size @var{line-size} +@cindex dcache line-size +@kindex set dcache line-size +Set number of bytes each dcache entry caches (dcache width above). +Must be a power of 2. + +@item show dcache size +@kindex show dcache size +Show maximum number of dcache entries. See also @ref{Caching Remote Data, info dcache}. + +@item show dcache line-size +@kindex show dcache line-size +Show default size of dcache lines. See also @ref{Caching Remote Data, info dcache}. + @end table @node Searching Memory @@ -9440,6 +9726,7 @@ please report it to us as a bug (including a test case!). @menu * Inline Functions:: How @value{GDBN} presents inlining +* Tail Call Frames:: @value{GDBN} analysis of jumps to functions @end menu @node Inline Functions @@ -9507,6 +9794,166 @@ and print a variable where your program stored the return value. @end itemize +@node Tail Call Frames +@section Tail Call Frames +@cindex tail call frames, debugging + +Function @code{B} can call function @code{C} in its very last statement. In +unoptimized compilation the call of @code{C} is immediately followed by return +instruction at the end of @code{B} code. Optimizing compiler may replace the +call and return in function @code{B} into one jump to function @code{C} +instead. Such use of a jump instruction is called @dfn{tail call}. + +During execution of function @code{C}, there will be no indication in the +function call stack frames that it was tail-called from @code{B}. If function +@code{A} regularly calls function @code{B} which tail-calls function @code{C}, +then @value{GDBN} will see @code{A} as the caller of @code{C}. However, in +some cases @value{GDBN} can determine that @code{C} was tail-called from +@code{B}, and it will then create fictitious call frame for that, with the +return address set up as if @code{B} called @code{C} normally. + +This functionality is currently supported only by DWARF 2 debugging format and +the compiler has to produce @samp{DW_TAG_GNU_call_site} tags. With +@value{NGCC}, you need to specify @option{-O -g} during compilation, to get +this information. + +@kbd{info frame} command (@pxref{Frame Info}) will indicate the tail call frame +kind by text @code{tail call frame} such as in this sample @value{GDBN} output: + +@smallexample +(gdb) x/i $pc - 2 + 0x40066b : jmp 0x400640 +(gdb) info frame +Stack level 1, frame at 0x7fffffffda30: + rip = 0x40066d in b (amd64-entry-value.cc:59); saved rip 0x4004c5 + tail call frame, caller of frame at 0x7fffffffda30 + source language c++. + Arglist at unknown address. + Locals at unknown address, Previous frame's sp is 0x7fffffffda30 +@end smallexample + +The detection of all the possible code path executions can find them ambiguous. +There is no execution history stored (possible @ref{Reverse Execution} is never +used for this purpose) and the last known caller could have reached the known +callee by multiple different jump sequences. In such case @value{GDBN} still +tries to show at least all the unambiguous top tail callers and all the +unambiguous bottom tail calees, if any. + +@table @code +@anchor{set debug entry-values} +@item set debug entry-values +@kindex set debug entry-values +When set to on, enables printing of analysis messages for both frame argument +values at function entry and tail calls. It will show all the possible valid +tail calls code paths it has considered. It will also print the intersection +of them with the final unambiguous (possibly partial or even empty) code path +result. + +@item show debug entry-values +@kindex show debug entry-values +Show the current state of analysis messages printing for both frame argument +values at function entry and tail calls. +@end table + +The analysis messages for tail calls can for example show why the virtual tail +call frame for function @code{c} has not been recognized (due to the indirect +reference by variable @code{x}): + +@smallexample +static void __attribute__((noinline, noclone)) c (void); +void (*x) (void) = c; +static void __attribute__((noinline, noclone)) a (void) @{ x++; @} +static void __attribute__((noinline, noclone)) c (void) @{ a (); @} +int main (void) @{ x (); return 0; @} + +Breakpoint 1, DW_OP_GNU_entry_value resolving cannot find +DW_TAG_GNU_call_site 0x40039a in main +a () at t.c:3 +3 static void __attribute__((noinline, noclone)) a (void) @{ x++; @} +(gdb) bt +#0 a () at t.c:3 +#1 0x000000000040039a in main () at t.c:5 +@end smallexample + +Another possibility is an ambiguous virtual tail call frames resolution: + +@smallexample +int i; +static void __attribute__((noinline, noclone)) f (void) @{ i++; @} +static void __attribute__((noinline, noclone)) e (void) @{ f (); @} +static void __attribute__((noinline, noclone)) d (void) @{ f (); @} +static void __attribute__((noinline, noclone)) c (void) @{ d (); @} +static void __attribute__((noinline, noclone)) b (void) +@{ if (i) c (); else e (); @} +static void __attribute__((noinline, noclone)) a (void) @{ b (); @} +int main (void) @{ a (); return 0; @} + +tailcall: initial: 0x4004d2(a) 0x4004ce(b) 0x4004b2(c) 0x4004a2(d) +tailcall: compare: 0x4004d2(a) 0x4004cc(b) 0x400492(e) +tailcall: reduced: 0x4004d2(a) | +(gdb) bt +#0 f () at t.c:2 +#1 0x00000000004004d2 in a () at t.c:8 +#2 0x0000000000400395 in main () at t.c:9 +@end smallexample + +@set CALLSEQ1A @code{main@value{ARROW}a@value{ARROW}b@value{ARROW}c@value{ARROW}d@value{ARROW}f} +@set CALLSEQ2A @code{main@value{ARROW}a@value{ARROW}b@value{ARROW}e@value{ARROW}f} + +@c Convert CALLSEQ#A to CALLSEQ#B depending on HAVE_MAKEINFO_CLICK. +@ifset HAVE_MAKEINFO_CLICK +@set ARROW @click{} +@set CALLSEQ1B @clicksequence{@value{CALLSEQ1A}} +@set CALLSEQ2B @clicksequence{@value{CALLSEQ2A}} +@end ifset +@ifclear HAVE_MAKEINFO_CLICK +@set ARROW -> +@set CALLSEQ1B @value{CALLSEQ1A} +@set CALLSEQ2B @value{CALLSEQ2A} +@end ifclear + +Frames #0 and #2 are real, #1 is a virtual tail call frame. +The code can have possible execution paths @value{CALLSEQ1B} or +@value{CALLSEQ2B}, @value{GDBN} cannot find which one from the inferior state. + +@code{initial:} state shows some random possible calling sequence @value{GDBN} +has found. It then finds another possible calling sequcen - that one is +prefixed by @code{compare:}. The non-ambiguous intersection of these two is +printed as the @code{reduced:} calling sequence. That one could have many +futher @code{compare:} and @code{reduced:} statements as long as there remain +any non-ambiguous sequence entries. + +For the frame of function @code{b} in both cases there are different possible +@code{$pc} values (@code{0x4004cc} or @code{0x4004ce}), therefore this frame is +also ambigous. The only non-ambiguous frame is the one for function @code{a}, +therefore this one is displayed to the user while the ambiguous frames are +omitted. + +There can be also reasons why printing of frame argument values at function +entry may fail: + +@smallexample +int v; +static void __attribute__((noinline, noclone)) c (int i) @{ v++; @} +static void __attribute__((noinline, noclone)) a (int i); +static void __attribute__((noinline, noclone)) b (int i) @{ a (i); @} +static void __attribute__((noinline, noclone)) a (int i) +@{ if (i) b (i - 1); else c (0); @} +int main (void) @{ a (5); return 0; @} + +(gdb) bt +#0 c (i=i@@entry=0) at t.c:2 +#1 0x0000000000400428 in a (DW_OP_GNU_entry_value resolving has found +function "a" at 0x400420 can call itself via tail calls +i=) at t.c:6 +#2 0x000000000040036e in main () at t.c:7 +@end smallexample + +@value{GDBN} cannot find out from the inferior state if and how many times did +function @code{a} call itself (via function @code{b}) as these calls would be +tail calls. Such tail calls would modify thue @code{i} variable, therefore +@value{GDBN} cannot be sure the value it knows would be right - @value{GDBN} +prints @code{} instead. @node Macros @chapter C Preprocessor Macros @@ -9562,10 +10009,20 @@ can be any string of tokens. @kindex info macro @cindex macro definition, showing -@cindex definition, showing a macro's -@item info macro @var{macro} -Show the definition of the macro named @var{macro}, and describe the -source location or compiler command-line where that definition was established. +@cindex definition of a macro, showing +@cindex macros, from debug info +@item info macro [-a|-all] [--] @var{macro} +Show the current definition or all definitions of the named @var{macro}, +and describe the source location or compiler command-line where that +definition was established. The optional double dash is to signify the end of +argument processing and the beginning of @var{macro} for non C-like macros where +the macro may begin with a hyphen. + +@kindex info macros +@item info macros @var{linespec} +Show all macro definitions that are in effect at the location specified +by @var{linespec}, and describe the source location or compiler +command-line where those definitions were established. @kindex macro define @cindex user-defined macros @@ -9624,9 +10081,12 @@ $ cat sample.h $ @end smallexample -Now, we compile the program using the @sc{gnu} C compiler, @value{NGCC}. -We pass the @option{-gdwarf-2} and @option{-g3} flags to ensure the -compiler includes information about preprocessor macros in the debugging +Now, we compile the program using the @sc{gnu} C compiler, +@value{NGCC}. We pass the @option{-gdwarf-2}@footnote{This is the +minimum. Recent versions of @value{NGCC} support @option{-gdwarf-3} +and @option{-gdwarf-4}; we recommend always choosing the most recent +version of DWARF.} @emph{and} @option{-g3} flags to ensure the compiler +includes information about preprocessor macros in the debugging information. @smallexample @@ -9871,9 +10331,21 @@ an address in the target program. @xref{Specify Location}. The @code{trace} command defines a tracepoint, which is a point in the target program where the debugger will briefly stop, collect some data, and then allow the program to continue. Setting a tracepoint or -changing its actions doesn't take effect until the next @code{tstart} +changing its actions takes effect immediately if the remote stub +supports the @samp{InstallInTrace} feature (@pxref{install tracepoint +in tracing}). +If remote stub doesn't support the @samp{InstallInTrace} feature, all +these changes don't take effect until the next @code{tstart} command, and once a trace experiment is running, further changes will -not have any effect until the next trace experiment starts. +not have any effect until the next trace experiment starts. In addition, +@value{GDBN} supports @dfn{pending tracepoints}---tracepoints whose +address is not yet resolved. (This is similar to pending breakpoints.) +Pending tracepoints are not downloaded to the target and not installed +until they are resolved. The resolution of pending tracepoints requires +@value{GDBN} support---when debugging with the remote target, and +@value{GDBN} disconnects from the remote stub (@pxref{disconnected +tracing}), pending tracepoints can not be resolved (and downloaded to +the remote stub) while @value{GDBN} is disconnected. Here are some examples of using the @code{trace} command: @@ -9914,6 +10386,23 @@ message. @value{GDBN} handles arguments to @code{ftrace} exactly as for @code{trace}. +On 32-bit x86-architecture systems, fast tracepoints normally need to +be placed at an instruction that is 5 bytes or longer, but can be +placed at 4-byte instructions if the low 64K of memory of the target +program is available to install trampolines. Some Unix-type systems, +such as @sc{gnu}/Linux, exclude low addresses from the program's +address space; but for instance with the Linux kernel it is possible +to let @value{GDBN} use this area by doing a @command{sysctl} command +to set the @code{mmap_min_addr} kernel parameter, as in + +@example +sudo sysctl -w vm.mmap_min_addr=32768 +@end example + +@noindent +which sets the low address to 32K, which leaves plenty of room for +trampolines. The minimum address should be set to a page boundary. + @item strace @var{location} [ if @var{cond} ] @cindex set static tracepoint @cindex static tracepoints, setting @@ -10011,14 +10500,20 @@ These commands are deprecated; they are equivalent to plain @code{disable} and @ @item disable tracepoint @r{[}@var{num}@r{]} Disable tracepoint @var{num}, or all tracepoints if no argument @var{num} is given. A disabled tracepoint will have no effect during -the next trace experiment, but it is not forgotten. You can re-enable +a trace experiment, but it is not forgotten. You can re-enable a disabled tracepoint using the @code{enable tracepoint} command. +If the command is issued during a trace experiment and the debug target +has support for disabling tracepoints during a trace experiment, then the +change will be effective immediately. Otherwise, it will be applied to the +next trace experiment. @kindex enable tracepoint @item enable tracepoint @r{[}@var{num}@r{]} -Enable tracepoint @var{num}, or all tracepoints. The enabled -tracepoints will become effective the next time a trace experiment is -run. +Enable tracepoint @var{num}, or all tracepoints. If this command is +issued during a trace experiment and the debug target supports enabling +tracepoints during a trace experiment, then the enabled tracepoints will +become effective immediately. Otherwise, they will become effective the +next time a trace experiment is run. @end table @node Tracepoint Passcounts @@ -10203,7 +10698,7 @@ end @end smallexample @kindex collect @r{(tracepoints)} -@item collect @var{expr1}, @var{expr2}, @dots{} +@item collect@r{[}/@var{mods}@r{]} @var{expr1}, @var{expr2}, @dots{} Collect values of the given expressions when the tracepoint is hit. This command accepts a comma-separated list of any valid expressions. In addition to global, static, or local variables, the following @@ -10219,6 +10714,10 @@ Collect all function arguments. @item $locals Collect all local variables. +@item $_ret +Collect the return address. This is helpful if you want to see more +of a backtrace. + @item $_sdata @vindex $_sdata@r{, collect} Collect static tracepoint marker specific data. Only available for @@ -10245,6 +10744,15 @@ You can give several consecutive @code{collect} commands, each one with a single argument, or one @code{collect} command with several arguments separated by commas; the effect is the same. +The optional @var{mods} changes the usual handling of the arguments. +@code{s} requests that pointers to chars be handled as strings, in +particular collecting the contents of the memory being pointed at, up +to the first zero. The upper bound is by default the value of the +@code{print elements} variable; if @code{s} is followed by a decimal +number, that is the upper bound instead. So for instance +@samp{collect/s25 mystr} collects as many as 25 characters at +@samp{mystr}. + The command @code{info scope} (@pxref{Symbols, info scope}) is particularly useful for figuring out what data to collect. @@ -10391,20 +10899,27 @@ Cnt ID Enb Address What @subsection Starting and Stopping Trace Experiments @table @code -@kindex tstart +@kindex tstart [ @var{notes} ] @cindex start a new trace experiment @cindex collected data discarded @item tstart -This command takes no arguments. It starts the trace experiment, and -begins collecting data. This has the side effect of discarding all -the data collected in the trace buffer during the previous trace -experiment. - -@kindex tstop +This command starts the trace experiment, and begins collecting data. +It has the side effect of discarding all the data collected in the +trace buffer during the previous trace experiment. If any arguments +are supplied, they are taken as a note and stored with the trace +experiment's state. The notes may be arbitrary text, and are +especially useful with disconnected tracing in a multi-user context; +the notes can explain what the trace is doing, supply user contact +information, and so forth. + +@kindex tstop [ @var{notes} ] @cindex stop a running trace experiment @item tstop -This command takes no arguments. It ends the trace experiment, and -stops collecting data. +This command stops the trace experiment. If any arguments are +supplied, they are recorded with the experiment as a note. This is +useful if you are stopping a trace started by someone else, for +instance if the trace is interfering with the system's behavior and +needs to be stopped quickly. @strong{Note}: a trace experiment and data collection may stop automatically if any tracepoint's passcount is reached @@ -10434,6 +10949,7 @@ Enter actions for tracepoint #1, one per line. (@value{GDBP}) @b{tstop} @end smallexample +@anchor{disconnected tracing} @cindex disconnected tracing You can choose to continue running the trace experiment even if @value{GDBN} disconnects from the target, voluntarily or @@ -10507,6 +11023,33 @@ for instance if you are looking at frames from a trace file. @end table +@table @code +@item set trace-user @var{text} +@kindex set trace-user + +@item show trace-user +@kindex show trace-user + +@item set trace-notes @var{text} +@kindex set trace-notes +Set the trace run's notes. + +@item show trace-notes +@kindex show trace-notes +Show the trace run's notes. + +@item set trace-stop-notes @var{text} +@kindex set trace-stop-notes +Set the trace run's stop notes. The handling of the note is as for +@code{tstop} arguments; the set command is convenient way to fix a +stop note that is mistaken or incomplete. + +@item show trace-stop-notes +@kindex show trace-stop-notes +Show the trace run's stop notes. + +@end table + @node Tracepoint Restrictions @subsection Tracepoint Restrictions @@ -10561,7 +11104,7 @@ by @code{ptr}. @item It is not possible to collect a complete stack backtrace at a tracepoint. Instead, you may collect the registers and a few hundred -bytes from the stack pointer with something like @code{*$esp@@300} +bytes from the stack pointer with something like @code{*(unsigned char *)$esp@@300} (adjust to use the name of the actual stack pointer register on your target architecture, and the amount of stack you wish to capture). Then the @code{backtrace} command will show a partial backtrace when @@ -11694,13 +12237,6 @@ effectively, you must compile your C@t{++} programs with a supported C@t{++} compiler, such as @sc{gnu} @code{g++}, or the HP ANSI C@t{++} compiler (@code{aCC}). -For best results when using @sc{gnu} C@t{++}, use the DWARF 2 debugging -format; if it doesn't work on your system, try the stabs+ debugging -format. You can select those formats explicitly with the @code{g++} -command-line options @option{-gdwarf-2} and @option{-gstabs+}. -@xref{Debugging Options,,Options for Debugging Your Program or GCC, -gcc.info, Using the @sc{gnu} Compiler Collection (GCC)}. - @menu * C Operators:: C and C@t{++} operators * C Constants:: C and C@t{++} constants @@ -11910,6 +12446,11 @@ of the character's ordinal value; or of the form @samp{\@var{x}}, where @samp{@var{x}} is a predefined special character---for example, @samp{\n} for newline. +Wide character constants can be written by prefixing a character +constant with @samp{L}, as in C. For example, @samp{L'x'} is the wide +form of @samp{x}. The target wide character set is used when +computing the value of this constant (@pxref{Character Sets}). + @item String constants are a sequence of character constants surrounded by double quotes (@code{"}). Any valid character constant (as described @@ -11917,6 +12458,10 @@ above) may appear. Double quotes within the string must be preceded by a backslash, so for instance @samp{"a\"b'c"} is a string of five characters. +Wide string constants can be written by prefixing a string constant +with @samp{L}, as in C. The target wide character set is used when +computing the value of this constant (@pxref{Character Sets}). + @item Pointer constants are an integral value. You can also write pointers to constants using the C operator @samp{&}. @@ -11939,16 +12484,14 @@ and @samp{@{&"hi", &"there", &"fred"@}} is a three-element array of pointers. @cindex debug formats and C@t{++} @cindex @value{NGCC} and C@t{++} @quotation -@emph{Warning:} @value{GDBN} can only debug C@t{++} code if you use the -proper compiler and the proper debug format. Currently, @value{GDBN} -works best when debugging C@t{++} code that is compiled with -@value{NGCC} 2.95.3 or with @value{NGCC} 3.1 or newer, using the options -@option{-gdwarf-2} or @option{-gstabs+}. DWARF 2 is preferred over -stabs+. Most configurations of @value{NGCC} emit either DWARF 2 or -stabs+ as their default debug format, so you usually don't need to -specify a debug format explicitly. Other compilers and/or debug formats -are likely to work badly or not at all when using @value{GDBN} to debug -C@t{++} code. +@emph{Warning:} @value{GDBN} can only debug C@t{++} code if you use +the proper compiler and the proper debug format. Currently, +@value{GDBN} works best when debugging C@t{++} code that is compiled +with the most recent version of @value{NGCC} possible. The DWARF +debugging format is preferred; @value{NGCC} defaults to this on most +popular platforms. Other compilers and/or debug formats are likely to +work badly or not at all when using @value{GDBN} to debug C@t{++} +code. @xref{Compilation}. @end quotation @enumerate @@ -11967,7 +12510,8 @@ count = aml->GetOriginal(x, y) While a member function is active (in the selected stack frame), your expressions have the same namespace available as the member function; that is, @value{GDBN} allows implicit references to the class instance -pointer @code{this} following the same rules as C@t{++}. +pointer @code{this} following the same rules as C@t{++}. @code{using} +declarations in the current scope are also respected by @value{GDBN}. @cindex call overloaded functions @cindex overloaded functions, calling @@ -12019,12 +12563,11 @@ necessary, for example in an expression like @samp{@var{scope1}::@var{scope2}::@var{name}}. @value{GDBN} also allows resolving name scope by reference to source files, in both C and C@t{++} debugging (@pxref{Variables, ,Program Variables}). -@end enumerate -In addition, when used with HP's C@t{++} compiler, @value{GDBN} supports -calling virtual functions correctly, printing out virtual bases of -objects, calling functions in a base subobject, casting objects, and -invoking user-defined operators. +@item +@value{GDBN} performs argument-dependent lookup, following the C@t{++} +specification. +@end enumerate @node C Defaults @subsubsection C and C@t{++} Defaults @@ -13829,16 +14372,34 @@ __read_nocancel + 6 in section .text of /usr/lib64/libc.so.6 @kindex whatis @item whatis [@var{arg}] -Print the data type of @var{arg}, which can be either an expression or -a data type. With no argument, print the data type of @code{$}, the -last value in the value history. If @var{arg} is an expression, it is -not actually evaluated, and any side-effecting operations (such as -assignments or function calls) inside it do not take place. If -@var{arg} is a type name, it may be the name of a type or typedef, or -for C code it may have the form @samp{class @var{class-name}}, -@samp{struct @var{struct-tag}}, @samp{union @var{union-tag}} or -@samp{enum @var{enum-tag}}. -@xref{Expressions, ,Expressions}. +Print the data type of @var{arg}, which can be either an expression +or a name of a data type. With no argument, print the data type of +@code{$}, the last value in the value history. + +If @var{arg} is an expression (@pxref{Expressions, ,Expressions}), it +is not actually evaluated, and any side-effecting operations (such as +assignments or function calls) inside it do not take place. + +If @var{arg} is a variable or an expression, @code{whatis} prints its +literal type as it is used in the source code. If the type was +defined using a @code{typedef}, @code{whatis} will @emph{not} print +the data type underlying the @code{typedef}. If the type of the +variable or the expression is a compound data type, such as +@code{struct} or @code{class}, @code{whatis} never prints their +fields or methods. It just prints the @code{struct}/@code{class} +name (a.k.a.@: its @dfn{tag}). If you want to see the members of +such a compound data type, use @code{ptype}. + +If @var{arg} is a type name that was defined using @code{typedef}, +@code{whatis} @dfn{unrolls} only one level of that @code{typedef}. +Unrolling means that @code{whatis} will show the underlying type used +in the @code{typedef} declaration of @var{arg}. However, if that +underlying type is also a @code{typedef}, @code{whatis} will not +unroll it. + +For C code, the type names may also have the form @samp{class +@var{class-name}}, @samp{struct @var{struct-tag}}, @samp{union +@var{union-tag}} or @samp{enum @var{enum-tag}}. @kindex ptype @item ptype [@var{arg}] @@ -13846,10 +14407,23 @@ for C code it may have the form @samp{class @var{class-name}}, detailed description of the type, instead of just the name of the type. @xref{Expressions, ,Expressions}. +Contrary to @code{whatis}, @code{ptype} always unrolls any +@code{typedef}s in its argument declaration, whether the argument is +a variable, expression, or a data type. This means that @code{ptype} +of a variable or an expression will not print literally its type as +present in the source code---use @code{whatis} for that. @code{typedef}s at +the pointer or reference targets are also unrolled. Only @code{typedef}s of +fields, methods and inner @code{class typedef}s of @code{struct}s, +@code{class}es and @code{union}s are not unrolled even with @code{ptype}. + For example, for this variable declaration: @smallexample -struct complex @{double real; double imag;@} v; +typedef double real_t; +struct complex @{ real_t real; double imag; @}; +typedef struct complex complex_t; +complex_t var; +real_t *real_pointer_var; @end smallexample @noindent @@ -13857,13 +14431,26 @@ the two commands give this output: @smallexample @group -(@value{GDBP}) whatis v +(@value{GDBP}) whatis var +type = complex_t +(@value{GDBP}) ptype var +type = struct complex @{ + real_t real; + double imag; +@} +(@value{GDBP}) whatis complex_t type = struct complex -(@value{GDBP}) ptype v +(@value{GDBP}) whatis struct complex +type = struct complex +(@value{GDBP}) ptype struct complex type = struct complex @{ - double real; + real_t real; double imag; @} +(@value{GDBP}) whatis real_pointer_var +type = real_t * +(@value{GDBP}) ptype real_pointer_var +type = double * @end group @end smallexample @@ -14707,14 +15294,14 @@ the program is running. To do this, use the @code{kill} command @cindex dynamic linking @item add-symbol-file @var{filename} @var{address} @itemx add-symbol-file @var{filename} @var{address} @r{[} -readnow @r{]} -@itemx add-symbol-file @var{filename} @r{-s}@var{section} @var{address} @dots{} +@itemx add-symbol-file @var{filename} @var{address} -s @var{section} @var{address} @dots{} The @code{add-symbol-file} command reads additional symbol table information from the file @var{filename}. You would use this command when @var{filename} has been dynamically loaded (by some other means) into the program that is running. @var{address} should be the memory address at which the file has been loaded; @value{GDBN} cannot figure this out for itself. You can additionally specify an arbitrary number -of @samp{@r{-s}@var{section} @var{address}} pairs, to give an explicit +of @samp{-s @var{section} @var{address}} pairs, to give an explicit section name and base address for that section. You can specify any @var{address} as an expression. @@ -15157,6 +15744,33 @@ This is the default. @end table @end table +@cindex file name canonicalization +@cindex base name differences +When processing file names provided by the user, @value{GDBN} +frequently needs to compare them to the file names recorded in the +program's debug info. Normally, @value{GDBN} compares just the +@dfn{base names} of the files as strings, which is reasonably fast +even for very large programs. (The base name of a file is the last +portion of its name, after stripping all the leading directories.) +This shortcut in comparison is based upon the assumption that files +cannot have more than one base name. This is usually true, but +references to files that use symlinks or similar filesystem +facilities violate that assumption. If your program records files +using such facilities, or if you provide file names to @value{GDBN} +using symlinks etc., you can set @code{basenames-may-differ} to +@code{true} to instruct @value{GDBN} to completely canonicalize each +pair of file names it needs to compare. This will make file-name +comparisons accurate, but at a price of a significant slowdown. + +@table @code +@item set basenames-may-differ +@kindex set basenames-may-differ +Set whether a source file may have multiple base names. + +@item show basenames-may-differ +@kindex show basenames-may-differ +Show whether a source file may have multiple base names. +@end table @node Separate Debug Files @section Debugging Information in Separate Files @@ -16134,6 +16748,7 @@ target system with the same privileges as the user running @subsection Running @code{gdbserver} @cindex arguments, to @code{gdbserver} +@cindex @code{gdbserver}, command-line arguments Run @code{gdbserver} on the target system. You need a copy of the program you want to debug, including any libraries it requires. @@ -16180,6 +16795,8 @@ and exits.} You must use the same port number with the host @value{GDBN} @code{target remote} command. @subsubsection Attaching to a Running Program +@cindex attach to a program, @code{gdbserver} +@cindex @option{--attach}, @code{gdbserver} option On some targets, @code{gdbserver} can also attach to running programs. This is accomplished via the @code{--attach} argument. The syntax is: @@ -16192,7 +16809,6 @@ target> gdbserver --attach @var{comm} @var{pid} to point @code{gdbserver} at a binary for the running process. @pindex pidof -@cindex attach to a program by name You can debug processes by name instead of process ID if your target has the @code{pidof} utility: @@ -16205,8 +16821,8 @@ has multiple threads, most versions of @code{pidof} support the @code{-s} option to only return the first process ID. @subsubsection Multi-Process Mode for @code{gdbserver} -@cindex gdbserver, multiple processes -@cindex multiple processes with gdbserver +@cindex @code{gdbserver}, multiple processes +@cindex multiple processes with @code{gdbserver} When you connect to @code{gdbserver} using @code{target remote}, @code{gdbserver} debugs the specified program only once. When the @@ -16223,23 +16839,60 @@ remote exec-file}) to select the program to run. Command line arguments are supported, except for wildcard expansion and I/O redirection (@pxref{Arguments}). +@cindex @option{--multi}, @code{gdbserver} option To start @code{gdbserver} without supplying an initial command to run or process ID to attach, use the @option{--multi} command line option. Then you can connect using @kbd{target extended-remote} and start the program you want to debug. -@code{gdbserver} does not automatically exit in multi-process mode. -You can terminate it by using @code{monitor exit} -(@pxref{Monitor Commands for gdbserver}). +In multi-process mode @code{gdbserver} does not automatically exit unless you +use the option @option{--once}. You can terminate it by using +@code{monitor exit} (@pxref{Monitor Commands for gdbserver}). Note that the +conditions under which @code{gdbserver} terminates depend on how @value{GDBN} +connects to it (@kbd{target remote} or @kbd{target extended-remote}). The +@option{--multi} option to @code{gdbserver} has no influence on that. + +@subsubsection TCP port allocation lifecycle of @code{gdbserver} + +This section applies only when @code{gdbserver} is run to listen on a TCP port. + +@code{gdbserver} normally terminates after all of its debugged processes have +terminated in @kbd{target remote} mode. On the other hand, for @kbd{target +extended-remote}, @code{gdbserver} stays running even with no processes left. +@value{GDBN} normally terminates the spawned debugged process on its exit, +which normally also terminates @code{gdbserver} in the @kbd{target remote} +mode. Therefore, when the connection drops unexpectedly, and @value{GDBN} +cannot ask @code{gdbserver} to kill its debugged processes, @code{gdbserver} +stays running even in the @kbd{target remote} mode. + +When @code{gdbserver} stays running, @value{GDBN} can connect to it again later. +Such reconnecting is useful for features like @ref{disconnected tracing}. For +completeness, at most one @value{GDBN} can be connected at a time. + +@cindex @option{--once}, @code{gdbserver} option +By default, @code{gdbserver} keeps the listening TCP port open, so that +additional connections are possible. However, if you start @code{gdbserver} +with the @option{--once} option, it will stop listening for any further +connection attempts after connecting to the first @value{GDBN} session. This +means no further connections to @code{gdbserver} will be possible after the +first one. It also means @code{gdbserver} will terminate after the first +connection with remote @value{GDBN} has closed, even for unexpectedly closed +connections and even in the @kbd{target extended-remote} mode. The +@option{--once} option allows reusing the same port number for connecting to +multiple instances of @code{gdbserver} running on the same host, since each +instance closes its port after the first connection. @subsubsection Other Command-Line Arguments for @code{gdbserver} +@cindex @option{--debug}, @code{gdbserver} option The @option{--debug} option tells @code{gdbserver} to display extra -status information about the debugging process. The -@option{--remote-debug} option tells @code{gdbserver} to display +status information about the debugging process. +@cindex @option{--remote-debug}, @code{gdbserver} option +The @option{--remote-debug} option tells @code{gdbserver} to display remote protocol debug output. These options are intended for @code{gdbserver} development and for bug reports to the developers. +@cindex @option{--wrapper}, @code{gdbserver} option The @option{--wrapper} option specifies a wrapper to launch programs for debugging. The option should be followed by the name of the wrapper, then any command-line arguments to pass to the wrapper, then @@ -16314,7 +16967,10 @@ protocol (@pxref{Remote Protocol}). When this command is issued, @var{path} is a colon-separated list of directories to search for @code{libthread_db} (@pxref{Threads,,set libthread-db-search-path}). If you omit @var{path}, -@samp{libthread-db-search-path} will be reset to an empty list. +@samp{libthread-db-search-path} will be reset to its default value. + +The special entry @samp{$pdir} for @samp{libthread-db-search-path} is +not supported in @code{gdbserver}. @item monitor exit Tell gdbserver to exit immediately. This command should be followed by @@ -16503,6 +17159,18 @@ responses. Restrict @value{GDBN} to using @var{limit} remote hardware breakpoint or watchpoints. A limit of -1, the default, is treated as unlimited. +@cindex limit hardware watchpoints length +@cindex remote target, limit watchpoints length +@anchor{set remote hardware-watchpoint-length-limit} +@item set remote hardware-watchpoint-length-limit @var{limit} +Restrict @value{GDBN} to using @var{limit} bytes for the maximum length of +a remote hardware watchpoint. A limit of -1, the default, is treated +as unlimited. + +@item show remote hardware-watchpoint-length-limit +Show the current limit (in bytes) of the maximum length of +a remote hardware watchpoint. + @item set remote exec-file @var{filename} @itemx show remote exec-file @anchor{set remote exec-file} @@ -16738,6 +17406,14 @@ are: @item @code{traceframe-info} @tab @code{qXfer:traceframe-info:read} @tab Traceframe info + +@item @code{install-in-trace} +@tab @code{InstallInTrace} +@tab Install tracepoint in tracing + +@item @code{disable-randomization} +@tab @code{QDisableRandomization} +@tab @code{set disable-randomization} @end multitable @node Remote Stub @@ -18742,6 +19418,9 @@ region using one of the following commands (@pxref{Expressions}): (@value{GDBP}) watch @{char[@var{length}]@} @var{address} @end smallexample +PowerPC embedded processors support masked watchpoints. See the discussion +about the @code{mask} argument in @ref{Set Watchpoints}. + @cindex ranged breakpoint PowerPC embedded processors support hardware accelerated @dfn{ranged breakpoints}. A ranged breakpoint stops execution of @@ -19256,7 +19935,6 @@ default). @item n64 @item eabi32 @item eabi64 -@item auto @end table @item show mips abi @@ -19453,6 +20131,35 @@ Directs @value{GDBN} to use @var{newprompt} as its prompt string henceforth. Prints a line of the form: @samp{Gdb's prompt is: @var{your-prompt}} @end table +Versions of @value{GDBN} that ship with Python scripting enabled have +prompt extensions. The commands for interacting with these extensions +are: + +@table @code +@kindex set extended-prompt +@item set extended-prompt @var{prompt} +Set an extended prompt that allows for substitutions. +@xref{gdb.prompt}, for a list of escape sequences that can be used for +substitution. Any escape sequences specified as part of the prompt +string are replaced with the corresponding strings each time the prompt +is displayed. + +For example: + +@smallexample +set extended-prompt Current working directory: \w (gdb) +@end smallexample + +Note that when an extended-prompt is set, it takes control of the +@var{prompt_hook} hook. @xref{prompt_hook}, for further information. + +@kindex show extended-prompt +@item show extended-prompt +Prints the extended prompt. Any escape sequences specified as part of +the prompt string with @code{set extended-prompt}, are replaced with the +corresponding strings each time the prompt is displayed. +@end table + @node Editing @section Command Editing @cindex readline @@ -20017,12 +20724,6 @@ Displays the current state of @value{GDBN} JIT debugging. Turns on or off debugging messages from the Linux LWP debug support. @item show debug lin-lwp Show the current state of Linux LWP debugging messages. -@item set debug lin-lwp-async -@cindex @sc{gnu}/Linux LWP async debug messages -@cindex Linux lightweight processes -Turns on or off debugging messages from the Linux LWP async debug support. -@item show debug lin-lwp-async -Show the current state of Linux LWP async debugging messages. @item set debug observer @cindex observer debugging info Turns on or off display of @value{GDBN} observer debugging. This @@ -20131,11 +20832,12 @@ Displays whether the debugger is operating in interactive mode or not. @chapter Extending @value{GDBN} @cindex extending GDB -@value{GDBN} provides two mechanisms for extension. The first is based -on composition of @value{GDBN} commands, and the second is based on the -Python scripting language. +@value{GDBN} provides three mechanisms for extension. The first is based +on composition of @value{GDBN} commands, the second is based on the +Python scripting language, and the third is for defining new aliases of +existing commands. -To facilitate the use of these extensions, @value{GDBN} is capable +To facilitate the use of the first two extensions, @value{GDBN} is capable of evaluating the contents of a file. When doing so, @value{GDBN} can recognize which scripting language is being used by looking at the filename extension. Files with an unrecognized filename extension @@ -20170,6 +20872,7 @@ Display the current value of the @code{script-extension} option. @menu * Sequences:: Canned Sequences of Commands * Python:: Scripting @value{GDBN} using Python +* Aliases:: Creating new spellings of existing commands @end menu @node Sequences @@ -20684,6 +21387,12 @@ This directory, known as the @dfn{python directory}, is automatically added to the Python Search Path in order to allow the Python interpreter to locate all scripts installed at this location. +Additionally, @value{GDBN} commands and convenience functions which +are written in Python and are located in the +@file{@var{data-directory}/python/gdb/command} or +@file{@var{data-directory}/python/gdb/function} directories are +automatically imported when @value{GDBN} starts. + @menu * Python Commands:: Accessing Python from @value{GDBN}. * Python API:: Accessing @value{GDBN} from Python. @@ -20727,13 +21436,14 @@ End with a line saying just "end". 23 @end smallexample -@kindex maint set python print-stack -@item maint set python print-stack -By default, @value{GDBN} will print a stack trace when an error occurs -in a Python script. This can be controlled using @code{maint set -python print-stack}: if @code{on}, the default, then Python stack -printing is enabled; if @code{off}, then Python stack printing is -disabled. +@kindex set python print-stack +@item set python print-stack +By default, @value{GDBN} will print only the message component of a +Python exception when an error occurs in a Python script. This can be +controlled using @code{set python print-stack}: if @code{full}, then +full Python stack printing is enabled; if @code{none}, then Python stack +and message printing is disabled; if @code{message}, the default, only +the message component of the error is printed. @end table It is also possible to execute a Python script from the @value{GDBN} @@ -20785,6 +21495,8 @@ situation, a Python @code{KeyboardInterrupt} exception is thrown. * Symbol Tables In Python:: Python representation of symbol tables. * Lazy Strings In Python:: Python representation of lazy strings. * Breakpoints In Python:: Manipulating breakpoints using Python. +* Finish Breakpoints in Python:: Setting Breakpoints on function return + using Python. @end menu @node Basic Python @@ -20799,12 +21511,12 @@ methods and classes added by @value{GDBN} are placed in this module. use in all scripts evaluated by the @code{python} command. @findex gdb.PYTHONDIR -@defvar PYTHONDIR +@defvar gdb.PYTHONDIR A string containing the python directory (@pxref{Python}). @end defvar @findex gdb.execute -@defun execute command [from_tty] [to_string] +@defun gdb.execute (command @r{[}, from_tty @r{[}, to_string@r{]]}) Evaluate @var{command}, a string, as a @value{GDBN} CLI command. If a GDB exception happens while @var{command} runs, it is translated as described in @ref{Exception Handling,,Exception Handling}. @@ -20823,13 +21535,13 @@ and height, and its pagination will be disabled; @pxref{Screen Size}. @end defun @findex gdb.breakpoints -@defun breakpoints +@defun gdb.breakpoints () Return a sequence holding all of @value{GDBN}'s breakpoints. @xref{Breakpoints In Python}, for more information. @end defun @findex gdb.parameter -@defun parameter parameter +@defun gdb.parameter (parameter) Return the value of a @value{GDBN} parameter. @var{parameter} is a string naming the parameter to look up; @var{parameter} may contain spaces if the parameter has a multi-part name. For example, @@ -20842,7 +21554,7 @@ type, and returned. @end defun @findex gdb.history -@defun history number +@defun gdb.history (number) Return a value from @value{GDBN}'s value history (@pxref{Value History}). @var{number} indicates which history element to return. If @var{number} is negative, then @value{GDBN} will take its absolute value @@ -20857,7 +21569,7 @@ If no exception is raised, the return value is always an instance of @end defun @findex gdb.parse_and_eval -@defun parse_and_eval expression +@defun gdb.parse_and_eval (expression) Parse @var{expression} as an expression in the current language, evaluate it, and return the result as a @code{gdb.Value}. @var{expression} must be a string. @@ -20870,7 +21582,7 @@ convenience variable (@pxref{Convenience Vars}) as a @code{gdb.Value}. @end defun @findex gdb.post_event -@defun post_event event +@defun gdb.post_event (event) Put @var{event}, a callable object taking no arguments, into @value{GDBN}'s internal event queue. This callable will be invoked at some later point, during @value{GDBN}'s event processing. Events @@ -20909,7 +21621,7 @@ this. For example: @end defun @findex gdb.write -@defun write string @r{[}stream{]} +@defun gdb.write (string @r{[}, stream{]}) Print a string to @value{GDBN}'s paginated output stream. The optional @var{stream} determines the stream to print to. The default stream is @value{GDBN}'s standard output stream. Possible stream @@ -20918,17 +21630,17 @@ values are: @table @code @findex STDOUT @findex gdb.STDOUT -@item STDOUT +@item gdb.STDOUT @value{GDBN}'s standard output stream. @findex STDERR @findex gdb.STDERR -@item STDERR +@item gdb.STDERR @value{GDBN}'s standard error stream. @findex STDLOG @findex gdb.STDLOG -@item STDLOG +@item gdb.STDLOG @value{GDBN}'s log stream (@pxref{Logging Output}). @end table @@ -20938,7 +21650,7 @@ relevant stream. @end defun @findex gdb.flush -@defun flush +@defun gdb.flush () Flush the buffer of a @value{GDBN} paginated stream so that the contents are displayed immediately. @value{GDBN} will flush the contents of a stream automatically when it encounters a newline in the @@ -20949,17 +21661,17 @@ stream values are: @table @code @findex STDOUT @findex gdb.STDOUT -@item STDOUT +@item gdb.STDOUT @value{GDBN}'s standard output stream. @findex STDERR @findex gdb.STDERR -@item STDERR +@item gdb.STDERR @value{GDBN}'s standard error stream. @findex STDLOG @findex gdb.STDLOG -@item STDLOG +@item gdb.STDLOG @value{GDBN}'s log stream (@pxref{Logging Output}). @end table @@ -20969,14 +21681,14 @@ call this function for the relevant stream. @end defun @findex gdb.target_charset -@defun target_charset +@defun gdb.target_charset () Return the name of the current target character set (@pxref{Character Sets}). This differs from @code{gdb.parameter('target-charset')} in that @samp{auto} is never returned. @end defun @findex gdb.target_wide_charset -@defun target_wide_charset +@defun gdb.target_wide_charset () Return the name of the current target wide character set (@pxref{Character Sets}). This differs from @code{gdb.parameter('target-wide-charset')} in that @samp{auto} is @@ -20984,13 +21696,13 @@ never returned. @end defun @findex gdb.solib_name -@defun solib_name address +@defun gdb.solib_name (address) Return the name of the shared library holding the given @var{address} as a string, or @code{None}. @end defun @findex gdb.decode_line -@defun decode_line @r{[}expression@r{]} +@defun gdb.decode_line @r{[}expression@r{]} Return locations of the line specified by @var{expression}, or of the current line if no argument was given. This function returns a Python tuple containing two elements. The first element contains a string @@ -21003,6 +21715,24 @@ provided, it is decoded the way that @value{GDBN}'s inbuilt @code{break} or @code{edit} commands do (@pxref{Specify Location}). @end defun +@defun gdb.prompt_hook (current_prompt) +@anchor{prompt_hook} + +If @var{prompt_hook} is callable, @value{GDBN} will call the method +assigned to this operation before a prompt is displayed by +@value{GDBN}. + +The parameter @code{current_prompt} contains the current @value{GDBN} +prompt. This method must return a Python string, or @code{None}. If +a string is returned, the @value{GDBN} prompt will be set to that +string. If @code{None} is returned, @value{GDBN} will continue to use +the current prompt. + +Some prompts cannot be substituted in @value{GDBN}. Secondary prompts +such as those used by readline for command input, and annotation +related prompts are prohibited from being changed. +@end defun + @node Exception Handling @subsubsection Exception Handling @cindex python exceptions @@ -21127,24 +21857,24 @@ Any values returned from a function call will be stored as a The following attributes are provided: @table @code -@defivar Value address +@defvar Value.address If this object is addressable, this read-only attribute holds a @code{gdb.Value} object representing the address. Otherwise, this attribute holds @code{None}. -@end defivar +@end defvar @cindex optimized out value in Python -@defivar Value is_optimized_out +@defvar Value.is_optimized_out This read-only boolean attribute is true if the compiler optimized out this value, thus it is not available for fetching from the inferior. -@end defivar +@end defvar -@defivar Value type +@defvar Value.type The type of this @code{gdb.Value}. The value of this attribute is a @code{gdb.Type} object (@pxref{Types In Python}). -@end defivar +@end defvar -@defivar Value dynamic_type +@defvar Value.dynamic_type The dynamic type of this @code{gdb.Value}. This uses C@t{++} run-time type information (@acronym{RTTI}) to determine the dynamic type of the value. If this value is of class type, it will return the class in @@ -21158,13 +21888,28 @@ Note that this feature will only work when debugging a C@t{++} program that includes @acronym{RTTI} for the object in question. Otherwise, it will just return the static type of the value as in @kbd{ptype foo} (@pxref{Symbols, ptype}). -@end defivar +@end defvar + +@defvar Value.is_lazy +The value of this read-only boolean attribute is @code{True} if this +@code{gdb.Value} has not yet been fetched from the inferior. +@value{GDBN} does not fetch values until necessary, for efficiency. +For example: + +@smallexample +myval = gdb.parse_and_eval ('somevar') +@end smallexample + +The value of @code{somevar} is not fetched at this time. It will be +fetched when the value is needed, or when the @code{fetch_lazy} +method is invoked. +@end defvar @end table The following methods are provided: @table @code -@defmethod Value __init__ @var{val} +@defun Value.__init__ (@var{val}) Many Python values can be converted directly to a @code{gdb.Value} via this object initializer. Specifically: @@ -21197,16 +21942,16 @@ If @code{val} is a @code{gdb.LazyString} (@pxref{Lazy Strings In Python}), then the lazy string's @code{value} method is called, and its result is used. @end table -@end defmethod +@end defun -@defmethod Value cast type +@defun Value.cast (type) Return a new instance of @code{gdb.Value} that is the result of casting this instance to the type described by @var{type}, which must be a @code{gdb.Type} object. If the cast cannot be performed for some reason, this method throws an exception. -@end defmethod +@end defun -@defmethod Value dereference +@defun Value.dereference () For pointer data types, this method returns a new @code{gdb.Value} object whose contents is the object pointed to by the pointer. For example, if @code{foo} is a C pointer to an @code{int}, declared in your C program as @@ -21225,19 +21970,19 @@ bar = foo.dereference () The result @code{bar} will be a @code{gdb.Value} object holding the value pointed to by @code{foo}. -@end defmethod +@end defun -@defmethod Value dynamic_cast type +@defun Value.dynamic_cast (type) Like @code{Value.cast}, but works as if the C@t{++} @code{dynamic_cast} operator were used. Consult a C@t{++} reference for details. -@end defmethod +@end defun -@defmethod Value reinterpret_cast type +@defun Value.reinterpret_cast (type) Like @code{Value.cast}, but works as if the C@t{++} @code{reinterpret_cast} operator were used. Consult a C@t{++} reference for details. -@end defmethod +@end defun -@defmethod Value string @r{[}encoding@r{]} @r{[}errors@r{]} @r{[}length@r{]} +@defun Value.string (@r{[}encoding@r{[}, errors@r{[}, length@r{]]]}) If this @code{gdb.Value} represents a string, then this method converts the contents to a Python string. Otherwise, this method will throw an exception. @@ -21267,9 +22012,9 @@ argument to Python's @code{string.decode} method. If the optional @var{length} argument is given, the string will be fetched and converted to the given length. -@end defmethod +@end defun -@defmethod Value lazy_string @r{[}encoding@r{]} @r{[}length@r{]} +@defun Value.lazy_string (@r{[}encoding @r{[}, length@r{]]}) If this @code{gdb.Value} represents a string, then this method converts the contents to a @code{gdb.LazyString} (@pxref{Lazy Strings In Python}). Otherwise, this method will throw an exception. @@ -21291,7 +22036,20 @@ If the optional @var{length} argument is given, the string will be fetched and encoded to the length of characters specified. If the @var{length} argument is not provided, the string will be fetched and encoded until a null of appropriate width is found. -@end defmethod +@end defun + +@defun Value.fetch_lazy () +If the @code{gdb.Value} object is currently a lazy value +(@code{gdb.Value.is_lazy} is @code{True}), then the value is +fetched from the inferior. Any errors that occur in the process +will produce a Python exception. + +If the @code{gdb.Value} object is not a lazy value, this method +has no effect. + +This method does not return a value. +@end defun + @end table @node Types In Python @@ -21307,7 +22065,7 @@ The following type-related functions are available in the @code{gdb} module: @findex gdb.lookup_type -@defun lookup_type name [block] +@defun gdb.lookup_type (name @r{[}, block@r{]}) This function looks up a type by name. @var{name} is the name of the type to look up. It must be a string. @@ -21318,32 +22076,45 @@ Ordinarily, this function will return an instance of @code{gdb.Type}. If the named type cannot be found, it will throw an exception. @end defun +If the type is a structure or class type, or an enum type, the fields +of that type can be accessed using the Python @dfn{dictionary syntax}. +For example, if @code{some_type} is a @code{gdb.Type} instance holding +a structure type, you can access its @code{foo} field with: + +@smallexample +bar = some_type['foo'] +@end smallexample + +@code{bar} will be a @code{gdb.Field} object; see below under the +description of the @code{Type.fields} method for a description of the +@code{gdb.Field} class. + An instance of @code{Type} has the following attributes: @table @code -@defivar Type code +@defvar Type.code The type code for this type. The type code will be one of the @code{TYPE_CODE_} constants defined below. -@end defivar +@end defvar -@defivar Type sizeof +@defvar Type.sizeof The size of this type, in target @code{char} units. Usually, a target's @code{char} type will be an 8-bit byte. However, on some unusual platforms, this type may have a different size. -@end defivar +@end defvar -@defivar Type tag +@defvar Type.tag The tag name for this type. The tag name is the name after @code{struct}, @code{union}, or @code{enum} in C and C@t{++}; not all languages have this concept. If this type has no tag name, then @code{None} is returned. -@end defivar +@end defvar @end table The following methods are provided: @table @code -@defmethod Type fields +@defun Type.fields () For structure and union types, this method returns the fields. Range types have two fields, the minimum and maximum values. Enum types have one field per enum constant. Function and method types have one @@ -21351,12 +22122,13 @@ field per parameter. The base types of C@t{++} classes are also represented as fields. If the type has no fields, or does not fit into one of these categories, an empty sequence will be returned. -Each field is an object, with some pre-defined attributes: +Each field is a @code{gdb.Field} object, with some pre-defined attributes: @table @code @item bitpos This attribute is not available for @code{static} fields (as in C@t{++} or Java). For non-@code{static} fields, the value is the bit -position of the field. +position of the field. For @code{enum} fields, the value is the +enumeration member's integer representation. @item name The name of the field, or @code{None} for anonymous fields. @@ -21381,56 +22153,56 @@ this will be zero; in this case the field's size is given by its type. The type of the field. This is usually an instance of @code{Type}, but it can be @code{None} in some situations. @end table -@end defmethod +@end defun -@defmethod Type array @var{n1} @r{[}@var{n2}@r{]} +@defun Type.array (@var{n1} @r{[}, @var{n2}@r{]}) Return a new @code{gdb.Type} object which represents an array of this type. If one argument is given, it is the inclusive upper bound of the array; in this case the lower bound is zero. If two arguments are given, the first argument is the lower bound of the array, and the second argument is the upper bound of the array. An array's length must not be negative, but the bounds can be. -@end defmethod +@end defun -@defmethod Type const +@defun Type.const () Return a new @code{gdb.Type} object which represents a @code{const}-qualified variant of this type. -@end defmethod +@end defun -@defmethod Type volatile +@defun Type.volatile () Return a new @code{gdb.Type} object which represents a @code{volatile}-qualified variant of this type. -@end defmethod +@end defun -@defmethod Type unqualified +@defun Type.unqualified () Return a new @code{gdb.Type} object which represents an unqualified variant of this type. That is, the result is neither @code{const} nor @code{volatile}. -@end defmethod +@end defun -@defmethod Type range +@defun Type.range () Return a Python @code{Tuple} object that contains two elements: the low bound of the argument type and the high bound of that type. If the type does not have a range, @value{GDBN} will raise a @code{gdb.error} exception (@pxref{Exception Handling}). -@end defmethod +@end defun -@defmethod Type reference +@defun Type.reference () Return a new @code{gdb.Type} object which represents a reference to this type. -@end defmethod +@end defun -@defmethod Type pointer +@defun Type.pointer () Return a new @code{gdb.Type} object which represents a pointer to this type. -@end defmethod +@end defun -@defmethod Type strip_typedefs +@defun Type.strip_typedefs () Return a new @code{gdb.Type} that represents the real type, after removing all layers of typedefs. -@end defmethod +@end defun -@defmethod Type target +@defun Type.target () Return a new @code{gdb.Type} object which represents the target type of this type. @@ -21443,9 +22215,9 @@ target type is the aliased type. If the type does not have a target, this method will throw an exception. -@end defmethod +@end defun -@defmethod Type template_argument n [block] +@defun Type.template_argument (n @r{[}, block@r{]}) If this @code{gdb.Type} is an instantiation of a template, this will return a new @code{gdb.Type} which represents the type of the @var{n}th template argument. @@ -21455,7 +22227,7 @@ exception. Ordinarily, only C@t{++} code will have template types. If @var{block} is given, then @var{name} is looked up in that scope. Otherwise, it is searched for globally. -@end defmethod +@end defun @end table @@ -21466,133 +22238,133 @@ defined in the @code{gdb} module: @table @code @findex TYPE_CODE_PTR @findex gdb.TYPE_CODE_PTR -@item TYPE_CODE_PTR +@item gdb.TYPE_CODE_PTR The type is a pointer. @findex TYPE_CODE_ARRAY @findex gdb.TYPE_CODE_ARRAY -@item TYPE_CODE_ARRAY +@item gdb.TYPE_CODE_ARRAY The type is an array. @findex TYPE_CODE_STRUCT @findex gdb.TYPE_CODE_STRUCT -@item TYPE_CODE_STRUCT +@item gdb.TYPE_CODE_STRUCT The type is a structure. @findex TYPE_CODE_UNION @findex gdb.TYPE_CODE_UNION -@item TYPE_CODE_UNION +@item gdb.TYPE_CODE_UNION The type is a union. @findex TYPE_CODE_ENUM @findex gdb.TYPE_CODE_ENUM -@item TYPE_CODE_ENUM +@item gdb.TYPE_CODE_ENUM The type is an enum. @findex TYPE_CODE_FLAGS @findex gdb.TYPE_CODE_FLAGS -@item TYPE_CODE_FLAGS +@item gdb.TYPE_CODE_FLAGS A bit flags type, used for things such as status registers. @findex TYPE_CODE_FUNC @findex gdb.TYPE_CODE_FUNC -@item TYPE_CODE_FUNC +@item gdb.TYPE_CODE_FUNC The type is a function. @findex TYPE_CODE_INT @findex gdb.TYPE_CODE_INT -@item TYPE_CODE_INT +@item gdb.TYPE_CODE_INT The type is an integer type. @findex TYPE_CODE_FLT @findex gdb.TYPE_CODE_FLT -@item TYPE_CODE_FLT +@item gdb.TYPE_CODE_FLT A floating point type. @findex TYPE_CODE_VOID @findex gdb.TYPE_CODE_VOID -@item TYPE_CODE_VOID +@item gdb.TYPE_CODE_VOID The special type @code{void}. @findex TYPE_CODE_SET @findex gdb.TYPE_CODE_SET -@item TYPE_CODE_SET +@item gdb.TYPE_CODE_SET A Pascal set type. @findex TYPE_CODE_RANGE @findex gdb.TYPE_CODE_RANGE -@item TYPE_CODE_RANGE +@item gdb.TYPE_CODE_RANGE A range type, that is, an integer type with bounds. @findex TYPE_CODE_STRING @findex gdb.TYPE_CODE_STRING -@item TYPE_CODE_STRING +@item gdb.TYPE_CODE_STRING A string type. Note that this is only used for certain languages with language-defined string types; C strings are not represented this way. @findex TYPE_CODE_BITSTRING @findex gdb.TYPE_CODE_BITSTRING -@item TYPE_CODE_BITSTRING +@item gdb.TYPE_CODE_BITSTRING A string of bits. @findex TYPE_CODE_ERROR @findex gdb.TYPE_CODE_ERROR -@item TYPE_CODE_ERROR +@item gdb.TYPE_CODE_ERROR An unknown or erroneous type. @findex TYPE_CODE_METHOD @findex gdb.TYPE_CODE_METHOD -@item TYPE_CODE_METHOD +@item gdb.TYPE_CODE_METHOD A method type, as found in C@t{++} or Java. @findex TYPE_CODE_METHODPTR @findex gdb.TYPE_CODE_METHODPTR -@item TYPE_CODE_METHODPTR +@item gdb.TYPE_CODE_METHODPTR A pointer-to-member-function. @findex TYPE_CODE_MEMBERPTR @findex gdb.TYPE_CODE_MEMBERPTR -@item TYPE_CODE_MEMBERPTR +@item gdb.TYPE_CODE_MEMBERPTR A pointer-to-member. @findex TYPE_CODE_REF @findex gdb.TYPE_CODE_REF -@item TYPE_CODE_REF +@item gdb.TYPE_CODE_REF A reference type. @findex TYPE_CODE_CHAR @findex gdb.TYPE_CODE_CHAR -@item TYPE_CODE_CHAR +@item gdb.TYPE_CODE_CHAR A character type. @findex TYPE_CODE_BOOL @findex gdb.TYPE_CODE_BOOL -@item TYPE_CODE_BOOL +@item gdb.TYPE_CODE_BOOL A boolean type. @findex TYPE_CODE_COMPLEX @findex gdb.TYPE_CODE_COMPLEX -@item TYPE_CODE_COMPLEX +@item gdb.TYPE_CODE_COMPLEX A complex float type. @findex TYPE_CODE_TYPEDEF @findex gdb.TYPE_CODE_TYPEDEF -@item TYPE_CODE_TYPEDEF +@item gdb.TYPE_CODE_TYPEDEF A typedef to some other type. @findex TYPE_CODE_NAMESPACE @findex gdb.TYPE_CODE_NAMESPACE -@item TYPE_CODE_NAMESPACE +@item gdb.TYPE_CODE_NAMESPACE A C@t{++} namespace. @findex TYPE_CODE_DECFLOAT @findex gdb.TYPE_CODE_DECFLOAT -@item TYPE_CODE_DECFLOAT +@item gdb.TYPE_CODE_DECFLOAT A decimal floating point type. @findex TYPE_CODE_INTERNAL_FUNCTION @findex gdb.TYPE_CODE_INTERNAL_FUNCTION -@item TYPE_CODE_INTERNAL_FUNCTION +@item gdb.TYPE_CODE_INTERNAL_FUNCTION A function internal to @value{GDBN}. This is the type used to represent convenience functions. @end table @@ -21608,7 +22380,7 @@ An example output is provided (@pxref{Pretty Printing}). A pretty-printer is just an object that holds a value and implements a specific interface, defined here. -@defop Operation {pretty printer} children (self) +@defun pretty_printer.children (self) @value{GDBN} will call this method on a pretty-printer to compute the children of the pretty-printer's value. @@ -21620,9 +22392,9 @@ object which is convertible to a @value{GDBN} value. This method is optional. If it does not exist, @value{GDBN} will act as though the value has no children. -@end defop +@end defun -@defop Operation {pretty printer} display_hint (self) +@defun pretty_printer.display_hint (self) The CLI may call this method and use its result to change the formatting of a value. The result will also be supplied to an MI consumer as a @samp{displayhint} attribute of the variable being @@ -21652,9 +22424,9 @@ string-printing function to format the string. For the CLI this means adding quotation marks, possibly escaping some characters, respecting @code{set print elements}, and the like. @end table -@end defop +@end defun -@defop Operation {pretty printer} to_string (self) +@defun pretty_printer.to_string (self) @value{GDBN} will call this method to display the string representation of the value passed to the object's constructor. @@ -21682,13 +22454,13 @@ Finally, if this method returns @code{None} then no further operations are peformed in this method and nothing is printed. If the result is not one of these types, an exception is raised. -@end defop +@end defun @value{GDBN} provides a function which can be used to look up the default pretty-printer for a @code{gdb.Value}: @findex gdb.default_visualizer -@defun default_visualizer value +@defun gdb.default_visualizer (value) This function takes a @code{gdb.Value} object as an argument. If a pretty-printer for this value exists, then it is returned. If no such printer exists, then this returns @code{None}. @@ -21814,7 +22586,7 @@ this code might appear in @code{gdb.libstdcxx.v6}: @smallexample def register_printers(objfile): - objfile.pretty_printers.add(str_lookup_function) + objfile.pretty_printers.append(str_lookup_function) @end smallexample @noindent @@ -21922,64 +22694,68 @@ via objects of the @code{gdb.Inferior} class. The following inferior-related functions are available in the @code{gdb} module: -@defun inferiors +@defun gdb.inferiors () Return a tuple containing all inferior objects. @end defun +@defun gdb.selected_inferior () +Return an object representing the current inferior. +@end defun + A @code{gdb.Inferior} object has the following attributes: @table @code -@defivar Inferior num +@defvar Inferior.num ID of inferior, as assigned by GDB. -@end defivar +@end defvar -@defivar Inferior pid +@defvar Inferior.pid Process ID of the inferior, as assigned by the underlying operating system. -@end defivar +@end defvar -@defivar Inferior was_attached +@defvar Inferior.was_attached Boolean signaling whether the inferior was created using `attach', or started by @value{GDBN} itself. -@end defivar +@end defvar @end table A @code{gdb.Inferior} object has the following methods: @table @code -@defmethod Inferior is_valid +@defun Inferior.is_valid () Returns @code{True} if the @code{gdb.Inferior} object is valid, @code{False} if not. A @code{gdb.Inferior} object will become invalid if the inferior no longer exists within @value{GDBN}. All other @code{gdb.Inferior} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun -@defmethod Inferior threads +@defun Inferior.threads () This method returns a tuple holding all the threads which are valid when it is called. If there are no valid threads, the method will return an empty tuple. -@end defmethod +@end defun @findex gdb.read_memory -@defmethod Inferior read_memory address length +@defun Inferior.read_memory (address, length) Read @var{length} bytes of memory from the inferior, starting at @var{address}. Returns a buffer object, which behaves much like an array or a string. It can be modified and given to the @code{gdb.write_memory} function. -@end defmethod +@end defun @findex gdb.write_memory -@defmethod Inferior write_memory address buffer @r{[}length@r{]} +@defun Inferior.write_memory (address, buffer @r{[}, length@r{]}) Write the contents of @var{buffer} to the inferior, starting at @var{address}. The @var{buffer} parameter must be a Python object which supports the buffer protocol, i.e., a string, an array or the object returned from @code{gdb.read_memory}. If given, @var{length} determines the number of bytes from @var{buffer} to be written. -@end defmethod +@end defun @findex gdb.search_memory -@defmethod Inferior search_memory address length pattern +@defun Inferior.search_memory (address, length, pattern) Search a region of the inferior memory starting at @var{address} with the given @var{length} using the search pattern supplied in @var{pattern}. The @var{pattern} parameter must be a Python object @@ -21987,7 +22763,7 @@ which supports the buffer protocol, i.e., a string, an array or the object returned from @code{gdb.read_memory}. Returns a Python @code{Long} containing the address where the pattern was found, or @code{None} if the pattern could not be found. -@end defmethod +@end defun @end table @node Events In Python @@ -22008,15 +22784,15 @@ with an @dfn{event registry}. An event registry is an object in the provides methods to register and unregister event handlers: @table @code -@defmethod EventRegistry connect object +@defun EventRegistry.connect (object) Add the given callable @var{object} to the registry. This object will be called when an event corresponding to this registry occurs. -@end defmethod +@end defun -@defmethod EventRegistry disconnect object +@defun EventRegistry.disconnect (object) Remove the given @var{object} from the registry. Once removed, the object will no longer receive notifications of events. -@end defmethod +@end defun @end table Here is an example: @@ -22052,10 +22828,10 @@ Examples of these events are @code{gdb.BreakpointEvent} and @code{gdb.ContinueEvent}. @table @code -@defivar ThreadEvent inferior_thread +@defvar ThreadEvent.inferior_thread In non-stop mode this attribute will be set to the specific thread which was involved in the emitted event. Otherwise, it will be set to @code{None}. -@end defivar +@end defvar @end table Emits @code{gdb.ContinueEvent} which extends @code{gdb.ThreadEvent}. @@ -22065,13 +22841,17 @@ inherited attribute refer to @code{gdb.ThreadEvent} above. @item events.exited Emits @code{events.ExitedEvent} which indicates that the inferior has exited. -@code{events.ExitedEvent} has one optional attribute. This attribute -will exist only in the case that the inferior exited with some -status. +@code{events.ExitedEvent} has two attributes: @table @code -@defivar ExitedEvent exit_code -An integer representing the exit code which the inferior has returned. -@end defivar +@defvar ExitedEvent.exit_code +An integer representing the exit code, if available, which the inferior +has returned. (The exit code could be unavailable if, for example, +@value{GDBN} detaches from the inferior.) If the exit code is unavailable, +the attribute does not exist. +@end defvar +@defvar ExitedEvent inferior +A reference to the inferior which triggered the @code{exited} event. +@end defvar @end table @item events.stop @@ -22088,23 +22868,40 @@ This event indicates that the inferior or one of its threads has received as signal. @code{gdb.SignalEvent} has the following attributes: @table @code -@defivar SignalEvent stop_signal +@defvar SignalEvent.stop_signal A string representing the signal received by the inferior. A list of possible signal values can be obtained by running the command @code{info signals} in the @value{GDBN} command prompt. -@end defivar +@end defvar @end table Also emits @code{gdb.BreakpointEvent} which extends @code{gdb.StopEvent}. -@code{gdb.BreakpointEvent} event indicates that a breakpoint has been hit, and -has the following attributes: +@code{gdb.BreakpointEvent} event indicates that one or more breakpoints have +been hit, and has the following attributes: @table @code -@defivar BreakpointEvent breakpoint -A reference to the breakpoint that was hit of type @code{gdb.Breakpoint}. +@defvar BreakpointEvent.breakpoints +A sequence containing references to all the breakpoints (type +@code{gdb.Breakpoint}) that were hit. @xref{Breakpoints In Python}, for details of the @code{gdb.Breakpoint} object. -@end defivar +@end defvar +@defvar BreakpointEvent.breakpoint +A reference to the first breakpoint that was hit. +This function is maintained for backward compatibility and is now deprecated +in favor of the @code{gdb.BreakpointEvent.breakpoints} attribute. +@end defvar +@end table + +@item events.new_objfile +Emits @code{gdb.NewObjFileEvent} which indicates that a new object file has +been loaded by @value{GDBN}. @code{gdb.NewObjFileEvent} has one attribute: + +@table @code +@defvar NewObjFileEvent.new_objfile +A reference to the object file (@code{gdb.Objfile}) which has been loaded. +@xref{Objfiles In Python}, for details of the @code{gdb.Objfile} object. +@end defvar @end table @end table @@ -22121,7 +22918,7 @@ The following thread-related functions are available in the @code{gdb} module: @findex gdb.selected_thread -@defun selected_thread +@defun gdb.selected_thread () This function returns the thread object for the selected thread. If there is no selected thread, this will return @code{None}. @end defun @@ -22129,7 +22926,7 @@ is no selected thread, this will return @code{None}. A @code{gdb.InferiorThread} object has the following attributes: @table @code -@defivar InferiorThread name +@defvar InferiorThread.name The name of the thread. If the user specified a name using @code{thread name}, then this returns that name. Otherwise, if an OS-supplied name is available, then it is returned. Otherwise, this @@ -22138,48 +22935,48 @@ returns @code{None}. This attribute can be assigned to. The new value must be a string object, which sets the new name, or @code{None}, which removes any user-specified thread name. -@end defivar +@end defvar -@defivar InferiorThread num +@defvar InferiorThread.num ID of the thread, as assigned by GDB. -@end defivar +@end defvar -@defivar InferiorThread ptid +@defvar InferiorThread.ptid ID of the thread, as assigned by the operating system. This attribute is a tuple containing three integers. The first is the Process ID (PID); the second is the Lightweight Process ID (LWPID), and the third is the Thread ID (TID). Either the LWPID or TID may be 0, which indicates that the operating system does not use that identifier. -@end defivar +@end defvar @end table A @code{gdb.InferiorThread} object has the following methods: @table @code -@defmethod InferiorThread is_valid +@defun InferiorThread.is_valid () Returns @code{True} if the @code{gdb.InferiorThread} object is valid, @code{False} if not. A @code{gdb.InferiorThread} object will become invalid if the thread exits, or the inferior that the thread belongs is deleted. All other @code{gdb.InferiorThread} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun -@defmethod InferiorThread switch +@defun InferiorThread.switch () This changes @value{GDBN}'s currently selected thread to the one represented by this object. -@end defmethod +@end defun -@defmethod InferiorThread is_stopped +@defun InferiorThread.is_stopped () Return a Boolean indicating whether the thread is stopped. -@end defmethod +@end defun -@defmethod InferiorThread is_running +@defun InferiorThread.is_running () Return a Boolean indicating whether the thread is running. -@end defmethod +@end defun -@defmethod InferiorThread is_exited +@defun InferiorThread.is_exited () Return a Boolean indicating whether the thread is exited. -@end defmethod +@end defun @end table @node Commands In Python @@ -22191,7 +22988,7 @@ You can implement new @value{GDBN} CLI commands in Python. A CLI command is implemented using an instance of the @code{gdb.Command} class, most commonly using a subclass. -@defmethod Command __init__ name @var{command_class} @r{[}@var{completer_class}@r{]} @r{[}@var{prefix}@r{]} +@defun Command.__init__ (name, @var{command_class} @r{[}, @var{completer_class} @r{[}, @var{prefix}@r{]]}) The object initializer for @code{Command} registers the new command with @value{GDBN}. This initializer is normally invoked from the subclass' own @code{__init__} method. @@ -22222,17 +23019,17 @@ The help text for the new command is taken from the Python documentation string for the command's class, if there is one. If no documentation string is provided, the default value ``This command is not documented.'' is used. -@end defmethod +@end defun @cindex don't repeat Python command -@defmethod Command dont_repeat +@defun Command.dont_repeat () By default, a @value{GDBN} command is repeated when the user enters a blank line at the command prompt. A command can suppress this behavior by invoking the @code{dont_repeat} method. This is similar to the user command @code{dont-repeat}, see @ref{Define, dont-repeat}. -@end defmethod +@end defun -@defmethod Command invoke argument from_tty +@defun Command.invoke (argument, from_tty) This method is called by @value{GDBN} when this command is invoked. @var{argument} is a string. It is the argument to the command, after @@ -22258,10 +23055,10 @@ print gdb.string_to_argv ("1 2\ \\\"3 '4 \"5' \"6 '7\"") ['1', '2 "3', '4 "5', "6 '7"] @end smallexample -@end defmethod +@end defun @cindex completion of Python commands -@defmethod Command complete text word +@defun Command.complete (text, word) This method is called by @value{GDBN} when the user attempts completion on this command. All forms of completion are handled by this method, that is, the @key{TAB} and @key{M-?} key bindings @@ -22292,7 +23089,7 @@ function is invoked, and its result is used. All other results are treated as though there were no available completions. @end itemize -@end defmethod +@end defun When a new command is registered, it must be declared as a member of some general class of commands. This is used to classify top-level @@ -22304,13 +23101,13 @@ defined in the @code{gdb} module: @table @code @findex COMMAND_NONE @findex gdb.COMMAND_NONE -@item COMMAND_NONE +@item gdb.COMMAND_NONE The command does not belong to any particular class. A command in this category will not be displayed in any of the help categories. @findex COMMAND_RUNNING @findex gdb.COMMAND_RUNNING -@item COMMAND_RUNNING +@item gdb.COMMAND_RUNNING The command is related to running the inferior. For example, @code{start}, @code{step}, and @code{continue} are in this category. Type @kbd{help running} at the @value{GDBN} prompt to see a list of @@ -22318,7 +23115,7 @@ commands in this category. @findex COMMAND_DATA @findex gdb.COMMAND_DATA -@item COMMAND_DATA +@item gdb.COMMAND_DATA The command is related to data or variables. For example, @code{call}, @code{find}, and @code{print} are in this category. Type @kbd{help data} at the @value{GDBN} prompt to see a list of commands @@ -22326,7 +23123,7 @@ in this category. @findex COMMAND_STACK @findex gdb.COMMAND_STACK -@item COMMAND_STACK +@item gdb.COMMAND_STACK The command has to do with manipulation of the stack. For example, @code{backtrace}, @code{frame}, and @code{return} are in this category. Type @kbd{help stack} at the @value{GDBN} prompt to see a @@ -22334,7 +23131,7 @@ list of commands in this category. @findex COMMAND_FILES @findex gdb.COMMAND_FILES -@item COMMAND_FILES +@item gdb.COMMAND_FILES This class is used for file-related commands. For example, @code{file}, @code{list} and @code{section} are in this category. Type @kbd{help files} at the @value{GDBN} prompt to see a list of @@ -22342,7 +23139,7 @@ commands in this category. @findex COMMAND_SUPPORT @findex gdb.COMMAND_SUPPORT -@item COMMAND_SUPPORT +@item gdb.COMMAND_SUPPORT This should be used for ``support facilities'', generally meaning things that are useful to the user when interacting with @value{GDBN}, but not related to the state of the inferior. For example, @@ -22352,7 +23149,7 @@ commands in this category. @findex COMMAND_STATUS @findex gdb.COMMAND_STATUS -@item COMMAND_STATUS +@item gdb.COMMAND_STATUS The command is an @samp{info}-related command, that is, related to the state of @value{GDBN} itself. For example, @code{info}, @code{macro}, and @code{show} are in this category. Type @kbd{help status} at the @@ -22360,7 +23157,7 @@ and @code{show} are in this category. Type @kbd{help status} at the @findex COMMAND_BREAKPOINTS @findex gdb.COMMAND_BREAKPOINTS -@item COMMAND_BREAKPOINTS +@item gdb.COMMAND_BREAKPOINTS The command has to do with breakpoints. For example, @code{break}, @code{clear}, and @code{delete} are in this category. Type @kbd{help breakpoints} at the @value{GDBN} prompt to see a list of commands in @@ -22368,7 +23165,7 @@ this category. @findex COMMAND_TRACEPOINTS @findex gdb.COMMAND_TRACEPOINTS -@item COMMAND_TRACEPOINTS +@item gdb.COMMAND_TRACEPOINTS The command has to do with tracepoints. For example, @code{trace}, @code{actions}, and @code{tfind} are in this category. Type @kbd{help tracepoints} at the @value{GDBN} prompt to see a list of @@ -22376,7 +23173,7 @@ commands in this category. @findex COMMAND_OBSCURE @findex gdb.COMMAND_OBSCURE -@item COMMAND_OBSCURE +@item gdb.COMMAND_OBSCURE The command is only used in unusual circumstances, or is not of general interest to users. For example, @code{checkpoint}, @code{fork}, and @code{stop} are in this category. Type @kbd{help @@ -22385,7 +23182,7 @@ category. @findex COMMAND_MAINTENANCE @findex gdb.COMMAND_MAINTENANCE -@item COMMAND_MAINTENANCE +@item gdb.COMMAND_MAINTENANCE The command is only useful to @value{GDBN} maintainers. The @code{maintenance} and @code{flushregs} commands are in this category. Type @kbd{help internals} at the @value{GDBN} prompt to see a list of @@ -22400,29 +23197,29 @@ constants are all defined in the @code{gdb} module: @table @code @findex COMPLETE_NONE @findex gdb.COMPLETE_NONE -@item COMPLETE_NONE +@item gdb.COMPLETE_NONE This constant means that no completion should be done. @findex COMPLETE_FILENAME @findex gdb.COMPLETE_FILENAME -@item COMPLETE_FILENAME +@item gdb.COMPLETE_FILENAME This constant means that filename completion should be performed. @findex COMPLETE_LOCATION @findex gdb.COMPLETE_LOCATION -@item COMPLETE_LOCATION +@item gdb.COMPLETE_LOCATION This constant means that location completion should be done. @xref{Specify Location}. @findex COMPLETE_COMMAND @findex gdb.COMPLETE_COMMAND -@item COMPLETE_COMMAND +@item gdb.COMPLETE_COMMAND This constant means that completion should examine @value{GDBN} command names. @findex COMPLETE_SYMBOL @findex gdb.COMPLETE_SYMBOL -@item COMPLETE_SYMBOL +@item gdb.COMPLETE_SYMBOL This constant means that completion should be done using symbol names as the source. @end table @@ -22468,7 +23265,7 @@ There are many parameters that already exist and can be set in behavior in @value{GDBN}. Similarly, you can define parameters that can be used to influence behavior in custom Python scripts and commands. -@defmethod Parameter __init__ name @var{command-class} @var{parameter-class} @r{[}@var{enum-sequence}@r{]} +@defun Parameter.__init__ (name, @var{command-class}, @var{parameter-class} @r{[}, @var{enum-sequence}@r{]}) The object initializer for @code{Parameter} registers the new parameter with @value{GDBN}. This initializer is normally invoked from the subclass' own @code{__init__} method. @@ -22503,44 +23300,44 @@ of a fourth argument will cause an exception to be thrown. The help text for the new parameter is taken from the Python documentation string for the parameter's class, if there is one. If there is no documentation string, a default value is used. -@end defmethod +@end defun -@defivar Parameter set_doc +@defvar Parameter.set_doc If this attribute exists, and is a string, then its value is used as the help text for this parameter's @code{set} command. The value is examined when @code{Parameter.__init__} is invoked; subsequent changes have no effect. -@end defivar +@end defvar -@defivar Parameter show_doc +@defvar Parameter.show_doc If this attribute exists, and is a string, then its value is used as the help text for this parameter's @code{show} command. The value is examined when @code{Parameter.__init__} is invoked; subsequent changes have no effect. -@end defivar +@end defvar -@defivar Parameter value +@defvar Parameter.value The @code{value} attribute holds the underlying value of the parameter. It can be read and assigned to just as any other attribute. @value{GDBN} does validation when assignments are made. -@end defivar +@end defvar There are two methods that should be implemented in any @code{Parameter} class. These are: -@defop Operation {parameter} get_set_string self +@defun Parameter.get_set_string (self) @value{GDBN} will call this method when a @var{parameter}'s value has been changed via the @code{set} API (for example, @kbd{set foo off}). The @code{value} attribute has already been populated with the new value and may be used in output. This method must return a string. -@end defop +@end defun -@defop Operation {parameter} get_show_string self svalue +@defun Parameter.get_show_string (self, svalue) @value{GDBN} will call this method when a @var{parameter}'s @code{show} API has been invoked (for example, @kbd{show foo}). The argument @code{svalue} receives the string representation of the current value. This method must return a string. -@end defop +@end defun When a new parameter is defined, its type must be specified. The available types are represented by constants defined in the @code{gdb} @@ -22549,32 +23346,32 @@ module: @table @code @findex PARAM_BOOLEAN @findex gdb.PARAM_BOOLEAN -@item PARAM_BOOLEAN +@item gdb.PARAM_BOOLEAN The value is a plain boolean. The Python boolean values, @code{True} and @code{False} are the only valid values. @findex PARAM_AUTO_BOOLEAN @findex gdb.PARAM_AUTO_BOOLEAN -@item PARAM_AUTO_BOOLEAN +@item gdb.PARAM_AUTO_BOOLEAN The value has three possible states: true, false, and @samp{auto}. In Python, true and false are represented using boolean constants, and @samp{auto} is represented using @code{None}. @findex PARAM_UINTEGER @findex gdb.PARAM_UINTEGER -@item PARAM_UINTEGER +@item gdb.PARAM_UINTEGER The value is an unsigned integer. The value of 0 should be interpreted to mean ``unlimited''. @findex PARAM_INTEGER @findex gdb.PARAM_INTEGER -@item PARAM_INTEGER +@item gdb.PARAM_INTEGER The value is a signed integer. The value of 0 should be interpreted to mean ``unlimited''. @findex PARAM_STRING @findex gdb.PARAM_STRING -@item PARAM_STRING +@item gdb.PARAM_STRING The value is a string. When the user modifies the string, any escape sequences, such as @samp{\t}, @samp{\f}, and octal escapes, are translated into corresponding characters and encoded into the current @@ -22582,30 +23379,30 @@ host charset. @findex PARAM_STRING_NOESCAPE @findex gdb.PARAM_STRING_NOESCAPE -@item PARAM_STRING_NOESCAPE +@item gdb.PARAM_STRING_NOESCAPE The value is a string. When the user modifies the string, escapes are passed through untranslated. @findex PARAM_OPTIONAL_FILENAME @findex gdb.PARAM_OPTIONAL_FILENAME -@item PARAM_OPTIONAL_FILENAME +@item gdb.PARAM_OPTIONAL_FILENAME The value is a either a filename (a string), or @code{None}. @findex PARAM_FILENAME @findex gdb.PARAM_FILENAME -@item PARAM_FILENAME +@item gdb.PARAM_FILENAME The value is a filename. This is just like @code{PARAM_STRING_NOESCAPE}, but uses file names for completion. @findex PARAM_ZINTEGER @findex gdb.PARAM_ZINTEGER -@item PARAM_ZINTEGER +@item gdb.PARAM_ZINTEGER The value is an integer. This is like @code{PARAM_INTEGER}, except 0 is interpreted as itself. @findex PARAM_ENUM @findex gdb.PARAM_ENUM -@item PARAM_ENUM +@item gdb.PARAM_ENUM The value is a string, which must be one of a collection string constants provided when the parameter is created. @end table @@ -22622,7 +23419,7 @@ You can implement new convenience functions (@pxref{Convenience Vars}) in Python. A convenience function is an instance of a subclass of the class @code{gdb.Function}. -@defmethod Function __init__ name +@defun Function.__init__ (name) The initializer for @code{Function} registers the new function with @value{GDBN}. The argument @var{name} is the name of the function, a string. The function will be visible to the user as a convenience @@ -22631,9 +23428,9 @@ the given @var{name}. The documentation for the new function is taken from the documentation string for the new class. -@end defmethod +@end defun -@defmethod Function invoke @var{*args} +@defun Function.invoke (@var{*args}) When a convenience function is evaluated, its arguments are converted to instances of @code{gdb.Value}, and then the function's @code{invoke} method is called. Note that @value{GDBN} does not @@ -22645,7 +23442,7 @@ function can have default values for parameters without ill effect. The return value of this method is used as its value in the enclosing expression. If an ordinary Python value is returned, it is converted to a @code{gdb.Value} following the usual rules. -@end defmethod +@end defun The following code snippet shows how a trivial convenience function can be implemented in Python: @@ -22686,31 +23483,31 @@ The following progspace-related functions are available in the @code{gdb} module: @findex gdb.current_progspace -@defun current_progspace +@defun gdb.current_progspace () This function returns the program space of the currently selected inferior. @xref{Inferiors and Programs}. @end defun @findex gdb.progspaces -@defun progspaces +@defun gdb.progspaces () Return a sequence of all the progspaces currently known to @value{GDBN}. @end defun Each progspace is represented by an instance of the @code{gdb.Progspace} class. -@defivar Progspace filename +@defvar Progspace.filename The file name of the progspace as a string. -@end defivar +@end defvar -@defivar Progspace pretty_printers +@defvar Progspace.pretty_printers The @code{pretty_printers} attribute is a list of functions. It is used to look up pretty-printers. A @code{Value} is passed to each function in order; if the function returns @code{None}, then the search continues. Otherwise, the return value should be an object which is used to format the value. @xref{Pretty Printing API}, for more information. -@end defivar +@end defvar @node Objfiles In Python @subsubsection Objfiles In Python @@ -22728,7 +23525,7 @@ The following objfile-related functions are available in the @code{gdb} module: @findex gdb.current_objfile -@defun current_objfile +@defun gdb.current_objfile () When auto-loading a Python script (@pxref{Auto-loading}), @value{GDBN} sets the ``current objfile'' to the corresponding objfile. This function returns the current objfile. If there is no current objfile, @@ -22736,7 +23533,7 @@ this function returns @code{None}. @end defun @findex gdb.objfiles -@defun objfiles +@defun gdb.objfiles () Return a sequence of all the objfiles current known to @value{GDBN}. @xref{Objfiles In Python}. @end defun @@ -22744,28 +23541,28 @@ Return a sequence of all the objfiles current known to @value{GDBN}. Each objfile is represented by an instance of the @code{gdb.Objfile} class. -@defivar Objfile filename +@defvar Objfile.filename The file name of the objfile as a string. -@end defivar +@end defvar -@defivar Objfile pretty_printers +@defvar Objfile.pretty_printers The @code{pretty_printers} attribute is a list of functions. It is used to look up pretty-printers. A @code{Value} is passed to each function in order; if the function returns @code{None}, then the search continues. Otherwise, the return value should be an object which is used to format the value. @xref{Pretty Printing API}, for more information. -@end defivar +@end defvar A @code{gdb.Objfile} object has the following methods: -@defmethod Objfile is_valid +@defun Objfile.is_valid () Returns @code{True} if the @code{gdb.Objfile} object is valid, @code{False} if not. A @code{gdb.Objfile} object can become invalid if the object file it refers to is not loaded in @value{GDBN} any longer. All other @code{gdb.Objfile} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun @node Frames In Python @subsubsection Accessing inferior stack frames from Python. @@ -22789,16 +23586,16 @@ True The following frame-related functions are available in the @code{gdb} module: @findex gdb.selected_frame -@defun selected_frame +@defun gdb.selected_frame () Return the selected frame object. (@pxref{Selection,,Selecting a Frame}). @end defun @findex gdb.newest_frame -@defun newest_frame +@defun gdb.newest_frame () Return the newest frame object for the selected thread. @end defun -@defun frame_stop_reason_string reason +@defun gdb.frame_stop_reason_string (reason) Return a string explaining the reason why @value{GDBN} stopped unwinding frames, as expressed by the given @var{reason} code (an integer, see the @code{unwind_stop_reason} method further down in this section). @@ -22807,19 +23604,19 @@ frames, as expressed by the given @var{reason} code (an integer, see the A @code{gdb.Frame} object has the following methods: @table @code -@defmethod Frame is_valid +@defun Frame.is_valid () Returns true if the @code{gdb.Frame} object is valid, false if not. A frame object can become invalid if the frame it refers to doesn't exist anymore in the inferior. All @code{gdb.Frame} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun -@defmethod Frame name +@defun Frame.name () Returns the function name of the frame, or @code{None} if it can't be obtained. -@end defmethod +@end defun -@defmethod Frame type +@defun Frame.type () Returns the type of the frame. The value can be one of: @table @code @item gdb.NORMAL_FRAME @@ -22833,6 +23630,9 @@ inferior function call. A frame representing an inlined function. The function was inlined into a @code{gdb.NORMAL_FRAME} that is older than this one. +@item gdb.TAILCALL_FRAME +A frame representing a tail call. @xref{Tail Call Frames}. + @item gdb.SIGTRAMP_FRAME A signal trampoline frame. This is the frame created by the OS when it calls into a signal handler. @@ -22844,54 +23644,99 @@ A fake stack frame representing a cross-architecture call. This is like @code{gdb.NORMAL_FRAME}, but it is only used for the newest frame. @end table -@end defmethod +@end defun -@defmethod Frame unwind_stop_reason +@defun Frame.unwind_stop_reason () Return an integer representing the reason why it's not possible to find more frames toward the outermost frame. Use @code{gdb.frame_stop_reason_string} to convert the value returned by this -function to a string. -@end defmethod +function to a string. The value can be one of: + +@table @code +@item gdb.FRAME_UNWIND_NO_REASON +No particular reason (older frames should be available). + +@item gdb.FRAME_UNWIND_NULL_ID +The previous frame's analyzer returns an invalid result. + +@item gdb.FRAME_UNWIND_OUTERMOST +This frame is the outermost. + +@item gdb.FRAME_UNWIND_UNAVAILABLE +Cannot unwind further, because that would require knowing the +values of registers or memory that have not been collected. + +@item gdb.FRAME_UNWIND_INNER_ID +This frame ID looks like it ought to belong to a NEXT frame, +but we got it for a PREV frame. Normally, this is a sign of +unwinder failure. It could also indicate stack corruption. -@defmethod Frame pc +@item gdb.FRAME_UNWIND_SAME_ID +This frame has the same ID as the previous one. That means +that unwinding further would almost certainly give us another +frame with exactly the same ID, so break the chain. Normally, +this is a sign of unwinder failure. It could also indicate +stack corruption. + +@item gdb.FRAME_UNWIND_NO_SAVED_PC +The frame unwinder did not find any saved PC, but we needed +one to unwind further. + +@item gdb.FRAME_UNWIND_FIRST_ERROR +Any stop reason greater or equal to this value indicates some kind +of error. This special value facilitates writing code that tests +for errors in unwinding in a way that will work correctly even if +the list of the other values is modified in future @value{GDBN} +versions. Using it, you could write: +@smallexample +reason = gdb.selected_frame().unwind_stop_reason () +reason_str = gdb.frame_stop_reason_string (reason) +if reason >= gdb.FRAME_UNWIND_FIRST_ERROR: + print "An error occured: %s" % reason_str +@end smallexample +@end table + +@end defun + +@defun Frame.pc () Returns the frame's resume address. -@end defmethod +@end defun -@defmethod Frame block +@defun Frame.block () Return the frame's code block. @xref{Blocks In Python}. -@end defmethod +@end defun -@defmethod Frame function +@defun Frame.function () Return the symbol for the function corresponding to this frame. @xref{Symbols In Python}. -@end defmethod +@end defun -@defmethod Frame older +@defun Frame.older () Return the frame that called this frame. -@end defmethod +@end defun -@defmethod Frame newer +@defun Frame.newer () Return the frame called by this frame. -@end defmethod +@end defun -@defmethod Frame find_sal +@defun Frame.find_sal () Return the frame's symtab and line object. @xref{Symbol Tables In Python}. -@end defmethod +@end defun -@defmethod Frame read_var variable @r{[}block@r{]} +@defun Frame.read_var (variable @r{[}, block@r{]}) Return the value of @var{variable} in this frame. If the optional argument @var{block} is provided, search for the variable from that block; otherwise start at the frame's current block (which is determined by the frame's current program counter). @var{variable} must be a string or a @code{gdb.Symbol} object. @var{block} must be a @code{gdb.Block} object. -@end defmethod +@end defun -@defmethod Frame select +@defun Frame.select () Set this frame to be the selected frame. @xref{Stack, ,Examining the Stack}. -@end defmethod +@end defun @end table @node Blocks In Python @@ -22912,7 +23757,7 @@ The following block-related functions are available in the @code{gdb} module: @findex gdb.block_for_pc -@defun block_for_pc pc +@defun gdb.block_for_pc (pc) Return the @code{gdb.Block} containing the given @var{pc} value. If the block cannot be found for the @var{pc} value specified, the function will return @code{None}. @@ -22921,7 +23766,7 @@ will return @code{None}. A @code{gdb.Block} object has the following methods: @table @code -@defmethod Block is_valid +@defun Block.is_valid () Returns @code{True} if the @code{gdb.Block} object is valid, @code{False} if not. A block object can become invalid if the block it refers to doesn't exist anymore in the inferior. All other @@ -22929,30 +23774,51 @@ refers to doesn't exist anymore in the inferior. All other the time the method is called. This method is also made available to the Python iterator object that @code{gdb.Block} provides in an iteration context and via the Python @code{iter} built-in function. -@end defmethod +@end defun @end table A @code{gdb.Block} object has the following attributes: @table @code -@defivar Block start +@defvar Block.start The start address of the block. This attribute is not writable. -@end defivar +@end defvar -@defivar Block end +@defvar Block.end The end address of the block. This attribute is not writable. -@end defivar +@end defvar -@defivar Block function +@defvar Block.function The name of the block represented as a @code{gdb.Symbol}. If the block is not named, then this attribute holds @code{None}. This attribute is not writable. -@end defivar +@end defvar -@defivar Block superblock +@defvar Block.superblock The block containing this block. If this parent block does not exist, this attribute holds @code{None}. This attribute is not writable. -@end defivar +@end defvar + +@defvar Block.global_block +The global block associated with this block. This attribute is not +writable. +@end defvar + +@defvar Block.static_block +The static block associated with this block. This attribute is not +writable. +@end defvar + +@defvar Block.is_global +@code{True} if the @code{gdb.Block} object is a global block, +@code{False} if not. This attribute is not +writable. +@end defvar + +@defvar Block.is_static +@code{True} if the @code{gdb.Block} object is a static block, +@code{False} if not. This attribute is not writable. +@end defvar @end table @node Symbols In Python @@ -22970,7 +23836,7 @@ The following symbol-related functions are available in the @code{gdb} module: @findex gdb.lookup_symbol -@defun lookup_symbol name @r{[}block@r{]} @r{[}domain@r{]} +@defun gdb.lookup_symbol (name @r{[}, block @r{[}, domain@r{]]}) This function searches for a symbol by name. The search scope can be restricted to the parameters defined in the optional domain and block arguments. @@ -22994,7 +23860,7 @@ If the symbol is not found, the second element is @code{False}. @end defun @findex gdb.lookup_global_symbol -@defun lookup_global_symbol name @r{[}domain@r{]} +@defun gdb.lookup_global_symbol (name @r{[}, domain@r{]}) This function searches for a global symbol by name. The search scope can be restricted to by the domain argument. @@ -23010,60 +23876,66 @@ is not found. A @code{gdb.Symbol} object has the following attributes: @table @code -@defivar Symbol symtab +@defvar Symbol.type +The type of the symbol or @code{None} if no type is recorded. +This attribute is represented as a @code{gdb.Type} object. +@xref{Types In Python}. This attribute is not writable. +@end defvar + +@defvar Symbol.symtab The symbol table in which the symbol appears. This attribute is represented as a @code{gdb.Symtab} object. @xref{Symbol Tables In Python}. This attribute is not writable. -@end defivar +@end defvar -@defivar Symbol name +@defvar Symbol.name The name of the symbol as a string. This attribute is not writable. -@end defivar +@end defvar -@defivar Symbol linkage_name +@defvar Symbol.linkage_name The name of the symbol, as used by the linker (i.e., may be mangled). This attribute is not writable. -@end defivar +@end defvar -@defivar Symbol print_name +@defvar Symbol.print_name The name of the symbol in a form suitable for output. This is either @code{name} or @code{linkage_name}, depending on whether the user asked @value{GDBN} to display demangled or mangled names. -@end defivar +@end defvar -@defivar Symbol addr_class +@defvar Symbol.addr_class The address class of the symbol. This classifies how to find the value of a symbol. Each address class is a constant defined in the @code{gdb} module and described later in this chapter. -@end defivar +@end defvar -@defivar Symbol is_argument +@defvar Symbol.is_argument @code{True} if the symbol is an argument of a function. -@end defivar +@end defvar -@defivar Symbol is_constant +@defvar Symbol.is_constant @code{True} if the symbol is a constant. -@end defivar +@end defvar -@defivar Symbol is_function +@defvar Symbol.is_function @code{True} if the symbol is a function or a method. -@end defivar +@end defvar -@defivar Symbol is_variable +@defvar Symbol.is_variable @code{True} if the symbol is a variable. -@end defivar +@end defvar @end table A @code{gdb.Symbol} object has the following methods: @table @code -@defmethod Symbol is_valid +@defun Symbol.is_valid () Returns @code{True} if the @code{gdb.Symbol} object is valid, @code{False} if not. A @code{gdb.Symbol} object can become invalid if the symbol it refers to does not exist in @value{GDBN} any longer. All other @code{gdb.Symbol} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun @end table The available domain categories in @code{gdb.Symbol} are represented @@ -23072,35 +23944,35 @@ as constants in the @code{gdb} module: @table @code @findex SYMBOL_UNDEF_DOMAIN @findex gdb.SYMBOL_UNDEF_DOMAIN -@item SYMBOL_UNDEF_DOMAIN +@item gdb.SYMBOL_UNDEF_DOMAIN This is used when a domain has not been discovered or none of the following domains apply. This usually indicates an error either in the symbol information or in @value{GDBN}'s handling of symbols. @findex SYMBOL_VAR_DOMAIN @findex gdb.SYMBOL_VAR_DOMAIN -@item SYMBOL_VAR_DOMAIN +@item gdb.SYMBOL_VAR_DOMAIN This domain contains variables, function names, typedef names and enum type values. @findex SYMBOL_STRUCT_DOMAIN @findex gdb.SYMBOL_STRUCT_DOMAIN -@item SYMBOL_STRUCT_DOMAIN +@item gdb.SYMBOL_STRUCT_DOMAIN This domain holds struct, union and enum type names. @findex SYMBOL_LABEL_DOMAIN @findex gdb.SYMBOL_LABEL_DOMAIN -@item SYMBOL_LABEL_DOMAIN +@item gdb.SYMBOL_LABEL_DOMAIN This domain contains names of labels (for gotos). @findex SYMBOL_VARIABLES_DOMAIN @findex gdb.SYMBOL_VARIABLES_DOMAIN -@item SYMBOL_VARIABLES_DOMAIN +@item gdb.SYMBOL_VARIABLES_DOMAIN This domain holds a subset of the @code{SYMBOLS_VAR_DOMAIN}; it contains everything minus functions and types. @findex SYMBOL_FUNCTIONS_DOMAIN @findex gdb.SYMBOL_FUNCTIONS_DOMAIN -@item SYMBOL_FUNCTION_DOMAIN +@item gdb.SYMBOL_FUNCTION_DOMAIN This domain contains all functions. @findex SYMBOL_TYPES_DOMAIN @findex gdb.SYMBOL_TYPES_DOMAIN -@item SYMBOL_TYPES_DOMAIN +@item gdb.SYMBOL_TYPES_DOMAIN This domain contains all types. @end table @@ -23110,68 +23982,68 @@ as constants in the @code{gdb} module: @table @code @findex SYMBOL_LOC_UNDEF @findex gdb.SYMBOL_LOC_UNDEF -@item SYMBOL_LOC_UNDEF +@item gdb.SYMBOL_LOC_UNDEF If this is returned by address class, it indicates an error either in the symbol information or in @value{GDBN}'s handling of symbols. @findex SYMBOL_LOC_CONST @findex gdb.SYMBOL_LOC_CONST -@item SYMBOL_LOC_CONST +@item gdb.SYMBOL_LOC_CONST Value is constant int. @findex SYMBOL_LOC_STATIC @findex gdb.SYMBOL_LOC_STATIC -@item SYMBOL_LOC_STATIC +@item gdb.SYMBOL_LOC_STATIC Value is at a fixed address. @findex SYMBOL_LOC_REGISTER @findex gdb.SYMBOL_LOC_REGISTER -@item SYMBOL_LOC_REGISTER +@item gdb.SYMBOL_LOC_REGISTER Value is in a register. @findex SYMBOL_LOC_ARG @findex gdb.SYMBOL_LOC_ARG -@item SYMBOL_LOC_ARG +@item gdb.SYMBOL_LOC_ARG Value is an argument. This value is at the offset stored within the symbol inside the frame's argument list. @findex SYMBOL_LOC_REF_ARG @findex gdb.SYMBOL_LOC_REF_ARG -@item SYMBOL_LOC_REF_ARG +@item gdb.SYMBOL_LOC_REF_ARG Value address is stored in the frame's argument list. Just like @code{LOC_ARG} except that the value's address is stored at the offset, not the value itself. @findex SYMBOL_LOC_REGPARM_ADDR @findex gdb.SYMBOL_LOC_REGPARM_ADDR -@item SYMBOL_LOC_REGPARM_ADDR +@item gdb.SYMBOL_LOC_REGPARM_ADDR Value is a specified register. Just like @code{LOC_REGISTER} except the register holds the address of the argument instead of the argument itself. @findex SYMBOL_LOC_LOCAL @findex gdb.SYMBOL_LOC_LOCAL -@item SYMBOL_LOC_LOCAL +@item gdb.SYMBOL_LOC_LOCAL Value is a local variable. @findex SYMBOL_LOC_TYPEDEF @findex gdb.SYMBOL_LOC_TYPEDEF -@item SYMBOL_LOC_TYPEDEF +@item gdb.SYMBOL_LOC_TYPEDEF Value not used. Symbols in the domain @code{SYMBOL_STRUCT_DOMAIN} all have this class. @findex SYMBOL_LOC_BLOCK @findex gdb.SYMBOL_LOC_BLOCK -@item SYMBOL_LOC_BLOCK +@item gdb.SYMBOL_LOC_BLOCK Value is a block. @findex SYMBOL_LOC_CONST_BYTES @findex gdb.SYMBOL_LOC_CONST_BYTES -@item SYMBOL_LOC_CONST_BYTES +@item gdb.SYMBOL_LOC_CONST_BYTES Value is a byte-sequence. @findex SYMBOL_LOC_UNRESOLVED @findex gdb.SYMBOL_LOC_UNRESOLVED -@item SYMBOL_LOC_UNRESOLVED +@item gdb.SYMBOL_LOC_UNRESOLVED Value is at a fixed address, but the address of the variable has to be determined from the minimal symbol table whenever the variable is referenced. @findex SYMBOL_LOC_OPTIMIZED_OUT @findex gdb.SYMBOL_LOC_OPTIMIZED_OUT -@item SYMBOL_LOC_OPTIMIZED_OUT +@item gdb.SYMBOL_LOC_OPTIMIZED_OUT The value does not actually exist in the program. @findex SYMBOL_LOC_COMPUTED @findex gdb.SYMBOL_LOC_COMPUTED -@item SYMBOL_LOC_COMPUTED +@item gdb.SYMBOL_LOC_COMPUTED The value's address is a computed location. @end table @@ -23194,62 +24066,62 @@ For more information on @value{GDBN}'s symbol table management, see A @code{gdb.Symtab_and_line} object has the following attributes: @table @code -@defivar Symtab_and_line symtab +@defvar Symtab_and_line.symtab The symbol table object (@code{gdb.Symtab}) for this frame. This attribute is not writable. -@end defivar +@end defvar -@defivar Symtab_and_line pc +@defvar Symtab_and_line.pc Indicates the current program counter address. This attribute is not writable. -@end defivar +@end defvar -@defivar Symtab_and_line line +@defvar Symtab_and_line.line Indicates the current line number for this object. This attribute is not writable. -@end defivar +@end defvar @end table A @code{gdb.Symtab_and_line} object has the following methods: @table @code -@defmethod Symtab_and_line is_valid +@defun Symtab_and_line.is_valid () Returns @code{True} if the @code{gdb.Symtab_and_line} object is valid, @code{False} if not. A @code{gdb.Symtab_and_line} object can become invalid if the Symbol table and line object it refers to does not exist in @value{GDBN} any longer. All other @code{gdb.Symtab_and_line} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun @end table A @code{gdb.Symtab} object has the following attributes: @table @code -@defivar Symtab filename +@defvar Symtab.filename The symbol table's source filename. This attribute is not writable. -@end defivar +@end defvar -@defivar Symtab objfile +@defvar Symtab.objfile The symbol table's backing object file. @xref{Objfiles In Python}. This attribute is not writable. -@end defivar +@end defvar @end table A @code{gdb.Symtab} object has the following methods: @table @code -@defmethod Symtab is_valid +@defun Symtab.is_valid () Returns @code{True} if the @code{gdb.Symtab} object is valid, @code{False} if not. A @code{gdb.Symtab} object can become invalid if the symbol table it refers to does not exist in @value{GDBN} any longer. All other @code{gdb.Symtab} methods will throw an exception if it is invalid at the time the method is called. -@end defmethod +@end defun -@defmethod Symtab fullname +@defun Symtab.fullname () Return the symbol table's source absolute file name. -@end defmethod +@end defun @end table @node Breakpoints In Python @@ -23261,25 +24133,25 @@ Return the symbol table's source absolute file name. Python code can manipulate breakpoints via the @code{gdb.Breakpoint} class. -@defmethod Breakpoint __init__ spec @r{[}type@r{]} @r{[}wp_class@r{]} @r{[}internal@r{]} +@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[},internal@r{]]]}) Create a new breakpoint. @var{spec} is a string naming the location of the breakpoint, or an expression that defines a watchpoint. The contents can be any location recognized by the @code{break} command, or in the case of a watchpoint, by the @code{watch} command. The optional @var{type} denotes the breakpoint to create from the types defined later in this chapter. This argument can be -either: @code{BP_BREAKPOINT} or @code{BP_WATCHPOINT}. @var{type} -defaults to @code{BP_BREAKPOINT}. The optional @var{internal} argument +either: @code{gdb.BP_BREAKPOINT} or @code{gdb.BP_WATCHPOINT}. @var{type} +defaults to @code{gdb.BP_BREAKPOINT}. The optional @var{internal} argument allows the breakpoint to become invisible to the user. The breakpoint will neither be reported when created, nor will it be listed in the output from @code{info breakpoints} (but will be listed with the @code{maint info breakpoints} command). The optional @var{wp_class} argument defines the class of watchpoint to create, if @var{type} is -@code{BP_WATCHPOINT}. If a watchpoint class is not provided, it is -assumed to be a @var{WP_WRITE} class. -@end defmethod +@code{gdb.BP_WATCHPOINT}. If a watchpoint class is not provided, it is +assumed to be a @code{gdb.WP_WRITE} class. +@end defun -@defop Operation {gdb.Breakpoint} stop (self) +@defun Breakpoint.stop (self) The @code{gdb.Breakpoint} class can be sub-classed and, in particular, you may choose to implement the @code{stop} method. If this method is defined as a sub-class of @code{gdb.Breakpoint}, @@ -23295,6 +24167,12 @@ methods have a chance to execute at that location. In this scenario if one of the methods returns @code{True} but the others return @code{False}, the inferior will still be stopped. +You should not alter the execution state of the inferior (i.e.@:, step, +next, etc.), alter the current frame context (i.e.@:, change the current +active frame), or alter, add or delete any breakpoint. As a general +rule, you should not alter any data within @value{GDBN} or the inferior +at this time. + Example @code{stop} implementation: @smallexample @@ -23305,7 +24183,7 @@ class MyBreakpoint (gdb.Breakpoint): return True return False @end smallexample -@end defop +@end defun The available watchpoint types represented by constants are defined in the @code{gdb} module: @@ -23313,83 +24191,83 @@ The available watchpoint types represented by constants are defined in the @table @code @findex WP_READ @findex gdb.WP_READ -@item WP_READ +@item gdb.WP_READ Read only watchpoint. @findex WP_WRITE @findex gdb.WP_WRITE -@item WP_WRITE +@item gdb.WP_WRITE Write only watchpoint. @findex WP_ACCESS @findex gdb.WP_ACCESS -@item WP_ACCESS +@item gdb.WP_ACCESS Read/Write watchpoint. @end table -@defmethod Breakpoint is_valid +@defun Breakpoint.is_valid () Return @code{True} if this @code{Breakpoint} object is valid, @code{False} otherwise. A @code{Breakpoint} object can become invalid if the user deletes the breakpoint. In this case, the object still exists, but the underlying breakpoint does not. In the cases of watchpoint scope, the watchpoint remains valid even if execution of the inferior leaves the scope of that watchpoint. -@end defmethod +@end defun -@defmethod Breakpoint delete +@defun Breakpoint.delete Permanently deletes the @value{GDBN} breakpoint. This also invalidates the Python @code{Breakpoint} object. Any further access to this object's attributes or methods will raise an error. -@end defmethod +@end defun -@defivar Breakpoint enabled +@defvar Breakpoint.enabled This attribute is @code{True} if the breakpoint is enabled, and @code{False} otherwise. This attribute is writable. -@end defivar +@end defvar -@defivar Breakpoint silent +@defvar Breakpoint.silent This attribute is @code{True} if the breakpoint is silent, and @code{False} otherwise. This attribute is writable. Note that a breakpoint can also be silent if it has commands and the first command is @code{silent}. This is not reported by the @code{silent} attribute. -@end defivar +@end defvar -@defivar Breakpoint thread +@defvar Breakpoint.thread If the breakpoint is thread-specific, this attribute holds the thread id. If the breakpoint is not thread-specific, this attribute is @code{None}. This attribute is writable. -@end defivar +@end defvar -@defivar Breakpoint task +@defvar Breakpoint.task If the breakpoint is Ada task-specific, this attribute holds the Ada task id. If the breakpoint is not task-specific (or the underlying language is not Ada), this attribute is @code{None}. This attribute is writable. -@end defivar +@end defvar -@defivar Breakpoint ignore_count +@defvar Breakpoint.ignore_count This attribute holds the ignore count for the breakpoint, an integer. This attribute is writable. -@end defivar +@end defvar -@defivar Breakpoint number +@defvar Breakpoint.number This attribute holds the breakpoint's number --- the identifier used by the user to manipulate the breakpoint. This attribute is not writable. -@end defivar +@end defvar -@defivar Breakpoint type +@defvar Breakpoint.type This attribute holds the breakpoint's type --- the identifier used to determine the actual breakpoint type or use-case. This attribute is not writable. -@end defivar +@end defvar -@defivar Breakpoint visible +@defvar Breakpoint.visible This attribute tells whether the breakpoint is visible to the user when set, or when the @samp{info breakpoints} command is run. This attribute is not writable. -@end defivar +@end defvar The available types are represented by constants defined in the @code{gdb} module: @@ -23397,61 +24275,112 @@ module: @table @code @findex BP_BREAKPOINT @findex gdb.BP_BREAKPOINT -@item BP_BREAKPOINT +@item gdb.BP_BREAKPOINT Normal code breakpoint. @findex BP_WATCHPOINT @findex gdb.BP_WATCHPOINT -@item BP_WATCHPOINT +@item gdb.BP_WATCHPOINT Watchpoint breakpoint. @findex BP_HARDWARE_WATCHPOINT @findex gdb.BP_HARDWARE_WATCHPOINT -@item BP_HARDWARE_WATCHPOINT +@item gdb.BP_HARDWARE_WATCHPOINT Hardware assisted watchpoint. @findex BP_READ_WATCHPOINT @findex gdb.BP_READ_WATCHPOINT -@item BP_READ_WATCHPOINT +@item gdb.BP_READ_WATCHPOINT Hardware assisted read watchpoint. @findex BP_ACCESS_WATCHPOINT @findex gdb.BP_ACCESS_WATCHPOINT -@item BP_ACCESS_WATCHPOINT +@item gdb.BP_ACCESS_WATCHPOINT Hardware assisted access watchpoint. @end table -@defivar Breakpoint hit_count +@defvar Breakpoint.hit_count This attribute holds the hit count for the breakpoint, an integer. This attribute is writable, but currently it can only be set to zero. -@end defivar +@end defvar -@defivar Breakpoint location +@defvar Breakpoint.location This attribute holds the location of the breakpoint, as specified by the user. It is a string. If the breakpoint does not have a location (that is, it is a watchpoint) the attribute's value is @code{None}. This attribute is not writable. -@end defivar +@end defvar -@defivar Breakpoint expression +@defvar Breakpoint.expression This attribute holds a breakpoint expression, as specified by the user. It is a string. If the breakpoint does not have an expression (the breakpoint is not a watchpoint) the attribute's value is @code{None}. This attribute is not writable. -@end defivar +@end defvar -@defivar Breakpoint condition +@defvar Breakpoint.condition This attribute holds the condition of the breakpoint, as specified by the user. It is a string. If there is no condition, this attribute's value is @code{None}. This attribute is writable. -@end defivar +@end defvar -@defivar Breakpoint commands +@defvar Breakpoint.commands This attribute holds the commands attached to the breakpoint. If there are commands, this attribute's value is a string holding all the commands, separated by newlines. If there are no commands, this attribute is @code{None}. This attribute is not writable. -@end defivar +@end defvar + +@node Finish Breakpoints in Python +@subsubsection Finish Breakpoints + +@cindex python finish breakpoints +@tindex gdb.FinishBreakpoint + +A finish breakpoint is a temporary breakpoint set at the return address of +a frame, based on the @code{finish} command. @code{gdb.FinishBreakpoint} +extends @code{gdb.Breakpoint}. The underlying breakpoint will be disabled +and deleted when the execution will run out of the breakpoint scope (i.e.@: +@code{Breakpoint.stop} or @code{FinishBreakpoint.out_of_scope} triggered). +Finish breakpoints are thread specific and must be create with the right +thread selected. + +@defun FinishBreakpoint.__init__ (@r{[}frame@r{]} @r{[}, internal@r{]}) +Create a finish breakpoint at the return address of the @code{gdb.Frame} +object @var{frame}. If @var{frame} is not provided, this defaults to the +newest frame. The optional @var{internal} argument allows the breakpoint to +become invisible to the user. @xref{Breakpoints In Python}, for further +details about this argument. +@end defun + +@defun FinishBreakpoint.out_of_scope (self) +In some circumstances (e.g.@: @code{longjmp}, C@t{++} exceptions, @value{GDBN} +@code{return} command, @dots{}), a function may not properly terminate, and +thus never hit the finish breakpoint. When @value{GDBN} notices such a +situation, the @code{out_of_scope} callback will be triggered. + +You may want to sub-class @code{gdb.FinishBreakpoint} and override this +method: + +@smallexample +class MyFinishBreakpoint (gdb.FinishBreakpoint) + def stop (self): + print "normal finish" + return True + + def out_of_scope (): + print "abnormal finish" +@end smallexample +@end defun + +@defvar FinishBreakpoint.return_value +When @value{GDBN} is stopped at a finish breakpoint and the frame +used to build the @code{gdb.FinishBreakpoint} object had debug symbols, this +attribute will contain a @code{gdb.Value} object corresponding to the return +value of the function. The value will be @code{None} if the function return +type is @code{void} or if the return value was not computable. This attribute +is not writable. +@end defvar @node Lazy Strings In Python @subsubsection Python representation of lazy strings. @@ -23474,39 +24403,39 @@ wrapping a string is immediately retrieved and encoded on creation. A @code{gdb.LazyString} object has the following functions: -@defmethod LazyString value +@defun LazyString.value () Convert the @code{gdb.LazyString} to a @code{gdb.Value}. This value will point to the string in memory, but will lose all the delayed retrieval, encoding and handling that @value{GDBN} applies to a @code{gdb.LazyString}. -@end defmethod +@end defun -@defivar LazyString address +@defvar LazyString.address This attribute holds the address of the string. This attribute is not writable. -@end defivar +@end defvar -@defivar LazyString length +@defvar LazyString.length This attribute holds the length of the string in characters. If the length is -1, then the string will be fetched and encoded up to the first null of appropriate width. This attribute is not writable. -@end defivar +@end defvar -@defivar LazyString encoding +@defvar LazyString.encoding This attribute holds the encoding that will be applied to the string when the string is printed by @value{GDBN}. If the encoding is not set, or contains an empty string, then @value{GDBN} will select the most appropriate encoding when the string is printed. This attribute is not writable. -@end defivar +@end defvar -@defivar LazyString type +@defvar LazyString.type This attribute holds the type that is represented by the lazy string's type. For a lazy string this will always be a pointer type. To resolve this to the lazy string's character type, use the type's @code{target} method. @xref{Types In Python}. This attribute is not writable. -@end defivar +@end defvar @node Auto-loading @subsection Auto-loading @@ -23526,7 +24455,8 @@ command, or because the inferior has loaded a shared library), The auto-loading feature is useful for supplying application-specific debugging commands and scripts. -Auto-loading can be enabled or disabled. +Auto-loading can be enabled or disabled, +and the list of auto-loaded scripts can be printed. @table @code @kindex set auto-load-scripts @@ -23536,6 +24466,30 @@ Enable or disable the auto-loading of Python scripts. @kindex show auto-load-scripts @item show auto-load-scripts Show whether auto-loading of Python scripts is enabled or disabled. + +@kindex info auto-load-scripts +@cindex print list of auto-loaded scripts +@item info auto-load-scripts [@var{regexp}] +Print the list of all scripts that @value{GDBN} auto-loaded. + +Also printed is the list of scripts that were mentioned in +the @code{.debug_gdb_scripts} section and were not found +(@pxref{.debug_gdb_scripts section}). +This is useful because their names are not printed when @value{GDBN} +tries to load them and fails. There may be many of them, and printing +an error message for each one is problematic. + +If @var{regexp} is supplied only scripts with matching names are printed. + +Example: + +@smallexample +(gdb) info auto-load-scripts +Loaded Script +Yes py-section-script.py + full name: /tmp/py-section-script.py +Missing my-foo-pretty-printers.py +@end smallexample @end table When reading an auto-loaded file, @value{GDBN} sets the @@ -23668,11 +24622,12 @@ top of the source tree to the source search path. @subsection Python modules @cindex python modules -@value{GDBN} comes with a module to assist writing Python code. +@value{GDBN} comes with several modules to assist writing Python code. @menu * gdb.printing:: Building and registering pretty-printers. * gdb.types:: Utilities for working with types. +* gdb.prompt:: Utilities for prompt value substitution. @end menu @node gdb.printing @@ -23697,8 +24652,11 @@ Utility class for handling multiple printers, all recognized via regular expressions. @xref{Writing a Pretty-Printer}, for an example. -@item register_pretty_printer (@var{obj}, @var{printer}) +@item register_pretty_printer (@var{obj}, @var{printer}, @var{replace}=False) Register @var{printer} with the pretty-printer list of @var{obj}. +If @var{replace} is @code{True} then any existing copy of the printer +is replaced. Otherwise a @code{RuntimeError} exception is raised +if a printer with the same name already exists. @end table @node gdb.types @@ -23738,8 +24696,182 @@ Return @code{True} if @var{type}, assumed to be a type with fields @item make_enum_dict (@var{enum_type}) Return a Python @code{dictionary} type produced from @var{enum_type}. + +@item deep_items (@var{type}) +Returns a Python iterator similar to the standard +@code{gdb.Type.iteritems} method, except that the iterator returned +by @code{deep_items} will recursively traverse anonymous struct or +union fields. For example: + +@smallexample +struct A +@{ + int a; + union @{ + int b0; + int b1; + @}; +@}; +@end smallexample + +@noindent +Then in @value{GDBN}: +@smallexample +(@value{GDBP}) python import gdb.types +(@value{GDBP}) python struct_a = gdb.lookup_type("struct A") +(@value{GDBP}) python print struct_a.keys () +@{['a', '']@} +(@value{GDBP}) python print [k for k,v in gdb.types.deep_items(struct_a)] +@{['a', 'b0', 'b1']@} +@end smallexample + @end table +@node gdb.prompt +@subsubsection gdb.prompt +@cindex gdb.prompt + +This module provides a method for prompt value-substitution. + +@table @code +@item substitute_prompt (@var{string}) +Return @var{string} with escape sequences substituted by values. Some +escape sequences take arguments. You can specify arguments inside +``@{@}'' immediately following the escape sequence. + +The escape sequences you can pass to this function are: + +@table @code +@item \\ +Substitute a backslash. +@item \e +Substitute an ESC character. +@item \f +Substitute the selected frame; an argument names a frame parameter. +@item \n +Substitute a newline. +@item \p +Substitute a parameter's value; the argument names the parameter. +@item \r +Substitute a carriage return. +@item \t +Substitute the selected thread; an argument names a thread parameter. +@item \v +Substitute the version of GDB. +@item \w +Substitute the current working directory. +@item \[ +Begin a sequence of non-printing characters. These sequences are +typically used with the ESC character, and are not counted in the string +length. Example: ``\[\e[0;34m\](gdb)\[\e[0m\]'' will return a +blue-colored ``(gdb)'' prompt where the length is five. +@item \] +End a sequence of non-printing characters. +@end table + +For example: + +@smallexample +substitute_prompt (``frame: \f, + print arguments: \p@{print frame-arguments@}'') +@end smallexample + +@exdent will return the string: + +@smallexample +"frame: main, print arguments: scalars" +@end smallexample +@end table + +@node Aliases +@section Creating new spellings of existing commands +@cindex aliases for commands + +It is often useful to define alternate spellings of existing commands. +For example, if a new @value{GDBN} command defined in Python has +a long name to type, it is handy to have an abbreviated version of it +that involves less typing. + +@value{GDBN} itself uses aliases. For example @samp{s} is an alias +of the @samp{step} command even though it is otherwise an ambiguous +abbreviation of other commands like @samp{set} and @samp{show}. + +Aliases are also used to provide shortened or more common versions +of multi-word commands. For example, @value{GDBN} provides the +@samp{tty} alias of the @samp{set inferior-tty} command. + +You can define a new alias with the @samp{alias} command. + +@table @code + +@kindex alias +@item alias [-a] [--] @var{ALIAS} = @var{COMMAND} + +@end table + +@var{ALIAS} specifies the name of the new alias. +Each word of @var{ALIAS} must consist of letters, numbers, dashes and +underscores. + +@var{COMMAND} specifies the name of an existing command +that is being aliased. + +The @samp{-a} option specifies that the new alias is an abbreviation +of the command. Abbreviations are not shown in command +lists displayed by the @samp{help} command. + +The @samp{--} option specifies the end of options, +and is useful when @var{ALIAS} begins with a dash. + +Here is a simple example showing how to make an abbreviation +of a command so that there is less to type. +Suppose you were tired of typing @samp{disas}, the current +shortest unambiguous abbreviation of the @samp{disassemble} command +and you wanted an even shorter version named @samp{di}. +The following will accomplish this. + +@smallexample +(gdb) alias -a di = disas +@end smallexample + +Note that aliases are different from user-defined commands. +With a user-defined command, you also need to write documentation +for it with the @samp{document} command. +An alias automatically picks up the documentation of the existing command. + +Here is an example where we make @samp{elms} an abbreviation of +@samp{elements} in the @samp{set print elements} command. +This is to show that you can make an abbreviation of any part +of a command. + +@smallexample +(gdb) alias -a set print elms = set print elements +(gdb) alias -a show print elms = show print elements +(gdb) set p elms 20 +(gdb) show p elms +Limit on string chars or array elements to print is 200. +@end smallexample + +Note that if you are defining an alias of a @samp{set} command, +and you want to have an alias for the corresponding @samp{show} +command, then you need to define the latter separately. + +Unambiguously abbreviated commands are allowed in @var{COMMAND} and +@var{ALIAS}, just as they are normally. + +@smallexample +(gdb) alias -a set pr elms = set p ele +@end smallexample + +Finally, here is an example showing the creation of a one word +alias for a more complex command. +This creates alias @samp{spe} of the command @samp{set print elements}. + +@smallexample +(gdb) alias spe = set print elements +(gdb) spe 20 +@end smallexample + @node Interpreters @chapter Command Interpreters @cindex command interpreters @@ -24289,7 +25421,7 @@ that can control the execution and describe the state of your program. If you specify an absolute file name when prompted for the @kbd{M-x gdb} argument, then Emacs sets your current working directory to where your program resides. If you only specify the file name, then Emacs -sets your current working directory to to the directory associated +sets your current working directory to the directory associated with the previous buffer. In this case, @value{GDBN} may find your program by searching your environment's @code{PATH} variable, but on some operating systems it might not find the source. So, although the @@ -24447,6 +25579,7 @@ may repeat one or more times. * GDB/MI Breakpoint Commands:: * GDB/MI Program Context:: * GDB/MI Thread Commands:: +* GDB/MI Ada Tasking Commands:: * GDB/MI Program Execution:: * GDB/MI Stack Manipulation:: * GDB/MI Variable Objects:: @@ -25085,6 +26218,25 @@ The inferior exited. The inferior exited normally. @item signal-received A signal was received by the inferior. +@item solib-event +The inferior has stopped due to a library being loaded or unloaded. +This can only happen when @code{stop-on-solib-events} (@pxref{Files}) +is set. +@item fork +The inferior has forked. This is reported when @code{catch fork} +(@pxref{Set Catchpoints}) has been used. +@item vfork +The inferior has vforked. This is reported in when @code{catch vfork} +(@pxref{Set Catchpoints}) has been used. +@item syscall-entry +The inferior entered a system call. This is reported when @code{catch +syscall} (@pxref{Set Catchpoints}) has been used. +@item syscall-entry +The inferior returned from a system call. This is reported when +@code{catch syscall} (@pxref{Set Catchpoints}) has been used. +@item exec +The inferior called @code{exec}. This is reported when @code{catch exec} +(@pxref{Set Catchpoints}) has been used. @end table The @var{id} field identifies the thread that directly caused the stop @@ -25163,6 +26315,19 @@ thread group in whose context the library was unloaded. If the field is absent, it means the library was unloaded in the context of all present thread groups. +@item =breakpoint-created,bkpt=@{...@} +@itemx =breakpoint-modified,bkpt=@{...@} +@itemx =breakpoint-deleted,bkpt=@{...@} +Reports that a breakpoint was created, modified, or deleted, +respectively. Only user-visible breakpoints are reported to the MI +user. + +The @var{bkpt} argument is of the same form as returned by the various +breakpoint commands; @xref{GDB/MI Breakpoint Commands}. + +Note that if a breakpoint is emitted in the result record of a +command, then it will not also be emitted in an async record. + @end table @node GDB/MI Frame Information @@ -26309,6 +27474,83 @@ args=[@{name="format",value="0x8048e9c \"%*s%c %d %c\\n\""@}, (gdb) @end smallexample +@c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +@node GDB/MI Ada Tasking Commands +@section @sc{gdb/mi} Ada Tasking Commands + +@subheading The @code{-ada-task-info} Command +@findex -ada-task-info + +@subsubheading Synopsis + +@smallexample + -ada-task-info [ @var{task-id} ] +@end smallexample + +Reports information about either a specific Ada task, if the +@var{task-id} parameter is present, or about all Ada tasks. + +@subsubheading @value{GDBN} Command + +The @samp{info tasks} command prints the same information +about all Ada tasks (@pxref{Ada Tasks}). + +@subsubheading Result + +The result is a table of Ada tasks. The following columns are +defined for each Ada task: + +@table @samp +@item current +This field exists only for the current thread. It has the value @samp{*}. + +@item id +The identifier that @value{GDBN} uses to refer to the Ada task. + +@item task-id +The identifier that the target uses to refer to the Ada task. + +@item thread-id +The identifier of the thread corresponding to the Ada task. + +This field should always exist, as Ada tasks are always implemented +on top of a thread. But if @value{GDBN} cannot find this corresponding +thread for any reason, the field is omitted. + +@item parent-id +This field exists only when the task was created by another task. +In this case, it provides the ID of the parent task. + +@item priority +The base priority of the task. + +@item state +The current state of the task. For a detailed description of the +possible states, see @ref{Ada Tasks}. + +@item name +The name of the task. + +@end table + +@subsubheading Example + +@smallexample +-ada-task-info +^done,tasks=@{nr_rows="3",nr_cols="8", +hdr=[@{width="1",alignment="-1",col_name="current",colhdr=""@}, +@{width="3",alignment="1",col_name="id",colhdr="ID"@}, +@{width="9",alignment="1",col_name="task-id",colhdr="TID"@}, +@{width="4",alignment="1",col_name="thread-id",colhdr=""@}, +@{width="4",alignment="1",col_name="parent-id",colhdr="P-ID"@}, +@{width="3",alignment="1",col_name="priority",colhdr="Pri"@}, +@{width="22",alignment="-1",col_name="state",colhdr="State"@}, +@{width="1",alignment="2",col_name="name",colhdr="Name"@}], +body=[@{current="*",id="1",task-id=" 644010",thread-id="1",priority="48", +state="Child Termination Wait",name="main_task"@}]@} +(gdb) +@end smallexample + @c %%%%%%%%%%%%%%%%%%%%%%%%%%%% SECTION %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @node GDB/MI Program Execution @section @sc{gdb/mi} Program Execution @@ -27289,7 +28531,7 @@ void do_work(...) @end smallexample If a fixed variable object for the @code{state} variable is created in -this function, and we enter the recursive call, the the variable +this function, and we enter the recursive call, the variable object will report the value of @code{state} in the top-level @code{do_work} invocation. On the other hand, a floating variable object will report the value of @code{state} in the current frame. @@ -29952,21 +31194,26 @@ The current list of features is: @table @samp @item frozen-varobjs -Indicates presence of the @code{-var-set-frozen} command, as well -as possible presense of the @code{frozen} field in the output +Indicates support for the @code{-var-set-frozen} command, as well +as possible presense of the @code{frozen} field in the output of @code{-varobj-create}. @item pending-breakpoints -Indicates presence of the @option{-f} option to the @code{-break-insert} command. +Indicates support for the @option{-f} option to the @code{-break-insert} +command. @item python -Indicates presence of Python scripting support, Python-based +Indicates Python scripting support, Python-based pretty-printing commands, and possible presence of the @samp{display_hint} field in the output of @code{-var-list-children} @item thread-info -Indicates presence of the @code{-thread-info} command. +Indicates support for the @code{-thread-info} command. @item data-read-memory-bytes -Indicates presense of the @code{-data-read-memory-bytes} and the +Indicates support for the @code{-data-read-memory-bytes} and the @code{-data-write-memory-bytes} commands. - +@item breakpoint-notifications +Indicates that changes to breakpoints and breakpoints created via the +CLI will be announced via async records. +@item ada-task-info +Indicates support for the @code{-ada-task-info} command. @end table @subheading The @code{-list-target-features} Command @@ -30627,6 +31874,7 @@ out about additional code. * Declarations:: Relevant C struct declarations * Registering Code:: Steps to register code * Unregistering Code:: Steps to unregister code +* Custom Debug Info:: Emit debug information in a custom format @end menu @node Declarations @@ -30723,6 +31971,121 @@ Set @code{action_flag} to @code{JIT_UNREGISTER} and call If the JIT frees or recompiles code without unregistering it, then @value{GDBN} and the JIT will leak the memory used for the associated symbol files. +@node Custom Debug Info +@section Custom Debug Info +@cindex custom JIT debug info +@cindex JIT debug info reader + +Generating debug information in platform-native file formats (like ELF +or COFF) may be an overkill for JIT compilers; especially if all the +debug info is used for is displaying a meaningful backtrace. The +issue can be resolved by having the JIT writers decide on a debug info +format and also provide a reader that parses the debug info generated +by the JIT compiler. This section gives a brief overview on writing +such a parser. More specific details can be found in the source file +@file{gdb/jit-reader.in}, which is also installed as a header at +@file{@var{includedir}/gdb/jit-reader.h} for easy inclusion. + +The reader is implemented as a shared object (so this functionality is +not available on platforms which don't allow loading shared objects at +runtime). Two @value{GDBN} commands, @code{jit-reader-load} and +@code{jit-reader-unload} are provided, to be used to load and unload +the readers from a preconfigured directory. Once loaded, the shared +object is used the parse the debug information emitted by the JIT +compiler. + +@menu +* Using JIT Debug Info Readers:: How to use supplied readers correctly +* Writing JIT Debug Info Readers:: Creating a debug-info reader +@end menu + +@node Using JIT Debug Info Readers +@subsection Using JIT Debug Info Readers +@kindex jit-reader-load +@kindex jit-reader-unload + +Readers can be loaded and unloaded using the @code{jit-reader-load} +and @code{jit-reader-unload} commands. + +@table @code +@item jit-reader-load @var{reader-name} +Load the JIT reader named @var{reader-name}. On a UNIX system, this +will usually load @file{@var{libdir}/gdb/@var{reader-name}}, where +@var{libdir} is the system library directory, usually +@file{/usr/local/lib}. Only one reader can be active at a time; +trying to load a second reader when one is already loaded will result +in @value{GDBN} reporting an error. A new JIT reader can be loaded by +first unloading the current one using @code{jit-reader-load} and then +invoking @code{jit-reader-load}. + +@item jit-reader-unload +Unload the currently loaded JIT reader. + +@end table + +@node Writing JIT Debug Info Readers +@subsection Writing JIT Debug Info Readers +@cindex writing JIT debug info readers + +As mentioned, a reader is essentially a shared object conforming to a +certain ABI. This ABI is described in @file{jit-reader.h}. + +@file{jit-reader.h} defines the structures, macros and functions +required to write a reader. It is installed (along with +@value{GDBN}), in @file{@var{includedir}/gdb} where @var{includedir} is +the system include directory. + +Readers need to be released under a GPL compatible license. A reader +can be declared as released under such a license by placing the macro +@code{GDB_DECLARE_GPL_COMPATIBLE_READER} in a source file. + +The entry point for readers is the symbol @code{gdb_init_reader}, +which is expected to be a function with the prototype + +@findex gdb_init_reader +@smallexample +extern struct gdb_reader_funcs *gdb_init_reader (void); +@end smallexample + +@cindex @code{struct gdb_reader_funcs} + +@code{struct gdb_reader_funcs} contains a set of pointers to callback +functions. These functions are executed to read the debug info +generated by the JIT compiler (@code{read}), to unwind stack frames +(@code{unwind}) and to create canonical frame IDs +(@code{get_Frame_id}). It also has a callback that is called when the +reader is being unloaded (@code{destroy}). The struct looks like this + +@smallexample +struct gdb_reader_funcs +@{ + /* Must be set to GDB_READER_INTERFACE_VERSION. */ + int reader_version; + + /* For use by the reader. */ + void *priv_data; + + gdb_read_debug_info *read; + gdb_unwind_frame *unwind; + gdb_get_frame_id *get_frame_id; + gdb_destroy_reader *destroy; +@}; +@end smallexample + +@cindex @code{struct gdb_symbol_callbacks} +@cindex @code{struct gdb_unwind_callbacks} + +The callbacks are provided with another set of callbacks by +@value{GDBN} to do their job. For @code{read}, these callbacks are +passed in a @code{struct gdb_symbol_callbacks} and for @code{unwind} +and @code{get_frame_id}, in a @code{struct gdb_unwind_callbacks}. +@code{struct gdb_symbol_callbacks} has callbacks to create new object +files and new symbol tables inside those object files. @code{struct +gdb_unwind_callbacks} has callbacks to read registers off the current +frame and to write out the values of the registers in the previous +frame. Both have a callback (@code{target_read}) to read bytes off the +target's address space. + @node GDB Bugs @chapter Reporting Bugs in @value{GDBN} @cindex bugs in @value{GDBN} @@ -30967,31 +32330,32 @@ things without first using the debugger to find the facts. @c The readline documentation is distributed with the readline code @c and consists of the two following files: -@c rluser.texinfo -@c inc-hist.texinfo +@c rluser.texi +@c hsuser.texi @c Use -I with makeinfo to point to the appropriate directory, @c environment var TEXINPUTS with TeX. @ifclear SYSTEM_READLINE @include rluser.texi -@include inc-hist.texinfo +@include hsuser.texi @end ifclear @node In Memoriam @appendix In Memoriam -The GDB project mourns the loss of the following long-time contributors: +The @value{GDBN} project mourns the loss of the following long-time +contributors: @table @code @item Fred Fish -Fred was a long-standing contributor to GDB (1991-2006), and to Free -Software in general. Outside of GDB, he was known in the Amiga world -for his series of Fish Disks, and the GeekGadget project. +Fred was a long-standing contributor to @value{GDBN} (1991-2006), and +to Free Software in general. Outside of @value{GDBN}, he was known in +the Amiga world for his series of Fish Disks, and the GeekGadget project. @item Michael Snyder -Michael was one of the Global Maintainers of the GDB project, with -contributions recorded as early as 1996, until 2011. In addition to -his day to day participation, he was a large driving force behind -adding Reverse Debugging to GDB. +Michael was one of the Global Maintainers of the @value{GDBN} project, +with contributions recorded as early as 1996, until 2011. In addition +to his day to day participation, he was a large driving force behind +adding Reverse Debugging to @value{GDBN}. @end table Beyond their technical contributions to the project, they were also @@ -31130,7 +32494,8 @@ Remote protocol memory maps (@pxref{Memory Map Format}) @item Target descriptions (@pxref{Target Descriptions}) @item -Remote shared library lists (@pxref{Library List Format}) +Remote shared library lists (@xref{Library List Format}, +or alternatively @pxref{Library List Format for SVR4 Targets}) @item MS-Windows shared libraries (@pxref{Shared Libraries}) @item @@ -31155,7 +32520,12 @@ Sets}) require a functioning @code{iconv} implementation. If you are on a GNU system, then this is provided by the GNU C Library. Some other systems also provide a working @code{iconv}. -On systems with @code{iconv}, you can install GNU Libiconv. If you +If @value{GDBN} is using the @code{iconv} program which is installed +in a non-standard place, you will need to tell @value{GDBN} where to find it. +This is done with @option{--with-iconv-bin} which specifies the +directory that contains the @code{iconv} program. + +On systems without @code{iconv}, you can install GNU Libiconv. If you have previously installed Libiconv, you can use the @option{--with-libiconv-prefix} option to configure. @@ -31711,18 +33081,22 @@ Takes an optional file parameter. @kindex maint print raw-registers @kindex maint print cooked-registers @kindex maint print register-groups +@kindex maint print remote-registers @item maint print registers @r{[}@var{file}@r{]} @itemx maint print raw-registers @r{[}@var{file}@r{]} @itemx maint print cooked-registers @r{[}@var{file}@r{]} @itemx maint print register-groups @r{[}@var{file}@r{]} +@itemx maint print remote-registers @r{[}@var{file}@r{]} Print @value{GDBN}'s internal register data structures. The command @code{maint print raw-registers} includes the contents of -the raw register cache; the command @code{maint print cooked-registers} -includes the (cooked) value of all registers, including registers which -aren't available on the target nor visible to user; and the -command @code{maint print register-groups} includes the groups that each -register is a member of. @xref{Registers,, Registers, gdbint, +the raw register cache; the command @code{maint print +cooked-registers} includes the (cooked) value of all registers, +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. @xref{Registers,, Registers, gdbint, @value{GDBN} Internals}. These commands take an optional parameter, a file name to which to @@ -31896,13 +33270,16 @@ switch (@pxref{Mode Options}). @kindex maint time @cindex time of command execution @item maint time -Control whether to display the execution time for each command. If -set to a nonzero value, @value{GDBN} will display how much time it +Control whether to display the execution time of @value{GDBN} for each command. +If set to a nonzero value, @value{GDBN} will display how much time it took to execute each command, following the command's own output. -The time is not printed for the commands that run the target, since -there's no mechanism currently to compute how much time was spend -by @value{GDBN} and how much time was spend by the program been debugged. -it's not possibly currently +Both CPU time and wallclock time are printed. +Printing both is useful when trying to determine whether the cost is +CPU or, e.g., disk/network, latency. +Note that the CPU time printed is for @value{GDBN} only, it does not include +the execution time of the inferior because there's no mechanism currently +to compute how much time was spent by @value{GDBN} and how much time was +spent by the program been debugged. This can also be requested by invoking @value{GDBN} with the @option{--statistics} command-line switch (@pxref{Mode Options}). @@ -31955,6 +33332,7 @@ Show the current setting of the target wait timeout. * Examples:: * File-I/O Remote Protocol Extension:: * Library List Format:: +* Library List Format for SVR4 Targets:: * Memory Map Format:: * Thread List Format:: * Traceframe Info Format:: @@ -32088,9 +33466,12 @@ For any @var{command} not supported by the stub, an empty response protocol. A newer @value{GDBN} can tell if a packet is supported based on that response. -A stub is required to support the @samp{g}, @samp{G}, @samp{m}, @samp{M}, -@samp{c}, and @samp{s} @var{command}s. All other @var{command}s are -optional. +At a minimum, a stub is required to support the @samp{g} and @samp{G} +commands for register access, and the @samp{m} and @samp{M} commands +for memory access. Stubs that only control single-threaded targets +can implement run control with the @samp{c} (continue), and @samp{s} +(step) commands. Stubs that support multi-threading targets should +support the @samp{vCont} command. All other commands are optional. @node Packets @section Packets @@ -32227,6 +33608,9 @@ Reply: Continue. @var{addr} is address to resume. If @var{addr} is omitted, resume at current address. +This packet is deprecated for multi-threading support. @xref{vCont +packet}. + Reply: @xref{Stop Reply Packets}, for the reply specifications. @@ -32235,6 +33619,9 @@ Reply: Continue with signal @var{sig} (hex signal number). If @samp{;@var{addr}} is omitted, resume at same address. +This packet is deprecated for multi-threading support. @xref{vCont +packet}. + Reply: @xref{Stop Reply Packets}, for the reply specifications. @@ -32317,13 +33704,15 @@ for success for an error @end table -@item H @var{c} @var{thread-id} +@item H @var{op} @var{thread-id} @cindex @samp{H} packet Set thread for subsequent operations (@samp{m}, @samp{M}, @samp{g}, -@samp{G}, et.al.). @var{c} depends on the operation to be performed: it -should be @samp{c} for step and continue operations, @samp{g} for other -operations. The thread designator @var{thread-id} has the format and -interpretation described in @ref{thread-id syntax}. +@samp{G}, et.al.). @var{op} depends on the operation to be performed: +it should be @samp{c} for step and continue operations (note that this +is deprecated, supporting the @samp{vCont} command is a better +option), @samp{g} for other operations. The thread designator +@var{thread-id} has the format and interpretation described in +@ref{thread-id syntax}. Reply: @table @samp @@ -32463,6 +33852,9 @@ The @samp{R} packet has no reply. Single step. @var{addr} is the address at which to resume. If @var{addr} is omitted, resume at same address. +This packet is deprecated for multi-threading support. @xref{vCont +packet}. + Reply: @xref{Stop Reply Packets}, for the reply specifications. @@ -32472,6 +33864,9 @@ Reply: Step with signal. This is analogous to the @samp{C} packet, but requests a single-step, rather than a normal resumption of execution. +This packet is deprecated for multi-threading support. @xref{vCont +packet}. + Reply: @xref{Stop Reply Packets}, for the reply specifications. @@ -32528,6 +33923,7 @@ for success in non-stop mode (@pxref{Remote Non-Stop}) @item vCont@r{[};@var{action}@r{[}:@var{thread-id}@r{]]}@dots{} @cindex @samp{vCont} packet +@anchor{vCont packet} Resume the inferior, specifying different actions for each thread. If an action is specified with no @var{thread-id}, then it is applied to any threads that don't have a specific action specified; if no default action is @@ -33060,6 +34456,38 @@ An error (such as memory fault) The specified memory region's checksum is @var{crc32}. @end table +@item QDisableRandomization:@var{value} +@cindex disable address space randomization, remote request +@cindex @samp{QDisableRandomization} packet +Some target operating systems will randomize the virtual address space +of the inferior process as a security feature, but provide a feature +to disable such randomization, e.g.@: to allow for a more deterministic +debugging experience. On such systems, this packet with a @var{value} +of 1 directs the target to disable address space randomization for +processes subsequently started via @samp{vRun} packets, while a packet +with a @var{value} of 0 tells the target to enable address space +randomization. + +This packet is only available in extended mode (@pxref{extended mode}). + +Reply: +@table @samp +@item OK +The request succeeded. + +@item E @var{nn} +An error occurred. @var{nn} are hex digits. + +@item +An empty reply indicates that @samp{QDisableRandomization} is not supported +by the stub. +@end table + +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +This should only be done on targets that actually support disabling +address space randomization. + @item qfThreadInfo @itemx qsThreadInfo @cindex list active threads, remote request @@ -33106,7 +34534,7 @@ thread local variable. (This offset is obtained from the debug information associated with the variable.) @var{lm} is the (big endian, hex encoded) OS/ABI-specific encoding of the -the load module associated with the thread local storage. For example, +load module associated with the thread local storage. For example, a @sc{gnu}/Linux system will pass the link map address of the shared object associated with the thread local storage under consideration. Other operating environments may choose to represent the load module @@ -33513,6 +34941,10 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab Yes +@item @samp{qXfer:fdpic:read} +@tab No +@tab @samp{-} +@tab Yes @item @samp{QNonStop} @tab No @@ -33559,6 +34991,21 @@ These are the currently defined stub features and their properties: @tab @samp{-} @tab No +@item @samp{QDisableRandomization} +@tab No +@tab @samp{-} +@tab No + +@item @samp{EnableDisableTracepoints} +@tab No +@tab @samp{-} +@tab No + +@item @samp{tracenz} +@tab No +@tab @samp{-} +@tab No + @end multitable These are the currently defined stub features, in more detail: @@ -33587,6 +35034,10 @@ The remote stub understands the @samp{qXfer:features:read} packet The remote stub understands the @samp{qXfer:libraries:read} packet (@pxref{qXfer library list read}). +@item qXfer:libraries-svr4:read +The remote stub understands the @samp{qXfer:libraries-svr4:read} packet +(@pxref{qXfer svr4 library list read}). + @item qXfer:memory-map:read The remote stub understands the @samp{qXfer:memory-map:read} packet (@pxref{qXfer memory map read}). @@ -33619,6 +35070,10 @@ The remote stub understands the @samp{qXfer:threads:read} packet The remote stub understands the @samp{qXfer:traceframe-info:read} packet (@pxref{qXfer traceframe info read}). +@item qXfer:fdpic:read +The remote stub understands the @samp{qXfer:fdpic:read} +packet (@pxref{qXfer fdpic loadmap read}). + @item QNonStop The remote stub understands the @samp{QNonStop} packet (@pxref{QNonStop}). @@ -33667,10 +35122,27 @@ the source form of tracepoint definitions. @item QAllow The remote stub understands the @samp{QAllow} packet. +@item QDisableRandomization +The remote stub understands the @samp{QDisableRandomization} packet. + @item StaticTracepoint @cindex static tracepoints, in remote protocol The remote stub supports static tracepoints. +@item InstallInTrace +@anchor{install tracepoint in tracing} +The remote stub supports installing tracepoint in tracing. + +@item EnableDisableTracepoints +The remote stub supports the @samp{QTEnable} (@pxref{QTEnable}) and +@samp{QTDisable} (@pxref{QTDisable}) packets that allow tracepoints +to be enabled and disabled while a trace experiment is running. + +@item tracenz +@cindex string tracing, in remote protocol +The remote stub supports the @samp{tracenz} bytecode for collecting strings. +See @ref{Bytecode Descriptions} for details about the bytecode. + @end table @item qSymbol:: @@ -33719,6 +35191,8 @@ encoded). @value{GDBN} will continue to supply the values of symbols @itemx qTfP @itemx qTfV @itemx QTFrame +@itemx qTMinFTPILen + @xref{Tracepoint Packets}. @item qThreadExtraInfo,@var{thread-id} @@ -33746,11 +35220,15 @@ the command by a @samp{,}, not a @samp{:}, contrary to the naming conventions above. Please don't use this packet as a model for new packets.) +@item QTNotes +@item qTP @item QTSave @item qTsP @item qTsV @itemx QTStart @itemx QTStop +@itemx QTEnable +@itemx QTDisable @itemx QTinit @itemx QTro @itemx qTStatus @@ -33805,6 +35283,18 @@ the operating system manages the list of loaded libraries. This packet is not probed by default; the remote stub must request it, by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +@item qXfer:libraries-svr4:read:@var{annex}:@var{offset},@var{length} +@anchor{qXfer svr4 library list read} +Access the target's list of loaded libraries when the target is an SVR4 +platform. @xref{Library List Format for SVR4 Targets}. The annex part +of the generic @samp{qXfer} packet must be empty (@pxref{qXfer read}). + +This packet is optional for better performance on SVR4 targets. +@value{GDBN} uses memory read packets to read the SVR4 library list otherwise. + +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). + @item qXfer:memory-map:read::@var{offset},@var{length} @anchor{qXfer memory map read} Access the target's @dfn{memory-map}. @xref{Memory Map Format}. The @@ -33867,6 +35357,15 @@ Return a description of the current traceframe's contents. This packet is not probed by default; the remote stub must request it, by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). +@item qXfer:fdpic:read:@var{annex}:@var{offset},@var{length} +@anchor{qXfer fdpic loadmap read} +Read contents of @code{loadmap}s on the target system. The +annex, either @samp{exec} or @samp{interp}, specifies which @code{loadmap}, +executable @code{loadmap} or interpreter @code{loadmap} to read. + +This packet is not probed by default; the remote stub must request it, +by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}). + @item qXfer:osdata:read::@var{offset},@var{length} @anchor{qXfer osdata read} Access the target's @dfn{operating system information}. @@ -34231,6 +35730,30 @@ numbers. Like @samp{QTFrame:range:@var{start}:@var{end}}, but select the first frame @emph{outside} the given range of addresses (exclusive). +@item qTMinFTPILen +This packet requests the minimum length of instruction at which a fast +tracepoint (@pxref{Set Tracepoints}) may be placed. For instance, on +the 32-bit x86 architecture, it is possible to use a 4-byte jump, but +it depends on the target system being able to create trampolines in +the first 64K of memory, which might or might not be possible for that +system. So the reply to this packet will be 4 if it is able to +arrange for that. + +Replies: + +@table @samp +@item 0 +The minimum instruction length is currently unknown. +@item @var{length} +The minimum instruction length is @var{length}, where @var{length} is greater +or equal to 1. @var{length} is a hexadecimal number. A reply of 1 means +that a fast tracepoint may be placed on any instruction regardless of size. +@item E +An error has occurred. +@item +An empty reply indicates that the request is not supported by the stub. +@end table + @item QTStart Begin the tracepoint experiment. Begin collecting data from tracepoint hits in the trace frame buffer. This packet supports the @@ -34240,6 +35763,18 @@ instruction reply packet}). @item QTStop End the tracepoint experiment. Stop collecting trace frames. +@item QTEnable:@var{n}:@var{addr} +@anchor{QTEnable} +Enable tracepoint @var{n} at address @var{addr} in a started tracepoint +experiment. If the tracepoint was previously disabled, then collection +of data from it will resume. + +@item QTDisable:@var{n}:@var{addr} +@anchor{QTDisable} +Disable tracepoint @var{n} at address @var{addr} in a started tracepoint +experiment. No more data will be collected from the tracepoint unless +@samp{QTEnable:@var{n}:@var{addr}} is subsequently issued. + @item QTinit Clear the table of tracepoints, and empty the trace frame buffer. @@ -34281,8 +35816,11 @@ explanations as one of the optional fields: @item tnotrun:0 No trace has been run yet. -@item tstop:0 -The trace was stopped by a user-originated stop command. +@item tstop[:@var{text}]:0 +The trace was stopped by a user-originated stop command. The optional +@var{text} field is a user-supplied string supplied as part of the +stop command (for instance, an explanation of why the trace was +stopped manually). It is hex-encoded. @item tfull:0 The trace stopped because the trace buffer filled up. @@ -34338,6 +35876,22 @@ that the trace run will stop. @end table +@item qTP:@var{tp}:@var{addr} +@cindex tracepoint status, remote request +@cindex @samp{qTP} packet +Ask the stub for the current state of tracepoint number @var{tp} at +address @var{addr}. + +Replies: +@table @samp +@item V@var{hits}:@var{usage} +The tracepoint has been hit @var{hits} times so far during the trace +run, and accounts for @var{usage} in the trace buffer. Note that +@code{while-stepping} steps are not counted as separate hits, but the +steps' space consumption is added into the usage number. + +@end table + @item qTV:@var{var} @cindex trace state variable value, remote request @cindex @samp{qTV} packet @@ -34431,6 +35985,11 @@ available. This packet directs the target to use a circular trace buffer if @var{value} is 1, or a linear buffer if the value is 0. +@item QTNotes:@r{[}@var{type}:@var{text}@r{]}@r{[};@var{type}:@var{text}@r{]}@dots{} +This packet adds optional textual notes to the trace run. Allowable +types include @code{user}, @code{notes}, and @code{tstop}, the +@var{text} fields are arbitrary strings, hex-encoded. + @end table @subsection Relocate instruction reply packet @@ -36047,6 +37606,68 @@ In addition, segments and section descriptors cannot be mixed within a single library element, and you must supply at least one segment or section for each library. +@node Library List Format for SVR4 Targets +@section Library List Format for SVR4 Targets +@cindex library list format, remote protocol + +On SVR4 platforms @value{GDBN} can use the symbol table of a dynamic loader +(e.g.@: @file{ld.so}) and normal memory operations to maintain a list of +shared libraries. Still a special library list provided by this packet is +more efficient for the @value{GDBN} remote protocol. + +The @samp{qXfer:libraries-svr4:read} packet returns an XML document which lists +loaded libraries and their SVR4 linker parameters. For each library on SVR4 +target, the following parameters are reported: + +@itemize @minus +@item +@code{name}, the absolute file name from the @code{l_name} field of +@code{struct link_map}. +@item +@code{lm} with address of @code{struct link_map} used for TLS +(Thread Local Storage) access. +@item +@code{l_addr}, the displacement as read from the field @code{l_addr} of +@code{struct link_map}. For prelinked libraries this is not an absolute +memory address. It is a displacement of absolute memory address against +address the file was prelinked to during the library load. +@item +@code{l_ld}, which is memory address of the @code{PT_DYNAMIC} segment +@end itemize + +Additionally the single @code{main-lm} attribute specifies address of +@code{struct link_map} used for the main executable. This parameter is used +for TLS access and its presence is optional. + +@value{GDBN} must be linked with the Expat library to support XML +SVR4 library lists. @xref{Expat}. + +A simple memory map, with two loaded libraries (which do not use prelink), +looks like this: + +@smallexample + + + + +@end smallexample + +The format of an SVR4 library list is described by this DTD: + +@smallexample + + + + + + + + + +@end smallexample + @node Memory Map Format @section Memory Map Format @cindex memory map format @@ -36216,10 +37837,6 @@ The formal DTD for the traceframe info format is given below: @appendix Target Descriptions @cindex target descriptions -@strong{Warning:} target descriptions are still under active development, -and the contents and format may change between @value{GDBN} releases. -The format is expected to stabilize in the future. - One of the challenges of using @value{GDBN} to debug embedded systems is that there are so many minor variants of each processor architecture in use. It is common practice for vendors to start with @@ -36554,7 +38171,7 @@ The register's size, in bits. @item regnum The register's number. If omitted, a register's number is one greater than that of the previous register (either in the current feature or in -a preceeding feature); the first register in the target description +a preceding feature); the first register in the target description defaults to zero. This register number is used to read or write the register; e.g.@: it is used in the remote @code{p} and @code{P} packets, and registers appear in the @code{g} and @code{G} packets @@ -36676,6 +38293,7 @@ registers using the capitalization used in the description. * MIPS Features:: * M68K Features:: * PowerPC Features:: +* TIC6x Features:: @end menu @@ -36837,6 +38455,21 @@ contain registers @samp{ev0h} through @samp{ev31h}, @samp{acc}, and these to present registers @samp{ev0} through @samp{ev31} to the user. +@node TIC6x Features +@subsection TMS320C6x Features +@cindex target descriptions, TIC6x features +@cindex target descriptions, TMS320C6x features +The @samp{org.gnu.gdb.tic6x.core} feature is required for TMS320C6x +targets. It should contain registers @samp{A0} through @samp{A15}, +registers @samp{B0} through @samp{B15}, @samp{CSR} and @samp{PC}. + +The @samp{org.gnu.gdb.tic6x.gp} feature is optional. It should +contain registers @samp{A16} through @samp{A31} and @samp{B16} +through @samp{B31}. + +The @samp{org.gnu.gdb.tic6x.c6xp} feature is optional. It should +contain registers @samp{TSR}, @samp{ILC} and @samp{RILC}. + @node Operating System Information @appendix Operating System Information @cindex operating system information @@ -36942,6 +38575,139 @@ Trace state variable block. This records the 8-byte signed value Future enhancements of the trace file format may include additional types of blocks. +@node Index Section Format +@appendix @code{.gdb_index} section format +@cindex .gdb_index section format +@cindex index section format + +This section documents the index section that is created by @code{save +gdb-index} (@pxref{Index Files}). The index section is +DWARF-specific; some knowledge of DWARF is assumed in this +description. + +The mapped index file format is designed to be directly +@code{mmap}able on any architecture. In most cases, a datum is +represented using a little-endian 32-bit integer value, called an +@code{offset_type}. Big endian machines must byte-swap the values +before using them. Exceptions to this rule are noted. The data is +laid out such that alignment is always respected. + +A mapped index consists of several areas, laid out in order. + +@enumerate +@item +The file header. This is a sequence of values, of @code{offset_type} +unless otherwise noted: + +@enumerate +@item +The version number, currently 5. Versions 1, 2 and 3 are obsolete. +Version 4 differs by its hashing function. + +@item +The offset, from the start of the file, of the CU list. + +@item +The offset, from the start of the file, of the types CU list. Note +that this area can be empty, in which case this offset will be equal +to the next offset. + +@item +The offset, from the start of the file, of the address area. + +@item +The offset, from the start of the file, of the symbol table. + +@item +The offset, from the start of the file, of the constant pool. +@end enumerate + +@item +The CU list. This is a sequence of pairs of 64-bit little-endian +values, sorted by the CU offset. The first element in each pair is +the offset of a CU in the @code{.debug_info} section. The second +element in each pair is the length of that CU. References to a CU +elsewhere in the map are done using a CU index, which is just the +0-based index into this table. Note that if there are type CUs, then +conceptually CUs and type CUs form a single list for the purposes of +CU indices. + +@item +The types CU list. This is a sequence of triplets of 64-bit +little-endian values. In a triplet, the first value is the CU offset, +the second value is the type offset in the CU, and the third value is +the type signature. The types CU list is not sorted. + +@item +The address area. The address area consists of a sequence of address +entries. Each address entry has three elements: + +@enumerate +@item +The low address. This is a 64-bit little-endian value. + +@item +The high address. This is a 64-bit little-endian value. Like +@code{DW_AT_high_pc}, the value is one byte beyond the end. + +@item +The CU index. This is an @code{offset_type} value. +@end enumerate + +@item +The symbol table. This is an open-addressed hash table. The size of +the hash table is always a power of 2. + +Each slot in the hash table consists of a pair of @code{offset_type} +values. The first value is the offset of the symbol's name in the +constant pool. The second value is the offset of the CU vector in the +constant pool. + +If both values are 0, then this slot in the hash table is empty. This +is ok because while 0 is a valid constant pool index, it cannot be a +valid index for both a string and a CU vector. + +The hash value for a table entry is computed by applying an +iterative hash function to the symbol's name. Starting with an +initial value of @code{r = 0}, each (unsigned) character @samp{c} in +the string is incorporated into the hash using the formula depending on the +index version: + +@table @asis +@item Version 4 +The formula is @code{r = r * 67 + c - 113}. + +@item Version 5 +The formula is @code{r = r * 67 + tolower (c) - 113}. +@end table + +The terminating @samp{\0} is not incorporated into the hash. + +The step size used in the hash table is computed via +@code{((hash * 17) & (size - 1)) | 1}, where @samp{hash} is the hash +value, and @samp{size} is the size of the hash table. The step size +is used to find the next candidate slot when handling a hash +collision. + +The names of C@t{++} symbols in the hash table are canonicalized. We +don't currently have a simple description of the canonicalization +algorithm; if you intend to create new index sections, you must read +the code. + +@item +The constant pool. This is simply a bunch of bytes. It is organized +so that alignment is correct: CU vectors are stored first, followed by +strings. + +A CU vector in the constant pool is a sequence of @code{offset_type} +values. The first value is the number of CU indices in the vector. +Each subsequent value is the index of a CU in the CU list. This +element in the hash table is used to indicate which CUs define the +symbol. + +A string in the constant pool is zero-terminated. +@end enumerate + @include gpl.texi @node GNU Free Documentation License diff --git a/contrib/gdb-7/gdb/doc/gdbint.texinfo b/contrib/gdb-7/gdb/doc/gdbint.texinfo index a49470708f..1845124bc9 100644 --- a/contrib/gdb-7/gdb/doc/gdbint.texinfo +++ b/contrib/gdb-7/gdb/doc/gdbint.texinfo @@ -9,9 +9,8 @@ @end direntry @copying -Copyright @copyright{} 1990, 1991, 1992, 1993, 1994, 1996, 1998, 1999, -2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 -Free Software Foundation, Inc. +Copyright @copyright{} 1990-1994, 1996, 1998-2006, 2008-2012 Free +Software Foundation, Inc. Contributed by Cygnus Solutions. Written by John Gilmore. Second Edition by Stan Shebs. @@ -3607,7 +3606,7 @@ register should be printed. Define a custom version of this function for fuller control over how the registers are displayed. The access should be for the specified architecture, @var{gdbarch}, -with output to the the file specified by the User Interface +with output to the file specified by the User Interface Independent Output file handle, @var{file} (@pxref{UI-Independent Output, , UI-Independent Output---the @code{ui_out} Functions}). diff --git a/contrib/gdb-7/gdb/doc/observer.texi b/contrib/gdb-7/gdb/doc/observer.texi index d16c865335..24233cbeb4 100644 --- a/contrib/gdb-7/gdb/doc/observer.texi +++ b/contrib/gdb-7/gdb/doc/observer.texi @@ -2,8 +2,7 @@ @c This file is part of the GDB manual. @c -@c Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 -@c Free Software Foundation, Inc. +@c Copyright (C) 2003-2006, 2008-2012 Free Software Foundation, Inc. @c @c See the file gdbint.texinfo for copying conditions. @c @@ -159,19 +158,18 @@ thread was resume, and may be RESUME_ALL if all threads are resumed. The target is about to be proceeded. @end deftypefun -@deftypefun void breakpoint_created (int @var{bpnum}) -A new breakpoint has been created. The argument @var{bpnum} is the -number of the newly-created breakpoint. +@deftypefun void breakpoint_created (struct breakpoint *@var{b}) +A new breakpoint @var{b} has been created. @end deftypefun -@deftypefun void breakpoint_deleted (int @var{bpnum}) -A breakpoint has been destroyed. The argument @var{bpnum} is the -number of the newly-destroyed breakpoint. +@deftypefun void breakpoint_deleted (struct breakpoint *@var{b}) +A breakpoint has been destroyed. The argument @var{b} is the +pointer to the destroyed breakpoint. @end deftypefun -@deftypefun void breakpoint_modified (int @var{bpnum}) -A breakpoint has been modified in some way. The argument @var{bpnum} -is the number of the modified breakpoint. +@deftypefun void breakpoint_modified (struct breakpoint *@var{b}) +A breakpoint has been modified in some way. The argument @var{b} +is the modified breakpoint. @end deftypefun @deftypefun void tracepoint_created (int @var{tpnum}) @@ -223,6 +221,11 @@ Bytes from @var{data} to @var{data} + @var{len} have been written to the current inferior at @var{addr}. @end deftypefun +@deftypefun void before_prompt (const char *@var{current_prompt}) +Called before a top-level prompt is displayed. @var{current_prompt} is +the current top-level prompt. +@end deftypefun + @deftypefun void test_notification (int @var{somearg}) This observer is used for internal testing. Do not use. See testsuite/gdb.gdb/observer.exp. diff --git a/contrib/gdb-7/gdb/doc/stabs.texinfo b/contrib/gdb-7/gdb/doc/stabs.texinfo index 732a170d40..f5a61eb379 100644 --- a/contrib/gdb-7/gdb/doc/stabs.texinfo +++ b/contrib/gdb-7/gdb/doc/stabs.texinfo @@ -13,9 +13,8 @@ @end direntry @copying -Copyright @copyright{} 1992, 1993, 1994, 1995, 1997, 1998, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 -Free Software Foundation, Inc. +Copyright @copyright{} 1992-1995, 1997-1998, 2000-2007, 2009-2012 Free +Software Foundation, Inc. Contributed by Cygnus Support. Written by Julia Menapace, Jim Kingdon, and David MacKenzie. diff --git a/contrib/gdb-7/gdb/doublest.c b/contrib/gdb-7/gdb/doublest.c index a339887f8e..c8c9e05932 100644 --- a/contrib/gdb-7/gdb/doublest.c +++ b/contrib/gdb-7/gdb/doublest.c @@ -1,8 +1,7 @@ /* Floating point routines for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-2001, 2003-2005, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -274,10 +273,6 @@ convert_floatformat_to_doublest (const struct floatformat *fmt, *to = dto; } -static void put_field (unsigned char *, enum floatformat_byteorders, - unsigned int, - unsigned int, unsigned int, unsigned long); - /* Set a field which starts at START and is LEN bytes long. DATA and TOTAL_LEN are the thing we are extracting it from, in byteorder ORDER. */ static void @@ -449,7 +444,7 @@ convert_doublest_to_floatformat (CONST struct floatformat *fmt, fmt->exp_len, fmt->exp_nan); /* Be sure it's not infinity, but NaN value is irrel. */ put_field (uto, order, fmt->totalsize, fmt->man_start, - 32, 1); + fmt->man_len, 1); goto finalize_byteorder; } diff --git a/contrib/gdb-7/gdb/doublest.h b/contrib/gdb-7/gdb/doublest.h index 8a3f25dc79..cb22d62191 100644 --- a/contrib/gdb-7/gdb/doublest.h +++ b/contrib/gdb-7/gdb/doublest.h @@ -1,8 +1,7 @@ /* Floating point definitions for GDB. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-2001, 2003, 2005-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/dummy-frame.c b/contrib/gdb-7/gdb/dummy-frame.c index 709cd68495..4a42a76b25 100644 --- a/contrib/gdb-7/gdb/dummy-frame.c +++ b/contrib/gdb-7/gdb/dummy-frame.c @@ -1,8 +1,6 @@ /* Code dealing with dummy stack frames, for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -261,7 +259,7 @@ dummy_frame_prev_register (struct frame_info *this_frame, /* Assuming that THIS_FRAME is a dummy, return its ID. That ID is determined by examining the NEXT frame's unwound registers using the method dummy_id(). As a side effect, THIS dummy frame's - dummy cache is located and and saved in THIS_PROLOGUE_CACHE. */ + dummy cache is located and saved in THIS_PROLOGUE_CACHE. */ static void dummy_frame_this_id (struct frame_info *this_frame, diff --git a/contrib/gdb-7/gdb/dummy-frame.h b/contrib/gdb-7/gdb/dummy-frame.h index dd14a7b7a7..a921e92bd5 100644 --- a/contrib/gdb-7/gdb/dummy-frame.h +++ b/contrib/gdb-7/gdb/dummy-frame.h @@ -1,7 +1,6 @@ /* Code dealing with dummy stack frames, for GDB, the GNU debugger. - Copyright (C) 2002, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/dwarf2-frame-tailcall.c b/contrib/gdb-7/gdb/dwarf2-frame-tailcall.c new file mode 100644 index 0000000000..912cdf4ac9 --- /dev/null +++ b/contrib/gdb-7/gdb/dwarf2-frame-tailcall.c @@ -0,0 +1,477 @@ +/* Virtual tail call frames unwinder for GDB. + + Copyright (C) 2010-2012 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 . */ + +#include "defs.h" +#include "gdb_assert.h" +#include "frame.h" +#include "dwarf2-frame-tailcall.h" +#include "dwarf2loc.h" +#include "frame-unwind.h" +#include "block.h" +#include "hashtab.h" +#include "exceptions.h" +#include "gdbtypes.h" +#include "regcache.h" +#include "value.h" +#include "dwarf2-frame.h" + +/* Contains struct tailcall_cache indexed by next_bottom_frame. */ +static htab_t cache_htab; + +/* Associate structure of the unwinder to call_site_chain. Lifetime of this + structure is maintained by REFC decremented by dealloc_cache, all of them + get deleted during reinit_frame_cache. */ +struct tailcall_cache +{ + /* It must be the first one of this struct. It is the furthest callee. */ + struct frame_info *next_bottom_frame; + + /* Reference count. The whole chain of virtual tail call frames shares one + tailcall_cache. */ + int refc; + + /* Associated found virtual taill call frames chain, it is never NULL. */ + struct call_site_chain *chain; + + /* Cached pretended_chain_levels result. */ + int chain_levels; + + /* Unwound PC from the top (caller) frame, as it is not contained + in CHAIN. */ + CORE_ADDR prev_pc; + + /* Compensate SP in caller frames appropriately. prev_sp and + entry_cfa_sp_offset are valid only if PREV_SP_P. PREV_SP is SP at the top + (caller) frame. ENTRY_CFA_SP_OFFSET is shift of SP in tail call frames + against next_bottom_frame SP. */ + unsigned prev_sp_p : 1; + CORE_ADDR prev_sp; + LONGEST entry_cfa_sp_offset; +}; + +/* hash_f for htab_create_alloc of cache_htab. */ + +static hashval_t +cache_hash (const void *arg) +{ + const struct tailcall_cache *cache = arg; + + return htab_hash_pointer (cache->next_bottom_frame); +} + +/* eq_f for htab_create_alloc of cache_htab. */ + +static int +cache_eq (const void *arg1, const void *arg2) +{ + const struct tailcall_cache *cache1 = arg1; + const struct tailcall_cache *cache2 = arg2; + + return cache1->next_bottom_frame == cache2->next_bottom_frame; +} + +/* Create new tailcall_cache for NEXT_BOTTOM_FRAME, NEXT_BOTTOM_FRAME must not + yet have been indexed by cache_htab. Caller holds one reference of the new + tailcall_cache. */ + +static struct tailcall_cache * +cache_new_ref1 (struct frame_info *next_bottom_frame) +{ + struct tailcall_cache *cache; + void **slot; + + cache = xzalloc (sizeof (*cache)); + + cache->next_bottom_frame = next_bottom_frame; + cache->refc = 1; + + slot = htab_find_slot (cache_htab, cache, INSERT); + gdb_assert (*slot == NULL); + *slot = cache; + + return cache; +} + +/* Create new reference to CACHE. */ + +static void +cache_ref (struct tailcall_cache *cache) +{ + gdb_assert (cache->refc > 0); + + cache->refc++; +} + +/* Drop reference to CACHE, possibly fully freeing it and unregistering it from + cache_htab. */ + +static void +cache_unref (struct tailcall_cache *cache) +{ + gdb_assert (cache->refc > 0); + + if (!--cache->refc) + { + gdb_assert (htab_find_slot (cache_htab, cache, NO_INSERT) != NULL); + htab_remove_elt (cache_htab, cache); + + xfree (cache->chain); + xfree (cache); + } +} + +/* Return 1 if FI is a non-bottom (not the callee) tail call frame. Otherwise + return 0. */ + +static int +frame_is_tailcall (struct frame_info *fi) +{ + return frame_unwinder_is (fi, &dwarf2_tailcall_frame_unwind); +} + +/* Try to find tailcall_cache in cache_htab if FI is a part of its virtual tail + call chain. Otherwise return NULL. No new reference is created. */ + +static struct tailcall_cache * +cache_find (struct frame_info *fi) +{ + struct tailcall_cache *cache; + void **slot; + + while (frame_is_tailcall (fi)) + { + fi = get_next_frame (fi); + gdb_assert (fi != NULL); + } + + slot = htab_find_slot (cache_htab, &fi, NO_INSERT); + if (slot == NULL) + return NULL; + + cache = *slot; + gdb_assert (cache != NULL); + return cache; +} + +/* Number of virtual frames between THIS_FRAME and CACHE->NEXT_BOTTOM_FRAME. + If THIS_FRAME is CACHE-> NEXT_BOTTOM_FRAME return -1. */ + +static int +existing_next_levels (struct frame_info *this_frame, + struct tailcall_cache *cache) +{ + int retval = (frame_relative_level (this_frame) + - frame_relative_level (cache->next_bottom_frame) - 1); + + gdb_assert (retval >= -1); + + return retval; +} + +/* The number of virtual tail call frames in CHAIN. With no virtual tail call + frames the function would return 0 (but CHAIN does not exist in such + case). */ + +static int +pretended_chain_levels (struct call_site_chain *chain) +{ + int chain_levels; + + gdb_assert (chain != NULL); + + if (chain->callers == chain->length && chain->callees == chain->length) + return chain->length; + + chain_levels = chain->callers + chain->callees; + gdb_assert (chain_levels < chain->length); + + return chain_levels; +} + +/* Implementation of frame_this_id_ftype. THIS_CACHE must be already + initialized with tailcall_cache, THIS_FRAME must be a part of THIS_CACHE. + + Specific virtual tail call frames are tracked by INLINE_DEPTH. */ + +static void +tailcall_frame_this_id (struct frame_info *this_frame, void **this_cache, + struct frame_id *this_id) +{ + struct tailcall_cache *cache = *this_cache; + struct frame_info *next_frame; + + /* Tail call does not make sense for a sentinel frame. */ + next_frame = get_next_frame (this_frame); + gdb_assert (next_frame != NULL); + + *this_id = get_frame_id (next_frame); + (*this_id).code_addr = get_frame_pc (this_frame); + (*this_id).code_addr_p = 1; + (*this_id).inline_depth = (cache->chain_levels + - existing_next_levels (this_frame, cache)); + gdb_assert ((*this_id).inline_depth > 0); +} + +/* Find PC to be unwound from THIS_FRAME. THIS_FRAME must be a part of + CACHE. */ + +static CORE_ADDR +pretend_pc (struct frame_info *this_frame, struct tailcall_cache *cache) +{ + int next_levels = existing_next_levels (this_frame, cache); + struct call_site_chain *chain = cache->chain; + int caller_no; + + gdb_assert (chain != NULL); + + next_levels++; + gdb_assert (next_levels >= 0); + + if (next_levels < chain->callees) + return chain->call_site[chain->length - next_levels - 1]->pc; + next_levels -= chain->callees; + + /* Otherwise CHAIN->CALLEES are already covered by CHAIN->CALLERS. */ + if (chain->callees != chain->length) + { + if (next_levels < chain->callers) + return chain->call_site[chain->callers - next_levels - 1]->pc; + next_levels -= chain->callers; + } + + gdb_assert (next_levels == 0); + return cache->prev_pc; +} + +/* Implementation of frame_prev_register_ftype. If no specific register + override is supplied NULL is returned (this is incompatible with + frame_prev_register_ftype semantics). next_bottom_frame and tail call + frames unwind the NULL case differently. */ + +struct value * +dwarf2_tailcall_prev_register_first (struct frame_info *this_frame, + void **tailcall_cachep, int regnum) +{ + struct gdbarch *this_gdbarch = get_frame_arch (this_frame); + struct tailcall_cache *cache = *tailcall_cachep; + CORE_ADDR addr; + + if (regnum == gdbarch_pc_regnum (this_gdbarch)) + addr = pretend_pc (this_frame, cache); + else if (cache->prev_sp_p && regnum == gdbarch_sp_regnum (this_gdbarch)) + { + int next_levels = existing_next_levels (this_frame, cache); + + if (next_levels == cache->chain_levels - 1) + addr = cache->prev_sp; + else + addr = dwarf2_frame_cfa (this_frame) - cache->entry_cfa_sp_offset; + } + else + return NULL; + + return frame_unwind_got_address (this_frame, regnum, addr); +} + +/* Implementation of frame_prev_register_ftype for tail call frames. Register + set of virtual tail call frames is assumed to be the one of the top (caller) + frame - assume unchanged register value for NULL from + dwarf2_tailcall_prev_register_first. */ + +static struct value * +tailcall_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + struct tailcall_cache *cache = *this_cache; + struct value *val; + + gdb_assert (this_frame != cache->next_bottom_frame); + + val = dwarf2_tailcall_prev_register_first (this_frame, this_cache, regnum); + if (val) + return val; + + return frame_unwind_got_register (this_frame, regnum, regnum); +} + +/* Implementation of frame_sniffer_ftype. It will never find a new chain, use + dwarf2_tailcall_sniffer_first for the bottom (callee) frame. It will find + all the predecessing virtual tail call frames, it will return false when + there exist no more tail call frames in this chain. */ + +static int +tailcall_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, void **this_cache) +{ + struct frame_info *next_frame; + int next_levels; + struct tailcall_cache *cache; + + /* Inner tail call element does not make sense for a sentinel frame. */ + next_frame = get_next_frame (this_frame); + if (next_frame == NULL) + return 0; + + cache = cache_find (next_frame); + if (cache == NULL) + return 0; + + cache_ref (cache); + + next_levels = existing_next_levels (this_frame, cache); + + /* NEXT_LEVELS is -1 only in dwarf2_tailcall_sniffer_first. */ + gdb_assert (next_levels >= 0); + gdb_assert (next_levels <= cache->chain_levels); + + if (next_levels == cache->chain_levels) + { + cache_unref (cache); + return 0; + } + + *this_cache = cache; + return 1; +} + +/* The initial "sniffer" whether THIS_FRAME is a bottom (callee) frame of a new + chain to create. Keep TAILCALL_CACHEP NULL if it did not find any chain, + initialize it otherwise. No tail call chain is created if there are no + unambiguous virtual tail call frames to report. + + ENTRY_CFA_SP_OFFSETP is NULL if no special SP handling is possible, + otherwise *ENTRY_CFA_SP_OFFSETP is the number of bytes to subtract from tail + call frames frame base to get the SP value there - to simulate return + address pushed on the stack. */ + +void +dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, + void **tailcall_cachep, + const LONGEST *entry_cfa_sp_offsetp) +{ + CORE_ADDR prev_pc = 0, prev_sp = 0; /* GCC warning. */ + int prev_sp_p = 0; + CORE_ADDR this_pc, pc; + struct gdbarch *prev_gdbarch; + struct call_site_chain *chain = NULL; + struct frame_info *fi; + struct tailcall_cache *cache; + volatile struct gdb_exception except; + + gdb_assert (*tailcall_cachep == NULL); + + this_pc = get_frame_pc (this_frame); + + /* Catch any unwinding errors. */ + TRY_CATCH (except, RETURN_MASK_ERROR) + { + int sp_regnum; + + prev_gdbarch = frame_unwind_arch (this_frame); + + /* Simulate frame_unwind_pc without setting this_frame->prev_pc.p. */ + prev_pc = gdbarch_unwind_pc (prev_gdbarch, this_frame); + + /* call_site_find_chain can throw an exception. */ + chain = call_site_find_chain (prev_gdbarch, prev_pc, this_pc); + + if (entry_cfa_sp_offsetp == NULL) + break; + sp_regnum = gdbarch_sp_regnum (prev_gdbarch); + if (sp_regnum == -1) + break; + prev_sp = frame_unwind_register_unsigned (this_frame, sp_regnum); + prev_sp_p = 1; + } + if (except.reason < 0) + { + if (entry_values_debug) + exception_print (gdb_stdout, except); + return; + } + + /* Ambiguous unwind or unambiguous unwind verified as matching. */ + if (chain == NULL || chain->length == 0) + { + xfree (chain); + return; + } + + cache = cache_new_ref1 (this_frame); + *tailcall_cachep = cache; + cache->chain = chain; + cache->prev_pc = prev_pc; + cache->chain_levels = pretended_chain_levels (chain); + cache->prev_sp_p = prev_sp_p; + if (cache->prev_sp_p) + { + cache->prev_sp = prev_sp; + cache->entry_cfa_sp_offset = *entry_cfa_sp_offsetp; + } + gdb_assert (cache->chain_levels > 0); +} + +/* Implementation of frame_dealloc_cache_ftype. It can be called even for the + bottom chain frame from dwarf2_frame_dealloc_cache which is not a real + TAILCALL_FRAME. */ + +static void +tailcall_frame_dealloc_cache (struct frame_info *self, void *this_cache) +{ + struct tailcall_cache *cache = this_cache; + + cache_unref (cache); +} + +/* Implementation of frame_prev_arch_ftype. We assume all the virtual tail + call frames have gdbarch of the bottom (callee) frame. */ + +static struct gdbarch * +tailcall_frame_prev_arch (struct frame_info *this_frame, + void **this_prologue_cache) +{ + struct tailcall_cache *cache = *this_prologue_cache; + + return get_frame_arch (cache->next_bottom_frame); +} + +/* Virtual tail call frame unwinder if dwarf2_tailcall_sniffer_first finds + a chain to create. */ + +const struct frame_unwind dwarf2_tailcall_frame_unwind = +{ + TAILCALL_FRAME, + default_frame_unwind_stop_reason, + tailcall_frame_this_id, + tailcall_frame_prev_register, + NULL, + tailcall_frame_sniffer, + tailcall_frame_dealloc_cache, + tailcall_frame_prev_arch +}; + +/* Provide a prototype to silence -Wmissing-prototypes. */ +extern initialize_file_ftype _initialize_tailcall_frame; + +void +_initialize_tailcall_frame (void) +{ + cache_htab = htab_create_alloc (50, cache_hash, cache_eq, NULL, xcalloc, + xfree); +} diff --git a/contrib/gdb-7/gdb/tui/tui-stack.h b/contrib/gdb-7/gdb/dwarf2-frame-tailcall.h similarity index 52% copy from contrib/gdb-7/gdb/tui/tui-stack.h copy to contrib/gdb-7/gdb/dwarf2-frame-tailcall.h index 00911589f6..c5c88045f7 100644 --- a/contrib/gdb-7/gdb/tui/tui-stack.h +++ b/contrib/gdb-7/gdb/dwarf2-frame-tailcall.h @@ -1,9 +1,6 @@ -/* TUI display locator. +/* Definitions for virtual tail call frames unwinder for GDB. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. - - Contributed by Hewlett-Packard Company. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -20,13 +17,23 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef TUI_STACK_H -#define TUI_STACK_H +#ifndef DWARF2_FRAME_TAILCALL_H +#define DWARF2_FRAME_TAILCALL_H 1 struct frame_info; +struct frame_unwind; + +/* The tail call frame unwinder. */ + +extern void + dwarf2_tailcall_sniffer_first (struct frame_info *this_frame, + void **tailcall_cachep, + const LONGEST *entry_cfa_sp_offsetp); + +extern struct value * + dwarf2_tailcall_prev_register_first (struct frame_info *this_frame, + void **tailcall_cachep, int regnum); -extern void tui_update_locator_filename (const char *); -extern void tui_show_locator_content (void); -extern void tui_show_frame_info (struct frame_info *); +extern const struct frame_unwind dwarf2_tailcall_frame_unwind; -#endif +#endif /* !DWARF2_FRAME_TAILCALL_H */ diff --git a/contrib/gdb-7/gdb/dwarf2-frame.c b/contrib/gdb-7/gdb/dwarf2-frame.c index e78c3284ad..88aa338919 100644 --- a/contrib/gdb-7/gdb/dwarf2-frame.c +++ b/contrib/gdb-7/gdb/dwarf2-frame.c @@ -1,7 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2005, 2007-2012 Free Software Foundation, Inc. Contributed by Mark Kettenis. @@ -41,6 +40,7 @@ #include "ax.h" #include "dwarf2loc.h" #include "exceptions.h" +#include "dwarf2-frame-tailcall.h" struct comp_unit; @@ -312,47 +312,6 @@ read_mem (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t len) read_memory (addr, buf, len); } -static void -no_get_frame_base (void *baton, const gdb_byte **start, size_t *length) -{ - internal_error (__FILE__, __LINE__, - _("Support for DW_OP_fbreg is unimplemented")); -} - -/* Helper function for execute_stack_op. */ - -static CORE_ADDR -no_get_frame_cfa (void *baton) -{ - internal_error (__FILE__, __LINE__, - _("Support for DW_OP_call_frame_cfa is unimplemented")); -} - -/* Helper function for execute_stack_op. */ - -static CORE_ADDR -no_get_frame_pc (void *baton) -{ - internal_error (__FILE__, __LINE__, _("\ -Support for DW_OP_GNU_implicit_pointer is unimplemented")); -} - -static CORE_ADDR -no_get_tls_address (void *baton, CORE_ADDR offset) -{ - internal_error (__FILE__, __LINE__, _("\ -Support for DW_OP_GNU_push_tls_address is unimplemented")); -} - -/* Helper function for execute_stack_op. */ - -static void -no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) -{ - internal_error (__FILE__, __LINE__, - _("Support for DW_OP_call* is invalid in CFI")); -} - /* Execute the required actions for both the DW_CFA_restore and DW_CFA_restore_extended instructions. */ static void @@ -383,6 +342,21 @@ register %s (#%d) at %s"), paddress (gdbarch, fs->pc)); } +/* Virtual method table for execute_stack_op below. */ + +static const struct dwarf_expr_context_funcs dwarf2_frame_ctx_funcs = +{ + read_reg, + read_mem, + ctx_no_get_frame_base, + ctx_no_get_frame_cfa, + ctx_no_get_frame_pc, + ctx_no_get_tls_address, + ctx_no_dwarf_call, + ctx_no_get_base_type, + ctx_no_push_dwarf_reg_entry_value +}; + static CORE_ADDR execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, CORE_ADDR offset, struct frame_info *this_frame, @@ -394,26 +368,22 @@ execute_stack_op (const gdb_byte *exp, ULONGEST len, int addr_size, ctx = new_dwarf_expr_context (); old_chain = make_cleanup_free_dwarf_expr_context (ctx); + make_cleanup_value_free_to_mark (value_mark ()); ctx->gdbarch = get_frame_arch (this_frame); ctx->addr_size = addr_size; + ctx->ref_addr_size = -1; ctx->offset = offset; ctx->baton = this_frame; - ctx->read_reg = read_reg; - ctx->read_mem = read_mem; - ctx->get_frame_base = no_get_frame_base; - ctx->get_frame_cfa = no_get_frame_cfa; - ctx->get_frame_pc = no_get_frame_pc; - ctx->get_tls_address = no_get_tls_address; - ctx->dwarf_call = no_dwarf_call; - - dwarf_expr_push (ctx, initial, initial_in_stack_memory); + ctx->funcs = &dwarf2_frame_ctx_funcs; + + dwarf_expr_push_address (ctx, initial, initial_in_stack_memory); dwarf_expr_eval (ctx, exp, len); if (ctx->location == DWARF_VALUE_MEMORY) result = dwarf_expr_fetch_address (ctx, 0); else if (ctx->location == DWARF_VALUE_REGISTER) - result = read_reg (this_frame, dwarf_expr_fetch (ctx, 0)); + result = read_reg (this_frame, value_as_long (dwarf_expr_fetch (ctx, 0))); else { /* This is actually invalid DWARF, but if we ever do run across @@ -429,7 +399,11 @@ Not implemented: computing unwound register using explicit value operator")); } -static void +/* Execute FDE program from INSN_PTR possibly up to INSN_END or up to inferior + PC. Modify FS state accordingly. Return current INSN_PTR where the + execution has stopped, one can resume it on the next call. */ + +static const gdb_byte * execute_cfa_program (struct dwarf2_fde *fde, const gdb_byte *insn_ptr, const gdb_byte *insn_end, struct gdbarch *gdbarch, CORE_ADDR pc, struct dwarf2_frame_state *fs) @@ -712,9 +686,14 @@ bad CFI data; mismatched DW_CFA_restore_state at %s"), } } - /* Don't allow remember/restore between CIE and FDE programs. */ - dwarf2_frame_state_free_regs (fs->regs.prev); - fs->regs.prev = NULL; + if (fs->initial.reg == NULL) + { + /* Don't allow remember/restore between CIE and FDE programs. */ + dwarf2_frame_state_free_regs (fs->regs.prev); + fs->regs.prev = NULL; + } + + return insn_ptr; } @@ -1006,6 +985,13 @@ struct dwarf2_frame_cache /* The .text offset. */ CORE_ADDR text_offset; + + /* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME + sequence. If NULL then it is a normal case with no TAILCALL_FRAME + involved. Non-bottom frames of a virtual tail call frames chain use + dwarf2_tailcall_frame_unwind unwinder so this field does not apply for + them. */ + void *tailcall_cache; }; static struct dwarf2_frame_cache * @@ -1019,6 +1005,10 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) struct dwarf2_frame_state *fs; struct dwarf2_fde *fde; volatile struct gdb_exception ex; + CORE_ADDR entry_pc; + LONGEST entry_cfa_sp_offset; + int entry_cfa_sp_offset_p = 0; + const gdb_byte *instr; if (*this_cache) return *this_cache; @@ -1070,8 +1060,25 @@ dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache) fs->initial = fs->regs; fs->initial.reg = dwarf2_frame_state_copy_regs (&fs->regs); + if (get_frame_func_if_available (this_frame, &entry_pc)) + { + /* Decode the insns in the FDE up to the entry PC. */ + instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, + entry_pc, fs); + + if (fs->regs.cfa_how == CFA_REG_OFFSET + && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg) + == gdbarch_sp_regnum (gdbarch))) + { + entry_cfa_sp_offset = fs->regs.cfa_offset; + entry_cfa_sp_offset_p = 1; + } + } + else + instr = fde->instructions; + /* Then decode the insns in the FDE up to our target PC. */ - execute_cfa_program (fde, fde->instructions, fde->end, gdbarch, + execute_cfa_program (fde, instr, fde->end, gdbarch, get_frame_pc (this_frame), fs); TRY_CATCH (ex, RETURN_MASK_ERROR) @@ -1212,6 +1219,12 @@ incomplete CFI data; unspecified registers (e.g., %s) at %s"), do_cleanups (old_chain); + /* Try to find a virtual tail call frames chain with bottom (callee) frame + starting at THIS_FRAME. */ + dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache, + (entry_cfa_sp_offset_p + ? &entry_cfa_sp_offset : NULL)); + return cache; } @@ -1257,6 +1270,22 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, CORE_ADDR addr; int realnum; + /* Non-bottom frames of a virtual tail call frames chain use + dwarf2_tailcall_frame_unwind unwinder so this code does not apply for + them. If dwarf2_tailcall_prev_register_first does not have specific value + unwind the register, tail call frames are assumed to have the register set + of the top caller. */ + if (cache->tailcall_cache) + { + struct value *val; + + val = dwarf2_tailcall_prev_register_first (this_frame, + &cache->tailcall_cache, + regnum); + if (val) + return val; + } + switch (cache->reg[regnum].how) { case DWARF2_FRAME_REG_UNDEFINED: @@ -1326,6 +1355,18 @@ dwarf2_frame_prev_register (struct frame_info *this_frame, void **this_cache, } } +/* Proxy for tailcall_frame_dealloc_cache for bottom frame of a virtual tail + call frames chain. */ + +static void +dwarf2_frame_dealloc_cache (struct frame_info *self, void *this_cache) +{ + struct dwarf2_frame_cache *cache = dwarf2_frame_cache (self, &this_cache); + + if (cache->tailcall_cache) + dwarf2_tailcall_frame_unwind.dealloc_cache (self, cache->tailcall_cache); +} + static int dwarf2_frame_sniffer (const struct frame_unwind *self, struct frame_info *this_frame, void **this_cache) @@ -1352,7 +1393,14 @@ dwarf2_frame_sniffer (const struct frame_unwind *self, this_frame)) return self->type == SIGTRAMP_FRAME; - return self->type != SIGTRAMP_FRAME; + if (self->type != NORMAL_FRAME) + return 0; + + /* Preinitializa the cache so that TAILCALL_FRAME can find the record by + dwarf2_tailcall_sniffer_first. */ + dwarf2_frame_cache (this_frame, this_cache); + + return 1; } static const struct frame_unwind dwarf2_frame_unwind = @@ -1362,7 +1410,8 @@ static const struct frame_unwind dwarf2_frame_unwind = dwarf2_frame_this_id, dwarf2_frame_prev_register, NULL, - dwarf2_frame_sniffer + dwarf2_frame_sniffer, + dwarf2_frame_dealloc_cache }; static const struct frame_unwind dwarf2_signal_frame_unwind = @@ -1372,7 +1421,10 @@ static const struct frame_unwind dwarf2_signal_frame_unwind = dwarf2_frame_this_id, dwarf2_frame_prev_register, NULL, - dwarf2_frame_sniffer + dwarf2_frame_sniffer, + + /* TAILCALL_CACHE can never be in such frame to need dealloc_cache. */ + NULL }; /* Append the DWARF-2 frame unwinders to GDBARCH's list. */ @@ -1380,6 +1432,10 @@ static const struct frame_unwind dwarf2_signal_frame_unwind = void dwarf2_append_unwinders (struct gdbarch *gdbarch) { + /* TAILCALL_FRAME must be first to find the record by + dwarf2_tailcall_sniffer_first. */ + frame_unwind_append_unwinder (gdbarch, &dwarf2_tailcall_frame_unwind); + frame_unwind_append_unwinder (gdbarch, &dwarf2_frame_unwind); frame_unwind_append_unwinder (gdbarch, &dwarf2_signal_frame_unwind); } @@ -1431,7 +1487,8 @@ dwarf2_frame_cfa (struct frame_info *this_frame) /* This restriction could be lifted if other unwinders are known to compute the frame base in a way compatible with the DWARF unwinder. */ - if (! frame_unwinder_is (this_frame, &dwarf2_frame_unwind)) + if (!frame_unwinder_is (this_frame, &dwarf2_frame_unwind) + && !frame_unwinder_is (this_frame, &dwarf2_tailcall_frame_unwind)) error (_("can't compute CFA for this frame")); return get_frame_base (this_frame); } @@ -1791,17 +1848,30 @@ add_fde (struct dwarf2_fde_table *fde_table, struct dwarf2_fde *fde) #define DW64_CIE_ID ~0 #endif +/* Defines the type of eh_frames that are expected to be decoded: CIE, FDE + or any of them. */ + +enum eh_frame_type +{ + EH_CIE_TYPE_ID = 1 << 0, + EH_FDE_TYPE_ID = 1 << 1, + EH_CIE_OR_FDE_TYPE_ID = EH_CIE_TYPE_ID | EH_FDE_TYPE_ID +}; + static gdb_byte *decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, struct dwarf2_cie_table *cie_table, - struct dwarf2_fde_table *fde_table); + struct dwarf2_fde_table *fde_table, + enum eh_frame_type entry_type); + +/* Decode the next CIE or FDE, entry_type specifies the expected type. + Return NULL if invalid input, otherwise the next byte to be processed. */ -/* Decode the next CIE or FDE. Return NULL if invalid input, otherwise - the next byte to be processed. */ static gdb_byte * decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, struct dwarf2_cie_table *cie_table, - struct dwarf2_fde_table *fde_table) + struct dwarf2_fde_table *fde_table, + enum eh_frame_type entry_type) { struct gdbarch *gdbarch = get_objfile_arch (unit->objfile); gdb_byte *buf, *end; @@ -1852,6 +1922,10 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, char *augmentation; unsigned int cie_version; + /* Check that a CIE was expected. */ + if ((entry_type & EH_CIE_TYPE_ID) == 0) + error (_("Found a CIE when not expecting it.")); + /* Record the offset into the .debug_frame section of this CIE. */ cie_pointer = start - unit->dwarf_frame_buffer; @@ -2017,6 +2091,10 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, /* This is a FDE. */ struct dwarf2_fde *fde; + /* Check that an FDE was expected. */ + if ((entry_type & EH_FDE_TYPE_ID) == 0) + error (_("Found an FDE when not expecting it.")); + /* In an .eh_frame section, the CIE pointer is the delta between the address within the FDE where the CIE pointer is stored and the address of the CIE. Convert it to an offset into the .eh_frame @@ -2038,7 +2116,8 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, if (fde->cie == NULL) { decode_frame_entry (unit, unit->dwarf_frame_buffer + cie_pointer, - eh_frame_p, cie_table, fde_table); + eh_frame_p, cie_table, fde_table, + EH_CIE_TYPE_ID); fde->cie = find_cie (cie_table, cie_pointer); } @@ -2079,11 +2158,14 @@ decode_frame_entry_1 (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, return end; } -/* Read a CIE or FDE in BUF and decode it. */ +/* Read a CIE or FDE in BUF and decode it. Entry_type specifies whether we + expect an FDE or a CIE. */ + static gdb_byte * decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, struct dwarf2_cie_table *cie_table, - struct dwarf2_fde_table *fde_table) + struct dwarf2_fde_table *fde_table, + enum eh_frame_type entry_type) { enum { NONE, ALIGN4, ALIGN8, FAIL } workaround = NONE; gdb_byte *ret; @@ -2092,7 +2174,7 @@ decode_frame_entry (struct comp_unit *unit, gdb_byte *start, int eh_frame_p, while (1) { ret = decode_frame_entry_1 (unit, start, eh_frame_p, - cie_table, fde_table); + cie_table, fde_table, entry_type); if (ret != NULL) break; @@ -2173,12 +2255,6 @@ Corrupt data in %s:%s; align 8 workaround apparently succeeded"), return ret; } - -/* Imported from dwarf2read.c. */ -extern void dwarf2_get_section_info (struct objfile *, const char *, - asection **, gdb_byte **, - bfd_size_type *); - static int qsort_fde_cmp (const void *a, const void *b) { @@ -2208,6 +2284,7 @@ dwarf2_build_frame_info (struct objfile *objfile) struct dwarf2_cie_table cie_table; struct dwarf2_fde_table fde_table; struct dwarf2_fde_table *fde_table2; + volatile struct gdb_exception e; cie_table.num_entries = 0; cie_table.entries = NULL; @@ -2223,52 +2300,104 @@ dwarf2_build_frame_info (struct objfile *objfile) unit->dbase = 0; unit->tbase = 0; - dwarf2_get_section_info (objfile, ".eh_frame", - &unit->dwarf_frame_section, - &unit->dwarf_frame_buffer, - &unit->dwarf_frame_size); - if (unit->dwarf_frame_size) + if (objfile->separate_debug_objfile_backlink == NULL) { - asection *got, *txt; - - /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base - that is used for the i386/amd64 target, which currently is - the only target in GCC that supports/uses the - DW_EH_PE_datarel encoding. */ - got = bfd_get_section_by_name (unit->abfd, ".got"); - if (got) - unit->dbase = got->vma; - - /* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64 - so far. */ - txt = bfd_get_section_by_name (unit->abfd, ".text"); - if (txt) - unit->tbase = txt->vma; - - frame_ptr = unit->dwarf_frame_buffer; - while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) - frame_ptr = decode_frame_entry (unit, frame_ptr, 1, - &cie_table, &fde_table); - - if (cie_table.num_entries != 0) + /* Do not read .eh_frame from separate file as they must be also + present in the main file. */ + dwarf2_get_section_info (objfile, DWARF2_EH_FRAME, + &unit->dwarf_frame_section, + &unit->dwarf_frame_buffer, + &unit->dwarf_frame_size); + if (unit->dwarf_frame_size) { - /* Reinit cie_table: debug_frame has different CIEs. */ - xfree (cie_table.entries); - cie_table.num_entries = 0; - cie_table.entries = NULL; + asection *got, *txt; + + /* FIXME: kettenis/20030602: This is the DW_EH_PE_datarel base + that is used for the i386/amd64 target, which currently is + the only target in GCC that supports/uses the + DW_EH_PE_datarel encoding. */ + got = bfd_get_section_by_name (unit->abfd, ".got"); + if (got) + unit->dbase = got->vma; + + /* GCC emits the DW_EH_PE_textrel encoding type on sh and ia64 + so far. */ + txt = bfd_get_section_by_name (unit->abfd, ".text"); + if (txt) + unit->tbase = txt->vma; + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + frame_ptr = unit->dwarf_frame_buffer; + while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) + frame_ptr = decode_frame_entry (unit, frame_ptr, 1, + &cie_table, &fde_table, + EH_CIE_OR_FDE_TYPE_ID); + } + + if (e.reason < 0) + { + warning (_("skipping .eh_frame info of %s: %s"), + objfile->name, e.message); + + if (fde_table.num_entries != 0) + { + xfree (fde_table.entries); + fde_table.entries = NULL; + fde_table.num_entries = 0; + } + /* The cie_table is discarded by the next if. */ + } + + if (cie_table.num_entries != 0) + { + /* Reinit cie_table: debug_frame has different CIEs. */ + xfree (cie_table.entries); + cie_table.num_entries = 0; + cie_table.entries = NULL; + } } } - dwarf2_get_section_info (objfile, ".debug_frame", + dwarf2_get_section_info (objfile, DWARF2_DEBUG_FRAME, &unit->dwarf_frame_section, &unit->dwarf_frame_buffer, &unit->dwarf_frame_size); if (unit->dwarf_frame_size) { - frame_ptr = unit->dwarf_frame_buffer; - while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) - frame_ptr = decode_frame_entry (unit, frame_ptr, 0, - &cie_table, &fde_table); + int num_old_fde_entries = fde_table.num_entries; + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + frame_ptr = unit->dwarf_frame_buffer; + while (frame_ptr < unit->dwarf_frame_buffer + unit->dwarf_frame_size) + frame_ptr = decode_frame_entry (unit, frame_ptr, 0, + &cie_table, &fde_table, + EH_CIE_OR_FDE_TYPE_ID); + } + if (e.reason < 0) + { + warning (_("skipping .debug_frame info of %s: %s"), + objfile->name, e.message); + + if (fde_table.num_entries != 0) + { + fde_table.num_entries = num_old_fde_entries; + if (num_old_fde_entries == 0) + { + xfree (fde_table.entries); + fde_table.entries = NULL; + } + else + { + fde_table.entries = xrealloc (fde_table.entries, + fde_table.num_entries * + sizeof (fde_table.entries[0])); + } + } + fde_table.num_entries = num_old_fde_entries; + /* The cie_table is discarded by the next if. */ + } } /* Discard the cie_table, it is no longer needed. */ diff --git a/contrib/gdb-7/gdb/dwarf2-frame.h b/contrib/gdb-7/gdb/dwarf2-frame.h index 91d7643be6..33f7bf7942 100644 --- a/contrib/gdb-7/gdb/dwarf2-frame.h +++ b/contrib/gdb-7/gdb/dwarf2-frame.h @@ -1,7 +1,6 @@ /* Frame unwinder for frames with DWARF Call Frame Information. - Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2005, 2007-2012 Free Software Foundation, Inc. Contributed by Mark Kettenis. diff --git a/contrib/gdb-7/gdb/dwarf2expr.c b/contrib/gdb-7/gdb/dwarf2expr.c index 8976a82ca0..222fcc302b 100644 --- a/contrib/gdb-7/gdb/dwarf2expr.c +++ b/contrib/gdb-7/gdb/dwarf2expr.c @@ -1,7 +1,7 @@ /* DWARF 2 Expression Evaluator. - Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005, 2007-2012 Free Software Foundation, + Inc. Contributed by Daniel Berlin (dan@dberlin.org) @@ -34,6 +34,61 @@ static void execute_stack_op (struct dwarf_expr_context *, const gdb_byte *, const gdb_byte *); +/* Cookie for gdbarch data. */ + +static struct gdbarch_data *dwarf_arch_cookie; + +/* This holds gdbarch-specific types used by the DWARF expression + evaluator. See comments in execute_stack_op. */ + +struct dwarf_gdbarch_types +{ + struct type *dw_types[3]; +}; + +/* Allocate and fill in dwarf_gdbarch_types for an arch. */ + +static void * +dwarf_gdbarch_types_init (struct gdbarch *gdbarch) +{ + struct dwarf_gdbarch_types *types + = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct dwarf_gdbarch_types); + + /* The types themselves are lazily initialized. */ + + return types; +} + +/* Return the type used for DWARF operations where the type is + unspecified in the DWARF spec. Only certain sizes are + supported. */ + +static struct type * +dwarf_expr_address_type (struct dwarf_expr_context *ctx) +{ + struct dwarf_gdbarch_types *types = gdbarch_data (ctx->gdbarch, + dwarf_arch_cookie); + int ndx; + + if (ctx->addr_size == 2) + ndx = 0; + else if (ctx->addr_size == 4) + ndx = 1; + else if (ctx->addr_size == 8) + ndx = 2; + else + error (_("Unsupported address size in DWARF expressions: %d bits"), + 8 * ctx->addr_size); + + if (types->dw_types[ndx] == NULL) + types->dw_types[ndx] + = arch_integer_type (ctx->gdbarch, + 8 * ctx->addr_size, + 0, ""); + + return types->dw_types[ndx]; +} + /* Create a new context for the expression evaluator. */ struct dwarf_expr_context * @@ -96,26 +151,32 @@ dwarf_expr_grow_stack (struct dwarf_expr_context *ctx, size_t need) /* Push VALUE onto CTX's stack. */ -void -dwarf_expr_push (struct dwarf_expr_context *ctx, ULONGEST value, +static void +dwarf_expr_push (struct dwarf_expr_context *ctx, struct value *value, int in_stack_memory) { struct dwarf_stack_value *v; - /* We keep all stack elements within the range defined by the - DWARF address size. */ - if (ctx->addr_size < sizeof (ULONGEST)) - value &= ((ULONGEST) 1 << (ctx->addr_size * HOST_CHAR_BIT)) - 1; - dwarf_expr_grow_stack (ctx, 1); v = &ctx->stack[ctx->stack_len++]; v->value = value; v->in_stack_memory = in_stack_memory; } -/* Pop the top item off of CTX's stack. */ +/* Push VALUE onto CTX's stack. */ void +dwarf_expr_push_address (struct dwarf_expr_context *ctx, CORE_ADDR value, + int in_stack_memory) +{ + dwarf_expr_push (ctx, + value_from_ulongest (dwarf_expr_address_type (ctx), value), + in_stack_memory); +} + +/* Pop the top item off of CTX's stack. */ + +static void dwarf_expr_pop (struct dwarf_expr_context *ctx) { if (ctx->stack_len <= 0) @@ -125,7 +186,7 @@ dwarf_expr_pop (struct dwarf_expr_context *ctx) /* Retrieve the N'th item on CTX's stack. */ -ULONGEST +struct value * dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n) { if (ctx->stack_len <= n) @@ -133,7 +194,61 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n) "stack only has %d elements on it."), n, ctx->stack_len); return ctx->stack[ctx->stack_len - (1 + n)].value; +} +/* Require that TYPE be an integral type; throw an exception if not. */ + +static void +dwarf_require_integral (struct type *type) +{ + if (TYPE_CODE (type) != TYPE_CODE_INT + && TYPE_CODE (type) != TYPE_CODE_CHAR + && TYPE_CODE (type) != TYPE_CODE_BOOL) + error (_("integral type expected in DWARF expression")); +} + +/* Return the unsigned form of TYPE. TYPE is necessarily an integral + type. */ + +static struct type * +get_unsigned_type (struct gdbarch *gdbarch, struct type *type) +{ + switch (TYPE_LENGTH (type)) + { + case 1: + return builtin_type (gdbarch)->builtin_uint8; + case 2: + return builtin_type (gdbarch)->builtin_uint16; + case 4: + return builtin_type (gdbarch)->builtin_uint32; + case 8: + return builtin_type (gdbarch)->builtin_uint64; + default: + error (_("no unsigned variant found for type, while evaluating " + "DWARF expression")); + } +} + +/* Return the signed form of TYPE. TYPE is necessarily an integral + type. */ + +static struct type * +get_signed_type (struct gdbarch *gdbarch, struct type *type) +{ + switch (TYPE_LENGTH (type)) + { + case 1: + return builtin_type (gdbarch)->builtin_int8; + case 2: + return builtin_type (gdbarch)->builtin_int16; + case 4: + return builtin_type (gdbarch)->builtin_int32; + case 8: + return builtin_type (gdbarch)->builtin_int64; + default: + error (_("no signed variant found for type, while evaluating " + "DWARF expression")); + } } /* Retrieve the N'th item on CTX's stack, converted to an address. */ @@ -141,7 +256,14 @@ dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n) CORE_ADDR dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n) { - ULONGEST result = dwarf_expr_fetch (ctx, n); + struct value *result_val = dwarf_expr_fetch (ctx, n); + enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch); + ULONGEST result; + + dwarf_require_integral (value_type (result_val)); + result = extract_unsigned_integer (value_contents (result_val), + TYPE_LENGTH (value_type (result_val)), + byte_order); /* For most architectures, calling extract_unsigned_integer() alone is sufficient for extracting an address. However, some @@ -151,25 +273,9 @@ dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n) for those architectures which require it. */ if (gdbarch_integer_to_address_p (ctx->gdbarch)) { - enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch); gdb_byte *buf = alloca (ctx->addr_size); - struct type *int_type; - - switch (ctx->addr_size) - { - case 2: - int_type = builtin_type (ctx->gdbarch)->builtin_uint16; - break; - case 4: - int_type = builtin_type (ctx->gdbarch)->builtin_uint32; - break; - case 8: - int_type = builtin_type (ctx->gdbarch)->builtin_uint64; - break; - default: - internal_error (__FILE__, __LINE__, - _("Unsupported address size.\n")); - } + struct type *int_type = get_unsigned_type (ctx->gdbarch, + value_type (result_val)); store_unsigned_integer (buf, ctx->addr_size, byte_order, result); return gdbarch_integer_to_address (ctx->gdbarch, int_type, buf); @@ -188,7 +294,6 @@ dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n) "stack only has %d elements on it."), n, ctx->stack_len); return ctx->stack[ctx->stack_len - (1 + n)].in_stack_memory; - } /* Return true if the expression stack is empty. */ @@ -238,8 +343,10 @@ add_piece (struct dwarf_expr_context *ctx, ULONGEST size, ULONGEST offset) else if (p->location == DWARF_VALUE_IMPLICIT_POINTER) { p->v.ptr.die = ctx->len; - p->v.ptr.offset = (LONGEST) dwarf_expr_fetch (ctx, 0); + p->v.ptr.offset = value_as_long (dwarf_expr_fetch (ctx, 0)); } + else if (p->location == DWARF_VALUE_REGISTER) + p->v.regno = value_as_long (dwarf_expr_fetch (ctx, 0)); else { p->v.value = dwarf_expr_fetch (ctx, 0); @@ -264,7 +371,7 @@ dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr, /* Decode the unsigned LEB128 constant at BUF into the variable pointed to by R, and return the new value of BUF. Verify that it doesn't extend - past BUF_END. */ + past BUF_END. R can be NULL, the constant is then only skipped. */ const gdb_byte * read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r) @@ -284,13 +391,14 @@ read_uleb128 (const gdb_byte *buf, const gdb_byte *buf_end, ULONGEST * r) break; shift += 7; } - *r = result; + if (r) + *r = result; return buf; } /* Decode the signed LEB128 constant at BUF into the variable pointed to by R, and return the new value of BUF. Verify that it doesn't extend - past BUF_END. */ + past BUF_END. R can be NULL, the constant is then only skipped. */ const gdb_byte * read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r) @@ -311,9 +419,10 @@ read_sleb128 (const gdb_byte *buf, const gdb_byte *buf_end, LONGEST * r) break; } if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0) - result |= -(1 << shift); + result |= -(((LONGEST) 1) << shift); - *r = result; + if (r) + *r = result; return buf; } @@ -330,11 +439,204 @@ dwarf_expr_require_composition (const gdb_byte *op_ptr, const gdb_byte *op_end, checked at the other place that this function is called. */ if (op_ptr != op_end && *op_ptr != DW_OP_piece && *op_ptr != DW_OP_bit_piece) error (_("DWARF-2 expression error: `%s' operations must be " - "used either alone or in conjuction with DW_OP_piece " + "used either alone or in conjunction with DW_OP_piece " "or DW_OP_bit_piece."), op_name); } +/* Return true iff the types T1 and T2 are "the same". This only does + checks that might reasonably be needed to compare DWARF base + types. */ + +static int +base_types_equal_p (struct type *t1, struct type *t2) +{ + if (TYPE_CODE (t1) != TYPE_CODE (t2)) + return 0; + if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) + return 0; + return TYPE_LENGTH (t1) == TYPE_LENGTH (t2); +} + +/* A convenience function to call get_base_type on CTX and return the + result. DIE is the DIE whose type we need. SIZE is non-zero if + this function should verify that the resulting type has the correct + size. */ + +static struct type * +dwarf_get_base_type (struct dwarf_expr_context *ctx, ULONGEST die, int size) +{ + struct type *result; + + if (ctx->funcs->get_base_type) + { + result = ctx->funcs->get_base_type (ctx, die); + if (result == NULL) + error (_("Could not find type for DW_OP_GNU_const_type")); + if (size != 0 && TYPE_LENGTH (result) != size) + error (_("DW_OP_GNU_const_type has different sizes for type and data")); + } + else + /* Anything will do. */ + result = builtin_type (ctx->gdbarch)->builtin_int; + + return result; +} + +/* If = DW_OP_reg0 && *buf <= DW_OP_reg31) + { + if (buf_end - buf != 1) + return -1; + return *buf - DW_OP_reg0; + } + + if (*buf == DW_OP_GNU_regval_type) + { + buf++; + buf = read_uleb128 (buf, buf_end, &dwarf_reg); + buf = read_uleb128 (buf, buf_end, NULL); + } + else if (*buf == DW_OP_regx) + { + buf++; + buf = read_uleb128 (buf, buf_end, &dwarf_reg); + } + else + return -1; + if (buf != buf_end || (int) dwarf_reg != dwarf_reg) + return -1; + return dwarf_reg; +} + +/* If = DW_OP_breg0 && *buf <= DW_OP_breg31) + { + dwarf_reg = *buf - DW_OP_breg0; + buf++; + } + else if (*buf == DW_OP_bregx) + { + buf++; + buf = read_uleb128 (buf, buf_end, &dwarf_reg); + if ((int) dwarf_reg != dwarf_reg) + return -1; + } + else + return -1; + + buf = read_sleb128 (buf, buf_end, &offset); + if (offset != 0) + return -1; + + if (buf >= buf_end) + return -1; + + if (*buf == DW_OP_deref) + { + buf++; + *deref_size_return = -1; + } + else if (*buf == DW_OP_deref_size) + { + buf++; + if (buf >= buf_end) + return -1; + *deref_size_return = *buf++; + } + else + return -1; + + if (buf != buf_end) + return -1; + + return dwarf_reg; +} + +/* If = DW_OP_breg0 && *buf <= DW_OP_breg31) + { + dwarf_reg = *buf - DW_OP_breg0; + buf++; + } + else + { + if (*buf != DW_OP_bregx) + return 0; + buf++; + buf = read_uleb128 (buf, buf_end, &dwarf_reg); + } + + if (gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_reg) + != gdbarch_sp_regnum (gdbarch)) + return 0; + + buf = read_sleb128 (buf, buf_end, &sp_offset); + *sp_offset_return = sp_offset; + if (buf != buf_end || sp_offset != (LONGEST) *sp_offset_return) + return 0; + + return 1; +} + /* The engine for the expression evaluator. Using the context in CTX, evaluate the expression between OP_PTR and OP_END. */ @@ -342,10 +644,15 @@ static void execute_stack_op (struct dwarf_expr_context *ctx, const gdb_byte *op_ptr, const gdb_byte *op_end) { -#define sign_ext(x) ((LONGEST) (((x) ^ sign_bit) - sign_bit)) - ULONGEST sign_bit = (ctx->addr_size >= sizeof (ULONGEST) ? 0 - : ((ULONGEST) 1) << (ctx->addr_size * 8 - 1)); enum bfd_endian byte_order = gdbarch_byte_order (ctx->gdbarch); + /* Old-style "untyped" DWARF values need special treatment in a + couple of places, specifically DW_OP_mod and DW_OP_shr. We need + a special type for these values so we can distinguish them from + values that have an explicit type, because explicitly-typed + values do not need special treatment. This special type must be + different (in the `==' sense) from any base type coming from the + CU. */ + struct type *address_type = dwarf_expr_address_type (ctx); ctx->location = DWARF_VALUE_MEMORY; ctx->initialized = 1; /* Default is initialized. */ @@ -368,6 +675,11 @@ execute_stack_op (struct dwarf_expr_context *ctx, int in_stack_memory = 0; ULONGEST uoffset, reg; LONGEST offset; + struct value *result_val = NULL; + + /* The DWARF expression might have a bug causing an infinite + loop. In that case, quitting is the only way out. */ + QUIT; switch (op) { @@ -404,6 +716,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_lit30: case DW_OP_lit31: result = op - DW_OP_lit0; + result_val = value_from_ulongest (address_type, result); break; case DW_OP_addr: @@ -416,47 +729,58 @@ execute_stack_op (struct dwarf_expr_context *ctx, branching between the address and the TLS op. */ if (op_ptr >= op_end || *op_ptr != DW_OP_GNU_push_tls_address) result += ctx->offset; + result_val = value_from_ulongest (address_type, result); break; case DW_OP_const1u: result = extract_unsigned_integer (op_ptr, 1, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 1; break; case DW_OP_const1s: result = extract_signed_integer (op_ptr, 1, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 1; break; case DW_OP_const2u: result = extract_unsigned_integer (op_ptr, 2, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 2; break; case DW_OP_const2s: result = extract_signed_integer (op_ptr, 2, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 2; break; case DW_OP_const4u: result = extract_unsigned_integer (op_ptr, 4, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 4; break; case DW_OP_const4s: result = extract_signed_integer (op_ptr, 4, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 4; break; case DW_OP_const8u: result = extract_unsigned_integer (op_ptr, 8, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 8; break; case DW_OP_const8s: result = extract_signed_integer (op_ptr, 8, byte_order); + result_val = value_from_ulongest (address_type, result); op_ptr += 8; break; case DW_OP_constu: op_ptr = read_uleb128 (op_ptr, op_end, &uoffset); result = uoffset; + result_val = value_from_ulongest (address_type, result); break; case DW_OP_consts: op_ptr = read_sleb128 (op_ptr, op_end, &offset); result = offset; + result_val = value_from_ulongest (address_type, result); break; /* The DW_OP_reg operations are required to occur alone in @@ -498,10 +822,11 @@ execute_stack_op (struct dwarf_expr_context *ctx, && *op_ptr != DW_OP_bit_piece && *op_ptr != DW_OP_GNU_uninit) error (_("DWARF-2 expression error: DW_OP_reg operations must be " - "used either alone or in conjuction with DW_OP_piece " + "used either alone or in conjunction with DW_OP_piece " "or DW_OP_bit_piece.")); result = op - DW_OP_reg0; + result_val = value_from_ulongest (address_type, result); ctx->location = DWARF_VALUE_REGISTER; break; @@ -510,6 +835,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, dwarf_expr_require_composition (op_ptr, op_end, "DW_OP_regx"); result = reg; + result_val = value_from_ulongest (address_type, result); ctx->location = DWARF_VALUE_REGISTER; break; @@ -539,14 +865,19 @@ execute_stack_op (struct dwarf_expr_context *ctx, ULONGEST die; LONGEST len; + if (ctx->ref_addr_size == -1) + error (_("DWARF-2 expression error: DW_OP_GNU_implicit_pointer " + "is not allowed in frame context")); + /* The referred-to DIE. */ - ctx->len = extract_unsigned_integer (op_ptr, ctx->addr_size, + ctx->len = extract_unsigned_integer (op_ptr, ctx->ref_addr_size, byte_order); - op_ptr += ctx->addr_size; + op_ptr += ctx->ref_addr_size; /* The byte offset into the data. */ op_ptr = read_sleb128 (op_ptr, op_end, &len); result = (ULONGEST) len; + result_val = value_from_ulongest (address_type, result); ctx->location = DWARF_VALUE_IMPLICIT_POINTER; dwarf_expr_require_composition (op_ptr, op_end, @@ -588,16 +919,18 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_breg31: { op_ptr = read_sleb128 (op_ptr, op_end, &offset); - result = (ctx->read_reg) (ctx->baton, op - DW_OP_breg0); + result = (ctx->funcs->read_reg) (ctx->baton, op - DW_OP_breg0); result += offset; + result_val = value_from_ulongest (address_type, result); } break; case DW_OP_bregx: { op_ptr = read_uleb128 (op_ptr, op_end, ®); op_ptr = read_sleb128 (op_ptr, op_end, &offset); - result = (ctx->read_reg) (ctx->baton, reg); + result = (ctx->funcs->read_reg) (ctx->baton, reg); result += offset; + result_val = value_from_ulongest (address_type, result); } break; case DW_OP_fbreg: @@ -615,16 +948,18 @@ execute_stack_op (struct dwarf_expr_context *ctx, /* FIXME: cagney/2003-03-26: This code should be using get_frame_base_address(), and then implement a dwarf2 specific this_base method. */ - (ctx->get_frame_base) (ctx->baton, &datastart, &datalen); + (ctx->funcs->get_frame_base) (ctx->baton, &datastart, &datalen); dwarf_expr_eval (ctx, datastart, datalen); if (ctx->location == DWARF_VALUE_MEMORY) result = dwarf_expr_fetch_address (ctx, 0); else if (ctx->location == DWARF_VALUE_REGISTER) - result = (ctx->read_reg) (ctx->baton, dwarf_expr_fetch (ctx, 0)); + result = (ctx->funcs->read_reg) (ctx->baton, + value_as_long (dwarf_expr_fetch (ctx, 0))); else error (_("Not implemented: computing frame " "base using explicit value operator")); result = result + offset; + result_val = value_from_ulongest (address_type, result); in_stack_memory = 1; ctx->stack_len = before_stack_len; ctx->location = DWARF_VALUE_MEMORY; @@ -632,7 +967,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, break; case DW_OP_dup: - result = dwarf_expr_fetch (ctx, 0); + result_val = dwarf_expr_fetch (ctx, 0); in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); break; @@ -642,7 +977,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_pick: offset = *op_ptr++; - result = dwarf_expr_fetch (ctx, offset); + result_val = dwarf_expr_fetch (ctx, offset); in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, offset); break; @@ -662,7 +997,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, } case DW_OP_over: - result = dwarf_expr_fetch (ctx, 1); + result_val = dwarf_expr_fetch (ctx, 1); in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 1); break; @@ -685,14 +1020,40 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_deref: case DW_OP_deref_size: + case DW_OP_GNU_deref_type: { int addr_size = (op == DW_OP_deref ? ctx->addr_size : *op_ptr++); gdb_byte *buf = alloca (addr_size); CORE_ADDR addr = dwarf_expr_fetch_address (ctx, 0); + struct type *type; + dwarf_expr_pop (ctx); - (ctx->read_mem) (ctx->baton, buf, addr, addr_size); - result = extract_unsigned_integer (buf, addr_size, byte_order); + if (op == DW_OP_GNU_deref_type) + { + ULONGEST type_die; + + op_ptr = read_uleb128 (op_ptr, op_end, &type_die); + type = dwarf_get_base_type (ctx, type_die, 0); + } + else + type = address_type; + + (ctx->funcs->read_mem) (ctx->baton, buf, addr, addr_size); + + /* If the size of the object read from memory is different + from the type length, we need to zero-extend it. */ + if (TYPE_LENGTH (type) != addr_size) + { + ULONGEST result = + extract_unsigned_integer (buf, addr_size, byte_order); + + buf = alloca (TYPE_LENGTH (type)); + store_unsigned_integer (buf, TYPE_LENGTH (type), + byte_order, result); + } + + result_val = value_from_contents_and_address (type, buf, addr); break; } @@ -700,27 +1061,34 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_neg: case DW_OP_not: case DW_OP_plus_uconst: - /* Unary operations. */ - result = dwarf_expr_fetch (ctx, 0); - dwarf_expr_pop (ctx); + { + /* Unary operations. */ + result_val = dwarf_expr_fetch (ctx, 0); + dwarf_expr_pop (ctx); - switch (op) - { - case DW_OP_abs: - if (sign_ext (result) < 0) - result = -result; - break; - case DW_OP_neg: - result = -result; - break; - case DW_OP_not: - result = ~result; - break; - case DW_OP_plus_uconst: - op_ptr = read_uleb128 (op_ptr, op_end, ®); - result += reg; - break; - } + switch (op) + { + case DW_OP_abs: + if (value_less (result_val, + value_zero (value_type (result_val), not_lval))) + result_val = value_neg (result_val); + break; + case DW_OP_neg: + result_val = value_neg (result_val); + break; + case DW_OP_not: + dwarf_require_integral (value_type (result_val)); + result_val = value_complement (result_val); + break; + case DW_OP_plus_uconst: + dwarf_require_integral (value_type (result_val)); + result = value_as_long (result_val); + op_ptr = read_uleb128 (op_ptr, op_end, ®); + result += reg; + result_val = value_from_ulongest (address_type, result); + break; + } + } break; case DW_OP_and: @@ -742,7 +1110,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_ne: { /* Binary operations. */ - ULONGEST first, second; + struct value *first, *second; second = dwarf_expr_fetch (ctx, 0); dwarf_expr_pop (ctx); @@ -750,62 +1118,127 @@ execute_stack_op (struct dwarf_expr_context *ctx, first = dwarf_expr_fetch (ctx, 0); dwarf_expr_pop (ctx); + if (! base_types_equal_p (value_type (first), value_type (second))) + error (_("Incompatible types on DWARF stack")); + switch (op) { case DW_OP_and: - result = first & second; + dwarf_require_integral (value_type (first)); + dwarf_require_integral (value_type (second)); + result_val = value_binop (first, second, BINOP_BITWISE_AND); break; case DW_OP_div: - if (!second) - error (_("Division by zero")); - result = sign_ext (first) / sign_ext (second); + result_val = value_binop (first, second, BINOP_DIV); break; case DW_OP_minus: - result = first - second; + result_val = value_binop (first, second, BINOP_SUB); break; case DW_OP_mod: - if (!second) - error (_("Division by zero")); - result = first % second; + { + int cast_back = 0; + struct type *orig_type = value_type (first); + + /* We have to special-case "old-style" untyped values + -- these must have mod computed using unsigned + math. */ + if (orig_type == address_type) + { + struct type *utype + = get_unsigned_type (ctx->gdbarch, orig_type); + + cast_back = 1; + first = value_cast (utype, first); + second = value_cast (utype, second); + } + /* Note that value_binop doesn't handle float or + decimal float here. This seems unimportant. */ + result_val = value_binop (first, second, BINOP_MOD); + if (cast_back) + result_val = value_cast (orig_type, result_val); + } break; case DW_OP_mul: - result = first * second; + result_val = value_binop (first, second, BINOP_MUL); break; case DW_OP_or: - result = first | second; + dwarf_require_integral (value_type (first)); + dwarf_require_integral (value_type (second)); + result_val = value_binop (first, second, BINOP_BITWISE_IOR); break; case DW_OP_plus: - result = first + second; + result_val = value_binop (first, second, BINOP_ADD); break; case DW_OP_shl: - result = first << second; + dwarf_require_integral (value_type (first)); + dwarf_require_integral (value_type (second)); + result_val = value_binop (first, second, BINOP_LSH); break; case DW_OP_shr: - result = first >> second; + dwarf_require_integral (value_type (first)); + dwarf_require_integral (value_type (second)); + if (!TYPE_UNSIGNED (value_type (first))) + { + struct type *utype + = get_unsigned_type (ctx->gdbarch, value_type (first)); + + first = value_cast (utype, first); + } + + result_val = value_binop (first, second, BINOP_RSH); + /* Make sure we wind up with the same type we started + with. */ + if (value_type (result_val) != value_type (second)) + result_val = value_cast (value_type (second), result_val); break; case DW_OP_shra: - result = sign_ext (first) >> second; + dwarf_require_integral (value_type (first)); + dwarf_require_integral (value_type (second)); + if (TYPE_UNSIGNED (value_type (first))) + { + struct type *stype + = get_signed_type (ctx->gdbarch, value_type (first)); + + first = value_cast (stype, first); + } + + result_val = value_binop (first, second, BINOP_RSH); + /* Make sure we wind up with the same type we started + with. */ + if (value_type (result_val) != value_type (second)) + result_val = value_cast (value_type (second), result_val); break; case DW_OP_xor: - result = first ^ second; + dwarf_require_integral (value_type (first)); + dwarf_require_integral (value_type (second)); + result_val = value_binop (first, second, BINOP_BITWISE_XOR); break; case DW_OP_le: - result = sign_ext (first) <= sign_ext (second); + /* A <= B is !(B < A). */ + result = ! value_less (second, first); + result_val = value_from_ulongest (address_type, result); break; case DW_OP_ge: - result = sign_ext (first) >= sign_ext (second); + /* A >= B is !(A < B). */ + result = ! value_less (first, second); + result_val = value_from_ulongest (address_type, result); break; case DW_OP_eq: - result = sign_ext (first) == sign_ext (second); + result = value_equal (first, second); + result_val = value_from_ulongest (address_type, result); break; case DW_OP_lt: - result = sign_ext (first) < sign_ext (second); + result = value_less (first, second); + result_val = value_from_ulongest (address_type, result); break; case DW_OP_gt: - result = sign_ext (first) > sign_ext (second); + /* A > B is B < A. */ + result = value_less (second, first); + result_val = value_from_ulongest (address_type, result); break; case DW_OP_ne: - result = sign_ext (first) != sign_ext (second); + result = ! value_equal (first, second); + result_val = value_from_ulongest (address_type, result); break; default: internal_error (__FILE__, __LINE__, @@ -815,7 +1248,8 @@ execute_stack_op (struct dwarf_expr_context *ctx, break; case DW_OP_call_frame_cfa: - result = (ctx->get_frame_cfa) (ctx->baton); + result = (ctx->funcs->get_frame_cfa) (ctx->baton); + result_val = value_from_ulongest (address_type, result); in_stack_memory = 1; break; @@ -828,9 +1262,10 @@ execute_stack_op (struct dwarf_expr_context *ctx, control block at which the variable is located. Nothing should follow this operator, so the top of stack would be returned. */ - result = dwarf_expr_fetch (ctx, 0); + result = value_as_long (dwarf_expr_fetch (ctx, 0)); dwarf_expr_pop (ctx); - result = (ctx->get_tls_address) (ctx->baton, result); + result = (ctx->funcs->get_tls_address) (ctx->baton, result); + result_val = value_from_ulongest (address_type, result); break; case DW_OP_skip: @@ -840,11 +1275,17 @@ execute_stack_op (struct dwarf_expr_context *ctx, goto no_push; case DW_OP_bra: - offset = extract_signed_integer (op_ptr, 2, byte_order); - op_ptr += 2; - if (dwarf_expr_fetch (ctx, 0) != 0) - op_ptr += offset; - dwarf_expr_pop (ctx); + { + struct value *val; + + offset = extract_signed_integer (op_ptr, 2, byte_order); + op_ptr += 2; + val = dwarf_expr_fetch (ctx, 0); + dwarf_require_integral (value_type (val)); + if (value_as_long (val) != 0) + op_ptr += offset; + dwarf_expr_pop (ctx); + } goto no_push; case DW_OP_nop: @@ -896,28 +1337,125 @@ execute_stack_op (struct dwarf_expr_context *ctx, case DW_OP_call2: result = extract_unsigned_integer (op_ptr, 2, byte_order); op_ptr += 2; - ctx->dwarf_call (ctx, result); + ctx->funcs->dwarf_call (ctx, result); goto no_push; case DW_OP_call4: result = extract_unsigned_integer (op_ptr, 4, byte_order); op_ptr += 4; - ctx->dwarf_call (ctx, result); + ctx->funcs->dwarf_call (ctx, result); goto no_push; case DW_OP_GNU_entry_value: - /* This operation is not yet supported by GDB. */ - ctx->location = DWARF_VALUE_OPTIMIZED_OUT; - ctx->stack_len = 0; - ctx->num_pieces = 0; - goto abort_expression; + { + ULONGEST len; + int dwarf_reg; + CORE_ADDR deref_size; + + op_ptr = read_uleb128 (op_ptr, op_end, &len); + if (op_ptr + len > op_end) + error (_("DW_OP_GNU_entry_value: too few bytes available.")); + + dwarf_reg = dwarf_block_to_dwarf_reg (op_ptr, op_ptr + len); + if (dwarf_reg != -1) + { + op_ptr += len; + ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg, + 0 /* unused */, + -1 /* deref_size */); + goto no_push; + } + + dwarf_reg = dwarf_block_to_dwarf_reg_deref (op_ptr, op_ptr + len, + &deref_size); + if (dwarf_reg != -1) + { + if (deref_size == -1) + deref_size = ctx->addr_size; + op_ptr += len; + ctx->funcs->push_dwarf_reg_entry_value (ctx, dwarf_reg, + 0 /* unused */, + deref_size); + goto no_push; + } + + error (_("DWARF-2 expression error: DW_OP_GNU_entry_value is " + "supported only for single DW_OP_reg* " + "or for DW_OP_breg*(0)+DW_OP_deref*")); + } + + case DW_OP_GNU_const_type: + { + ULONGEST type_die; + int n; + const gdb_byte *data; + struct type *type; + + op_ptr = read_uleb128 (op_ptr, op_end, &type_die); + n = *op_ptr++; + data = op_ptr; + op_ptr += n; + + type = dwarf_get_base_type (ctx, type_die, n); + result_val = value_from_contents (type, data); + } + break; + + case DW_OP_GNU_regval_type: + { + ULONGEST type_die; + struct type *type; + + op_ptr = read_uleb128 (op_ptr, op_end, ®); + op_ptr = read_uleb128 (op_ptr, op_end, &type_die); + + type = dwarf_get_base_type (ctx, type_die, 0); + result = (ctx->funcs->read_reg) (ctx->baton, reg); + result_val = value_from_ulongest (address_type, result); + result_val = value_from_contents (type, + value_contents_all (result_val)); + } + break; + + case DW_OP_GNU_convert: + case DW_OP_GNU_reinterpret: + { + ULONGEST type_die; + struct type *type; + + op_ptr = read_uleb128 (op_ptr, op_end, &type_die); + + if (type_die == 0) + type = address_type; + else + type = dwarf_get_base_type (ctx, type_die, 0); + + result_val = dwarf_expr_fetch (ctx, 0); + dwarf_expr_pop (ctx); + + if (op == DW_OP_GNU_convert) + result_val = value_cast (type, result_val); + else if (type == value_type (result_val)) + { + /* Nothing. */ + } + else if (TYPE_LENGTH (type) + != TYPE_LENGTH (value_type (result_val))) + error (_("DW_OP_GNU_reinterpret has wrong size")); + else + result_val + = value_from_contents (type, + value_contents_all (result_val)); + } + break; default: error (_("Unhandled dwarf expression opcode 0x%x"), op); } /* Most things push a result value. */ - dwarf_expr_push (ctx, result, in_stack_memory); + gdb_assert (result_val != NULL); + dwarf_expr_push (ctx, result_val, in_stack_memory); no_push: ; } @@ -931,5 +1469,71 @@ execute_stack_op (struct dwarf_expr_context *ctx, abort_expression: ctx->recursion_depth--; gdb_assert (ctx->recursion_depth >= 0); -#undef sign_ext +} + +/* Stub dwarf_expr_context_funcs.get_frame_base implementation. */ + +void +ctx_no_get_frame_base (void *baton, const gdb_byte **start, size_t *length) +{ + error (_("%s is invalid in this context"), "DW_OP_fbreg"); +} + +/* Stub dwarf_expr_context_funcs.get_frame_cfa implementation. */ + +CORE_ADDR +ctx_no_get_frame_cfa (void *baton) +{ + error (_("%s is invalid in this context"), "DW_OP_call_frame_cfa"); +} + +/* Stub dwarf_expr_context_funcs.get_frame_pc implementation. */ + +CORE_ADDR +ctx_no_get_frame_pc (void *baton) +{ + error (_("%s is invalid in this context"), "DW_OP_GNU_implicit_pointer"); +} + +/* Stub dwarf_expr_context_funcs.get_tls_address implementation. */ + +CORE_ADDR +ctx_no_get_tls_address (void *baton, CORE_ADDR offset) +{ + error (_("%s is invalid in this context"), "DW_OP_GNU_push_tls_address"); +} + +/* Stub dwarf_expr_context_funcs.dwarf_call implementation. */ + +void +ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) +{ + error (_("%s is invalid in this context"), "DW_OP_call*"); +} + +/* Stub dwarf_expr_context_funcs.get_base_type implementation. */ + +struct type * +ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die) +{ + error (_("Support for typed DWARF is not supported in this context")); +} + +/* Stub dwarf_expr_context_funcs.push_dwarf_block_entry_value + implementation. */ + +void +ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, + int dwarf_reg, CORE_ADDR fb_offset, + int deref_size) +{ + internal_error (__FILE__, __LINE__, + _("Support for DW_OP_GNU_entry_value is unimplemented")); +} + +void +_initialize_dwarf2expr (void) +{ + dwarf_arch_cookie + = gdbarch_data_register_post_init (dwarf_gdbarch_types_init); } diff --git a/contrib/gdb-7/gdb/dwarf2expr.h b/contrib/gdb-7/gdb/dwarf2expr.h index 78ff53fcf2..fd70bf98a3 100644 --- a/contrib/gdb-7/gdb/dwarf2expr.h +++ b/contrib/gdb-7/gdb/dwarf2expr.h @@ -1,7 +1,7 @@ /* DWARF 2 Expression Evaluator. - Copyright (C) 2001, 2002, 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2005, 2007-2012 Free Software Foundation, + Inc. Contributed by Daniel Berlin . @@ -23,6 +23,64 @@ #if !defined (DWARF2EXPR_H) #define DWARF2EXPR_H +struct dwarf_expr_context; + +/* Virtual method table for struct dwarf_expr_context below. */ + +struct dwarf_expr_context_funcs +{ + /* Return the value of register number REGNUM. */ + CORE_ADDR (*read_reg) (void *baton, int regnum); + + /* Read LENGTH bytes at ADDR into BUF. */ + void (*read_mem) (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t length); + + /* Return the location expression for the frame base attribute, in + START and LENGTH. The result must be live until the current + expression evaluation is complete. */ + void (*get_frame_base) (void *baton, const gdb_byte **start, size_t *length); + + /* Return the CFA for the frame. */ + CORE_ADDR (*get_frame_cfa) (void *baton); + + /* Return the PC for the frame. */ + CORE_ADDR (*get_frame_pc) (void *baton); + + /* Return the thread-local storage address for + DW_OP_GNU_push_tls_address. */ + CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); + + /* Execute DW_AT_location expression for the DWARF expression subroutine in + the DIE at DIE_OFFSET in the CU from CTX. Do not touch STACK while it + being passed to and returned from the called DWARF subroutine. */ + void (*dwarf_call) (struct dwarf_expr_context *ctx, size_t die_offset); + + /* Return the base type given by the indicated DIE. This can throw + an exception if the DIE is invalid or does not represent a base + type. If can also be NULL in the special case where the + callbacks are not performing evaluation, and thus it is + meaningful to substitute a stub type of the correct size. */ + struct type *(*get_base_type) (struct dwarf_expr_context *ctx, size_t die); + + /* Push on DWARF stack an entry evaluated for DW_TAG_GNU_call_site's + DWARF_REG/FB_OFFSET at the caller of specified BATON. If DWARF register + number DWARF_REG specifying the push_dwarf_reg_entry_value parameter is + not -1 FB_OFFSET is ignored. Otherwise FB_OFFSET specifies stack + parameter offset against caller's stack pointer (which equals the callee's + frame base). If DEREF_SIZE is not -1 then use + DW_AT_GNU_call_site_data_value instead of DW_AT_GNU_call_site_value. */ + void (*push_dwarf_reg_entry_value) (struct dwarf_expr_context *ctx, + int dwarf_reg, CORE_ADDR fb_offset, + int deref_size); + +#if 0 + /* Not yet implemented. */ + + /* Return the `object address' for DW_OP_push_object_address. */ + CORE_ADDR (*get_object_address) (void *baton); +#endif +}; + /* The location of a value. */ enum dwarf_value_location { @@ -51,7 +109,7 @@ enum dwarf_value_location struct dwarf_stack_value { - ULONGEST value; + struct value *value; /* Non-zero if the piece is in memory and is known to be on the program's stack. It is always ok to set this to zero. @@ -78,6 +136,10 @@ struct dwarf_expr_context /* Target address size in bytes. */ int addr_size; + /* DW_FORM_ref_addr size in bytes. If -1 DWARF is executed from a frame + context and operations depending on DW_FORM_ref_addr are not allowed. */ + int ref_addr_size; + /* Offset used to relocate DW_OP_addr argument. */ CORE_ADDR offset; @@ -85,38 +147,8 @@ struct dwarf_expr_context to all of the callback functions. */ void *baton; - /* Return the value of register number REGNUM. */ - CORE_ADDR (*read_reg) (void *baton, int regnum); - - /* Read LENGTH bytes at ADDR into BUF. */ - void (*read_mem) (void *baton, gdb_byte *buf, CORE_ADDR addr, size_t length); - - /* Return the location expression for the frame base attribute, in - START and LENGTH. The result must be live until the current - expression evaluation is complete. */ - void (*get_frame_base) (void *baton, const gdb_byte **start, size_t *length); - - /* Return the CFA for the frame. */ - CORE_ADDR (*get_frame_cfa) (void *baton); - - /* Return the PC for the frame. */ - CORE_ADDR (*get_frame_pc) (void *baton); - - /* Return the thread-local storage address for - DW_OP_GNU_push_tls_address. */ - CORE_ADDR (*get_tls_address) (void *baton, CORE_ADDR offset); - - /* Execute DW_AT_location expression for the DWARF expression subroutine in - the DIE at DIE_OFFSET in the CU from CTX. Do not touch STACK while it - being passed to and returned from the called DWARF subroutine. */ - void (*dwarf_call) (struct dwarf_expr_context *ctx, size_t die_offset); - -#if 0 - /* Not yet implemented. */ - - /* Return the `object address' for DW_OP_push_object_address. */ - CORE_ADDR (*get_object_address) (void *baton); -#endif + /* Callback functions. */ + const struct dwarf_expr_context_funcs *funcs; /* The current depth of dwarf expression recursion, via DW_OP_call*, DW_OP_fbreg, DW_OP_push_object_address, etc., and the maximum @@ -180,9 +212,11 @@ struct dwarf_expr_piece int in_stack_memory; } mem; - /* The piece's register number or literal value, for - DWARF_VALUE_REGISTER or DWARF_VALUE_STACK pieces. */ - ULONGEST value; + /* The piece's register number, for DWARF_VALUE_REGISTER pieces. */ + int regno; + + /* The piece's literal value, for DWARF_VALUE_STACK pieces. */ + struct value *value; struct { @@ -214,12 +248,12 @@ void free_dwarf_expr_context (struct dwarf_expr_context *ctx); struct cleanup * make_cleanup_free_dwarf_expr_context (struct dwarf_expr_context *ctx); -void dwarf_expr_push (struct dwarf_expr_context *ctx, ULONGEST value, - int in_stack_memory); -void dwarf_expr_pop (struct dwarf_expr_context *ctx); +void dwarf_expr_push_address (struct dwarf_expr_context *ctx, + CORE_ADDR value, + int in_stack_memory); void dwarf_expr_eval (struct dwarf_expr_context *ctx, const gdb_byte *addr, size_t len); -ULONGEST dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n); +struct value *dwarf_expr_fetch (struct dwarf_expr_context *ctx, int n); CORE_ADDR dwarf_expr_fetch_address (struct dwarf_expr_context *ctx, int n); int dwarf_expr_fetch_in_stack_memory (struct dwarf_expr_context *ctx, int n); @@ -234,4 +268,30 @@ const char *dwarf_stack_op_name (unsigned int); void dwarf_expr_require_composition (const gdb_byte *, const gdb_byte *, const char *); +/* Stub dwarf_expr_context_funcs implementations. */ + +void ctx_no_get_frame_base (void *baton, const gdb_byte **start, + size_t *length); +CORE_ADDR ctx_no_get_frame_cfa (void *baton); +CORE_ADDR ctx_no_get_frame_pc (void *baton); +CORE_ADDR ctx_no_get_tls_address (void *baton, CORE_ADDR offset); +void ctx_no_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset); +struct type *ctx_no_get_base_type (struct dwarf_expr_context *ctx, size_t die); +void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, + int dwarf_reg, CORE_ADDR fb_offset, + int deref_size); + +int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end); + +int dwarf_block_to_dwarf_reg_deref (const gdb_byte *buf, + const gdb_byte *buf_end, + CORE_ADDR *deref_size_return); + +int dwarf_block_to_fb_offset (const gdb_byte *buf, const gdb_byte *buf_end, + CORE_ADDR *fb_offset_return); + +int dwarf_block_to_sp_offset (struct gdbarch *gdbarch, const gdb_byte *buf, + const gdb_byte *buf_end, + CORE_ADDR *sp_offset_return); + #endif /* dwarf2expr.h */ diff --git a/contrib/gdb-7/gdb/dwarf2loc.c b/contrib/gdb-7/gdb/dwarf2loc.c index 4c13307bb0..313df7b490 100644 --- a/contrib/gdb-7/gdb/dwarf2loc.c +++ b/contrib/gdb-7/gdb/dwarf2loc.c @@ -1,7 +1,6 @@ /* DWARF 2 location expression support for GDB. - Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2007-2012 Free Software Foundation, Inc. Contributed by Daniel Jacobowitz, MontaVista Software, Inc. @@ -33,6 +32,7 @@ #include "objfiles.h" #include "exceptions.h" #include "block.h" +#include "gdbcmd.h" #include "dwarf2.h" #include "dwarf2expr.h" @@ -44,15 +44,17 @@ extern int dwarf2_always_disassemble; -static void -dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, - const gdb_byte **start, size_t *length); +static void dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, + const gdb_byte **start, size_t *length); -static struct value * -dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, - const gdb_byte *data, unsigned short size, - struct dwarf2_per_cu_data *per_cu, - LONGEST byte_offset); +static const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs; + +static struct value *dwarf2_evaluate_loc_desc_full (struct type *type, + struct frame_info *frame, + const gdb_byte *data, + unsigned short size, + struct dwarf2_per_cu_data *per_cu, + LONGEST byte_offset); /* A function for dealing with location lists. Given a symbol baton (BATON) and a pc value (PC), find the appropriate @@ -109,7 +111,10 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton, /* An end-of-list entry. */ if (low == 0 && high == 0) - return NULL; + { + *locexpr_length = 0; + return NULL; + } /* Otherwise, a location expression entry. */ low += base_address; @@ -118,6 +123,24 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton, length = extract_unsigned_integer (loc_ptr, 2, byte_order); loc_ptr += 2; + if (low == high && pc == low) + { + /* This is entry PC record present only at entry point + of a function. Verify it is really the function entry point. */ + + struct block *pc_block = block_for_pc (pc); + struct symbol *pc_func = NULL; + + if (pc_block) + pc_func = block_linkage_function (pc_block); + + if (pc_func && pc == BLOCK_START (SYMBOL_BLOCK_VALUE (pc_func))) + { + *locexpr_length = length; + return loc_ptr; + } + } + if (pc >= low && pc < high) { *locexpr_length = length; @@ -194,7 +217,7 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, const gdb_byte **start, size_t *length) { if (SYMBOL_LOCATION_BATON (framefunc) == NULL) - *start = NULL; + *length = 0; else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_loclist_funcs) { struct dwarf2_loclist_baton *symbaton; @@ -213,10 +236,10 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, *start = symbaton->data; } else - *start = NULL; + *length = 0; } - if (*start == NULL) + if (*length == 0) error (_("Could not find the frame base for \"%s\"."), SYMBOL_NATURAL_NAME (framefunc)); } @@ -283,7 +306,849 @@ dwarf_expr_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) struct dwarf_expr_baton *debaton = ctx->baton; per_cu_dwarf_call (ctx, die_offset, debaton->per_cu, - ctx->get_frame_pc, ctx->baton); + ctx->funcs->get_frame_pc, ctx->baton); +} + +/* Callback function for dwarf2_evaluate_loc_desc. */ + +static struct type * +dwarf_expr_get_base_type (struct dwarf_expr_context *ctx, size_t die_offset) +{ + struct dwarf_expr_baton *debaton = ctx->baton; + + return dwarf2_get_die_type (die_offset, debaton->per_cu); +} + +/* See dwarf2loc.h. */ + +int entry_values_debug = 0; + +/* Helper to set entry_values_debug. */ + +static void +show_entry_values_debug (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("Entry values and tail call frames debugging is %s.\n"), + value); +} + +/* Find DW_TAG_GNU_call_site's DW_AT_GNU_call_site_target address. + CALLER_FRAME (for registers) can be NULL if it is not known. This function + always returns valid address or it throws NO_ENTRY_VALUE_ERROR. */ + +static CORE_ADDR +call_site_to_target_addr (struct gdbarch *call_site_gdbarch, + struct call_site *call_site, + struct frame_info *caller_frame) +{ + switch (FIELD_LOC_KIND (call_site->target)) + { + case FIELD_LOC_KIND_DWARF_BLOCK: + { + struct dwarf2_locexpr_baton *dwarf_block; + struct value *val; + struct type *caller_core_addr_type; + struct gdbarch *caller_arch; + + dwarf_block = FIELD_DWARF_BLOCK (call_site->target); + if (dwarf_block == NULL) + { + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol_by_pc (call_site->pc - 1); + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_AT_GNU_call_site_target is not specified " + "at %s in %s"), + paddress (call_site_gdbarch, call_site->pc), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + + } + if (caller_frame == NULL) + { + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol_by_pc (call_site->pc - 1); + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_AT_GNU_call_site_target DWARF block resolving " + "requires known frame which is currently not " + "available at %s in %s"), + paddress (call_site_gdbarch, call_site->pc), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + + } + caller_arch = get_frame_arch (caller_frame); + caller_core_addr_type = builtin_type (caller_arch)->builtin_func_ptr; + val = dwarf2_evaluate_loc_desc (caller_core_addr_type, caller_frame, + dwarf_block->data, dwarf_block->size, + dwarf_block->per_cu); + /* DW_AT_GNU_call_site_target is a DWARF expression, not a DWARF + location. */ + if (VALUE_LVAL (val) == lval_memory) + return value_address (val); + else + return value_as_address (val); + } + + case FIELD_LOC_KIND_PHYSNAME: + { + const char *physname; + struct minimal_symbol *msym; + + physname = FIELD_STATIC_PHYSNAME (call_site->target); + msym = lookup_minimal_symbol_text (physname, NULL); + if (msym == NULL) + { + msym = lookup_minimal_symbol_by_pc (call_site->pc - 1); + throw_error (NO_ENTRY_VALUE_ERROR, + _("Cannot find function \"%s\" for a call site target " + "at %s in %s"), + physname, paddress (call_site_gdbarch, call_site->pc), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + + } + return SYMBOL_VALUE_ADDRESS (msym); + } + + case FIELD_LOC_KIND_PHYSADDR: + return FIELD_STATIC_PHYSADDR (call_site->target); + + default: + internal_error (__FILE__, __LINE__, _("invalid call site target kind")); + } +} + +/* Convert function entry point exact address ADDR to the function which is + compliant with TAIL_CALL_LIST_COMPLETE condition. Throw + NO_ENTRY_VALUE_ERROR otherwise. */ + +static struct symbol * +func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + struct symbol *sym = find_pc_function (addr); + struct type *type; + + if (sym == NULL || BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) != addr) + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_TAG_GNU_call_site resolving failed to find function " + "name for address %s"), + paddress (gdbarch, addr)); + + type = SYMBOL_TYPE (sym); + gdb_assert (TYPE_CODE (type) == TYPE_CODE_FUNC); + gdb_assert (TYPE_SPECIFIC_FIELD (type) == TYPE_SPECIFIC_FUNC); + + return sym; +} + +/* Verify function with entry point exact address ADDR can never call itself + 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 + 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. */ + +static void +func_verify_no_selftailcall (struct gdbarch *gdbarch, CORE_ADDR verify_addr) +{ + struct obstack addr_obstack; + struct cleanup *old_chain; + CORE_ADDR addr; + + /* Track here CORE_ADDRs which were already visited. */ + htab_t addr_hash; + + /* The verification is completely unordered. Track here function addresses + which still need to be iterated. */ + VEC (CORE_ADDR) *todo = NULL; + + obstack_init (&addr_obstack); + old_chain = make_cleanup_obstack_free (&addr_obstack); + addr_hash = htab_create_alloc_ex (64, core_addr_hash, core_addr_eq, NULL, + &addr_obstack, hashtab_obstack_allocate, + NULL); + make_cleanup_htab_delete (addr_hash); + + make_cleanup (VEC_cleanup (CORE_ADDR), &todo); + + VEC_safe_push (CORE_ADDR, todo, verify_addr); + while (!VEC_empty (CORE_ADDR, todo)) + { + struct symbol *func_sym; + struct call_site *call_site; + + addr = VEC_pop (CORE_ADDR, todo); + + func_sym = func_addr_to_tail_call_list (gdbarch, addr); + + for (call_site = TYPE_TAIL_CALL_LIST (SYMBOL_TYPE (func_sym)); + call_site; call_site = call_site->tail_call_next) + { + CORE_ADDR target_addr; + void **slot; + + /* CALLER_FRAME with registers is not available for tail-call jumped + frames. */ + target_addr = call_site_to_target_addr (gdbarch, call_site, NULL); + + if (target_addr == verify_addr) + { + struct minimal_symbol *msym; + + msym = lookup_minimal_symbol_by_pc (verify_addr); + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_OP_GNU_entry_value resolving has found " + "function \"%s\" at %s can call itself via tail " + "calls"), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym), + paddress (gdbarch, verify_addr)); + } + + slot = htab_find_slot (addr_hash, &target_addr, INSERT); + if (*slot == NULL) + { + *slot = obstack_copy (&addr_obstack, &target_addr, + sizeof (target_addr)); + VEC_safe_push (CORE_ADDR, todo, target_addr); + } + } + } + + do_cleanups (old_chain); +} + +/* Print user readable form of CALL_SITE->PC to gdb_stdlog. Used only for + ENTRY_VALUES_DEBUG. */ + +static void +tailcall_dump (struct gdbarch *gdbarch, const struct call_site *call_site) +{ + CORE_ADDR addr = call_site->pc; + struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (addr - 1); + + fprintf_unfiltered (gdb_stdlog, " %s(%s)", paddress (gdbarch, addr), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + +} + +/* vec.h needs single word type name, typedef it. */ +typedef struct call_site *call_sitep; + +/* Define VEC (call_sitep) functions. */ +DEF_VEC_P (call_sitep); + +/* Intersect RESULTP with CHAIN to keep RESULTP unambiguous, keep in RESULTP + only top callers and bottom callees which are present in both. GDBARCH is + used only for ENTRY_VALUES_DEBUG. RESULTP is NULL after return if there are + no remaining possibilities to provide unambiguous non-trivial result. + RESULTP should point to NULL on the first (initialization) call. Caller is + responsible for xfree of any RESULTP data. */ + +static void +chain_candidate (struct gdbarch *gdbarch, struct call_site_chain **resultp, + VEC (call_sitep) *chain) +{ + struct call_site_chain *result = *resultp; + long length = VEC_length (call_sitep, chain); + int callers, callees, idx; + + if (result == NULL) + { + /* Create the initial chain containing all the passed PCs. */ + + result = xmalloc (sizeof (*result) + sizeof (*result->call_site) + * (length - 1)); + result->length = length; + result->callers = result->callees = length; + memcpy (result->call_site, VEC_address (call_sitep, chain), + sizeof (*result->call_site) * length); + *resultp = result; + + if (entry_values_debug) + { + fprintf_unfiltered (gdb_stdlog, "tailcall: initial:"); + for (idx = 0; idx < length; idx++) + tailcall_dump (gdbarch, result->call_site[idx]); + fputc_unfiltered ('\n', gdb_stdlog); + } + + return; + } + + if (entry_values_debug) + { + fprintf_unfiltered (gdb_stdlog, "tailcall: compare:"); + for (idx = 0; idx < length; idx++) + tailcall_dump (gdbarch, VEC_index (call_sitep, chain, idx)); + fputc_unfiltered ('\n', gdb_stdlog); + } + + /* Intersect callers. */ + + callers = min (result->callers, length); + for (idx = 0; idx < callers; idx++) + if (result->call_site[idx] != VEC_index (call_sitep, chain, idx)) + { + result->callers = idx; + break; + } + + /* Intersect callees. */ + + callees = min (result->callees, length); + for (idx = 0; idx < callees; idx++) + if (result->call_site[result->length - 1 - idx] + != VEC_index (call_sitep, chain, length - 1 - idx)) + { + result->callees = idx; + break; + } + + if (entry_values_debug) + { + fprintf_unfiltered (gdb_stdlog, "tailcall: reduced:"); + for (idx = 0; idx < result->callers; idx++) + tailcall_dump (gdbarch, result->call_site[idx]); + fputs_unfiltered (" |", gdb_stdlog); + for (idx = 0; idx < result->callees; idx++) + tailcall_dump (gdbarch, result->call_site[result->length + - result->callees + idx]); + fputc_unfiltered ('\n', gdb_stdlog); + } + + if (result->callers == 0 && result->callees == 0) + { + /* There are no common callers or callees. It could be also a direct + call (which has length 0) with ambiguous possibility of an indirect + call - CALLERS == CALLEES == 0 is valid during the first allocation + but any subsequence processing of such entry means ambiguity. */ + xfree (result); + *resultp = NULL; + return; + } + + /* See call_site_find_chain_1 why there is no way to reach the bottom callee + PC again. In such case there must be two different code paths to reach + it, therefore some of the former determined intermediate PCs must differ + and the unambiguous chain gets shortened. */ + gdb_assert (result->callers + result->callees < result->length); +} + +/* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All the + assumed frames between them use GDBARCH. Use depth first search so we can + keep single CHAIN of call_site's back to CALLER_PC. Function recursion + would have needless GDB stack overhead. Caller is responsible for xfree of + the returned result. Any unreliability results in thrown + NO_ENTRY_VALUE_ERROR. */ + +static struct call_site_chain * +call_site_find_chain_1 (struct gdbarch *gdbarch, CORE_ADDR caller_pc, + CORE_ADDR callee_pc) +{ + struct func_type *func_specific; + struct obstack addr_obstack; + struct cleanup *back_to_retval, *back_to_workdata; + struct call_site_chain *retval = NULL; + struct call_site *call_site; + + /* Mark CALL_SITEs so we do not visit the same ones twice. */ + htab_t addr_hash; + + /* CHAIN contains only the intermediate CALL_SITEs. Neither CALLER_PC's + call_site nor any possible call_site at CALLEE_PC's function is there. + Any CALL_SITE in CHAIN will be iterated to its siblings - via + TAIL_CALL_NEXT. This is inappropriate for CALLER_PC's call_site. */ + VEC (call_sitep) *chain = NULL; + + /* We are not interested in the specific PC inside the callee function. */ + callee_pc = get_pc_function_start (callee_pc); + if (callee_pc == 0) + throw_error (NO_ENTRY_VALUE_ERROR, _("Unable to find function for PC %s"), + paddress (gdbarch, callee_pc)); + + back_to_retval = make_cleanup (free_current_contents, &retval); + + obstack_init (&addr_obstack); + back_to_workdata = make_cleanup_obstack_free (&addr_obstack); + addr_hash = htab_create_alloc_ex (64, core_addr_hash, core_addr_eq, NULL, + &addr_obstack, hashtab_obstack_allocate, + NULL); + make_cleanup_htab_delete (addr_hash); + + make_cleanup (VEC_cleanup (call_sitep), &chain); + + /* Do not push CALL_SITE to CHAIN. Push there only the first tail call site + at the target's function. All the possible tail call sites in the + target's function will get iterated as already pushed into CHAIN via their + TAIL_CALL_NEXT. */ + call_site = call_site_for_pc (gdbarch, caller_pc); + + while (call_site) + { + CORE_ADDR target_func_addr; + struct call_site *target_call_site; + + /* CALLER_FRAME with registers is not available for tail-call jumped + frames. */ + target_func_addr = call_site_to_target_addr (gdbarch, call_site, NULL); + + if (target_func_addr == callee_pc) + { + chain_candidate (gdbarch, &retval, chain); + if (retval == NULL) + break; + + /* There is no way to reach CALLEE_PC again as we would prevent + entering it twice as being already marked in ADDR_HASH. */ + target_call_site = NULL; + } + else + { + struct symbol *target_func; + + target_func = func_addr_to_tail_call_list (gdbarch, target_func_addr); + target_call_site = TYPE_TAIL_CALL_LIST (SYMBOL_TYPE (target_func)); + } + + do + { + /* Attempt to visit TARGET_CALL_SITE. */ + + if (target_call_site) + { + void **slot; + + slot = htab_find_slot (addr_hash, &target_call_site->pc, INSERT); + if (*slot == NULL) + { + /* Successfully entered TARGET_CALL_SITE. */ + + *slot = &target_call_site->pc; + VEC_safe_push (call_sitep, chain, target_call_site); + break; + } + } + + /* Backtrack (without revisiting the originating call_site). Try the + callers's sibling; if there isn't any try the callers's callers's + sibling etc. */ + + target_call_site = NULL; + while (!VEC_empty (call_sitep, chain)) + { + call_site = VEC_pop (call_sitep, chain); + + gdb_assert (htab_find_slot (addr_hash, &call_site->pc, + NO_INSERT) != NULL); + htab_remove_elt (addr_hash, &call_site->pc); + + target_call_site = call_site->tail_call_next; + if (target_call_site) + break; + } + } + while (target_call_site); + + if (VEC_empty (call_sitep, chain)) + call_site = NULL; + else + call_site = VEC_last (call_sitep, chain); + } + + if (retval == NULL) + { + struct minimal_symbol *msym_caller, *msym_callee; + + msym_caller = lookup_minimal_symbol_by_pc (caller_pc); + 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 " + "and callee function \"%s\" at %s"), + (msym_caller == NULL + ? "???" : SYMBOL_PRINT_NAME (msym_caller)), + paddress (gdbarch, caller_pc), + (msym_callee == NULL + ? "???" : SYMBOL_PRINT_NAME (msym_callee)), + paddress (gdbarch, callee_pc)); + } + + do_cleanups (back_to_workdata); + discard_cleanups (back_to_retval); + return retval; +} + +/* Create and return call_site_chain for CALLER_PC and CALLEE_PC. All the + assumed frames between them use GDBARCH. If valid call_site_chain cannot be + constructed return NULL. Caller is responsible for xfree of the returned + result. */ + +struct call_site_chain * +call_site_find_chain (struct gdbarch *gdbarch, CORE_ADDR caller_pc, + CORE_ADDR callee_pc) +{ + volatile struct gdb_exception e; + struct call_site_chain *retval = NULL; + + TRY_CATCH (e, RETURN_MASK_ERROR) + { + retval = call_site_find_chain_1 (gdbarch, caller_pc, callee_pc); + } + if (e.reason < 0) + { + if (e.error == NO_ENTRY_VALUE_ERROR) + { + if (entry_values_debug) + exception_print (gdb_stdout, e); + + return NULL; + } + else + throw_exception (e); + } + return retval; +} + +/* Fetch call_site_parameter from caller matching the parameters. FRAME is for + callee. See DWARF_REG and FB_OFFSET description at struct + dwarf_expr_context_funcs->push_dwarf_reg_entry_value. + + Function always returns non-NULL, it throws NO_ENTRY_VALUE_ERROR + otherwise. */ + +static struct call_site_parameter * +dwarf_expr_reg_to_entry_parameter (struct frame_info *frame, int dwarf_reg, + CORE_ADDR fb_offset, + struct dwarf2_per_cu_data **per_cu_return) +{ + CORE_ADDR func_addr = get_frame_func (frame); + CORE_ADDR caller_pc; + struct gdbarch *gdbarch = get_frame_arch (frame); + struct frame_info *caller_frame = get_prev_frame (frame); + struct call_site *call_site; + int iparams; + struct value *val; + struct dwarf2_locexpr_baton *dwarf_block; + /* Initialize it just to avoid a GCC false warning. */ + struct call_site_parameter *parameter = NULL; + CORE_ADDR target_addr; + + if (gdbarch != frame_unwind_arch (frame)) + { + struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (func_addr); + struct gdbarch *caller_gdbarch = frame_unwind_arch (frame); + + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_OP_GNU_entry_value resolving callee gdbarch %s " + "(of %s (%s)) does not match caller gdbarch %s"), + gdbarch_bfd_arch_info (gdbarch)->printable_name, + paddress (gdbarch, func_addr), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym), + gdbarch_bfd_arch_info (caller_gdbarch)->printable_name); + } + + if (caller_frame == NULL) + { + struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (func_addr); + + throw_error (NO_ENTRY_VALUE_ERROR, _("DW_OP_GNU_entry_value resolving " + "requires caller of %s (%s)"), + paddress (gdbarch, func_addr), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + } + caller_pc = get_frame_pc (caller_frame); + call_site = call_site_for_pc (gdbarch, caller_pc); + + target_addr = call_site_to_target_addr (gdbarch, call_site, caller_frame); + if (target_addr != func_addr) + { + struct minimal_symbol *target_msym, *func_msym; + + target_msym = lookup_minimal_symbol_by_pc (target_addr); + func_msym = lookup_minimal_symbol_by_pc (func_addr); + throw_error (NO_ENTRY_VALUE_ERROR, + _("DW_OP_GNU_entry_value resolving expects callee %s at %s " + "but the called frame is for %s at %s"), + (target_msym == NULL ? "???" + : SYMBOL_PRINT_NAME (target_msym)), + paddress (gdbarch, target_addr), + func_msym == NULL ? "???" : SYMBOL_PRINT_NAME (func_msym), + paddress (gdbarch, func_addr)); + } + + /* No entry value based parameters would be reliable if this function can + call itself via tail calls. */ + func_verify_no_selftailcall (gdbarch, func_addr); + + for (iparams = 0; iparams < call_site->parameter_count; iparams++) + { + parameter = &call_site->parameter[iparams]; + if (parameter->dwarf_reg == -1 && dwarf_reg == -1) + { + if (parameter->fb_offset == fb_offset) + break; + } + else if (parameter->dwarf_reg == dwarf_reg) + break; + } + if (iparams == call_site->parameter_count) + { + struct minimal_symbol *msym = lookup_minimal_symbol_by_pc (caller_pc); + + /* DW_TAG_GNU_call_site_parameter will be missing just if GCC could not + determine its value. */ + throw_error (NO_ENTRY_VALUE_ERROR, _("Cannot find matching parameter " + "at DW_TAG_GNU_call_site %s at %s"), + paddress (gdbarch, caller_pc), + msym == NULL ? "???" : SYMBOL_PRINT_NAME (msym)); + } + + *per_cu_return = call_site->per_cu; + return parameter; +} + +/* Return value for PARAMETER matching DEREF_SIZE. If DEREF_SIZE is -1, return + the normal DW_AT_GNU_call_site_value block. Otherwise return the + DW_AT_GNU_call_site_data_value (dereferenced) block. + + TYPE and CALLER_FRAME specify how to evaluate the DWARF block into returned + struct value. + + Function always returns non-NULL, non-optimized out value. It throws + NO_ENTRY_VALUE_ERROR if it cannot resolve the value for any reason. */ + +static struct value * +dwarf_entry_parameter_to_value (struct call_site_parameter *parameter, + CORE_ADDR deref_size, struct type *type, + struct frame_info *caller_frame, + struct dwarf2_per_cu_data *per_cu) +{ + const gdb_byte *data_src; + gdb_byte *data; + size_t size; + + data_src = deref_size == -1 ? parameter->value : parameter->data_value; + size = deref_size == -1 ? parameter->value_size : parameter->data_value_size; + + /* DEREF_SIZE size is not verified here. */ + if (data_src == NULL) + throw_error (NO_ENTRY_VALUE_ERROR, + _("Cannot resolve DW_AT_GNU_call_site_data_value")); + + /* DW_AT_GNU_call_site_value is a DWARF expression, not a DWARF + location. Postprocessing of DWARF_VALUE_MEMORY would lose the type from + DWARF block. */ + data = alloca (size + 1); + memcpy (data, data_src, size); + data[size] = DW_OP_stack_value; + + return dwarf2_evaluate_loc_desc (type, caller_frame, data, size + 1, per_cu); +} + +/* Execute call_site_parameter's DWARF block matching DEREF_SIZE for caller of + the CTX's frame. CTX must be of dwarf_expr_ctx_funcs kind. See DWARF_REG + and FB_OFFSET description at struct + dwarf_expr_context_funcs->push_dwarf_reg_entry_value. + + The CTX caller can be from a different CU - per_cu_dwarf_call implementation + can be more simple as it does not support cross-CU DWARF executions. */ + +static void +dwarf_expr_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, + int dwarf_reg, CORE_ADDR fb_offset, + int deref_size) +{ + struct dwarf_expr_baton *debaton; + struct frame_info *frame, *caller_frame; + struct dwarf2_per_cu_data *caller_per_cu; + struct dwarf_expr_baton baton_local; + struct dwarf_expr_context saved_ctx; + struct call_site_parameter *parameter; + const gdb_byte *data_src; + size_t size; + + gdb_assert (ctx->funcs == &dwarf_expr_ctx_funcs); + debaton = ctx->baton; + frame = debaton->frame; + caller_frame = get_prev_frame (frame); + + parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset, + &caller_per_cu); + data_src = deref_size == -1 ? parameter->value : parameter->data_value; + size = deref_size == -1 ? parameter->value_size : parameter->data_value_size; + + /* DEREF_SIZE size is not verified here. */ + if (data_src == NULL) + throw_error (NO_ENTRY_VALUE_ERROR, + _("Cannot resolve DW_AT_GNU_call_site_data_value")); + + baton_local.frame = caller_frame; + baton_local.per_cu = caller_per_cu; + + saved_ctx.gdbarch = ctx->gdbarch; + saved_ctx.addr_size = ctx->addr_size; + saved_ctx.offset = ctx->offset; + saved_ctx.baton = ctx->baton; + ctx->gdbarch = get_objfile_arch (dwarf2_per_cu_objfile (baton_local.per_cu)); + ctx->addr_size = dwarf2_per_cu_addr_size (baton_local.per_cu); + ctx->offset = dwarf2_per_cu_text_offset (baton_local.per_cu); + ctx->baton = &baton_local; + + dwarf_expr_eval (ctx, data_src, size); + + ctx->gdbarch = saved_ctx.gdbarch; + ctx->addr_size = saved_ctx.addr_size; + ctx->offset = saved_ctx.offset; + ctx->baton = saved_ctx.baton; +} + +/* VALUE must be of type lval_computed with entry_data_value_funcs. Perform + the indirect method on it, that is use its stored target value, the sole + purpose of entry_data_value_funcs.. */ + +static struct value * +entry_data_value_coerce_ref (const struct value *value) +{ + struct type *checked_type = check_typedef (value_type (value)); + struct value *target_val; + + if (TYPE_CODE (checked_type) != TYPE_CODE_REF) + return NULL; + + target_val = value_computed_closure (value); + value_incref (target_val); + return target_val; +} + +/* Implement copy_closure. */ + +static void * +entry_data_value_copy_closure (const struct value *v) +{ + struct value *target_val = value_computed_closure (v); + + value_incref (target_val); + return target_val; +} + +/* Implement free_closure. */ + +static void +entry_data_value_free_closure (struct value *v) +{ + struct value *target_val = value_computed_closure (v); + + value_free (target_val); +} + +/* Vector for methods for an entry value reference where the referenced value + is stored in the caller. On the first dereference use + DW_AT_GNU_call_site_data_value in the caller. */ + +static const struct lval_funcs entry_data_value_funcs = +{ + NULL, /* read */ + NULL, /* write */ + NULL, /* check_validity */ + NULL, /* check_any_valid */ + NULL, /* indirect */ + entry_data_value_coerce_ref, + NULL, /* check_synthetic_pointer */ + entry_data_value_copy_closure, + entry_data_value_free_closure +}; + +/* Read parameter of TYPE at (callee) FRAME's function entry. DWARF_REG and + FB_OFFSET are used to match DW_AT_location at the caller's + DW_TAG_GNU_call_site_parameter. See DWARF_REG and FB_OFFSET description at + struct dwarf_expr_context_funcs->push_dwarf_reg_entry_value. + + Function always returns non-NULL value. It throws NO_ENTRY_VALUE_ERROR if it + cannot resolve the parameter for any reason. */ + +static struct value * +value_of_dwarf_reg_entry (struct type *type, struct frame_info *frame, + int dwarf_reg, CORE_ADDR fb_offset) +{ + struct type *checked_type = check_typedef (type); + struct type *target_type = TYPE_TARGET_TYPE (checked_type); + struct frame_info *caller_frame = get_prev_frame (frame); + struct value *outer_val, *target_val, *val; + struct call_site_parameter *parameter; + struct dwarf2_per_cu_data *caller_per_cu; + CORE_ADDR addr; + + parameter = dwarf_expr_reg_to_entry_parameter (frame, dwarf_reg, fb_offset, + &caller_per_cu); + + outer_val = dwarf_entry_parameter_to_value (parameter, -1 /* deref_size */, + type, caller_frame, + caller_per_cu); + + /* Check if DW_AT_GNU_call_site_data_value cannot be used. If it should be + used and it is not available do not fall back to OUTER_VAL - dereferencing + TYPE_CODE_REF with non-entry data value would give current value - not the + entry value. */ + + if (TYPE_CODE (checked_type) != TYPE_CODE_REF + || TYPE_TARGET_TYPE (checked_type) == NULL) + return outer_val; + + target_val = dwarf_entry_parameter_to_value (parameter, + TYPE_LENGTH (target_type), + target_type, caller_frame, + caller_per_cu); + + /* value_as_address dereferences TYPE_CODE_REF. */ + addr = extract_typed_address (value_contents (outer_val), checked_type); + + /* The target entry value has artificial address of the entry value + reference. */ + VALUE_LVAL (target_val) = lval_memory; + set_value_address (target_val, addr); + + release_value (target_val); + val = allocate_computed_value (type, &entry_data_value_funcs, + target_val /* closure */); + + /* Copy the referencing pointer to the new computed value. */ + memcpy (value_contents_raw (val), value_contents_raw (outer_val), + TYPE_LENGTH (checked_type)); + set_value_lazy (val, 0); + + return val; +} + +/* Read parameter of TYPE at (callee) FRAME's function entry. DATA and + SIZE are DWARF block used to match DW_AT_location at the caller's + DW_TAG_GNU_call_site_parameter. + + Function always returns non-NULL value. It throws NO_ENTRY_VALUE_ERROR if it + cannot resolve the parameter for any reason. */ + +static struct value * +value_of_dwarf_block_entry (struct type *type, struct frame_info *frame, + const gdb_byte *block, size_t block_len) +{ + int dwarf_reg; + CORE_ADDR fb_offset; + + dwarf_reg = dwarf_block_to_dwarf_reg (block, block + block_len); + if (dwarf_reg != -1) + return value_of_dwarf_reg_entry (type, frame, dwarf_reg, 0 /* unused */); + + if (dwarf_block_to_fb_offset (block, block + block_len, &fb_offset)) + return value_of_dwarf_reg_entry (type, frame, -1, fb_offset); + + /* This can normally happen - throw NO_ENTRY_VALUE_ERROR to get the message + suppressed during normal operation. The expression can be arbitrary if + there is no caller-callee entry value binding expected. */ + throw_error (NO_ENTRY_VALUE_ERROR, + _("DWARF-2 expression error: DW_OP_GNU_entry_value is supported " + "only for single DW_OP_reg* or for DW_OP_fbreg(*)")); } struct piece_closure @@ -313,6 +1178,7 @@ allocate_piece_closure (struct dwarf2_per_cu_data *per_cu, int addr_size) { struct piece_closure *c = XZALLOC (struct piece_closure); + int i; c->refc = 1; c->per_cu = per_cu; @@ -321,6 +1187,9 @@ allocate_piece_closure (struct dwarf2_per_cu_data *per_cu, c->pieces = XCALLOC (n_pieces, struct dwarf_expr_piece); memcpy (c->pieces, pieces, n_pieces * sizeof (struct dwarf_expr_piece)); + for (i = 0; i < n_pieces; ++i) + if (c->pieces[i].location == DWARF_VALUE_STACK) + value_incref (c->pieces[i].v.value); return c; } @@ -576,7 +1445,7 @@ read_pieced_value (struct value *v) case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value); + int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno); int reg_offset = source_offset; if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG @@ -609,7 +1478,7 @@ read_pieced_value (struct value *v) else { error (_("Unable to access DWARF register number %s"), - paddress (arch, p->v.value)); + paddress (arch, p->v.regno)); } } break; @@ -623,7 +1492,6 @@ read_pieced_value (struct value *v) case DWARF_VALUE_STACK: { - struct gdbarch *gdbarch = get_type_arch (value_type (v)); size_t n = this_size; if (n > c->addr_size - source_offset) @@ -634,18 +1502,11 @@ read_pieced_value (struct value *v) { /* Nothing. */ } - else if (source_offset == 0) - store_unsigned_integer (buffer, n, - gdbarch_byte_order (gdbarch), - p->v.value); else { - gdb_byte bytes[sizeof (ULONGEST)]; + const gdb_byte *val_bytes = value_contents_all (p->v.value); - store_unsigned_integer (bytes, n + source_offset, - gdbarch_byte_order (gdbarch), - p->v.value); - memcpy (buffer, bytes + source_offset, n); + intermediate_buffer = val_bytes + source_offset; } } break; @@ -776,7 +1637,7 @@ write_pieced_value (struct value *to, struct value *from) case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.value); + int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, p->v.regno); int reg_offset = dest_offset; if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG @@ -816,7 +1677,7 @@ write_pieced_value (struct value *to, struct value *from) else { error (_("Unable to write to DWARF register number %s"), - paddress (arch, p->v.value)); + paddress (arch, p->v.regno)); } } break; @@ -958,10 +1819,9 @@ indirect_pieced_value (struct value *value) struct dwarf2_locexpr_baton baton; int i, bit_offset, bit_length; struct dwarf_expr_piece *piece = NULL; - struct value *result; LONGEST byte_offset; - type = value_type (value); + type = check_typedef (value_type (value)); if (TYPE_CODE (type) != TYPE_CODE_PTR) return NULL; @@ -1000,6 +1860,8 @@ indirect_pieced_value (struct value *value) } frame = get_selected_frame (_("No frame selected.")); + + /* This is an offset requested by GDB, such as value subcripts. */ byte_offset = value_as_address (value); gdb_assert (piece); @@ -1007,11 +1869,9 @@ indirect_pieced_value (struct value *value) get_frame_address_in_block_wrapper, frame); - result = dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame, - baton.data, baton.size, baton.per_cu, - byte_offset); - - return result; + return dwarf2_evaluate_loc_desc_full (TYPE_TARGET_TYPE (type), frame, + baton.data, baton.size, baton.per_cu, + piece->v.ptr.offset + byte_offset); } static void * @@ -1033,18 +1893,25 @@ free_pieced_value_closure (struct value *v) --c->refc; if (c->refc == 0) { + int i; + + for (i = 0; i < c->n_pieces; ++i) + if (c->pieces[i].location == DWARF_VALUE_STACK) + value_free (c->pieces[i].v.value); + xfree (c->pieces); xfree (c); } } /* Functions for accessing a variable described by DW_OP_piece. */ -static struct lval_funcs pieced_value_funcs = { +static const struct lval_funcs pieced_value_funcs = { read_pieced_value, write_pieced_value, check_pieced_value_validity, check_pieced_value_invalid, indirect_pieced_value, + NULL, /* coerce_ref */ check_pieced_synthetic_pointer, copy_pieced_value_closure, free_pieced_value_closure @@ -1060,6 +1927,21 @@ invalid_synthetic_pointer (void) "referenced via synthetic pointer")); } +/* Virtual method table for dwarf2_evaluate_loc_desc_full below. */ + +static const struct dwarf_expr_context_funcs dwarf_expr_ctx_funcs = +{ + dwarf_expr_read_reg, + dwarf_expr_read_mem, + dwarf_expr_frame_base, + dwarf_expr_frame_cfa, + dwarf_expr_frame_pc, + dwarf_expr_tls_address, + dwarf_expr_dwarf_call, + dwarf_expr_get_base_type, + dwarf_expr_push_dwarf_reg_entry_value +}; + /* Evaluate a location description, starting at DATA and with length SIZE, to find the current location of variable of TYPE in the context of FRAME. BYTE_OFFSET is applied after the contents are @@ -1074,7 +1956,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, struct value *retval; struct dwarf_expr_baton baton; struct dwarf_expr_context *ctx; - struct cleanup *old_chain; + struct cleanup *old_chain, *value_chain; struct objfile *objfile = dwarf2_per_cu_objfile (per_cu); volatile struct gdb_exception ex; @@ -1082,30 +1964,21 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, invalid_synthetic_pointer (); if (size == 0) - { - retval = allocate_value (type); - VALUE_LVAL (retval) = not_lval; - set_value_optimized_out (retval, 1); - return retval; - } + return allocate_optimized_out_value (type); baton.frame = frame; baton.per_cu = per_cu; ctx = new_dwarf_expr_context (); old_chain = make_cleanup_free_dwarf_expr_context (ctx); + value_chain = make_cleanup_value_free_to_mark (value_mark ()); ctx->gdbarch = get_objfile_arch (objfile); ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); + ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu); ctx->offset = dwarf2_per_cu_text_offset (per_cu); ctx->baton = &baton; - ctx->read_reg = dwarf_expr_read_reg; - ctx->read_mem = dwarf_expr_read_mem; - ctx->get_frame_base = dwarf_expr_frame_base; - ctx->get_frame_cfa = dwarf_expr_frame_cfa; - ctx->get_frame_pc = dwarf_expr_frame_pc; - ctx->get_tls_address = dwarf_expr_tls_address; - ctx->dwarf_call = dwarf_expr_dwarf_call; + ctx->funcs = &dwarf_expr_ctx_funcs; TRY_CATCH (ex, RETURN_MASK_ERROR) { @@ -1115,10 +1988,18 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, { if (ex.error == NOT_AVAILABLE_ERROR) { + do_cleanups (old_chain); retval = allocate_value (type); mark_value_bytes_unavailable (retval, 0, TYPE_LENGTH (type)); return retval; } + else if (ex.error == NO_ENTRY_VALUE_ERROR) + { + if (entry_values_debug) + exception_print (gdb_stdout, ex); + do_cleanups (old_chain); + return allocate_optimized_out_value (type); + } else throw_exception (ex); } @@ -1137,6 +2018,9 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, c = allocate_piece_closure (per_cu, ctx->num_pieces, ctx->pieces, ctx->addr_size); + /* We must clean up the value chain after creating the piece + closure but before allocating the result. */ + do_cleanups (value_chain); retval = allocate_computed_value (type, &pieced_value_funcs, c); VALUE_FRAME_ID (retval) = frame_id; set_value_offset (retval, byte_offset); @@ -1148,11 +2032,12 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, case DWARF_VALUE_REGISTER: { struct gdbarch *arch = get_frame_arch (frame); - ULONGEST dwarf_regnum = dwarf_expr_fetch (ctx, 0); + ULONGEST dwarf_regnum = value_as_long (dwarf_expr_fetch (ctx, 0)); int gdb_regnum = gdbarch_dwarf2_reg_to_regnum (arch, dwarf_regnum); if (byte_offset != 0) error (_("cannot use offset on synthetic pointer to register")); + do_cleanups (value_chain); if (gdb_regnum != -1) retval = value_from_register (type, gdb_regnum, frame); else @@ -1166,6 +2051,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, CORE_ADDR address = dwarf_expr_fetch_address (ctx, 0); int in_stack_memory = dwarf_expr_fetch_in_stack_memory (ctx, 0); + do_cleanups (value_chain); retval = allocate_value_lazy (type); VALUE_LVAL (retval) = lval_memory; if (in_stack_memory) @@ -1176,26 +2062,36 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, case DWARF_VALUE_STACK: { - ULONGEST value = dwarf_expr_fetch (ctx, 0); - bfd_byte *contents, *tem; - size_t n = ctx->addr_size; + struct value *value = dwarf_expr_fetch (ctx, 0); + gdb_byte *contents; + const gdb_byte *val_bytes; + size_t n = TYPE_LENGTH (value_type (value)); if (byte_offset + TYPE_LENGTH (type) > n) invalid_synthetic_pointer (); - tem = alloca (n); - store_unsigned_integer (tem, n, - gdbarch_byte_order (ctx->gdbarch), - value); - - tem += byte_offset; + val_bytes = value_contents_all (value); + val_bytes += byte_offset; n -= byte_offset; + /* Preserve VALUE because we are going to free values back + to the mark, but we still need the value contents + below. */ + value_incref (value); + do_cleanups (value_chain); + make_cleanup_value_free (value); + retval = allocate_value (type); contents = value_contents_raw (retval); if (n > TYPE_LENGTH (type)) - n = TYPE_LENGTH (type); - memcpy (contents, tem, n); + { + struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile); + + if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG) + val_bytes += n - TYPE_LENGTH (type); + n = TYPE_LENGTH (type); + } + memcpy (contents, val_bytes, n); } break; @@ -1208,6 +2104,7 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, if (byte_offset + TYPE_LENGTH (type) > n) invalid_synthetic_pointer (); + do_cleanups (value_chain); retval = allocate_value (type); contents = value_contents_raw (retval); @@ -1215,15 +2112,20 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, n -= byte_offset; if (n > TYPE_LENGTH (type)) - n = TYPE_LENGTH (type); + { + struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile); + + if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG) + ldata += n - TYPE_LENGTH (type); + n = TYPE_LENGTH (type); + } memcpy (contents, ldata, n); } break; case DWARF_VALUE_OPTIMIZED_OUT: - retval = allocate_value (type); - VALUE_LVAL (retval) = not_lval; - set_value_optimized_out (retval, 1); + do_cleanups (value_chain); + retval = allocate_optimized_out_value (type); break; /* DWARF_VALUE_IMPLICIT_POINTER was converted to a pieced @@ -1322,9 +2224,35 @@ needs_frame_dwarf_call (struct dwarf_expr_context *ctx, size_t die_offset) struct needs_frame_baton *nf_baton = ctx->baton; per_cu_dwarf_call (ctx, die_offset, nf_baton->per_cu, - ctx->get_frame_pc, ctx->baton); + ctx->funcs->get_frame_pc, ctx->baton); } +/* DW_OP_GNU_entry_value accesses require a caller, therefore a frame. */ + +static void +needs_dwarf_reg_entry_value (struct dwarf_expr_context *ctx, + int dwarf_reg, CORE_ADDR fb_offset, int deref_size) +{ + struct needs_frame_baton *nf_baton = ctx->baton; + + nf_baton->needs_frame = 1; +} + +/* Virtual method table for dwarf2_loc_desc_needs_frame below. */ + +static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs = +{ + needs_frame_read_reg, + needs_frame_read_mem, + needs_frame_frame_base, + needs_frame_frame_cfa, + needs_frame_frame_cfa, /* get_frame_pc */ + needs_frame_tls_address, + needs_frame_dwarf_call, + NULL, /* get_base_type */ + needs_dwarf_reg_entry_value +}; + /* Return non-zero iff the location expression at DATA (length SIZE) requires a frame to evaluate. */ @@ -1343,18 +2271,14 @@ dwarf2_loc_desc_needs_frame (const gdb_byte *data, unsigned short size, ctx = new_dwarf_expr_context (); old_chain = make_cleanup_free_dwarf_expr_context (ctx); + make_cleanup_value_free_to_mark (value_mark ()); ctx->gdbarch = get_objfile_arch (objfile); ctx->addr_size = dwarf2_per_cu_addr_size (per_cu); + ctx->ref_addr_size = dwarf2_per_cu_ref_addr_size (per_cu); ctx->offset = dwarf2_per_cu_text_offset (per_cu); ctx->baton = &baton; - ctx->read_reg = needs_frame_read_reg; - ctx->read_mem = needs_frame_read_mem; - ctx->get_frame_base = needs_frame_frame_base; - ctx->get_frame_cfa = needs_frame_frame_cfa; - ctx->get_frame_pc = needs_frame_frame_cfa; - ctx->get_tls_address = needs_frame_tls_address; - ctx->dwarf_call = needs_frame_dwarf_call; + ctx->funcs = &needs_frame_ctx_funcs; dwarf_expr_eval (ctx, data, size); @@ -2139,6 +3063,19 @@ locexpr_read_variable (struct symbol *symbol, struct frame_info *frame) return val; } +/* Return the value of SYMBOL in FRAME at (callee) FRAME's function + entry. SYMBOL should be a function parameter, otherwise NO_ENTRY_VALUE_ERROR + will be thrown. */ + +static struct value * +locexpr_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame) +{ + struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + + return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, dlbaton->data, + dlbaton->size); +} + /* Return non-zero iff we need a frame to evaluate SYMBOL. */ static int locexpr_read_needs_frame (struct symbol *symbol) @@ -2158,6 +3095,18 @@ piece_end_p (const gdb_byte *data, const gdb_byte *end) return data == end || data[0] == DW_OP_piece || data[0] == DW_OP_bit_piece; } +/* Helper for locexpr_describe_location_piece that finds the name of a + DWARF register. */ + +static const char * +locexpr_regname (struct gdbarch *gdbarch, int dwarf_regnum) +{ + int regnum; + + regnum = gdbarch_dwarf2_reg_to_regnum (gdbarch, dwarf_regnum); + return gdbarch_register_name (gdbarch, regnum); +} + /* Nicely describe a single piece of a location, returning an updated position in the bytecode sequence. This function cannot recognize all locations; if a location is not recognized, it simply returns @@ -2170,13 +3119,11 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, unsigned int addr_size) { struct gdbarch *gdbarch = get_objfile_arch (objfile); - int regno; if (data[0] >= DW_OP_reg0 && data[0] <= DW_OP_reg31) { - regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_reg0); fprintf_filtered (stream, _("a variable in $%s"), - gdbarch_register_name (gdbarch, regno)); + locexpr_regname (gdbarch, data[0] - DW_OP_reg0)); data += 1; } else if (data[0] == DW_OP_regx) @@ -2184,9 +3131,8 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, ULONGEST reg; data = read_uleb128 (data + 1, end, ®); - regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, reg); fprintf_filtered (stream, _("a variable in $%s"), - gdbarch_register_name (gdbarch, regno)); + locexpr_regname (gdbarch, reg)); } else if (data[0] == DW_OP_fbreg) { @@ -2242,11 +3188,9 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, return save_data; } - regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, frame_reg); - fprintf_filtered (stream, _("a variable at frame base reg $%s offset %s+%s"), - gdbarch_register_name (gdbarch, regno), + locexpr_regname (gdbarch, frame_reg), plongest (base_offset), plongest (frame_offset)); } else if (data[0] >= DW_OP_breg0 && data[0] <= DW_OP_breg31 @@ -2254,14 +3198,12 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, { LONGEST offset; - regno = gdbarch_dwarf2_reg_to_regnum (gdbarch, data[0] - DW_OP_breg0); - data = read_sleb128 (data + 1, end, &offset); fprintf_filtered (stream, _("a variable at offset %s from base reg $%s"), plongest (offset), - gdbarch_register_name (gdbarch, regno)); + locexpr_regname (gdbarch, data[0] - DW_OP_breg0)); } /* The location expression for a TLS variable looks like this (on a @@ -2316,14 +3258,11 @@ locexpr_describe_location_piece (struct symbol *symbol, struct ui_file *stream, static const gdb_byte * disassemble_dwarf_expression (struct ui_file *stream, struct gdbarch *arch, unsigned int addr_size, - int offset_size, + int offset_size, const gdb_byte *start, const gdb_byte *data, const gdb_byte *end, - int all) + int indent, int all, + struct dwarf2_per_cu_data *per_cu) { - const gdb_byte *start = data; - - fprintf_filtered (stream, _("a complex DWARF expression:\n")); - while (data < end && (all || (data[0] != DW_OP_piece && data[0] != DW_OP_bit_piece))) @@ -2337,8 +3276,9 @@ disassemble_dwarf_expression (struct ui_file *stream, if (!name) error (_("Unrecognized DWARF opcode 0x%02x at %ld"), - op, (long) (data - start)); - fprintf_filtered (stream, " % 4ld: %s", (long) (data - start), name); + op, (long) (data - 1 - start)); + fprintf_filtered (stream, " %*ld: %s", indent + 4, + (long) (data - 1 - start), name); switch (op) { @@ -2431,13 +3371,13 @@ disassemble_dwarf_expression (struct ui_file *stream, case DW_OP_reg30: case DW_OP_reg31: fprintf_filtered (stream, " [$%s]", - gdbarch_register_name (arch, op - DW_OP_reg0)); + locexpr_regname (arch, op - DW_OP_reg0)); break; case DW_OP_regx: data = read_uleb128 (data, end, &ul); fprintf_filtered (stream, " %s [$%s]", pulongest (ul), - gdbarch_register_name (arch, (int) ul)); + locexpr_regname (arch, (int) ul)); break; case DW_OP_implicit_value: @@ -2480,7 +3420,7 @@ disassemble_dwarf_expression (struct ui_file *stream, case DW_OP_breg31: data = read_sleb128 (data, end, &l); fprintf_filtered (stream, " %s [$%s]", plongest (l), - gdbarch_register_name (arch, op - DW_OP_breg0)); + locexpr_regname (arch, op - DW_OP_breg0)); break; case DW_OP_bregx: @@ -2488,7 +3428,7 @@ disassemble_dwarf_expression (struct ui_file *stream, data = read_sleb128 (data, end, &l); fprintf_filtered (stream, " register %s [$%s] offset %s", pulongest (ul), - gdbarch_register_name (arch, (int) ul), + locexpr_regname (arch, (int) ul), plongest (l)); break; @@ -2571,6 +3511,80 @@ disassemble_dwarf_expression (struct ui_file *stream, plongest (l)); } break; + + case DW_OP_GNU_deref_type: + { + int addr_size = *data++; + ULONGEST offset; + struct type *type; + + data = read_uleb128 (data, end, &offset); + type = dwarf2_get_die_type (offset, per_cu); + fprintf_filtered (stream, "<"); + type_print (type, "", stream, -1); + fprintf_filtered (stream, " [0x%s]> %d", phex_nz (offset, 0), + addr_size); + } + break; + + case DW_OP_GNU_const_type: + { + ULONGEST type_die; + struct type *type; + + data = read_uleb128 (data, end, &type_die); + type = dwarf2_get_die_type (type_die, per_cu); + fprintf_filtered (stream, "<"); + type_print (type, "", stream, -1); + fprintf_filtered (stream, " [0x%s]>", phex_nz (type_die, 0)); + } + break; + + case DW_OP_GNU_regval_type: + { + ULONGEST type_die, reg; + struct type *type; + + data = read_uleb128 (data, end, ®); + data = read_uleb128 (data, end, &type_die); + + type = dwarf2_get_die_type (type_die, per_cu); + fprintf_filtered (stream, "<"); + type_print (type, "", stream, -1); + fprintf_filtered (stream, " [0x%s]> [$%s]", phex_nz (type_die, 0), + locexpr_regname (arch, reg)); + } + break; + + case DW_OP_GNU_convert: + case DW_OP_GNU_reinterpret: + { + ULONGEST type_die; + + data = read_uleb128 (data, end, &type_die); + + if (type_die == 0) + fprintf_filtered (stream, "<0>"); + else + { + struct type *type; + + type = dwarf2_get_die_type (type_die, per_cu); + fprintf_filtered (stream, "<"); + type_print (type, "", stream, -1); + fprintf_filtered (stream, " [0x%s]>", phex_nz (type_die, 0)); + } + } + break; + + case DW_OP_GNU_entry_value: + data = read_uleb128 (data, end, &ul); + fputc_filtered ('\n', stream); + disassemble_dwarf_expression (stream, arch, addr_size, offset_size, + start, data, data + ul, indent + 2, + all, per_cu); + data += ul; + continue; } fprintf_filtered (stream, "\n"); @@ -2587,7 +3601,7 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr, struct ui_file *stream, const gdb_byte *data, int size, struct objfile *objfile, unsigned int addr_size, - int offset_size) + int offset_size, struct dwarf2_per_cu_data *per_cu) { const gdb_byte *end = data + size; int first_piece = 1, bad = 0; @@ -2615,10 +3629,15 @@ locexpr_describe_location_1 (struct symbol *symbol, CORE_ADDR addr, disassemble = 0; } if (disassemble) - data = disassemble_dwarf_expression (stream, - get_objfile_arch (objfile), - addr_size, offset_size, data, end, - dwarf2_always_disassemble); + { + fprintf_filtered (stream, _("a complex DWARF expression:\n")); + data = disassemble_dwarf_expression (stream, + get_objfile_arch (objfile), + addr_size, offset_size, data, + data, end, 0, + dwarf2_always_disassemble, + per_cu); + } if (data < end) { @@ -2682,7 +3701,8 @@ locexpr_describe_location (struct symbol *symbol, CORE_ADDR addr, locexpr_describe_location_1 (symbol, addr, stream, dlbaton->data, dlbaton->size, - objfile, addr_size, offset_size); + objfile, addr_size, offset_size, + dlbaton->per_cu); } /* Describe the location of SYMBOL as an agent value in VALUE, generating @@ -2695,7 +3715,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); - if (dlbaton->data == NULL || dlbaton->size == 0) + if (dlbaton->size == 0) value->optimized_out = 1; else dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, @@ -2707,6 +3727,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, evaluator. */ const struct symbol_computed_ops dwarf2_locexpr_funcs = { locexpr_read_variable, + locexpr_read_variable_at_entry, locexpr_read_needs_frame, locexpr_describe_location, locexpr_tracepoint_var_ref @@ -2728,19 +3749,38 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame) CORE_ADDR pc = frame ? get_frame_address_in_block (frame) : 0; data = dwarf2_find_location_expression (dlbaton, &size, pc); - if (data == NULL) - { - val = allocate_value (SYMBOL_TYPE (symbol)); - VALUE_LVAL (val) = not_lval; - set_value_optimized_out (val, 1); - } - else - val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size, - dlbaton->per_cu); + val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size, + dlbaton->per_cu); return val; } +/* Read variable SYMBOL like loclist_read_variable at (callee) FRAME's function + entry. SYMBOL should be a function parameter, otherwise NO_ENTRY_VALUE_ERROR + will be thrown. + + Function always returns non-NULL value, it may be marked optimized out if + inferior frame information is not available. It throws NO_ENTRY_VALUE_ERROR + if it cannot resolve the parameter for any reason. */ + +static struct value * +loclist_read_variable_at_entry (struct symbol *symbol, struct frame_info *frame) +{ + struct dwarf2_loclist_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); + const gdb_byte *data; + size_t size; + CORE_ADDR pc; + + if (frame == NULL || !get_frame_func_if_available (frame, &pc)) + return allocate_optimized_out_value (SYMBOL_TYPE (symbol)); + + data = dwarf2_find_location_expression (dlbaton, &size, pc); + if (data == NULL) + return allocate_optimized_out_value (SYMBOL_TYPE (symbol)); + + return value_of_dwarf_block_entry (SYMBOL_TYPE (symbol), frame, data, size); +} + /* Return non-zero iff we need a frame to evaluate SYMBOL. */ static int loclist_read_needs_frame (struct symbol *symbol) @@ -2828,7 +3868,8 @@ loclist_describe_location (struct symbol *symbol, CORE_ADDR addr, /* Now describe this particular location. */ locexpr_describe_location_1 (symbol, low, stream, loc_ptr, length, - objfile, addr_size, offset_size); + objfile, addr_size, offset_size, + dlbaton->per_cu); fprintf_filtered (stream, "\n"); @@ -2848,7 +3889,7 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); data = dwarf2_find_location_expression (dlbaton, &size, ax->scope); - if (data == NULL || size == 0) + if (size == 0) value->optimized_out = 1; else dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, data, data + size, @@ -2859,7 +3900,25 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, evaluator and location lists. */ const struct symbol_computed_ops dwarf2_loclist_funcs = { loclist_read_variable, + loclist_read_variable_at_entry, loclist_read_needs_frame, loclist_describe_location, loclist_tracepoint_var_ref }; + +void +_initialize_dwarf2loc (void) +{ + add_setshow_zinteger_cmd ("entry-values", class_maintenance, + &entry_values_debug, + _("Set entry values and tail call frames " + "debugging."), + _("Show entry values and tail call frames " + "debugging."), + _("When non-zero, the process of determining " + "parameter values from function entry point " + "and tail call frames will be printed."), + NULL, + show_entry_values_debug, + &setdebuglist, &showdebuglist); +} diff --git a/contrib/gdb-7/gdb/dwarf2loc.h b/contrib/gdb-7/gdb/dwarf2loc.h index 96a490e5de..da05c98e50 100644 --- a/contrib/gdb-7/gdb/dwarf2loc.h +++ b/contrib/gdb-7/gdb/dwarf2loc.h @@ -1,7 +1,6 @@ /* DWARF 2 location expression support for GDB. - Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -31,6 +30,9 @@ struct axs_value; /* This header is private to the DWARF-2 reader. It is shared between dwarf2read.c and dwarf2loc.c. */ +/* `set debug entry-values' setting. */ +extern int entry_values_debug; + /* Return the OBJFILE associated with the compilation unit CU. If CU came from a separate debuginfo file, then the master objfile is returned. */ @@ -39,6 +41,10 @@ struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu); /* Return the address size given in the compilation unit header for CU. */ CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu); +/* Return the DW_FORM_ref_addr size given in the compilation unit header for + CU. */ +int dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *cu); + /* Return the offset size given in the compilation unit header for CU. */ int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *cu); @@ -59,6 +65,9 @@ struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block CORE_ADDR (*get_frame_pc) (void *baton), void *baton); +struct type *dwarf2_get_die_type (unsigned int die_offset, + struct dwarf2_per_cu_data *per_cu); + /* Evaluate a location description, starting at DATA and with length SIZE, to find the current location of variable of TYPE in the context of FRAME. */ @@ -77,10 +86,12 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type, struct dwarf2_locexpr_baton { - /* Pointer to the start of the location expression. */ + /* Pointer to the start of the location expression. Valid only if SIZE is + not zero. */ const gdb_byte *data; - /* Length of the location expression. */ + /* Length of the location expression. For optimized out expressions it is + zero. */ unsigned long size; /* The compilation unit containing the symbol whose location @@ -129,4 +140,23 @@ extern void dwarf2_compile_expr_to_ax (struct agent_expr *expr, const gdb_byte *op_end, struct dwarf2_per_cu_data *per_cu); +/* Determined tail calls for constructing virtual tail call frames. */ + +struct call_site_chain + { + /* Initially CALLERS == CALLEES == LENGTH. For partially ambiguous result + CALLERS + CALLEES < LENGTH. */ + int callers, callees, length; + + /* Variably sized array with LENGTH elements. Later [0..CALLERS-1] contain + top (GDB "prev") sites and [LENGTH-CALLEES..LENGTH-1] contain bottom + (GDB "next") sites. One is interested primarily in the PC field. */ + struct call_site *call_site[1]; + }; + +struct call_site_stuff; +extern struct call_site_chain *call_site_find_chain (struct gdbarch *gdbarch, + CORE_ADDR caller_pc, + CORE_ADDR callee_pc); + #endif /* dwarf2loc.h */ diff --git a/contrib/gdb-7/gdb/dwarf2read.c b/contrib/gdb-7/gdb/dwarf2read.c index 5bc9d0edc9..8c81c8a78d 100644 --- a/contrib/gdb-7/gdb/dwarf2read.c +++ b/contrib/gdb-7/gdb/dwarf2read.c @@ -1,8 +1,6 @@ /* DWARF 2 debugging format support for GDB. - Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1994-2012 Free Software Foundation, Inc. Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, Inc. with support from Florida State University (under contract @@ -34,6 +32,7 @@ #include "dwarf2.h" #include "buildsym.h" #include "demangle.h" +#include "gdb-demangle.h" #include "expression.h" #include "filenames.h" /* for DOSish file names */ #include "macrotab.h" @@ -137,11 +136,17 @@ struct dwarf2_section_info asection *asection; gdb_byte *buffer; bfd_size_type size; - int was_mmapped; + /* Not NULL if the section was actually mmapped. */ + void *map_addr; + /* Page aligned size of mmapped area. */ + bfd_size_type map_len; /* True if we have tried to read this section. */ int readin; }; +typedef struct dwarf2_section_info dwarf2_section_info_def; +DEF_VEC_O (dwarf2_section_info_def); + /* All offsets in the index are of this type. It must be architecture-independent. */ typedef uint32_t offset_type; @@ -152,16 +157,24 @@ DEF_VEC_I (offset_type); a comment by the code that writes the index. */ struct mapped_index { + /* Index data format version. */ + int version; + /* The total length of the buffer. */ off_t total_size; + /* A pointer to the address table data. */ const gdb_byte *address_table; + /* Size of the address table data in bytes. */ offset_type address_table_size; + /* The symbol table, implemented as a hash table. */ const offset_type *symbol_table; + /* Size in slots, each slot is 2 offset_types. */ offset_type symbol_table_slots; + /* A pointer to the constant pool. */ const char *constant_pool; }; @@ -173,13 +186,15 @@ struct dwarf2_per_objfile struct dwarf2_section_info line; struct dwarf2_section_info loc; struct dwarf2_section_info macinfo; + struct dwarf2_section_info macro; struct dwarf2_section_info str; struct dwarf2_section_info ranges; - struct dwarf2_section_info types; struct dwarf2_section_info frame; struct dwarf2_section_info eh_frame; struct dwarf2_section_info gdb_index; + VEC (dwarf2_section_info_def) *types; + /* Back link. */ struct objfile *objfile; @@ -238,22 +253,26 @@ struct dwarf2_per_objfile static struct dwarf2_per_objfile *dwarf2_per_objfile; -/* names of the debugging sections */ +/* Default names of the debugging sections. */ /* Note that if the debugging section has been compressed, it might have a name like .zdebug_info. */ -#define INFO_SECTION "debug_info" -#define ABBREV_SECTION "debug_abbrev" -#define LINE_SECTION "debug_line" -#define LOC_SECTION "debug_loc" -#define MACINFO_SECTION "debug_macinfo" -#define STR_SECTION "debug_str" -#define RANGES_SECTION "debug_ranges" -#define TYPES_SECTION "debug_types" -#define FRAME_SECTION "debug_frame" -#define EH_FRAME_SECTION "eh_frame" -#define GDB_INDEX_SECTION "gdb_index" +static const struct dwarf2_debug_sections dwarf2_elf_names = { + { ".debug_info", ".zdebug_info" }, + { ".debug_abbrev", ".zdebug_abbrev" }, + { ".debug_line", ".zdebug_line" }, + { ".debug_loc", ".zdebug_loc" }, + { ".debug_macinfo", ".zdebug_macinfo" }, + { ".debug_macro", ".zdebug_macro" }, + { ".debug_str", ".zdebug_str" }, + { ".debug_ranges", ".zdebug_ranges" }, + { ".debug_types", ".zdebug_types" }, + { ".debug_frame", ".zdebug_frame" }, + { ".eh_frame", NULL }, + { ".gdb_index", ".zgdb_index" }, + 23 +}; /* local data types */ @@ -387,6 +406,9 @@ struct dwarf2_cu after all type information has been read. */ VEC (delayed_method_info) *method_list; + /* To be copied to symtab->call_site_htab. */ + htab_t call_site_htab; + /* Mark used when releasing cached dies. */ unsigned int mark : 1; @@ -434,9 +456,9 @@ struct dwarf2_per_cu_data hash table and don't find it. */ unsigned int load_all_dies : 1; - /* Non-zero if this CU is from .debug_types. - Otherwise it's from .debug_info. */ - unsigned int from_debug_types : 1; + /* Non-null if this CU is from .debug_types; in which case it points + to the section. Otherwise it's from .debug_info. */ + struct dwarf2_section_info *debug_types_section; /* Set to non-NULL iff this CU is currently loaded. When it gets freed out of the CU cache it gets reset to NULL again. */ @@ -465,9 +487,6 @@ struct signatured_type { ULONGEST signature; - /* Offset in .debug_types of the TU (type_unit) for this type. */ - unsigned int offset; - /* Offset in .debug_types of the type defined by this TU. */ unsigned int type_offset; @@ -702,6 +721,8 @@ struct function_range struct dwarf_block { unsigned int size; + + /* Valid only if SIZE is not zero. */ gdb_byte *data; }; @@ -844,10 +865,11 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2, } static void -dwarf2_macros_too_long_complaint (void) +dwarf2_macros_too_long_complaint (struct dwarf2_section_info *section) { complaint (&symfile_complaints, - _("macro info runs off end of `.debug_macinfo' section")); + _("macro info runs off end of `%s' section"), + section->asection->name); } static void @@ -874,6 +896,9 @@ static void dwarf2_locate_sections (bfd *, asection *, void *); static void dwarf2_create_include_psymtab (char *, struct partial_symtab *, struct objfile *); +static void dwarf2_find_base_address (struct die_info *die, + struct dwarf2_cu *cu); + static void dwarf2_build_psymtabs_hard (struct objfile *); static void scan_partial_symbols (struct partial_die_info *, @@ -910,6 +935,8 @@ static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu); static void dwarf2_free_abbrev_table (void *); +static unsigned int peek_abbrev_code (bfd *, gdb_byte *); + static struct abbrev_info *peek_die_abbrev (gdb_byte *, unsigned int *, struct dwarf2_cu *); @@ -1002,8 +1029,9 @@ static struct line_header *(dwarf_decode_line_header (unsigned int offset, bfd *abfd, struct dwarf2_cu *cu)); -static void dwarf_decode_lines (struct line_header *, const char *, bfd *, - struct dwarf2_cu *, struct partial_symtab *); +static void dwarf_decode_lines (struct line_header *, const char *, + struct dwarf2_cu *, struct partial_symtab *, + int); static void dwarf2_start_subfile (char *, const char *, const char *); @@ -1058,6 +1086,8 @@ static void read_func_scope (struct die_info *, struct dwarf2_cu *); static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *); +static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu); + static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, struct partial_symtab *); @@ -1190,7 +1220,13 @@ static struct die_info *follow_die_sig (struct die_info *, struct attribute *, struct dwarf2_cu **); +static struct signatured_type *lookup_signatured_type_at_offset + (struct objfile *objfile, + struct dwarf2_section_info *section, + unsigned int offset); + static void read_signatured_type_at_offset (struct objfile *objfile, + struct dwarf2_section_info *sect, unsigned int offset); static void read_signatured_type (struct objfile *, @@ -1210,7 +1246,9 @@ static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR, struct dwarf2_cu *); static void dwarf_decode_macros (struct line_header *, unsigned int, - char *, bfd *, struct dwarf2_cu *); + char *, bfd *, struct dwarf2_cu *, + struct dwarf2_section_info *, + int); static int attr_form_is_block (struct attribute *); @@ -1298,7 +1336,8 @@ static gdb_byte *partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, gdb_byte *buffer, unsigned int buffer_size, - bfd *abfd); + bfd *abfd, + int is_debug_types_section); static void init_cu_die_reader (struct die_reader_specs *reader, struct dwarf2_cu *cu); @@ -1333,10 +1372,13 @@ static const char *dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu); /* Try to locate the sections we need for DWARF 2 debugging - information and return true if we have enough to do something. */ + information and return true if we have enough to do something. + NAMES points to the dwarf2 section names, or is NULL if the standard + ELF names are used. */ int -dwarf2_has_info (struct objfile *objfile) +dwarf2_has_info (struct objfile *objfile, + const struct dwarf2_debug_sections *names) { dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); if (!dwarf2_per_objfile) @@ -1349,23 +1391,28 @@ dwarf2_has_info (struct objfile *objfile) set_objfile_data (objfile, dwarf2_objfile_data_key, data); dwarf2_per_objfile = data; - bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, NULL); + bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, + (void *) names); dwarf2_per_objfile->objfile = objfile; } return (dwarf2_per_objfile->info.asection != NULL && dwarf2_per_objfile->abbrev.asection != NULL); } -/* When loading sections, we can either look for ".", or for - * ".z", which indicates a compressed section. */ +/* When loading sections, we look either for uncompressed section or for + compressed section names. */ static int -section_is_p (const char *section_name, const char *name) +section_is_p (const char *section_name, + const struct dwarf2_section_names *names) { - return (section_name[0] == '.' - && (strcmp (section_name + 1, name) == 0 - || (section_name[1] == 'z' - && strcmp (section_name + 2, name) == 0))); + if (names->normal != NULL + && strcmp (section_name, names->normal) == 0) + return 1; + if (names->compressed != NULL + && strcmp (section_name, names->compressed) == 0) + return 1; + return 0; } /* This function is mapped across the sections and remembers the @@ -1373,44 +1420,56 @@ section_is_p (const char *section_name, const char *name) in. */ static void -dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) +dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames) { - if (section_is_p (sectp->name, INFO_SECTION)) + const struct dwarf2_debug_sections *names; + + if (vnames == NULL) + names = &dwarf2_elf_names; + else + names = (const struct dwarf2_debug_sections *) vnames; + + if (section_is_p (sectp->name, &names->info)) { dwarf2_per_objfile->info.asection = sectp; dwarf2_per_objfile->info.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, ABBREV_SECTION)) + else if (section_is_p (sectp->name, &names->abbrev)) { dwarf2_per_objfile->abbrev.asection = sectp; dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, LINE_SECTION)) + else if (section_is_p (sectp->name, &names->line)) { dwarf2_per_objfile->line.asection = sectp; dwarf2_per_objfile->line.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, LOC_SECTION)) + else if (section_is_p (sectp->name, &names->loc)) { dwarf2_per_objfile->loc.asection = sectp; dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, MACINFO_SECTION)) + else if (section_is_p (sectp->name, &names->macinfo)) { dwarf2_per_objfile->macinfo.asection = sectp; dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, STR_SECTION)) + else if (section_is_p (sectp->name, &names->macro)) + { + dwarf2_per_objfile->macro.asection = sectp; + dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp); + } + else if (section_is_p (sectp->name, &names->str)) { dwarf2_per_objfile->str.asection = sectp; dwarf2_per_objfile->str.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, FRAME_SECTION)) + else if (section_is_p (sectp->name, &names->frame)) { dwarf2_per_objfile->frame.asection = sectp; dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, EH_FRAME_SECTION)) + else if (section_is_p (sectp->name, &names->eh_frame)) { flagword aflag = bfd_get_section_flags (ignore_abfd, sectp); @@ -1420,17 +1479,23 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *ignore_ptr) dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp); } } - else if (section_is_p (sectp->name, RANGES_SECTION)) + else if (section_is_p (sectp->name, &names->ranges)) { dwarf2_per_objfile->ranges.asection = sectp; dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, TYPES_SECTION)) + else if (section_is_p (sectp->name, &names->types)) { - dwarf2_per_objfile->types.asection = sectp; - dwarf2_per_objfile->types.size = bfd_get_section_size (sectp); + struct dwarf2_section_info type_section; + + memset (&type_section, 0, sizeof (type_section)); + type_section.asection = sectp; + type_section.size = bfd_get_section_size (sectp); + + VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types, + &type_section); } - else if (section_is_p (sectp->name, GDB_INDEX_SECTION)) + else if (section_is_p (sectp->name, &names->gdb_index)) { dwarf2_per_objfile->gdb_index.asection = sectp; dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp); @@ -1543,7 +1608,7 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) if (info->readin) return; info->buffer = NULL; - info->was_mmapped = 0; + info->map_addr = NULL; info->readin = 1; if (dwarf2_section_empty_p (info)) @@ -1573,17 +1638,14 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0) { - off_t pg_offset = sectp->filepos & ~(pagesize - 1); - size_t map_length = info->size + sectp->filepos - pg_offset; - caddr_t retbuf = bfd_mmap (abfd, 0, map_length, PROT_READ, - MAP_PRIVATE, pg_offset); + info->buffer = bfd_mmap (abfd, 0, info->size, PROT_READ, + MAP_PRIVATE, sectp->filepos, + &info->map_addr, &info->map_len); - if (retbuf != MAP_FAILED) + if ((caddr_t)info->buffer != MAP_FAILED) { - info->was_mmapped = 1; - info->buffer = retbuf + (sectp->filepos & (pagesize - 1)) ; #if HAVE_POSIX_MADVISE - posix_madvise (retbuf, map_length, POSIX_MADV_WILLNEED); + posix_madvise (info->map_addr, info->map_len, POSIX_MADV_WILLNEED); #endif return; } @@ -1631,7 +1693,8 @@ dwarf2_section_size (struct objfile *objfile, SECTION_NAME. */ void -dwarf2_get_section_info (struct objfile *objfile, const char *section_name, +dwarf2_get_section_info (struct objfile *objfile, + enum dwarf2_section_enum sect, asection **sectp, gdb_byte **bufp, bfd_size_type *sizep) { @@ -1648,12 +1711,17 @@ dwarf2_get_section_info (struct objfile *objfile, const char *section_name, *sizep = 0; return; } - if (section_is_p (section_name, EH_FRAME_SECTION)) - info = &data->eh_frame; - else if (section_is_p (section_name, FRAME_SECTION)) - info = &data->frame; - else - gdb_assert_not_reached ("unexpected section"); + switch (sect) + { + case DWARF2_DEBUG_FRAME: + info = &data->frame; + break; + case DWARF2_EH_FRAME: + info = &data->eh_frame; + break; + default: + gdb_assert_not_reached ("unexpected section"); + } dwarf2_read_section (objfile, info); @@ -1760,6 +1828,25 @@ create_quick_file_names_table (unsigned int nr_initial_entries) delete_file_name_entry, xcalloc, xfree); } +/* Read in PER_CU->CU. This function is unrelated to symtabs, symtab would + have to be created afterwards. You should call age_cached_comp_units after + processing PER_CU->CU. dw2_setup must have been already called. */ + +static void +load_cu (struct dwarf2_per_cu_data *per_cu) +{ + if (per_cu->debug_types_section) + read_signatured_type_at_offset (per_cu->objfile, + per_cu->debug_types_section, + per_cu->offset); + else + load_full_comp_unit (per_cu, per_cu->objfile); + + dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu); + + gdb_assert (per_cu->cu != NULL); +} + /* Read in the symbols for PER_CU. OBJFILE is the objfile from which this CU came. */ @@ -1773,10 +1860,7 @@ dw2_do_instantiate_symtab (struct objfile *objfile, queue_comp_unit (per_cu, objfile); - if (per_cu->from_debug_types) - read_signatured_type_at_offset (objfile, per_cu->offset); - else - load_full_comp_unit (per_cu, objfile); + load_cu (per_cu); process_queue (objfile); @@ -1884,6 +1968,7 @@ create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list, static int create_signatured_type_table_from_index (struct objfile *objfile, + struct dwarf2_section_info *section, const gdb_byte *bytes, offset_type elements) { @@ -1913,9 +1998,8 @@ create_signatured_type_table_from_index (struct objfile *objfile, type_sig = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct signatured_type); type_sig->signature = signature; - type_sig->offset = offset; type_sig->type_offset = type_offset; - type_sig->per_cu.from_debug_types = 1; + type_sig->per_cu.debug_types_section = section; type_sig->per_cu.offset = offset; type_sig->per_cu.objfile = objfile; type_sig->per_cu.v.quick @@ -1973,21 +2057,27 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index) do_cleanups (cleanup); } -/* The hash function for strings in the mapped index. This is the - same as the hashtab.c hash function, but we keep a separate copy to - maintain control over the implementation. This is necessary - because the hash function is tied to the format of the mapped index - file. */ +/* The hash function for strings in the mapped index. This is the same as + SYMBOL_HASH_NEXT, but we keep a separate copy to maintain control over the + implementation. This is necessary because the hash function is tied to the + format of the mapped index file. The hash values do not have to match with + SYMBOL_HASH_NEXT. + + Use INT_MAX for INDEX_VERSION if you generate the current index format. */ static hashval_t -mapped_index_string_hash (const void *p) +mapped_index_string_hash (int index_version, const void *p) { const unsigned char *str = (const unsigned char *) p; hashval_t r = 0; unsigned char c; while ((c = *str++) != 0) - r = r * 67 + c - 113; + { + if (index_version >= 5) + c = tolower (c); + r = r * 67 + c - 113; + } return r; } @@ -2003,6 +2093,7 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name, struct cleanup *back_to = make_cleanup (null_cleanup, 0); offset_type hash; offset_type slot, step; + int (*cmp) (const char *, const char *); if (current_language->la_language == language_cplus || current_language->la_language == language_java @@ -2025,9 +2116,17 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name, } } - hash = mapped_index_string_hash (name); + /* Index version 4 did not support case insensitive searches. But the + indexes for case insensitive languages are built in lowercase, therefore + simulate our NAME being searched is also lowercased. */ + hash = mapped_index_string_hash ((index->version == 4 + && case_sensitivity == case_sensitive_off + ? 5 : index->version), + name); + slot = hash & (index->symbol_table_slots - 1); step = ((hash * 17) & (index->symbol_table_slots - 1)) | 1; + cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp); for (;;) { @@ -2041,7 +2140,7 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name, } str = index->constant_pool + MAYBE_SWAP (index->symbol_table[i]); - if (!strcmp (name, str)) + if (!cmp (name, str)) { *vec_out = (offset_type *) (index->constant_pool + MAYBE_SWAP (index->symbol_table[i + 1])); @@ -2085,15 +2184,17 @@ dwarf2_read_index (struct objfile *objfile) /* Versions earlier than 3 emitted every copy of a psymbol. This causes the index to behave very poorly for certain requests. Version 3 contained incomplete addrmap. So, it seems better to just ignore such - indices. */ + indices. Index version 4 uses a different hash function than index + version 5 and later. */ if (version < 4) return 0; /* Indexes with higher version than the one supported by GDB may be no longer backward compatible. */ - if (version > 4) + if (version > 5) return 0; map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index); + map->version = version; map->total_size = dwarf2_per_objfile->gdb_index.size; metadata = (offset_type *) (addr + sizeof (offset_type)); @@ -2126,10 +2227,23 @@ dwarf2_read_index (struct objfile *objfile) if (!create_cus_from_index (objfile, cu_list, cu_list_elements)) return 0; - if (types_list_elements - && !create_signatured_type_table_from_index (objfile, types_list, - types_list_elements)) - return 0; + if (types_list_elements) + { + struct dwarf2_section_info *section; + + /* We can only handle a single .debug_types when we have an + index. */ + if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) != 1) + return 0; + + section = VEC_index (dwarf2_section_info_def, + dwarf2_per_objfile->types, 0); + + if (!create_signatured_type_table_from_index (objfile, section, + types_list, + types_list_elements)) + return 0; + } create_addrmap_from_index (objfile, map); @@ -2164,7 +2278,7 @@ dw2_get_file_names (struct objfile *objfile, struct cleanup *cleanups; struct die_info *comp_unit_die; struct dwarf2_section_info* sec; - gdb_byte *beg_of_comp_unit, *info_ptr, *buffer; + gdb_byte *info_ptr, *buffer; int has_children, i; struct dwarf2_cu cu; unsigned int bytes_read, buffer_size; @@ -2183,23 +2297,27 @@ dw2_get_file_names (struct objfile *objfile, init_one_comp_unit (&cu, objfile); cleanups = make_cleanup (free_stack_comp_unit, &cu); - if (this_cu->from_debug_types) - sec = &dwarf2_per_objfile->types; + if (this_cu->debug_types_section) + sec = this_cu->debug_types_section; else sec = &dwarf2_per_objfile->info; dwarf2_read_section (objfile, sec); buffer_size = sec->size; buffer = sec->buffer; info_ptr = buffer + this_cu->offset; - beg_of_comp_unit = info_ptr; info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, buffer, buffer_size, - abfd); + abfd, + this_cu->debug_types_section != NULL); - /* Complete the cu_header. */ - cu.header.offset = beg_of_comp_unit - buffer; - cu.header.first_die_offset = info_ptr - beg_of_comp_unit; + /* Skip dummy compilation units. */ + if (info_ptr >= buffer + buffer_size + || peek_abbrev_code (abfd, info_ptr) == 0) + { + do_cleanups (cleanups); + return NULL; + } this_cu->cu = &cu; cu.per_cu = this_cu; @@ -2207,8 +2325,6 @@ dw2_get_file_names (struct objfile *objfile, dwarf2_read_abbrevs (abfd, &cu); make_cleanup (dwarf2_free_abbrev_table, &cu); - if (this_cu->from_debug_types) - info_ptr += 8 /*signature*/ + cu.header.offset_size; init_cu_die_reader (&reader_specs, &cu); read_full_die (&reader_specs, &comp_unit_die, info_ptr, &has_children); @@ -2322,13 +2438,42 @@ dw2_forget_cached_source_info (struct objfile *objfile) dw2_free_cached_file_names, NULL); } +/* Helper function for dw2_map_symtabs_matching_filename that expands + the symtabs and calls the iterator. */ + +static int +dw2_map_expand_apply (struct objfile *objfile, + struct dwarf2_per_cu_data *per_cu, + const char *name, + const char *full_path, const char *real_path, + int (*callback) (struct symtab *, void *), + void *data) +{ + struct symtab *last_made = objfile->symtabs; + + /* Don't visit already-expanded CUs. */ + if (per_cu->v.quick->symtab) + return 0; + + /* This may expand more than one symtab, and we want to iterate over + all of them. */ + dw2_instantiate_symtab (objfile, per_cu); + + return iterate_over_some_symtabs (name, full_path, real_path, callback, data, + objfile->symtabs, last_made); +} + +/* Implementation of the map_symtabs_matching_filename method. */ + static int -dw2_lookup_symtab (struct objfile *objfile, const char *name, - const char *full_path, const char *real_path, - struct symtab **result) +dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, + const char *full_path, const char *real_path, + int (*callback) (struct symtab *, void *), + void *data) { int i; - int check_basename = lbasename (name) == name; + const char *name_basename = lbasename (name); + int check_basename = name_basename == name; struct dwarf2_per_cu_data *base_cu = NULL; dw2_setup (objfile); @@ -2340,6 +2485,7 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct quick_file_names *file_data; + /* We only need to look at symtabs not already expanded. */ if (per_cu->v.quick->symtab) continue; @@ -2353,14 +2499,22 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, if (FILENAME_CMP (name, this_name) == 0) { - *result = dw2_instantiate_symtab (objfile, per_cu); - return 1; + if (dw2_map_expand_apply (objfile, per_cu, + name, full_path, real_path, + callback, data)) + return 1; } if (check_basename && ! base_cu && FILENAME_CMP (lbasename (this_name), name) == 0) base_cu = per_cu; + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if (! basenames_may_differ + && FILENAME_CMP (lbasename (this_name), name_basename) != 0) + continue; + if (full_path != NULL) { const char *this_real_name = dw2_get_real_path (objfile, @@ -2369,8 +2523,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, if (this_real_name != NULL && FILENAME_CMP (full_path, this_real_name) == 0) { - *result = dw2_instantiate_symtab (objfile, per_cu); - return 1; + if (dw2_map_expand_apply (objfile, per_cu, + name, full_path, real_path, + callback, data)) + return 1; } } @@ -2382,8 +2538,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, if (this_real_name != NULL && FILENAME_CMP (real_path, this_real_name) == 0) { - *result = dw2_instantiate_symtab (objfile, per_cu); - return 1; + if (dw2_map_expand_apply (objfile, per_cu, + name, full_path, real_path, + callback, data)) + return 1; } } } @@ -2391,8 +2549,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name, if (base_cu) { - *result = dw2_instantiate_symtab (objfile, base_cu); - return 1; + if (dw2_map_expand_apply (objfile, base_cu, + name, full_path, real_path, + callback, data)) + return 1; } return 0; @@ -2437,7 +2597,7 @@ dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name) static void dw2_pre_expand_symtabs_matching (struct objfile *objfile, - int kind, const char *name, + enum block_enum block_kind, const char *name, domain_enum domain) { dw2_do_expand_symtabs_matching (objfile, name); @@ -2516,6 +2676,7 @@ dw2_expand_symtabs_with_filename (struct objfile *objfile, struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct quick_file_names *file_data; + /* We only need to look at symtabs not already expanded. */ if (per_cu->v.quick->symtab) continue; @@ -2546,7 +2707,21 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name) /* index_table is NULL if OBJF_READNOW. */ if (!dwarf2_per_objfile->index_table) - return NULL; + { + struct symtab *s; + + ALL_OBJFILE_SYMTABS (objfile, s) + if (s->primary) + { + struct blockvector *bv = BLOCKVECTOR (s); + const struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK); + struct symbol *sym = lookup_block_symbol (block, name, VAR_DOMAIN); + + if (sym) + return sym->symtab->filename; + } + return NULL; + } if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table, name, &vec)) @@ -2580,11 +2755,12 @@ dw2_map_matching_symbols (const char * name, domain_enum namespace, } static void -dw2_expand_symtabs_matching (struct objfile *objfile, - int (*file_matcher) (const char *, void *), - int (*name_matcher) (const char *, void *), - domain_enum kind, - void *data) +dw2_expand_symtabs_matching + (struct objfile *objfile, + int (*file_matcher) (const char *, void *), + int (*name_matcher) (const struct language_defn *, const char *, void *), + enum search_domain kind, + void *data) { int i; offset_type iter; @@ -2606,6 +2782,8 @@ dw2_expand_symtabs_matching (struct objfile *objfile, struct quick_file_names *file_data; per_cu->v.quick->mark = 0; + + /* We only need to look at symtabs not already expanded. */ if (per_cu->v.quick->symtab) continue; @@ -2634,7 +2812,7 @@ dw2_expand_symtabs_matching (struct objfile *objfile, name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]); - if (! (*name_matcher) (name, data)) + if (! (*name_matcher) (current_language, name, data)) continue; /* The name was matched, now expand corresponding CUs that were @@ -2679,9 +2857,8 @@ dw2_find_pc_sect_symtab (struct objfile *objfile, } static void -dw2_map_symbol_filenames (struct objfile *objfile, - void (*fun) (const char *, const char *, void *), - void *data) +dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun, + void *data, int need_fullname) { int i; @@ -2694,6 +2871,7 @@ dw2_map_symbol_filenames (struct objfile *objfile, struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); struct quick_file_names *file_data; + /* We only need to look at symtabs not already expanded. */ if (per_cu->v.quick->symtab) continue; @@ -2703,8 +2881,12 @@ dw2_map_symbol_filenames (struct objfile *objfile, for (j = 0; j < file_data->num_file_names; ++j) { - const char *this_real_name = dw2_get_real_path (objfile, file_data, - j); + const char *this_real_name; + + if (need_fullname) + this_real_name = dw2_get_real_path (objfile, file_data, j); + else + this_real_name = NULL; (*fun) (file_data->file_names[j], this_real_name, data); } } @@ -2721,7 +2903,7 @@ const struct quick_symbol_functions dwarf2_gdb_index_functions = dw2_has_symbols, dw2_find_last_source_symtab, dw2_forget_cached_source_info, - dw2_lookup_symtab, + dw2_map_symtabs_matching_filename, dw2_lookup_symbol, dw2_pre_expand_symtabs_matching, dw2_print_stats, @@ -2837,15 +3019,26 @@ read_comp_unit_head (struct comp_unit_head *cu_header, return info_ptr; } +/* Read in a CU header and perform some basic error checking. */ + static gdb_byte * partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, gdb_byte *buffer, unsigned int buffer_size, - bfd *abfd) + bfd *abfd, int is_debug_types_section) { gdb_byte *beg_of_comp_unit = info_ptr; + header->offset = beg_of_comp_unit - buffer; + info_ptr = read_comp_unit_head (header, info_ptr, abfd); + /* If we're reading a type unit, skip over the signature and + type_offset fields. */ + if (is_debug_types_section) + info_ptr += 8 /*signature*/ + header->offset_size; + + header->first_die_offset = info_ptr - beg_of_comp_unit; + if (header->version != 2 && header->version != 3 && header->version != 4) error (_("Dwarf Error: wrong version in compilation unit header " "(is %d, should be 2, 3, or 4) [in module %s]"), header->version, @@ -2876,14 +3069,14 @@ partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr, static gdb_byte * read_type_comp_unit_head (struct comp_unit_head *cu_header, + struct dwarf2_section_info *section, ULONGEST *signature, gdb_byte *types_ptr, bfd *abfd) { gdb_byte *initial_types_ptr = types_ptr; - dwarf2_read_section (dwarf2_per_objfile->objfile, - &dwarf2_per_objfile->types); - cu_header->offset = types_ptr - dwarf2_per_objfile->types.buffer; + dwarf2_read_section (dwarf2_per_objfile->objfile, section); + cu_header->offset = types_ptr - section->buffer; types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd); @@ -2953,7 +3146,7 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, return; /* No linetable, so no includes. */ /* NOTE: pst->dirname is DW_AT_comp_dir (if present). */ - dwarf_decode_lines (lh, pst->dirname, abfd, cu, pst); + dwarf_decode_lines (lh, pst->dirname, cu, pst, 1); free_line_header (lh); } @@ -3011,80 +3204,112 @@ add_signatured_type_cu_to_list (void **slot, void *datum) static int create_debug_types_hash_table (struct objfile *objfile) { - gdb_byte *info_ptr; - htab_t types_htab; + htab_t types_htab = NULL; struct dwarf2_per_cu_data **iter; + int ix; + struct dwarf2_section_info *section; - dwarf2_read_section (objfile, &dwarf2_per_objfile->types); - info_ptr = dwarf2_per_objfile->types.buffer; - - if (info_ptr == NULL) + if (VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types)) { dwarf2_per_objfile->signatured_types = NULL; return 0; } - types_htab = allocate_signatured_type_table (objfile); + for (ix = 0; + VEC_iterate (dwarf2_section_info_def, dwarf2_per_objfile->types, + ix, section); + ++ix) + { + gdb_byte *info_ptr, *end_ptr; - if (dwarf2_die_debug) - fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); + dwarf2_read_section (objfile, section); + info_ptr = section->buffer; - while (info_ptr < dwarf2_per_objfile->types.buffer - + dwarf2_per_objfile->types.size) - { - unsigned int offset; - unsigned int offset_size; - unsigned int type_offset; - unsigned int length, initial_length_size; - unsigned short version; - ULONGEST signature; - struct signatured_type *type_sig; - void **slot; - gdb_byte *ptr = info_ptr; + if (info_ptr == NULL) + continue; - offset = ptr - dwarf2_per_objfile->types.buffer; + if (types_htab == NULL) + types_htab = allocate_signatured_type_table (objfile); - /* We need to read the type's signature in order to build the hash - table, but we don't need to read anything else just yet. */ + if (dwarf2_die_debug) + fprintf_unfiltered (gdb_stdlog, "Signatured types:\n"); - /* Sanity check to ensure entire cu is present. */ - length = read_initial_length (objfile->obfd, ptr, &initial_length_size); - if (ptr + length + initial_length_size - > dwarf2_per_objfile->types.buffer + dwarf2_per_objfile->types.size) + end_ptr = info_ptr + section->size; + while (info_ptr < end_ptr) { - complaint (&symfile_complaints, - _("debug type entry runs off end " - "of `.debug_types' section, ignored")); - break; - } + unsigned int offset; + unsigned int offset_size; + unsigned int type_offset; + unsigned int length, initial_length_size; + unsigned short version; + ULONGEST signature; + struct signatured_type *type_sig; + void **slot; + gdb_byte *ptr = info_ptr; - offset_size = initial_length_size == 4 ? 4 : 8; - ptr += initial_length_size; - version = bfd_get_16 (objfile->obfd, ptr); - ptr += 2; - ptr += offset_size; /* abbrev offset */ - ptr += 1; /* address size */ - signature = bfd_get_64 (objfile->obfd, ptr); - ptr += 8; - type_offset = read_offset_1 (objfile->obfd, ptr, offset_size); + offset = ptr - section->buffer; - type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig)); - memset (type_sig, 0, sizeof (*type_sig)); - type_sig->signature = signature; - type_sig->offset = offset; - type_sig->type_offset = type_offset; - type_sig->per_cu.objfile = objfile; - type_sig->per_cu.from_debug_types = 1; + /* We need to read the type's signature in order to build the hash + table, but we don't need to read anything else just yet. */ - slot = htab_find_slot (types_htab, type_sig, INSERT); - gdb_assert (slot != NULL); - *slot = type_sig; + /* Sanity check to ensure entire cu is present. */ + length = read_initial_length (objfile->obfd, ptr, + &initial_length_size); + if (ptr + length + initial_length_size > end_ptr) + { + complaint (&symfile_complaints, + _("debug type entry runs off end " + "of `.debug_types' section, ignored")); + break; + } - if (dwarf2_die_debug) - fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n", - offset, phex (signature, sizeof (signature))); + offset_size = initial_length_size == 4 ? 4 : 8; + ptr += initial_length_size; + version = bfd_get_16 (objfile->obfd, ptr); + ptr += 2; + ptr += offset_size; /* abbrev offset */ + ptr += 1; /* address size */ + signature = bfd_get_64 (objfile->obfd, ptr); + ptr += 8; + type_offset = read_offset_1 (objfile->obfd, ptr, offset_size); + ptr += offset_size; + + /* Skip dummy type units. */ + if (ptr >= end_ptr || peek_abbrev_code (objfile->obfd, ptr) == 0) + { + info_ptr = info_ptr + initial_length_size + length; + continue; + } + + type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig)); + memset (type_sig, 0, sizeof (*type_sig)); + type_sig->signature = signature; + type_sig->type_offset = type_offset; + type_sig->per_cu.objfile = objfile; + type_sig->per_cu.debug_types_section = section; + type_sig->per_cu.offset = offset; + + slot = htab_find_slot (types_htab, type_sig, INSERT); + gdb_assert (slot != NULL); + if (*slot != NULL) + { + const struct signatured_type *dup_sig = *slot; + + complaint (&symfile_complaints, + _("debug type entry at offset 0x%x is duplicate to the " + "entry at offset 0x%x, signature 0x%s"), + offset, dup_sig->per_cu.offset, + phex (signature, sizeof (signature))); + gdb_assert (signature == dup_sig->signature); + } + *slot = type_sig; - info_ptr = info_ptr + initial_length_size + length; + if (dwarf2_die_debug) + fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n", + offset, phex (signature, sizeof (signature))); + + info_ptr = info_ptr + initial_length_size + length; + } } dwarf2_per_objfile->signatured_types = types_htab; @@ -3130,10 +3355,10 @@ init_cu_die_reader (struct die_reader_specs *reader, { reader->abfd = cu->objfile->obfd; reader->cu = cu; - if (cu->per_cu->from_debug_types) + if (cu->per_cu->debug_types_section) { - gdb_assert (dwarf2_per_objfile->types.readin); - reader->buffer = dwarf2_per_objfile->types.buffer; + gdb_assert (cu->per_cu->debug_types_section->readin); + reader->buffer = cu->per_cu->debug_types_section->buffer; } else { @@ -3205,11 +3430,18 @@ process_psymtab_comp_unit (struct objfile *objfile, info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr, buffer, buffer_size, - abfd); + abfd, + this_cu->debug_types_section != NULL); - /* Complete the cu_header. */ - cu.header.offset = beg_of_comp_unit - buffer; - cu.header.first_die_offset = info_ptr - beg_of_comp_unit; + /* Skip dummy compilation units. */ + if (info_ptr >= buffer + buffer_size + || peek_abbrev_code (abfd, info_ptr) == 0) + { + info_ptr = (beg_of_comp_unit + cu.header.length + + cu.header.initial_length_size); + do_cleanups (back_to_inner); + return info_ptr; + } cu.list_in_scope = &file_symbols; @@ -3234,16 +3466,14 @@ process_psymtab_comp_unit (struct objfile *objfile, make_cleanup (dwarf2_free_abbrev_table, &cu); /* Read the compilation unit die. */ - if (this_cu->from_debug_types) - info_ptr += 8 /*signature*/ + cu.header.offset_size; init_cu_die_reader (&reader_specs, &cu); info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr, &has_children); - if (this_cu->from_debug_types) + if (this_cu->debug_types_section) { - /* offset,length haven't been set yet for type units. */ - this_cu->offset = cu.header.offset; + /* LENGTH has not been set yet for type units. */ + gdb_assert (this_cu->offset == cu.header.offset); this_cu->length = cu.header.length + cu.header.initial_length_size; } else if (comp_unit_die->tag == DW_TAG_partial_unit) @@ -3268,6 +3498,7 @@ process_psymtab_comp_unit (struct objfile *objfile, 0, objfile->global_psymbols.next, objfile->static_psymbols.next); + pst->psymtabs_addrmap_supported = 1; attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu); if (attr != NULL) @@ -3336,7 +3567,7 @@ process_psymtab_comp_unit (struct objfile *objfile, info_ptr = (beg_of_comp_unit + cu.header.length + cu.header.initial_length_size); - if (this_cu->from_debug_types) + if (this_cu->debug_types_section) { /* It's not clear we want to do anything with stmt lists here. Waiting to see what gcc ultimately does. */ @@ -3365,11 +3596,12 @@ process_type_comp_unit (void **slot, void *info) this_cu = &entry->per_cu; - gdb_assert (dwarf2_per_objfile->types.readin); + gdb_assert (this_cu->debug_types_section->readin); process_psymtab_comp_unit (objfile, this_cu, - dwarf2_per_objfile->types.buffer, - dwarf2_per_objfile->types.buffer + entry->offset, - dwarf2_per_objfile->types.size); + this_cu->debug_types_section->buffer, + (this_cu->debug_types_section->buffer + + this_cu->offset), + this_cu->debug_types_section->size); return 1; } @@ -3470,7 +3702,7 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu, struct objfile *objfile) { bfd *abfd = objfile->obfd; - gdb_byte *info_ptr, *beg_of_comp_unit; + gdb_byte *info_ptr; struct die_info *comp_unit_die; struct dwarf2_cu *cu; struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup = NULL; @@ -3478,11 +3710,10 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu, struct die_reader_specs reader_specs; int read_cu = 0; - gdb_assert (! this_cu->from_debug_types); + gdb_assert (! this_cu->debug_types_section); gdb_assert (dwarf2_per_objfile->info.readin); info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset; - beg_of_comp_unit = info_ptr; if (this_cu->cu == NULL) { @@ -3497,11 +3728,16 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu, info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr, dwarf2_per_objfile->info.buffer, dwarf2_per_objfile->info.size, - abfd); + abfd, 0); - /* Complete the cu_header. */ - cu->header.offset = this_cu->offset; - cu->header.first_die_offset = info_ptr - beg_of_comp_unit; + /* Skip dummy compilation units. */ + if (info_ptr >= (dwarf2_per_objfile->info.buffer + + dwarf2_per_objfile->info.size) + || peek_abbrev_code (abfd, info_ptr) == 0) + { + do_cleanups (free_cu_cleanup); + return; + } /* Link this compilation unit into the compilation unit tree. */ this_cu->cu = cu; @@ -3750,7 +3986,10 @@ partial_die_parent_scope (struct partial_die_info *pdi, return NULL; } - if (parent->tag == DW_TAG_namespace + if (pdi->tag == DW_TAG_enumerator) + /* Enumerators should not get the name of the enumeration as a prefix. */ + parent->scope = grandparent_scope; + else if (parent->tag == DW_TAG_namespace || parent->tag == DW_TAG_module || parent->tag == DW_TAG_structure_type || parent->tag == DW_TAG_class_type @@ -3765,9 +4004,6 @@ partial_die_parent_scope (struct partial_die_info *pdi, grandparent_scope, parent->name, 0, cu); } - else if (parent->tag == DW_TAG_enumerator) - /* Enumerators should not get the name of the enumeration as a prefix. */ - parent->scope = grandparent_scope; else { /* FIXME drow/2004-04-01: What should we be doing with @@ -4115,6 +4351,16 @@ add_partial_enumeration (struct partial_die_info *enum_pdi, } } +/* Return the initial uleb128 in the die at INFO_PTR. */ + +static unsigned int +peek_abbrev_code (bfd *abfd, gdb_byte *info_ptr) +{ + unsigned int bytes_read; + + return read_unsigned_leb128 (abfd, info_ptr, &bytes_read); +} + /* Read the initial uleb128 in the die at INFO_PTR in compilation unit CU. Return the corresponding abbrev, or NULL if the number is zero (indicating an empty DIE). In either case *BYTES_READ will be set to the length of @@ -4477,7 +4723,7 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, struct attribute *attr; int read_cu = 0; - gdb_assert (! per_cu->from_debug_types); + gdb_assert (! per_cu->debug_types_section); /* Set local variables from the partial symbol table info. */ offset = per_cu->offset; @@ -4499,6 +4745,15 @@ load_full_comp_unit (struct dwarf2_per_cu_data *per_cu, /* Read in the comp_unit header. */ info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd); + /* Skip dummy compilation units. */ + if (info_ptr >= (dwarf2_per_objfile->info.buffer + + dwarf2_per_objfile->info.size) + || peek_abbrev_code (abfd, info_ptr) == 0) + { + do_cleanups (free_cu_cleanup); + return; + } + /* Complete the cu_header. */ cu->header.offset = offset; cu->header.first_die_offset = info_ptr - beg_of_comp_unit; @@ -4587,52 +4842,14 @@ compute_delayed_physnames (struct dwarf2_cu *cu) struct delayed_method_info *mi; for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i) { - char *physname; + const char *physname; struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index); - physname = (char *) dwarf2_physname ((char *) mi->name, mi->die, cu); + physname = dwarf2_physname ((char *) mi->name, mi->die, cu); fn_flp->fn_fields[mi->index].physname = physname ? physname : ""; } } -/* Check for GCC >= 4.0. */ - -static int -producer_is_gcc_ge_4_0 (struct dwarf2_cu *cu) -{ - const char *cs; - int major, minor; - - if (cu->producer == NULL) - { - /* For unknown compilers expect their behavior is not compliant. For GCC - this case can also happen for -gdwarf-4 type units supported since - gcc-4.5. */ - - return 0; - } - - /* Skip any identifier after "GNU " - such as "C++" or "Java". */ - - if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0) - { - /* For non-GCC compilers expect their behavior is not compliant. */ - - return 0; - } - cs = &cu->producer[strlen ("GNU ")]; - while (*cs && !isdigit (*cs)) - cs++; - if (sscanf (cs, "%d.%d", &major, &minor) != 2) - { - /* Not recognized as GCC. */ - - return 0; - } - - return major >= 4; -} - /* Generate full symbol information for PST and CU, whose DIEs have already been loaded into memory. */ @@ -4654,8 +4871,6 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) cu->list_in_scope = &file_symbols; - dwarf2_find_base_address (cu->dies, cu); - /* Do line number decoding in read_file_scope () */ process_die (cu->dies, cu); @@ -4674,6 +4889,8 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) if (symtab != NULL) { + int gcc_4_minor = producer_is_gcc_ge_4 (cu->producer); + /* Set symtab language to language from DW_AT_language. If the compilation is from a C file generated by language preprocessors, do not set the language if it was already deduced by start_subfile. */ @@ -4690,8 +4907,13 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu) Still one can confuse GDB by using non-standard GCC compilation options - this waits on GCC PR other/32998 (-frecord-gcc-switches). */ - if (cu->has_loclist && producer_is_gcc_ge_4_0 (cu)) + if (cu->has_loclist && gcc_4_minor >= 0) symtab->locations_valid = 1; + + if (gcc_4_minor >= 5) + symtab->epilogue_unwind_valid = 1; + + symtab->call_site_htab = cu->call_site_htab; } if (dwarf2_per_objfile->using_index) @@ -4730,6 +4952,9 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_catch_block: read_lexical_block_scope (die, cu); break; + case DW_TAG_GNU_call_site: + read_call_site_scope (die, cu); + break; case DW_TAG_class_type: case DW_TAG_interface_type: case DW_TAG_structure_type: @@ -5211,7 +5436,7 @@ static void read_import_statement (struct die_info *die, struct dwarf2_cu *cu) { struct attribute *import_attr; - struct die_info *imported_die; + struct die_info *imported_die, *child_die; struct dwarf2_cu *imported_cu; const char *imported_name; const char *imported_name_prefix; @@ -5219,6 +5444,8 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu) const char *import_alias; const char *imported_declaration = NULL; const char *import_prefix; + VEC (const_char_ptr) *excludes = NULL; + struct cleanup *cleanups; char *temp; @@ -5298,11 +5525,60 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu) else canonical_name = imported_name; + cleanups = make_cleanup (VEC_cleanup (const_char_ptr), &excludes); + + if (die->tag == DW_TAG_imported_module && cu->language == language_fortran) + for (child_die = die->child; child_die && child_die->tag; + child_die = sibling_die (child_die)) + { + /* DWARF-4: A Fortran use statement with a “rename list” may be + represented by an imported module entry with an import attribute + referring to the module and owned entries corresponding to those + entities that are renamed as part of being imported. */ + + if (child_die->tag != DW_TAG_imported_declaration) + { + complaint (&symfile_complaints, + _("child DW_TAG_imported_declaration expected " + "- DIE at 0x%x [in module %s]"), + child_die->offset, cu->objfile->name); + continue; + } + + import_attr = dwarf2_attr (child_die, DW_AT_import, cu); + if (import_attr == NULL) + { + complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"), + dwarf_tag_name (child_die->tag)); + continue; + } + + imported_cu = cu; + imported_die = follow_die_ref_or_sig (child_die, import_attr, + &imported_cu); + imported_name = dwarf2_name (imported_die, imported_cu); + if (imported_name == NULL) + { + complaint (&symfile_complaints, + _("child DW_TAG_imported_declaration has unknown " + "imported name - DIE at 0x%x [in module %s]"), + child_die->offset, cu->objfile->name); + continue; + } + + VEC_safe_push (const_char_ptr, excludes, imported_name); + + process_die (child_die, cu); + } + cp_add_using_directive (import_prefix, canonical_name, import_alias, imported_declaration, + excludes, &cu->objfile->objfile_obstack); + + do_cleanups (cleanups); } static void @@ -5362,6 +5638,35 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu, *name = ""; } +/* Handle DW_AT_stmt_list for a compilation unit or type unit. + DIE is the DW_TAG_compile_unit or DW_TAG_type_unit die for CU. + COMP_DIR is the compilation directory. + WANT_LINE_INFO is non-zero if the pc/line-number mapping is needed. */ + +static void +handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, + const char *comp_dir, int want_line_info) +{ + struct attribute *attr; + struct objfile *objfile = cu->objfile; + bfd *abfd = objfile->obfd; + + attr = dwarf2_attr (die, DW_AT_stmt_list, cu); + if (attr) + { + unsigned int line_offset = DW_UNSND (attr); + struct line_header *line_header + = dwarf_decode_line_header (line_offset, abfd, cu); + + if (line_header) + { + cu->line_header = line_header; + make_cleanup (free_cu_line_header, cu); + dwarf_decode_lines (line_header, comp_dir, cu, NULL, want_line_info); + } + } +} + /* Process DW_TAG_compile_unit. */ static void @@ -5376,7 +5681,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) char *comp_dir = NULL; struct die_info *child_die; bfd *abfd = objfile->obfd; - struct line_header *line_header = 0; CORE_ADDR baseaddr; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -5422,18 +5726,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) /* Decode line number information if present. We do this before processing child DIEs, so that the line header table is available for DW_AT_decl_file. */ - attr = dwarf2_attr (die, DW_AT_stmt_list, cu); - if (attr) - { - unsigned int line_offset = DW_UNSND (attr); - line_header = dwarf_decode_line_header (line_offset, abfd, cu); - if (line_header) - { - cu->line_header = line_header; - make_cleanup (free_cu_line_header, cu); - dwarf_decode_lines (line_header, comp_dir, abfd, cu, NULL); - } - } + handle_DW_AT_stmt_list (die, cu, comp_dir, 1); /* Process all dies in compilation unit. */ if (die->child != NULL) @@ -5450,13 +5743,28 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) refers to information in the line number info statement program header, so we can only read it if we've read the header successfully. */ - attr = dwarf2_attr (die, DW_AT_macro_info, cu); - if (attr && line_header) + attr = dwarf2_attr (die, DW_AT_GNU_macros, cu); + if (attr && cu->line_header) + { + if (dwarf2_attr (die, DW_AT_macro_info, cu)) + complaint (&symfile_complaints, + _("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info")); + + dwarf_decode_macros (cu->line_header, DW_UNSND (attr), + comp_dir, abfd, cu, + &dwarf2_per_objfile->macro, 1); + } + else { - unsigned int macro_offset = DW_UNSND (attr); + attr = dwarf2_attr (die, DW_AT_macro_info, cu); + if (attr && cu->line_header) + { + unsigned int macro_offset = DW_UNSND (attr); - dwarf_decode_macros (line_header, macro_offset, - comp_dir, abfd, cu); + dwarf_decode_macros (cu->line_header, macro_offset, + comp_dir, abfd, cu, + &dwarf2_per_objfile->macinfo, 0); + } } do_cleanups (back_to); } @@ -5520,6 +5828,12 @@ read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu) record_debugformat ("DWARF 2"); record_producer (cu->producer); + /* Decode line number information if present. We do this before + processing child DIEs, so that the line header table is available + for DW_AT_decl_file. + We don't need the pc/line-number mapping for type units. */ + handle_DW_AT_stmt_list (die, cu, comp_dir, 0); + /* Process the dies in the type unit. */ if (die->child == NULL) { @@ -5942,12 +6256,264 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) using_directives = new->using_directives; } -/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. - Return 1 if the attributes are present and valid, otherwise, return 0. - If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */ +/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab. */ -static int -dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, +static void +read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + CORE_ADDR pc, baseaddr; + struct attribute *attr; + struct call_site *call_site, call_site_local; + void **slot; + int nparams; + struct die_info *child_die; + + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + attr = dwarf2_attr (die, DW_AT_low_pc, cu); + if (!attr) + { + complaint (&symfile_complaints, + _("missing DW_AT_low_pc for DW_TAG_GNU_call_site " + "DIE 0x%x [in module %s]"), + die->offset, cu->objfile->name); + return; + } + pc = DW_ADDR (attr) + baseaddr; + + if (cu->call_site_htab == NULL) + cu->call_site_htab = htab_create_alloc_ex (16, core_addr_hash, core_addr_eq, + NULL, &objfile->objfile_obstack, + hashtab_obstack_allocate, NULL); + call_site_local.pc = pc; + slot = htab_find_slot (cu->call_site_htab, &call_site_local, INSERT); + if (*slot != NULL) + { + complaint (&symfile_complaints, + _("Duplicate PC %s for DW_TAG_GNU_call_site " + "DIE 0x%x [in module %s]"), + paddress (gdbarch, pc), die->offset, cu->objfile->name); + return; + } + + /* Count parameters at the caller. */ + + nparams = 0; + for (child_die = die->child; child_die && child_die->tag; + child_die = sibling_die (child_die)) + { + if (child_die->tag != DW_TAG_GNU_call_site_parameter) + { + complaint (&symfile_complaints, + _("Tag %d is not DW_TAG_GNU_call_site_parameter in " + "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), + child_die->tag, child_die->offset, cu->objfile->name); + continue; + } + + nparams++; + } + + call_site = obstack_alloc (&objfile->objfile_obstack, + (sizeof (*call_site) + + (sizeof (*call_site->parameter) + * (nparams - 1)))); + *slot = call_site; + memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter)); + call_site->pc = pc; + + if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu)) + { + struct die_info *func_die; + + /* Skip also over DW_TAG_inlined_subroutine. */ + for (func_die = die->parent; + func_die && func_die->tag != DW_TAG_subprogram + && func_die->tag != DW_TAG_subroutine_type; + func_die = func_die->parent); + + /* DW_AT_GNU_all_call_sites is a superset + of DW_AT_GNU_all_tail_call_sites. */ + if (func_die + && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu) + && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu)) + { + /* TYPE_TAIL_CALL_LIST is not interesting in functions where it is + not complete. But keep CALL_SITE for look ups via call_site_htab, + both the initial caller containing the real return address PC and + the final callee containing the current PC of a chain of tail + calls do not need to have the tail call list complete. But any + function candidate for a virtual tail call frame searched via + TYPE_TAIL_CALL_LIST must have the tail call list complete to be + determined unambiguously. */ + } + else + { + struct type *func_type = NULL; + + if (func_die) + func_type = get_die_type (func_die, cu); + if (func_type != NULL) + { + gdb_assert (TYPE_CODE (func_type) == TYPE_CODE_FUNC); + + /* Enlist this call site to the function. */ + call_site->tail_call_next = TYPE_TAIL_CALL_LIST (func_type); + TYPE_TAIL_CALL_LIST (func_type) = call_site; + } + else + complaint (&symfile_complaints, + _("Cannot find function owning DW_TAG_GNU_call_site " + "DIE 0x%x [in module %s]"), + die->offset, cu->objfile->name); + } + } + + attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); + SET_FIELD_DWARF_BLOCK (call_site->target, NULL); + if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)) + /* Keep NULL DWARF_BLOCK. */; + else if (attr_form_is_block (attr)) + { + struct dwarf2_locexpr_baton *dlbaton; + + dlbaton = obstack_alloc (&objfile->objfile_obstack, sizeof (*dlbaton)); + dlbaton->data = DW_BLOCK (attr)->data; + dlbaton->size = DW_BLOCK (attr)->size; + dlbaton->per_cu = cu->per_cu; + + SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton); + } + else if (is_ref_attr (attr)) + { + struct objfile *objfile = cu->objfile; + struct dwarf2_cu *target_cu = cu; + struct die_info *target_die; + + target_die = follow_die_ref_or_sig (die, attr, &target_cu); + gdb_assert (target_cu->objfile == objfile); + if (die_is_declaration (target_die, target_cu)) + { + const char *target_physname; + + target_physname = dwarf2_physname (NULL, target_die, target_cu); + if (target_physname == NULL) + complaint (&symfile_complaints, + _("DW_AT_GNU_call_site_target target DIE has invalid " + "physname, for referencing DIE 0x%x [in module %s]"), + die->offset, cu->objfile->name); + else + SET_FIELD_PHYSNAME (call_site->target, (char *) target_physname); + } + else + { + CORE_ADDR lowpc; + + /* DW_AT_entry_pc should be preferred. */ + if (!dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)) + complaint (&symfile_complaints, + _("DW_AT_GNU_call_site_target target DIE has invalid " + "low pc, for referencing DIE 0x%x [in module %s]"), + die->offset, cu->objfile->name); + else + SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr); + } + } + else + complaint (&symfile_complaints, + _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither " + "block nor reference, for DIE 0x%x [in module %s]"), + die->offset, cu->objfile->name); + + call_site->per_cu = cu->per_cu; + + for (child_die = die->child; + child_die && child_die->tag; + child_die = sibling_die (child_die)) + { + struct dwarf2_locexpr_baton *dlbaton; + struct call_site_parameter *parameter; + + if (child_die->tag != DW_TAG_GNU_call_site_parameter) + { + /* Already printed the complaint above. */ + continue; + } + + gdb_assert (call_site->parameter_count < nparams); + parameter = &call_site->parameter[call_site->parameter_count]; + + /* DW_AT_location specifies the register number. Value of the data + assumed for the register is contained in DW_AT_GNU_call_site_value. */ + + attr = dwarf2_attr (child_die, DW_AT_location, cu); + if (!attr || !attr_form_is_block (attr)) + { + complaint (&symfile_complaints, + _("No DW_FORM_block* DW_AT_location for " + "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), + child_die->offset, cu->objfile->name); + continue; + } + parameter->dwarf_reg = dwarf_block_to_dwarf_reg (DW_BLOCK (attr)->data, + &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size]); + if (parameter->dwarf_reg == -1 + && !dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (attr)->data, + &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size], + ¶meter->fb_offset)) + { + complaint (&symfile_complaints, + _("Only single DW_OP_reg or DW_OP_fbreg is supported " + "for DW_FORM_block* DW_AT_location for " + "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), + child_die->offset, cu->objfile->name); + continue; + } + + attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu); + if (!attr_form_is_block (attr)) + { + complaint (&symfile_complaints, + _("No DW_FORM_block* DW_AT_GNU_call_site_value for " + "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), + child_die->offset, cu->objfile->name); + continue; + } + parameter->value = DW_BLOCK (attr)->data; + parameter->value_size = DW_BLOCK (attr)->size; + + /* Parameters are not pre-cleared by memset above. */ + parameter->data_value = NULL; + parameter->data_value_size = 0; + call_site->parameter_count++; + + attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu); + if (attr) + { + if (!attr_form_is_block (attr)) + complaint (&symfile_complaints, + _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for " + "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), + child_die->offset, cu->objfile->name); + else + { + parameter->data_value = DW_BLOCK (attr)->data; + parameter->data_value_size = DW_BLOCK (attr)->size; + } + } + } +} + +/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. + Return 1 if the attributes are present and valid, otherwise, return 0. + If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */ + +static int +dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, CORE_ADDR *high_return, struct dwarf2_cu *cu, struct partial_symtab *ranges_pst) { @@ -6141,7 +6707,8 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, return 0; *lowpc = low; - *highpc = high; + if (highpc) + *highpc = high; return ret; } @@ -6604,7 +7171,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, (so through at least 3.2.1) incorrectly generate DW_TAG_variable tags. */ - char *physname; + const char *physname; /* Get name of field. */ fieldname = dwarf2_name (die, cu); @@ -6625,7 +7192,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, } /* Get physical name. */ - physname = (char *) dwarf2_physname (fieldname, die, cu); + physname = dwarf2_physname (fieldname, die, cu); /* The name is already allocated along with this objfile, so we don't need to duplicate it for the type. */ @@ -6854,7 +7421,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, } else { - char *physname = (char *) dwarf2_physname (fieldname, die, cu); + const char *physname = dwarf2_physname (fieldname, die, cu); fnp->physname = physname ? physname : ""; } @@ -7376,6 +7943,9 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) } do_cleanups (back_to); + + if (HAVE_CPLUS_STRUCT (type)) + TYPE_CPLUS_REALLY_JAVA (type) = cu->language == language_java; } quirk_gcc_member_function_pointer (type, cu->objfile); @@ -7539,6 +8109,27 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) TYPE_UNSIGNED (this_type) = 1; } + /* If we are reading an enum from a .debug_types unit, and the enum + is a declaration, and the enum is not the signatured type in the + unit, then we do not want to add a symbol for it. Adding a + symbol would in some cases obscure the true definition of the + enum, giving users an incomplete type when the definition is + actually available. Note that we do not want to do this for all + enums which are just declarations, because C++0x allows forward + enum declarations. */ + if (cu->per_cu->debug_types_section + && die_is_declaration (die, cu)) + { + struct signatured_type *type_sig; + + type_sig + = lookup_signatured_type_at_offset (dwarf2_per_objfile->objfile, + cu->per_cu->debug_types_section, + cu->per_cu->offset); + if (type_sig->type_offset != die->offset) + return; + } + new_symbol (die, this_type, cu); } @@ -7830,7 +8421,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) const char *previous_prefix = determine_prefix (die, cu); cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL, - NULL, &objfile->objfile_obstack); + NULL, NULL, &objfile->objfile_obstack); } } @@ -8368,15 +8959,21 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) break; case DW_ATE_unsigned: type_flags |= TYPE_FLAG_UNSIGNED; + if (cu->language == language_fortran + && name + && strncmp (name, "character(", sizeof ("character(") - 1) == 0) + code = TYPE_CODE_CHAR; break; case DW_ATE_signed_char: if (cu->language == language_ada || cu->language == language_m2 - || cu->language == language_pascal) + || cu->language == language_pascal + || cu->language == language_fortran) code = TYPE_CODE_CHAR; break; case DW_ATE_unsigned_char: if (cu->language == language_ada || cu->language == language_m2 - || cu->language == language_pascal) + || cu->language == language_pascal + || cu->language == language_fortran) code = TYPE_CODE_CHAR; type_flags |= TYPE_FLAG_UNSIGNED; break; @@ -8439,7 +9036,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_upper_bound, cu); if (attr) { - if (attr->form == DW_FORM_block1 || is_ref_attr (attr)) + if (attr_form_is_block (attr) || is_ref_attr (attr)) { /* GCC encodes arrays with unspecified or dynamic length with a DW_FORM_block1 attribute or a reference attribute. @@ -8522,7 +9119,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) /* Mark arrays with dynamic length at least as an array of unspecified length. GDB could check the boundary but before it gets implemented at least allow accessing the array elements. */ - if (attr && attr->form == DW_FORM_block1) + if (attr && attr_form_is_block (attr)) TYPE_HIGH_BOUND_UNDEFINED (range_type) = 1; /* Ada expects an empty array on no boundary attributes. */ @@ -8634,11 +9231,9 @@ read_die_and_children (const struct die_reader_specs *reader, { fprintf_unfiltered (gdb_stdlog, "\nRead die from %s of %s:\n", - reader->buffer == dwarf2_per_objfile->info.buffer - ? ".debug_info" - : reader->buffer == dwarf2_per_objfile->types.buffer - ? ".debug_types" - : "unknown section", + (reader->cu->per_cu->debug_types_section + ? ".debug_types" + : ".debug_info"), reader->abfd->filename); dump_die (result, dwarf2_die_debug); } @@ -9068,7 +9663,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr, if (parent_die == NULL && part_die->has_specification == 0 && part_die->is_declaration == 0 - && (part_die->tag == DW_TAG_typedef + && ((part_die->tag == DW_TAG_typedef && !part_die->has_children) || part_die->tag == DW_TAG_base_type || part_die->tag == DW_TAG_subrange_type)) { @@ -9081,6 +9676,20 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr, continue; } + /* The exception for DW_TAG_typedef with has_children above is + a workaround of GCC PR debug/47510. In the case of this complaint + type_name_no_tag_or_error will error on such types later. + + GDB skipped children of DW_TAG_typedef by the shortcut above and then + it could not find the child DIEs referenced later, this is checked + above. In correct DWARF DW_TAG_typedef should have no children. */ + + if (part_die->tag == DW_TAG_typedef && part_die->has_children) + complaint (&symfile_complaints, + _("DW_TAG_typedef has childen - GCC PR debug/47510 bug " + "- DIE at 0x%x [in module %s]"), + part_die->offset, cu->objfile->name); + /* If we're at the second level, and we're an enumerator, and our parent has no specification (meaning possibly lives in a namespace elsewhere), then we can add the partial symbol now @@ -9410,7 +10019,7 @@ find_partial_die (unsigned int offset, struct dwarf2_cu *cu) struct dwarf2_per_cu_data *per_cu = NULL; struct partial_die_info *pd = NULL; - if (cu->per_cu->from_debug_types) + if (cu->per_cu->debug_types_section) { pd = find_partial_die_in_comp_unit (offset, cu); if (pd != NULL) @@ -9573,7 +10182,7 @@ fixup_partial_die (struct partial_die_info *part_die, NOTE: We need to do this even if cu->has_namespace_info != 0. gcc-4.5 -gdwarf-4 can drop the enclosing namespace. */ if (cu->language == language_cplus - && dwarf2_per_objfile->types.asection != NULL + && !VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types) && part_die->die_parent == NULL && part_die->has_children && (part_die->tag == DW_TAG_class_type @@ -9584,9 +10193,10 @@ fixup_partial_die (struct partial_die_info *part_die, /* GCC might emit a nameless struct or union that has a linkage name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */ if (part_die->name == NULL - && (part_die->tag == DW_TAG_structure_type - || part_die->tag == DW_TAG_union_type - || part_die->tag == DW_TAG_class_type) + && (part_die->tag == DW_TAG_class_type + || part_die->tag == DW_TAG_interface_type + || part_die->tag == DW_TAG_structure_type + || part_die->tag == DW_TAG_union_type) && part_die->linkage_name != NULL) { char *demangled; @@ -9594,7 +10204,17 @@ fixup_partial_die (struct partial_die_info *part_die, demangled = cplus_demangle (part_die->linkage_name, DMGL_TYPES); if (demangled) { - part_die->name = obsavestring (demangled, strlen (demangled), + const char *base; + + /* Strip any leading namespaces/classes, keep only the base name. + DW_AT_name for named DIEs does not contain the prefixes. */ + base = strrchr (demangled, ':'); + if (base && base > demangled && base[-1] == ':') + base++; + else + base = demangled; + + part_die->name = obsavestring (base, strlen (base), &cu->objfile->objfile_obstack); xfree (demangled); } @@ -10027,32 +10647,32 @@ read_direct_string (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) } static char * -read_indirect_string (bfd *abfd, gdb_byte *buf, - const struct comp_unit_head *cu_header, - unsigned int *bytes_read_ptr) +read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset) { - LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr); - dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str); if (dwarf2_per_objfile->str.buffer == NULL) - { - error (_("DW_FORM_strp used without .debug_str section [in module %s]"), - bfd_get_filename (abfd)); - return NULL; - } + error (_("DW_FORM_strp used without .debug_str section [in module %s]"), + bfd_get_filename (abfd)); if (str_offset >= dwarf2_per_objfile->str.size) - { - error (_("DW_FORM_strp pointing outside of " - ".debug_str section [in module %s]"), - bfd_get_filename (abfd)); - return NULL; - } + error (_("DW_FORM_strp pointing outside of " + ".debug_str section [in module %s]"), + bfd_get_filename (abfd)); gdb_assert (HOST_CHAR_BIT == 8); if (dwarf2_per_objfile->str.buffer[str_offset] == '\0') return NULL; return (char *) (dwarf2_per_objfile->str.buffer + str_offset); } +static char * +read_indirect_string (bfd *abfd, gdb_byte *buf, + const struct comp_unit_head *cu_header, + unsigned int *bytes_read_ptr) +{ + LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr); + + return read_indirect_string_at_offset (abfd, str_offset); +} + static unsigned long read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr) { @@ -10609,31 +11229,12 @@ noop_record_line (struct subfile *subfile, int line, CORE_ADDR pc) return; } -/* Decode the Line Number Program (LNP) for the given line_header - structure and CU. The actual information extracted and the type - of structures created from the LNP depends on the value of PST. - - 1. If PST is NULL, then this procedure uses the data from the program - to create all necessary symbol tables, and their linetables. - - 2. If PST is not NULL, this procedure reads the program to determine - the list of files included by the unit represented by PST, and - builds all the associated partial symbol tables. - - COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown. - It is used for relative paths in the line table. - NOTE: When processing partial symtabs (pst != NULL), - comp_dir == pst->dirname. - - NOTE: It is important that psymtabs have the same file name (via strcmp) - as the corresponding symtab. Since COMP_DIR is not used in the name of the - symtab we don't use it in the name of the psymtabs we create. - E.g. expand_line_sal requires this when finding psymtabs to expand. - A good testcase for this is mb-inline.exp. */ +/* Subroutine of dwarf_decode_lines to simplify it. + Process the line number information in LH. */ static void -dwarf_decode_lines (struct line_header *lh, const char *comp_dir, bfd *abfd, - struct dwarf2_cu *cu, struct partial_symtab *pst) +dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir, + struct dwarf2_cu *cu, struct partial_symtab *pst) { gdb_byte *line_ptr, *extended_end; gdb_byte *line_end; @@ -10641,9 +11242,10 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir, bfd *abfd, unsigned char op_code, extended_op, adj_opcode; CORE_ADDR baseaddr; struct objfile *objfile = cu->objfile; + bfd *abfd = objfile->obfd; struct gdbarch *gdbarch = get_objfile_arch (objfile); const int decode_for_pst_p = (pst != NULL); - struct subfile *last_subfile = NULL, *first_subfile = current_subfile; + struct subfile *last_subfile = NULL; void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc) = record_line; @@ -10923,6 +11525,41 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir, bfd *abfd, } } } +} + +/* Decode the Line Number Program (LNP) for the given line_header + structure and CU. The actual information extracted and the type + of structures created from the LNP depends on the value of PST. + + 1. If PST is NULL, then this procedure uses the data from the program + to create all necessary symbol tables, and their linetables. + + 2. If PST is not NULL, this procedure reads the program to determine + the list of files included by the unit represented by PST, and + builds all the associated partial symbol tables. + + COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown. + It is used for relative paths in the line table. + NOTE: When processing partial symtabs (pst != NULL), + comp_dir == pst->dirname. + + NOTE: It is important that psymtabs have the same file name (via strcmp) + as the corresponding symtab. Since COMP_DIR is not used in the name of the + symtab we don't use it in the name of the psymtabs we create. + E.g. expand_line_sal requires this when finding psymtabs to expand. + A good testcase for this is mb-inline.exp. */ + +static void +dwarf_decode_lines (struct line_header *lh, const char *comp_dir, + struct dwarf2_cu *cu, struct partial_symtab *pst, + int want_line_info) +{ + struct objfile *objfile = cu->objfile; + const int decode_for_pst_p = (pst != NULL); + struct subfile *first_subfile = current_subfile; + + if (want_line_info) + dwarf_decode_lines_1 (lh, comp_dir, cu, pst); if (decode_for_pst_p) { @@ -10944,13 +11581,12 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir, bfd *abfd, /* Make sure a symtab is created for every file, even files which contain only variables (i.e. no code with associated line numbers). */ - int i; - struct file_entry *fe; for (i = 0; i < lh->num_file_names; i++) { char *dir = NULL; + struct file_entry *fe; fe = &lh->file_names[i]; if (fe->dir_index) @@ -11329,14 +11965,6 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, { dwarf2_const_value (attr, sym, cu); } - attr = dwarf2_attr (die, DW_AT_variable_parameter, cu); - if (attr && DW_UNSND (attr)) - { - struct type *ref_type; - - ref_type = lookup_reference_type (SYMBOL_TYPE (sym)); - SYMBOL_TYPE (sym) = ref_type; - } list_to_add = cu->list_in_scope; break; @@ -11445,7 +12073,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, namespaces based on the demangled name. */ if (!processing_has_namespace_info && cu->language == language_cplus) - cp_scan_for_anonymous_namespaces (sym); + cp_scan_for_anonymous_namespaces (sym, objfile); } return (sym); } @@ -11750,8 +12378,8 @@ lookup_die_type (struct die_info *die, struct attribute *attr, "at 0x%x [in module %s]"), die->offset, cu->objfile->name); - gdb_assert (sig_type->per_cu.from_debug_types); - offset = sig_type->offset + sig_type->type_offset; + gdb_assert (sig_type->per_cu.debug_types_section); + offset = sig_type->per_cu.offset + sig_type->type_offset; this_type = get_die_type_at_offset (offset, &sig_type->per_cu); } else @@ -11963,6 +12591,42 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu) return NULL; } +/* GCC might emit a nameless typedef that has a linkage name. Determine the + prefix part in such case. See + http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */ + +static char * +anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *attr; + char *base; + + if (die->tag != DW_TAG_class_type && die->tag != DW_TAG_interface_type + && die->tag != DW_TAG_structure_type && die->tag != DW_TAG_union_type) + return NULL; + + attr = dwarf2_attr (die, DW_AT_name, cu); + if (attr != NULL && DW_STRING (attr) != NULL) + return NULL; + + attr = dwarf2_attr (die, DW_AT_linkage_name, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + if (attr == NULL || DW_STRING (attr) == NULL) + return NULL; + + /* dwarf2_name had to be already called. */ + gdb_assert (DW_STRING_IS_CANONICAL (attr)); + + /* Strip the base name, keep any leading namespaces/classes. */ + base = strrchr (DW_STRING (attr), ':'); + if (base == NULL || base == DW_STRING (attr) || base[-1] != ':') + return ""; + + return obsavestring (DW_STRING (attr), &base[-1] - DW_STRING (attr), + &cu->objfile->objfile_obstack); +} + /* Return the name of the namespace/class that DIE is defined within, or "" if we can't tell. The caller should not xfree the result. @@ -11984,11 +12648,16 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) struct die_info *parent, *spec_die; struct dwarf2_cu *spec_cu; struct type *parent_type; + char *retval; if (cu->language != language_cplus && cu->language != language_java && cu->language != language_fortran) return ""; + retval = anonymous_struct_prefix (die, cu); + if (retval) + return retval; + /* We have to be careful in the presence of DW_AT_specification. For example, with GCC 3.4, given the code @@ -12092,7 +12761,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_compile_unit: /* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */ if (cu->language == language_cplus - && dwarf2_per_objfile->types.asection != NULL + && !VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types) && die->child != NULL && (die->tag == DW_TAG_class_type || die->tag == DW_TAG_structure_type @@ -12280,12 +12949,21 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) if (demangled) { + char *base; + /* FIXME: we already did this for the partial symbol... */ - DW_STRING (attr) - = obsavestring (demangled, strlen (demangled), - &cu->objfile->objfile_obstack); + DW_STRING (attr) = obsavestring (demangled, strlen (demangled), + &cu->objfile->objfile_obstack); DW_STRING_IS_CANONICAL (attr) = 1; xfree (demangled); + + /* Strip any leading namespaces/classes, keep only the base name. + DW_AT_name for named DIEs does not contain the prefixes. */ + base = strrchr (DW_STRING (attr), ':'); + if (base && base > DW_STRING (attr) && base[-1] == ':') + return &base[1]; + else + return DW_STRING (attr); } } break; @@ -12469,6 +13147,8 @@ dwarf_tag_name (unsigned tag) return "DW_TAG_PGI_kanji_type"; case DW_TAG_PGI_interface_block: return "DW_TAG_PGI_interface_block"; + case DW_TAG_GNU_call_site: + return "DW_TAG_GNU_call_site"; default: return "DW_TAG_"; } @@ -13142,6 +13822,18 @@ dwarf_stack_op_name (unsigned op) return "DW_OP_GNU_uninit"; case DW_OP_GNU_implicit_pointer: return "DW_OP_GNU_implicit_pointer"; + case DW_OP_GNU_entry_value: + return "DW_OP_GNU_entry_value"; + case DW_OP_GNU_const_type: + return "DW_OP_GNU_const_type"; + case DW_OP_GNU_regval_type: + return "DW_OP_GNU_regval_type"; + case DW_OP_GNU_deref_type: + return "DW_OP_GNU_deref_type"; + case DW_OP_GNU_convert: + return "DW_OP_GNU_convert"; + case DW_OP_GNU_reinterpret: + return "DW_OP_GNU_reinterpret"; default: return NULL; } @@ -13366,7 +14058,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) case DW_FORM_ref_sig8: if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL) fprintf_unfiltered (f, "signatured type, offset: 0x%x", - DW_SIGNATURED_TYPE (&die->attrs[i])->offset); + DW_SIGNATURED_TYPE (&die->attrs[i])->per_cu.offset); else fprintf_unfiltered (f, "signatured type, offset: unknown"); break; @@ -13592,7 +14284,7 @@ follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu) target_cu = cu; - if (cu->per_cu->from_debug_types) + if (cu->per_cu->debug_types_section) { /* .debug_types CUs cannot reference anything outside their CU. If they need to, they have to reference a signatured type via @@ -13645,8 +14337,9 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr, return die; } -/* Return DWARF block and its CU referenced by OFFSET at PER_CU. Returned - value is intended for DW_OP_call*. */ +/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU. + Returned value is intended for DW_OP_call*. Returned + dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */ struct dwarf2_locexpr_baton dwarf2_fetch_die_location_block (unsigned int offset, @@ -13654,13 +14347,17 @@ dwarf2_fetch_die_location_block (unsigned int offset, CORE_ADDR (*get_frame_pc) (void *baton), void *baton) { - struct dwarf2_cu *cu = per_cu->cu; + struct dwarf2_cu *cu; struct die_info *die; struct attribute *attr; struct dwarf2_locexpr_baton retval; dw2_setup (per_cu->objfile); + if (per_cu->cu == NULL) + load_cu (per_cu); + cu = per_cu->cu; + die = follow_die_offset (offset, &cu); if (!die) error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"), @@ -13669,7 +14366,8 @@ dwarf2_fetch_die_location_block (unsigned int offset, attr = dwarf2_attr (die, DW_AT_location, cu); if (!attr) { - /* DWARF: "If there is no such attribute, then there is no effect.". */ + /* DWARF: "If there is no such attribute, then there is no effect.". + DATA is ignored if SIZE is 0. */ retval.data = NULL; retval.size = 0; @@ -13697,9 +14395,23 @@ dwarf2_fetch_die_location_block (unsigned int offset, retval.size = DW_BLOCK (attr)->size; } retval.per_cu = cu->per_cu; + + age_cached_comp_units (); + return retval; } +/* Return the type of the DIE at DIE_OFFSET in the CU named by + PER_CU. */ + +struct type * +dwarf2_get_die_type (unsigned int die_offset, + struct dwarf2_per_cu_data *per_cu) +{ + dw2_setup (per_cu->objfile); + return get_die_type_at_offset (die_offset, per_cu); +} + /* Follow the signature attribute ATTR in SRC_DIE. On entry *REF_CU is the CU of SRC_DIE. On exit *REF_CU is the CU of the result. */ @@ -13745,9 +14457,11 @@ follow_die_sig (struct die_info *src_die, struct attribute *attr, /* Given an offset of a signatured type, return its signatured_type. */ static struct signatured_type * -lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset) +lookup_signatured_type_at_offset (struct objfile *objfile, + struct dwarf2_section_info *section, + unsigned int offset) { - gdb_byte *info_ptr = dwarf2_per_objfile->types.buffer + offset; + gdb_byte *info_ptr = section->buffer + offset; unsigned int length, initial_length_size; unsigned int sig_offset; struct signatured_type find_entry, *type_sig; @@ -13763,7 +14477,7 @@ lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset) /* This is only used to lookup previously recorded types. If we didn't find it, it's our bug. */ gdb_assert (type_sig != NULL); - gdb_assert (offset == type_sig->offset); + gdb_assert (offset == type_sig->per_cu.offset); return type_sig; } @@ -13772,15 +14486,16 @@ lookup_signatured_type_at_offset (struct objfile *objfile, unsigned int offset) static void read_signatured_type_at_offset (struct objfile *objfile, + struct dwarf2_section_info *sect, unsigned int offset) { struct signatured_type *type_sig; - dwarf2_read_section (objfile, &dwarf2_per_objfile->types); + dwarf2_read_section (objfile, sect); /* We have the section offset, but we need the signature to do the hash table lookup. */ - type_sig = lookup_signatured_type_at_offset (objfile, offset); + type_sig = lookup_signatured_type_at_offset (objfile, sect, offset); gdb_assert (type_sig->per_cu.cu == NULL); @@ -13800,9 +14515,10 @@ read_signatured_type (struct objfile *objfile, struct dwarf2_cu *cu; ULONGEST signature; struct cleanup *back_to, *free_cu_cleanup; + struct dwarf2_section_info *section = type_sig->per_cu.debug_types_section; - dwarf2_read_section (objfile, &dwarf2_per_objfile->types); - types_ptr = dwarf2_per_objfile->types.buffer + type_sig->offset; + dwarf2_read_section (objfile, section); + types_ptr = section->buffer + type_sig->per_cu.offset; gdb_assert (type_sig->per_cu.cu == NULL); @@ -13815,7 +14531,7 @@ read_signatured_type (struct objfile *objfile, /* If an error occurs while loading, release our storage. */ free_cu_cleanup = make_cleanup (free_one_comp_unit, cu); - types_ptr = read_type_comp_unit_head (&cu->header, &signature, + types_ptr = read_type_comp_unit_head (&cu->header, section, &signature, types_ptr, objfile->obfd); gdb_assert (signature == type_sig->signature); @@ -14011,6 +14727,11 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) i += 4; break; + case DW_OP_const8u: + stack[++stacki] = read_8_bytes (objfile->obfd, &data[i]); + i += 8; + break; + case DW_OP_constu: stack[++stacki] = read_unsigned_leb128 (NULL, (data + i), &bytes_read); @@ -14058,9 +14779,12 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) /* Nothing should follow this operator, so the top of stack would be returned. */ /* This is valid for partial global symbols, but the variable's - address will be bogus in the psymtab. */ + address will be bogus in the psymtab. Make it always at least + non-zero to not look as a variable garbage collected by linker + which have DW_OP_addr 0. */ if (i < size) dwarf2_complex_location_expr_complaint (); + stack[stacki]++; break; case DW_OP_GNU_uninit: @@ -14396,117 +15120,205 @@ parse_macro_definition (struct macro_source_file *file, int line, dwarf2_macro_malformed_definition_complaint (body); } +/* Skip some bytes from BYTES according to the form given in FORM. + Returns the new pointer. */ -static void -dwarf_decode_macros (struct line_header *lh, unsigned int offset, - char *comp_dir, bfd *abfd, - struct dwarf2_cu *cu) +static gdb_byte * +skip_form_bytes (bfd *abfd, gdb_byte *bytes, + enum dwarf_form form, + unsigned int offset_size, + struct dwarf2_section_info *section) { - gdb_byte *mac_ptr, *mac_end; - struct macro_source_file *current_file = 0; - enum dwarf_macinfo_record_type macinfo_type; - int at_commandline; + unsigned int bytes_read; - dwarf2_read_section (dwarf2_per_objfile->objfile, - &dwarf2_per_objfile->macinfo); - if (dwarf2_per_objfile->macinfo.buffer == NULL) + switch (form) { - complaint (&symfile_complaints, _("missing .debug_macinfo section")); - return; + case DW_FORM_data1: + case DW_FORM_flag: + ++bytes; + break; + + case DW_FORM_data2: + bytes += 2; + break; + + case DW_FORM_data4: + bytes += 4; + break; + + case DW_FORM_data8: + bytes += 8; + break; + + case DW_FORM_string: + read_direct_string (abfd, bytes, &bytes_read); + bytes += bytes_read; + break; + + case DW_FORM_sec_offset: + case DW_FORM_strp: + bytes += offset_size; + break; + + case DW_FORM_block: + bytes += read_unsigned_leb128 (abfd, bytes, &bytes_read); + bytes += bytes_read; + break; + + case DW_FORM_block1: + bytes += 1 + read_1_byte (abfd, bytes); + break; + case DW_FORM_block2: + bytes += 2 + read_2_bytes (abfd, bytes); + break; + case DW_FORM_block4: + bytes += 4 + read_4_bytes (abfd, bytes); + break; + + case DW_FORM_sdata: + case DW_FORM_udata: + bytes = skip_leb128 (abfd, bytes); + break; + + default: + { + complain: + complaint (&symfile_complaints, + _("invalid form 0x%x in `%s'"), + form, + section->asection->name); + return NULL; + } } - /* First pass: Find the name of the base filename. - This filename is needed in order to process all macros whose definition - (or undefinition) comes from the command line. These macros are defined - before the first DW_MACINFO_start_file entry, and yet still need to be - associated to the base file. + return bytes; +} - To determine the base file name, we scan the macro definitions until we - reach the first DW_MACINFO_start_file entry. We then initialize - CURRENT_FILE accordingly so that any macro definition found before the - first DW_MACINFO_start_file can still be associated to the base file. */ +/* A helper for dwarf_decode_macros that handles skipping an unknown + opcode. Returns an updated pointer to the macro data buffer; or, + on error, issues a complaint and returns NULL. */ - mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; - mac_end = dwarf2_per_objfile->macinfo.buffer - + dwarf2_per_objfile->macinfo.size; +static gdb_byte * +skip_unknown_opcode (unsigned int opcode, + gdb_byte **opcode_definitions, + gdb_byte *mac_ptr, + bfd *abfd, + unsigned int offset_size, + struct dwarf2_section_info *section) +{ + unsigned int bytes_read, i; + unsigned long arg; + gdb_byte *defn; - do + if (opcode_definitions[opcode] == NULL) { - /* Do we at least have room for a macinfo type byte? */ - if (mac_ptr >= mac_end) - { - /* Complaint is printed during the second pass as GDB will probably - stop the first pass earlier upon finding - DW_MACINFO_start_file. */ - break; - } + complaint (&symfile_complaints, + _("unrecognized DW_MACFINO opcode 0x%x"), + opcode); + return NULL; + } - macinfo_type = read_1_byte (abfd, mac_ptr); - mac_ptr++; + defn = opcode_definitions[opcode]; + arg = read_unsigned_leb128 (abfd, defn, &bytes_read); + defn += bytes_read; - switch (macinfo_type) - { - /* A zero macinfo type indicates the end of the macro - information. */ - case 0: - break; + for (i = 0; i < arg; ++i) + { + mac_ptr = skip_form_bytes (abfd, mac_ptr, defn[i], offset_size, section); + if (mac_ptr == NULL) + { + /* skip_form_bytes already issued the complaint. */ + return NULL; + } + } - case DW_MACINFO_define: - case DW_MACINFO_undef: - /* Only skip the data by MAC_PTR. */ - { - unsigned int bytes_read; + return mac_ptr; +} - read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - read_direct_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - } - break; +/* A helper function which parses the header of a macro section. + If the macro section is the extended (for now called "GNU") type, + then this updates *OFFSET_SIZE. Returns a pointer to just after + the header, or issues a complaint and returns NULL on error. */ - case DW_MACINFO_start_file: - { - unsigned int bytes_read; - int line, file; +static gdb_byte * +dwarf_parse_macro_header (gdb_byte **opcode_definitions, + bfd *abfd, + gdb_byte *mac_ptr, + unsigned int *offset_size, + int section_is_gnu) +{ + memset (opcode_definitions, 0, 256 * sizeof (gdb_byte *)); - line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; + if (section_is_gnu) + { + unsigned int version, flags; - current_file = macro_start_file (file, line, current_file, - comp_dir, lh, cu->objfile); - } - break; + version = read_2_bytes (abfd, mac_ptr); + if (version != 4) + { + complaint (&symfile_complaints, + _("unrecognized version `%d' in .debug_macro section"), + version); + return NULL; + } + mac_ptr += 2; - case DW_MACINFO_end_file: - /* No data to skip by MAC_PTR. */ - break; + flags = read_1_byte (abfd, mac_ptr); + ++mac_ptr; + *offset_size = (flags & 1) ? 8 : 4; - case DW_MACINFO_vendor_ext: - /* Only skip the data by MAC_PTR. */ - { - unsigned int bytes_read; + if ((flags & 2) != 0) + /* We don't need the line table offset. */ + mac_ptr += *offset_size; - read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - read_direct_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - } - break; + /* Vendor opcode descriptions. */ + if ((flags & 4) != 0) + { + unsigned int i, count; - default: - break; + count = read_1_byte (abfd, mac_ptr); + ++mac_ptr; + for (i = 0; i < count; ++i) + { + unsigned int opcode, bytes_read; + unsigned long arg; + + opcode = read_1_byte (abfd, mac_ptr); + ++mac_ptr; + opcode_definitions[opcode] = mac_ptr; + arg = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + mac_ptr += arg; + } } - } while (macinfo_type != 0 && current_file == NULL); + } - /* Second pass: Process all entries. + return mac_ptr; +} - Use the AT_COMMAND_LINE flag to determine whether we are still processing - command-line macro definitions/undefinitions. This flag is unset when we - reach the first DW_MACINFO_start_file entry. */ +/* A helper for dwarf_decode_macros that handles the GNU extensions, + including DW_GNU_MACINFO_transparent_include. */ - mac_ptr = dwarf2_per_objfile->macinfo.buffer + offset; +static void +dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end, + struct macro_source_file *current_file, + struct line_header *lh, char *comp_dir, + struct dwarf2_section_info *section, + int section_is_gnu, + unsigned int offset_size, + struct objfile *objfile) +{ + enum dwarf_macro_record_type macinfo_type; + int at_commandline; + gdb_byte *opcode_definitions[256]; + + mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr, + &offset_size, section_is_gnu); + if (mac_ptr == NULL) + { + /* We already issued a complaint. */ + return; + } /* Determines if GDB is still before first DW_MACINFO_start_file. If true GDB is still reading the definitions from command line. First @@ -14522,13 +15334,15 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, /* Do we at least have room for a macinfo type byte? */ if (mac_ptr >= mac_end) { - dwarf2_macros_too_long_complaint (); + dwarf2_macros_too_long_complaint (section); break; } macinfo_type = read_1_byte (abfd, mac_ptr); mac_ptr++; + /* Note that we rely on the fact that the corresponding GNU and + DWARF constants are the same. */ switch (macinfo_type) { /* A zero macinfo type indicates the end of the macro @@ -14536,29 +15350,45 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, case 0: break; - case DW_MACINFO_define: - case DW_MACINFO_undef: + case DW_MACRO_GNU_define: + case DW_MACRO_GNU_undef: + case DW_MACRO_GNU_define_indirect: + case DW_MACRO_GNU_undef_indirect: { unsigned int bytes_read; int line; char *body; + int is_define; - line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - body = read_direct_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + if (macinfo_type == DW_MACRO_GNU_define + || macinfo_type == DW_MACRO_GNU_undef) + { + body = read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + } + else + { + LONGEST str_offset; + + str_offset = read_offset_1 (abfd, mac_ptr, offset_size); + mac_ptr += offset_size; + + body = read_indirect_string_at_offset (abfd, str_offset); + } + is_define = (macinfo_type == DW_MACRO_GNU_define + || macinfo_type == DW_MACRO_GNU_define_indirect); if (! current_file) { /* DWARF violation as no main source is present. */ complaint (&symfile_complaints, _("debug info with no main source gives macro %s " "on line %d: %s"), - macinfo_type == DW_MACINFO_define ? - _("definition") : - macinfo_type == DW_MACINFO_undef ? - _("undefinition") : - _("something-or-other"), line, body); + is_define ? _("definition") : _("undefinition"), + line, body); break; } if ((line == 0 && !at_commandline) @@ -14566,21 +15396,21 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, complaint (&symfile_complaints, _("debug info gives %s macro %s with %s line %d: %s"), at_commandline ? _("command-line") : _("in-file"), - macinfo_type == DW_MACINFO_define ? - _("definition") : - macinfo_type == DW_MACINFO_undef ? - _("undefinition") : - _("something-or-other"), + is_define ? _("definition") : _("undefinition"), line == 0 ? _("zero") : _("non-zero"), line, body); - if (macinfo_type == DW_MACINFO_define) + if (is_define) parse_macro_definition (current_file, line, body); - else if (macinfo_type == DW_MACINFO_undef) - macro_undef (current_file, line, body); + else + { + gdb_assert (macinfo_type == DW_MACRO_GNU_undef + || macinfo_type == DW_MACRO_GNU_undef_indirect); + macro_undef (current_file, line, body); + } } break; - case DW_MACINFO_start_file: + case DW_MACRO_GNU_start_file: { unsigned int bytes_read; int line, file; @@ -14600,17 +15430,18 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, if (at_commandline) { - /* This DW_MACINFO_start_file was executed in the pass one. */ + /* This DW_MACRO_GNU_start_file was executed in the + pass one. */ at_commandline = 0; } else current_file = macro_start_file (file, line, current_file, comp_dir, - lh, cu->objfile); + lh, objfile); } break; - case DW_MACINFO_end_file: + case DW_MACRO_GNU_end_file: if (! current_file) complaint (&symfile_complaints, _("macro debug info has an unmatched " @@ -14620,7 +15451,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, current_file = current_file->included_by; if (! current_file) { - enum dwarf_macinfo_record_type next_type; + enum dwarf_macro_record_type next_type; /* GCC circa March 2002 doesn't produce the zero type byte marking the end of the compilation @@ -14630,7 +15461,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, /* Do we at least have room for a macinfo type byte? */ if (mac_ptr >= mac_end) { - dwarf2_macros_too_long_complaint (); + dwarf2_macros_too_long_complaint (section); return; } @@ -14647,23 +15478,199 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset, } break; + case DW_MACRO_GNU_transparent_include: + { + LONGEST offset; + + offset = read_offset_1 (abfd, mac_ptr, offset_size); + mac_ptr += offset_size; + + dwarf_decode_macro_bytes (abfd, + section->buffer + offset, + mac_end, current_file, + lh, comp_dir, + section, section_is_gnu, + offset_size, objfile); + } + break; + case DW_MACINFO_vendor_ext: - { - unsigned int bytes_read; - int constant; + if (!section_is_gnu) + { + unsigned int bytes_read; + int constant; - constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; - read_direct_string (abfd, mac_ptr, &bytes_read); - mac_ptr += bytes_read; + constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; - /* We don't recognize any vendor extensions. */ - } - break; + /* We don't recognize any vendor extensions. */ + break; + } + /* FALLTHROUGH */ + + default: + mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions, + mac_ptr, abfd, offset_size, + section); + if (mac_ptr == NULL) + return; + break; } } while (macinfo_type != 0); } +static void +dwarf_decode_macros (struct line_header *lh, unsigned int offset, + char *comp_dir, bfd *abfd, + struct dwarf2_cu *cu, + struct dwarf2_section_info *section, + int section_is_gnu) +{ + gdb_byte *mac_ptr, *mac_end; + struct macro_source_file *current_file = 0; + enum dwarf_macro_record_type macinfo_type; + unsigned int offset_size = cu->header.offset_size; + gdb_byte *opcode_definitions[256]; + + dwarf2_read_section (dwarf2_per_objfile->objfile, section); + if (section->buffer == NULL) + { + complaint (&symfile_complaints, _("missing %s section"), + section->asection->name); + return; + } + + /* First pass: Find the name of the base filename. + This filename is needed in order to process all macros whose definition + (or undefinition) comes from the command line. These macros are defined + before the first DW_MACINFO_start_file entry, and yet still need to be + associated to the base file. + + To determine the base file name, we scan the macro definitions until we + reach the first DW_MACINFO_start_file entry. We then initialize + CURRENT_FILE accordingly so that any macro definition found before the + first DW_MACINFO_start_file can still be associated to the base file. */ + + mac_ptr = section->buffer + offset; + mac_end = section->buffer + section->size; + + mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr, + &offset_size, section_is_gnu); + if (mac_ptr == NULL) + { + /* We already issued a complaint. */ + return; + } + + do + { + /* Do we at least have room for a macinfo type byte? */ + if (mac_ptr >= mac_end) + { + /* Complaint is printed during the second pass as GDB will probably + stop the first pass earlier upon finding + DW_MACINFO_start_file. */ + break; + } + + macinfo_type = read_1_byte (abfd, mac_ptr); + mac_ptr++; + + /* Note that we rely on the fact that the corresponding GNU and + DWARF constants are the same. */ + switch (macinfo_type) + { + /* A zero macinfo type indicates the end of the macro + information. */ + case 0: + break; + + case DW_MACRO_GNU_define: + case DW_MACRO_GNU_undef: + /* Only skip the data by MAC_PTR. */ + { + unsigned int bytes_read; + + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + } + break; + + case DW_MACRO_GNU_start_file: + { + unsigned int bytes_read; + int line, file; + + line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + file = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + + current_file = macro_start_file (file, line, current_file, + comp_dir, lh, cu->objfile); + } + break; + + case DW_MACRO_GNU_end_file: + /* No data to skip by MAC_PTR. */ + break; + + case DW_MACRO_GNU_define_indirect: + case DW_MACRO_GNU_undef_indirect: + { + unsigned int bytes_read; + + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + mac_ptr += offset_size; + } + break; + + case DW_MACRO_GNU_transparent_include: + /* Note that, according to the spec, a transparent include + chain cannot call DW_MACRO_GNU_start_file. So, we can just + skip this opcode. */ + mac_ptr += offset_size; + break; + + case DW_MACINFO_vendor_ext: + /* Only skip the data by MAC_PTR. */ + if (!section_is_gnu) + { + unsigned int bytes_read; + + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + read_direct_string (abfd, mac_ptr, &bytes_read); + mac_ptr += bytes_read; + } + /* FALLTHROUGH */ + + default: + mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions, + mac_ptr, abfd, offset_size, + section); + if (mac_ptr == NULL) + return; + break; + } + } while (macinfo_type != 0 && current_file == NULL); + + /* Second pass: Process all entries. + + Use the AT_COMMAND_LINE flag to determine whether we are still processing + command-line macro definitions/undefinitions. This flag is unset when we + reach the first DW_MACINFO_start_file entry. */ + + dwarf_decode_macro_bytes (abfd, section->buffer + offset, mac_end, + current_file, lh, comp_dir, section, section_is_gnu, + offset_size, cu->objfile); +} + /* Check if the attribute's form is a DW_FORM_block* if so return true else false. */ static int @@ -14792,7 +15799,6 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, dwarf2_invalid_attrib_class_complaint ("location description", SYMBOL_NATURAL_NAME (sym)); baton->size = 0; - baton->data = NULL; } SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; @@ -14817,26 +15823,42 @@ dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *per_cu) return objfile; } +/* Return comp_unit_head for PER_CU, either already available in PER_CU->CU + (CU_HEADERP is unused in such case) or prepare a temporary copy at + CU_HEADERP first. */ + +static const struct comp_unit_head * +per_cu_header_read_in (struct comp_unit_head *cu_headerp, + struct dwarf2_per_cu_data *per_cu) +{ + struct objfile *objfile; + struct dwarf2_per_objfile *per_objfile; + gdb_byte *info_ptr; + + if (per_cu->cu) + return &per_cu->cu->header; + + objfile = per_cu->objfile; + per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + info_ptr = per_objfile->info.buffer + per_cu->offset; + + memset (cu_headerp, 0, sizeof (*cu_headerp)); + read_comp_unit_head (cu_headerp, info_ptr, objfile->obfd); + + return cu_headerp; +} + /* Return the address size given in the compilation unit header for CU. */ CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) { - if (per_cu->cu) - return per_cu->cu->header.addr_size; - else - { - /* If the CU is not currently read in, we re-read its header. */ - struct objfile *objfile = per_cu->objfile; - struct dwarf2_per_objfile *per_objfile - = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; - struct comp_unit_head cu_header; + struct comp_unit_head cu_header_local; + const struct comp_unit_head *cu_headerp; - memset (&cu_header, 0, sizeof cu_header); - read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); - return cu_header.addr_size; - } + cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu); + + return cu_headerp->addr_size; } /* Return the offset size given in the compilation unit header for CU. */ @@ -14844,21 +15866,28 @@ dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) { - if (per_cu->cu) - return per_cu->cu->header.offset_size; - else - { - /* If the CU is not currently read in, we re-read its header. */ - struct objfile *objfile = per_cu->objfile; - struct dwarf2_per_objfile *per_objfile - = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; - struct comp_unit_head cu_header; + struct comp_unit_head cu_header_local; + const struct comp_unit_head *cu_headerp; - memset (&cu_header, 0, sizeof cu_header); - read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); - return cu_header.offset_size; - } + cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu); + + return cu_headerp->offset_size; +} + +/* See its dwarf2loc.h declaration. */ + +int +dwarf2_per_cu_ref_addr_size (struct dwarf2_per_cu_data *per_cu) +{ + struct comp_unit_head cu_header_local; + const struct comp_unit_head *cu_headerp; + + cu_headerp = per_cu_header_read_in (&cu_header_local, per_cu); + + if (cu_headerp->version == 2) + return cu_headerp->addr_size; + else + return cu_headerp->offset_size; } /* Return the text offset of the CU. The returned offset comes from @@ -15183,7 +16212,7 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) && !HAVE_GNAT_AUX_INFO (type)) INIT_GNAT_SPECIFIC (type); - if (cu->per_cu->from_debug_types) + if (cu->per_cu->debug_types_section) type_hash_ptr = &dwarf2_per_objfile->debug_types_type_hash; else type_hash_ptr = &dwarf2_per_objfile->debug_info_type_hash; @@ -15223,7 +16252,7 @@ get_die_type_at_offset (unsigned int offset, struct dwarf2_offset_and_type *slot, ofs; htab_t type_hash; - if (per_cu->from_debug_types) + if (per_cu->debug_types_section) type_hash = dwarf2_per_objfile->debug_types_type_hash; else type_hash = dwarf2_per_objfile->debug_info_type_hash; @@ -15360,14 +16389,13 @@ show_dwarf2_cmd (char *args, int from_tty) static void munmap_section_buffer (struct dwarf2_section_info *info) { - if (info->was_mmapped) + if (info->map_addr != NULL) { #ifdef HAVE_MMAP - intptr_t begin = (intptr_t) info->buffer; - intptr_t map_begin = begin & ~(pagesize - 1); - size_t map_length = info->size + begin - map_begin; + int res; - gdb_assert (munmap ((void *) map_begin, map_length) == 0); + res = munmap (info->map_addr, info->map_len); + gdb_assert (res == 0); #else /* Without HAVE_MMAP, we should never be here to begin with. */ gdb_assert_not_reached ("no mmap support"); @@ -15381,6 +16409,8 @@ static void dwarf2_per_objfile_free (struct objfile *objfile, void *d) { struct dwarf2_per_objfile *data = d; + int ix; + struct dwarf2_section_info *section; /* This is sorted according to the order they're defined in to make it easier to keep in sync. */ @@ -15389,12 +16419,19 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d) munmap_section_buffer (&data->line); munmap_section_buffer (&data->loc); munmap_section_buffer (&data->macinfo); + munmap_section_buffer (&data->macro); munmap_section_buffer (&data->str); munmap_section_buffer (&data->ranges); - munmap_section_buffer (&data->types); munmap_section_buffer (&data->frame); munmap_section_buffer (&data->eh_frame); munmap_section_buffer (&data->gdb_index); + + for (ix = 0; + VEC_iterate (dwarf2_section_info_def, data->types, ix, section); + ++ix) + munmap_section_buffer (section); + + VEC_free (dwarf2_section_info_def, data->types); } @@ -15408,13 +16445,16 @@ struct strtab_entry const char *str; }; -/* Hash function for a strtab_entry. */ +/* Hash function for a strtab_entry. + + Function is used only during write_hash_table so no index format backward + compatibility is needed. */ static hashval_t hash_strtab_entry (const void *e) { const struct strtab_entry *entry = e; - return mapped_index_string_hash (entry->str); + return mapped_index_string_hash (INT_MAX, entry->str); } /* Equality function for a strtab_entry. */ @@ -15552,12 +16592,15 @@ cleanup_mapped_symtab (void *p) } /* Find a slot in SYMTAB for the symbol NAME. Returns a pointer to - the slot. */ + the slot. + + Function is used only during write_hash_table so no index format backward + compatibility is needed. */ static struct symtab_index_entry ** find_slot (struct mapped_symtab *symtab, const char *name) { - offset_type index, step, hash = mapped_index_string_hash (name); + offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name); index = hash & (symtab->size - 1); step = ((hash * 17) & (symtab->size - 1)) | 1; @@ -15618,7 +16661,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name, /* Don't push an index twice. Due to how we add entries we only have to check the last one. */ if (VEC_empty (offset_type, (*slot)->cu_indices) - || VEC_length (offset_type, (*slot)->cu_indices) != cu_index) + || VEC_last (offset_type, (*slot)->cu_indices) != cu_index) VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index); } @@ -15931,7 +16974,7 @@ write_one_signatured_type (void **slot, void *d) psymtab->n_static_syms, info->cu_index, 1); - store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->offset); + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->per_cu.offset); obstack_grow (info->types_list, val, 8); store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->type_offset); obstack_grow (info->types_list, val, 8); @@ -15943,14 +16986,6 @@ write_one_signatured_type (void **slot, void *d) return 1; } -/* A cleanup function for an htab_t. */ - -static void -cleanup_htab (void *arg) -{ - htab_delete (arg); -} - /* Create an index file for OBJFILE in the directory DIR. */ static void @@ -15970,11 +17005,15 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) htab_t cu_index_htab; struct psymtab_cu_index_map *psymtab_cu_index_map; - if (!objfile->psymtabs) + if (!objfile->psymtabs || !objfile->psymtabs_addrmap) return; + if (dwarf2_per_objfile->using_index) error (_("Cannot use an index to create the index")); + if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1) + error (_("Cannot make an index when the file has multiple .debug_types sections")); + if (stat (objfile->name, &st) < 0) perror_with_name (objfile->name); @@ -16003,7 +17042,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer, NULL, xcalloc, xfree); - make_cleanup (cleanup_htab, psyms_seen); + make_cleanup_htab_delete (psyms_seen); /* While we're scanning CU's create a table that maps a psymtab pointer (which is what addrmap records) to its index (which is what is recorded @@ -16013,7 +17052,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) hash_psymtab_cu_index, eq_psymtab_cu_index, NULL, xcalloc, xfree); - make_cleanup (cleanup_htab, cu_index_htab); + make_cleanup_htab_delete (cu_index_htab); psymtab_cu_index_map = (struct psymtab_cu_index_map *) xmalloc (sizeof (struct psymtab_cu_index_map) * dwarf2_per_objfile->n_comp_units); @@ -16085,7 +17124,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) total_len = size_of_contents; /* The version number. */ - val = MAYBE_SWAP (4); + val = MAYBE_SWAP (5); obstack_grow (&contents, &val, sizeof (val)); /* The offset of the CU list from the start of the file. */ @@ -16131,75 +17170,10 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) do_cleanups (cleanup); } -/* The mapped index file format is designed to be directly mmap()able - on any architecture. In most cases, a datum is represented using a - little-endian 32-bit integer value, called an offset_type. Big - endian machines must byte-swap the values before using them. - Exceptions to this rule are noted. The data is laid out such that - alignment is always respected. - - A mapped index consists of several sections. - - 1. The file header. This is a sequence of values, of offset_type - unless otherwise noted: - - [0] The version number, currently 4. Versions 1, 2 and 3 are - obsolete. - [1] The offset, from the start of the file, of the CU list. - [2] The offset, from the start of the file, of the types CU list. - Note that this section can be empty, in which case this offset will - be equal to the next offset. - [3] The offset, from the start of the file, of the address section. - [4] The offset, from the start of the file, of the symbol table. - [5] The offset, from the start of the file, of the constant pool. - - 2. The CU list. This is a sequence of pairs of 64-bit - little-endian values, sorted by the CU offset. The first element - in each pair is the offset of a CU in the .debug_info section. The - second element in each pair is the length of that CU. References - to a CU elsewhere in the map are done using a CU index, which is - just the 0-based index into this table. Note that if there are - type CUs, then conceptually CUs and type CUs form a single list for - the purposes of CU indices. - - 3. The types CU list. This is a sequence of triplets of 64-bit - little-endian values. In a triplet, the first value is the CU - offset, the second value is the type offset in the CU, and the - third value is the type signature. The types CU list is not - sorted. - - 4. The address section. The address section consists of a sequence - of address entries. Each address entry has three elements. - [0] The low address. This is a 64-bit little-endian value. - [1] The high address. This is a 64-bit little-endian value. - Like DW_AT_high_pc, the value is one byte beyond the end. - [2] The CU index. This is an offset_type value. - - 5. The symbol table. This is a hash table. The size of the hash - table is always a power of 2. The initial hash and the step are - currently defined by the `find_slot' function. - - Each slot in the hash table consists of a pair of offset_type - values. The first value is the offset of the symbol's name in the - constant pool. The second value is the offset of the CU vector in - the constant pool. - - If both values are 0, then this slot in the hash table is empty. - This is ok because while 0 is a valid constant pool index, it - cannot be a valid index for both a string and a CU vector. - - A string in the constant pool is stored as a \0-terminated string, - as you'd expect. - - A CU vector in the constant pool is a sequence of offset_type - values. The first value is the number of CU indices in the vector. - Each subsequent value is the index of a CU in the CU list. This - element in the hash table is used to indicate which CUs define the - symbol. - - 6. The constant pool. This is simply a bunch of bytes. It is - organized so that alignment is correct: CU vectors are stored - first, followed by strings. */ +/* Implementation of the `save gdb-index' command. + + Note that the file format used by this command is documented in the + GDB manual. Any changes here must be documented there. */ static void save_gdb_index_command (char *arg, int from_tty) diff --git a/contrib/gdb-7/gdb/elfread.c b/contrib/gdb-7/gdb/elfread.c index 226ce276fe..ca1c2a9d3e 100644 --- a/contrib/gdb-7/gdb/elfread.c +++ b/contrib/gdb-7/gdb/elfread.c @@ -1,8 +1,6 @@ /* Read ELF (Executable and Linking Format) object files for GDB. - Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1991-2012 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -206,18 +204,7 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, bfd_section, objfile); } -/* - - LOCAL FUNCTION - - elf_symtab_read -- read the symbol table of an ELF file - - SYNOPSIS - - void elf_symtab_read (struct objfile *objfile, int type, - long number_of_symbols, asymbol **symbol_table) - - DESCRIPTION +/* Read the symbol table of an ELF file. Given an objfile, a symbol table, and a flag indicating whether the symbol table contains regular, dynamic, or synthetic symbols, add all @@ -227,9 +214,7 @@ record_minimal_symbol (const char *name, int name_len, int copy_name, defined in the ELF symbol table, which can be used to locate the beginnings of sections from each ".o" file that was linked to form the executable objfile. We gather any such info and record it - in data structures hung off the objfile's private data. - - */ + in data structures hung off the objfile's private data. */ #define ST_REGULAR 0 #define ST_DYNAMIC 1 @@ -285,7 +270,7 @@ elf_symtab_read (struct objfile *objfile, int type, { struct minimal_symbol *msym; bfd *abfd = objfile->obfd; - asection *sect; + asection *sect; /* Symbol is a reference to a function defined in a shared library. @@ -375,7 +360,7 @@ elf_symtab_read (struct objfile *objfile, int type, NOTE: uweigand-20071112: Synthetic symbols do not have an ELF-private part, so do not touch those. */ - unsigned int shndx = type == ST_SYNTHETIC ? 0 : + unsigned int shndx = type == ST_SYNTHETIC ? 0 : ((elf_symbol_type *) sym)->internal_elf_sym.st_shndx; switch (shndx) @@ -411,7 +396,11 @@ elf_symtab_read (struct objfile *objfile, int type, else ms_type = mst_text; } - else if ((sym->name[0] == '.' && sym->name[1] == 'L') + /* The BSF_SYNTHETIC check is there to omit ppc64 function + descriptors mistaken for static functions starting with 'L'. + */ + else if ((sym->name[0] == '.' && sym->name[1] == 'L' + && (sym->flags & BSF_SYNTHETIC) == 0) || ((sym->flags & BSF_LOCAL) && sym->name[0] == '$' && sym->name[1] == 'L')) @@ -477,7 +466,7 @@ elf_symtab_read (struct objfile *objfile, int type, already includes one element, so we need to allocate max_index aadditional elements. */ - size = (sizeof (struct stab_section_info) + size = (sizeof (struct stab_section_info) + (sizeof (CORE_ADDR) * max_index)); sectinfo = (struct stab_section_info *) xmalloc (size); @@ -531,7 +520,7 @@ elf_symtab_read (struct objfile *objfile, int type, else { /* FIXME: Solaris2 shared libraries include lots of - odd "absolute" and "undefined" symbols, that play + odd "absolute" and "undefined" symbols, that play hob with actions like finding what function the PC is in. Ignore them if they aren't text, data, or bss. */ /* ms_type = mst_unknown; */ @@ -550,7 +539,7 @@ elf_symtab_read (struct objfile *objfile, int type, ELF-private part. However, in some cases (e.g. synthetic 'dot' symbols on ppc64) the udata.p entry is set to point back to the original ELF symbol it was derived from. Get the size - from that symbol. */ + from that symbol. */ if (type != ST_SYNTHETIC) elf_sym = (elf_symbol_type *) sym; else @@ -558,7 +547,7 @@ elf_symtab_read (struct objfile *objfile, int type, if (elf_sym) MSYMBOL_SIZE(msym) = elf_sym->internal_elf_sym.st_size; - + msym->filename = filesymname; gdbarch_elf_make_msymbol_special (gdbarch, sym, msym); } @@ -663,14 +652,14 @@ elf_rel_plt_read (struct objfile *objfile, asymbol **dyn_symbol_table) OBJFILE the symbol is undefined and the objfile having NAME defined may not yet have been loaded. */ - if (string_buffer_size < name_len + got_suffix_len) + if (string_buffer_size < name_len + got_suffix_len + 1) { string_buffer_size = 2 * (name_len + got_suffix_len); string_buffer = xrealloc (string_buffer, string_buffer_size); } memcpy (string_buffer, name, name_len); memcpy (&string_buffer[name_len], SYMBOL_GOT_PLT_SUFFIX, - got_suffix_len); + got_suffix_len + 1); msym = record_minimal_symbol (string_buffer, name_len + got_suffix_len, 1, address, mst_slot_got_plt, got_plt, @@ -899,7 +888,7 @@ elf_gnu_ifunc_resolve_name (const char *name, CORE_ADDR *addr_p) { if (elf_gnu_ifunc_resolve_by_cache (name, addr_p)) return 1; - + if (elf_gnu_ifunc_resolve_by_got (name, addr_p)) return 1; @@ -1041,7 +1030,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) } gdb_assert (b->type == bp_gnu_ifunc_resolver); - gdb_assert (current_program_space == b->pspace); + gdb_assert (current_program_space == b->pspace || b->pspace == NULL); elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc); sal = find_pc_line (resolved_pc, 0); @@ -1197,7 +1186,7 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) } /* Scan and build partial symbols for a symbol file. - We have been initialized by a call to elf_symfile_init, which + We have been initialized by a call to elf_symfile_init, which currently does nothing. SECTION_OFFSETS is a set of offsets to apply to relocate the symbols @@ -1227,7 +1216,7 @@ find_separate_debug_file_by_buildid (struct objfile *objfile) static void elf_symfile_read (struct objfile *objfile, int symfile_flags) { - bfd *abfd = objfile->obfd; + bfd *synth_abfd, *abfd = objfile->obfd; struct elfinfo ei; struct cleanup *back_to; long symcount = 0, dynsymcount = 0, synthcount, storage_needed; @@ -1298,9 +1287,26 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) elf_rel_plt_read (objfile, dyn_symbol_table); } + /* Contrary to binutils --strip-debug/--only-keep-debug the strip command from + elfutils (eu-strip) moves even the .symtab section into the .debug file. + + bfd_get_synthetic_symtab on ppc64 for each function descriptor ELF symbol + 'name' creates a new BSF_SYNTHETIC ELF symbol '.name' with its code + address. But with eu-strip files bfd_get_synthetic_symtab would fail to + read the code address from .opd while it reads the .symtab section from + a separate debug info file as the .opd section is SHT_NOBITS there. + + With SYNTH_ABFD the .opd section will be read from the original + backlinked binary where it is valid. */ + + if (objfile->separate_debug_objfile_backlink) + synth_abfd = objfile->separate_debug_objfile_backlink->obfd; + else + synth_abfd = abfd; + /* Add synthetic symbols - for instance, names for any PLT entries. */ - synthcount = bfd_get_synthetic_symtab (abfd, symcount, symbol_table, + synthcount = bfd_get_synthetic_symtab (synth_abfd, symcount, symbol_table, dynsymcount, dyn_symbol_table, &synthsyms); if (synthcount > 0) @@ -1370,7 +1376,7 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) bfd_section_size (abfd, str_sect)); } - if (dwarf2_has_info (objfile)) + if (dwarf2_has_info (objfile, NULL)) { /* elf_sym_fns_gdb_index cannot handle simultaneous non-DWARF debug information present in OBJFILE. If there is such debug info present @@ -1416,7 +1422,7 @@ elf_symfile_read (struct objfile *objfile, int symfile_flags) static void read_psyms (struct objfile *objfile) { - if (dwarf2_has_info (objfile)) + if (dwarf2_has_info (objfile, NULL)) dwarf2_build_psymtabs (objfile); } @@ -1541,7 +1547,7 @@ elfstab_offset_sections (struct objfile *objfile, struct partial_symtab *pst) /* Found it! Allocate a new psymtab struct, and fill it in. */ maybe->found++; pst->section_offsets = (struct section_offsets *) - obstack_alloc (&objfile->objfile_obstack, + obstack_alloc (&objfile->objfile_obstack, SIZEOF_N_SECTION_OFFSETS (objfile->num_sections)); for (i = 0; i < maybe->num_sections; i++) (pst->section_offsets)->offsets[i] = maybe->sections[i]; diff --git a/contrib/gdb-7/gdb/environ.c b/contrib/gdb-7/gdb/environ.c index 62d23e6d4f..33426eb90b 100644 --- a/contrib/gdb-7/gdb/environ.c +++ b/contrib/gdb-7/gdb/environ.c @@ -1,7 +1,7 @@ /* environ.c -- library for manipulating environments for GNU. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 2000, 2005 - 2003, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1995, 2000, 2003, 2005, 2007-2012 Free + Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/environ.h b/contrib/gdb-7/gdb/environ.h index 7a9347848c..52d51ef7c8 100644 --- a/contrib/gdb-7/gdb/environ.h +++ b/contrib/gdb-7/gdb/environ.h @@ -1,6 +1,6 @@ /* Header for environment manipulation library. - Copyright (C) 1989, 1992, 2000, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1989, 1992, 2000, 2005, 2007-2012 Free Software + Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/eval.c b/contrib/gdb-7/gdb/eval.c index bbc7b8a71f..d48b450e92 100644 --- a/contrib/gdb-7/gdb/eval.c +++ b/contrib/gdb-7/gdb/eval.c @@ -1,8 +1,6 @@ /* Evaluate expressions for GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2003, 2005-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -860,6 +858,27 @@ evaluate_subexp_standard (struct type *expect_type, return ret; } + case OP_VAR_ENTRY_VALUE: + (*pos) += 2; + if (noside == EVAL_SKIP) + goto nosideret; + + { + struct symbol *sym = exp->elts[pc + 1].symbol; + struct frame_info *frame; + + if (noside == EVAL_AVOID_SIDE_EFFECTS) + return value_zero (SYMBOL_TYPE (sym), not_lval); + + if (SYMBOL_CLASS (sym) != LOC_COMPUTED + || SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry == NULL) + error (_("Symbol \"%s\" does not have any specific entry value"), + SYMBOL_PRINT_NAME (sym)); + + frame = get_selected_frame (NULL); + return SYMBOL_COMPUTED_OPS (sym)->read_variable_at_entry (sym, frame); + } + case OP_LAST: (*pos) += 2; return @@ -1653,13 +1672,7 @@ evaluate_subexp_standard (struct type *expect_type, func_name = (char *) alloca (name_len + 1); strcpy (func_name, &exp->elts[string_pc + 1].string); - /* Prepare list of argument types for overload resolution. */ - arg_types = (struct type **) - alloca (nargs * (sizeof (struct type *))); - for (ix = 1; ix <= nargs; ix++) - arg_types[ix - 1] = value_type (argvec[ix]); - - find_overload_match (arg_types, nargs, func_name, + find_overload_match (&argvec[1], nargs, func_name, NON_METHOD, /* not method */ 0, /* strict match */ NULL, NULL, /* pass NULL symbol since @@ -1695,13 +1708,7 @@ evaluate_subexp_standard (struct type *expect_type, evaluation. */ struct value *valp = NULL; - /* Prepare list of argument types for overload resolution. */ - arg_types = (struct type **) - alloca (nargs * (sizeof (struct type *))); - for (ix = 1; ix <= nargs; ix++) - arg_types[ix - 1] = value_type (argvec[ix]); - - (void) find_overload_match (arg_types, nargs, tstr, + (void) find_overload_match (&argvec[1], nargs, tstr, METHOD, /* method */ 0, /* strict match */ &arg2, /* the object */ @@ -1772,13 +1779,7 @@ evaluate_subexp_standard (struct type *expect_type, if (op == OP_VAR_VALUE) function = exp->elts[save_pos1+2].symbol; - /* Prepare list of argument types for overload resolution. */ - arg_types = (struct type **) - alloca (nargs * (sizeof (struct type *))); - for (ix = 1; ix <= nargs; ix++) - arg_types[ix - 1] = value_type (argvec[ix]); - - (void) find_overload_match (arg_types, nargs, + (void) find_overload_match (&argvec[1], nargs, NULL, /* no need for name */ NON_METHOD, /* not method */ 0, /* strict match */ @@ -2198,7 +2199,7 @@ evaluate_subexp_standard (struct type *expect_type, { struct value *v_one, *retval; - v_one = value_one (value_type (arg2), not_lval); + v_one = value_one (value_type (arg2)); binop_promote (exp->language_defn, exp->gdbarch, &arg1, &v_one); retval = value_binop (arg1, v_one, op); return retval; @@ -2742,7 +2743,7 @@ evaluate_subexp_standard (struct type *expect_type, { struct value *tmp = arg1; - arg2 = value_one (value_type (arg1), not_lval); + arg2 = value_one (value_type (arg1)); binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); arg2 = value_binop (tmp, arg2, BINOP_ADD); } @@ -2766,7 +2767,7 @@ evaluate_subexp_standard (struct type *expect_type, { struct value *tmp = arg1; - arg2 = value_one (value_type (arg1), not_lval); + arg2 = value_one (value_type (arg1)); binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); arg2 = value_binop (tmp, arg2, BINOP_SUB); } @@ -2792,7 +2793,7 @@ evaluate_subexp_standard (struct type *expect_type, { struct value *tmp = arg1; - arg2 = value_one (value_type (arg1), not_lval); + arg2 = value_one (value_type (arg1)); binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); arg2 = value_binop (tmp, arg2, BINOP_ADD); } @@ -2819,7 +2820,7 @@ evaluate_subexp_standard (struct type *expect_type, { struct value *tmp = arg1; - arg2 = value_one (value_type (arg1), not_lval); + arg2 = value_one (value_type (arg1)); binop_promote (exp->language_defn, exp->gdbarch, &tmp, &arg2); arg2 = value_binop (tmp, arg2, BINOP_SUB); } @@ -2830,11 +2831,7 @@ evaluate_subexp_standard (struct type *expect_type, case OP_THIS: (*pos) += 1; - return value_of_this (1); - - case OP_OBJC_SELF: - (*pos) += 1; - return value_of_local ("self", 1); + return value_of_this (exp->language_defn); case OP_TYPE: /* The value is not supposed to be used. This is here to make it diff --git a/contrib/gdb-7/gdb/event-loop.c b/contrib/gdb-7/gdb/event-loop.c index 617835feb0..279335a192 100644 --- a/contrib/gdb-7/gdb/event-loop.c +++ b/contrib/gdb-7/gdb/event-loop.c @@ -1,6 +1,5 @@ /* Event loop machinery for GDB, the GNU debugger. - Copyright (C) 1999, 2000, 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1999-2002, 2005-2012 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. This file is part of GDB. @@ -410,11 +409,10 @@ process_event (void) /* Process one high level event. If nothing is ready at this time, wait for something to happen (via gdb_wait_for_event), then process it. Returns >0 if something was done otherwise returns <0 (this - can happen if there are no event sources to wait for). If an error - occurs catch_errors() which calls this function returns zero. */ + can happen if there are no event sources to wait for). */ int -gdb_do_one_event (void *data) +gdb_do_one_event (void) { static int event_source_head = 0; const int number_of_sources = 3; @@ -478,30 +476,30 @@ gdb_do_one_event (void *data) void start_event_loop (void) { - /* Loop until there is nothing to do. This is the entry point to the - event loop engine. gdb_do_one_event, called via catch_errors() - will process one event for each invocation. It blocks waits for - an event and then processes it. >0 when an event is processed, 0 - when catch_errors() caught an error and <0 when there are no - longer any event sources registered. */ + /* Loop until there is nothing to do. This is the entry point to + the event loop engine. gdb_do_one_event will process one event + for each invocation. It blocks waiting for an event and then + processes it. */ while (1) { - int gdb_result; + volatile struct gdb_exception ex; + int result = 0; - gdb_result = catch_errors (gdb_do_one_event, 0, "", RETURN_MASK_ALL); - if (gdb_result < 0) - break; - - /* If we long-jumped out of do_one_event, we probably - didn't get around to resetting the prompt, which leaves - readline in a messed-up state. Reset it here. */ - - if (gdb_result == 0) + TRY_CATCH (ex, RETURN_MASK_ALL) + { + result = gdb_do_one_event (); + } + if (ex.reason < 0) { + exception_print (gdb_stderr, ex); + /* If any exception escaped to here, we better enable stdin. Otherwise, any command that calls async_disable_stdin, and then throws, will leave stdin inoperable. */ async_enable_stdin (); + /* If we long-jumped out of do_one_event, we probably didn't + get around to resetting the prompt, which leaves readline + in a messed-up state. Reset it here. */ /* FIXME: this should really be a call to a hook that is interface specific, because interfaces can display the prompt in their own way. */ @@ -517,6 +515,8 @@ start_event_loop (void) /* Maybe better to set a flag to be checked somewhere as to whether display the prompt or not. */ } + if (result < 0) + break; } /* We are done with the event loop. There are no more event sources @@ -759,7 +759,6 @@ handle_file_event (event_data data) int mask; #ifdef HAVE_POLL int error_mask; - int error_mask_returned; #endif int event_file_desc = data.integer; @@ -783,22 +782,19 @@ handle_file_event (event_data data) if (use_poll) { #ifdef HAVE_POLL + /* POLLHUP means EOF, but can be combined with POLLIN to + signal more data to read. */ error_mask = POLLHUP | POLLERR | POLLNVAL; - mask = (file_ptr->ready_mask & file_ptr->mask) | - (file_ptr->ready_mask & error_mask); - error_mask_returned = mask & error_mask; + mask = file_ptr->ready_mask & (file_ptr->mask | error_mask); - if (error_mask_returned != 0) + if ((mask & (POLLERR | POLLNVAL)) != 0) { /* Work in progress. We may need to tell somebody what kind of error we had. */ - if (error_mask_returned & POLLHUP) - printf_unfiltered (_("Hangup detected on fd %d\n"), - file_ptr->fd); - if (error_mask_returned & POLLERR) + if (mask & POLLERR) printf_unfiltered (_("Error detected on fd %d\n"), file_ptr->fd); - if (error_mask_returned & POLLNVAL) + if (mask & POLLNVAL) printf_unfiltered (_("Invalid or non-`poll'able fd %d\n"), file_ptr->fd); file_ptr->error = 1; diff --git a/contrib/gdb-7/gdb/event-loop.h b/contrib/gdb-7/gdb/event-loop.h index 54d83c469e..fe5d241da5 100644 --- a/contrib/gdb-7/gdb/event-loop.h +++ b/contrib/gdb-7/gdb/event-loop.h @@ -1,6 +1,5 @@ /* Definitions used by the GDB event loop. - Copyright (C) 1999, 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2007-2012 Free Software Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. This file is part of GDB. @@ -91,7 +90,7 @@ queue_position; /* Exported functions from event-loop.c */ extern void start_event_loop (void); -extern int gdb_do_one_event (void *data); +extern int gdb_do_one_event (void); extern void delete_file_handler (int fd); extern void add_file_handler (int fd, handler_func *proc, gdb_client_data client_data); diff --git a/contrib/gdb-7/gdb/event-top.c b/contrib/gdb-7/gdb/event-top.c index 660f137b08..52e78523cf 100644 --- a/contrib/gdb-7/gdb/event-top.c +++ b/contrib/gdb-7/gdb/event-top.c @@ -1,7 +1,7 @@ /* Top level stuff for GDB, the GNU debugger. - Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1999-2002, 2004-2005, 2007-2012 Free Software + Foundation, Inc. Written by Elena Zannoni of Cygnus Solutions. @@ -33,7 +33,8 @@ #include "cli/cli-script.h" /* for reset_command_nest_depth */ #include "main.h" #include "gdbthread.h" - +#include "observer.h" +#include "continuations.h" #include "gdbcmd.h" /* for dont_repeat() */ /* readline include files. */ @@ -46,8 +47,8 @@ static void rl_callback_read_char_wrapper (gdb_client_data client_data); static void command_line_handler (char *rl); static void change_line_handler (void); -static void change_annotation_level (void); static void command_handler (char *command); +static char *top_level_prompt (void); /* Signal handlers. */ #ifdef SIGQUIT @@ -107,10 +108,6 @@ void (*call_readline) (gdb_client_data); loop as default engine, and event-top.c is merged into top.c. */ int async_command_editing_p; -/* This variable contains the new prompt that the user sets with the - set prompt command. */ -char *new_async_prompt; - /* This is the annotation suffix that will be used when the annotation_level is 2. */ char *async_annotation_suffix; @@ -123,11 +120,6 @@ int exec_done_display_p = 0; read commands from. */ int input_fd; -/* This is the prompt stack. Prompts will be pushed on the stack as - needed by the different 'kinds' of user inputs GDB is asking - for. See event-loop.h. */ -struct prompts the_prompts; - /* Signal handling variables. */ /* Each of these is a pointer to a function that the event loop will invoke if the corresponding signal has received. The real signal @@ -154,7 +146,7 @@ void *sigtstp_token; because each line of input is handled by a different call to command_line_handler, and normally there is no state retained between different calls. */ -int more_to_come = 0; +static int more_to_come = 0; struct readline_input_state { @@ -184,27 +176,7 @@ rl_callback_read_char_wrapper (gdb_client_data client_data) void cli_command_loop (void) { - /* If we are using readline, set things up and display the first - prompt, otherwise just print the prompt. */ - if (async_command_editing_p) - { - int length; - char *a_prompt; - char *gdb_prompt = get_prompt (); - - /* Tell readline what the prompt to display is and what function - it will need to call after a whole line is read. This also - displays the first prompt. */ - length = strlen (PREFIX (0)) - + strlen (gdb_prompt) + strlen (SUFFIX (0)) + 1; - a_prompt = (char *) alloca (length); - strcpy (a_prompt, PREFIX (0)); - strcat (a_prompt, gdb_prompt); - strcat (a_prompt, SUFFIX (0)); - rl_callback_handler_install (a_prompt, input_handler); - } - else - display_gdb_prompt (0); + display_gdb_prompt (0); /* Now it's time to start the event loop. */ start_event_loop (); @@ -243,22 +215,28 @@ change_line_handler (void) } } -/* Displays the prompt. The prompt that is displayed is the current - top of the prompt stack, if the argument NEW_PROMPT is - 0. Otherwise, it displays whatever NEW_PROMPT is. This is used - after each gdb command has completed, and in the following cases: +/* Displays the prompt. If the argument NEW_PROMPT is NULL, the + prompt that is displayed is the current top level prompt. + Otherwise, it displays whatever NEW_PROMPT is as a local/secondary + prompt. + + This is used after each gdb command has completed, and in the + following cases: + 1. When the user enters a command line which is ended by '\' - indicating that the command will continue on the next line. - In that case the prompt that is displayed is the empty string. + indicating that the command will continue on the next line. In + that case the prompt that is displayed is the empty string. + 2. When the user is entering 'commands' for a breakpoint, or actions for a tracepoint. In this case the prompt will be '>' - 3. Other???? - FIXME: 2. & 3. not implemented yet for async. */ + + 3. On prompting for pagination. */ + void display_gdb_prompt (char *new_prompt) { - int prompt_length = 0; - char *gdb_prompt = get_prompt (); + char *actual_gdb_prompt = NULL; + struct cleanup *old_chain; /* Reset the nesting depth used when trace-commands is set. */ reset_command_nest_depth (); @@ -268,48 +246,47 @@ display_gdb_prompt (char *new_prompt) if (!current_interp_display_prompt_p ()) return; - if (sync_execution && is_running (inferior_ptid)) - { - /* This is to trick readline into not trying to display the - prompt. Even though we display the prompt using this - function, readline still tries to do its own display if we - don't call rl_callback_handler_install and - rl_callback_handler_remove (which readline detects because a - global variable is not set). If readline did that, it could - mess up gdb signal handlers for SIGINT. Readline assumes - that between calls to rl_set_signals and rl_clear_signals gdb - doesn't do anything with the signal handlers. Well, that's - not the case, because when the target executes we change the - SIGINT signal handler. If we allowed readline to display the - prompt, the signal handler change would happen exactly - between the calls to the above two functions. - Calling rl_callback_handler_remove(), does the job. */ + old_chain = make_cleanup (free_current_contents, &actual_gdb_prompt); - rl_callback_handler_remove (); - return; - } - - if (!new_prompt) + /* Do not call the python hook on an explicit prompt change as + passed to this function, as this forms a secondary/local prompt, + IE, displayed but not set. */ + if (! new_prompt) { - /* Just use the top of the prompt stack. */ - prompt_length = strlen (PREFIX (0)) + - strlen (SUFFIX (0)) + - strlen (gdb_prompt) + 1; - - new_prompt = (char *) alloca (prompt_length); - - /* Prefix needs to have new line at end. */ - strcpy (new_prompt, PREFIX (0)); - strcat (new_prompt, gdb_prompt); - /* Suffix needs to have a new line at end and \032 \032 at - beginning. */ - strcat (new_prompt, SUFFIX (0)); + if (sync_execution) + { + /* This is to trick readline into not trying to display the + prompt. Even though we display the prompt using this + function, readline still tries to do its own display if + we don't call rl_callback_handler_install and + rl_callback_handler_remove (which readline detects + because a global variable is not set). If readline did + that, it could mess up gdb signal handlers for SIGINT. + Readline assumes that between calls to rl_set_signals and + rl_clear_signals gdb doesn't do anything with the signal + handlers. Well, that's not the case, because when the + target executes we change the SIGINT signal handler. If + we allowed readline to display the prompt, the signal + handler change would happen exactly between the calls to + the above two functions. Calling + rl_callback_handler_remove(), does the job. */ + + rl_callback_handler_remove (); + return; + } + else + { + /* Display the top level prompt. */ + actual_gdb_prompt = top_level_prompt (); + } } + else + actual_gdb_prompt = xstrdup (new_prompt); if (async_command_editing_p) { rl_callback_handler_remove (); - rl_callback_handler_install (new_prompt, input_handler); + rl_callback_handler_install (actual_gdb_prompt, input_handler); } /* new_prompt at this point can be the top of the stack or the one passed in. It can't be NULL. */ @@ -318,100 +295,64 @@ display_gdb_prompt (char *new_prompt) /* Don't use a _filtered function here. It causes the assumed character position to be off, since the newline we read from the user is not accounted for. */ - fputs_unfiltered (new_prompt, gdb_stdout); + fputs_unfiltered (actual_gdb_prompt, gdb_stdout); gdb_flush (gdb_stdout); } + + do_cleanups (old_chain); } -/* Used when the user requests a different annotation level, with - 'set annotate'. It pushes a new prompt (with prefix and suffix) on top - of the prompt stack, if the annotation level desired is 2, otherwise - it pops the top of the prompt stack when we want the annotation level - to be the normal ones (1 or 0). */ -static void -change_annotation_level (void) +/* Return the top level prompt, as specified by "set prompt", possibly + overriden by the python gdb.prompt_hook hook, and then composed + with the prompt prefix and suffix (annotations). The caller is + responsible for freeing the returned string. */ + +static char * +top_level_prompt (void) { - char *prefix, *suffix; + char *prefix; + char *prompt = NULL; + char *suffix; + char *composed_prompt; + size_t prompt_length; - if (!PREFIX (0) || !PROMPT (0) || !SUFFIX (0)) - { - /* The prompt stack has not been initialized to "", we are - using gdb w/o the --async switch. */ - warning (_("Command has same effect as set annotate")); - return; - } + /* Give observers a chance of changing the prompt. E.g., the python + `gdb.prompt_hook' is installed as an observer. */ + observer_notify_before_prompt (get_prompt ()); + + prompt = xstrdup (get_prompt ()); - if (annotation_level > 1) + if (annotation_level >= 2) { - if (!strcmp (PREFIX (0), "") && !strcmp (SUFFIX (0), "")) - { - /* Push a new prompt if the previous annotation_level was not >1. */ - prefix = (char *) alloca (strlen (async_annotation_suffix) + 10); - strcpy (prefix, "\n\032\032pre-"); - strcat (prefix, async_annotation_suffix); - strcat (prefix, "\n"); - - suffix = (char *) alloca (strlen (async_annotation_suffix) + 6); - strcpy (suffix, "\n\032\032"); - strcat (suffix, async_annotation_suffix); - strcat (suffix, "\n"); - - push_prompt (prefix, (char *) 0, suffix); - } + /* Prefix needs to have new line at end. */ + prefix = (char *) alloca (strlen (async_annotation_suffix) + 10); + strcpy (prefix, "\n\032\032pre-"); + strcat (prefix, async_annotation_suffix); + strcat (prefix, "\n"); + + /* Suffix needs to have a new line at end and \032 \032 at + beginning. */ + suffix = (char *) alloca (strlen (async_annotation_suffix) + 6); + strcpy (suffix, "\n\032\032"); + strcat (suffix, async_annotation_suffix); + strcat (suffix, "\n"); } else { - if (strcmp (PREFIX (0), "") && strcmp (SUFFIX (0), "")) - { - /* Pop the top of the stack, we are going back to annotation < 1. */ - pop_prompt (); - } + prefix = ""; + suffix = ""; } -} -/* Pushes a new prompt on the prompt stack. Each prompt has three - parts: prefix, prompt, suffix. Usually prefix and suffix are empty - strings, except when the annotation level is 2. Memory is allocated - within xstrdup for the new prompt. */ -void -push_prompt (char *prefix, char *prompt, char *suffix) -{ - the_prompts.top++; - PREFIX (0) = xstrdup (prefix); - - /* Note that this function is used by the set annotate 2 - command. This is why we take care of saving the old prompt - in case a new one is not specified. */ - if (prompt) - PROMPT (0) = xstrdup (prompt); - else - PROMPT (0) = xstrdup (PROMPT (-1)); + prompt_length = strlen (prefix) + strlen (prompt) + strlen (suffix); + composed_prompt = xmalloc (prompt_length + 1); - SUFFIX (0) = xstrdup (suffix); -} + strcpy (composed_prompt, prefix); + strcat (composed_prompt, prompt); + strcat (composed_prompt, suffix); -/* Pops the top of the prompt stack, and frees the memory allocated - for it. */ -void -pop_prompt (void) -{ - /* If we are not during a 'synchronous' execution command, in which - case, the top prompt would be empty. */ - if (strcmp (PROMPT (0), "")) - /* This is for the case in which the prompt is set while the - annotation level is 2. The top prompt will be changed, but when - we return to annotation level < 2, we want that new prompt to be - in effect, until the user does another 'set prompt'. */ - if (strcmp (PROMPT (0), PROMPT (-1))) - { - xfree (PROMPT (-1)); - PROMPT (-1) = xstrdup (PROMPT (0)); - } - - xfree (PREFIX (0)); - xfree (PROMPT (0)); - xfree (SUFFIX (0)); - the_prompts.top--; + xfree (prompt); + + return composed_prompt; } /* When there is an event ready on the stdin file desriptor, instead @@ -448,7 +389,6 @@ async_enable_stdin (void) sync_execution. Current target_terminal_ours() implementations check for sync_execution before switching the terminal. */ target_terminal_ours (); - pop_prompt (); sync_execution = 0; } } @@ -459,11 +399,7 @@ async_enable_stdin (void) void async_disable_stdin (void) { - if (!sync_execution) - { - sync_execution = 1; - push_prompt ("", "", ""); - } + sync_execution = 1; } @@ -520,8 +456,6 @@ command_line_handler (char *rl) static unsigned linelength = 0; char *p; char *p1; - extern char *line; - extern int linesize; char *nline; char got_eof = 0; @@ -548,7 +482,6 @@ command_line_handler (char *rl) p = readline_input_state.linebuffer_ptr; xfree (readline_input_state.linebuffer); more_to_come = 0; - pop_prompt (); } #ifdef STOP_SIGNAL @@ -601,8 +534,7 @@ command_line_handler (char *rl) input expected to complete the command. So, we need to print an empty prompt here. */ more_to_come = 1; - push_prompt ("", "", ""); - display_gdb_prompt (0); + display_gdb_prompt (""); return; } @@ -661,7 +593,7 @@ command_line_handler (char *rl) previous command, return the value in the global buffer. */ if (repeat && p == linebuffer && *p != '\\') { - command_handler (line); + command_handler (saved_command_line); display_gdb_prompt (0); return; } @@ -669,7 +601,7 @@ command_line_handler (char *rl) for (p1 = linebuffer; *p1 == ' ' || *p1 == '\t'; p1++); if (repeat && !*p1) { - command_handler (line); + command_handler (saved_command_line); display_gdb_prompt (0); return; } @@ -693,15 +625,15 @@ command_line_handler (char *rl) /* Save into global buffer if appropriate. */ if (repeat) { - if (linelength > linesize) + if (linelength > saved_command_line_size) { - line = xrealloc (line, linelength); - linesize = linelength; + saved_command_line = xrealloc (saved_command_line, linelength); + saved_command_line_size = linelength; } - strcpy (line, linebuffer); + strcpy (saved_command_line, linebuffer); if (!more_to_come) { - command_handler (line); + command_handler (saved_command_line); display_gdb_prompt (0); } return; @@ -938,9 +870,25 @@ handle_sighup (int sig) static void async_disconnect (gdb_client_data arg) { - catch_errors (quit_cover, NULL, - "Could not kill the program being debugged", - RETURN_MASK_ALL); + volatile struct gdb_exception exception; + + TRY_CATCH (exception, RETURN_MASK_ALL) + { + quit_cover (); + } + + if (exception.reason < 0) + { + fputs_filtered ("Could not kill the program being debugged", + gdb_stderr); + exception_print (gdb_stderr, exception); + } + + TRY_CATCH (exception, RETURN_MASK_ALL) + { + pop_all_targets (1); + } + signal (SIGHUP, SIG_DFL); /*FIXME: ??????????? */ raise (SIGHUP); } @@ -1023,21 +971,6 @@ set_async_editing_command (char *args, int from_tty, change_line_handler (); } -/* Called by do_setshow_command. */ -void -set_async_annotation_level (char *args, int from_tty, - struct cmd_list_element *c) -{ - change_annotation_level (); -} - -/* Called by do_setshow_command. */ -void -set_async_prompt (char *args, int from_tty, struct cmd_list_element *c) -{ - PROMPT (0) = xstrdup (new_async_prompt); -} - /* Set things up for readline to be invoked via the alternate interface, i.e. via a callback function (rl_callback_read_char), and hook up instream to the event loop. */ diff --git a/contrib/gdb-7/gdb/event-top.h b/contrib/gdb-7/gdb/event-top.h index 8550164423..76a790e613 100644 --- a/contrib/gdb-7/gdb/event-top.h +++ b/contrib/gdb-7/gdb/event-top.h @@ -1,7 +1,7 @@ /* Definitions used by event-top.c, for GDB, the GNU debugger. - Copyright (C) 1999, 2001, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999, 2001, 2003, 2007-2012 Free Software Foundation, + Inc. Written by Elena Zannoni of Cygnus Solutions. @@ -25,54 +25,6 @@ struct cmd_list_element; -/* Stack for prompts. Each prompt is composed as a prefix, a prompt - and a suffix. The prompt to be displayed at any given time is the - one on top of the stack. A stack is necessary because of cases in - which the execution of a gdb command requires further input from - the user, like for instance 'commands' for breakpoints and - 'actions' for tracepoints. In these cases, the prompt is '>' and - gdb should process input using the asynchronous readline interface - and the event loop. In order to achieve this, we need to save - somewhere the state of GDB, i.e. that it is processing user input - as part of a command and not as part of the top level command loop. - The prompt stack represents part of the saved state. Another part - would be the function that readline would invoke after a whole line - of input has ben entered. This second piece would be something - like, for instance, where to return within the code for the actions - commands after a line has been read. This latter portion has not - beeen implemented yet. The need for a 3-part prompt arises from - the annotation level. When this is set to 2, the prompt is - actually composed of a prefix, the prompt itself and a suffix. */ - -/* At any particular time there will be always at least one prompt on - the stack, the one being currently displayed by gdb. If gdb is - using annotation level equal 2, there will be 2 prompts on the - stack: the usual one, w/o prefix and suffix (at top - 1), and the - 'composite' one with prefix and suffix added (at top). At this - time, this is the only use of the prompt stack. Resetting annotate - to 0 or 1, pops the top of the stack, resetting its size to one - element. The MAXPROMPTS limit is safe, for now. Once other cases - are dealt with (like the different prompts used for 'commands' or - 'actions') this array implementation of the prompt stack may have - to change. */ - -#define MAXPROMPTS 10 -struct prompts - { - struct - { - char *prefix; - char *prompt; - char *suffix; - } - prompt_stack[MAXPROMPTS]; - int top; - }; - -#define PROMPT(X) the_prompts.prompt_stack[the_prompts.top + X].prompt -#define PREFIX(X) the_prompts.prompt_stack[the_prompts.top + X].prefix -#define SUFFIX(X) the_prompts.prompt_stack[the_prompts.top + X].suffix - /* Exported functions from event-top.c. FIXME: these should really go into top.h. */ @@ -82,10 +34,6 @@ void gdb_disable_readline (void); extern void async_init_signals (void); extern void set_async_editing_command (char *args, int from_tty, struct cmd_list_element *c); -extern void set_async_annotation_level (char *args, int from_tty, - struct cmd_list_element *c); -extern void set_async_prompt (char *args, int from_tty, - struct cmd_list_element *c); /* Signal to catch ^Z typed while reading a command: SIGTSTP or SIGCONT. */ #ifndef STOP_SIGNAL @@ -97,8 +45,6 @@ extern void handle_stop_sig (int sig); #endif extern void handle_sigint (int sig); extern void handle_sigterm (int sig); -extern void pop_prompt (void); -extern void push_prompt (char *prefix, char *prompt, char *suffix); extern void gdb_readline2 (void *client_data); extern void mark_async_signal_handler_wrapper (void *token); extern void async_request_quit (void *arg); @@ -112,7 +58,6 @@ extern void async_enable_stdin (void); extern int async_command_editing_p; extern int exec_done_display_p; extern char *async_annotation_suffix; -extern char *new_async_prompt; extern struct prompts the_prompts; extern void (*call_readline) (void *); extern void (*input_handler) (char *); diff --git a/contrib/gdb-7/gdb/exceptions.c b/contrib/gdb-7/gdb/exceptions.c index 099ef0d2b1..2ac1283b2f 100644 --- a/contrib/gdb-7/gdb/exceptions.c +++ b/contrib/gdb-7/gdb/exceptions.c @@ -1,8 +1,6 @@ /* Exception (throw catch) mechanism, for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -60,7 +58,6 @@ struct catcher volatile struct gdb_exception *exception; /* Saved/current state. */ int mask; - struct ui_out *saved_uiout; struct cleanup *saved_cleanup_chain; /* Back link. */ struct catcher *prev; @@ -70,8 +67,7 @@ struct catcher static struct catcher *current_catcher; EXCEPTIONS_SIGJMP_BUF * -exceptions_state_mc_init (struct ui_out *func_uiout, - volatile struct gdb_exception *exception, +exceptions_state_mc_init (volatile struct gdb_exception *exception, return_mask mask) { struct catcher *new_catcher = XZALLOC (struct catcher); @@ -84,10 +80,6 @@ exceptions_state_mc_init (struct ui_out *func_uiout, new_catcher->mask = mask; - /* Override the global ``struct ui_out'' builder. */ - new_catcher->saved_uiout = uiout; - uiout = func_uiout; - /* Prevent error/quit during FUNC from calling cleanups established prior to here. */ new_catcher->saved_cleanup_chain = save_cleanups (); @@ -112,8 +104,6 @@ catcher_pop (void) restore_cleanups (old_catcher->saved_cleanup_chain); - uiout = old_catcher->saved_uiout; - xfree (old_catcher); } @@ -215,23 +205,9 @@ exceptions_state_mc_action_iter_1 (void) void throw_exception (struct gdb_exception exception) { - struct thread_info *tp = NULL; - quit_flag = 0; immediate_quit = 0; - if (!ptid_equal (inferior_ptid, null_ptid)) - tp = find_thread_ptid (inferior_ptid); - - /* Perhaps it would be cleaner to do this via the cleanup chain (not sure - I can think of a reason why that is vital, though). */ - if (tp != NULL) - { - /* Clear queued breakpoint commands. */ - bpstat_clear_actions (tp->control.stop_bpstat); - } - - disable_current_display (); do_cleanups (ALL_CLEANUPS); /* Jump to the containing catch_errors() call, communicating REASON @@ -442,7 +418,7 @@ throw_error (enum errors error, const char *fmt, ...) be replaced by judicious use of QUIT. */ /* MAYBE: cagney/1999-11-05: catch_errors() in conjunction with - error() et al. could maintain a set of flags that indicate the the + error() et al. could maintain a set of flags that indicate the current state of each of the longjmp buffers. This would give the longjmp code the chance to detect a longjmp botch (before it gets to longjmperror()). Prior to 1999-11-05 this wasn't possible as @@ -458,23 +434,8 @@ catch_exceptions (struct ui_out *uiout, return catch_exceptions_with_msg (uiout, func, func_args, NULL, mask); } -struct gdb_exception -catch_exception (struct ui_out *uiout, - catch_exception_ftype *func, - void *func_args, - return_mask mask) -{ - volatile struct gdb_exception exception; - - TRY_CATCH (exception, mask) - { - (*func) (uiout, func_args); - } - return exception; -} - int -catch_exceptions_with_msg (struct ui_out *uiout, +catch_exceptions_with_msg (struct ui_out *func_uiout, catch_exceptions_ftype *func, void *func_args, char **gdberrmsg, @@ -482,11 +443,27 @@ catch_exceptions_with_msg (struct ui_out *uiout, { volatile struct gdb_exception exception; volatile int val = 0; + struct ui_out *saved_uiout; + + /* Save and override the global ``struct ui_out'' builder. */ + saved_uiout = current_uiout; + current_uiout = func_uiout; - TRY_CATCH (exception, mask) + TRY_CATCH (exception, RETURN_MASK_ALL) { - val = (*func) (uiout, func_args); + val = (*func) (current_uiout, func_args); } + + /* Restore the global builder. */ + current_uiout = saved_uiout; + + if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0) + { + /* The caller didn't request that the event be caught. + Rethrow. */ + throw_exception (exception); + } + print_any_exception (gdb_stderr, NULL, exception); gdb_assert (val >= 0); gdb_assert (exception.reason <= 0); @@ -515,11 +492,26 @@ catch_errors (catch_errors_ftype *func, void *func_args, char *errstring, { volatile int val = 0; volatile struct gdb_exception exception; + struct ui_out *saved_uiout; + + /* Save the global ``struct ui_out'' builder. */ + saved_uiout = current_uiout; - TRY_CATCH (exception, mask) + TRY_CATCH (exception, RETURN_MASK_ALL) { val = func (func_args); } + + /* Restore the global builder. */ + current_uiout = saved_uiout; + + if (exception.reason < 0 && (mask & RETURN_MASK (exception.reason)) == 0) + { + /* The caller didn't request that the event be caught. + Rethrow. */ + throw_exception (exception); + } + print_any_exception (gdb_stderr, errstring, exception); if (exception.reason != 0) return 0; diff --git a/contrib/gdb-7/gdb/exceptions.h b/contrib/gdb-7/gdb/exceptions.h index b1c45878c1..0c59a25f1f 100644 --- a/contrib/gdb-7/gdb/exceptions.h +++ b/contrib/gdb-7/gdb/exceptions.h @@ -1,8 +1,6 @@ /* Exception (throw catch) mechanism, for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -85,6 +83,9 @@ enum errors { traceframe. */ NOT_AVAILABLE_ERROR, + /* DW_OP_GNU_entry_value resolving failed. */ + NO_ENTRY_VALUE_ERROR, + /* Add more errors here. */ NR_ERRORS }; @@ -114,8 +115,7 @@ extern const struct gdb_exception exception_none; /* Functions to drive the exceptions state m/c (internal to exceptions). */ -EXCEPTIONS_SIGJMP_BUF *exceptions_state_mc_init (struct ui_out *func_uiout, - volatile struct +EXCEPTIONS_SIGJMP_BUF *exceptions_state_mc_init (volatile struct gdb_exception *exception, return_mask mask); int exceptions_state_mc_action_iter (void); @@ -146,7 +146,7 @@ int exceptions_state_mc_action_iter_1 (void); #define TRY_CATCH(EXCEPTION,MASK) \ { \ EXCEPTIONS_SIGJMP_BUF *buf = \ - exceptions_state_mc_init (uiout, &(EXCEPTION), (MASK)); \ + exceptions_state_mc_init (&(EXCEPTION), (MASK)); \ EXCEPTIONS_SIGSETJMP (*buf); \ } \ while (exceptions_state_mc_action_iter ()) \ @@ -182,8 +182,8 @@ extern void throw_vfatal (const char *fmt, va_list ap) extern void throw_error (enum errors error, const char *fmt, ...) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3); -/* Instead of deprecated_throw_reason, code should use catch_exception - and throw_exception. */ +/* Instead of deprecated_throw_reason, code should use + throw_exception. */ extern void deprecated_throw_reason (enum return_reason reason) ATTRIBUTE_NORETURN; @@ -234,14 +234,6 @@ extern int catch_exceptions_with_msg (struct ui_out *uiout, char **gdberrmsg, return_mask mask); -/* This function, in addition, suppresses the printing of the captured - error message. It's up to the client to print it. */ - -extern struct gdb_exception catch_exception (struct ui_out *uiout, - catch_exception_ftype *func, - void *func_args, - return_mask mask); - /* If CATCH_ERRORS_FTYPE throws an error, catch_errors() returns zero otherwize the result from CATCH_ERRORS_FTYPE is returned. It is probably useful for CATCH_ERRORS_FTYPE to always return a non-zero diff --git a/contrib/gdb-7/gdb/exec.c b/contrib/gdb-7/gdb/exec.c index a2da9d5297..cd129f7cbc 100644 --- a/contrib/gdb-7/gdb/exec.c +++ b/contrib/gdb-7/gdb/exec.c @@ -1,8 +1,6 @@ /* Work with executable files, for GDB. - Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1988-2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/exec.h b/contrib/gdb-7/gdb/exec.h index 89fd1565f7..a0f9eaba6d 100644 --- a/contrib/gdb-7/gdb/exec.h +++ b/contrib/gdb-7/gdb/exec.h @@ -1,7 +1,6 @@ /* Work with executable files, for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/expprint.c b/contrib/gdb-7/gdb/expprint.c index a52dee3a91..d9d9b8fc87 100644 --- a/contrib/gdb-7/gdb/expprint.c +++ b/contrib/gdb-7/gdb/expprint.c @@ -1,8 +1,7 @@ /* Print in infix form a struct expression. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-2000, 2003, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -135,6 +134,16 @@ print_subexp_standard (struct expression *exp, int *pos, } return; + case OP_VAR_ENTRY_VALUE: + { + struct block *b; + + (*pos) += 2; + fprintf_filtered (stream, "%s@entry", + SYMBOL_PRINT_NAME (exp->elts[pc + 1].symbol)); + } + return; + case OP_LAST: (*pos) += 2; fprintf_filtered (stream, "$%d", @@ -499,14 +508,11 @@ print_subexp_standard (struct expression *exp, int *pos, case OP_THIS: ++(*pos); - fputs_filtered ("this", stream); - return; - - /* Objective-C ops */ - - case OP_OBJC_SELF: - ++(*pos); - fputs_filtered ("self", stream); /* The ObjC equivalent of "this". */ + if (exp->language_defn->la_name_of_this) + fputs_filtered (exp->language_defn->la_name_of_this, stream); + else + fprintf_filtered (stream, _(""), + exp->language_defn->la_name); return; /* Modula-2 ops */ @@ -856,6 +862,13 @@ dump_subexp_body_standard (struct expression *exp, SYMBOL_PRINT_NAME (exp->elts[elt + 1].symbol)); elt += 3; break; + case OP_VAR_ENTRY_VALUE: + fprintf_filtered (stream, "Entry value of symbol @"); + gdb_print_host_address (exp->elts[elt].symbol, stream); + fprintf_filtered (stream, " (%s)", + SYMBOL_PRINT_NAME (exp->elts[elt].symbol)); + elt += 2; + break; case OP_LAST: fprintf_filtered (stream, "History element %ld", (long) exp->elts[elt].longconst); diff --git a/contrib/gdb-7/gdb/expression.h b/contrib/gdb-7/gdb/expression.h index 45f336e2b2..be26002998 100644 --- a/contrib/gdb-7/gdb/expression.h +++ b/contrib/gdb-7/gdb/expression.h @@ -1,7 +1,7 @@ /* Definitions for expressions stored in reversed prefix form, for GDB. - Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2007-2012 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/f-exp.y b/contrib/gdb-7/gdb/f-exp.y index d9cf3cfcb9..fa464cf7ed 100644 --- a/contrib/gdb-7/gdb/f-exp.y +++ b/contrib/gdb-7/gdb/f-exp.y @@ -1,7 +1,6 @@ /* YACC parser for Fortran expressions, for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 1995, 1996, 2000, 2001, - 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1991, 1993-1996, 2000-2012 Free Software + Foundation, Inc. Contributed by Motorola. Adapted from the C parser by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -765,7 +764,7 @@ parse_number (p, len, parsed_float, putithere) /* If the number is too big to be an int, or it's got an l suffix then it's a long. Work out if this has to be a long by - shifting right and and seeing if anything remains, and the + shifting right and seeing if anything remains, and the target int size is different to the target long size. In the expression below, we could have tested diff --git a/contrib/gdb-7/gdb/f-lang.c b/contrib/gdb-7/gdb/f-lang.c index 61513c121e..4149cefc09 100644 --- a/contrib/gdb-7/gdb/f-lang.c +++ b/contrib/gdb-7/gdb/f-lang.c @@ -1,7 +1,7 @@ /* Fortran language support routines for GDB, the GNU debugger. - Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, - 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1993-1996, 1998-2005, 2007-2012 Free Software + Foundation, Inc. Contributed by Motorola. Adapted from the C parser by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -32,6 +32,7 @@ #include "valprint.h" #include "value.h" #include "cp-support.h" +#include "charset.h" /* Following is dubious stuff that had been in the xcoff reader. */ @@ -76,6 +77,33 @@ static void f_printchar (int c, struct type *type, struct ui_file * stream); static void f_emit_char (int c, struct type *type, struct ui_file * stream, int quoter); +/* Return the encoding that should be used for the character type + TYPE. */ + +static const char * +f_get_encoding (struct type *type) +{ + const char *encoding; + + switch (TYPE_LENGTH (type)) + { + case 1: + encoding = target_charset (get_type_arch (type)); + break; + case 4: + if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_BIG) + encoding = "UTF-32BE"; + else + encoding = "UTF-32LE"; + break; + + default: + error (_("unrecognized character type")); + } + + return encoding; +} + /* Print the character C on STREAM as part of the contents of a literal string whose delimiter is QUOTER. Note that that format for printing characters and strings is language specific. @@ -85,48 +113,12 @@ static void f_emit_char (int c, struct type *type, static void f_emit_char (int c, struct type *type, struct ui_file *stream, int quoter) { - c &= 0xFF; /* Avoid sign bit follies. */ + const char *encoding = f_get_encoding (type); - if (PRINT_LITERAL_FORM (c)) - { - if (c == '\\' || c == quoter) - fputs_filtered ("\\", stream); - fprintf_filtered (stream, "%c", c); - } - else - { - switch (c) - { - case '\n': - fputs_filtered ("\\n", stream); - break; - case '\b': - fputs_filtered ("\\b", stream); - break; - case '\t': - fputs_filtered ("\\t", stream); - break; - case '\f': - fputs_filtered ("\\f", stream); - break; - case '\r': - fputs_filtered ("\\r", stream); - break; - case '\033': - fputs_filtered ("\\e", stream); - break; - case '\007': - fputs_filtered ("\\a", stream); - break; - default: - fprintf_filtered (stream, "\\%.3o", (unsigned int) c); - break; - } - } + generic_emit_char (c, type, stream, quoter, encoding); } -/* FIXME: This is a copy of the same function from c-exp.y. It should - be replaced with a true F77version. */ +/* Implementation of la_printchar. */ static void f_printchar (int c, struct type *type, struct ui_file *stream) @@ -148,83 +140,16 @@ f_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, unsigned int length, const char *encoding, int force_ellipses, const struct value_print_options *options) { - unsigned int i; - unsigned int things_printed = 0; - int in_quotes = 0; - int need_comma = 0; - - if (length == 0) - { - fputs_filtered ("''", gdb_stdout); - return; - } - - for (i = 0; i < length && things_printed < options->print_max; ++i) - { - /* Position of the character we are examining - to see whether it is repeated. */ - unsigned int rep1; - /* Number of repetitions we have detected so far. */ - unsigned int reps; - - QUIT; - - if (need_comma) - { - fputs_filtered (", ", stream); - need_comma = 0; - } + const char *type_encoding = f_get_encoding (type); - rep1 = i + 1; - reps = 1; - while (rep1 < length && string[rep1] == string[i]) - { - ++rep1; - ++reps; - } + if (TYPE_LENGTH (type) == 4) + fputs_filtered ("4_", stream); - if (reps > options->repeat_count_threshold) - { - if (in_quotes) - { - if (options->inspect_it) - fputs_filtered ("\\', ", stream); - else - fputs_filtered ("', ", stream); - in_quotes = 0; - } - f_printchar (string[i], type, stream); - fprintf_filtered (stream, " ", reps); - i = rep1 - 1; - things_printed += options->repeat_count_threshold; - need_comma = 1; - } - else - { - if (!in_quotes) - { - if (options->inspect_it) - fputs_filtered ("\\'", stream); - else - fputs_filtered ("'", stream); - in_quotes = 1; - } - LA_EMIT_CHAR (string[i], type, stream, '"'); - ++things_printed; - } - } - - /* Terminate the quotes if necessary. */ - if (in_quotes) - { - if (options->inspect_it) - fputs_filtered ("\\'", stream); - else - fputs_filtered ("'", stream); - } + if (!encoding || !*encoding) + encoding = type_encoding; - if (force_ellipses || i < length) - fputs_filtered ("...", stream); + generic_printstr (stream, type, string, length, encoding, + force_ellipses, '\'', 0, options); } @@ -384,6 +309,8 @@ const struct language_defn f_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; diff --git a/contrib/gdb-7/gdb/f-lang.h b/contrib/gdb-7/gdb/f-lang.h index 8043577cf4..3a46ebf67a 100644 --- a/contrib/gdb-7/gdb/f-lang.h +++ b/contrib/gdb-7/gdb/f-lang.h @@ -1,7 +1,7 @@ /* Fortran language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 1993, 1994, 1995, 1998, 2000, 2005, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1995, 1998, 2000, 2005, 2007-2012 Free Software + Foundation, Inc. Contributed by Motorola. Adapted from the C definitions by Farooq Butt (fmbutt@engage.sps.mot.com). diff --git a/contrib/gdb-7/gdb/f-typeprint.c b/contrib/gdb-7/gdb/f-typeprint.c index ad988d23dd..a95ef8449c 100644 --- a/contrib/gdb-7/gdb/f-typeprint.c +++ b/contrib/gdb-7/gdb/f-typeprint.c @@ -1,8 +1,7 @@ /* Support for printing Fortran types for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1993, 1994, 1995, 1996, 1998, 2000, - 2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991, 1993-1996, 1998, 2000-2003, + 2006-2012 Free Software Foundation, Inc. Contributed by Motorola. Adapted from the C version by Farooq Butt (fmbutt@engage.sps.mot.com). @@ -321,10 +320,6 @@ f_type_print_base (struct type *type, struct ui_file *stream, int show, break; case TYPE_CODE_CHAR: - /* Override name "char" and make it "character". */ - fprintfi_filtered (level, stream, "character"); - break; - case TYPE_CODE_INT: /* There may be some character types that attempt to come through as TYPE_CODE_INT since dbxstclass.h is so diff --git a/contrib/gdb-7/gdb/f-valprint.c b/contrib/gdb-7/gdb/f-valprint.c index 3280ddcb5d..87b2ed1a1a 100644 --- a/contrib/gdb-7/gdb/f-valprint.c +++ b/contrib/gdb-7/gdb/f-valprint.c @@ -1,7 +1,7 @@ /* Support for printing Fortran values for GDB, the GNU debugger. - Copyright (C) 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2003, 2005, 2006, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1993-1996, 1998-2000, 2003, 2005-2012 Free Software + Foundation, Inc. Contributed by Motorola. Adapted from the C definitions by Farooq Butt (fmbutt@engage.sps.mot.com), additionally worked over by Stan Shebs. @@ -271,10 +271,23 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, break; case TYPE_CODE_ARRAY: - fprintf_filtered (stream, "("); - f77_print_array (type, valaddr, embedded_offset, - address, stream, recurse, original_value, options); - fprintf_filtered (stream, ")"); + if (TYPE_CODE (TYPE_TARGET_TYPE (type)) != TYPE_CODE_CHAR) + { + fprintf_filtered (stream, "("); + f77_print_array (type, valaddr, embedded_offset, + address, stream, recurse, original_value, options); + fprintf_filtered (stream, ")"); + } + else + { + struct type *ch_type = TYPE_TARGET_TYPE (type); + + f77_get_dynamic_length_of_aggregate (type); + LA_PRINT_STRING (stream, ch_type, + valaddr + embedded_offset, + TYPE_LENGTH (type) / TYPE_LENGTH (ch_type), + NULL, 0, options); + } break; case TYPE_CODE_PTR: @@ -333,10 +346,19 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF) { - struct value *deref_val = - value_at - (TYPE_TARGET_TYPE (type), - unpack_pointer (type, valaddr + embedded_offset)); + struct value *deref_val; + + deref_val = coerce_ref_if_computed (original_value); + if (deref_val != NULL) + { + /* More complicated computed references are not supported. */ + gdb_assert (embedded_offset == 0); + } + else + deref_val = value_at (TYPE_TARGET_TYPE (type), + unpack_pointer (type, + (valaddr + + embedded_offset))); common_val_print (deref_val, stream, recurse, options, current_language); @@ -363,6 +385,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, break; case TYPE_CODE_INT: + case TYPE_CODE_CHAR: if (options->format || options->output_format) { struct value_print_options opts = *options; @@ -379,7 +402,7 @@ f_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, Since we don't know whether the value is really intended to be used as an integer or a character, print the character equivalent as well. */ - if (TYPE_LENGTH (type) == 1) + if (TYPE_LENGTH (type) == 1 || TYPE_CODE (type) == TYPE_CODE_CHAR) { LONGEST c; diff --git a/contrib/gdb-7/gdb/fbsd-nat.c b/contrib/gdb-7/gdb/fbsd-nat.c index 406ac37233..6a69b39750 100644 --- a/contrib/gdb-7/gdb/fbsd-nat.c +++ b/contrib/gdb-7/gdb/fbsd-nat.c @@ -1,7 +1,6 @@ /* Native-dependent code for FreeBSD. - Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/fbsd-nat.h b/contrib/gdb-7/gdb/fbsd-nat.h index c232a4fa2d..94d35156f9 100644 --- a/contrib/gdb-7/gdb/fbsd-nat.h +++ b/contrib/gdb-7/gdb/fbsd-nat.h @@ -1,7 +1,6 @@ /* Native-dependent code for FreeBSD. - Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/features/feature_to_c.sh b/contrib/gdb-7/gdb/features/feature_to_c.sh index dd9f225ab9..e9d65df6a2 100644 --- a/contrib/gdb-7/gdb/features/feature_to_c.sh +++ b/contrib/gdb-7/gdb/features/feature_to_c.sh @@ -2,7 +2,7 @@ # Convert text files to compilable C arrays. # -# Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2007-2012 Free Software Foundation, Inc. # # This file is part of GDB. # diff --git a/contrib/gdb-7/gdb/features/gdb-target.dtd b/contrib/gdb-7/gdb/features/gdb-target.dtd index fd7dac33fa..e9fb3352d5 100644 --- a/contrib/gdb-7/gdb/features/gdb-target.dtd +++ b/contrib/gdb-7/gdb/features/gdb-target.dtd @@ -1,4 +1,4 @@ - + + + + + + + + + + + diff --git a/contrib/gdb-7/gdb/features/library-list.dtd b/contrib/gdb-7/gdb/features/library-list.dtd index 8c4edc21c8..0095105e92 100644 --- a/contrib/gdb-7/gdb/features/library-list.dtd +++ b/contrib/gdb-7/gdb/features/library-list.dtd @@ -1,4 +1,4 @@ - jump to normal symbol processing. */ - if (sym) - return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL); + volatile struct gdb_exception exc; + + /* Avoid "may be used uninitialized" warning. */ + values.sals = NULL; + values.nelts = 0; - /* If symbol was not found, look in minimal symbol tables. */ - msymbol = lookup_minimal_symbol (copy, NULL, NULL); - /* Min symbol was found --> jump to minsym processing. */ - if (msymbol) - return minsym_found (funfirstline, msymbol); + TRY_CATCH (exc, RETURN_MASK_ERROR) + { + values = decode_variable (self, copy); + } + + if (exc.reason == 0) + return values; + + if (exc.error != NOT_FOUND_ERROR) + throw_exception (exc); /* Not a user variable or function -- must be convenience variable. */ if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx)) @@ -2022,18 +2512,37 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, init_sal (&val); - /* Either history value or convenience value from above, in valx. */ - val.symtab = file_symtab ? file_symtab : default_symtab; - val.line = valx; - val.pc = 0; - val.pspace = current_program_space; + values.sals = NULL; + values.nelts = 0; - values.sals = (struct symtab_and_line *) xmalloc (sizeof val); - values.sals[0] = val; - values.nelts = 1; + for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix) + { + if (elt == NULL) + { + elt = self->default_symtab; + set_current_program_space (self->program_space); + } + else + set_current_program_space (SYMTAB_PSPACE (elt)); + + /* Either history value or convenience value from above, in valx. */ + val.symtab = elt; + val.line = valx; + val.pc = 0; + val.pspace = elt ? SYMTAB_PSPACE (elt) : current_program_space; - if (need_canonical) - build_canonical_line_spec (values.sals, NULL, canonical); + add_sal_to_sals (self, &values, &val, NULL); + } + + if (self->canonical) + { + self->canonical->pre_expanded = 1; + if (self->user_filename) + self->canonical->addr_string = xstrprintf ("%s:%s", + self->user_filename, copy); + else + self->canonical->addr_string = xstrdup (copy); + } return values; } @@ -2042,7 +2551,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, /* A helper for decode_line_1 that tries to find a label. The label is searched for in the current block. - FUNCTION_SYMBOL is the enclosing function; or NULL if none + FUNCTION_SYMBOLS is a list of the enclosing functions; or NULL if none specified. COPY is the name of the label to find. CANONICAL is the same as the "canonical" argument to decode_line_1. @@ -2051,63 +2560,408 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab, This function returns 1 if a label was found, 0 otherwise. */ static int -decode_label (struct symbol *function_symbol, char *copy, - struct linespec_result *canonical, +decode_label (struct linespec_state *self, + VEC (symbolp) *function_symbols, char *copy, struct symtabs_and_lines *result) { - struct symbol *sym; - struct block *block; + struct symbol *fn_sym; + int ix; - if (function_symbol) - block = SYMBOL_BLOCK_VALUE (function_symbol); - else + if (function_symbols == NULL) { - block = get_selected_block (0); + struct block *block; + struct symbol *sym; + struct symtab_and_line sal; + struct symtabs_and_lines values; + + values.nelts = 0; + values.sals = NULL; + + set_current_program_space (self->program_space); + block = get_search_block (NULL); + for (; block && !BLOCK_FUNCTION (block); block = BLOCK_SUPERBLOCK (block)) ; if (!block) return 0; - function_symbol = BLOCK_FUNCTION (block); + fn_sym = BLOCK_FUNCTION (block); + + sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0); + + if (sym == NULL) + return 0; + + symbol_to_sal (&sal, self->funfirstline, sym); + add_sal_to_sals (self, &values, &sal, + SYMBOL_NATURAL_NAME (fn_sym)); + + if (self->canonical) + { + self->canonical->special_display = 1; + self->canonical->addr_string + = xstrprintf ("%s:%s", SYMBOL_NATURAL_NAME (fn_sym), + copy); + } + + *result = values; + + return 1; + } + + result->sals = NULL; + result->nelts = 0; + + for (ix = 0; VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix) + { + struct block *block; + struct symbol *sym; + + set_current_program_space (SYMTAB_PSPACE (SYMBOL_SYMTAB (fn_sym))); + block = SYMBOL_BLOCK_VALUE (fn_sym); + sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0); + + if (sym != NULL) + { + struct symtab_and_line sal; + char *symname; + + symbol_to_sal (&sal, self->funfirstline, sym); + symname = xstrprintf ("%s:%s", + SYMBOL_NATURAL_NAME (fn_sym), + SYMBOL_NATURAL_NAME (sym)); + add_sal_to_sals (self, result, &sal, symname); + xfree (symname); + } + } + + if (self->canonical && result->nelts > 0) + { + self->canonical->pre_expanded = 1; + self->canonical->special_display = 1; + + gdb_assert (self->user_function); + self->canonical->addr_string + = xstrprintf ("%s:%s", self->user_function, copy); } - sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0); + return result->nelts > 0; +} + +/* A callback used to possibly add a symbol to the results. */ + +static int +collect_symbols (struct symbol *sym, void *data) +{ + struct collect_info *info = data; + struct symtab_and_line sal; + + if (symbol_to_sal (&sal, info->state->funfirstline, sym) + && maybe_add_address (info->state->addr_set, + SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)), + sal.pc)) + add_sal_to_sals (info->state, &info->result, &sal, + SYMBOL_NATURAL_NAME (sym)); + + return 1; +} + +/* We've found a minimal symbol MSYMBOL to associate with our + linespec; add it to the result symtabs_and_lines. */ + +static void +minsym_found (struct linespec_state *self, struct objfile *objfile, + struct minimal_symbol *msymbol, + struct symtabs_and_lines *result) +{ + struct gdbarch *gdbarch = get_objfile_arch (objfile); + CORE_ADDR pc; + struct symtab_and_line sal; + + sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol), + (struct obj_section *) 0, 0); + sal.section = SYMBOL_OBJ_SECTION (msymbol); + + /* The minimal symbol might point to a function descriptor; + resolve it to the actual code address instead. */ + pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, ¤t_target); + if (pc != sal.pc) + sal = find_pc_sect_line (pc, NULL, 0); - if (sym != NULL) - *result = symbol_found (0, canonical, copy, sym, NULL, function_symbol); + if (self->funfirstline) + skip_prologue_sal (&sal); - return sym != NULL; + if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc)) + add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol)); +} + +/* A helper struct which just holds a minimal symbol and the object + file from which it came. */ + +typedef struct minsym_and_objfile +{ + struct minimal_symbol *minsym; + struct objfile *objfile; +} minsym_and_objfile_d; + +DEF_VEC_O (minsym_and_objfile_d); + +/* A helper struct to pass some data through + iterate_over_minimal_symbols. */ + +struct collect_minsyms +{ + /* The objfile we're examining. */ + struct objfile *objfile; + + /* The funfirstline setting from the initial call. */ + int funfirstline; + + /* The list_mode setting from the initial call. */ + int list_mode; + + /* The resulting symbols. */ + VEC (minsym_and_objfile_d) *msyms; +}; + +/* A helper function to classify a minimal_symbol_type according to + priority. */ + +static int +classify_mtype (enum minimal_symbol_type t) +{ + switch (t) + { + case mst_file_text: + case mst_file_data: + case mst_file_bss: + /* Intermediate priority. */ + return 1; + + case mst_solib_trampoline: + /* Lowest priority. */ + return 2; + + default: + /* Highest priority. */ + return 0; + } +} + +/* Callback for qsort that sorts symbols by priority. */ + +static int +compare_msyms (const void *a, const void *b) +{ + const minsym_and_objfile_d *moa = a; + const minsym_and_objfile_d *mob = b; + enum minimal_symbol_type ta = MSYMBOL_TYPE (moa->minsym); + enum minimal_symbol_type tb = MSYMBOL_TYPE (mob->minsym); + + return classify_mtype (ta) - classify_mtype (tb); +} + +/* Callback for iterate_over_minimal_symbols that adds the symbol to + the result. */ + +static void +add_minsym (struct minimal_symbol *minsym, void *d) +{ + struct collect_minsyms *info = d; + minsym_and_objfile_d mo; + + /* Exclude data symbols when looking for breakpoint locations. */ + if (!info->list_mode) + switch (minsym->type) + { + case mst_slot_got_plt: + case mst_data: + case mst_bss: + case mst_abs: + case mst_file_data: + case mst_file_bss: + { + /* Make sure this minsym is not a function descriptor + before we decide to discard it. */ + struct gdbarch *gdbarch = info->objfile->gdbarch; + CORE_ADDR addr = gdbarch_convert_from_func_ptr_addr + (gdbarch, SYMBOL_VALUE_ADDRESS (minsym), + ¤t_target); + + if (addr == SYMBOL_VALUE_ADDRESS (minsym)) + return; + } + } + + mo.minsym = minsym; + mo.objfile = info->objfile; + VEC_safe_push (minsym_and_objfile_d, info->msyms, &mo); +} + +/* Search minimal symbols in all objfiles for NAME. If SEARCH_PSPACE + is not NULL, the search is restricted to just that program + space. */ + +static void +search_minsyms_for_name (struct collect_info *info, const char *name, + struct program_space *search_pspace) +{ + struct objfile *objfile; + struct program_space *pspace; + + ALL_PSPACES (pspace) + { + struct collect_minsyms local; + struct cleanup *cleanup; + + if (search_pspace != NULL && search_pspace != pspace) + continue; + if (pspace->executing_startup) + continue; + + set_current_program_space (pspace); + + memset (&local, 0, sizeof (local)); + local.funfirstline = info->state->funfirstline; + local.list_mode = info->state->list_mode; + + cleanup = make_cleanup (VEC_cleanup (minsym_and_objfile_d), + &local.msyms); + + ALL_OBJFILES (objfile) + { + local.objfile = objfile; + iterate_over_minimal_symbols (objfile, name, add_minsym, &local); + } + + if (!VEC_empty (minsym_and_objfile_d, local.msyms)) + { + int classification; + int ix; + minsym_and_objfile_d *item; + + qsort (VEC_address (minsym_and_objfile_d, local.msyms), + VEC_length (minsym_and_objfile_d, local.msyms), + sizeof (minsym_and_objfile_d), + compare_msyms); + + /* Now the minsyms are in classification order. So, we walk + over them and process just the minsyms with the same + classification as the very first minsym in the list. */ + item = VEC_index (minsym_and_objfile_d, local.msyms, 0); + classification = classify_mtype (MSYMBOL_TYPE (item->minsym)); + + for (ix = 0; + VEC_iterate (minsym_and_objfile_d, local.msyms, ix, item); + ++ix) + { + if (classify_mtype (MSYMBOL_TYPE (item->minsym)) != classification) + break; + + minsym_found (info->state, item->objfile, item->minsym, + &info->result); + } + } + + do_cleanups (cleanup); + } +} + +/* A helper function to add all symbols matching NAME to INFO. If + PSPACE is not NULL, the search is restricted to just that program + space. */ + +static void +add_matching_symbols_to_info (const char *name, + struct collect_info *info, + struct program_space *pspace) +{ + int ix; + struct symtab *elt; + + for (ix = 0; VEC_iterate (symtab_p, info->state->file_symtabs, ix, elt); ++ix) + { + struct symbol *sym; + + if (elt == NULL) + { + iterate_over_all_matching_symtabs (name, VAR_DOMAIN, + collect_symbols, info, + pspace); + search_minsyms_for_name (info, name, pspace); + } + else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt)) + { + /* Program spaces that are executing startup should have + been filtered out earlier. */ + gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup); + set_current_program_space (SYMTAB_PSPACE (elt)); + LA_ITERATE_OVER_SYMBOLS (get_search_block (elt), name, + VAR_DOMAIN, collect_symbols, + info); + } + } } /* Decode a linespec that's a variable. If FILE_SYMTAB is non-NULL, look in that symtab's static variables first. */ static struct symtabs_and_lines -decode_variable (char *copy, int funfirstline, - struct linespec_result *canonical, - struct symtab *file_symtab) +decode_variable (struct linespec_state *self, char *copy) { - struct symbol *sym; - struct minimal_symbol *msymbol; + struct collect_info info; + const char *lookup_name; + char *canon; + struct cleanup *cleanup; - sym = lookup_symbol (copy, get_search_block (file_symtab), - VAR_DOMAIN, 0); + info.state = self; + info.result.sals = NULL; + info.result.nelts = 0; - if (sym != NULL) - return symbol_found (funfirstline, canonical, copy, sym, file_symtab, NULL); + cleanup = demangle_for_lookup (copy, current_language->la_language, + &lookup_name); + if (current_language->la_language == language_ada) + { + /* In Ada, the symbol lookups are performed using the encoded + name rather than the demangled name. */ + lookup_name = ada_name_for_lookup (copy); + make_cleanup (xfree, (void *) lookup_name); + } - msymbol = lookup_minimal_symbol (copy, NULL, NULL); + canon = cp_canonicalize_string_no_typedefs (lookup_name); + if (canon != NULL) + { + make_cleanup (xfree, canon); + lookup_name = canon; + } - if (msymbol != NULL) - return minsym_found (funfirstline, msymbol); + add_matching_symbols_to_info (lookup_name, &info, NULL); + + if (info.result.nelts > 0) + { + if (self->canonical) + { + self->canonical->pre_expanded = 1; + if (self->user_filename) + self->canonical->addr_string + = xstrprintf ("%s:%s", self->user_filename, copy); + else + self->canonical->addr_string = xstrdup (copy); + } + return info.result; + } if (!have_full_symbols () && !have_partial_symbols () && !have_minimal_symbols ()) throw_error (NOT_FOUND_ERROR, _("No symbol table is loaded. Use the \"file\" command.")); - throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy); + if (self->user_filename) + throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined in \"%s\"."), + copy, self->user_filename); + else + throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy); } @@ -2116,130 +2970,82 @@ decode_variable (char *copy, int funfirstline, /* Now come some functions that are called from multiple places within decode_line_1. */ -/* We've found a symbol SYM to associate with our linespec; build a - corresponding struct symtabs_and_lines. */ - -static struct symtabs_and_lines -symbol_found (int funfirstline, struct linespec_result *canonical, char *copy, - struct symbol *sym, struct symtab *file_symtab, - struct symbol *function_symbol) +static int +symbol_to_sal (struct symtab_and_line *result, + int funfirstline, struct symbol *sym) { - struct symtabs_and_lines values; - if (SYMBOL_CLASS (sym) == LOC_BLOCK) { - /* Arg is the name of a function. */ - values.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - values.sals[0] = find_function_start_sal (sym, funfirstline); - values.nelts = 1; - - /* Don't use the SYMBOL_LINE; if used at all it points to - the line containing the parameters or thereabouts, not - the first line of code. */ - - /* We might need a canonical line spec if it is a static - function. */ - if (file_symtab == 0) - { - struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym)); - struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK); - - if (lookup_block_symbol (b, copy, VAR_DOMAIN) != NULL) - build_canonical_line_spec (values.sals, copy, canonical); - } - return values; + *result = find_function_start_sal (sym, funfirstline); + return 1; } else { if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0) { - /* We know its line number. */ - values.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - values.nelts = 1; - init_sal (&values.sals[0]); - values.sals[0].symtab = SYMBOL_SYMTAB (sym); - values.sals[0].line = SYMBOL_LINE (sym); - values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym); - values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); - values.sals[0].explicit_pc = 1; - - if (canonical) - { - canonical->special_display = 1; - canonical->canonical = xmalloc (sizeof (char *)); - canonical->canonical[0] - = xstrprintf ("%s:%s", - SYMBOL_NATURAL_NAME (function_symbol), - SYMBOL_NATURAL_NAME (sym)); - } - - return values; + init_sal (result); + result->symtab = SYMBOL_SYMTAB (sym); + result->line = SYMBOL_LINE (sym); + result->pc = SYMBOL_VALUE_ADDRESS (sym); + result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); + result->explicit_pc = 1; + return 1; } else if (funfirstline) { - /* NOT_FOUND_ERROR is not correct but it ensures COPY will be - searched also as a minimal symbol. */ - - throw_error (NOT_FOUND_ERROR, _("\"%s\" is not a function"), copy); + /* Nothing. */ } else if (SYMBOL_LINE (sym) != 0) { /* We know its line number. */ - values.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - values.nelts = 1; - memset (&values.sals[0], 0, sizeof (values.sals[0])); - values.sals[0].symtab = SYMBOL_SYMTAB (sym); - values.sals[0].line = SYMBOL_LINE (sym); - values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); - return values; + init_sal (result); + result->symtab = SYMBOL_SYMTAB (sym); + result->line = SYMBOL_LINE (sym); + result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)); + return 1; } - else - /* This can happen if it is compiled with a compiler which doesn't - put out line numbers for variables. */ - /* FIXME: Shouldn't we just set .line and .symtab to zero - and return? For example, "info line foo" could print - the address. */ - error (_("Line number not known for symbol \"%s\""), copy); } + + return 0; } -/* We've found a minimal symbol MSYMBOL to associate with our - linespec; build a corresponding struct symtabs_and_lines. */ +/* See the comment in linespec.h. */ -static struct symtabs_and_lines -minsym_found (int funfirstline, struct minimal_symbol *msymbol) +void +init_linespec_result (struct linespec_result *lr) { - struct objfile *objfile = msymbol_objfile (msymbol); - struct gdbarch *gdbarch = get_objfile_arch (objfile); - struct symtabs_and_lines values; - CORE_ADDR pc; + memset (lr, 0, sizeof (*lr)); +} - values.sals = (struct symtab_and_line *) - xmalloc (sizeof (struct symtab_and_line)); - values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol), - (struct obj_section *) 0, 0); - values.sals[0].section = SYMBOL_OBJ_SECTION (msymbol); +/* See the comment in linespec.h. */ - /* The minimal symbol might point to a function descriptor; - resolve it to the actual code address instead. */ - pc = gdbarch_convert_from_func_ptr_addr (gdbarch, - values.sals[0].pc, - ¤t_target); - if (pc != values.sals[0].pc) - values.sals[0] = find_pc_sect_line (pc, NULL, 0); +void +destroy_linespec_result (struct linespec_result *ls) +{ + int i; + struct linespec_sals *lsal; - if (funfirstline) - skip_prologue_sal (&values.sals[0]); + xfree (ls->addr_string); + for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i) + { + xfree (lsal->canonical); + xfree (lsal->sals.sals); + } + VEC_free (linespec_sals, ls->sals); +} - values.nelts = 1; - return values; +/* Cleanup function for a linespec_result. */ + +static void +cleanup_linespec_result (void *a) +{ + destroy_linespec_result (a); } -void -init_linespec_result (struct linespec_result *lr) +/* See the comment in linespec.h. */ + +struct cleanup * +make_cleanup_destroy_linespec_result (struct linespec_result *ls) { - memset (lr, 0, sizeof (*lr)); + return make_cleanup (cleanup_linespec_result, ls); } diff --git a/contrib/gdb-7/gdb/linespec.h b/contrib/gdb-7/gdb/linespec.h index 3c86af36cb..ed8174fb7a 100644 --- a/contrib/gdb-7/gdb/linespec.h +++ b/contrib/gdb-7/gdb/linespec.h @@ -1,6 +1,5 @@ /* Header for GDB line completion. - Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2007-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,8 +19,44 @@ struct symtab; +#include "vec.h" + +/* Flags to pass to decode_line_1 and decode_line_full. */ + +enum decode_line_flags + { + /* Set this flag if you want the resulting SALs to describe the + first line of indicated functions. */ + DECODE_LINE_FUNFIRSTLINE = 1, + + /* Set this flag if you want "list mode". In this mode, a + FILE:LINE linespec will always return a result, and such + linespecs will not be expanded to all matches. */ + DECODE_LINE_LIST_MODE = 2 + }; + +/* decode_line_full returns a vector of these. */ + +struct linespec_sals +{ + /* This is the linespec corresponding to the sals contained in this + object. It can be passed as the FILTER argument to future calls + to decode_line_full. This is freed by + destroy_linespec_result. */ + char *canonical; + + /* Sals. The 'sals' field is destroyed by + destroy_linespec_result. */ + struct symtabs_and_lines sals; +}; + +typedef struct linespec_sals linespec_sals; +DEF_VEC_O (linespec_sals); + /* An instance of this may be filled in by decode_line_1. The caller - must call init_linespec_result to initialize it. */ + must call init_linespec_result to initialize it and + destroy_linespec_result to destroy it. The caller must make copies + of any data that it needs to keep. */ struct linespec_result { @@ -30,22 +65,78 @@ struct linespec_result display mechanism would do the wrong thing. */ int special_display; - /* If non-NULL, an array of canonical names for returned - symtab_and_line objects. The array has as many elements as the - `nelts' field in the symtabs_and_line returned by decode_line_1. - An element in the array may be NULL. The array and each non-NULL - element in it are allocated with xmalloc and must be freed by the - caller. */ - char **canonical; + /* If non-zero, the linespec result should be considered to be a + "pre-expanded" multi-location linespec. A pre-expanded linespec + holds all matching locations in a single linespec_sals + object. */ + int pre_expanded; + + /* If PRE_EXPANDED is non-zero, this is set to the linespec entered + by the user. This will be freed by destroy_linespec_result. */ + char *addr_string; + + /* The sals. The vector will be freed by + destroy_linespec_result. */ + VEC (linespec_sals) *sals; }; /* Initialize a linespec_result. */ extern void init_linespec_result (struct linespec_result *); +/* Destroy a linespec_result. */ + +extern void destroy_linespec_result (struct linespec_result *); + +/* Return a cleanup that destroys a linespec_result. */ + +extern struct cleanup * + make_cleanup_destroy_linespec_result (struct linespec_result *); + extern struct symtabs_and_lines - decode_line_1 (char **argptr, int funfirstline, - struct symtab *default_symtab, int default_line, - struct linespec_result *canonical); + decode_line_1 (char **argptr, int flags, + struct symtab *default_symtab, int default_line); + +/* Parse *ARGPTR as a linespec and return results. This is the "full" + interface to this module, which handles multiple results + properly. + + For FLAGS, see decode_line_flags. DECODE_LINE_LIST_MODE is not + valid for this function. + + DEFAULT_SYMTAB and DEFAULT_LINE describe the default location. + DEFAULT_SYMTAB can be NULL, in which case the current symtab and + line are used. + + CANONICAL is where the results are stored. It must not be NULL. + + SELECT_MODE must be one of the multiple_symbols_* constants, or + NULL. It determines how multiple results will be handled. If + NULL, the appropriate CLI value will be used. + + FILTER can either be NULL or a string holding a canonical name. + This is only valid when SELECT_MODE is multiple_symbols_all. + + Multiple results are handled differently depending on the + arguments: + + . With multiple_symbols_cancel, an exception is thrown. + + . With multiple_symbols_ask, a menu is presented to the user. The + user may select none, in which case an exception is thrown; or all, + which is handled like multiple_symbols_all, below. Otherwise, + CANONICAL->SALS will have one entry for each name the user chose. + + . With multiple_symbols_all, CANONICAL->SALS will have a single + entry describing all the matching locations. If FILTER is + non-NULL, then only locations whose canonical name is equal (in the + strcmp sense) to FILTER will be returned; all others will be + filtered out. */ + +extern void decode_line_full (char **argptr, int flags, + struct symtab *default_symtab, int default_line, + struct linespec_result *canonical, + const char *select_mode, + const char *filter); #endif /* defined (LINESPEC_H) */ diff --git a/contrib/gdb-7/gdb/m2-exp.y b/contrib/gdb-7/gdb/m2-exp.y index 1809af8ee5..1e3e3cbcab 100644 --- a/contrib/gdb-7/gdb/m2-exp.y +++ b/contrib/gdb-7/gdb/m2-exp.y @@ -1,6 +1,6 @@ /* YACC grammar for Modula-2 expressions, for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, - 2000, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1996, 1999-2000, 2007-2012 Free Software + Foundation, Inc. Generated from expread.y (now c-exp.y) and contributed by the Department of Computer Science at the State University of New York at Buffalo, 1991. diff --git a/contrib/gdb-7/gdb/m2-lang.c b/contrib/gdb-7/gdb/m2-lang.c index f83c622e21..e91ea32287 100644 --- a/contrib/gdb-7/gdb/m2-lang.c +++ b/contrib/gdb-7/gdb/m2-lang.c @@ -1,7 +1,7 @@ /* Modula 2 language support routines for GDB, the GNU debugger. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2002, 2003, 2004, - 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998, 2000, 2002-2005, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -401,6 +401,8 @@ const struct language_defn m2_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; diff --git a/contrib/gdb-7/gdb/m2-lang.h b/contrib/gdb-7/gdb/m2-lang.h index 88a085d9de..2803e634ff 100644 --- a/contrib/gdb-7/gdb/m2-lang.h +++ b/contrib/gdb-7/gdb/m2-lang.h @@ -1,7 +1,7 @@ /* Modula 2 language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 1998, 2000, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992, 1998, 2000, 2005, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/m2-typeprint.c b/contrib/gdb-7/gdb/m2-typeprint.c index 0caf945d61..9735d7f75b 100644 --- a/contrib/gdb-7/gdb/m2-typeprint.c +++ b/contrib/gdb-7/gdb/m2-typeprint.c @@ -1,7 +1,6 @@ /* Support for printing Modula 2 types for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1995, 2000, 2001, 2002, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-1992, 1995, 2000-2012 Free + Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/m2-valprint.c b/contrib/gdb-7/gdb/m2-valprint.c index ed997b16b6..4378b00ff9 100644 --- a/contrib/gdb-7/gdb/m2-valprint.c +++ b/contrib/gdb-7/gdb/m2-valprint.c @@ -1,7 +1,7 @@ /* Support for printing Modula 2 values for GDB, the GNU debugger. - Copyright (C) 1986, 1988, 1989, 1991, 1992, 1996, 1998, 2000, 2005, 2006, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-1989, 1991-1992, 1996, 1998, 2000, 2005-2012 + Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macrocmd.c b/contrib/gdb-7/gdb/macrocmd.c index c77156a416..367f211d06 100644 --- a/contrib/gdb-7/gdb/macrocmd.c +++ b/contrib/gdb-7/gdb/macrocmd.c @@ -1,6 +1,5 @@ /* C preprocessor macro expansion commands for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -23,6 +22,7 @@ #include "macrotab.h" #include "macroexp.h" #include "macroscope.h" +#include "cli/cli-utils.h" #include "command.h" #include "gdbcmd.h" #include "gdb_string.h" @@ -45,6 +45,14 @@ macro_command (char *arg, int from_tty) /* Macro expansion commands. */ +/* Prints an informational message regarding the lack of macro information. */ +static void macro_inform_no_debuginfo() +{ + fputs_filtered ("GDB has no preprocessor macro information for " + "that code.", + gdb_stdout); +} + static void macro_expand_command (char *exp, int from_tty) { @@ -73,9 +81,7 @@ macro_expand_command (char *exp, int from_tty) fputs_filtered ("\n", gdb_stdout); } else - fputs_filtered ("GDB has no preprocessor macro information for " - "that code.\n", - gdb_stdout); + macro_inform_no_debuginfo (); do_cleanups (cleanup_chain); return; @@ -109,15 +115,16 @@ macro_expand_once_command (char *exp, int from_tty) fputs_filtered ("\n", gdb_stdout); } else - fputs_filtered ("GDB has no preprocessor macro information for " - "that code.\n", - gdb_stdout); + macro_inform_no_debuginfo (); do_cleanups (cleanup_chain); return; } +/* Outputs the include path of a macro starting at FILE and LINE to STREAM. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void show_pp_source_pos (struct ui_file *stream, struct macro_source_file *file, @@ -134,36 +141,27 @@ show_pp_source_pos (struct ui_file *stream, } } +/* Outputs a macro for human consumption, detailing the include path + and macro definition. NAME is the name of the macro. + D the definition. FILE the start of the include path, and LINE the + line number in FILE. + Care should be taken that this function does not cause any lookups into + the splay tree so that it can be safely used while iterating. */ static void -info_macro_command (char *name, int from_tty) +print_macro_definition (const char *name, + const struct macro_definition *d, + struct macro_source_file *file, + int line) { - struct macro_scope *ms = NULL; - struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); - struct macro_definition *d; - - if (! name || ! *name) - error (_("You must follow the `info macro' command with the name" - " of the macro\n" - "whose definition you want to see.")); - - ms = default_macro_scope (); - if (! ms) - error (_("GDB has no preprocessor macro information for that code.")); - - d = macro_lookup_definition (ms->file, ms->line, name); - if (d) - { - int line; - struct macro_source_file *file - = macro_definition_location (ms->file, ms->line, name, &line); - fprintf_filtered (gdb_stdout, "Defined at "); show_pp_source_pos (gdb_stdout, file, line); + if (line != 0) fprintf_filtered (gdb_stdout, "#define %s", name); else fprintf_filtered (gdb_stdout, "-D%s", name); + if (d->kind == macro_function_like) { int i; @@ -177,23 +175,126 @@ info_macro_command (char *name, int from_tty) } fputs_filtered (")", gdb_stdout); } + if (line != 0) fprintf_filtered (gdb_stdout, " %s\n", d->replacement); else fprintf_filtered (gdb_stdout, "=%s\n", d->replacement); +} + +/* A callback function for usage with macro_for_each and friends. + If USER_DATA is null all macros will be printed. + Otherwise USER_DATA is considered to be a string, printing + only macros who's NAME matches USER_DATA. Other arguments are + routed to print_macro_definition. */ +static void +print_macro_callback (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, + void *user_data) +{ + if (! user_data || strcmp (user_data, name) == 0) + print_macro_definition (name, macro, source, line); +} + +/* The implementation of the `info macro' command. */ +static void +info_macro_command (char *args, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain; + char *name; + int show_all_macros_named = 0; + char *arg_start = args; + int processing_args = 1; + + while (processing_args + && arg_start && *arg_start == '-' && *arg_start != '\0') + { + char *p = skip_to_space (arg_start); + + if (strncmp (arg_start, "-a", p - arg_start) == 0 + || strncmp (arg_start, "-all", p - arg_start) == 0) + show_all_macros_named = 1; + else if (strncmp (arg_start, "--", p - arg_start) == 0) + /* Our macro support seems rather C specific but this would + seem necessary for languages allowing - in macro names. + e.g. Scheme's (defmacro ->foo () "bar\n") */ + processing_args = 0; + else + { + /* Relies on modified 'args' not making it in to history */ + *p = '\0'; + error (_("Unrecognized option '%s' to info macro command. " + "Try \"help info macro\"."), arg_start); + } + + arg_start = skip_spaces (p); } + + name = arg_start; + + if (! name || ! *name) + error (_("You must follow the `info macro' command with the name" + " of the macro\n" + "whose definition you want to see.")); + + ms = default_macro_scope (); + cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (! ms) + macro_inform_no_debuginfo (); + else if (show_all_macros_named) + macro_for_each (ms->file->table, print_macro_callback, name); else { - fprintf_filtered (gdb_stdout, - "The symbol `%s' has no definition as a C/C++" - " preprocessor macro\n" - "at ", name); - show_pp_source_pos (gdb_stdout, ms->file, ms->line); + struct macro_definition *d; + + d = macro_lookup_definition (ms->file, ms->line, name); + if (d) + { + int line; + struct macro_source_file *file + = macro_definition_location (ms->file, ms->line, name, &line); + + print_macro_definition (name, d, file, line); + } + else + { + fprintf_filtered (gdb_stdout, + "The symbol `%s' has no definition as a C/C++" + " preprocessor macro\n" + "at ", name); + show_pp_source_pos (gdb_stdout, ms->file, ms->line); + } } do_cleanups (cleanup_chain); } +/* Implementation of the "info macros" command. */ +static void +info_macros_command (char *args, int from_tty) +{ + struct macro_scope *ms = NULL; + struct cleanup *cleanup_chain = make_cleanup (free_current_contents, &ms); + + if (args == NULL) + ms = default_macro_scope (); + else + { + struct symtabs_and_lines sals = decode_line_spec (args, 0); + + if (sals.nelts) + ms = sal_macro_scope (sals.sals[0]); + } + + if (! ms || ! ms->file || ! ms->file->table) + macro_inform_no_debuginfo (); + else + macro_for_each_in_scope (ms->file, ms->line, print_macro_callback, NULL); + + do_cleanups (cleanup_chain); +} /* User-defined macros. */ @@ -359,6 +460,7 @@ macro_undef_command (char *exp, int from_tty) static void print_one_macro (const char *name, const struct macro_definition *macro, + struct macro_source_file *source, int line, void *ignore) { fprintf_filtered (gdb_stdout, "macro define %s", name); @@ -382,7 +484,6 @@ macro_list_command (char *exp, int from_tty) macro_for_each (macro_user_macros, print_one_macro, NULL); } - /* Initializing the `macrocmd' module. */ @@ -417,7 +518,19 @@ expression work together to yield a pre-processed expression."), add_alias_cmd ("exp1", "expand-once", no_class, 1, ¯olist); add_cmd ("macro", no_class, info_macro_command, - _("Show the definition of MACRO, and its source location."), + _("Show the definition of MACRO, and it's source location.\n\ +Usage: info macro [-a|-all] [--] MACRO\n\ +Options: \n\ + -a, --all Output all definitions of MACRO in the current compilation\ + unit.\n\ + -- Specify the end of arguments and the beginning of the MACRO."), + + &infolist); + + add_cmd ("macros", no_class, info_macros_command, + _("Show the definitions of all macros at LINESPEC, or the current \ +source location.\n\ +Usage: info macros [LINESPEC]"), &infolist); add_cmd ("define", no_class, macro_define_command, _("\ diff --git a/contrib/gdb-7/gdb/macroexp.c b/contrib/gdb-7/gdb/macroexp.c index 6080ee43ea..d5e4e40326 100644 --- a/contrib/gdb-7/gdb/macroexp.c +++ b/contrib/gdb-7/gdb/macroexp.c @@ -1,6 +1,5 @@ /* C preprocessor macro expansion for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macroexp.h b/contrib/gdb-7/gdb/macroexp.h index 3b7c319547..289619eba9 100644 --- a/contrib/gdb-7/gdb/macroexp.h +++ b/contrib/gdb-7/gdb/macroexp.h @@ -1,6 +1,5 @@ /* Interface to C preprocessor macro expansion for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macroscope.c b/contrib/gdb-7/gdb/macroscope.c index b529e68c1f..a23cac4f7e 100644 --- a/contrib/gdb-7/gdb/macroscope.c +++ b/contrib/gdb-7/gdb/macroscope.c @@ -1,6 +1,5 @@ /* Functions for deciding which macros are currently in scope. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macroscope.h b/contrib/gdb-7/gdb/macroscope.h index fbbecfa9b1..0db498e072 100644 --- a/contrib/gdb-7/gdb/macroscope.h +++ b/contrib/gdb-7/gdb/macroscope.h @@ -1,6 +1,5 @@ /* Interface to functions for deciding which macros are currently in scope. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/macrotab.c b/contrib/gdb-7/gdb/macrotab.c index cba285dc9d..7428839889 100644 --- a/contrib/gdb-7/gdb/macrotab.c +++ b/contrib/gdb-7/gdb/macrotab.c @@ -1,6 +1,5 @@ /* C preprocessor macro tables for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -913,7 +912,8 @@ foreach_macro (splay_tree_node node, void *arg) struct macro_key *key = (struct macro_key *) node->key; struct macro_definition *def = (struct macro_definition *) node->value; - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } @@ -945,7 +945,8 @@ foreach_macro_in_scope (splay_tree_node node, void *info) && (!key->end_file || compare_locations (key->end_file, key->end_line, datum->file, datum->line) >= 0)) - (*datum->fn) (key->name, def, datum->user_data); + (*datum->fn) (key->name, def, key->start_file, key->start_line, + datum->user_data); return 0; } diff --git a/contrib/gdb-7/gdb/macrotab.h b/contrib/gdb-7/gdb/macrotab.h index d2b2b63290..8316cc375d 100644 --- a/contrib/gdb-7/gdb/macrotab.h +++ b/contrib/gdb-7/gdb/macrotab.h @@ -1,6 +1,5 @@ /* Interface to C preprocessor macro tables for GDB. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. This file is part of GDB. @@ -306,11 +305,14 @@ struct macro_source_file *(macro_definition_location int *definition_line)); /* Callback function when walking a macro table. NAME is the name of - the macro, and DEFINITION is the definition. USER_DATA is an - arbitrary pointer which is passed by the caller to macro_for_each - or macro_for_each_in_scope. */ + the macro, and DEFINITION is the definition. SOURCE is the file at the + start of the include path, and LINE is the line number of the SOURCE file + where the macro was defined. USER_DATA is an arbitrary pointer which is + passed by the caller to macro_for_each or macro_for_each_in_scope. */ typedef void (*macro_callback_fn) (const char *name, const struct macro_definition *definition, + struct macro_source_file *source, + int line, void *user_data); /* Call the function FN for each macro in the macro table TABLE. diff --git a/contrib/gdb-7/gdb/main.c b/contrib/gdb-7/gdb/main.c index ff305a1f69..8b45c25b4f 100644 --- a/contrib/gdb-7/gdb/main.c +++ b/contrib/gdb-7/gdb/main.c @@ -1,8 +1,6 @@ /* Top level stuff for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -104,6 +102,7 @@ extern char *external_editor_command; file or directory. FLAG is true if the value is relocatable, false otherwise. Returns a newly allocated string; this may return NULL under the same conditions as make_relative_prefix. */ + static char * relocate_path (const char *progname, const char *initial, int flag) { @@ -117,12 +116,13 @@ relocate_path (const char *progname, const char *initial, int flag) the result is a directory, it is used; otherwise, INITIAL is used. The chosen directory is then canonicalized using lrealpath. This function always returns a newly-allocated string. */ -static char * -relocate_directory (const char *progname, const char *initial, int flag) + +char * +relocate_gdb_directory (const char *initial, int flag) { char *dir; - dir = relocate_path (progname, initial, flag); + dir = relocate_path (gdb_program_name, initial, flag); if (dir) { struct stat s; @@ -225,6 +225,10 @@ get_init_files (char **system_gdbinit, static int captured_command_loop (void *data) { + /* Top-level execution commands can be run on the background from + here on. */ + interpreter_async = 1; + current_interp_command_loop (); /* FIXME: cagney/1999-11-05: A correct command_loop() implementaton would clean things up (restoring the cleanup chain) to the state @@ -294,7 +298,14 @@ captured_main (void *data) int save_auto_load; struct objfile *objfile; - struct cleanup *pre_stat_chain = make_command_stats_cleanup (0); + struct cleanup *pre_stat_chain; + +#ifdef HAVE_SBRK + /* Set this before calling make_command_stats_cleanup. */ + lim_at_start = (char *) sbrk (0); +#endif + + pre_stat_chain = make_command_stats_cleanup (0); #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) setlocale (LC_MESSAGES, ""); @@ -305,10 +316,6 @@ captured_main (void *data) bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); -#ifdef HAVE_SBRK - lim_at_start = (char *) sbrk (0); -#endif - cmdsize = 1; cmdarg = (struct cmdarg *) xmalloc (cmdsize * sizeof (*cmdarg)); ncmd = 0; @@ -317,8 +324,8 @@ captured_main (void *data) ndir = 0; quit_flag = 0; - line = (char *) xmalloc (linesize); - line[0] = '\0'; /* Terminate saved (now empty) cmd line. */ + saved_command_line = (char *) xmalloc (saved_command_line_size); + saved_command_line[0] = '\0'; instream = stdin; gdb_stdout = stdio_fileopen (stdout); @@ -342,22 +349,21 @@ captured_main (void *data) current_directory = gdb_dirbuf; /* Set the sysroot path. */ - gdb_sysroot = relocate_directory (argv[0], TARGET_SYSTEM_ROOT, - TARGET_SYSTEM_ROOT_RELOCATABLE); + gdb_sysroot = relocate_gdb_directory (TARGET_SYSTEM_ROOT, + TARGET_SYSTEM_ROOT_RELOCATABLE); - debug_file_directory = relocate_directory (argv[0], DEBUGDIR, - DEBUGDIR_RELOCATABLE); + debug_file_directory = relocate_gdb_directory (DEBUGDIR, + DEBUGDIR_RELOCATABLE); - gdb_datadir = relocate_directory (argv[0], GDB_DATADIR, - GDB_DATADIR_RELOCATABLE); + gdb_datadir = relocate_gdb_directory (GDB_DATADIR, + GDB_DATADIR_RELOCATABLE); #ifdef WITH_PYTHON_PATH { /* For later use in helping Python find itself. */ char *tmp = concat (WITH_PYTHON_PATH, SLASH_STRING, "lib", NULL); - python_libdir = relocate_directory (argv[0], tmp, - PYTHON_PATH_RELOCATABLE); + python_libdir = relocate_gdb_directory (tmp, PYTHON_PATH_RELOCATABLE); xfree (tmp); } #endif diff --git a/contrib/gdb-7/gdb/main.h b/contrib/gdb-7/gdb/main.h index fbbc473a45..41dbdd6cc6 100644 --- a/contrib/gdb-7/gdb/main.h +++ b/contrib/gdb-7/gdb/main.h @@ -1,7 +1,6 @@ /* Main interface for GDB, the GNU debugger. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/maint.c b/contrib/gdb-7/gdb/maint.c index ca9b3cca64..6a106fd387 100644 --- a/contrib/gdb-7/gdb/maint.c +++ b/contrib/gdb-7/gdb/maint.c @@ -1,7 +1,7 @@ /* Support for GDB maintenance commands. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, - 2003, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1997, 1999-2004, 2007-2012 Free Software + Foundation, Inc. Written by Fred Fish at Cygnus Support. @@ -74,19 +74,7 @@ show_watchdog (struct ui_file *file, int from_tty, fprintf_filtered (file, _("Watchdog timer is %s.\n"), value); } -/* - - LOCAL FUNCTION - - maintenance_command -- access the maintenance subcommands - - SYNOPSIS - - void maintenance_command (char *args, int from_tty) - - DESCRIPTION - - */ +/* Access the maintenance subcommands. */ static void maintenance_command (char *args, int from_tty) diff --git a/contrib/gdb-7/gdb/mdebugread.c b/contrib/gdb-7/gdb/mdebugread.c index e224f19180..c95c09b62e 100644 --- a/contrib/gdb-7/gdb/mdebugread.c +++ b/contrib/gdb-7/gdb/mdebugread.c @@ -1,8 +1,7 @@ /* Read a symbol table in ECOFF format (Third-Eye). - Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1986-1987, 1989-2004, 2007-2012 Free Software + Foundation, Inc. Original version contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work by Per Bothner, John Gilmore and Ian Lance Taylor @@ -52,6 +51,7 @@ #include "stabsread.h" #include "complaints.h" #include "demangle.h" +#include "gdb-demangle.h" #include "gdb_assert.h" #include "block.h" #include "dictionary.h" @@ -78,6 +78,11 @@ extern void _initialize_mdebugread (void); case the symbol's ELF section could not be represented in ECOFF. */ #define ECOFF_IN_ELF(bfd) (bfd_get_flavour (bfd) == bfd_target_elf_flavour \ && bfd_get_section_by_name (bfd, ".mdebug") != NULL) + +/* The objfile we are currently reading. */ + +static struct objfile *mdebugread_objfile; + /* We put a pointer to this structure in the read_symtab_private field @@ -510,7 +515,7 @@ add_pending (FDR *fh, char *sh, struct type *t) if (!p) { p = ((struct mdebug_pending *) - obstack_alloc (¤t_objfile->objfile_obstack, + obstack_alloc (&mdebugread_objfile->objfile_obstack, sizeof (struct mdebug_pending))); p->s = sh; p->t = t; @@ -1003,7 +1008,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, if (sh->iss == 0 || name[0] == '.' || name[0] == '\0') TYPE_TAG_NAME (t) = NULL; else - TYPE_TAG_NAME (t) = obconcat (¤t_objfile->objfile_obstack, + TYPE_TAG_NAME (t) = obconcat (&mdebugread_objfile->objfile_obstack, name, (char *) NULL); TYPE_CODE (t) = type_code; @@ -1048,12 +1053,12 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, FIELD_BITSIZE (*f) = 0; enum_sym = ((struct symbol *) - obstack_alloc (¤t_objfile->objfile_obstack, + obstack_alloc (&mdebugread_objfile->objfile_obstack, sizeof (struct symbol))); memset (enum_sym, 0, sizeof (struct symbol)); SYMBOL_SET_LINKAGE_NAME (enum_sym, obsavestring (f->name, strlen (f->name), - ¤t_objfile->objfile_obstack)); + &mdebugread_objfile->objfile_obstack)); SYMBOL_CLASS (enum_sym) = LOC_CONST; SYMBOL_TYPE (enum_sym) = t; SYMBOL_DOMAIN (enum_sym) = VAR_DOMAIN; @@ -1144,9 +1149,9 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend, s = new_symbol (MDEBUG_EFI_SYMBOL_NAME); SYMBOL_DOMAIN (s) = LABEL_DOMAIN; SYMBOL_CLASS (s) = LOC_CONST; - SYMBOL_TYPE (s) = objfile_type (current_objfile)->builtin_void; + SYMBOL_TYPE (s) = objfile_type (mdebugread_objfile)->builtin_void; e = ((struct mdebug_extra_func_info *) - obstack_alloc (¤t_objfile->objfile_obstack, + obstack_alloc (&mdebugread_objfile->objfile_obstack, sizeof (struct mdebug_extra_func_info))); memset (e, 0, sizeof (struct mdebug_extra_func_info)); SYMBOL_VALUE_BYTES (s) = (gdb_byte *) e; @@ -1529,19 +1534,19 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, /* Handle undefined types, they have indexNil. */ if (aux_index == indexNil) - return basic_type (btInt, current_objfile); + return basic_type (btInt, mdebugread_objfile); /* Handle corrupt aux indices. */ if (aux_index >= (debug_info->fdr + fd)->caux) { index_complaint (sym_name); - return basic_type (btInt, current_objfile); + return basic_type (btInt, mdebugread_objfile); } ax += aux_index; /* Use aux as a type information record, map its basic type. */ (*debug_swap->swap_tir_in) (bigend, &ax->a_ti, t); - tp = basic_type (t->bt, current_objfile); + tp = basic_type (t->bt, mdebugread_objfile); if (tp == NULL) { /* Cannot use builtin types -- build our own. */ @@ -1574,7 +1579,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, break; default: basic_type_complaint (t->bt, sym_name); - return basic_type (btInt, current_objfile); + return basic_type (btInt, mdebugread_objfile); } } @@ -1592,9 +1597,9 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, as short and unsigned short types with a field width of 8. Enum types also have a field width which we ignore for now. */ if (t->bt == btShort && width == 8) - tp = basic_type (btChar, current_objfile); + tp = basic_type (btChar, mdebugread_objfile); else if (t->bt == btUShort && width == 8) - tp = basic_type (btUChar, current_objfile); + tp = basic_type (btUChar, mdebugread_objfile); else if (t->bt == btEnum) ; else @@ -1630,7 +1635,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, { complaint (&symfile_complaints, _("unable to cross ref btIndirect for %s"), sym_name); - return basic_type (btInt, current_objfile); + return basic_type (btInt, mdebugread_objfile); } xref_fh = get_rfd (fd, rf); xref_fd = xref_fh - debug_info->fdr; @@ -1654,7 +1659,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, /* Try to cross reference this type, build new type on failure. */ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); if (tp == (struct type *) NULL) - tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); + tp = init_type (type_code, 0, 0, (char *) NULL, mdebugread_objfile); /* DEC c89 produces cross references to qualified aggregate types, dereference them. */ @@ -1698,7 +1703,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, || strcmp (TYPE_TAG_NAME (tp), name) != 0) TYPE_TAG_NAME (tp) = obsavestring (name, strlen (name), - ¤t_objfile->objfile_obstack); + &mdebugread_objfile->objfile_obstack); } } @@ -1713,7 +1718,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, /* Try to cross reference this type, build new type on failure. */ ax += cross_ref (fd, ax, &tp, type_code, &name, bigend, sym_name); if (tp == (struct type *) NULL) - tp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); + tp = init_type (type_code, 0, 0, (char *) NULL, mdebugread_objfile); /* Make sure that TYPE_CODE(tp) has an expected type code. Any type may be returned from cross_ref if file indirect entries @@ -1734,7 +1739,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, if (TYPE_NAME (tp) == NULL || strcmp (TYPE_NAME (tp), name) != 0) TYPE_NAME (tp) = obsavestring (name, strlen (name), - ¤t_objfile->objfile_obstack); + &mdebugread_objfile->objfile_obstack); } } if (t->bt == btTypedef) @@ -1747,7 +1752,7 @@ parse_type (int fd, union aux_ext *ax, unsigned int aux_index, int *bs, { complaint (&symfile_complaints, _("unable to cross ref btTypedef for %s"), sym_name); - tp = basic_type (btInt, current_objfile); + tp = basic_type (btInt, mdebugread_objfile); } } @@ -1858,7 +1863,7 @@ upgrade_type (int fd, struct type **tpp, int tq, union aux_ext *ax, int bigend, complaint (&symfile_complaints, _("illegal array index type for %s, assuming int"), sym_name); - indx = objfile_type (current_objfile)->builtin_int; + indx = objfile_type (mdebugread_objfile)->builtin_int; } /* Get the bounds, and create the array type. */ @@ -4011,7 +4016,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) external_pdr_size = debug_swap->external_pdr_size; swap_sym_in = debug_swap->swap_sym_in; swap_pdr_in = debug_swap->swap_pdr_in; - current_objfile = pst->objfile; + mdebugread_objfile = pst->objfile; cur_fd = FDR_IDX (pst); fh = ((cur_fd == -1) ? (FDR *) NULL @@ -4047,7 +4052,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) if (fh->csym <= 2) /* FIXME, this blows psymtab->symtab ptr. */ { - current_objfile = NULL; + mdebugread_objfile = NULL; return; } for (cur_sdx = 2; cur_sdx < fh->csym; cur_sdx++) @@ -4109,7 +4114,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) procedure specific info. */ struct mdebug_extra_func_info *e = ((struct mdebug_extra_func_info *) - obstack_alloc (¤t_objfile->objfile_obstack, + obstack_alloc (&mdebugread_objfile->objfile_obstack, sizeof (struct mdebug_extra_func_info))); struct symbol *s = new_symbol (MDEBUG_EFI_SYMBOL_NAME); @@ -4204,7 +4209,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) { /* This symbol table contains ordinary ecoff entries. */ - int maxlines; + int maxlines, size; EXTR *ext_ptr; if (fh == 0) @@ -4311,7 +4316,14 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) } } - LINETABLE (st) = lines; + size = lines->nitems; + if (size > 1) + --size; + LINETABLE (st) = obstack_copy (&mdebugread_objfile->objfile_obstack, + lines, + (sizeof (struct linetable) + + size * sizeof (lines->item))); + xfree (lines); /* .. and our share of externals. XXX use the global list to speed up things here. How? @@ -4350,7 +4362,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst, const char *filename) /* Now link the psymtab and the symtab. */ pst->symtab = st; - current_objfile = NULL; + mdebugread_objfile = NULL; } /* Ancillary parsing procedures. */ @@ -4427,7 +4439,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, { *pname = ""; *tpp = init_type (type_code, 0, TYPE_FLAG_STUB, - (char *) NULL, current_objfile); + (char *) NULL, mdebugread_objfile); return result; } @@ -4514,7 +4526,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, { case btVoid: *tpp = init_type (type_code, 0, 0, (char *) NULL, - current_objfile); + mdebugread_objfile); *pname = ""; break; @@ -4550,7 +4562,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, _("illegal bt %d in forward typedef for %s"), tir.bt, sym_name); *tpp = init_type (type_code, 0, 0, (char *) NULL, - current_objfile); + mdebugread_objfile); break; } return result; @@ -4578,7 +4590,7 @@ cross_ref (int fd, union aux_ext *ax, struct type **tpp, has not been parsed yet. Initialize the type only, it will be filled in when it's definition is parsed. */ - *tpp = init_type (type_code, 0, 0, (char *) NULL, current_objfile); + *tpp = init_type (type_code, 0, 0, (char *) NULL, mdebugread_objfile); } add_pending (fh, esh, *tpp); } @@ -4763,7 +4775,6 @@ new_symtab (const char *name, int maxlines, struct objfile *objfile) BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK)) = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), GLOBAL_BLOCK); - s->free_code = free_linetable; s->debugformat = "ECOFF"; return (s); } @@ -4803,7 +4814,9 @@ new_linetable (int size) { struct linetable *l; - size = (size - 1) * sizeof (l->item) + sizeof (struct linetable); + if (size > 1) + --size; + size = size * sizeof (l->item) + sizeof (struct linetable); l = (struct linetable *) xmalloc (size); l->nitems = 0; return l; @@ -4867,12 +4880,12 @@ static struct symbol * new_symbol (char *name) { struct symbol *s = ((struct symbol *) - obstack_alloc (¤t_objfile->objfile_obstack, + obstack_alloc (&mdebugread_objfile->objfile_obstack, sizeof (struct symbol))); memset (s, 0, sizeof (*s)); SYMBOL_SET_LANGUAGE (s, psymtab_language); - SYMBOL_SET_NAMES (s, name, strlen (name), 1, current_objfile); + SYMBOL_SET_NAMES (s, name, strlen (name), 1, mdebugread_objfile); return s; } @@ -4883,7 +4896,7 @@ new_type (char *name) { struct type *t; - t = alloc_type (current_objfile); + t = alloc_type (mdebugread_objfile); TYPE_NAME (t) = name; INIT_CPLUS_SPECIFIC (t); return t; diff --git a/contrib/gdb-7/gdb/mdebugread.h b/contrib/gdb-7/gdb/mdebugread.h index 71427cbd8c..2642abb9df 100644 --- a/contrib/gdb-7/gdb/mdebugread.h +++ b/contrib/gdb-7/gdb/mdebugread.h @@ -1,7 +1,6 @@ /* Read a symbol table in ECOFF format (Third-Eye). - Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mem-break.c b/contrib/gdb-7/gdb/mem-break.c index ba7dc242e5..7d0e3f1b3c 100644 --- a/contrib/gdb-7/gdb/mem-break.c +++ b/contrib/gdb-7/gdb/mem-break.c @@ -1,7 +1,7 @@ /* Simulate breakpoints by patching locations in the target system, for GDB. - Copyright (C) 1990, 1991, 1992, 1993, 1995, 1997, 1998, 1999, 2000, 2002, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1990-1993, 1995, 1997-2000, 2002, 2007-2012 Free + Software Foundation, Inc. Contributed by Cygnus Support. Written by John Gilmore. @@ -60,8 +60,8 @@ default_memory_insert_breakpoint (struct gdbarch *gdbarch, /* Write the breakpoint. */ if (val == 0) - val = target_write_memory (bp_tgt->placed_address, bp, - bp_tgt->placed_size); + val = target_write_raw_memory (bp_tgt->placed_address, bp, + bp_tgt->placed_size); return val; } @@ -71,8 +71,8 @@ int default_memory_remove_breakpoint (struct gdbarch *gdbarch, struct bp_target_info *bp_tgt) { - return target_write_memory (bp_tgt->placed_address, bp_tgt->shadow_contents, - bp_tgt->placed_size); + return target_write_raw_memory (bp_tgt->placed_address, bp_tgt->shadow_contents, + bp_tgt->placed_size); } diff --git a/contrib/gdb-7/gdb/memattr.c b/contrib/gdb-7/gdb/memattr.c index d576155c80..ec7deb5f54 100644 --- a/contrib/gdb-7/gdb/memattr.c +++ b/contrib/gdb-7/gdb/memattr.c @@ -1,7 +1,6 @@ /* Memory attributes support, for GDB. - Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 2001-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/memattr.h b/contrib/gdb-7/gdb/memattr.h index 5596730686..dbee1d11a8 100644 --- a/contrib/gdb-7/gdb/memattr.h +++ b/contrib/gdb-7/gdb/memattr.h @@ -1,7 +1,6 @@ /* Memory attributes support, for GDB. - Copyright (C) 2001, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001, 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/memory-map.c b/contrib/gdb-7/gdb/memory-map.c index 5e61ca5722..a2e2a1998b 100644 --- a/contrib/gdb-7/gdb/memory-map.c +++ b/contrib/gdb-7/gdb/memory-map.c @@ -1,7 +1,6 @@ /* Routines for handling XML memory maps provided by target. - Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/memory-map.h b/contrib/gdb-7/gdb/memory-map.h index 64a711f94c..fcde0d428f 100644 --- a/contrib/gdb-7/gdb/memory-map.h +++ b/contrib/gdb-7/gdb/memory-map.h @@ -1,7 +1,6 @@ /* Routines for handling XML memory maps provided by target. - Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/memrange.c b/contrib/gdb-7/gdb/memrange.c index dcacff665e..ed41b9ac01 100644 --- a/contrib/gdb-7/gdb/memrange.c +++ b/contrib/gdb-7/gdb/memrange.c @@ -1,6 +1,6 @@ /* Memory ranges - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/memrange.h b/contrib/gdb-7/gdb/memrange.h index 9071b88de5..926af22fe9 100644 --- a/contrib/gdb-7/gdb/memrange.h +++ b/contrib/gdb-7/gdb/memrange.h @@ -1,6 +1,6 @@ /* The memory range data structure, and associated utilities. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-break.c b/contrib/gdb-7/gdb/mi/mi-cmd-break.c index fe007a5cea..e04d34d60d 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-break.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-break.c @@ -1,6 +1,5 @@ /* MI Command Set - breakpoint and watchpoint commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -29,6 +28,7 @@ #include "gdb.h" #include "exceptions.h" #include "observer.h" +#include "mi-main.h" enum { @@ -46,10 +46,10 @@ static int mi_can_breakpoint_notify; /* Output a single breakpoint, when allowed. */ static void -breakpoint_notify (int b) +breakpoint_notify (struct breakpoint *b) { if (mi_can_breakpoint_notify) - gdb_breakpoint_query (uiout, b, NULL); + gdb_breakpoint_query (current_uiout, b->number, NULL); } enum bp_type @@ -83,7 +83,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc) IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT, TRACEPOINT_OPT, }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"h", HARDWARE_OPT, 0}, {"t", TEMP_OPT, 0}, @@ -146,8 +146,6 @@ mi_cmd_break_insert (char *command, char **argv, int argc) if (! mi_breakpoint_observers_installed) { observer_attach_breakpoint_created (breakpoint_notify); - observer_attach_breakpoint_modified (breakpoint_notify); - observer_attach_breakpoint_deleted (breakpoint_notify); mi_breakpoint_observers_installed = 1; } @@ -170,7 +168,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc) temp_p, type_wanted, ignore_count, pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE, - NULL, 0, enabled, 0); + &bkpt_breakpoint_ops, 0, enabled, 0, 0); do_cleanups (back_to); } @@ -187,7 +185,7 @@ mi_cmd_break_passcount (char *command, char **argv, int argc) { int n; int p; - struct breakpoint *t; + struct tracepoint *t; if (argc != 2) error (_("Usage: tracepoint-number passcount")); @@ -203,7 +201,7 @@ mi_cmd_break_passcount (char *command, char **argv, int argc) } else { - error (_("Cound not find tracepoint %d"), n); + error (_("Could not find tracepoint %d"), n); } } @@ -222,7 +220,7 @@ mi_cmd_break_watch (char *command, char **argv, int argc) { READ_OPT, ACCESS_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"r", READ_OPT, 0}, {"a", ACCESS_OPT, 0}, diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-disas.c b/contrib/gdb-7/gdb/mi/mi-cmd-disas.c index 28e84f661d..6de7c5f6c9 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-disas.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-disas.c @@ -1,6 +1,5 @@ /* MI Command Set - disassemble commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -55,6 +54,7 @@ void mi_cmd_disassemble (char *command, char **argv, int argc) { struct gdbarch *gdbarch = get_current_arch (); + struct ui_out *uiout = current_uiout; CORE_ADDR start; int mode, disasm_flags; @@ -82,7 +82,7 @@ mi_cmd_disassemble (char *command, char **argv, int argc) { FILE_OPT, LINE_OPT, NUM_OPT, START_OPT, END_OPT }; - static struct mi_opt opts[] = { + static const struct mi_opt opts[] = { {"f", FILE_OPT, 1}, {"l", LINE_OPT, 1}, {"n", NUM_OPT, 1}, diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-env.c b/contrib/gdb-7/gdb/mi/mi-cmd-env.c index ad34aacf56..65307a69ed 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-env.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-env.c @@ -1,7 +1,6 @@ /* MI Command Set - environment commands. - Copyright (C) 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2004, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat Inc. @@ -69,6 +68,8 @@ env_execute_cli_command (const char *cmd, const char *args) void mi_cmd_env_pwd (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; + if (argc > 0) error (_("-environment-pwd: No arguments required")); @@ -112,6 +113,7 @@ env_mod_path (char *dirname, char **which_path) void mi_cmd_env_path (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; char *exec_path; char *env; int reset = 0; @@ -122,7 +124,7 @@ mi_cmd_env_path (char *command, char **argv, int argc) { RESET_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"r", RESET_OPT, 0}, { 0, 0, 0 } @@ -185,6 +187,7 @@ mi_cmd_env_path (char *command, char **argv, int argc) void mi_cmd_env_dir (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; int i; int optind = 0; int reset = 0; @@ -193,7 +196,7 @@ mi_cmd_env_dir (char *command, char **argv, int argc) { RESET_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"r", RESET_OPT, 0}, { 0, 0, 0 } @@ -257,7 +260,8 @@ mi_cmd_inferior_tty_show (char *command, char **argv, int argc) error (_("-inferior-tty-show: Usage: No args")); if (inferior_io_terminal) - ui_out_field_string (uiout, "inferior_tty_terminal", inferior_io_terminal); + ui_out_field_string (current_uiout, + "inferior_tty_terminal", inferior_io_terminal); } void diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-file.c b/contrib/gdb-7/gdb/mi/mi-cmd-file.c index 0150ca07d4..c4d1461917 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-file.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-file.c @@ -1,6 +1,5 @@ /* MI Command Set - breakpoint and watchpoint commands. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -34,6 +33,7 @@ void mi_cmd_file_list_exec_source_file (char *command, char **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)) error (_("-file-list-exec-source-file: Usage: No args")); @@ -67,6 +67,8 @@ static void print_partial_file_name (const char *filename, const char *fullname, void *ignore) { + struct ui_out *uiout = current_uiout; + ui_out_begin (uiout, ui_out_type_tuple, NULL); ui_out_field_string (uiout, "file", filename); @@ -80,6 +82,7 @@ print_partial_file_name (const char *filename, const char *fullname, void mi_cmd_file_list_exec_source_files (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct symtab *s; struct objfile *objfile; @@ -105,7 +108,8 @@ mi_cmd_file_list_exec_source_files (char *command, char **argv, int argc) ui_out_end (uiout, ui_out_type_tuple); } - map_partial_symbol_filenames (print_partial_file_name, NULL); + map_partial_symbol_filenames (print_partial_file_name, NULL, + 1 /*need_fullname*/); ui_out_end (uiout, ui_out_type_list); } diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-stack.c b/contrib/gdb-7/gdb/mi/mi-cmd-stack.c index ad2085115b..c0c17bce9a 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-stack.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-stack.c @@ -1,6 +1,6 @@ /* MI Command Set - stack commands. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2002-2005, 2007-2012 Free Software Foundation, + Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -36,7 +36,8 @@ enum what_to_list { locals, arguments, all }; static void list_args_or_locals (enum what_to_list what, - int values, struct frame_info *fi); + enum print_values values, + struct frame_info *fi); /* Print a list of the stack frames. Args can be none, in which case we want to print the whole backtrace, or a pair of numbers @@ -78,7 +79,7 @@ mi_cmd_stack_list_frames (char *command, char **argv, int argc) if (fi == NULL) error (_("-stack-list-frames: Not enough frames in stack.")); - cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "stack"); + cleanup_stack = make_cleanup_ui_out_list_begin_end (current_uiout, "stack"); /* Now let;s print the frames up to frame_high, or until there are frames in the stack. */ @@ -117,7 +118,7 @@ mi_cmd_stack_info_depth (char *command, char **argv, int argc) i++, fi = get_prev_frame (fi)) QUIT; - ui_out_field_int (uiout, "depth", i); + ui_out_field_int (current_uiout, "depth", i); } static enum print_values @@ -166,6 +167,7 @@ mi_cmd_stack_list_args (char *command, char **argv, int argc) struct frame_info *fi; struct cleanup *cleanup_stack_args; enum print_values print_values; + struct ui_out *uiout = current_uiout; if (argc < 1 || argc > 3 || argc == 2) error (_("-stack-list-arguments: Usage: " @@ -234,21 +236,95 @@ mi_cmd_stack_list_variables (char *command, char **argv, int argc) list_args_or_locals (all, parse_print_values (argv[0]), frame); } +/* Print single local or argument. ARG must be already read in. For WHAT and + VALUES see list_args_or_locals. + + Errors are printed as if they would be the parameter value. Use zeroed ARG + iff it should not be printed accoring to VALUES. */ + +static void +list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, + enum print_values values) +{ + struct cleanup *cleanup_tuple = NULL; + struct ui_out *uiout = current_uiout; + struct ui_stream *stb = ui_out_stream_new (uiout); + + gdb_assert (!arg->val || !arg->error); + gdb_assert ((values == PRINT_NO_VALUES && arg->val == NULL + && arg->error == NULL) + || values == PRINT_SIMPLE_VALUES + || (values == PRINT_ALL_VALUES + && (arg->val != NULL || arg->error != NULL))); + gdb_assert (arg->entry_kind == print_entry_values_no + || (arg->entry_kind == print_entry_values_only + && (arg->val || arg->error))); + + if (values != PRINT_NO_VALUES || what == all) + cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + fputs_filtered (SYMBOL_PRINT_NAME (arg->sym), stb->stream); + if (arg->entry_kind == print_entry_values_only) + fputs_filtered ("@entry", stb->stream); + ui_out_field_stream (uiout, "name", stb); + + if (what == all && SYMBOL_IS_ARGUMENT (arg->sym)) + ui_out_field_int (uiout, "arg", 1); + + if (values == PRINT_SIMPLE_VALUES) + { + check_typedef (arg->sym->type); + type_print (arg->sym->type, "", stb->stream, -1); + ui_out_field_stream (uiout, "type", stb); + } + + if (arg->val || arg->error) + { + volatile struct gdb_exception except; + + if (arg->error) + except.message = arg->error; + else + { + /* TRY_CATCH has two statements, wrap it in a block. */ + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + struct value_print_options opts; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + common_val_print (arg->val, stb->stream, 0, &opts, + language_def (SYMBOL_LANGUAGE (arg->sym))); + } + } + if (except.message) + fprintf_filtered (stb->stream, _(""), + except.message); + ui_out_field_stream (uiout, "value", stb); + } + + ui_out_stream_delete (stb); + if (values != PRINT_NO_VALUES || what == all) + do_cleanups (cleanup_tuple); +} /* Print a list of the locals or the arguments for the currently selected frame. If the argument passed is 0, printonly the names of the variables, if an argument of 1 is passed, print the values as well. */ static void -list_args_or_locals (enum what_to_list what, int values, struct frame_info *fi) +list_args_or_locals (enum what_to_list what, enum print_values values, + struct frame_info *fi) { struct block *block; struct symbol *sym; struct dict_iterator iter; struct cleanup *cleanup_list; - static struct ui_stream *stb = NULL; + struct ui_stream *stb; struct type *type; char *name_of_result; + struct ui_out *uiout = current_uiout; stb = ui_out_stream_new (uiout); @@ -309,16 +385,8 @@ list_args_or_locals (enum what_to_list what, int values, struct frame_info *fi) } if (print_me) { - struct cleanup *cleanup_tuple = NULL; struct symbol *sym2; - struct value *val; - - if (values != PRINT_NO_VALUES || what == all) - cleanup_tuple = - make_cleanup_ui_out_tuple_begin_end (uiout, NULL); - ui_out_field_string (uiout, "name", SYMBOL_PRINT_NAME (sym)); - if (what == all && SYMBOL_IS_ARGUMENT (sym)) - ui_out_field_int (uiout, "arg", 1); + struct frame_arg arg, entryarg; if (SYMBOL_IS_ARGUMENT (sym)) sym2 = lookup_symbol (SYMBOL_NATURAL_NAME (sym), @@ -326,64 +394,34 @@ list_args_or_locals (enum what_to_list what, int values, struct frame_info *fi) (int *) NULL); else sym2 = sym; + + memset (&arg, 0, sizeof (arg)); + arg.sym = sym2; + arg.entry_kind = print_entry_values_no; + memset (&entryarg, 0, sizeof (entryarg)); + entryarg.sym = sym2; + entryarg.entry_kind = print_entry_values_no; + switch (values) { case PRINT_SIMPLE_VALUES: type = check_typedef (sym2->type); - type_print (sym2->type, "", stb->stream, -1); - ui_out_field_stream (uiout, "type", stb); if (TYPE_CODE (type) != TYPE_CODE_ARRAY && TYPE_CODE (type) != TYPE_CODE_STRUCT && TYPE_CODE (type) != TYPE_CODE_UNION) { - volatile struct gdb_exception except; - - TRY_CATCH (except, RETURN_MASK_ERROR) - { - struct value_print_options opts; - - val = read_var_value (sym2, fi); - get_raw_print_options (&opts); - opts.deref_ref = 1; - common_val_print - (val, stb->stream, 0, &opts, - language_def (SYMBOL_LANGUAGE (sym2))); - } - if (except.reason < 0) - fprintf_filtered (stb->stream, - _(""), - except.message); - - ui_out_field_stream (uiout, "value", stb); - } - break; case PRINT_ALL_VALUES: - { - volatile struct gdb_exception except; - - TRY_CATCH (except, RETURN_MASK_ERROR) - { - struct value_print_options opts; - - val = read_var_value (sym2, fi); - get_raw_print_options (&opts); - opts.deref_ref = 1; - common_val_print - (val, stb->stream, 0, &opts, - language_def (SYMBOL_LANGUAGE (sym2))); - } - if (except.reason < 0) - fprintf_filtered (stb->stream, - _(""), - except.message); - - ui_out_field_stream (uiout, "value", stb); - } + read_frame_arg (sym2, fi, &arg, &entryarg); + } break; } - if (values != PRINT_NO_VALUES || what == all) - do_cleanups (cleanup_tuple); + if (arg.entry_kind != print_entry_values_only) + list_arg_or_local (&arg, what, values); + if (entryarg.entry_kind != print_entry_values_no) + list_arg_or_local (&entryarg, what, values); + xfree (arg.error); + xfree (entryarg.error); } } if (BLOCK_FUNCTION (block)) diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-target.c b/contrib/gdb-7/gdb/mi/mi-cmd-target.c index 295a38bd4b..edeedaf527 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-target.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-target.c @@ -1,5 +1,5 @@ /* MI Command Set - target commands. - Copyright (C) 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -29,11 +29,11 @@ mi_cmd_target_file_get (char *command, char **argv, int argc) int optind = 0; char *optarg; const char *remote_file, *local_file; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { { 0, 0, 0 } }; - static const char *prefix = "-target-file-get"; + static const char prefix[] = "-target-file-get"; if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) != -1 || optind != argc - 2) @@ -53,11 +53,11 @@ mi_cmd_target_file_put (char *command, char **argv, int argc) int optind = 0; char *optarg; const char *remote_file, *local_file; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { { 0, 0, 0 } }; - static const char *prefix = "-target-file-put"; + static const char prefix[] = "-target-file-put"; if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) != -1 || optind != argc - 2) @@ -77,11 +77,11 @@ mi_cmd_target_file_delete (char *command, char **argv, int argc) int optind = 0; char *optarg; const char *remote_file; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { { 0, 0, 0 } }; - static const char *prefix = "-target-file-delete"; + static const char prefix[] = "-target-file-delete"; if (mi_getopt (prefix, argc, argv, opts, &optind, &optarg) != -1 || optind != argc - 1) diff --git a/contrib/gdb-7/gdb/mi/mi-cmd-var.c b/contrib/gdb-7/gdb/mi/mi-cmd-var.c index a40184680d..1bc7144a76 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmd-var.c +++ b/contrib/gdb-7/gdb/mi/mi-cmd-var.c @@ -1,7 +1,7 @@ /* MI Command Set - varobj commands. - Copyright (C) 2000, 2002, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2002, 2004-2005, 2007-2012 Free Software + Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -51,6 +51,7 @@ static void print_varobj (struct varobj *var, enum print_values print_values, int print_expression) { + struct ui_out *uiout = current_uiout; char *type; int thread_id; char *display_hint; @@ -98,6 +99,7 @@ print_varobj (struct varobj *var, enum print_values print_values, void mi_cmd_var_create (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; CORE_ADDR frameaddr = 0; struct varobj *var; char *name; @@ -167,6 +169,7 @@ mi_cmd_var_delete (char *command, char **argv, int argc) int numdel; int children_only_p = 0; struct cleanup *old_cleanups; + struct ui_out *uiout = current_uiout; if (argc < 1 || argc > 2) error (_("-var-delete: Usage: [-c] EXPRESSION.")); @@ -196,7 +199,7 @@ mi_cmd_var_delete (char *command, char **argv, int argc) children_only_p = 1; do_cleanups (old_cleanups); name = xstrdup (argv[1]); - make_cleanup (free_current_contents, &name); + old_cleanups = make_cleanup (free_current_contents, &name); } /* If we didn't error out, now NAME contains the name of the @@ -244,6 +247,7 @@ mi_cmd_var_set_format (char *command, char **argv, int argc) enum varobj_display_formats format; struct varobj *var; char *val; + struct ui_out *uiout = current_uiout; if (argc != 2) error (_("-var-set-format: Usage: NAME FORMAT.")); @@ -310,6 +314,7 @@ mi_cmd_var_set_frozen (char *command, char **argv, int argc) void mi_cmd_var_show_format (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; enum varobj_display_formats format; struct varobj *var; @@ -328,6 +333,7 @@ mi_cmd_var_show_format (char *command, char **argv, int argc) void mi_cmd_var_info_num_children (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct varobj *var; if (argc != 1) @@ -394,6 +400,7 @@ mi_print_value_p (struct varobj *var, enum print_values print_values) void mi_cmd_var_list_children (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct varobj *var; VEC(varobj_p) *children; struct varobj *child; @@ -466,6 +473,7 @@ mi_cmd_var_list_children (char *command, char **argv, int argc) void mi_cmd_var_info_type (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct varobj *var; if (argc != 1) @@ -480,6 +488,7 @@ mi_cmd_var_info_type (char *command, char **argv, int argc) void mi_cmd_var_info_path_expression (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct varobj *var; char *path_expr; @@ -497,6 +506,7 @@ mi_cmd_var_info_path_expression (char *command, char **argv, int argc) void mi_cmd_var_info_expression (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; enum varobj_languages lang; struct varobj *var; @@ -515,6 +525,7 @@ mi_cmd_var_info_expression (char *command, char **argv, int argc) void mi_cmd_var_show_attributes (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; int attr; char *attstr; struct varobj *var; @@ -538,6 +549,7 @@ mi_cmd_var_show_attributes (char *command, char **argv, int argc) void mi_cmd_var_evaluate_expression (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct varobj *var; enum varobj_display_formats format; @@ -549,7 +561,7 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc) { OP_FORMAT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"f", OP_FORMAT, 1}, { 0, 0, 0 } @@ -606,6 +618,7 @@ mi_cmd_var_evaluate_expression (char *command, char **argv, int argc) void mi_cmd_var_assign (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct varobj *var; char *expression, *val; @@ -667,6 +680,7 @@ mi_cmd_var_update_iter (struct varobj *var, void *data_pointer) void mi_cmd_var_update (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct cleanup *cleanup; char *name; enum print_values print_values; @@ -722,6 +736,7 @@ static void varobj_update_one (struct varobj *var, enum print_values print_values, int explicit) { + struct ui_out *uiout = current_uiout; struct cleanup *cleanup = NULL; VEC (varobj_update_result) *changes; varobj_update_result *r; diff --git a/contrib/gdb-7/gdb/mi/mi-cmds.c b/contrib/gdb-7/gdb/mi/mi-cmds.c index 0b32db0c9a..81648a7bdc 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmds.c +++ b/contrib/gdb-7/gdb/mi/mi-cmds.c @@ -1,7 +1,7 @@ /* MI Command Set for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2003, 2007-2012 Free Software Foundation, + Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -33,6 +33,7 @@ static void build_table (struct mi_cmd *commands); struct mi_cmd mi_cmds[] = { + { "ada-task-info", { NULL, 0 }, mi_cmd_ada_task_info }, { "add-inferior", { NULL, 0 }, mi_cmd_add_inferior }, { "break-after", { "ignore", 1 }, NULL }, { "break-condition", { "cond", 1 }, NULL }, diff --git a/contrib/gdb-7/gdb/mi/mi-cmds.h b/contrib/gdb-7/gdb/mi/mi-cmds.h index 18b4ad7d3b..309a3cede7 100644 --- a/contrib/gdb-7/gdb/mi/mi-cmds.h +++ b/contrib/gdb-7/gdb/mi/mi-cmds.h @@ -1,7 +1,7 @@ /* MI Command Set for GDB, the GNU debugger. - Copyright (C) 2000, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2003-2005, 2007-2012 Free Software Foundation, + Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -36,6 +36,7 @@ extern const char mi_all_values[]; typedef void (mi_cmd_argv_ftype) (char *command, char **argv, int argc); /* Function implementing each command */ +extern mi_cmd_argv_ftype mi_cmd_ada_task_info; extern mi_cmd_argv_ftype mi_cmd_add_inferior; extern mi_cmd_argv_ftype mi_cmd_break_insert; extern mi_cmd_argv_ftype mi_cmd_break_commands; diff --git a/contrib/gdb-7/gdb/mi/mi-common.c b/contrib/gdb-7/gdb/mi/mi-common.c index ab126f6b85..1eaa99011b 100644 --- a/contrib/gdb-7/gdb/mi/mi-common.c +++ b/contrib/gdb-7/gdb/mi/mi-common.c @@ -1,6 +1,5 @@ /* Interface for common GDB/MI data - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +17,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "gdb_assert.h" #include "mi-common.h" static const char * const async_reason_string_lookup[] = @@ -34,22 +34,19 @@ static const char * const async_reason_string_lookup[] = "exited", "exited-normally", "signal-received", + "solib-event", + "fork", + "vfork", + "syscall-entry", + "syscall-return", + "exec", NULL }; +static_assert (ARRAY_SIZE (async_reason_string_lookup) == EXEC_ASYNC_LAST + 1); + const char * async_reason_lookup (enum async_reply_reason reason) { return async_reason_string_lookup[reason]; } - -/* Provide a prototype to silence -Wmissing-prototypes. */ -extern initialize_file_ftype _initialize_gdb_mi_common; - -void -_initialize_gdb_mi_common (void) -{ - if (ARRAY_SIZE (async_reason_string_lookup) != EXEC_ASYNC_LAST + 1) - internal_error (__FILE__, __LINE__, - _("async_reason_string_lookup is inconsistent")); -} diff --git a/contrib/gdb-7/gdb/mi/mi-common.h b/contrib/gdb-7/gdb/mi/mi-common.h index e3aab7d785..d7f459cb5f 100644 --- a/contrib/gdb-7/gdb/mi/mi-common.h +++ b/contrib/gdb-7/gdb/mi/mi-common.h @@ -1,6 +1,5 @@ /* Interface for common GDB/MI data - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -37,6 +36,12 @@ enum async_reply_reason EXEC_ASYNC_EXITED, EXEC_ASYNC_EXITED_NORMALLY, EXEC_ASYNC_SIGNAL_RECEIVED, + EXEC_ASYNC_SOLIB_EVENT, + EXEC_ASYNC_FORK, + EXEC_ASYNC_VFORK, + EXEC_ASYNC_SYSCALL_ENTRY, + EXEC_ASYNC_SYSCALL_RETURN, + EXEC_ASYNC_EXEC, /* This is here only to represent the number of enums. */ EXEC_ASYNC_LAST }; @@ -52,6 +57,9 @@ struct mi_interp struct ui_file *targ; struct ui_file *event_channel; + /* MI's builder. */ + struct ui_out *uiout; + /* This is the interpreter for the mi... */ struct interp *mi2_interp; struct interp *mi1_interp; diff --git a/contrib/gdb-7/gdb/mi/mi-console.c b/contrib/gdb-7/gdb/mi/mi-console.c index df64b6cc4e..6b4601b224 100644 --- a/contrib/gdb-7/gdb/mi/mi-console.c +++ b/contrib/gdb-7/gdb/mi/mi-console.c @@ -1,7 +1,6 @@ /* MI Console code. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). diff --git a/contrib/gdb-7/gdb/mi/mi-console.h b/contrib/gdb-7/gdb/mi/mi-console.h index f5dfadcdc4..9727eb6c79 100644 --- a/contrib/gdb-7/gdb/mi/mi-console.h +++ b/contrib/gdb-7/gdb/mi/mi-console.h @@ -1,6 +1,5 @@ /* MI Command Set - MI Console. - Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-getopt.c b/contrib/gdb-7/gdb/mi/mi-getopt.c index 81b833a30b..2e288a29c0 100644 --- a/contrib/gdb-7/gdb/mi/mi-getopt.c +++ b/contrib/gdb-7/gdb/mi/mi-getopt.c @@ -1,6 +1,5 @@ /* MI Command Set - MI Option Parser. - Copyright (C) 2000, 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -25,11 +24,11 @@ int mi_getopt (const char *prefix, int argc, char **argv, - struct mi_opt *opts, + const struct mi_opt *opts, int *optind, char **optarg) { char *arg; - struct mi_opt *opt; + const struct mi_opt *opt; /* We assume that argv/argc are ok. */ if (*optind > argc || *optind < 0) @@ -80,7 +79,7 @@ mi_valid_noargs (const char *prefix, int argc, char **argv) { int optind = 0; char *optarg; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { { 0, 0, 0 } }; diff --git a/contrib/gdb-7/gdb/mi/mi-getopt.h b/contrib/gdb-7/gdb/mi/mi-getopt.h index a34a354e45..ea09b44070 100644 --- a/contrib/gdb-7/gdb/mi/mi-getopt.h +++ b/contrib/gdb-7/gdb/mi/mi-getopt.h @@ -1,6 +1,5 @@ /* MI Option Parser. - Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. @@ -42,7 +41,7 @@ struct mi_opt; extern int mi_getopt (const char *prefix, int argc, char **argv, - struct mi_opt *opt, int *optind, char **optarg); + const struct mi_opt *opt, int *optind, char **optarg); /* The option list. Terminated by NAME==NULL. ARG_P that the option requires an argument. INDEX is returned to identify th option. */ diff --git a/contrib/gdb-7/gdb/mi/mi-interp.c b/contrib/gdb-7/gdb/mi/mi-interp.c index 5e01abc7a1..c9cd24d676 100644 --- a/contrib/gdb-7/gdb/mi/mi-interp.c +++ b/contrib/gdb-7/gdb/mi/mi-interp.c @@ -1,7 +1,6 @@ /* MI Interpreter Definitions and Commands for GDB, the GNU debugger. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -35,6 +34,7 @@ #include "observer.h" #include "gdbthread.h" #include "solist.h" +#include "gdb.h" /* These are the interpreter setup, etc. functions for the MI interpreter */ static void mi_execute_command_wrapper (char *cmd); @@ -64,13 +64,18 @@ static void mi_on_resume (ptid_t ptid); static void mi_solib_loaded (struct so_list *solib); static void mi_solib_unloaded (struct so_list *solib); static void mi_about_to_proceed (void); +static void mi_breakpoint_created (struct breakpoint *b); +static void mi_breakpoint_deleted (struct breakpoint *b); +static void mi_breakpoint_modified (struct breakpoint *b); static int report_initial_inferior (struct inferior *inf, void *closure); static void * -mi_interpreter_init (int top_level) +mi_interpreter_init (struct interp *interp, int top_level) { struct mi_interp *mi = XMALLOC (struct mi_interp); + const char *name; + int mi_version; /* HACK: We need to force stdout/stderr to point at the console. This avoids any potential side effects caused by legacy code that is still @@ -86,6 +91,22 @@ mi_interpreter_init (int top_level) mi->targ = mi_console_file_new (raw_stdout, "@", '"'); mi->event_channel = mi_console_file_new (raw_stdout, "=", 0); + name = interp_name (interp); + /* INTERP_MI selects the most recent released version. "mi2" was + released as part of GDB 6.0. */ + if (strcmp (name, INTERP_MI) == 0) + mi_version = 2; + else if (strcmp (name, INTERP_MI1) == 0) + mi_version = 1; + else if (strcmp (name, INTERP_MI2) == 0) + mi_version = 2; + else if (strcmp (name, INTERP_MI3) == 0) + mi_version = 3; + else + gdb_assert_not_reached ("unhandled MI version"); + + mi->uiout = mi_out_new (mi_version); + if (top_level) { observer_attach_new_thread (mi_new_thread); @@ -99,6 +120,9 @@ mi_interpreter_init (int top_level) observer_attach_solib_loaded (mi_solib_loaded); observer_attach_solib_unloaded (mi_solib_unloaded); observer_attach_about_to_proceed (mi_about_to_proceed); + observer_attach_breakpoint_created (mi_breakpoint_created); + observer_attach_breakpoint_deleted (mi_breakpoint_deleted); + observer_attach_breakpoint_modified (mi_breakpoint_modified); /* The initial inferior is created before this function is called, so we need to report it explicitly. Use iteration in case future version @@ -394,18 +418,24 @@ mi_on_normal_stop (struct bpstats *bs, int print_frame) { int core; - if (uiout != mi_uiout) + if (current_uiout != mi_uiout) { /* The normal_stop function has printed frame information into CLI uiout, or some other non-MI uiout. There's no way we can extract proper fields from random uiout object, so we print the frame again. In practice, this can only happen when running a CLI command in MI. */ - struct ui_out *saved_uiout = uiout; + struct ui_out *saved_uiout = current_uiout; + struct target_waitstatus last; + ptid_t last_ptid; + + current_uiout = mi_uiout; + + get_last_target_status (&last_ptid, &last); + bpstat_print (bs, last.kind); - uiout = mi_uiout; print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC); - uiout = saved_uiout; + current_uiout = saved_uiout; } ui_out_field_int (mi_uiout, "thread-id", @@ -451,6 +481,95 @@ mi_about_to_proceed (void) mi_proceeded = 1; } +/* When non-zero, no MI notifications will be emitted in + response to breakpoint change observers. */ +int mi_suppress_breakpoint_notifications = 0; + +/* Emit notification about a created breakpoint. */ +static void +mi_breakpoint_created (struct breakpoint *b) +{ + struct mi_interp *mi = top_level_interpreter_data (); + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); + struct gdb_exception e; + + if (mi_suppress_breakpoint_notifications) + return; + + if (b->number <= 0) + return; + + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "breakpoint-created"); + /* We want the output from gdb_breakpoint_query to go to + mi->event_channel. One approach would be to just + call gdb_breakpoint_query, and then use mi_out_put to + send the current content of mi_outout into mi->event_channel. + However, that will break if anything is output to mi_uiout + prior the calling the breakpoint_created notifications. + So, we use ui_out_redirect. */ + ui_out_redirect (mi_uiout, mi->event_channel); + TRY_CATCH (e, RETURN_MASK_ERROR) + gdb_breakpoint_query (mi_uiout, b->number, NULL); + ui_out_redirect (mi_uiout, NULL); + + gdb_flush (mi->event_channel); +} + +/* Emit notification about deleted breakpoint. */ +static void +mi_breakpoint_deleted (struct breakpoint *b) +{ + struct mi_interp *mi = top_level_interpreter_data (); + + if (mi_suppress_breakpoint_notifications) + return; + + if (b->number <= 0) + return; + + target_terminal_ours (); + + fprintf_unfiltered (mi->event_channel, "breakpoint-deleted,id=\"%d\"", + b->number); + + gdb_flush (mi->event_channel); +} + +/* Emit notification about modified breakpoint. */ +static void +mi_breakpoint_modified (struct breakpoint *b) +{ + struct mi_interp *mi = top_level_interpreter_data (); + struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ()); + struct gdb_exception e; + + if (mi_suppress_breakpoint_notifications) + return; + + if (b->number <= 0) + return; + + target_terminal_ours (); + fprintf_unfiltered (mi->event_channel, + "breakpoint-modified"); + /* We want the output from gdb_breakpoint_query to go to + mi->event_channel. One approach would be to just + call gdb_breakpoint_query, and then use mi_out_put to + send the current content of mi_outout into mi->event_channel. + However, that will break if anything is output to mi_uiout + prior the calling the breakpoint_created notifications. + So, we use ui_out_redirect. */ + ui_out_redirect (mi_uiout, mi->event_channel); + TRY_CATCH (e, RETURN_MASK_ERROR) + gdb_breakpoint_query (mi_uiout, b->number, NULL); + ui_out_redirect (mi_uiout, NULL); + + gdb_flush (mi->event_channel); +} + + static int mi_output_running_pid (struct thread_info *info, void *arg) { @@ -605,6 +724,14 @@ report_initial_inferior (struct inferior *inf, void *closure) return 0; } +static struct ui_out * +mi_ui_out (struct interp *interp) +{ + struct mi_interp *mi = interp_data (interp); + + return mi->uiout; +} + extern initialize_file_ftype _initialize_mi_interp; /* -Wmissing-prototypes */ void @@ -616,15 +743,13 @@ _initialize_mi_interp (void) mi_interpreter_resume, /* resume_proc */ mi_interpreter_suspend, /* suspend_proc */ mi_interpreter_exec, /* exec_proc */ - mi_interpreter_prompt_p /* prompt_proc_p */ + mi_interpreter_prompt_p, /* prompt_proc_p */ + mi_ui_out /* ui_out_proc */ }; /* The various interpreter levels. */ - interp_add (interp_new (INTERP_MI1, NULL, mi_out_new (1), &procs)); - interp_add (interp_new (INTERP_MI2, NULL, mi_out_new (2), &procs)); - interp_add (interp_new (INTERP_MI3, NULL, mi_out_new (3), &procs)); - - /* "mi" selects the most recent released version. "mi2" was - released as part of GDB 6.0. */ - interp_add (interp_new (INTERP_MI, NULL, mi_out_new (2), &procs)); + interp_add (interp_new (INTERP_MI1, &procs)); + interp_add (interp_new (INTERP_MI2, &procs)); + interp_add (interp_new (INTERP_MI3, &procs)); + interp_add (interp_new (INTERP_MI, &procs)); } diff --git a/contrib/gdb-7/gdb/mi/mi-main.c b/contrib/gdb-7/gdb/mi/mi-main.c index ef6bfc3013..b170f01ab4 100644 --- a/contrib/gdb-7/gdb/mi/mi-main.c +++ b/contrib/gdb-7/gdb/mi/mi-main.c @@ -1,7 +1,6 @@ /* MI Command Set. - Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 2000-2005, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -52,6 +51,8 @@ #include "osdata.h" #include "splay-tree.h" #include "tracepoint.h" +#include "ada-lang.h" +#include "linespec.h" #include #include @@ -117,7 +118,7 @@ mi_cmd_gdb_exit (char *command, char **argv, int argc) if (current_token) fputs_unfiltered (current_token, raw_stdout); fputs_unfiltered ("^exit\n", raw_stdout); - mi_out_put (uiout, raw_stdout); + mi_out_put (current_uiout, raw_stdout); gdb_flush (raw_stdout); /* FIXME: The function called is not yet a formal libgdb function. */ quit_force (NULL, FROM_TTY); @@ -285,9 +286,6 @@ exec_reverse_continue (char **argv, int argc) enum exec_direction_kind dir = execution_direction; struct cleanup *old_chain; - if (dir == EXEC_ERROR) - error (_("Target %s does not support this command."), target_shortname); - if (dir == EXEC_REVERSE) error (_("Already in reverse mode.")); @@ -473,7 +471,7 @@ mi_cmd_thread_select (char *command, char **argv, int argc) if (argc != 1) error (_("-thread-select: USAGE: threadnum.")); - rc = gdb_thread_select (uiout, argv[0], &mi_error_message); + rc = gdb_thread_select (current_uiout, argv[0], &mi_error_message); if (rc == GDB_RC_FAIL) { @@ -491,7 +489,7 @@ mi_cmd_thread_list_ids (char *command, char **argv, int argc) if (argc != 0) error (_("-thread-list-ids: No arguments required.")); - rc = gdb_list_thread_ids (uiout, &mi_error_message); + rc = gdb_list_thread_ids (current_uiout, &mi_error_message); if (rc == GDB_RC_FAIL) { @@ -506,7 +504,7 @@ mi_cmd_thread_info (char *command, char **argv, int argc) if (argc != 0 && argc != 1) error (_("Invalid MI command")); - print_thread_info (uiout, argv[0], -1); + print_thread_info (current_uiout, argv[0], -1); } struct collect_cores_data @@ -553,6 +551,7 @@ static int print_one_inferior (struct inferior *inferior, void *xdata) { struct print_one_inferior_data *top_data = xdata; + struct ui_out *uiout = current_uiout; if (VEC_empty (int, top_data->inferiors) || bsearch (&(inferior->pid), VEC_address (int, top_data->inferiors), @@ -673,6 +672,7 @@ list_available_thread_groups (VEC (int) *ids, int recurse) struct osdata *data; struct osdata_item *item; int ix_items; + struct ui_out *uiout = current_uiout; /* This keeps a map from integer (pid) to VEC (struct osdata_item *)* The vector contains information about all threads for the given pid. @@ -790,6 +790,7 @@ list_available_thread_groups (VEC (int) *ids, int recurse) void mi_cmd_list_thread_groups (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct cleanup *back_to; int available = 0; int recurse = 0; @@ -799,7 +800,7 @@ mi_cmd_list_thread_groups (char *command, char **argv, int argc) { AVAILABLE_OPT, RECURSE_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"-available", AVAILABLE_OPT, 0}, {"-recurse", RECURSE_OPT, 1}, @@ -892,6 +893,7 @@ void mi_cmd_data_list_register_names (char *command, char **argv, int argc) { struct gdbarch *gdbarch; + struct ui_out *uiout = current_uiout; int regnum, numregs; int i; struct cleanup *cleanup; @@ -943,6 +945,7 @@ void mi_cmd_data_list_changed_registers (char *command, char **argv, int argc) { static struct regcache *this_regs = NULL; + struct ui_out *uiout = current_uiout; struct regcache *prev_regs; struct gdbarch *gdbarch; int regnum, numregs, changed; @@ -1047,6 +1050,7 @@ register_changed_p (int regnum, struct regcache *prev_regs, void mi_cmd_data_list_register_values (char *command, char **argv, int argc) { + struct ui_out *uiout = current_uiout; struct frame_info *frame; struct gdbarch *gdbarch; int regnum, numregs, format; @@ -1113,9 +1117,10 @@ static void get_register (struct frame_info *frame, int regnum, int format) { struct gdbarch *gdbarch = get_frame_arch (frame); + struct ui_out *uiout = current_uiout; CORE_ADDR addr; enum lval_type lval; - static struct ui_stream *stb = NULL; + struct ui_stream *stb; struct value *val; stb = ui_out_stream_new (uiout); @@ -1232,6 +1237,7 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc) struct value *val; struct ui_stream *stb = NULL; struct value_print_options opts; + struct ui_out *uiout = current_uiout; stb = ui_out_stream_new (uiout); @@ -1282,6 +1288,7 @@ void mi_cmd_data_read_memory (char *command, char **argv, int argc) { struct gdbarch *gdbarch = get_current_arch (); + struct ui_out *uiout = current_uiout; struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); CORE_ADDR addr; long total_bytes; @@ -1301,7 +1308,7 @@ mi_cmd_data_read_memory (char *command, char **argv, int argc) { OFFSET_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"o", OFFSET_OPT, 1}, { 0, 0, 0 } @@ -1473,6 +1480,7 @@ void mi_cmd_data_read_memory_bytes (char *command, char **argv, int argc) { struct gdbarch *gdbarch = get_current_arch (); + struct ui_out *uiout = current_uiout; struct cleanup *cleanups; CORE_ADDR addr; LONGEST length; @@ -1486,7 +1494,7 @@ mi_cmd_data_read_memory_bytes (char *command, char **argv, int argc) { OFFSET_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"o", OFFSET_OPT, 1}, { 0, 0, 0 } @@ -1553,7 +1561,7 @@ mi_cmd_data_read_memory_bytes (char *command, char **argv, int argc) /* DATA-MEMORY-WRITE: - COLUMN_OFFSET: optional argument. Must be preceeded by '-o'. The + COLUMN_OFFSET: optional argument. Must be preceded by '-o'. The offset from the beginning of the memory grid row where the cell to be written is. ADDR: start address of the row in the memory grid where the memory @@ -1587,7 +1595,7 @@ mi_cmd_data_write_memory (char *command, char **argv, int argc) { OFFSET_OPT }; - static struct mi_opt opts[] = + static const struct mi_opt opts[] = { {"o", OFFSET_OPT, 1}, { 0, 0, 0 } @@ -1705,12 +1713,15 @@ mi_cmd_list_features (char *command, char **argv, int argc) if (argc == 0) { struct cleanup *cleanup = NULL; + struct ui_out *uiout = current_uiout; cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features"); ui_out_field_string (uiout, NULL, "frozen-varobjs"); ui_out_field_string (uiout, NULL, "pending-breakpoints"); ui_out_field_string (uiout, NULL, "thread-info"); ui_out_field_string (uiout, NULL, "data-read-memory-bytes"); + ui_out_field_string (uiout, NULL, "breakpoint-notifications"); + ui_out_field_string (uiout, NULL, "ada-task-info"); #if HAVE_PYTHON ui_out_field_string (uiout, NULL, "python"); @@ -1729,6 +1740,7 @@ mi_cmd_list_target_features (char *command, char **argv, int argc) if (argc == 0) { struct cleanup *cleanup = NULL; + struct ui_out *uiout = current_uiout; cleanup = make_cleanup_ui_out_list_begin_end (uiout, "features"); if (target_can_async_p ()) @@ -1753,7 +1765,7 @@ mi_cmd_add_inferior (char *command, char **argv, int argc) inf = add_inferior_with_spaces (); - ui_out_field_fmt (uiout, "inferior", "i%d", inf->num); + ui_out_field_fmt (current_uiout, "inferior", "i%d", inf->num); } /* Callback used to find the first inferior other than the @@ -1816,10 +1828,9 @@ mi_cmd_remove_inferior (char *command, char **argv, int argc) prompt, display error). */ static void -captured_mi_execute_command (struct ui_out *uiout, void *data) +captured_mi_execute_command (struct ui_out *uiout, struct mi_parse *context) { struct cleanup *cleanup; - struct mi_parse *context = (struct mi_parse *) data; if (do_timings) current_command_ts = context->cmd_start; @@ -1947,7 +1958,7 @@ mi_execute_command (char *cmd, int from_tty) } else { - struct gdb_exception result; + volatile struct gdb_exception result; ptid_t previous_ptid = inferior_ptid; command->token = token; @@ -1959,14 +1970,16 @@ mi_execute_command (char *cmd, int from_tty) timestamp (command->cmd_start); } - result = catch_exception (uiout, captured_mi_execute_command, command, - RETURN_MASK_ALL); + TRY_CATCH (result, RETURN_MASK_ALL) + { + captured_mi_execute_command (current_uiout, command); + } if (result.reason < 0) { /* The command execution failed and error() was called somewhere. */ mi_print_exception (command->token, result); - mi_out_rewind (uiout); + mi_out_rewind (current_uiout); } bpstat_do_actions (); @@ -2024,9 +2037,7 @@ mi_cmd_execute (struct mi_parse *parse) { struct cleanup *cleanup; - prepare_execute_command (); - - cleanup = make_cleanup (null_cleanup, NULL); + cleanup = prepare_execute_command (); if (parse->all && parse->thread_group != -1) error (_("Cannot specify --thread-group together with --all")); @@ -2054,7 +2065,7 @@ mi_cmd_execute (struct mi_parse *parse) This is not a problem -- frontend should always provide --thread if it wishes to operate on a specific thread. */ if (inf->pid != 0) - tp = any_thread_of_process (inf->pid); + tp = any_live_thread_of_process (inf->pid); switch_to_thread (tp ? tp->ptid : null_ptid); set_current_program_space (inf->pspace); } @@ -2087,8 +2098,16 @@ mi_cmd_execute (struct mi_parse *parse) current_context = parse; + if (strncmp (parse->command, "break-", sizeof ("break-") - 1 ) == 0) + { + make_cleanup_restore_integer (&mi_suppress_breakpoint_notifications); + mi_suppress_breakpoint_notifications = 1; + } + if (parse->cmd->argv_func != NULL) - parse->cmd->argv_func (parse->command, parse->argv, parse->argc); + { + parse->cmd->argv_func (parse->command, parse->argv, parse->argc); + } else if (parse->cmd->cli.cmd != 0) { /* FIXME: DELETE THIS. */ @@ -2155,18 +2174,9 @@ mi_execute_async_cli_command (char *cli_command, char **argv, int argc) execute_command ( /*ui */ run, 0 /*from_tty */ ); - if (target_can_async_p ()) - { - /* If we're not executing, an exception should have been throw. */ - gdb_assert (is_running (inferior_ptid)); - do_cleanups (old_cleanups); - } - else - { - /* Do this before doing any printing. It would appear that some - print code leaves garbage around in the buffer. */ - do_cleanups (old_cleanups); - } + /* Do this before doing any printing. It would appear that some + print code leaves garbage around in the buffer. */ + do_cleanups (old_cleanups); } void @@ -2181,22 +2191,25 @@ mi_load_progress (const char *section_name, static char *previous_sect_name = NULL; int new_section; struct ui_out *saved_uiout; + struct ui_out *uiout; /* This function is called through deprecated_show_load_progress which means uiout may not be correct. Fix it for the duration of this function. */ - saved_uiout = uiout; + saved_uiout = current_uiout; if (current_interp_named_p (INTERP_MI) || current_interp_named_p (INTERP_MI2)) - uiout = mi_out_new (2); + current_uiout = mi_out_new (2); else if (current_interp_named_p (INTERP_MI1)) - uiout = mi_out_new (1); + current_uiout = mi_out_new (1); else if (current_interp_named_p (INTERP_MI3)) - uiout = mi_out_new (3); + current_uiout = mi_out_new (3); else return; + uiout = current_uiout; + update_threshold.tv_sec = 0; update_threshold.tv_usec = 500000; gettimeofday (&time_now, NULL); @@ -2255,7 +2268,7 @@ mi_load_progress (const char *section_name, } xfree (uiout); - uiout = saved_uiout; + current_uiout = saved_uiout; } static void @@ -2424,7 +2437,7 @@ mi_cmd_trace_find (char *command, char **argv, int argc) if (argc != 2) error (_("Line is required")); - sals = decode_line_spec (argv[1], 1); + sals = decode_line_spec (argv[1], DECODE_LINE_FUNFIRSTLINE); back_to = make_cleanup (xfree, sals.sals); sal = sals.sals[0]; @@ -2477,7 +2490,7 @@ mi_cmd_trace_save (char *command, char **argv, int argc) void mi_cmd_trace_start (char *command, char **argv, int argc) { - start_tracing (); + start_tracing (NULL); } void @@ -2489,6 +2502,17 @@ mi_cmd_trace_status (char *command, char **argv, int argc) void mi_cmd_trace_stop (char *command, char **argv, int argc) { - stop_tracing (); + stop_tracing (NULL); trace_status_mi (1); } + +/* Implement the "-ada-task-info" GDB/MI command. */ + +void +mi_cmd_ada_task_info (char *command, char **argv, int argc) +{ + if (argc != 0 && argc != 1) + error (_("Invalid MI command")); + + print_ada_task_info (current_uiout, argv[0], current_inferior ()); +} diff --git a/contrib/gdb-7/gdb/mi/mi-main.h b/contrib/gdb-7/gdb/mi/mi-main.h index 3ad6d0f5a8..beac2cde97 100644 --- a/contrib/gdb-7/gdb/mi/mi-main.h +++ b/contrib/gdb-7/gdb/mi/mi-main.h @@ -1,7 +1,6 @@ /* MI Internal Functions for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -33,6 +32,7 @@ extern char *current_token; extern int running_result_record_printed; extern int mi_proceeded; +extern int mi_suppress_breakpoint_notifications; #endif diff --git a/contrib/gdb-7/gdb/mi/mi-out.c b/contrib/gdb-7/gdb/mi/mi-out.c index 9aaeec6654..f8f62257a9 100644 --- a/contrib/gdb-7/gdb/mi/mi-out.c +++ b/contrib/gdb-7/gdb/mi/mi-out.c @@ -1,7 +1,7 @@ /* MI Command Set - output generating routines. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2002-2005, 2007-2012 Free Software Foundation, + Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -30,6 +30,7 @@ struct ui_out_data int suppress_output; int mi_version; struct ui_file *buffer; + struct ui_file *original_buffer; }; typedef struct ui_out_data mi_out_data; @@ -63,6 +64,7 @@ static void mi_message (struct ui_out *uiout, int verbosity, ATTRIBUTE_PRINTF (3, 0); static void mi_wrap_hint (struct ui_out *uiout, char *identstring); static void mi_flush (struct ui_out *uiout); +static int mi_redirect (struct ui_out *uiout, struct ui_file *outstream); /* This is the MI ui-out implementation functions vector */ @@ -86,7 +88,7 @@ struct ui_out_impl mi_ui_out_impl = mi_message, mi_wrap_hint, mi_flush, - NULL, + mi_redirect, 1, /* Needs MI hacks. */ }; @@ -210,11 +212,6 @@ void mi_field_skip (struct ui_out *uiout, int fldno, int width, enum ui_align alignment, const char *fldname) { - mi_out_data *data = ui_out_data (uiout); - - if (data->suppress_output) - return; - mi_field_string (uiout, fldno, width, alignment, fldname, ""); } /* other specific mi_field_* end up here so alignment and field @@ -294,6 +291,25 @@ mi_flush (struct ui_out *uiout) gdb_flush (data->buffer); } +int +mi_redirect (struct ui_out *uiout, struct ui_file *outstream) +{ + mi_out_data *data = ui_out_data (uiout); + + if (outstream != NULL) + { + data->original_buffer = data->buffer; + data->buffer = outstream; + } + else if (data->original_buffer != NULL) + { + data->buffer = data->original_buffer; + data->original_buffer = NULL; + } + + return 0; +} + /* local functions */ /* access to ui_out format private members */ diff --git a/contrib/gdb-7/gdb/mi/mi-out.h b/contrib/gdb-7/gdb/mi/mi-out.h index 515aefa764..d8763ad566 100644 --- a/contrib/gdb-7/gdb/mi/mi-out.h +++ b/contrib/gdb-7/gdb/mi/mi-out.h @@ -1,6 +1,5 @@ /* MI Command Set - MI output generating routines for GDB. - Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-parse.c b/contrib/gdb-7/gdb/mi/mi-parse.c index fcaf151242..2fbfc382c1 100644 --- a/contrib/gdb-7/gdb/mi/mi-parse.c +++ b/contrib/gdb-7/gdb/mi/mi-parse.c @@ -1,7 +1,6 @@ /* MI Command Set - MI parser. - Copyright (C) 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). @@ -253,7 +252,7 @@ mi_parse (char *cmd, char **token) /* Find/skip any token and then extract it. */ for (chp = cmd; *chp >= '0' && *chp <= '9'; chp++) ; - *token = xmalloc ((chp - cmd + 1) * sizeof (char *)); + *token = xmalloc (chp - cmd + 1); memcpy (*token, cmd, (chp - cmd)); (*token)[chp - cmd] = '\0'; @@ -276,7 +275,7 @@ mi_parse (char *cmd, char **token) for (; *chp && !isspace (*chp); chp++) ; - parse->command = xmalloc ((chp - tmp + 1) * sizeof (char *)); + parse->command = xmalloc (chp - tmp + 1); memcpy (parse->command, tmp, chp - tmp); parse->command[chp - tmp] = '\0'; } diff --git a/contrib/gdb-7/gdb/mi/mi-parse.h b/contrib/gdb-7/gdb/mi/mi-parse.h index 91bc5a4115..59e57de5a7 100644 --- a/contrib/gdb-7/gdb/mi/mi-parse.h +++ b/contrib/gdb-7/gdb/mi/mi-parse.h @@ -1,6 +1,5 @@ /* MI Command Set - MI Command Parser. - Copyright (C) 2000, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions (a Red Hat company). This file is part of GDB. diff --git a/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c b/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c index 17ff8c361a..7feb02435d 100644 --- a/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c +++ b/contrib/gdb-7/gdb/mi/mi-symbol-cmds.c @@ -1,6 +1,5 @@ /* MI Command Set - symbol commands. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -37,6 +36,7 @@ mi_cmd_symbol_list_lines (char *command, char **argv, int argc) struct symtab *s; int i; struct cleanup *cleanup_stack, *cleanup_tuple; + struct ui_out *uiout = current_uiout; if (argc != 1) error (_("-symbol-list-lines: Usage: SOURCE_FILENAME")); diff --git a/contrib/gdb-7/gdb/minsyms.c b/contrib/gdb-7/gdb/minsyms.c index b054e3ff98..2aec6324d0 100644 --- a/contrib/gdb-7/gdb/minsyms.c +++ b/contrib/gdb-7/gdb/minsyms.c @@ -1,7 +1,5 @@ /* GDB routines for manipulating the minimal symbol tables. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-2004, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. This file is part of GDB. @@ -91,7 +89,7 @@ msymbol_hash_iw (const char *string) ++string; if (*string && *string != '(') { - hash = hash * 67 + *string - 113; + hash = SYMBOL_HASH_NEXT (hash, *string); ++string; } } @@ -106,7 +104,7 @@ msymbol_hash (const char *string) unsigned int hash = 0; for (; *string; ++string) - hash = hash * 67 + *string - 113; + hash = SYMBOL_HASH_NEXT (hash, *string); return hash; } @@ -239,11 +237,16 @@ lookup_minimal_symbol (const char *name, const char *sfile, if (pass == 1) { - match = strcmp (SYMBOL_LINKAGE_NAME (msymbol), - modified_name) == 0; + int (*cmp) (const char *, const char *); + + cmp = (case_sensitivity == case_sensitive_on + ? strcmp : strcasecmp); + match = cmp (SYMBOL_LINKAGE_NAME (msymbol), + modified_name) == 0; } else { + /* The function respects CASE_SENSITIVITY. */ match = SYMBOL_MATCHES_SEARCH_NAME (msymbol, modified_name); } @@ -305,6 +308,46 @@ lookup_minimal_symbol (const char *name, const char *sfile, return NULL; } +/* Iterate over all the minimal symbols in the objfile OBJF which + match NAME. Both the ordinary and demangled names of each symbol + are considered. The caller is responsible for canonicalizing NAME, + should that need to be done. + + For each matching symbol, CALLBACK is called with the symbol and + USER_DATA as arguments. */ + +void +iterate_over_minimal_symbols (struct objfile *objf, const char *name, + void (*callback) (struct minimal_symbol *, + void *), + void *user_data) +{ + unsigned int hash; + struct minimal_symbol *iter; + int (*cmp) (const char *, const char *); + + /* The first pass is over the ordinary hash table. */ + hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE; + iter = objf->msymbol_hash[hash]; + cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp); + while (iter) + { + if (cmp (SYMBOL_LINKAGE_NAME (iter), name) == 0) + (*callback) (iter, user_data); + iter = iter->hash_next; + } + + /* The second pass is over the demangled table. */ + hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE; + iter = objf->msymbol_demangled_hash[hash]; + while (iter) + { + if (SYMBOL_MATCHES_SEARCH_NAME (iter, name)) + (*callback) (iter, user_data); + iter = iter->demangled_hash_next; + } +} + /* Look through all the current minimal symbol tables 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 pointer @@ -578,7 +621,7 @@ lookup_minimal_symbol_by_pc_section_1 (CORE_ADDR pc, /* If we are looking for a trampoline and this is a text symbol, or the other way around, check the - preceeding symbol too. If they are otherwise + preceding symbol too. If they are otherwise identical prefer that one. */ if (hi > 0 && MSYMBOL_TYPE (&msymbol[hi]) == other_type diff --git a/contrib/gdb-7/gdb/mipsread.c b/contrib/gdb-7/gdb/mipsread.c index 74d795d4a6..5790730f3f 100644 --- a/contrib/gdb-7/gdb/mipsread.c +++ b/contrib/gdb-7/gdb/mipsread.c @@ -1,7 +1,6 @@ /* Read a symbol table in MIPS' format (Third-Eye). - Copyright (C) 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1998, 1999, 2000, 2001, 2003, 2004, 2007, 2008, 2009, 2010, 2011 + Copyright (C) 1986-1987, 1989-1996, 1998-2001, 2003-2004, 2007-2012 Free Software Foundation, Inc. Contributed by Alessandro Forin (af@cs.cmu.edu) at CMU. Major work @@ -240,7 +239,7 @@ read_alphacoff_dynamic_symtab (struct section_offsets *section_offsets, (file_ptr) 0, got_secsize)) return; - /* Find the number of local GOT entries and the index for the the + /* Find the number of local GOT entries and the index for the first dynamic symbol in the GOT. */ for (dyninfo_p = dyninfo_secptr, dyninfo_end = dyninfo_p + dyninfo_secsize; dyninfo_p < dyninfo_end; diff --git a/contrib/gdb-7/gdb/objc-exp.y b/contrib/gdb-7/gdb/objc-exp.y index 852adff642..346b404181 100644 --- a/contrib/gdb-7/gdb/objc-exp.y +++ b/contrib/gdb-7/gdb/objc-exp.y @@ -1,7 +1,7 @@ /* YACC parser for C expressions, for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1993, 1994, 2002, 2006, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989-1991, 1993-1994, 2002, 2006-2012 Free + Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -755,8 +755,8 @@ variable: name_not_typename if (innermost_block == 0 || contained_in (block_found, innermost_block)) innermost_block = block_found; - write_exp_elt_opcode (OP_OBJC_SELF); - write_exp_elt_opcode (OP_OBJC_SELF); + write_exp_elt_opcode (OP_THIS); + write_exp_elt_opcode (OP_THIS); write_exp_elt_opcode (STRUCTOP_PTR); write_exp_string ($1.stoken); write_exp_elt_opcode (STRUCTOP_PTR); diff --git a/contrib/gdb-7/gdb/objc-lang.c b/contrib/gdb-7/gdb/objc-lang.c index 592b52e3ca..1c963096fa 100644 --- a/contrib/gdb-7/gdb/objc-lang.c +++ b/contrib/gdb-7/gdb/objc-lang.c @@ -1,7 +1,6 @@ /* Objective-C language support routines for GDB, the GNU debugger. - Copyright (C) 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2005, 2007-2012 Free Software Foundation, Inc. Contributed by Apple Computer, Inc. Written by Michael Snyder. @@ -541,6 +540,8 @@ const struct language_defn objc_language_defn = { default_print_array_index, default_pass_by_reference, default_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; @@ -952,49 +953,7 @@ classes_info (char *regexp, int from_tty) printf_filtered (_("No classes matching \"%s\"\n"), regexp ? regexp : "*"); } -/* - * Function: find_imps (char *selector, struct symbol **sym_arr) - * - * Input: a string representing a selector - * a pointer to an array of symbol pointers - * possibly a pointer to a symbol found by the caller. - * - * Output: number of methods that implement that selector. Side - * effects: The array of symbol pointers is filled with matching syms. - * - * By analogy with function "find_methods" (symtab.c), builds a list - * of symbols matching the ambiguous input, so that "decode_line_2" - * (symtab.c) can list them and ask the user to choose one or more. - * In this case the matches are objective c methods - * ("implementations") matching an objective c selector. - * - * Note that it is possible for a normal (c-style) function to have - * the same name as an objective c selector. To prevent the selector - * from eclipsing the function, we allow the caller (decode_line_1) to - * search for such a function first, and if it finds one, pass it in - * to us. We will then integrate it into the list. We also search - * for one here, among the minsyms. - * - * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided - * into two parts: debuggable (struct symbol) syms, and - * non_debuggable (struct minimal_symbol) syms. The debuggable - * ones will come first, before NUM_DEBUGGABLE (which will thus - * be the index of the first non-debuggable one). - */ - -/* - * Function: total_number_of_imps (char *selector); - * - * Input: a string representing a selector - * Output: number of methods that implement that selector. - * - * By analogy with function "total_number_of_methods", this allows - * decode_line_1 (symtab.c) to detect if there are objective c methods - * matching the input, and to allocate an array of pointers to them - * which can be manipulated by "decode_line_2" (also in symtab.c). - */ - -char * +static char * parse_selector (char *method, char **selector) { char *s1 = NULL; @@ -1050,7 +1009,7 @@ parse_selector (char *method, char **selector) return s2; } -char * +static char * parse_method (char *method, char *type, char **class, char **category, char **selector) { @@ -1154,15 +1113,11 @@ parse_method (char *method, char *type, char **class, } static void -find_methods (struct symtab *symtab, char type, - const char *class, const char *category, - const char *selector, struct symbol **syms, - unsigned int *nsym, unsigned int *ndebug) +find_methods (char type, const char *class, const char *category, + const char *selector, + VEC (const_char_ptr) **symbol_names) { struct objfile *objfile = NULL; - struct minimal_symbol *msymbol = NULL; - struct block *block = NULL; - struct symbol *sym = NULL; char *symname = NULL; @@ -1171,21 +1126,15 @@ find_methods (struct symtab *symtab, char type, char *ncategory = NULL; char *nselector = NULL; - unsigned int csym = 0; - unsigned int cdebug = 0; - static char *tmp = NULL; static unsigned int tmplen = 0; - gdb_assert (nsym != NULL); - gdb_assert (ndebug != NULL); - - if (symtab) - block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK); + gdb_assert (symbol_names != NULL); ALL_OBJFILES (objfile) { unsigned int *objc_csym; + struct minimal_symbol *msymbol = NULL; /* The objfile_csym variable counts the number of ObjC methods that this objfile defines. We save that count as a private @@ -1202,7 +1151,6 @@ find_methods (struct symtab *symtab, char type, ALL_OBJFILE_MSYMBOLS (objfile, msymbol) { struct gdbarch *gdbarch = get_objfile_arch (objfile); - CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol); QUIT; @@ -1216,18 +1164,8 @@ find_methods (struct symtab *symtab, char type, /* Not a method name. */ continue; - /* The minimal symbol might point to a function descriptor; - resolve it to the actual code address instead. */ - pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc, - ¤t_target); - objfile_csym++; - if (symtab) - if (pc < BLOCK_START (block) || pc >= BLOCK_END (block)) - /* Not in the specified symtab. */ - continue; - /* Now that thinks are a bit sane, clean up the symname. */ while ((strlen (symname) + 1) >= tmplen) { @@ -1255,41 +1193,9 @@ find_methods (struct symtab *symtab, char type, ((nselector == NULL) || (strcmp (selector, nselector) != 0))) continue; - sym = find_pc_function (pc); - if (sym != NULL) - { - const char *newsymname = SYMBOL_NATURAL_NAME (sym); - - if (strcmp (symname, newsymname) == 0) - { - /* Found a high-level method sym: swap it into the - lower part of sym_arr (below num_debuggable). */ - if (syms != NULL) - { - syms[csym] = syms[cdebug]; - syms[cdebug] = sym; - } - csym++; - cdebug++; - } - else - { - warning ( -"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring", - newsymname, symname); - if (syms != NULL) - syms[csym] = (struct symbol *) msymbol; - csym++; - } - } - else - { - /* Found a non-debuggable method symbol. */ - if (syms != NULL) - syms[csym] = (struct symbol *) msymbol; - csym++; - } + VEC_safe_push (const_char_ptr, *symbol_names, symname); } + if (objc_csym == NULL) { objc_csym = obstack_alloc (&objfile->objfile_obstack, @@ -1301,38 +1207,79 @@ find_methods (struct symtab *symtab, char type, /* Count of ObjC methods in this objfile should be constant. */ gdb_assert (*objc_csym == objfile_csym); } +} + +/* Uniquify a VEC of strings. */ - if (nsym != NULL) - *nsym = csym; - if (ndebug != NULL) - *ndebug = cdebug; +static void +uniquify_strings (VEC (const_char_ptr) **strings) +{ + int ix; + const char *elem, *last = NULL; + int out; + + qsort (VEC_address (const_char_ptr, *strings), + VEC_length (const_char_ptr, *strings), + sizeof (const_char_ptr), + compare_strings); + out = 0; + for (ix = 0; VEC_iterate (const_char_ptr, *strings, ix, elem); ++ix) + { + if (last == NULL || strcmp (last, elem) != 0) + { + /* Keep ELEM. */ + VEC_replace (const_char_ptr, *strings, out, elem); + ++out; + } + last = elem; + } + VEC_truncate (const_char_ptr, *strings, out); } -char *find_imps (struct symtab *symtab, struct block *block, - char *method, struct symbol **syms, - unsigned int *nsym, unsigned int *ndebug) +/* + * Function: find_imps (char *selector, struct symbol **sym_arr) + * + * Input: a string representing a selector + * a pointer to an array of symbol pointers + * possibly a pointer to a symbol found by the caller. + * + * Output: number of methods that implement that selector. Side + * effects: The array of symbol pointers is filled with matching syms. + * + * By analogy with function "find_methods" (symtab.c), builds a list + * of symbols matching the ambiguous input, so that "decode_line_2" + * (symtab.c) can list them and ask the user to choose one or more. + * In this case the matches are objective c methods + * ("implementations") matching an objective c selector. + * + * Note that it is possible for a normal (c-style) function to have + * the same name as an objective c selector. To prevent the selector + * from eclipsing the function, we allow the caller (decode_line_1) to + * search for such a function first, and if it finds one, pass it in + * to us. We will then integrate it into the list. We also search + * for one here, among the minsyms. + * + * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided + * into two parts: debuggable (struct symbol) syms, and + * non_debuggable (struct minimal_symbol) syms. The debuggable + * ones will come first, before NUM_DEBUGGABLE (which will thus + * be the index of the first non-debuggable one). + */ + +char * +find_imps (char *method, VEC (const_char_ptr) **symbol_names) { char type = '\0'; char *class = NULL; char *category = NULL; char *selector = NULL; - unsigned int csym = 0; - unsigned int cdebug = 0; - - unsigned int ncsym = 0; - unsigned int ncdebug = 0; - char *buf = NULL; char *tmp = NULL; - gdb_assert (nsym != NULL); - gdb_assert (ndebug != NULL); + int selector_case = 0; - if (nsym != NULL) - *nsym = 0; - if (ndebug != NULL) - *ndebug = 0; + gdb_assert (symbol_names != NULL); buf = (char *) alloca (strlen (method) + 1); strcpy (buf, method); @@ -1340,99 +1287,37 @@ char *find_imps (struct symtab *symtab, struct block *block, if (tmp == NULL) { - struct symbol *sym = NULL; - struct minimal_symbol *msym = NULL; - strcpy (buf, method); tmp = parse_selector (buf, &selector); if (tmp == NULL) return NULL; - sym = lookup_symbol (selector, block, VAR_DOMAIN, 0); - if (sym != NULL) - { - if (syms) - syms[csym] = sym; - csym++; - cdebug++; - } - - if (sym == NULL) - msym = lookup_minimal_symbol (selector, 0, 0); - - if (msym != NULL) - { - if (syms) - syms[csym] = (struct symbol *)msym; - csym++; - } + selector_case = 1; } - if (syms != NULL) - find_methods (symtab, type, class, category, selector, - syms + csym, &ncsym, &ncdebug); - else - find_methods (symtab, type, class, category, selector, - NULL, &ncsym, &ncdebug); - - /* If we didn't find any methods, just return. */ - if (ncsym == 0 && ncdebug == 0) - return method; + find_methods (type, class, category, selector, symbol_names); - /* Take debug symbols from the second batch of symbols and swap them - * with debug symbols from the first batch. Repeat until either the - * second section is out of debug symbols or the first section is - * full of debug symbols. Either way we have all debug symbols - * packed to the beginning of the buffer. - */ - - if (syms != NULL) + /* If we hit the "selector" case, and we found some methods, then + add the selector itself as a symbol, if it exists. */ + if (selector_case && !VEC_empty (const_char_ptr, *symbol_names)) { - while ((cdebug < csym) && (ncdebug > 0)) + struct symbol *sym = lookup_symbol (selector, NULL, VAR_DOMAIN, 0); + + if (sym != NULL) + VEC_safe_push (const_char_ptr, *symbol_names, + SYMBOL_NATURAL_NAME (sym)); + else { - struct symbol *s = NULL; - /* First non-debugging symbol. */ - unsigned int i = cdebug; - /* Last of second batch of debug symbols. */ - unsigned int j = csym + ncdebug - 1; - - s = syms[j]; - syms[j] = syms[i]; - syms[i] = s; - - /* We've moved a symbol from the second debug section to the - first one. */ - cdebug++; - ncdebug--; + struct minimal_symbol *msym = lookup_minimal_symbol (selector, 0, 0); + + if (msym != NULL) + VEC_safe_push (const_char_ptr, *symbol_names, + SYMBOL_NATURAL_NAME (msym)); } } - csym += ncsym; - cdebug += ncdebug; - - if (nsym != NULL) - *nsym = csym; - if (ndebug != NULL) - *ndebug = cdebug; - - if (syms == NULL) - return method + (tmp - buf); - - if (csym > 1) - { - /* Sort debuggable symbols. */ - if (cdebug > 1) - qsort (syms, cdebug, sizeof (struct minimal_symbol *), - compare_classes); - - /* Sort minimal_symbols. */ - if ((csym - cdebug) > 1) - qsort (&syms[cdebug], csym - cdebug, - sizeof (struct minimal_symbol *), compare_classes); - } - /* Terminate the sym_arr list. */ - syms[csym] = 0; + uniquify_strings (symbol_names); return method + (tmp - buf); } diff --git a/contrib/gdb-7/gdb/objc-lang.h b/contrib/gdb-7/gdb/objc-lang.h index ee4cc293a3..593ef02222 100644 --- a/contrib/gdb-7/gdb/objc-lang.h +++ b/contrib/gdb-7/gdb/objc-lang.h @@ -1,7 +1,6 @@ /* Objective-C language support definitions for GDB, the GNU debugger. - Copyright (C) 1992, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992, 2005, 2007-2012 Free Software Foundation, Inc. Contributed by Apple Computer, Inc. @@ -21,6 +20,8 @@ #if !defined(OBJC_LANG_H) #define OBJC_LANG_H +#include "cp-support.h" /* For VEC (const_char_ptr) */ + struct stoken; struct value; @@ -39,15 +40,7 @@ extern char *objc_demangle (const char *mangled, int options); extern int find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc); -extern char *parse_selector (char *method, char **selector); - -extern char *parse_method (char *method, char *type, - char **class, char **category, - char **selector); - -extern char *find_imps (struct symtab *symtab, struct block *block, - char *method, struct symbol **syms, - unsigned int *nsym, unsigned int *ndebug); +extern char *find_imps (char *method, VEC (const_char_ptr) **symbol_names); extern struct value *value_nsstring (struct gdbarch *gdbarch, char *ptr, int len); diff --git a/contrib/gdb-7/gdb/objfiles.c b/contrib/gdb-7/gdb/objfiles.c index 7b0c450ccb..afe4fb4322 100644 --- a/contrib/gdb-7/gdb/objfiles.c +++ b/contrib/gdb-7/gdb/objfiles.c @@ -1,8 +1,6 @@ /* GDB routines for manipulating objfiles. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-2004, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -64,7 +62,6 @@ static void objfile_free_data (struct objfile *objfile); /* Externally visible variables that are owned by this module. See declarations in objfile.h for more info. */ -struct objfile *current_objfile; /* For symbol file being read in */ struct objfile *rt_common_objfile; /* For runtime common symbols */ struct objfile_pspace_info @@ -163,12 +160,6 @@ add_to_objfile_sections (struct bfd *abfd, struct bfd_section *asect, int build_objfile_section_table (struct objfile *objfile) { - /* objfile->sections can be already set when reading a mapped symbol - file. I believe that we do need to rebuild the section table in - this case (we rebuild other things derived from the bfd), but we - can't free the old one (it's in the objfile_obstack). So we just - waste some memory. */ - objfile->sections_end = 0; bfd_map_over_sections (objfile->obfd, add_to_objfile_sections, (void *) objfile); @@ -247,10 +238,6 @@ allocate_objfile (bfd *abfd, int flags) objfile->sect_index_bss = -1; objfile->sect_index_rodata = -1; - /* We don't yet have a C++-specific namespace symtab. */ - - objfile->cp_namespace_symtab = NULL; - /* Add this file onto the tail of the linked list of other such files. */ objfile->next = NULL; @@ -587,6 +574,10 @@ free_objfile (struct objfile *objfile) lists. */ preserve_values (objfile); + /* It still may reference data modules have associated with the objfile and + the symbol file data. */ + forget_cached_source_info_for_objfile (objfile); + /* First do any symbol file specific actions required when we are finished with a particular symbol file. Note that if the objfile is using reusable symbol information (via mmalloc) then each of @@ -599,7 +590,8 @@ free_objfile (struct objfile *objfile) (*objfile->sf->sym_finish) (objfile); } - /* Discard any data modules have associated with the objfile. */ + /* Discard any data modules have associated with the objfile. The function + still may reference objfile->obfd. */ objfile_free_data (objfile); gdb_bfd_unref (objfile->obfd); @@ -636,13 +628,9 @@ free_objfile (struct objfile *objfile) { struct symtab_and_line cursal = get_current_source_symtab_and_line (); - struct symtab *s; - ALL_OBJFILE_SYMTABS (objfile, s) - { - if (s == cursal.symtab) - clear_current_source_symtab_and_line (); - } + if (cursal.symtab && cursal.symtab->objfile == objfile) + clear_current_source_symtab_and_line (); } /* The last thing we do is free the objfile struct itself. */ diff --git a/contrib/gdb-7/gdb/objfiles.h b/contrib/gdb-7/gdb/objfiles.h index 275c2ac39f..aba1791498 100644 --- a/contrib/gdb-7/gdb/objfiles.h +++ b/contrib/gdb-7/gdb/objfiles.h @@ -1,8 +1,6 @@ /* Definitions for symbol file management in GDB. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -128,13 +126,13 @@ struct obj_section /* The memory address of section S (vma + offset). */ #define obj_section_addr(s) \ - (bfd_get_section_vma ((s)->objfile->abfd, s->the_bfd_section) \ + (bfd_get_section_vma ((s)->objfile->obfd, s->the_bfd_section) \ + obj_section_offset (s)) /* The one-passed-the-end memory address of section S (vma + size + offset). */ #define obj_section_endaddr(s) \ - (bfd_get_section_vma ((s)->objfile->abfd, s->the_bfd_section) \ + (bfd_get_section_vma ((s)->objfile->obfd, s->the_bfd_section) \ + bfd_get_section_size ((s)->the_bfd_section) \ + obj_section_offset (s)) @@ -173,19 +171,9 @@ struct objfile { /* All struct objfile's are chained together by their next pointers. - The global variable "object_files" points to the first link in this - chain. - - FIXME: There is a problem here if the objfile is reusable, and if - multiple users are to be supported. The problem is that the objfile - list is linked through a member of the objfile struct itself, which - is only valid for one gdb process. The list implementation needs to - be changed to something like: - - struct list {struct list *next; struct objfile *objfile}; - - where the list structure is completely maintained separately within - each gdb process. */ + The program space field "objfiles" (frequently referenced via + the macro "object_files") points to the first link in this + chain. */ struct objfile *next; @@ -196,7 +184,8 @@ struct objfile CORE_ADDR addr_low; - /* Some flag bits for this objfile. */ + /* Some flag bits for this objfile. + The values are defined by OBJF_*. */ unsigned short flags; @@ -244,6 +233,11 @@ struct objfile long mtime; + /* Cached 32-bit CRC as computed by gnu_debuglink_crc32. CRC32 is valid + iff CRC32_P. */ + unsigned long crc32; + int crc32_p; + /* Obstack to hold objects that should be freed when we load a new symbol table from this object file. */ @@ -389,13 +383,6 @@ struct objfile /* Place to stash various statistics about this objfile. */ OBJSTATS; - /* A symtab that the C++ code uses to stash special symbols - associated to namespaces. */ - - /* FIXME/carlton-2003-06-27: Delete this in a few years once - "possible namespace symbols" go away. */ - struct symtab *cp_namespace_symtab; - /* A linked list of symbols created when reading template types or function templates. These symbols are not stored in any symbol table, so we have to keep them here to relocate them @@ -441,26 +428,16 @@ struct objfile #define OBJF_PSYMTABS_READ (1 << 4) +/* Set if this is the main symbol file + (as opposed to symbol file for dynamically loaded code). */ + +#define OBJF_MAINLINE (1 << 5) + /* The object file that contains the runtime common minimal symbols for SunOS4. Note that this objfile has no associated BFD. */ extern struct objfile *rt_common_objfile; -/* When we need to allocate a new type, we need to know which objfile_obstack - to allocate the type on, since there is one for each objfile. The places - where types are allocated are deeply buried in function call hierarchies - which know nothing about objfiles, so rather than trying to pass a - particular objfile down to them, we just do an end run around them and - set current_objfile to be whatever objfile we expect to be using at the - time types are being allocated. For instance, when we start reading - symbols for a particular objfile, we set current_objfile to point to that - objfile, and when we are done, we set it back to NULL, to ensure that we - never put a type someplace other than where we are expecting to put it. - FIXME: Maybe we should review the entire type handling system and - see if there is a better way to avoid this problem. */ - -extern struct objfile *current_objfile; - /* Declarations for functions defined in objfiles.c */ extern struct objfile *allocate_objfile (bfd *, int); diff --git a/contrib/gdb-7/gdb/observer.c b/contrib/gdb-7/gdb/observer.c index de59ac67da..4944480df1 100644 --- a/contrib/gdb-7/gdb/observer.c +++ b/contrib/gdb-7/gdb/observer.c @@ -1,7 +1,6 @@ /* GDB Notifications to Observers. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/observer.sh b/contrib/gdb-7/gdb/observer.sh index ba8ba4e192..b5c49ac939 100755 --- a/contrib/gdb-7/gdb/observer.sh +++ b/contrib/gdb-7/gdb/observer.sh @@ -29,8 +29,7 @@ rm -f ${otmp} cat <>${otmp} /* GDB Notifications to Observers. - Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -64,6 +63,7 @@ struct bpstats; struct so_list; struct objfile; struct thread_info; +struct inferior; EOF ;; esac diff --git a/contrib/gdb-7/gdb/opencl-lang.c b/contrib/gdb-7/gdb/opencl-lang.c index 22d16112ab..6557a08f20 100644 --- a/contrib/gdb-7/gdb/opencl-lang.c +++ b/contrib/gdb-7/gdb/opencl-lang.c @@ -1,5 +1,5 @@ /* OpenCL language support for GDB, the GNU debugger. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. Contributed by Ken Werner . @@ -354,13 +354,14 @@ lval_func_free_closure (struct value *v) } } -static struct lval_funcs opencl_value_funcs = +static const struct lval_funcs opencl_value_funcs = { lval_func_read, lval_func_write, lval_func_check_validity, lval_func_check_any_valid, - NULL, + NULL, /* indirect */ + NULL, /* coerce_ref */ lval_func_check_synthetic_pointer, lval_func_copy_closure, lval_func_free_closure @@ -1023,6 +1024,8 @@ const struct language_defn opencl_language_defn = default_print_array_index, default_pass_by_reference, c_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; diff --git a/contrib/gdb-7/gdb/osabi.c b/contrib/gdb-7/gdb/osabi.c index a264924fe8..aba9842734 100644 --- a/contrib/gdb-7/gdb/osabi.c +++ b/contrib/gdb-7/gdb/osabi.c @@ -1,7 +1,6 @@ /* OS ABI variant handling for GDB. - Copyright (C) 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -514,11 +513,15 @@ generic_elf_osabi_sniffer (bfd *abfd) switch (elfosabi) { case ELFOSABI_NONE: + case ELFOSABI_GNU: /* When the EI_OSABI field in the ELF header is ELFOSABI_NONE (0), then the ELF structures in the file are conforming to the base specification for that machine (there are no OS-specific extensions). In order to determine the real OS - in use we must look for OS-specific notes. */ + in use, we must look for OS-specific notes. + + The same applies for ELFOSABI_GNU: this can mean GNU/Hurd, + GNU/Linux, and possibly more. */ bfd_map_over_sections (abfd, generic_elf_osabi_sniff_abi_tag_sections, &osabi); @@ -532,14 +535,6 @@ generic_elf_osabi_sniffer (bfd *abfd) osabi = GDB_OSABI_NETBSD_ELF; break; - case ELFOSABI_LINUX: - osabi = GDB_OSABI_LINUX; - break; - - case ELFOSABI_HURD: - osabi = GDB_OSABI_HURD; - break; - case ELFOSABI_SOLARIS: osabi = GDB_OSABI_SOLARIS; break; diff --git a/contrib/gdb-7/gdb/osabi.h b/contrib/gdb-7/gdb/osabi.h index 0c25da3561..ced2fa5c5b 100644 --- a/contrib/gdb-7/gdb/osabi.h +++ b/contrib/gdb-7/gdb/osabi.h @@ -1,6 +1,5 @@ /* OS ABI variant handling for GDB. - Copyright (C) 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2001-2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/osdata.c b/contrib/gdb-7/gdb/osdata.c index 024d8f4131..62ce412ca6 100644 --- a/contrib/gdb-7/gdb/osdata.c +++ b/contrib/gdb-7/gdb/osdata.c @@ -1,6 +1,6 @@ /* Routines for handling XML generic OS data provided by target. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -291,29 +291,39 @@ get_osdata_column (struct osdata_item *item, const char *name) static void info_osdata_command (char *type, int from_tty) { + struct ui_out *uiout = current_uiout; struct osdata *osdata = NULL; - struct osdata_item *last; + struct osdata_item *last = NULL; struct cleanup *old_chain; - int ncols; - int nprocs; + int ncols = 0; + int nrows; osdata = get_osdata (type); old_chain = make_cleanup_osdata_free (osdata); - nprocs = VEC_length (osdata_item_s, osdata->items); + nrows = VEC_length (osdata_item_s, osdata->items); - if (!type && nprocs == 0) + if (!type && nrows == 0) error (_("Available types of OS data not reported.")); + + if (!VEC_empty (osdata_item_s, osdata->items)) + { + last = VEC_last (osdata_item_s, osdata->items); + if (last->columns) + ncols = VEC_length (osdata_column_s, last->columns); + } - last = VEC_last (osdata_item_s, osdata->items); - if (last && last->columns) - ncols = VEC_length (osdata_column_s, last->columns); - else - ncols = 0; - - make_cleanup_ui_out_table_begin_end (uiout, ncols, nprocs, + make_cleanup_ui_out_table_begin_end (uiout, ncols, nrows, "OSDataTable"); + /* With no columns/items, we just output an empty table, but we + still output the table. This matters for MI. */ + if (ncols == 0) + { + do_cleanups (old_chain); + return; + } + if (last && last->columns) { struct osdata_column *col; @@ -323,13 +333,18 @@ info_osdata_command (char *type, int from_tty) VEC_iterate (osdata_column_s, last->columns, ix, col); ix++) - ui_out_table_header (uiout, 10, ui_left, - col->name, col->name); + { + char col_name[32]; + + snprintf (col_name, 32, "col%d", ix); + ui_out_table_header (uiout, 10, ui_left, + col_name, col->name); + } } ui_out_table_body (uiout); - if (nprocs != 0) + if (nrows != 0) { struct osdata_item *item; int ix_items; @@ -352,8 +367,13 @@ info_osdata_command (char *type, int from_tty) VEC_iterate (osdata_column_s, item->columns, ix_cols, col); ix_cols++) - ui_out_field_string (uiout, col->name, col->value); - + { + char col_name[32]; + + snprintf (col_name, 32, "col%d", ix_cols); + ui_out_field_string (uiout, col_name, col->value); + } + do_cleanups (old_chain); ui_out_text (uiout, "\n"); diff --git a/contrib/gdb-7/gdb/osdata.h b/contrib/gdb-7/gdb/osdata.h index d849976fef..f63b0f3f19 100644 --- a/contrib/gdb-7/gdb/osdata.h +++ b/contrib/gdb-7/gdb/osdata.h @@ -1,6 +1,6 @@ /* Routines for handling XML generic OS data provided by target. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/p-exp.y b/contrib/gdb-7/gdb/p-exp.y index 32c7aca657..7b05d585f5 100644 --- a/contrib/gdb-7/gdb/p-exp.y +++ b/contrib/gdb-7/gdb/p-exp.y @@ -1,6 +1,5 @@ /* YACC parser for Pascal expressions, for GDB. - Copyright (C) 2000, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2006-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -612,7 +611,7 @@ exp : THIS write_exp_elt_opcode (OP_THIS); write_exp_elt_opcode (OP_THIS); /* We need type of this. */ - this_val = value_of_this (0); + this_val = value_of_this_silent (parse_language); if (this_val) this_type = value_type (this_val); else @@ -760,7 +759,7 @@ variable: name_not_typename write_exp_string ($1.stoken); write_exp_elt_opcode (STRUCTOP_PTR); /* We need type of this. */ - this_val = value_of_this (0); + this_val = value_of_this_silent (parse_language); if (this_val) this_type = value_type (this_val); else diff --git a/contrib/gdb-7/gdb/p-lang.c b/contrib/gdb-7/gdb/p-lang.c index 655279bcfa..cd56630efd 100644 --- a/contrib/gdb-7/gdb/p-lang.c +++ b/contrib/gdb-7/gdb/p-lang.c @@ -1,7 +1,7 @@ /* Pascal language support routines for GDB, the GNU debugger. - Copyright (C) 2000, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2002-2005, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. @@ -459,6 +459,8 @@ const struct language_defn pascal_language_defn = default_print_array_index, default_pass_by_reference, default_get_string, + strcmp_iw_ordered, + iterate_over_symbols, LANG_MAGIC }; diff --git a/contrib/gdb-7/gdb/p-lang.h b/contrib/gdb-7/gdb/p-lang.h index c284c1dfa5..308b7b50dd 100644 --- a/contrib/gdb-7/gdb/p-lang.h +++ b/contrib/gdb-7/gdb/p-lang.h @@ -1,7 +1,6 @@ /* Pascal language support definitions for GDB, the GNU debugger. - Copyright (C) 2000, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2005-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -44,7 +43,7 @@ extern int pascal_val_print (struct type *, const gdb_byte *, int, extern int pascal_value_print (struct value *, struct ui_file *, const struct value_print_options *); -extern void pascal_type_print_method_args (char *, char *, +extern void pascal_type_print_method_args (const char *, const char *, struct ui_file *); /* These are in p-lang.c: */ diff --git a/contrib/gdb-7/gdb/p-typeprint.c b/contrib/gdb-7/gdb/p-typeprint.c index 54a761d464..dae56d3a04 100644 --- a/contrib/gdb-7/gdb/p-typeprint.c +++ b/contrib/gdb-7/gdb/p-typeprint.c @@ -1,6 +1,5 @@ /* Support for printing Pascal types for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2002, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2002, 2006-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -31,7 +30,7 @@ #include "language.h" #include "p-lang.h" #include "typeprint.h" - +#include "gdb-demangle.h" #include "gdb_string.h" #include #include @@ -153,7 +152,7 @@ pascal_type_print_derivation_info (struct ui_file *stream, struct type *type) /* Print the Pascal method arguments ARGS to the file STREAM. */ void -pascal_type_print_method_args (char *physname, char *methodname, +pascal_type_print_method_args (const char *physname, const char *methodname, struct ui_file *stream) { int is_constructor = (strncmp (physname, "__ct__", 6) == 0); @@ -173,8 +172,7 @@ pascal_type_print_method_args (char *physname, char *methodname, while (isdigit (physname[0])) { int len = 0; - int i; - char storec; + int i, j; char *argname; while (isdigit (physname[len])) @@ -183,10 +181,10 @@ pascal_type_print_method_args (char *physname, char *methodname, } i = strtol (physname, &argname, 0); physname += len; - storec = physname[i]; - physname[i] = 0; - fputs_filtered (physname, stream); - physname[i] = storec; + + for (j = 0; j < i; ++j) + fputc_filtered (physname[j], stream); + physname += i; if (physname[0] != 0) { @@ -638,7 +636,7 @@ pascal_type_print_base (struct type *type, struct ui_file *stream, int show, It might work for GNU pascal. */ for (j = 0; j < len2; j++) { - char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); + const char *physname = TYPE_FN_FIELD_PHYSNAME (f, j); int is_constructor = (strncmp (physname, "__ct__", 6) == 0); int is_destructor = (strncmp (physname, "__dt__", 6) == 0); diff --git a/contrib/gdb-7/gdb/p-valprint.c b/contrib/gdb-7/gdb/p-valprint.c index d2efa5b3d2..c5bef8a0ff 100644 --- a/contrib/gdb-7/gdb/p-valprint.c +++ b/contrib/gdb-7/gdb/p-valprint.c @@ -1,7 +1,7 @@ /* Support for printing Pascal values for GDB, the GNU debugger. - Copyright (C) 2000, 2001, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000-2001, 2003, 2005-2012 Free Software Foundation, + Inc. This file is part of GDB. @@ -272,10 +272,19 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, { if (TYPE_CODE (elttype) != TYPE_CODE_UNDEF) { - struct value *deref_val = - value_at - (TYPE_TARGET_TYPE (type), - unpack_pointer (type, valaddr + embedded_offset)); + struct value *deref_val; + + deref_val = coerce_ref_if_computed (original_value); + if (deref_val != NULL) + { + /* More complicated computed references are not supported. */ + gdb_assert (embedded_offset == 0); + } + else + deref_val = value_at (TYPE_TARGET_TYPE (type), + unpack_pointer (type, + (valaddr + + embedded_offset))); common_val_print (deref_val, stream, recurse + 1, options, current_language); diff --git a/contrib/gdb-7/gdb/parse.c b/contrib/gdb-7/gdb/parse.c index 4815854c83..b0fa2379fd 100644 --- a/contrib/gdb-7/gdb/parse.c +++ b/contrib/gdb-7/gdb/parse.c @@ -1,8 +1,7 @@ /* Parse expressions for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1989-2001, 2004-2005, 2007-2012 Free Software + Foundation, Inc. Modified from expread.y by the Department of Computer Science at the State University of New York at Buffalo, 1991. @@ -23,7 +22,7 @@ along with this program. If not, see . */ /* Parse an expression from text in a string, - and return the result as a struct expression pointer. + and return the result as a struct expression pointer. That structure contains arithmetic operations in reverse polish, with constants represented by operations that are followed by special data. See expression.h for the details of the format. @@ -190,7 +189,7 @@ free_funcalls (void *ignore) } } -/* This page contains the functions for adding data to the struct expression +/* This page contains the functions for adding data to the struct expression being constructed. */ /* Add one element to the end of the expression. */ @@ -198,8 +197,8 @@ free_funcalls (void *ignore) /* To avoid a bug in the Sun 4 compiler, we pass things that can fit into a register through here. */ -void -write_exp_elt (union exp_element expelt) +static void +write_exp_elt (const union exp_element *expelt) { if (expout_ptr >= expout_size) { @@ -208,7 +207,7 @@ write_exp_elt (union exp_element expelt) xrealloc ((char *) expout, sizeof (struct expression) + EXP_ELEM_TO_BYTES (expout_size)); } - expout->elts[expout_ptr++] = expelt; + expout->elts[expout_ptr++] = *expelt; } void @@ -218,7 +217,7 @@ write_exp_elt_opcode (enum exp_opcode expelt) memset (&tmp, 0, sizeof (union exp_element)); tmp.opcode = expelt; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -228,7 +227,7 @@ write_exp_elt_sym (struct symbol *expelt) memset (&tmp, 0, sizeof (union exp_element)); tmp.symbol = expelt; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -238,7 +237,7 @@ write_exp_elt_block (struct block *b) memset (&tmp, 0, sizeof (union exp_element)); tmp.block = b; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -248,7 +247,7 @@ write_exp_elt_objfile (struct objfile *objfile) memset (&tmp, 0, sizeof (union exp_element)); tmp.objfile = objfile; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -258,7 +257,7 @@ write_exp_elt_longcst (LONGEST expelt) memset (&tmp, 0, sizeof (union exp_element)); tmp.longconst = expelt; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -268,7 +267,7 @@ write_exp_elt_dblcst (DOUBLEST expelt) memset (&tmp, 0, sizeof (union exp_element)); tmp.doubleconst = expelt; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -280,7 +279,7 @@ write_exp_elt_decfloatcst (gdb_byte expelt[16]) for (index = 0; index < 16; index++) tmp.decfloatconst[index] = expelt[index]; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -290,7 +289,7 @@ write_exp_elt_type (struct type *expelt) memset (&tmp, 0, sizeof (union exp_element)); tmp.type = expelt; - write_exp_elt (tmp); + write_exp_elt (&tmp); } void @@ -300,7 +299,7 @@ write_exp_elt_intern (struct internalvar *expelt) memset (&tmp, 0, sizeof (union exp_element)); tmp.internalvar = expelt; - write_exp_elt (tmp); + write_exp_elt (&tmp); } /* Add a string constant to the end of the expression. @@ -853,6 +852,7 @@ operator_length_standard (const struct expression *expr, int endpos, case OP_BOOL: case OP_LAST: case OP_INTERNALVAR: + case OP_VAR_ENTRY_VALUE: oplen = 3; break; @@ -963,7 +963,6 @@ operator_length_standard (const struct expression *expr, int endpos, /* C++ */ case OP_THIS: - case OP_OBJC_SELF: oplen = 2; break; @@ -1060,7 +1059,7 @@ prefixify_subexp (struct expression *inexpr, } /* Read an expression from the string *STRINGPTR points to, - parse it, and return a pointer to a struct expression that we malloc. + parse it, and return a pointer to a struct expression that we malloc. Use block BLOCK as the lexical context for variable names; if BLOCK is zero, use the block of the selected stack frame. Meanwhile, advance *STRINGPTR to point after the expression, diff --git a/contrib/gdb-7/gdb/parser-defs.h b/contrib/gdb-7/gdb/parser-defs.h index 3f743d15be..d14aea6bbe 100644 --- a/contrib/gdb-7/gdb/parser-defs.h +++ b/contrib/gdb-7/gdb/parser-defs.h @@ -1,8 +1,7 @@ /* Parser definitions for GDB. - Copyright (C) 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986, 1989-2000, 2002, 2007-2012 Free Software + Foundation, Inc. Modified from expread.y by the Department of Computer Science at the State University of New York at Buffalo. @@ -131,8 +130,6 @@ union type_stack_elt extern union type_stack_elt *type_stack; extern int type_stack_depth, type_stack_size; -extern void write_exp_elt (union exp_element); - extern void write_exp_elt_opcode (enum exp_opcode); extern void write_exp_elt_sym (struct symbol *); diff --git a/contrib/gdb-7/gdb/posix-hdep.c b/contrib/gdb-7/gdb/posix-hdep.c index 9bd3a9a072..793f1c60d3 100644 --- a/contrib/gdb-7/gdb/posix-hdep.c +++ b/contrib/gdb-7/gdb/posix-hdep.c @@ -1,7 +1,6 @@ /* Host support routines for MinGW, for GDB, the GNU debugger. - Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/printcmd.c b/contrib/gdb-7/gdb/printcmd.c index f1ebb7e9e0..bee8a85090 100644 --- a/contrib/gdb-7/gdb/printcmd.c +++ b/contrib/gdb-7/gdb/printcmd.c @@ -1,8 +1,6 @@ /* Print values for GNU debugger GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -32,6 +30,7 @@ #include "target.h" #include "breakpoint.h" #include "demangle.h" +#include "gdb-demangle.h" #include "valprint.h" #include "annotate.h" #include "symfile.h" /* for overlay functions */ @@ -62,9 +61,6 @@ # define USE_PRINTF_I64 0 #endif -extern int asm_demangle; /* Whether to demangle syms in asm - printouts. */ - struct format_data { int count; @@ -129,7 +125,7 @@ show_print_symbol_filename (struct ui_file *file, int from_tty, } /* Number of auto-display expression currently being displayed. - So that we can disable it if we get an error or a signal within it. + So that we can disable it if we get a signal within it. -1 when not doing one. */ int current_display_number; @@ -1663,6 +1659,7 @@ undisplay_command (char *args, int from_tty) static void do_one_display (struct display *d) { + struct cleanup *old_chain; int within_current_scope; if (d->enabled_p == 0) @@ -1714,6 +1711,7 @@ do_one_display (struct display *d) if (!within_current_scope) return; + old_chain = make_cleanup_restore_integer (¤t_display_number); current_display_number = d->number; annotate_display_begin (); @@ -1722,8 +1720,7 @@ do_one_display (struct display *d) printf_filtered (": "); if (d->format.size) { - CORE_ADDR addr; - struct value *val; + volatile struct gdb_exception ex; annotate_display_format (); @@ -1745,18 +1742,26 @@ do_one_display (struct display *d) else printf_filtered (" "); - val = evaluate_expression (d->exp); - addr = value_as_address (val); - if (d->format.format == 'i') - addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr); - annotate_display_value (); - do_examine (d->format, d->exp->gdbarch, addr); + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + struct value *val; + CORE_ADDR addr; + + val = evaluate_expression (d->exp); + addr = value_as_address (val); + if (d->format.format == 'i') + addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr); + do_examine (d->format, d->exp->gdbarch, addr); + } + if (ex.reason < 0) + fprintf_filtered (gdb_stdout, _("\n"), ex.message); } else { struct value_print_options opts; + volatile struct gdb_exception ex; annotate_display_format (); @@ -1774,15 +1779,23 @@ do_one_display (struct display *d) get_formatted_print_options (&opts, d->format.format); opts.raw = d->format.raw; - print_formatted (evaluate_expression (d->exp), - d->format.size, &opts, gdb_stdout); + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + struct value *val; + + val = evaluate_expression (d->exp); + print_formatted (val, d->format.size, &opts, gdb_stdout); + } + if (ex.reason < 0) + fprintf_filtered (gdb_stdout, _(""), ex.message); printf_filtered ("\n"); } annotate_display_end (); gdb_flush (gdb_stdout); - current_display_number = -1; + do_cleanups (old_chain); } /* Display all of the values on the auto-display chain which can be @@ -1959,6 +1972,7 @@ print_variable_and_value (const char *name, struct symbol *var, val = read_var_value (var, frame); get_user_print_options (&opts); + opts.deref_ref = 1; common_val_print (val, stream, indent, &opts, current_language); } if (except.reason < 0) diff --git a/contrib/gdb-7/gdb/proc-service.list b/contrib/gdb-7/gdb/proc-service.list index 101dd1f151..5660e9e8ae 100644 --- a/contrib/gdb-7/gdb/proc-service.list +++ b/contrib/gdb-7/gdb/proc-service.list @@ -1,6 +1,6 @@ /* -Wl,--dynamic-list symbols exported for libthread_db. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/progspace.c b/contrib/gdb-7/gdb/progspace.c index 9f32cef6ec..7175fa6ab1 100644 --- a/contrib/gdb-7/gdb/progspace.c +++ b/contrib/gdb-7/gdb/progspace.c @@ -1,6 +1,6 @@ /* Program and address space management, for GDB, the GNU debugger. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -397,7 +397,7 @@ maintenance_info_program_spaces_command (char *args, int from_tty) error (_("program space ID %d not known."), requested); } - print_program_space (uiout, requested); + print_program_space (current_uiout, requested); } /* Simply returns the count of program spaces. */ diff --git a/contrib/gdb-7/gdb/progspace.h b/contrib/gdb-7/gdb/progspace.h index 5d3ed950f7..9822f70b70 100644 --- a/contrib/gdb-7/gdb/progspace.h +++ b/contrib/gdb-7/gdb/progspace.h @@ -1,6 +1,6 @@ /* Program and address space management, for GDB, the GNU debugger. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -185,6 +185,9 @@ struct program_space solib.c. */ struct so_list *so_list; + /* Number of calls to solib_add. */ + unsigned solib_add_generation; + /* Per pspace data-pointers required by other GDB modules. */ void **data; unsigned num_data; diff --git a/contrib/gdb-7/gdb/prologue-value.c b/contrib/gdb-7/gdb/prologue-value.c index 46c5b689d3..e84a103bad 100644 --- a/contrib/gdb-7/gdb/prologue-value.c +++ b/contrib/gdb-7/gdb/prologue-value.c @@ -1,6 +1,5 @@ /* Prologue value handling for GDB. - Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright 2003-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -399,7 +398,7 @@ pv_area_store_would_trash (struct pv_area *area, pv_t addr) This may return zero, if AREA has no entries. And since the entries are a ring, this may return an entry that - entirely preceeds OFFSET. This is the correct behavior: depending + entirely precedes OFFSET. This is the correct behavior: depending on the sizes involved, we could still overlap such an area, with wrap-around. */ static struct area_entry * diff --git a/contrib/gdb-7/gdb/prologue-value.h b/contrib/gdb-7/gdb/prologue-value.h index c8d45ffc9a..93dab10f60 100644 --- a/contrib/gdb-7/gdb/prologue-value.h +++ b/contrib/gdb-7/gdb/prologue-value.h @@ -1,6 +1,5 @@ /* Interface to prologue value handling for GDB. - Copyright 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright 2003-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/psympriv.h b/contrib/gdb-7/gdb/psympriv.h index 95d7676cbf..7cf9260ba0 100644 --- a/contrib/gdb-7/gdb/psympriv.h +++ b/contrib/gdb-7/gdb/psympriv.h @@ -1,6 +1,6 @@ /* Private partial symbol table definitions. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -92,7 +92,8 @@ struct partial_symtab struct section_offsets *section_offsets; /* Range of text addresses covered by this file; texthigh is the - beginning of the next section. */ + beginning of the next section. Do not use if PSYMTABS_ADDRMAP_SUPPORTED + is set. */ CORE_ADDR textlow; CORE_ADDR texthigh; @@ -135,6 +136,12 @@ struct partial_symtab unsigned char readin; + /* True iff objfile->psymtabs_addrmap is properly populated for this + partial_symtab. For discontiguous overlapping psymtabs is the only usable + info in PSYMTABS_ADDRMAP. */ + + unsigned char psymtabs_addrmap_supported; + /* Pointer to symtab eventually allocated for this source file, 0 if !readin or if we haven't looked for the symtab after it was readin. */ diff --git a/contrib/gdb-7/gdb/psymtab.c b/contrib/gdb-7/gdb/psymtab.c index cd117c1e1e..d5cfa8b22f 100644 --- a/contrib/gdb-7/gdb/psymtab.c +++ b/contrib/gdb-7/gdb/psymtab.c @@ -1,6 +1,6 @@ /* Partial symbol tables. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -125,23 +125,61 @@ require_partial_symbols (struct objfile *objfile, int verbose) ALL_OBJFILES (objfile) \ ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p) -/* Lookup the partial symbol table of a source file named NAME. - *If* there is no '/' in the name, a match after a '/' - in the psymtab filename will also work. */ +/* Helper function for partial_map_symtabs_matching_filename that + expands the symtabs and calls the iterator. */ -static struct partial_symtab * -lookup_partial_symtab (struct objfile *objfile, const char *name, - const char *full_path, const char *real_path) +static int +partial_map_expand_apply (struct objfile *objfile, + const char *name, + const char *full_path, + const char *real_path, + struct partial_symtab *pst, + int (*callback) (struct symtab *, void *), + void *data) +{ + struct symtab *last_made = objfile->symtabs; + + /* Don't visit already-expanded psymtabs. */ + if (pst->readin) + return 0; + + /* This may expand more than one symtab, and we want to iterate over + all of them. */ + psymtab_to_symtab (pst); + + return iterate_over_some_symtabs (name, full_path, real_path, callback, data, + objfile->symtabs, last_made); +} + +/* Implementation of the map_symtabs_matching_filename method. */ + +static int +partial_map_symtabs_matching_filename (struct objfile *objfile, + const char *name, + const char *full_path, + const char *real_path, + int (*callback) (struct symtab *, + void *), + void *data) { struct partial_symtab *pst; + const char *name_basename = lbasename (name); ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (FILENAME_CMP (name, pst->filename) == 0) { - return (pst); + if (partial_map_expand_apply (objfile, name, full_path, real_path, + pst, callback, data)) + return 1; } + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if (! basenames_may_differ + && FILENAME_CMP (name_basename, lbasename (pst->filename)) != 0) + continue; + /* If the user gave us an absolute path, try to find the file in this symtab and use its absolute path. */ if (full_path != NULL) @@ -150,7 +188,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, if (pst->fullname != NULL && FILENAME_CMP (full_path, pst->fullname) == 0) { - return pst; + if (partial_map_expand_apply (objfile, name, full_path, real_path, + pst, callback, data)) + return 1; } } @@ -165,40 +205,25 @@ lookup_partial_symtab (struct objfile *objfile, const char *name, } if (rp != NULL && FILENAME_CMP (real_path, rp) == 0) { - return pst; + if (partial_map_expand_apply (objfile, name, full_path, real_path, + pst, callback, data)) + return 1; } } } /* Now, search for a matching tail (only if name doesn't have any dirs). */ - if (lbasename (name) == name) + if (name_basename == name) ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) { if (FILENAME_CMP (lbasename (pst->filename), name) == 0) - return (pst); + if (partial_map_expand_apply (objfile, name, full_path, real_path, pst, + callback, data)) + return 1; } - return (NULL); -} - -static int -lookup_symtab_via_partial_symtab (struct objfile *objfile, const char *name, - const char *full_path, const char *real_path, - struct symtab **result) -{ - struct partial_symtab *ps; - - ps = lookup_partial_symtab (objfile, name, full_path, real_path); - if (!ps) - return 0; - - if (ps->readin) - error (_("Internal: readin %s pst for `%s' found when no symtab found."), - ps->filename, name); - - *result = PSYMTAB_TO_SYMTAB (ps); - return 1; + return 0; } /* Find which partial symtab contains PC and SECTION starting at psymtab PST. @@ -214,6 +239,8 @@ find_pc_sect_psymtab_closer (CORE_ADDR pc, struct obj_section *section, struct partial_symtab *best_pst = pst; CORE_ADDR best_addr = pst->textlow; + gdb_assert (!pst->psymtabs_addrmap_supported); + /* An objfile that has its functions reordered might have many partial symbol tables containing the PC, but we want the partial symbol table that contains the @@ -337,7 +364,8 @@ find_pc_sect_psymtab (struct objfile *objfile, CORE_ADDR pc, debug info type in single OBJFILE. */ ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst) - if (pc >= pst->textlow && pc < pst->texthigh) + if (!pst->psymtabs_addrmap_supported + && pc >= pst->textlow && pc < pst->texthigh) { struct partial_symtab *best_pst; @@ -588,7 +616,8 @@ match_partial_symbol (struct partial_symtab *pst, int global, static void pre_expand_symtabs_matching_psymtabs (struct objfile *objfile, - int kind, const char *name, + enum block_enum block_kind, + const char *name, domain_enum domain) { /* Nothing. */ @@ -690,8 +719,15 @@ lookup_partial_symbol (struct partial_symtab *pst, const char *name, internal_error (__FILE__, __LINE__, _("failed internal consistency check")); - while (top <= real_top - && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name)) + /* For `case_sensitivity == case_sensitive_off' strcmp_iw_ordered will + search more exactly than what matches SYMBOL_MATCHES_SEARCH_NAME. */ + while (top >= start && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name)) + top--; + + /* Fixup to have a symbol which matches SYMBOL_MATCHES_SEARCH_NAME. */ + top++; + + while (top <= real_top && SYMBOL_MATCHES_SEARCH_NAME (*top, search_name)) { if (symbol_matches_domain (SYMBOL_LANGUAGE (*top), SYMBOL_DOMAIN (*top), domain)) @@ -961,6 +997,8 @@ dump_psymtab (struct objfile *objfile, struct partial_symtab *psymtab, fprintf_filtered (outfile, "-"); fputs_filtered (paddress (gdbarch, psymtab->texthigh), outfile); fprintf_filtered (outfile, "\n"); + fprintf_filtered (outfile, " Address map supported - %s.\n", + psymtab->psymtabs_addrmap_supported ? "yes" : "no"); fprintf_filtered (outfile, " Depends on %d other partial symtabs.\n", psymtab->number_of_dependencies); for (i = 0; i < psymtab->number_of_dependencies; i++) @@ -1074,9 +1112,8 @@ read_psymtabs_with_filename (struct objfile *objfile, const char *filename) static void map_symbol_filenames_psymtab (struct objfile *objfile, - void (*fun) (const char *, const char *, - void *), - void *data) + symbol_filename_ftype *fun, void *data, + int need_fullname) { struct partial_symtab *ps; @@ -1087,7 +1124,11 @@ map_symbol_filenames_psymtab (struct objfile *objfile, if (ps->readin) continue; - fullname = psymtab_to_fullname (ps); + QUIT; + if (need_fullname) + fullname = psymtab_to_fullname (ps); + else + fullname = NULL; (*fun) (ps->filename, fullname, data); } } @@ -1103,6 +1144,7 @@ int find_and_open_source (const char *filename, If this function fails to find the file that this partial_symtab represents, NULL will be returned and ps->fullname will be set to NULL. */ + static char * psymtab_to_fullname (struct partial_symtab *ps) { @@ -1111,8 +1153,12 @@ psymtab_to_fullname (struct partial_symtab *ps) if (!ps) return NULL; - /* Don't check ps->fullname here, the file could have been - deleted/moved/..., look for it again. */ + /* Use cached copy if we have it. + We rely on forget_cached_source_info being called appropriately + to handle cases like the file being moved. */ + if (ps->fullname) + return ps->fullname; + r = find_and_open_source (ps->filename, ps->dirname, &ps->fullname); if (r >= 0) @@ -1203,13 +1249,12 @@ map_matching_symbols_psymtab (const char *name, domain_enum namespace, } static void -expand_symtabs_matching_via_partial (struct objfile *objfile, - int (*file_matcher) (const char *, - void *), - int (*name_matcher) (const char *, - void *), - domain_enum kind, - void *data) +expand_symtabs_matching_via_partial + (struct objfile *objfile, + int (*file_matcher) (const char *, void *), + int (*name_matcher) (const struct language_defn *, const char *, void *), + enum search_domain kind, + void *data) { struct partial_symtab *ps; @@ -1259,7 +1304,8 @@ expand_symtabs_matching_via_partial (struct objfile *objfile, && SYMBOL_CLASS (*psym) == LOC_BLOCK) || (kind == TYPES_DOMAIN && SYMBOL_CLASS (*psym) == LOC_TYPEDEF)) - && (*name_matcher) (SYMBOL_NATURAL_NAME (*psym), data)) + && (*name_matcher) (current_language, + SYMBOL_NATURAL_NAME (*psym), data)) { PSYMTAB_TO_SYMTAB (ps); keep_going = 0; @@ -1281,7 +1327,7 @@ const struct quick_symbol_functions psym_functions = objfile_has_psyms, find_last_source_symtab_from_partial, forget_cached_source_info_partial, - lookup_symtab_via_partial_symtab, + partial_map_symtabs_matching_filename, lookup_symbol_aux_psymtabs, pre_expand_symtabs_matching_psymtabs, print_psymtab_stats_for_objfile, @@ -1758,6 +1804,9 @@ maintenance_info_psymtabs (char *regexp, int from_tty) fputs_filtered (paddress (gdbarch, psymtab->texthigh), gdb_stdout); printf_filtered ("\n"); + printf_filtered (" psymtabs_addrmap_supported %s\n", + (psymtab->psymtabs_addrmap_supported + ? "yes" : "no")); printf_filtered (" globals "); if (psymtab->n_global_syms) { @@ -1896,7 +1945,9 @@ maintenance_check_symtabs (char *ignore, int from_tty) void -expand_partial_symbol_names (int (*fun) (const char *, void *), void *data) +expand_partial_symbol_names (int (*fun) (const struct language_defn *, + const char *, void *), + void *data) { struct objfile *objfile; @@ -1909,15 +1960,15 @@ expand_partial_symbol_names (int (*fun) (const char *, void *), void *data) } void -map_partial_symbol_filenames (void (*fun) (const char *, const char *, - void *), - void *data) +map_partial_symbol_filenames (symbol_filename_ftype *fun, void *data, + int need_fullname) { struct objfile *objfile; ALL_OBJFILES (objfile) { if (objfile->sf) - objfile->sf->qf->map_symbol_filenames (objfile, fun, data); + objfile->sf->qf->map_symbol_filenames (objfile, fun, data, + need_fullname); } } diff --git a/contrib/gdb-7/gdb/psymtab.h b/contrib/gdb-7/gdb/psymtab.h index 086ff2fb66..8fd91ee283 100644 --- a/contrib/gdb-7/gdb/psymtab.h +++ b/contrib/gdb-7/gdb/psymtab.h @@ -1,6 +1,6 @@ /* Public partial symbol table definitions. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -20,6 +20,8 @@ #ifndef PSYMTAB_H #define PSYMTAB_H +#include "symfile.h" + /* A bcache for partial symbols. */ struct psymbol_bcache; @@ -28,12 +30,12 @@ extern struct psymbol_bcache *psymbol_bcache_init (void); extern void psymbol_bcache_free (struct psymbol_bcache *); extern struct bcache *psymbol_bcache_get_bcache (struct psymbol_bcache *); -void expand_partial_symbol_names (int (*fun) (const char *, void *), +void expand_partial_symbol_names (int (*fun) (const struct language_defn *, + const char *, void *), void *data); -void map_partial_symbol_filenames (void (*) (const char *, const char *, - void *), - void *); +void map_partial_symbol_filenames (symbol_filename_ftype *fun, void *data, + int need_fullname); extern const struct quick_symbol_functions psym_functions; diff --git a/contrib/gdb-7/gdb/python/lib/gdb/__init__.py b/contrib/gdb-7/gdb/python/lib/gdb/__init__.py index 43975c2819..a82e4959e4 100644 --- a/contrib/gdb-7/gdb/python/lib/gdb/__init__.py +++ b/contrib/gdb-7/gdb/python/lib/gdb/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,6 +13,29 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -import gdb.command.pretty_printers +import traceback -gdb.command.pretty_printers.register_pretty_printer_commands() +# Auto-load all functions/commands. + +# Modules to auto-load, and the paths where those modules exist. + +module_dict = { + 'gdb.function': os.path.join(gdb.PYTHONDIR, 'gdb', 'function'), + 'gdb.command': os.path.join(gdb.PYTHONDIR, 'gdb', 'command') +} + +# Iterate the dictionary, collating the Python files in each module +# path. Construct the module name, and import. + +for module, location in module_dict.iteritems(): + if os.path.exists(location): + py_files = filter(lambda x: x.endswith('.py') and x != '__init__.py', + os.listdir(location)) + + for py_file in py_files: + # Construct from foo.py, gdb.module.foo + py_file = module + '.' + py_file[:-3] + try: + exec('import ' + py_file) + except: + print >> sys.stderr, traceback.format_exc() diff --git a/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py b/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py index ee2b61ff06..0eb19f24a9 100644 --- a/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py +++ b/contrib/gdb-7/gdb/python/lib/gdb/command/__init__.py @@ -1,4 +1,4 @@ -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py b/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py index 86923d7cf8..3ae3517edd 100644 --- a/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py +++ b/contrib/gdb-7/gdb/python/lib/gdb/command/pretty_printers.py @@ -1,5 +1,5 @@ # Pretty-printer commands. -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -148,7 +148,7 @@ class InfoPrettyPrinter(gdb.Command): def invoke1(self, title, printer_list, obj_name_to_match, object_re, name_re, subname_re): - """"Subroutine of invoke to simplify it.""" + """Subroutine of invoke to simplify it.""" if printer_list and object_re.match(obj_name_to_match): print title self.list_pretty_printers(printer_list, name_re, subname_re) @@ -368,3 +368,5 @@ def register_pretty_printer_commands(): InfoPrettyPrinter() EnablePrettyPrinter() DisablePrettyPrinter() + +register_pretty_printer_commands() diff --git a/contrib/gdb-7/gdb/python/lib/gdb/command/prompt.py b/contrib/gdb-7/gdb/python/lib/gdb/command/prompt.py new file mode 100644 index 0000000000..2bc03ef3e1 --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/command/prompt.py @@ -0,0 +1,66 @@ +# Extended prompt. +# Copyright (C) 2011-2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +"""GDB command for working with extended prompts.""" + +import gdb +import gdb.prompt + +class _ExtendedPrompt(gdb.Parameter): + + """Set the extended prompt. + +Usage: set extended-prompt VALUE + +Substitutions are applied to VALUE to compute the real prompt. + +The currently defined substitutions are: + +""" + # Add the prompt library's dynamically generated help to the + # __doc__ string. + __doc__ = __doc__ + gdb.prompt.prompt_help() + + set_doc = "Set the extended prompt." + show_doc = "Show the extended prompt." + + def __init__(self): + super(_ExtendedPrompt, self).__init__("extended-prompt", + gdb.COMMAND_SUPPORT, + gdb.PARAM_STRING_NOESCAPE) + self.value = '' + self.hook_set = False + + def get_show_string (self, pvalue): + if self.value is not '': + return "The extended prompt is: " + self.value + else: + return "The extended prompt is not set." + + def get_set_string (self): + if self.hook_set == False: + gdb.prompt_hook = self.before_prompt_hook + self.hook_set = True + return "" + + def before_prompt_hook(self, current): + if self.value is not '': + newprompt = gdb.prompt.substitute_prompt(self.value) + return newprompt.replace('\\', '\\\\') + else: + return None + +_ExtendedPrompt() diff --git a/contrib/gdb-7/gdb/python/lib/gdb/printing.py b/contrib/gdb-7/gdb/python/lib/gdb/printing.py index ff24bb4e7a..98cfd27462 100644 --- a/contrib/gdb-7/gdb/python/lib/gdb/printing.py +++ b/contrib/gdb-7/gdb/python/lib/gdb/printing.py @@ -1,5 +1,5 @@ # Pretty-printer utilities. -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -26,12 +26,12 @@ class PrettyPrinter(object): Attributes: name: A unique string among all printers for the context in which - it is defined (objfile, progspace, or global(gdb)), and should - meaningfully describe what can be pretty-printed. - E.g., "StringPiece" or "protobufs". + it is defined (objfile, progspace, or global(gdb)), and should + meaningfully describe what can be pretty-printed. + E.g., "StringPiece" or "protobufs". subprinters: An iterable object with each element having a `name' - attribute, and, potentially, "enabled" attribute. - Or this is None if there are no subprinters. + attribute, and, potentially, "enabled" attribute. + Or this is None if there are no subprinters. enabled: A boolean indicating if the printer is enabled. Subprinters are for situations where "one" pretty-printer is actually a @@ -68,17 +68,21 @@ class SubPrettyPrinter(object): self.enabled = True -def register_pretty_printer(obj, printer): +def register_pretty_printer(obj, printer, replace=False): """Register pretty-printer PRINTER with OBJ. The printer is added to the front of the search list, thus one can override - an existing printer if one needs to. + an existing printer if one needs to. Use a different name when overriding + an existing printer, otherwise an exception will be raised; multiple + printers with the same name are disallowed. Arguments: obj: Either an objfile, progspace, or None (in which case the printer - is registered globally). + is registered globally). printer: Either a function of one argument (old way) or any object - which has attributes: name, enabled, __call__. + which has attributes: name, enabled, __call__. + replace: If True replace any existing copy of the printer. + Otherwise if the printer already exists raise an exception. Returns: Nothing. @@ -86,6 +90,7 @@ def register_pretty_printer(obj, printer): Raises: TypeError: A problem with the type of the printer. ValueError: The printer's name contains a semicolon ";". + RuntimeError: A printer with the same name is already registered. If the caller wants the printer to be listable and disableable, it must follow the PrettyPrinter API. This applies to the old way (functions) too. @@ -125,10 +130,16 @@ def register_pretty_printer(obj, printer): # Alas, we can't do the same for functions and __name__, they could # all have a canonical name like "lookup_function". # PERF: gdb records printers in a list, making this inefficient. - if (printer.name in - [p.name for p in obj.pretty_printers if hasattr(p, "name")]): - raise RuntimeError("pretty-printer already registered: %s" % - printer.name) + i = 0 + for p in obj.pretty_printers: + if hasattr(p, "name") and p.name == printer.name: + if replace: + del obj.pretty_printers[i] + break + else: + raise RuntimeError("pretty-printer already registered: %s" % + printer.name) + i = i + 1 obj.pretty_printers.insert(0, printer) @@ -164,7 +175,7 @@ class RegexpCollectionPrettyPrinter(PrettyPrinter): name: The name of the subprinter. regexp: The regular expression, as a string. gen_printer: A function/method that given a value returns an - object to pretty-print it. + object to pretty-print it. Returns: Nothing. diff --git a/contrib/gdb-7/gdb/python/lib/gdb/prompt.py b/contrib/gdb-7/gdb/python/lib/gdb/prompt.py new file mode 100644 index 0000000000..1f49b54888 --- /dev/null +++ b/contrib/gdb-7/gdb/python/lib/gdb/prompt.py @@ -0,0 +1,149 @@ +# Extended prompt utilities. +# Copyright (C) 2011-2012 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +""" Extended prompt library functions.""" + +import gdb +import os + +def _prompt_pwd(ignore): + "The current working directory." + return os.getcwdu() + +def _prompt_object_attr(func, what, attr, nattr): + """Internal worker for fetching GDB attributes.""" + if attr is None: + attr = nattr + try: + obj = func() + except gdb.error: + return '' % what + if hasattr(obj, attr): + result = getattr(obj, attr) + if callable(result): + result = result() + return result + else: + return '' % (attr, what) + +def _prompt_frame(attr): + "The selected frame; an argument names a frame parameter." + return _prompt_object_attr(gdb.selected_frame, 'frame', attr, 'name') + +def _prompt_thread(attr): + "The selected thread; an argument names a thread parameter." + return _prompt_object_attr(gdb.selected_thread, 'thread', attr, 'num') + +def _prompt_version(attr): + "The version of GDB." + return gdb.VERSION + +def _prompt_esc(attr): + "The ESC character." + return '\033' + +def _prompt_bs(attr): + "A backslash." + return '\\' + +def _prompt_n(attr): + "A newline." + return '\n' + +def _prompt_r(attr): + "A carriage return." + return '\r' + +def _prompt_param(attr): + "A parameter's value; the argument names the parameter." + return gdb.parameter(attr) + +def _prompt_noprint_begin(attr): + "Begins a sequence of non-printing characters." + return '\001' + +def _prompt_noprint_end(attr): + "Ends a sequence of non-printing characters." + return '\002' + +prompt_substitutions = { + 'e': _prompt_esc, + '\\': _prompt_bs, + 'n': _prompt_n, + 'r': _prompt_r, + 'v': _prompt_version, + 'w': _prompt_pwd, + 'f': _prompt_frame, + 't': _prompt_thread, + 'p': _prompt_param, + '[': _prompt_noprint_begin, + ']': _prompt_noprint_end +} + +def prompt_help(): + """Generate help dynamically from the __doc__ strings of attribute + functions.""" + + result = '' + keys = prompt_substitutions.keys() + keys.sort() + for key in keys: + result += ' \\%s\t%s\n' % (key, prompt_substitutions[key].__doc__) + result += """ +A substitution can be used in a simple form, like "\\f". +An argument can also be passed to it, like "\\f{name}". +The meaning of the argument depends on the particular substitution.""" + return result + +def substitute_prompt(prompt): + "Perform substitutions on PROMPT." + + result = '' + plen = len(prompt) + i = 0 + while i < plen: + if prompt[i] == '\\': + i = i + 1 + if i >= plen: + break + cmdch = prompt[i] + + if cmdch in prompt_substitutions: + cmd = prompt_substitutions[cmdch] + + if i + 1 < plen and prompt[i + 1] == '{': + j = i + 1 + while j < plen and prompt[j] != '}': + j = j + 1 + # Just ignore formatting errors. + if j >= plen or prompt[j] != '}': + arg = None + else: + arg = prompt[i + 2 : j] + i = j + else: + arg = None + result += str(cmd(arg)) + else: + # Unrecognized escapes are turned into the escaped + # character itself. + result += prompt[i] + else: + result += prompt[i] + + i = i + 1 + + return result diff --git a/contrib/gdb-7/gdb/python/lib/gdb/types.py b/contrib/gdb-7/gdb/python/lib/gdb/types.py index 54fbe3c7bf..aca84f3f66 100644 --- a/contrib/gdb-7/gdb/python/lib/gdb/types.py +++ b/contrib/gdb-7/gdb/python/lib/gdb/types.py @@ -1,5 +1,5 @@ # Type utilities. -# Copyright (C) 2010, 2011 Free Software Foundation, Inc. +# Copyright (C) 2010-2012 Free Software Foundation, Inc. # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -89,3 +89,23 @@ def make_enum_dict(enum_type): # The enum's value is stored in "bitpos". enum_dict[field.name] = field.bitpos return enum_dict + + +def deep_items (type_): + """Return an iterator that recursively traverses anonymous fields. + + Arguments: + type_: The type to traverse. It should be one of + gdb.TYPE_CODE_STRUCT or gdb.TYPE_CODE_UNION. + + Returns: + an iterator similar to gdb.Type.iteritems(), i.e., it returns + pairs of key, value, but for any anonymous struct or union + field that field is traversed recursively, depth-first. + """ + for k, v in type_.iteritems (): + if k: + yield k, v + else: + for i in deep_items (v.type): + yield i diff --git a/contrib/gdb-7/gdb/python/py-auto-load.c b/contrib/gdb-7/gdb/python/py-auto-load.c index e822838ebd..3abb82a15c 100644 --- a/contrib/gdb-7/gdb/python/py-auto-load.c +++ b/contrib/gdb-7/gdb/python/py-auto-load.c @@ -1,6 +1,6 @@ /* GDB routines for supporting auto-loaded scripts. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +18,7 @@ along with this program. If not, see . */ #include "defs.h" +#include "filenames.h" #include "gdb_string.h" #include "gdb_regex.h" #include "top.h" @@ -68,11 +69,15 @@ struct auto_load_pspace_info { /* For each program space we keep track of loaded scripts. */ struct htab *loaded_scripts; + + /* Non-zero if we've issued the warning about an auto-load script not being + found. We only want to issue this warning once. */ + int script_not_found_warning_printed; }; /* Objects of this type are stored in the loaded script hash table. */ -struct loaded_script_entry +struct loaded_script { /* Name as provided by the objfile. */ const char *name; @@ -132,7 +137,7 @@ get_auto_load_pspace_data (struct program_space *pspace) static hashval_t hash_loaded_script_entry (const void *data) { - const struct loaded_script_entry *e = data; + const struct loaded_script *e = data; return htab_hash_string (e->name); } @@ -142,17 +147,17 @@ hash_loaded_script_entry (const void *data) static int eq_loaded_script_entry (const void *a, const void *b) { - const struct loaded_script_entry *ea = a; - const struct loaded_script_entry *eb = b; + const struct loaded_script *ea = a; + const struct loaded_script *eb = b; return strcmp (ea->name, eb->name) == 0; } -/* Create the hash table used for loaded scripts. +/* Initialize the table to track loaded scripts. Each entry is hashed by the full path name. */ static void -create_loaded_scripts_hash (struct auto_load_pspace_info *pspace_info) +init_loaded_scripts_info (struct auto_load_pspace_info *pspace_info) { /* Choose 31 as the starting size of the hash table, somewhat arbitrarily. Space for each entry is obtained with one malloc so we can free them @@ -162,6 +167,64 @@ create_loaded_scripts_hash (struct auto_load_pspace_info *pspace_info) hash_loaded_script_entry, eq_loaded_script_entry, xfree); + + pspace_info->script_not_found_warning_printed = FALSE; +} + +/* Wrapper on get_auto_load_pspace_data to also allocate the hash table + for loading scripts. */ + +static struct auto_load_pspace_info * +get_auto_load_pspace_data_for_loading (struct program_space *pspace) +{ + struct auto_load_pspace_info *info; + + info = get_auto_load_pspace_data (pspace); + if (info->loaded_scripts == NULL) + init_loaded_scripts_info (info); + + return info; +} + +/* Add script NAME to hash table HTAB. + FULL_PATH is NULL if the script wasn't found. + The result is true if the script was already in the hash table. */ + +static int +maybe_add_script (struct htab *htab, const char *name, const char *full_path) +{ + struct loaded_script **slot, entry; + int in_hash_table; + + entry.name = name; + entry.full_path = full_path; + slot = (struct loaded_script **) htab_find_slot (htab, &entry, INSERT); + in_hash_table = *slot != NULL; + + /* If this script is not in the hash table, add it. */ + + if (! in_hash_table) + { + char *p; + + /* Allocate all space in one chunk so it's easier to free. */ + *slot = xmalloc (sizeof (**slot) + + strlen (name) + 1 + + (full_path != NULL ? (strlen (full_path) + 1) : 0)); + p = ((char*) *slot) + sizeof (**slot); + strcpy (p, name); + (*slot)->name = p; + if (full_path != NULL) + { + p += strlen (p) + 1; + strcpy (p, full_path); + (*slot)->full_path = p; + } + else + (*slot)->full_path = NULL; + } + + return in_hash_table; } /* Load scripts specified in OBJFILE. @@ -182,11 +245,8 @@ source_section_scripts (struct objfile *objfile, const char *source_name, { const char *p; struct auto_load_pspace_info *pspace_info; - struct loaded_script_entry **slot, entry; - pspace_info = get_auto_load_pspace_data (current_program_space); - if (pspace_info->loaded_scripts == NULL) - create_loaded_scripts_hash (pspace_info); + pspace_info = get_auto_load_pspace_data_for_loading (current_program_space); for (p = start; p < end; ++p) { @@ -226,57 +286,36 @@ source_section_scripts (struct objfile *objfile, const char *source_name, opened = find_and_open_script (file, 1 /*search_path*/, &stream, &full_path); - /* If the file is not found, we still record the file in the hash table, - we only want to print an error message once. + /* If one script isn't found it's not uncommon for more to not be + found either. We don't want to print an error message for each + script, too much noise. Instead, we print the warning once and tell + the user how to find the list of scripts that weren't loaded. + IWBN if complaints.c were more general-purpose. */ - entry.name = file; - if (opened) - entry.full_path = full_path; - else - entry.full_path = NULL; - slot = ((struct loaded_script_entry **) - htab_find_slot (pspace_info->loaded_scripts, - &entry, INSERT)); - in_hash_table = *slot != NULL; - - /* If this file is not in the hash table, add it. */ - if (! in_hash_table) + in_hash_table = maybe_add_script (pspace_info->loaded_scripts, file, + opened ? full_path : NULL); + + if (! opened) { - char *p; - - *slot = xmalloc (sizeof (**slot) - + strlen (file) + 1 - + (opened ? (strlen (full_path) + 1) : 0)); - p = ((char*) *slot) + sizeof (**slot); - strcpy (p, file); - (*slot)->name = p; - if (opened) + /* We don't throw an error, the program is still debuggable. */ + if (! pspace_info->script_not_found_warning_printed) { - p += strlen (p) + 1; - strcpy (p, full_path); - (*slot)->full_path = p; + warning (_("Missing auto-load scripts referenced in section %s\n\ +of file %s\n\ +Use `info auto-load-scripts [REGEXP]' to list them."), + GDBPY_AUTO_SECTION_NAME, objfile->name); + pspace_info->script_not_found_warning_printed = TRUE; } - else - (*slot)->full_path = NULL; } - - if (opened) - free (full_path); - - if (! opened) + else { - /* We don't throw an error, the program is still debuggable. - Check in_hash_table to only print the warning once. */ + /* If this file is not currently loaded, load it. */ if (! in_hash_table) - warning (_("%s (referenced in %s): %s"), - file, GDBPY_AUTO_SECTION_NAME, safe_strerror (errno)); - continue; + source_python_script_for_objfile (objfile, full_path); + fclose (stream); + xfree (full_path); } - - /* If this file is not currently loaded, load it. */ - if (! in_hash_table) - source_python_script_for_objfile (objfile, stream, file); } } @@ -322,6 +361,7 @@ clear_section_scripts (void) { htab_delete (info->loaded_scripts); info->loaded_scripts = NULL; + info->script_not_found_warning_printed = FALSE; } } @@ -378,7 +418,20 @@ auto_load_objfile_script (struct objfile *objfile, const char *suffix) if (input) { - source_python_script_for_objfile (objfile, input, debugfile); + struct auto_load_pspace_info *pspace_info; + + /* Add this script to the hash table too so "info auto-load-scripts" + can print it. */ + pspace_info = + get_auto_load_pspace_data_for_loading (current_program_space); + maybe_add_script (pspace_info->loaded_scripts, debugfile, debugfile); + + /* To preserve existing behaviour we don't check for whether the + script was already in the table, and always load it. + It's highly unlikely that we'd ever load it twice, + and these scripts are required to be idempotent under multiple + loads anyway. */ + source_python_script_for_objfile (objfile, debugfile); fclose (input); } @@ -416,56 +469,136 @@ load_auto_scripts_for_objfile (struct objfile *objfile) } } +/* Collect scripts to be printed in a vec. */ + +typedef struct loaded_script *loaded_script_ptr; +DEF_VEC_P (loaded_script_ptr); + /* Traversal function for htab_traverse. - Print the entry if specified in the regex. */ + Collect the entry if it matches the regexp. */ static int -maybe_print_section_script (void **slot, void *info) +collect_matching_scripts (void **slot, void *info) +{ + struct loaded_script *script = *slot; + VEC (loaded_script_ptr) **scripts_ptr = info; + + if (re_exec (script->name)) + VEC_safe_push (loaded_script_ptr, *scripts_ptr, script); + + return 1; +} + +/* Print SCRIPT. */ + +static void +print_script (struct loaded_script *script) { - struct loaded_script_entry *entry = *slot; + struct ui_out *uiout = current_uiout; + struct cleanup *chain; - if (re_exec (entry->name)) + chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + ui_out_field_string (uiout, "loaded", script->full_path ? "Yes" : "Missing"); + ui_out_field_string (uiout, "script", script->name); + ui_out_text (uiout, "\n"); + + /* If the name isn't the full path, print it too. */ + if (script->full_path != NULL + && strcmp (script->name, script->full_path) != 0) { - printf_filtered (_("Script name: %s\n"), entry->name); - printf_filtered (_(" Full name: %s\n"), - entry->full_path ? entry->full_path : _("unknown")); + ui_out_text (uiout, "\tfull name: "); + ui_out_field_string (uiout, "full_path", script->full_path); + ui_out_text (uiout, "\n"); } - return 1; + do_cleanups (chain); +} + +/* Helper for info_auto_load_scripts to sort the scripts by name. */ + +static int +sort_scripts_by_name (const void *ap, const void *bp) +{ + const struct loaded_script *a = *(const struct loaded_script **) ap; + const struct loaded_script *b = *(const struct loaded_script **) bp; + + return FILENAME_CMP (a->name, b->name); } -/* "maint print section-scripts" command. */ +/* "info auto-load-scripts" command. */ static void -maintenance_print_section_scripts (char *pattern, int from_tty) +info_auto_load_scripts (char *pattern, int from_tty) { + struct ui_out *uiout = current_uiout; struct auto_load_pspace_info *pspace_info; + struct cleanup *script_chain; + VEC (loaded_script_ptr) *scripts; + int nr_scripts; dont_repeat (); + pspace_info = get_auto_load_pspace_data (current_program_space); + if (pattern && *pattern) { char *re_err = re_comp (pattern); if (re_err) error (_("Invalid regexp: %s"), re_err); - - printf_filtered (_("Objfile scripts matching %s:\n"), pattern); } else { re_comp (""); - printf_filtered (_("Objfile scripts:\n")); } - pspace_info = get_auto_load_pspace_data (current_program_space); - if (pspace_info == NULL || pspace_info->loaded_scripts == NULL) - return; + /* We need to know the number of rows before we build the table. + Plus we want to sort the scripts by name. + So first traverse the hash table collecting the matching scripts. */ + + scripts = VEC_alloc (loaded_script_ptr, 10); + script_chain = make_cleanup (VEC_cleanup (loaded_script_ptr), &scripts); + + if (pspace_info != NULL && pspace_info->loaded_scripts != NULL) + { + immediate_quit++; + /* Pass a pointer to scripts as VEC_safe_push can realloc space. */ + htab_traverse_noresize (pspace_info->loaded_scripts, + collect_matching_scripts, &scripts); + immediate_quit--; + } - immediate_quit++; - htab_traverse_noresize (pspace_info->loaded_scripts, - maybe_print_section_script, NULL); - immediate_quit--; + nr_scripts = VEC_length (loaded_script_ptr, scripts); + make_cleanup_ui_out_table_begin_end (uiout, 2, nr_scripts, + "AutoLoadedScriptsTable"); + + ui_out_table_header (uiout, 7, ui_left, "loaded", "Loaded"); + ui_out_table_header (uiout, 70, ui_left, "script", "Script"); + ui_out_table_body (uiout); + + if (nr_scripts > 0) + { + int i; + loaded_script_ptr script; + + qsort (VEC_address (loaded_script_ptr, scripts), + VEC_length (loaded_script_ptr, scripts), + sizeof (loaded_script_ptr), sort_scripts_by_name); + for (i = 0; VEC_iterate (loaded_script_ptr, scripts, i, script); ++i) + print_script (script); + } + + do_cleanups (script_chain); + + if (nr_scripts == 0) + { + if (pattern && *pattern) + ui_out_message (uiout, 0, "No auto-load scripts matching %s.\n", + pattern); + else + ui_out_message (uiout, 0, "No auto-load scripts.\n"); + } } void @@ -486,10 +619,10 @@ an executable or shared library."), &setlist, &showlist); - add_cmd ("section-scripts", class_maintenance, - maintenance_print_section_scripts, - _("Print dump of auto-loaded section scripts matching REGEXP."), - &maintenanceprintlist); + add_info ("auto-load-scripts", + info_auto_load_scripts, + _("Print the list of automatically loaded scripts.\n\ +Usage: info auto-load-scripts [REGEXP]")); } #else /* ! HAVE_PYTHON */ diff --git a/contrib/gdb-7/gdb/python/py-block.c b/contrib/gdb-7/gdb/python/py-block.c index 08d4455508..ac48193121 100644 --- a/contrib/gdb-7/gdb/python/py-block.c +++ b/contrib/gdb-7/gdb/python/py-block.c @@ -1,6 +1,6 @@ /* Python interface to blocks. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -28,7 +28,7 @@ typedef struct blpy_block_object { PyObject_HEAD /* The GDB block structure that represents a frame's code block. */ - struct block *block; + const struct block *block; /* The backing object file. There is no direct relationship in GDB between a block and an object file. When a block is created also store a pointer to the object file for later use. */ @@ -85,7 +85,7 @@ static PyObject * blpy_iter (PyObject *self) { block_syms_iterator_object *block_iter_obj; - struct block *block = NULL; + const struct block *block = NULL; BLPY_REQUIRE_VALID (self, block); @@ -105,7 +105,7 @@ blpy_iter (PyObject *self) static PyObject * blpy_get_start (PyObject *self, void *closure) { - struct block *block = NULL; + const struct block *block = NULL; BLPY_REQUIRE_VALID (self, block); @@ -115,7 +115,7 @@ blpy_get_start (PyObject *self, void *closure) static PyObject * blpy_get_end (PyObject *self, void *closure) { - struct block *block = NULL; + const struct block *block = NULL; BLPY_REQUIRE_VALID (self, block); @@ -126,7 +126,7 @@ static PyObject * blpy_get_function (PyObject *self, void *closure) { struct symbol *sym; - struct block *block = NULL; + const struct block *block; BLPY_REQUIRE_VALID (self, block); @@ -140,8 +140,8 @@ blpy_get_function (PyObject *self, void *closure) static PyObject * blpy_get_superblock (PyObject *self, void *closure) { - struct block *block = NULL; - struct block *super_block = NULL; + const struct block *block; + const struct block *super_block; block_object *self_obj = (block_object *) self; BLPY_REQUIRE_VALID (self, block); @@ -153,6 +153,77 @@ blpy_get_superblock (PyObject *self, void *closure) Py_RETURN_NONE; } +/* Return the global block associated to this block. */ + +static PyObject * +blpy_get_global_block (PyObject *self, void *closure) +{ + const struct block *block; + const struct block *global_block; + block_object *self_obj = (block_object *) self; + + BLPY_REQUIRE_VALID (self, block); + + global_block = block_global_block (block); + + return block_to_block_object (global_block, + self_obj->objfile); + +} + +/* Return the static block associated to this block. Return None + if we cannot get the static block (this is the global block). */ + +static PyObject * +blpy_get_static_block (PyObject *self, void *closure) +{ + const struct block *block; + const struct block *static_block; + block_object *self_obj = (block_object *) self; + + BLPY_REQUIRE_VALID (self, block); + + if (BLOCK_SUPERBLOCK (block) == NULL) + Py_RETURN_NONE; + + static_block = block_static_block (block); + + return block_to_block_object (static_block, self_obj->objfile); +} + +/* Implementation of gdb.Block.is_global (self) -> Boolean. + Returns True if this block object is a global block. */ + +static PyObject * +blpy_is_global (PyObject *self, void *closure) +{ + const struct block *block; + + BLPY_REQUIRE_VALID (self, block); + + if (BLOCK_SUPERBLOCK (block)) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Implementation of gdb.Block.is_static (self) -> Boolean. + Returns True if this block object is a static block. */ + +static PyObject * +blpy_is_static (PyObject *self, void *closure) +{ + const struct block *block; + + BLPY_REQUIRE_VALID (self, block); + + if (BLOCK_SUPERBLOCK (block) != NULL + && BLOCK_SUPERBLOCK (BLOCK_SUPERBLOCK (block)) == NULL) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + static void blpy_dealloc (PyObject *obj) { @@ -176,7 +247,7 @@ blpy_dealloc (PyObject *obj) with the life-cycle of the object file associated with this block, if needed. */ static void -set_block (block_object *obj, struct block *block, +set_block (block_object *obj, const struct block *block, struct objfile *objfile) { obj->block = block; @@ -196,7 +267,7 @@ set_block (block_object *obj, struct block *block, /* Create a new block object (gdb.Block) that encapsulates the struct block object from GDB. */ PyObject * -block_to_block_object (struct block *block, struct objfile *objfile) +block_to_block_object (const struct block *block, struct objfile *objfile) { block_object *block_obj; @@ -208,7 +279,7 @@ block_to_block_object (struct block *block, struct objfile *objfile) } /* Return struct block reference that is wrapped by this object. */ -struct block * +const struct block * block_object_to_block (PyObject *obj) { if (! PyObject_TypeCheck (obj, &block_object_type)) @@ -269,7 +340,7 @@ blpy_block_syms_dealloc (PyObject *obj) static PyObject * blpy_is_valid (PyObject *self, PyObject *args) { - struct block *block; + const struct block *block; block = block_object_to_block (self); if (block == NULL) @@ -300,14 +371,20 @@ gdbpy_block_for_pc (PyObject *self, PyObject *args) { gdb_py_ulongest pc; struct block *block; - struct obj_section *section; - struct symtab *symtab; + struct obj_section *section = NULL; + struct symtab *symtab = NULL; + volatile struct gdb_exception except; if (!PyArg_ParseTuple (args, GDB_PY_LLU_ARG, &pc)) return NULL; - section = find_pc_mapped_section (pc); - symtab = find_pc_sect_symtab (pc, section); + TRY_CATCH (except, RETURN_MASK_ALL) + { + section = find_pc_mapped_section (pc); + symtab = find_pc_sect_symtab (pc, section); + } + GDB_PY_HANDLE_EXCEPTION (except); + if (!symtab || symtab->objfile == NULL) { PyErr_SetString (PyExc_RuntimeError, @@ -386,6 +463,14 @@ static PyGetSetDef block_object_getset[] = { "Symbol that names the block, or None.", NULL }, { "superblock", blpy_get_superblock, NULL, "Block containing the block, or None.", NULL }, + { "global_block", blpy_get_global_block, NULL, + "Block containing the global block.", NULL }, + { "static_block", blpy_get_static_block, NULL, + "Block containing the static block.", NULL }, + { "is_static", blpy_is_static, NULL, + "Whether this block is a static block.", NULL }, + { "is_global", blpy_is_global, NULL, + "Whether this block is a global block.", NULL }, { NULL } /* Sentinel */ }; diff --git a/contrib/gdb-7/gdb/python/py-bpevent.c b/contrib/gdb-7/gdb/python/py-bpevent.c index c7f79654a1..138c39f0b2 100644 --- a/contrib/gdb-7/gdb/python/py-bpevent.c +++ b/contrib/gdb-7/gdb/python/py-bpevent.c @@ -1,6 +1,6 @@ /* Python interface to inferior breakpoint stop events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -24,7 +24,7 @@ static PyTypeObject breakpoint_event_object_type; /* Create and initialize a BreakpointEvent object. */ PyObject * -create_breakpoint_event_object (PyObject *breakpoint) +create_breakpoint_event_object (PyObject *breakpoint_list, PyObject *first_bp) { PyObject *breakpoint_event_obj = create_stop_event_object (&breakpoint_event_object_type); @@ -34,7 +34,11 @@ create_breakpoint_event_object (PyObject *breakpoint) if (evpy_add_attribute (breakpoint_event_obj, "breakpoint", - breakpoint) < 0) + first_bp) < 0) + goto fail; + if (evpy_add_attribute (breakpoint_event_obj, + "breakpoints", + breakpoint_list) < 0) goto fail; return breakpoint_event_obj; diff --git a/contrib/gdb-7/gdb/python/py-breakpoint.c b/contrib/gdb-7/gdb/python/py-breakpoint.c index 0c21bfc302..0c84d03b0a 100644 --- a/contrib/gdb-7/gdb/python/py-breakpoint.c +++ b/contrib/gdb-7/gdb/python/py-breakpoint.c @@ -1,6 +1,6 @@ /* Python interface to breakpoints - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -31,52 +31,16 @@ #include "arch-utils.h" #include "language.h" -static PyTypeObject breakpoint_object_type; - /* Number of live breakpoints. */ static int bppy_live; /* Variables used to pass information between the Breakpoint constructor and the breakpoint-created hook function. */ -static breakpoint_object *bppy_pending_object; +breakpoint_object *bppy_pending_object; /* Function that is called when a Python condition is evaluated. */ static char * const stop_func = "stop"; -struct breakpoint_object -{ - PyObject_HEAD - - /* The breakpoint number according to gdb. */ - int number; - - /* The gdb breakpoint object, or NULL if the breakpoint has been - deleted. */ - struct breakpoint *bp; -}; - -/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python - exception if it is invalid. */ -#define BPPY_REQUIRE_VALID(Breakpoint) \ - do { \ - if ((Breakpoint)->bp == NULL) \ - return PyErr_Format (PyExc_RuntimeError, \ - _("Breakpoint %d is invalid."), \ - (Breakpoint)->number); \ - } while (0) - -/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python - exception if it is invalid. This macro is for use in setter functions. */ -#define BPPY_SET_REQUIRE_VALID(Breakpoint) \ - do { \ - if ((Breakpoint)->bp == NULL) \ - { \ - PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \ - (Breakpoint)->number); \ - return -1; \ - } \ - } while (0) - /* This is used to initialize various gdb.bp_* constants. */ struct pybp_code { @@ -150,6 +114,7 @@ bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure) { breakpoint_object *self_bp = (breakpoint_object *) self; int cmp; + volatile struct gdb_exception except; BPPY_SET_REQUIRE_VALID (self_bp); @@ -170,10 +135,16 @@ bppy_set_enabled (PyObject *self, PyObject *newvalue, void *closure) cmp = PyObject_IsTrue (newvalue); if (cmp < 0) return -1; - else if (cmp == 1) - enable_breakpoint (self_bp->bp); - else - disable_breakpoint (self_bp->bp); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (cmp == 1) + enable_breakpoint (self_bp->bp); + else + disable_breakpoint (self_bp->bp); + } + GDB_PY_SET_HANDLE_EXCEPTION (except); + return 0; } @@ -255,6 +226,8 @@ bppy_set_task (PyObject *self, PyObject *newvalue, void *closure) { breakpoint_object *self_bp = (breakpoint_object *) self; long id; + int valid_id = 0; + volatile struct gdb_exception except; BPPY_SET_REQUIRE_VALID (self_bp); @@ -269,7 +242,13 @@ bppy_set_task (PyObject *self, PyObject *newvalue, void *closure) if (! gdb_py_int_as_long (newvalue, &id)) return -1; - if (! valid_task_id (id)) + TRY_CATCH (except, RETURN_MASK_ALL) + { + valid_id = valid_task_id (id); + } + GDB_PY_SET_HANDLE_EXCEPTION (except); + + if (! valid_id) { PyErr_SetString (PyExc_RuntimeError, _("Invalid task ID.")); @@ -299,10 +278,15 @@ static PyObject * bppy_delete_breakpoint (PyObject *self, PyObject *args) { breakpoint_object *self_bp = (breakpoint_object *) self; + volatile struct gdb_exception except; BPPY_REQUIRE_VALID (self_bp); - delete_breakpoint (self_bp->bp); + TRY_CATCH (except, RETURN_MASK_ALL) + { + delete_breakpoint (self_bp->bp); + } + GDB_PY_HANDLE_EXCEPTION (except); Py_RETURN_NONE; } @@ -314,6 +298,7 @@ bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure) { breakpoint_object *self_bp = (breakpoint_object *) self; long value; + volatile struct gdb_exception except; BPPY_SET_REQUIRE_VALID (self_bp); @@ -335,7 +320,12 @@ bppy_set_ignore_count (PyObject *self, PyObject *newvalue, void *closure) if (value < 0) value = 0; - set_ignore_count (self_bp->number, (int) value, 0); + + TRY_CATCH (except, RETURN_MASK_ALL) + { + set_ignore_count (self_bp->number, (int) value, 0); + } + GDB_PY_SET_HANDLE_EXCEPTION (except); return 0; } @@ -399,16 +389,16 @@ bppy_get_expression (PyObject *self, void *closure) { char *str; breakpoint_object *obj = (breakpoint_object *) self; + struct watchpoint *wp; BPPY_REQUIRE_VALID (obj); - if (obj->bp->type != bp_watchpoint - && obj->bp->type != bp_hardware_watchpoint - && obj->bp->type != bp_read_watchpoint - && obj->bp->type != bp_access_watchpoint) + if (!is_watchpoint (obj->bp)) Py_RETURN_NONE; - str = obj->bp->exp_string; + wp = (struct watchpoint *) obj->bp; + + str = wp->exp_string; if (! str) str = ""; @@ -492,12 +482,12 @@ bppy_get_commands (PyObject *self, void *closure) string_file = mem_fileopen (); chain = make_cleanup_ui_file_delete (string_file); - ui_out_redirect (uiout, string_file); + ui_out_redirect (current_uiout, string_file); TRY_CATCH (except, RETURN_MASK_ALL) { - print_command_lines (uiout, breakpoint_commands (bp), 0); + print_command_lines (current_uiout, breakpoint_commands (bp), 0); } - ui_out_redirect (uiout, NULL); + ui_out_redirect (current_uiout, NULL); GDB_PY_HANDLE_EXCEPTION (except); cmdstr = ui_file_xstrdup (string_file, &length); @@ -599,7 +589,7 @@ static int bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) { static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL }; - char *spec; + const char *spec; int type = bp_breakpoint; int access_type = hw_write; PyObject *internal = NULL; @@ -623,27 +613,31 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) TRY_CATCH (except, RETURN_MASK_ALL) { + char *copy = xstrdup (spec); + struct cleanup *cleanup = make_cleanup (xfree, copy); + switch (type) { case bp_breakpoint: { create_breakpoint (python_gdbarch, - spec, NULL, -1, + copy, NULL, -1, 0, 0, bp_breakpoint, 0, AUTO_BOOLEAN_TRUE, - NULL, 0, 1, internal_bp); + &bkpt_breakpoint_ops, + 0, 1, internal_bp, 0); break; } case bp_watchpoint: { if (access_type == hw_write) - watch_command_wrapper (spec, 0, internal_bp); + watch_command_wrapper (copy, 0, internal_bp); else if (access_type == hw_access) - awatch_command_wrapper (spec, 0, internal_bp); + awatch_command_wrapper (copy, 0, internal_bp); else if (access_type == hw_read) - rwatch_command_wrapper (spec, 0, internal_bp); + rwatch_command_wrapper (copy, 0, internal_bp); else error(_("Cannot understand watchpoint access type.")); break; @@ -651,6 +645,8 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) default: error(_("Do not understand breakpoint type to set.")); } + + do_cleanups (cleanup); } if (except.reason < 0) { @@ -691,7 +687,7 @@ build_bp_list (struct breakpoint *b, void *arg) PyObject * gdbpy_breakpoints (PyObject *self, PyObject *args) { - PyObject *list; + PyObject *list, *tuple; if (bppy_live == 0) Py_RETURN_NONE; @@ -709,7 +705,10 @@ gdbpy_breakpoints (PyObject *self, PyObject *args) return NULL; } - return PyList_AsTuple (list); + tuple = PyList_AsTuple (list); + Py_DECREF (list); + + return tuple; } /* Call the "stop" method (if implemented) in the breakpoint @@ -727,6 +726,9 @@ gdbpy_should_stop (struct breakpoint_object *bp_obj) struct gdbarch *garch = b->gdbarch ? b->gdbarch : get_current_arch (); struct cleanup *cleanup = ensure_python_env (garch, current_language); + if (bp_obj->is_finish_bp) + bpfinishpy_pre_stop_hook (bp_obj); + if (PyObject_HasAttrString (py_bp, stop_func)) { PyObject *result = PyObject_CallMethod (py_bp, stop_func, NULL); @@ -748,6 +750,10 @@ gdbpy_should_stop (struct breakpoint_object *bp_obj) else gdbpy_print_stack (); } + + if (bp_obj->is_finish_bp) + bpfinishpy_post_stop_hook (bp_obj); + do_cleanups (cleanup); return stop; @@ -766,10 +772,9 @@ gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj) get_current_arch (); struct cleanup *cleanup = ensure_python_env (garch, current_language); - if (py_bp == NULL) - return 0; + if (py_bp != NULL) + has_func = PyObject_HasAttrString (py_bp, stop_func); - has_func = PyObject_HasAttrString (py_bp, stop_func); do_cleanups (cleanup); return has_func; @@ -782,17 +787,12 @@ gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj) /* Callback that is used when a breakpoint is created. This function will create a new Python breakpoint object. */ static void -gdbpy_breakpoint_created (int num) +gdbpy_breakpoint_created (struct breakpoint *bp) { breakpoint_object *newbp; - struct breakpoint *bp = NULL; PyGILState_STATE state; - bp = get_breakpoint (num); - if (! bp) - return; - - if (num < 0 && bppy_pending_object == NULL) + if (bp->number < 0 && bppy_pending_object == NULL) return; if (bp->type != bp_breakpoint @@ -813,9 +813,10 @@ gdbpy_breakpoint_created (int num) newbp = PyObject_New (breakpoint_object, &breakpoint_object_type); if (newbp) { - newbp->number = num; + newbp->number = bp->number; newbp->bp = bp; newbp->bp->py_bp_object = newbp; + newbp->is_finish_bp = 0; Py_INCREF (newbp); ++bppy_live; } @@ -832,23 +833,24 @@ gdbpy_breakpoint_created (int num) /* Callback that is used when a breakpoint is deleted. This will invalidate the corresponding Python object. */ static void -gdbpy_breakpoint_deleted (int num) +gdbpy_breakpoint_deleted (struct breakpoint *b) { + int num = b->number; PyGILState_STATE state; struct breakpoint *bp = NULL; breakpoint_object *bp_obj; state = PyGILState_Ensure (); bp = get_breakpoint (num); - if (! bp) - return; - - bp_obj = bp->py_bp_object; - if (bp_obj) + if (bp) { - bp_obj->bp = NULL; - --bppy_live; - Py_DECREF (bp_obj); + bp_obj = bp->py_bp_object; + if (bp_obj) + { + bp_obj->bp = NULL; + --bppy_live; + Py_DECREF (bp_obj); + } } PyGILState_Release (state); } @@ -861,6 +863,7 @@ gdbpy_initialize_breakpoints (void) { int i; + breakpoint_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&breakpoint_object_type) < 0) return; @@ -975,7 +978,7 @@ static PyMethodDef breakpoint_object_methods[] = { NULL } /* Sentinel. */ }; -static PyTypeObject breakpoint_object_type = +PyTypeObject breakpoint_object_type = { PyObject_HEAD_INIT (NULL) 0, /*ob_size*/ @@ -1015,5 +1018,4 @@ static PyTypeObject breakpoint_object_type = 0, /* tp_dictoffset */ bppy_init, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ }; diff --git a/contrib/gdb-7/gdb/python/py-cmd.c b/contrib/gdb-7/gdb/python/py-cmd.c index c0e3291411..aad1ab466c 100644 --- a/contrib/gdb-7/gdb/python/py-cmd.c +++ b/contrib/gdb-7/gdb/python/py-cmd.c @@ -1,6 +1,6 @@ /* gdb commands implemented in Python - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -70,7 +70,6 @@ typedef struct cmdpy_object cmdpy_object; static PyTypeObject cmdpy_object_type; - /* Constants used by this module. */ static PyObject *invoke_cst; static PyObject *complete_cst; @@ -206,6 +205,7 @@ cmdpy_function (struct cmd_list_element *command, char *args, int from_tty) } /* Called by gdb for command completion. */ + static char ** cmdpy_completer (struct cmd_list_element *command, char *text, char *word) { @@ -300,7 +300,7 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word) /* Helper for cmdpy_init which locates the command list to use and pulls out the command name. - TEXT is the command name list. The final word in the list is the + NAME is the command name list. The final word in the list is the name of the new command. All earlier words must be existing prefix commands. @@ -311,19 +311,20 @@ cmdpy_completer (struct cmd_list_element *command, char *text, char *word) This function returns the xmalloc()d name of the new command. On error sets the Python error and returns NULL. */ + char * -gdbpy_parse_command_name (char *text, +gdbpy_parse_command_name (const char *name, struct cmd_list_element ***base_list, struct cmd_list_element **start_list) { struct cmd_list_element *elt; - int len = strlen (text); + int len = strlen (name); int i, lastchar; - char *prefix_text; + char *prefix_text, *prefix_text2; char *result; /* Skip trailing whitespace. */ - for (i = len - 1; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + for (i = len - 1; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i) ; if (i < 0) { @@ -333,17 +334,17 @@ gdbpy_parse_command_name (char *text, lastchar = i; /* Find first character of the final word. */ - for (; i > 0 && (isalnum (text[i - 1]) - || text[i - 1] == '-' - || text[i - 1] == '_'); + for (; i > 0 && (isalnum (name[i - 1]) + || name[i - 1] == '-' + || name[i - 1] == '_'); --i) ; result = xmalloc (lastchar - i + 2); - memcpy (result, &text[i], lastchar - i + 1); + memcpy (result, &name[i], lastchar - i + 1); result[lastchar - i + 1] = '\0'; /* Skip whitespace again. */ - for (--i; i >= 0 && (text[i] == ' ' || text[i] == '\t'); --i) + for (--i; i >= 0 && (name[i] == ' ' || name[i] == '\t'); --i) ; if (i < 0) { @@ -352,11 +353,11 @@ gdbpy_parse_command_name (char *text, } prefix_text = xmalloc (i + 2); - memcpy (prefix_text, text, i + 1); + memcpy (prefix_text, name, i + 1); prefix_text[i + 1] = '\0'; - text = prefix_text; - elt = lookup_cmd_1 (&text, *start_list, NULL, 1); + prefix_text2 = prefix_text; + elt = lookup_cmd_1 (&prefix_text2, *start_list, NULL, 1); if (!elt || elt == (struct cmd_list_element *) -1) { PyErr_Format (PyExc_RuntimeError, _("Could not find command prefix %s."), @@ -398,14 +399,13 @@ gdbpy_parse_command_name (char *text, If PREFIX is True, then this command is a prefix command. The documentation for the command is taken from the doc string for - the python class. - -*/ + the python class. */ + static int cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) { cmdpy_object *obj = (cmdpy_object *) self; - char *name; + const char *name; int cmdtype; int completetype = -1; char *docstring = NULL; @@ -551,11 +551,13 @@ cmdpy_init (PyObject *self, PyObject *args, PyObject *kw) /* Initialize the 'commands' code. */ + void gdbpy_initialize_commands (void) { int i; + cmdpy_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&cmdpy_object_type) < 0) return; @@ -643,7 +645,6 @@ static PyTypeObject cmdpy_object_type = 0, /* tp_dictoffset */ cmdpy_init, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ }; @@ -659,7 +660,7 @@ PyObject * gdbpy_string_to_argv (PyObject *self, PyObject *args) { PyObject *py_argv; - char *input; + const char *input; if (!PyArg_ParseTuple (args, "s", &input)) return NULL; @@ -682,14 +683,12 @@ gdbpy_string_to_argv (PyObject *self, PyObject *args) if (argp == NULL || PyList_Append (py_argv, argp) < 0) { - if (argp != NULL) - { - Py_DECREF (argp); - } + Py_XDECREF (argp); Py_DECREF (py_argv); freeargv (c_argv); return NULL; } + Py_DECREF (argp); } freeargv (c_argv); diff --git a/contrib/gdb-7/gdb/python/py-continueevent.c b/contrib/gdb-7/gdb/python/py-continueevent.c index 1338ba6b2b..4582fb5ab9 100644 --- a/contrib/gdb-7/gdb/python/py-continueevent.c +++ b/contrib/gdb-7/gdb/python/py-continueevent.c @@ -1,6 +1,6 @@ /* Python interface to inferior continue events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-event.c b/contrib/gdb-7/gdb/python/py-event.c index 88f8db6385..7d4ff14457 100644 --- a/contrib/gdb-7/gdb/python/py-event.c +++ b/contrib/gdb-7/gdb/python/py-event.c @@ -1,6 +1,6 @@ /* Python interface to inferior events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-event.h b/contrib/gdb-7/gdb/python/py-event.h index f4b3ee2569..e54c17a503 100644 --- a/contrib/gdb-7/gdb/python/py-event.h +++ b/contrib/gdb-7/gdb/python/py-event.h @@ -1,6 +1,6 @@ /* Python interface to inferior events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -104,13 +104,14 @@ typedef struct } event_object; extern int emit_continue_event (ptid_t ptid); -extern int emit_exited_event (const LONGEST *exit_code); +extern int emit_exited_event (const LONGEST *exit_code, struct inferior *inf); extern int evpy_emit_event (PyObject *event, eventregistry_object *registry); extern PyObject *create_event_object (PyTypeObject *py_type); extern PyObject *create_thread_event_object (PyTypeObject *py_type); +extern int emit_new_objfile_event (struct objfile *objfile); extern void evpy_dealloc (PyObject *self); extern int evpy_add_attribute (PyObject *event, diff --git a/contrib/gdb-7/gdb/python/py-events.h b/contrib/gdb-7/gdb/python/py-events.h index 6d4dae57c0..dbf239423e 100644 --- a/contrib/gdb-7/gdb/python/py-events.h +++ b/contrib/gdb-7/gdb/python/py-events.h @@ -1,6 +1,6 @@ /* Python interface to inferior events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -45,13 +45,14 @@ typedef struct eventregistry_object *stop; eventregistry_object *cont; eventregistry_object *exited; + eventregistry_object *new_objfile; PyObject *module; } events_object; /* Python events singleton. */ -events_object gdb_py_events; +extern events_object gdb_py_events; extern eventregistry_object *create_eventregistry_object (void); extern int evregpy_no_listeners_p (eventregistry_object *registry); diff --git a/contrib/gdb-7/gdb/python/py-evtregistry.c b/contrib/gdb-7/gdb/python/py-evtregistry.c index e1b4346c6b..0a2c336d93 100644 --- a/contrib/gdb-7/gdb/python/py-evtregistry.c +++ b/contrib/gdb-7/gdb/python/py-evtregistry.c @@ -1,6 +1,6 @@ /* Python interface to inferior thread event registries. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -21,6 +21,8 @@ #include "command.h" #include "py-events.h" +events_object gdb_py_events; + static PyTypeObject eventregistry_object_type; /* Implementation of EventRegistry.connect () -> NULL. diff --git a/contrib/gdb-7/gdb/python/py-evts.c b/contrib/gdb-7/gdb/python/py-evts.c index 50c05f3ad7..38cd128d52 100644 --- a/contrib/gdb-7/gdb/python/py-evts.c +++ b/contrib/gdb-7/gdb/python/py-evts.c @@ -1,6 +1,6 @@ /* Python interface to inferior events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -58,6 +58,9 @@ gdbpy_initialize_py_events (void) if (add_new_registry (&gdb_py_events.exited, "exited") < 0) goto fail; + if (add_new_registry (&gdb_py_events.new_objfile, "new_objfile") < 0) + goto fail; + Py_INCREF (gdb_py_events.module); if (PyModule_AddObject (gdb_module, "events", diff --git a/contrib/gdb-7/gdb/python/py-exitedevent.c b/contrib/gdb-7/gdb/python/py-exitedevent.c index 08150e567f..272fd30395 100644 --- a/contrib/gdb-7/gdb/python/py-exitedevent.c +++ b/contrib/gdb-7/gdb/python/py-exitedevent.c @@ -1,6 +1,6 @@ /* Python interface to inferior exit events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -22,9 +22,10 @@ static PyTypeObject exited_event_object_type; static PyObject * -create_exited_event_object (const LONGEST *exit_code) +create_exited_event_object (const LONGEST *exit_code, struct inferior *inf) { PyObject *exited_event; + PyObject *inf_obj; exited_event = create_event_object (&exited_event_object_type); @@ -37,6 +38,12 @@ create_exited_event_object (const LONGEST *exit_code) PyLong_FromLongLong (*exit_code)) < 0) goto fail; + inf_obj = inferior_to_inferior_object (inf); + if (!inf_obj || evpy_add_attribute (exited_event, + "inferior", + inf_obj) < 0) + goto fail; + return exited_event; fail: @@ -48,14 +55,14 @@ create_exited_event_object (const LONGEST *exit_code) will create a new Python exited event object. */ int -emit_exited_event (const LONGEST *exit_code) +emit_exited_event (const LONGEST *exit_code, struct inferior *inf) { PyObject *event; if (evregpy_no_listeners_p (gdb_py_events.exited)) return 0; - event = create_exited_event_object (exit_code); + event = create_exited_event_object (exit_code, inf); if (event) return evpy_emit_event (event, gdb_py_events.exited); diff --git a/contrib/gdb-7/gdb/python/py-finishbreakpoint.c b/contrib/gdb-7/gdb/python/py-finishbreakpoint.c new file mode 100644 index 0000000000..e083576f8e --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-finishbreakpoint.c @@ -0,0 +1,462 @@ +/* Python interface to finish breakpoints + + Copyright (C) 2011-2012 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 . */ + + + +#include "defs.h" +#include "exceptions.h" +#include "python-internal.h" +#include "breakpoint.h" +#include "frame.h" +#include "gdbthread.h" +#include "arch-utils.h" +#include "language.h" +#include "observer.h" +#include "inferior.h" + +static PyTypeObject finish_breakpoint_object_type; + +/* Function that is called when a Python finish bp is found out of scope. */ +static char * const outofscope_func = "out_of_scope"; + +/* struct implementing the gdb.FinishBreakpoint object by extending + the gdb.Breakpoint class. */ +struct finish_breakpoint_object +{ + /* gdb.Breakpoint base class. */ + breakpoint_object py_bp; + /* gdb.Type object of the value return by the breakpointed function. + May be NULL if no debug information was available or return type + was VOID. */ + PyObject *return_type; + /* gdb.Type object of the function finished by this breakpoint. Will be + NULL if return_type is NULL. */ + PyObject *function_type; + /* When stopped at this FinishBreakpoint, gdb.Value object returned by + the function; Py_None if the value is not computable; NULL if GDB is + not stopped at a FinishBreakpoint. */ + PyObject *return_value; +}; + +/* Python function to get the 'return_value' attribute of + FinishBreakpoint. */ + +static PyObject * +bpfinishpy_get_returnvalue (PyObject *self, void *closure) +{ + struct finish_breakpoint_object *self_finishbp = + (struct finish_breakpoint_object *) self; + + if (!self_finishbp->return_value) + Py_RETURN_NONE; + + Py_INCREF (self_finishbp->return_value); + return self_finishbp->return_value; +} + +/* Deallocate FinishBreakpoint object. */ + +static void +bpfinishpy_dealloc (PyObject *self) +{ + struct finish_breakpoint_object *self_bpfinish = + (struct finish_breakpoint_object *) self; + + Py_XDECREF (self_bpfinish->function_type); + Py_XDECREF (self_bpfinish->return_type); + Py_XDECREF (self_bpfinish->return_value); +} + +/* Triggered when gdbpy_should_stop is about to execute the `stop' callback + of the gdb.FinishBreakpoint object BP_OBJ. Will compute and cache the + `return_value', if possible. */ + +void +bpfinishpy_pre_stop_hook (struct breakpoint_object *bp_obj) +{ + struct finish_breakpoint_object *self_finishbp = + (struct finish_breakpoint_object *) bp_obj; + volatile struct gdb_exception except; + + /* Can compute return_value only once. */ + gdb_assert (!self_finishbp->return_value); + + if (!self_finishbp->return_type) + return; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + struct value *ret = + get_return_value (type_object_to_type (self_finishbp->function_type), + type_object_to_type (self_finishbp->return_type)); + + if (ret) + { + self_finishbp->return_value = value_to_value_object (ret); + if (!self_finishbp->return_value) + gdbpy_print_stack (); + } + else + { + Py_INCREF (Py_None); + self_finishbp->return_value = Py_None; + } + } + if (except.reason < 0) + { + gdbpy_convert_exception (except); + gdbpy_print_stack (); + } +} + +/* Triggered when gdbpy_should_stop has triggered the `stop' callback + of the gdb.FinishBreakpoint object BP_OBJ. */ + +void +bpfinishpy_post_stop_hook (struct breakpoint_object *bp_obj) +{ + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + /* Can't delete it here, but it will be removed at the next stop. */ + disable_breakpoint (bp_obj->bp); + gdb_assert (bp_obj->bp->disposition == disp_del); + } + if (except.reason < 0) + { + gdbpy_convert_exception (except); + gdbpy_print_stack (); + } +} + +/* Python function to create a new breakpoint. */ + +static int +bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs) +{ + static char *keywords[] = { "frame", "internal", NULL }; + struct finish_breakpoint_object *self_bpfinish = + (struct finish_breakpoint_object *) self; + int type = bp_breakpoint; + PyObject *frame_obj = NULL; + int thread; + struct frame_info *frame, *prev_frame = NULL; + struct frame_id frame_id; + PyObject *internal = NULL; + int internal_bp = 0; + CORE_ADDR finish_pc, pc; + volatile struct gdb_exception except; + char *addr_str, small_buf[100]; + struct symbol *function; + + if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords, + &frame_obj, &internal)) + return -1; + + /* Default frame to gdb.newest_frame if necessary. */ + if (!frame_obj) + frame_obj = gdbpy_newest_frame (NULL, NULL); + else + Py_INCREF (frame_obj); + + frame = frame_object_to_frame_info (frame_obj); + Py_DECREF (frame_obj); + + if (frame == NULL) + goto invalid_frame; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + prev_frame = get_prev_frame (frame); + if (prev_frame == 0) + { + PyErr_SetString (PyExc_ValueError, _("\"FinishBreakpoint\" not " \ + "meaningful in the outermost "\ + "frame.")); + } + else if (get_frame_type (prev_frame) == DUMMY_FRAME) + { + PyErr_SetString (PyExc_ValueError, _("\"FinishBreakpoint\" cannot "\ + "be set on a dummy frame.")); + } + else + { + frame_id = get_frame_id (prev_frame); + if (frame_id_eq (frame_id, null_frame_id)) + PyErr_SetString (PyExc_ValueError, + _("Invalid ID for the `frame' object.")); + } + } + if (except.reason < 0) + { + gdbpy_convert_exception (except); + return -1; + } + else if (PyErr_Occurred ()) + return -1; + + thread = pid_to_thread_id (inferior_ptid); + if (thread == 0) + { + PyErr_SetString (PyExc_ValueError, + _("No thread currently selected.")); + return -1; + } + + if (internal) + { + internal_bp = PyObject_IsTrue (internal); + if (internal_bp == -1) + { + PyErr_SetString (PyExc_ValueError, + _("The value of `internal' must be a boolean.")); + return -1; + } + } + + /* Find the function we will return from. */ + self_bpfinish->return_type = NULL; + self_bpfinish->function_type = NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (get_frame_pc_if_available (frame, &pc)) + { + function = find_pc_function (pc); + if (function != NULL) + { + struct type *ret_type = + TYPE_TARGET_TYPE (SYMBOL_TYPE (function)); + + /* Remember only non-void return types. */ + if (TYPE_CODE (ret_type) != TYPE_CODE_VOID) + { + /* Ignore Python errors at this stage. */ + self_bpfinish->return_type = type_to_type_object (ret_type); + PyErr_Clear (); + self_bpfinish->function_type = + type_to_type_object (SYMBOL_TYPE (function)); + PyErr_Clear (); + } + } + } + } + if (except.reason < 0 + || !self_bpfinish->return_type || !self_bpfinish->function_type) + { + /* Won't be able to compute return value. */ + Py_XDECREF (self_bpfinish->return_type); + Py_XDECREF (self_bpfinish->function_type); + + self_bpfinish->return_type = NULL; + self_bpfinish->function_type = NULL; + } + + bppy_pending_object = &self_bpfinish->py_bp; + bppy_pending_object->number = -1; + bppy_pending_object->bp = NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + /* Set a breakpoint on the return address. */ + finish_pc = get_frame_pc (prev_frame); + sprintf (small_buf, "*%s", hex_string (finish_pc)); + addr_str = small_buf; + + create_breakpoint (python_gdbarch, + addr_str, NULL, thread, + 0, + 1 /*temp_flag*/, + bp_breakpoint, + 0, + AUTO_BOOLEAN_TRUE, + &bkpt_breakpoint_ops, + 0, 1, internal_bp, 0); + } + GDB_PY_SET_HANDLE_EXCEPTION (except); + + self_bpfinish->py_bp.bp->frame_id = frame_id; + self_bpfinish->py_bp.is_finish_bp = 1; + + /* Bind the breakpoint with the current program space. */ + self_bpfinish->py_bp.bp->pspace = current_program_space; + + return 0; + + invalid_frame: + PyErr_SetString (PyExc_ValueError, + _("Invalid ID for the `frame' object.")); + return -1; +} + +/* Called when GDB notices that the finish breakpoint BP_OBJ is out of + the current callstack. Triggers the method OUT_OF_SCOPE if implemented, + then delete the breakpoint. */ + +static void +bpfinishpy_out_of_scope (struct finish_breakpoint_object *bpfinish_obj) +{ + volatile struct gdb_exception except; + breakpoint_object *bp_obj = (breakpoint_object *) bpfinish_obj; + PyObject *py_obj = (PyObject *) bp_obj; + + if (bpfinish_obj->py_bp.bp->enable_state == bp_enabled + && PyObject_HasAttrString (py_obj, outofscope_func)) + { + if (!PyObject_CallMethod (py_obj, outofscope_func, NULL)) + gdbpy_print_stack (); + } + + delete_breakpoint (bpfinish_obj->py_bp.bp); +} + +/* Callback for `bpfinishpy_detect_out_scope'. Triggers Python's + `B->out_of_scope' function if B is a FinishBreakpoint out of its scope. */ + +static int +bpfinishpy_detect_out_scope_cb (struct breakpoint *b, void *args) +{ + volatile struct gdb_exception except; + struct breakpoint *bp_stopped = (struct breakpoint *) args; + PyObject *py_bp = (PyObject *) b->py_bp_object; + struct gdbarch *garch = b->gdbarch ? b->gdbarch : get_current_arch (); + + /* Trigger out_of_scope if this is a FinishBreakpoint and its frame is + not anymore in the current callstack. */ + if (py_bp != NULL && b->py_bp_object->is_finish_bp) + { + struct finish_breakpoint_object *finish_bp = + (struct finish_breakpoint_object *) py_bp; + + /* Check scope if not currently stopped at the FinishBreakpoint. */ + if (b != bp_stopped) + { + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (b->pspace == current_inferior ()->pspace + && (!target_has_registers + || frame_find_by_id (b->frame_id) == NULL)) + bpfinishpy_out_of_scope (finish_bp); + } + if (except.reason < 0) + { + gdbpy_convert_exception (except); + gdbpy_print_stack (); + } + } + } + + return 0; +} + +/* Attached to `stop' notifications, check if the execution has run + out of the scope of any FinishBreakpoint before it has been hit. */ + +static void +bpfinishpy_handle_stop (struct bpstats *bs, int print_frame) +{ + struct cleanup *cleanup = ensure_python_env (get_current_arch (), + current_language); + + iterate_over_breakpoints (bpfinishpy_detect_out_scope_cb, + bs == NULL ? NULL : bs->breakpoint_at); + + do_cleanups (cleanup); +} + +/* Attached to `exit' notifications, triggers all the necessary out of + scope notifications. */ + +static void +bpfinishpy_handle_exit (struct inferior *inf) +{ + struct cleanup *cleanup = ensure_python_env (target_gdbarch, + current_language); + + iterate_over_breakpoints (bpfinishpy_detect_out_scope_cb, NULL); + + do_cleanups (cleanup); +} + +/* Initialize the Python finish breakpoint code. */ + +void +gdbpy_initialize_finishbreakpoints (void) +{ + if (PyType_Ready (&finish_breakpoint_object_type) < 0) + return; + + Py_INCREF (&finish_breakpoint_object_type); + PyModule_AddObject (gdb_module, "FinishBreakpoint", + (PyObject *) &finish_breakpoint_object_type); + + observer_attach_normal_stop (bpfinishpy_handle_stop); + observer_attach_inferior_exit (bpfinishpy_handle_exit); +} + +static PyGetSetDef finish_breakpoint_object_getset[] = { + { "return_value", bpfinishpy_get_returnvalue, NULL, + "gdb.Value object representing the return value, if any. \ +None otherwise.", NULL }, + { NULL } /* Sentinel. */ +}; + +static PyTypeObject finish_breakpoint_object_type = +{ + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.FinishBreakpoint", /*tp_name*/ + sizeof (struct finish_breakpoint_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + bpfinishpy_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro */ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "GDB finish breakpoint object", /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + finish_breakpoint_object_getset,/* tp_getset */ + &breakpoint_object_type, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + bpfinishpy_init, /* tp_init */ + 0, /* tp_alloc */ + 0 /* tp_new */ +}; diff --git a/contrib/gdb-7/gdb/python/py-frame.c b/contrib/gdb-7/gdb/python/py-frame.c index d7128a9dca..a8ce5980a8 100644 --- a/contrib/gdb-7/gdb/python/py-frame.c +++ b/contrib/gdb-7/gdb/python/py-frame.c @@ -1,6 +1,6 @@ /* Python interface to stack frames - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -60,9 +60,10 @@ static PyTypeObject frame_object_type; object. If the frame doesn't exist anymore (the frame id doesn't correspond to any frame in the inferior), returns NULL. */ -static struct frame_info * -frame_object_to_frame_info (frame_object *frame_obj) +struct frame_info * +frame_object_to_frame_info (PyObject *obj) { + frame_object *frame_obj = (frame_object *) obj; struct frame_info *frame; frame = frame_find_by_id (frame_obj->frame_id); @@ -101,9 +102,15 @@ frapy_str (PyObject *self) static PyObject * frapy_is_valid (PyObject *self, PyObject *args) { - struct frame_info *frame; + struct frame_info *frame = NULL; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + frame = frame_object_to_frame_info (self); + } + GDB_PY_HANDLE_EXCEPTION (except); - frame = frame_object_to_frame_info ((frame_object *) self); if (frame == NULL) Py_RETURN_FALSE; @@ -124,7 +131,7 @@ frapy_name (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); find_frame_funname (frame, &name, &lang, NULL); } @@ -153,7 +160,7 @@ frapy_type (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); type = get_frame_type (frame); } @@ -174,7 +181,7 @@ frapy_unwind_stop_reason (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); } GDB_PY_HANDLE_EXCEPTION (except); @@ -195,7 +202,7 @@ frapy_pc (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); pc = get_frame_pc (frame); } @@ -216,7 +223,7 @@ frapy_block (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); block = get_frame_block (frame, NULL); } GDB_PY_HANDLE_EXCEPTION (except); @@ -257,7 +264,7 @@ frapy_function (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); sym = find_pc_function (get_frame_address_in_block (frame)); } @@ -276,6 +283,7 @@ PyObject * frame_info_to_frame_object (struct frame_info *frame) { frame_object *frame_obj; + volatile struct gdb_exception except; frame_obj = PyObject_New (frame_object, &frame_object_type); if (frame_obj == NULL) @@ -285,23 +293,27 @@ frame_info_to_frame_object (struct frame_info *frame) return NULL; } - /* Try to get the previous frame, to determine if this is the last frame - in a corrupt stack. If so, we need to store the frame_id of the next - frame and not of this one (which is possibly invalid). */ - if (get_prev_frame (frame) == NULL - && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON - && get_next_frame (frame) != NULL) - { - frame_obj->frame_id = get_frame_id (get_next_frame (frame)); - frame_obj->frame_id_is_next = 1; - } - else + TRY_CATCH (except, RETURN_MASK_ALL) { - frame_obj->frame_id = get_frame_id (frame); - frame_obj->frame_id_is_next = 0; - } - frame_obj->gdbarch = get_frame_arch (frame); + /* Try to get the previous frame, to determine if this is the last frame + in a corrupt stack. If so, we need to store the frame_id of the next + frame and not of this one (which is possibly invalid). */ + if (get_prev_frame (frame) == NULL + && get_frame_unwind_stop_reason (frame) != UNWIND_NO_REASON + && get_next_frame (frame) != NULL) + { + frame_obj->frame_id = get_frame_id (get_next_frame (frame)); + frame_obj->frame_id_is_next = 1; + } + else + { + frame_obj->frame_id = get_frame_id (frame); + frame_obj->frame_id_is_next = 0; + } + frame_obj->gdbarch = get_frame_arch (frame); + } + GDB_PY_HANDLE_EXCEPTION (except); return (PyObject *) frame_obj; } @@ -319,7 +331,7 @@ frapy_older (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); prev = get_prev_frame (frame); if (prev) @@ -348,7 +360,7 @@ frapy_newer (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); next = get_next_frame (frame); if (next) @@ -377,7 +389,7 @@ frapy_find_sal (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); find_frame_sal (frame, &sal); sal_obj = symtab_and_line_to_sal_object (sal); @@ -411,7 +423,7 @@ frapy_read_var (PyObject *self, PyObject *args) else if (gdbpy_is_string (sym_obj)) { char *var_name; - struct block *block = NULL; + const struct block *block = NULL; struct cleanup *cleanup; volatile struct gdb_exception except; @@ -433,7 +445,7 @@ frapy_read_var (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); if (!block) block = get_frame_block (frame, NULL); @@ -461,20 +473,12 @@ frapy_read_var (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID ((frame_object *) self, frame); + FRAPY_REQUIRE_VALID (self, frame); val = read_var_value (var, frame); } GDB_PY_HANDLE_EXCEPTION (except); - if (!val) - { - PyErr_Format (PyExc_ValueError, - _("Variable cannot be found for symbol '%s'."), - SYMBOL_NATURAL_NAME (var)); - return NULL; - } - return value_to_value_object (val); } @@ -484,12 +488,11 @@ static PyObject * frapy_select (PyObject *self, PyObject *args) { struct frame_info *fi; - frame_object *frame = (frame_object *) self; volatile struct gdb_exception except; TRY_CATCH (except, RETURN_MASK_ALL) { - FRAPY_REQUIRE_VALID (frame, fi); + FRAPY_REQUIRE_VALID (self, fi); select_frame (fi); } @@ -550,7 +553,7 @@ gdbpy_frame_stop_reason_string (PyObject *self, PyObject *args) if (!PyArg_ParseTuple (args, "i", &reason)) return NULL; - if (reason < 0 || reason > UNWIND_NO_SAVED_PC) + if (reason < UNWIND_FIRST || reason > UNWIND_LAST) { PyErr_SetString (PyExc_ValueError, _("Invalid frame stop reason.")); @@ -593,6 +596,7 @@ frapy_richcompare (PyObject *self, PyObject *other, int op) void gdbpy_initialize_frames (void) { + frame_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&frame_object_type) < 0) return; @@ -602,21 +606,17 @@ gdbpy_initialize_frames (void) PyModule_AddIntConstant (gdb_module, "NORMAL_FRAME", NORMAL_FRAME); PyModule_AddIntConstant (gdb_module, "DUMMY_FRAME", DUMMY_FRAME); PyModule_AddIntConstant (gdb_module, "INLINE_FRAME", INLINE_FRAME); + PyModule_AddIntConstant (gdb_module, "TAILCALL_FRAME", TAILCALL_FRAME); PyModule_AddIntConstant (gdb_module, "SIGTRAMP_FRAME", SIGTRAMP_FRAME); PyModule_AddIntConstant (gdb_module, "ARCH_FRAME", ARCH_FRAME); PyModule_AddIntConstant (gdb_module, "SENTINEL_FRAME", SENTINEL_FRAME); - PyModule_AddIntConstant (gdb_module, - "FRAME_UNWIND_NO_REASON", UNWIND_NO_REASON); - PyModule_AddIntConstant (gdb_module, - "FRAME_UNWIND_NULL_ID", UNWIND_NULL_ID); - PyModule_AddIntConstant (gdb_module, - "FRAME_UNWIND_FIRST_ERROR", UNWIND_FIRST_ERROR); - PyModule_AddIntConstant (gdb_module, - "FRAME_UNWIND_INNER_ID", UNWIND_INNER_ID); - PyModule_AddIntConstant (gdb_module, - "FRAME_UNWIND_SAME_ID", UNWIND_SAME_ID); - PyModule_AddIntConstant (gdb_module, - "FRAME_UNWIND_NO_SAVED_PC", UNWIND_NO_SAVED_PC); + +#define SET(name, description) \ + PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name); +#define FIRST_ERROR(name) \ + PyModule_AddIntConstant (gdb_module, "FRAME_"#name, name); +#include "unwind_stop_reasons.def" +#undef SET Py_INCREF (&frame_object_type); PyModule_AddObject (gdb_module, "Frame", (PyObject *) &frame_object_type); @@ -702,5 +702,4 @@ static PyTypeObject frame_object_type = { 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ }; diff --git a/contrib/gdb-7/gdb/python/py-function.c b/contrib/gdb-7/gdb/python/py-function.c index 0c3e6f2a46..59ff65cd9b 100644 --- a/contrib/gdb-7/gdb/python/py-function.c +++ b/contrib/gdb-7/gdb/python/py-function.c @@ -1,6 +1,6 @@ /* Convenience functions implemented in Python. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -38,6 +38,9 @@ convert_values_to_python (int argc, struct value **argv) { int i; PyObject *result = PyTuple_New (argc); + + if (! result) + return NULL; for (i = 0; i < argc; ++i) { @@ -45,7 +48,7 @@ convert_values_to_python (int argc, struct value **argv) if (! elt) { Py_DECREF (result); - error (_("Could not convert value to Python object.")); + return NULL; } PyTuple_SetItem (result, i, elt); } @@ -59,24 +62,35 @@ fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language, void *cookie, int argc, struct value **argv) { struct value *value = NULL; - PyObject *result, *callable, *args; + /* 'result' must be set to NULL, this initially indicates whether + the function was called, or not. */ + PyObject *result = NULL; + PyObject *callable, *args; struct cleanup *cleanup; cleanup = ensure_python_env (gdbarch, language); args = convert_values_to_python (argc, argv); + /* convert_values_to_python can return NULL on error. If we + encounter this, do not call the function, but allow the Python -> + error code conversion below to deal with the Python exception. + Note, that this is different if the function simply does not + have arguments. */ - callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke"); - if (! callable) + if (args) { + callable = PyObject_GetAttrString ((PyObject *) cookie, "invoke"); + if (! callable) + { + Py_DECREF (args); + error (_("No method named 'invoke' in object.")); + } + + result = PyObject_Call (callable, args, NULL); + Py_DECREF (callable); Py_DECREF (args); - error (_("No method named 'invoke' in object.")); } - result = PyObject_Call (callable, args, NULL); - Py_DECREF (callable); - Py_DECREF (args); - if (!result) { PyObject *ptype, *pvalue, *ptraceback; @@ -150,7 +164,8 @@ fnpy_call (struct gdbarch *gdbarch, const struct language_defn *language, static int fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) { - char *name, *docstring = NULL; + const char *name; + char *docstring = NULL; if (! PyArg_ParseTuple (args, "s", &name)) return -1; @@ -181,6 +196,7 @@ fnpy_init (PyObject *self, PyObject *args, PyObject *kwds) void gdbpy_initialize_functions (void) { + fnpy_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&fnpy_object_type) < 0) return; @@ -230,5 +246,4 @@ static PyTypeObject fnpy_object_type = 0, /* tp_dictoffset */ fnpy_init, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ }; diff --git a/contrib/gdb-7/gdb/python/py-inferior.c b/contrib/gdb-7/gdb/python/py-inferior.c index da0a4b6815..339a221035 100644 --- a/contrib/gdb-7/gdb/python/py-inferior.c +++ b/contrib/gdb-7/gdb/python/py-inferior.c @@ -1,6 +1,6 @@ /* Python interface to inferiors. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,7 @@ #include "gdbcore.h" #include "gdbthread.h" #include "inferior.h" +#include "objfiles.h" #include "observer.h" #include "python-internal.h" #include "arch-utils.h" @@ -119,15 +120,35 @@ python_inferior_exit (struct inferior *inf) if (inf->has_exit_code) exit_code = &inf->exit_code; - if (emit_exited_event (exit_code) < 0) + if (emit_exited_event (exit_code, inf) < 0) gdbpy_print_stack (); do_cleanups (cleanup); } -/* Return a borrowed reference to the Python object of type Inferior +/* Callback used to notify Python listeners about new objfiles loaded in the + inferior. */ + +static void +python_new_objfile (struct objfile *objfile) +{ + struct cleanup *cleanup; + + if (objfile == NULL) + return; + + cleanup = ensure_python_env (get_objfile_arch (objfile), current_language); + + if (emit_new_objfile_event (objfile) < 0) + gdbpy_print_stack (); + + do_cleanups (cleanup); +} + +/* Return a reference to the Python object of type Inferior representing INFERIOR. If the object has already been created, - return it, otherwise, create it. Return NULL on failure. */ + return it and increment the reference count, otherwise, create it. + Return NULL on failure. */ PyObject * inferior_to_inferior_object (struct inferior *inferior) { @@ -136,15 +157,9 @@ inferior_to_inferior_object (struct inferior *inferior) inf_obj = inferior_data (inferior, infpy_inf_data_key); if (!inf_obj) { - struct cleanup *cleanup; - cleanup = ensure_python_env (python_gdbarch, python_language); - inf_obj = PyObject_New (inferior_object, &inferior_object_type); if (!inf_obj) - { - do_cleanups (cleanup); return NULL; - } inf_obj->inferior = inferior; inf_obj->threads = NULL; @@ -152,15 +167,15 @@ inferior_to_inferior_object (struct inferior *inferior) set_inferior_data (inferior, infpy_inf_data_key, inf_obj); - do_cleanups (cleanup); } + else + Py_INCREF ((PyObject *)inf_obj); return (PyObject *) inf_obj; } /* Finds the Python Inferior object for the given PID. Returns a - borrowed reference, or NULL if PID does not match any inferior - object. */ + reference, or NULL if PID does not match any inferior object. */ PyObject * find_inferior_object (int pid) @@ -180,6 +195,7 @@ find_thread_object (ptid_t ptid) int pid; struct threadlist_entry *thread; PyObject *inf_obj; + thread_object *found = NULL; pid = PIDGET (ptid); if (pid == 0) @@ -187,11 +203,21 @@ find_thread_object (ptid_t ptid) inf_obj = find_inferior_object (pid); - if (inf_obj) - for (thread = ((inferior_object *)inf_obj)->threads; thread; - thread = thread->next) - if (ptid_equal (thread->thread_obj->thread->ptid, ptid)) - return thread->thread_obj; + if (! inf_obj) + return NULL; + + for (thread = ((inferior_object *)inf_obj)->threads; thread; + thread = thread->next) + if (ptid_equal (thread->thread_obj->thread->ptid, ptid)) + { + found = thread->thread_obj; + break; + } + + Py_DECREF (inf_obj); + + if (found) + return found; return NULL; } @@ -233,10 +259,15 @@ delete_thread_object (struct thread_info *tp, int ignore) inferior_object *inf_obj; thread_object *thread_obj; struct threadlist_entry **entry, *tmp; + + cleanup = ensure_python_env (python_gdbarch, python_language); inf_obj = (inferior_object *) find_inferior_object (PIDGET(tp->ptid)); if (!inf_obj) - return; + { + do_cleanups (cleanup); + return; + } /* Find thread entry in its inferior's thread_list. */ for (entry = &inf_obj->threads; *entry != NULL; entry = @@ -245,9 +276,11 @@ delete_thread_object (struct thread_info *tp, int ignore) break; if (!*entry) - return; - - cleanup = ensure_python_env (python_gdbarch, python_language); + { + Py_DECREF (inf_obj); + do_cleanups (cleanup); + return; + } tmp = *entry; tmp->thread_obj->thread = NULL; @@ -256,6 +289,7 @@ delete_thread_object (struct thread_info *tp, int ignore) inf_obj->nthreads--; Py_DECREF (tmp->thread_obj); + Py_DECREF (inf_obj); xfree (tmp); do_cleanups (cleanup); @@ -321,8 +355,15 @@ build_inferior_list (struct inferior *inf, void *arg) { PyObject *list = arg; PyObject *inferior = inferior_to_inferior_object (inf); + int success = 0; + + if (! inferior) + return 0; - if (PyList_Append (list, inferior)) + success = PyList_Append (list, inferior); + Py_DECREF (inferior); + + if (success) return 1; return 0; @@ -333,9 +374,7 @@ build_inferior_list (struct inferior *inf, void *arg) PyObject * gdbpy_inferiors (PyObject *unused, PyObject *unused2) { - int i = 0; - PyObject *list, *inferior; - struct inferior *inf; + PyObject *list, *tuple; list = PyList_New (0); if (!list) @@ -347,7 +386,10 @@ gdbpy_inferiors (PyObject *unused, PyObject *unused2) return NULL; } - return PyList_AsTuple (list); + tuple = PyList_AsTuple (list); + Py_DECREF (list); + + return tuple; } /* Membuf and memory manipulation. */ @@ -428,7 +470,8 @@ infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw) static PyObject * infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw) { - int buf_len, error = 0; + Py_ssize_t buf_len; + int error = 0; const char *buffer; CORE_ADDR addr, length; PyObject *addr_obj, *length_obj = NULL; @@ -616,6 +659,17 @@ infpy_is_valid (PyObject *self, PyObject *args) Py_RETURN_TRUE; } +static void +infpy_dealloc (PyObject *obj) +{ + inferior_object *inf_obj = (inferior_object *) obj; + struct inferior *inf = inf_obj->inferior; + + if (! inf) + return; + + set_inferior_data (inf, infpy_inf_data_key, NULL); +} /* Clear the INFERIOR pointer in an Inferior object and clear the thread list. */ @@ -647,6 +701,20 @@ py_free_inferior (struct inferior *inf, void *datum) do_cleanups (cleanup); } +/* Implementation of gdb.selected_inferior() -> gdb.Inferior. + Returns the current inferior object. */ + +PyObject * +gdbpy_selected_inferior (PyObject *self, PyObject *args) +{ + PyObject *inf_obj; + + inf_obj = inferior_to_inferior_object (current_inferior ()); + Py_INCREF (inf_obj); + + return inf_obj; +} + void gdbpy_initialize_inferior (void) { @@ -665,7 +733,9 @@ gdbpy_initialize_inferior (void) observer_attach_normal_stop (python_on_normal_stop); observer_attach_target_resumed (python_on_resume); observer_attach_inferior_exit (python_inferior_exit); + observer_attach_new_objfile (python_new_objfile); + membuf_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&membuf_object_type) < 0) return; @@ -713,7 +783,7 @@ static PyTypeObject inferior_object_type = "gdb.Inferior", /* tp_name */ sizeof (inferior_object), /* tp_basicsize */ 0, /* tp_itemsize */ - 0, /* tp_dealloc */ + infpy_dealloc, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ @@ -803,5 +873,4 @@ static PyTypeObject membuf_object_type = { 0, /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ }; diff --git a/contrib/gdb-7/gdb/python/py-infthread.c b/contrib/gdb-7/gdb/python/py-infthread.c index b37c53ca83..3a37ef787e 100644 --- a/contrib/gdb-7/gdb/python/py-infthread.c +++ b/contrib/gdb-7/gdb/python/py-infthread.c @@ -1,6 +1,6 @@ /* Python interface to inferior threads. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -49,7 +49,6 @@ create_thread_object (struct thread_info *tp) thread_obj->thread = tp; thread_obj->inf_obj = find_inferior_object (PIDGET (tp->ptid)); - Py_INCREF (thread_obj->inf_obj); return thread_obj; } diff --git a/contrib/gdb-7/gdb/python/py-lazy-string.c b/contrib/gdb-7/gdb/python/py-lazy-string.c index 940ce88cf5..11048b3e50 100644 --- a/contrib/gdb-7/gdb/python/py-lazy-string.c +++ b/contrib/gdb-7/gdb/python/py-lazy-string.c @@ -1,6 +1,6 @@ /* Python interface to lazy strings. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -96,7 +96,8 @@ static PyObject * stpy_convert_to_value (PyObject *self, PyObject *args) { lazy_string_object *self_string = (lazy_string_object *) self; - struct value *val; + struct value *val = NULL; + volatile struct gdb_exception except; if (self_string->address == 0) { @@ -105,7 +106,12 @@ stpy_convert_to_value (PyObject *self, PyObject *args) return NULL; } - val = value_at_lazy (self_string->type, self_string->address); + TRY_CATCH (except, RETURN_MASK_ALL) + { + val = value_at_lazy (self_string->type, self_string->address); + } + GDB_PY_HANDLE_EXCEPTION (except); + return value_to_value_object (val); } diff --git a/contrib/gdb-7/gdb/python/py-newobjfileevent.c b/contrib/gdb-7/gdb/python/py-newobjfileevent.c new file mode 100644 index 0000000000..1e26b044b4 --- /dev/null +++ b/contrib/gdb-7/gdb/python/py-newobjfileevent.c @@ -0,0 +1,70 @@ +/* Python interface to new object file loading events. + + Copyright (C) 2011-2012 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 . */ + +#include "py-event.h" + +static PyTypeObject new_objfile_event_object_type; + +PyObject * +create_new_objfile_event_object (struct objfile *objfile) +{ + PyObject *objfile_event; + PyObject *py_objfile; + + objfile_event = create_event_object (&new_objfile_event_object_type); + if (!objfile_event) + goto fail; + + py_objfile = objfile_to_objfile_object (objfile); + if (!py_objfile || evpy_add_attribute (objfile_event, + "new_objfile", + py_objfile) < 0) + goto fail; + + return objfile_event; + + fail: + Py_XDECREF (objfile_event); + return NULL; +} + +/* Callback function which notifies observers when a new objfile event occurs. + This function will create a new Python new_objfile event object. + Return -1 if emit fails. */ + +int +emit_new_objfile_event (struct objfile *objfile) +{ + PyObject *event; + + if (evregpy_no_listeners_p (gdb_py_events.new_objfile)) + return 0; + + event = create_new_objfile_event_object (objfile); + if (event) + return evpy_emit_event (event, gdb_py_events.new_objfile); + return -1; +} + +GDBPY_NEW_EVENT_TYPE (new_objfile, + "gdb.NewObjFileEvent", + "NewObjFileEvent", + "GDB new object file event object", + event_object_type, + static); diff --git a/contrib/gdb-7/gdb/python/py-objfile.c b/contrib/gdb-7/gdb/python/py-objfile.c index f9821f507c..9fa6813f62 100644 --- a/contrib/gdb-7/gdb/python/py-objfile.c +++ b/contrib/gdb-7/gdb/python/py-objfile.c @@ -1,6 +1,6 @@ /* Python interface to objfiles. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-param.c b/contrib/gdb-7/gdb/python/py-param.c index 4d873d88c3..963427e57d 100644 --- a/contrib/gdb-7/gdb/python/py-param.c +++ b/contrib/gdb-7/gdb/python/py-param.c @@ -1,6 +1,6 @@ /* GDB parameters implemented in Python - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -331,6 +331,7 @@ call_doc_function (PyObject *obj, PyObject *method, PyObject *arg) if (gdbpy_is_string (result)) { data = python_string_to_host_string (result); + Py_DECREF (result); if (! data) return NULL; } @@ -338,6 +339,7 @@ call_doc_function (PyObject *obj, PyObject *method, PyObject *arg) { PyErr_SetString (PyExc_RuntimeError, _("Parameter must return a string value.")); + Py_DECREF (result); return NULL; } @@ -645,7 +647,7 @@ static int parmpy_init (PyObject *self, PyObject *args, PyObject *kwds) { parmpy_object *obj = (parmpy_object *) self; - char *name; + const char *name; char *set_doc, *show_doc, *doc; char *cmd_name; int parmclass, cmdtype; @@ -743,6 +745,7 @@ gdbpy_initialize_parameters (void) { int i; + parmpy_object_type.tp_new = PyType_GenericNew; if (PyType_Ready (&parmpy_object_type) < 0) return; @@ -808,5 +811,4 @@ static PyTypeObject parmpy_object_type = 0, /* tp_dictoffset */ parmpy_init, /* tp_init */ 0, /* tp_alloc */ - PyType_GenericNew /* tp_new */ }; diff --git a/contrib/gdb-7/gdb/python/py-prettyprint.c b/contrib/gdb-7/gdb/python/py-prettyprint.c index a657432504..86d4f2ce6e 100644 --- a/contrib/gdb-7/gdb/python/py-prettyprint.c +++ b/contrib/gdb-7/gdb/python/py-prettyprint.c @@ -1,6 +1,6 @@ /* Python pretty-printing - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -526,7 +526,7 @@ print_children (PyObject *printer, const char *hint, for (i = 0; i < options->print_max; ++i) { PyObject *py_v, *item = PyIter_Next (iter); - char *name; + const char *name; struct cleanup *inner_cleanup; if (! item) diff --git a/contrib/gdb-7/gdb/python/py-progspace.c b/contrib/gdb-7/gdb/python/py-progspace.c index c30b37d20f..1cb82408ce 100644 --- a/contrib/gdb-7/gdb/python/py-progspace.c +++ b/contrib/gdb-7/gdb/python/py-progspace.c @@ -1,6 +1,6 @@ /* Python interface to program spaces. - Copyright (C) 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-signalevent.c b/contrib/gdb-7/gdb/python/py-signalevent.c index 3d7ce3229a..323d6f6706 100644 --- a/contrib/gdb-7/gdb/python/py-signalevent.c +++ b/contrib/gdb-7/gdb/python/py-signalevent.c @@ -1,6 +1,6 @@ /* Python interface to inferior signal stop events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-stopevent.c b/contrib/gdb-7/gdb/python/py-stopevent.c index 122fe6bec3..1df4ae9e1d 100644 --- a/contrib/gdb-7/gdb/python/py-stopevent.c +++ b/contrib/gdb-7/gdb/python/py-stopevent.c @@ -1,6 +1,6 @@ /* Python interface to inferior stop events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -45,18 +45,42 @@ int emit_stop_event (struct bpstats *bs, enum target_signal stop_signal) { PyObject *stop_event_obj = NULL; /* Appease GCC warning. */ + PyObject *list = NULL; + PyObject *first_bp = NULL; + struct bpstats *current_bs; if (evregpy_no_listeners_p (gdb_py_events.stop)) return 0; - if (bs && bs->breakpoint_at - && bs->breakpoint_at->py_bp_object) + /* Add any breakpoint set at this location to the list. */ + for (current_bs = bs; current_bs != NULL; current_bs = current_bs->next) { - stop_event_obj = create_breakpoint_event_object ((PyObject *) bs - ->breakpoint_at - ->py_bp_object); + if (current_bs->breakpoint_at + && current_bs->breakpoint_at->py_bp_object) + { + PyObject *current_py_bp = + (PyObject *) current_bs->breakpoint_at->py_bp_object; + + if (list == NULL) + { + list = PyList_New (0); + if (!list) + goto fail; + } + + if (PyList_Append (list, current_py_bp)) + goto fail; + + if (first_bp == NULL) + first_bp = current_py_bp; + } + } + + if (list != NULL) + { + stop_event_obj = create_breakpoint_event_object (list, first_bp); if (!stop_event_obj) - goto fail; + goto fail; } /* Check if the signal is "Signal 0" or "Trace/breakpoint trap". */ @@ -75,13 +99,14 @@ emit_stop_event (struct bpstats *bs, enum target_signal stop_signal) { stop_event_obj = create_stop_event_object (&stop_event_object_type); if (!stop_event_obj) - goto fail; + goto fail; } return evpy_emit_event (stop_event_obj, gdb_py_events.stop); - fail: - return -1; + fail: + Py_XDECREF (list); + return -1; } GDBPY_NEW_EVENT_TYPE (stop, diff --git a/contrib/gdb-7/gdb/python/py-stopevent.h b/contrib/gdb-7/gdb/python/py-stopevent.h index 52f3511df3..df642860c7 100644 --- a/contrib/gdb-7/gdb/python/py-stopevent.h +++ b/contrib/gdb-7/gdb/python/py-stopevent.h @@ -1,6 +1,6 @@ /* Python interface to inferior events. - Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -28,7 +28,8 @@ extern void stop_evpy_dealloc (PyObject *self); extern int emit_stop_event (struct bpstats *bs, enum target_signal stop_signal); -extern PyObject *create_breakpoint_event_object (PyObject *breakpoint); +extern PyObject *create_breakpoint_event_object (PyObject *breakpoint_list, + PyObject *first_bp); extern PyObject *create_signal_event_object (enum target_signal stop_signal); diff --git a/contrib/gdb-7/gdb/python/py-symbol.c b/contrib/gdb-7/gdb/python/py-symbol.c index 046d78c76a..9d32a71773 100644 --- a/contrib/gdb-7/gdb/python/py-symbol.c +++ b/contrib/gdb-7/gdb/python/py-symbol.c @@ -1,6 +1,6 @@ /* Python interface to symbols. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -65,6 +65,22 @@ sympy_str (PyObject *self) return result; } +static PyObject * +sympy_get_type (PyObject *self, void *closure) +{ + struct symbol *symbol = NULL; + + SYMPY_REQUIRE_VALID (self, symbol); + + if (SYMBOL_TYPE (symbol) == NULL) + { + Py_INCREF (Py_None); + return Py_None; + } + + return type_to_type_object (SYMBOL_TYPE (symbol)); +} + static PyObject * sympy_get_symtab (PyObject *self, void *closure) { @@ -258,9 +274,10 @@ gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw) int domain = VAR_DOMAIN, is_a_field_of_this = 0; const char *name; static char *keywords[] = { "name", "block", "domain", NULL }; - struct symbol *symbol; + struct symbol *symbol = NULL; PyObject *block_obj = NULL, *ret_tuple, *sym_obj, *bool_obj; - struct block *block = NULL; + const struct block *block = NULL; + volatile struct gdb_exception except; if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!i", keywords, &name, &block_object_type, &block_obj, &domain)) @@ -281,7 +298,11 @@ gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw) GDB_PY_HANDLE_EXCEPTION (except); } - symbol = lookup_symbol (name, block, domain, &is_a_field_of_this); + TRY_CATCH (except, RETURN_MASK_ALL) + { + symbol = lookup_symbol (name, block, domain, &is_a_field_of_this); + } + GDB_PY_HANDLE_EXCEPTION (except); ret_tuple = PyTuple_New (2); if (!ret_tuple) @@ -319,14 +340,19 @@ gdbpy_lookup_global_symbol (PyObject *self, PyObject *args, PyObject *kw) int domain = VAR_DOMAIN; const char *name; static char *keywords[] = { "name", "domain", NULL }; - struct symbol *symbol; + struct symbol *symbol = NULL; PyObject *sym_obj; + volatile struct gdb_exception except; if (! PyArg_ParseTupleAndKeywords (args, kw, "s|i", keywords, &name, &domain)) return NULL; - symbol = lookup_symbol_global (name, NULL, domain); + TRY_CATCH (except, RETURN_MASK_ALL) + { + symbol = lookup_symbol_global (name, NULL, domain); + } + GDB_PY_HANDLE_EXCEPTION (except); if (symbol) { @@ -412,6 +438,8 @@ gdbpy_initialize_symbols (void) static PyGetSetDef symbol_object_getset[] = { + { "type", sympy_get_type, NULL, + "Type of the symbol.", NULL }, { "symtab", sympy_get_symtab, NULL, "Symbol table in which the symbol appears.", NULL }, { "name", sympy_get_name, NULL, diff --git a/contrib/gdb-7/gdb/python/py-symtab.c b/contrib/gdb-7/gdb/python/py-symtab.c index 107cdec6e0..09b760fc4d 100644 --- a/contrib/gdb-7/gdb/python/py-symtab.c +++ b/contrib/gdb-7/gdb/python/py-symtab.c @@ -1,6 +1,6 @@ /* Python interface to symbol tables. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-threadevent.c b/contrib/gdb-7/gdb/python/py-threadevent.c index 7963412e08..67f9e2006a 100644 --- a/contrib/gdb-7/gdb/python/py-threadevent.c +++ b/contrib/gdb-7/gdb/python/py-threadevent.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. +/* Copyright (C) 2009-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-type.c b/contrib/gdb-7/gdb/python/py-type.c index c010420ee3..dadb0375a9 100644 --- a/contrib/gdb-7/gdb/python/py-type.c +++ b/contrib/gdb-7/gdb/python/py-type.c @@ -1,6 +1,6 @@ /* Python interface to types. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -29,6 +29,7 @@ #include "language.h" #include "vec.h" #include "bcache.h" +#include "dwarf2loc.h" typedef struct pyty_type_object { @@ -55,6 +56,19 @@ typedef struct pyty_field_object static PyTypeObject field_object_type; +/* A type iterator object. */ +typedef struct { + PyObject_HEAD + /* The current field index. */ + int field; + /* What to return. */ + enum gdbpy_iter_kind kind; + /* Pointer back to the original source type object. */ + struct pyty_type_object *source; +} typy_iterator_object; + +static PyTypeObject type_iterator_object_type; + /* This is used to initialize various gdb.TYPE_ constants. */ struct pyty_code { @@ -64,6 +78,9 @@ struct pyty_code const char *name; }; +/* Forward declarations. */ +static PyObject *typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind); + #define ENTRY(X) { X, #X } static struct pyty_code pyty_codes[] = @@ -137,7 +154,8 @@ typy_get_code (PyObject *self, void *closure) } /* Helper function for typy_fields which converts a single field to a - dictionary. Returns NULL on error. */ + gdb.Field object. Returns NULL on error. */ + static PyObject * convert_field (struct type *type, int field) { @@ -210,47 +228,157 @@ convert_field (struct type *type, int field) return NULL; } -/* Return a sequence of all fields. Each field is a dictionary with - some pre-defined keys. */ +/* Helper function to return the name of a field, as a gdb.Field object. + If the field doesn't have a name, None is returned. */ + static PyObject * -typy_fields (PyObject *self, PyObject *args) +field_name (struct type *type, int field) { PyObject *result; - int i; - struct type *type = ((type_object *) self)->type; + + if (TYPE_FIELD_NAME (type, field)) + result = PyString_FromString (TYPE_FIELD_NAME (type, field)); + else + { + result = Py_None; + Py_INCREF (result); + } + return result; +} + +/* Helper function for Type standard mapping methods. Returns a + Python object for field i of the type. "kind" specifies what to + return: the name of the field, a gdb.Field object corresponding to + the field, or a tuple consisting of field name and gdb.Field + object. */ + +static PyObject * +make_fielditem (struct type *type, int i, enum gdbpy_iter_kind kind) +{ + PyObject *item = NULL, *key = NULL, *value = NULL; + + switch (kind) + { + case iter_items: + key = field_name (type, i); + if (key == NULL) + goto fail; + value = convert_field (type, i); + if (value == NULL) + goto fail; + item = PyTuple_New (2); + if (item == NULL) + goto fail; + PyTuple_SET_ITEM (item, 0, key); + PyTuple_SET_ITEM (item, 1, value); + break; + case iter_keys: + item = field_name (type, i); + break; + case iter_values: + item = convert_field (type, i); + break; + } + return item; + + fail: + Py_XDECREF (key); + Py_XDECREF (value); + Py_XDECREF (item); + return NULL; +} + +/* Return a sequence of all field names, fields, or (name, field) pairs. + Each field is a gdb.Field object. */ + +static PyObject * +typy_fields_items (PyObject *self, enum gdbpy_iter_kind kind) +{ + PyObject *py_type = self; + PyObject *result = NULL, *iter = NULL; volatile struct gdb_exception except; + struct type *type = ((type_object *) py_type)->type; + struct type *checked_type = type; TRY_CATCH (except, RETURN_MASK_ALL) { - CHECK_TYPEDEF (type); + CHECK_TYPEDEF (checked_type); } GDB_PY_HANDLE_EXCEPTION (except); - /* We would like to make a tuple here, make fields immutable, and - then memoize the result (and perhaps make Field.type() lazy). - However, that can lead to cycles. */ - result = PyList_New (0); - - for (i = 0; i < TYPE_NFIELDS (type); ++i) + if (checked_type != type) + py_type = type_to_type_object (checked_type); + iter = typy_make_iter (py_type, kind); + if (checked_type != type) { - PyObject *dict = convert_field (type, i); - - if (!dict) - { - Py_DECREF (result); - return NULL; - } - if (PyList_Append (result, dict)) - { - Py_DECREF (dict); - Py_DECREF (result); - return NULL; - } + /* Need to wrap this in braces because Py_DECREF isn't wrapped + in a do{}while(0). */ + Py_DECREF (py_type); + } + if (iter != NULL) + { + result = PySequence_List (iter); + Py_DECREF (iter); } return result; } +/* Return a sequence of all fields. Each field is a gdb.Field object. */ + +static PyObject * +typy_values (PyObject *self, PyObject *args) +{ + return typy_fields_items (self, iter_values); +} + +/* Return a sequence of all fields. Each field is a gdb.Field object. + This method is similar to typy_values, except where the supplied + gdb.Type is an array, in which case it returns a list of one entry + which is a gdb.Field object for a range (the array bounds). */ + +static PyObject * +typy_fields (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + PyObject *r, *rl; + + if (TYPE_CODE (type) != TYPE_CODE_ARRAY) + return typy_fields_items (self, iter_values); + + /* Array type. Handle this as a special case because the common + machinery wants struct or union or enum types. Build a list of + one entry which is the range for the array. */ + r = convert_field (type, 0); + if (r == NULL) + return NULL; + + rl = Py_BuildValue ("[O]", r); + if (rl == NULL) + { + Py_DECREF (r); + } + + return rl; +} + +/* Return a sequence of all field names. Each field is a gdb.Field object. */ + +static PyObject * +typy_field_names (PyObject *self, PyObject *args) +{ + return typy_fields_items (self, iter_keys); +} + +/* Return a sequence of all (name, fields) pairs. Each field is a + gdb.Field object. */ + +static PyObject * +typy_items (PyObject *self, PyObject *args) +{ + return typy_fields_items (self, iter_items); +} + /* Return the type's tag, or None. */ static PyObject * typy_get_tag (PyObject *self, void *closure) @@ -267,10 +395,59 @@ static PyObject * typy_strip_typedefs (PyObject *self, PyObject *args) { struct type *type = ((type_object *) self)->type; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = check_typedef (type); + } + GDB_PY_HANDLE_EXCEPTION (except); return type_to_type_object (check_typedef (type)); } +/* Strip typedefs and pointers/reference from a type. Then check that + it is a struct, union, or enum type. If not, raise TypeError. */ + +static struct type * +typy_get_composite (struct type *type) +{ + volatile struct gdb_exception except; + + for (;;) + { + TRY_CATCH (except, RETURN_MASK_ALL) + { + CHECK_TYPEDEF (type); + } + /* Don't use GDB_PY_HANDLE_EXCEPTION here because that returns + a (NULL) pointer of the wrong type. */ + if (except.reason < 0) + { + gdbpy_convert_exception (except); + return NULL; + } + + if (TYPE_CODE (type) != TYPE_CODE_PTR + && TYPE_CODE (type) != TYPE_CODE_REF) + break; + type = TYPE_TARGET_TYPE (type); + } + + /* If this is not a struct, union, or enum type, raise TypeError + exception. */ + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION + && TYPE_CODE (type) != TYPE_CODE_ENUM) + { + PyErr_SetString (PyExc_TypeError, + "Type is not a structure, union, or enum type."); + return NULL; + } + + return type; +} + /* Return an array type. */ static PyObject * @@ -497,7 +674,7 @@ typy_get_sizeof (PyObject *self, void *closure) } static struct type * -typy_lookup_typename (char *type_name, struct block *block) +typy_lookup_typename (const char *type_name, const struct block *block) { struct type *type = NULL; volatile struct gdb_exception except; @@ -516,9 +693,7 @@ typy_lookup_typename (char *type_name, struct block *block) } if (except.reason < 0) { - PyErr_Format (except.reason == RETURN_QUIT - ? PyExc_KeyboardInterrupt : PyExc_RuntimeError, - "%s", except.message); + gdbpy_convert_exception (except); return NULL; } @@ -527,11 +702,12 @@ typy_lookup_typename (char *type_name, struct block *block) static struct type * typy_lookup_type (struct demangle_component *demangled, - struct block *block) + const struct block *block) { - struct type *type; - char *type_name; + struct type *type, *rtype = NULL; + char *type_name = NULL; enum demangle_component_type demangled_type; + volatile struct gdb_exception except; /* Save the type: typy_lookup_type() may (indirectly) overwrite memory pointed by demangled. */ @@ -546,19 +722,41 @@ typy_lookup_type (struct demangle_component *demangled, if (! type) return NULL; - switch (demangled_type) + TRY_CATCH (except, RETURN_MASK_ALL) + { + /* If the demangled_type matches with one of the types + below, run the corresponding function and save the type + to return later. We cannot just return here as we are in + an exception handler. */ + switch (demangled_type) + { + case DEMANGLE_COMPONENT_REFERENCE: + rtype = lookup_reference_type (type); + break; + case DEMANGLE_COMPONENT_POINTER: + rtype = lookup_pointer_type (type); + break; + case DEMANGLE_COMPONENT_CONST: + rtype = make_cv_type (1, 0, type, NULL); + break; + case DEMANGLE_COMPONENT_VOLATILE: + rtype = make_cv_type (0, 1, type, NULL); + break; + } + } + if (except.reason < 0) { - case DEMANGLE_COMPONENT_REFERENCE: - return lookup_reference_type (type); - case DEMANGLE_COMPONENT_POINTER: - return lookup_pointer_type (type); - case DEMANGLE_COMPONENT_CONST: - return make_cv_type (1, 0, type, NULL); - case DEMANGLE_COMPONENT_VOLATILE: - return make_cv_type (0, 1, type, NULL); + gdbpy_convert_exception (except); + return NULL; } } - + + /* If we have a type from the switch statement above, just return + that. */ + if (rtype) + return rtype; + + /* We don't have a type, so lookup the type. */ type_name = cp_comp_to_string (demangled, 10); type = typy_lookup_typename (type_name, block); xfree (type_name); @@ -572,13 +770,16 @@ typy_lookup_type (struct demangle_component *demangled, versions of GCC, that do not emit DW_TAG_template_*. */ static PyObject * -typy_legacy_template_argument (struct type *type, struct block *block, +typy_legacy_template_argument (struct type *type, const struct block *block, int argno) { int i; struct demangle_component *demangled; + struct demangle_parse_info *info = NULL; const char *err; struct type *argtype; + struct cleanup *cleanup; + volatile struct gdb_exception except; if (TYPE_NAME (type) == NULL) { @@ -586,13 +787,20 @@ typy_legacy_template_argument (struct type *type, struct block *block, return NULL; } - /* Note -- this is not thread-safe. */ - demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err); - if (! demangled) + TRY_CATCH (except, RETURN_MASK_ALL) + { + /* Note -- this is not thread-safe. */ + info = cp_demangled_name_to_comp (TYPE_NAME (type), &err); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (! info) { PyErr_SetString (PyExc_RuntimeError, err); return NULL; } + demangled = info->tree; + cleanup = make_cleanup_cp_demangled_name_parse_free (info); /* Strip off component names. */ while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME @@ -601,6 +809,7 @@ typy_legacy_template_argument (struct type *type, struct block *block, if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE) { + do_cleanups (cleanup); PyErr_SetString (PyExc_RuntimeError, _("Type is not a template.")); return NULL; } @@ -613,12 +822,14 @@ typy_legacy_template_argument (struct type *type, struct block *block, if (! demangled) { + do_cleanups (cleanup); PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."), argno); return NULL; } argtype = typy_lookup_type (demangled->u.s_binary.left, block); + do_cleanups (cleanup); if (! argtype) return NULL; @@ -630,7 +841,7 @@ typy_template_argument (PyObject *self, PyObject *args) { int argno; struct type *type = ((type_object *) self)->type; - struct block *block = NULL; + const struct block *block = NULL; PyObject *block_obj = NULL; struct symbol *sym; struct value *val = NULL; @@ -736,7 +947,7 @@ DEF_VEC_O (type_equality_entry_d); the same, 0 otherwise. Handles NULLs properly. */ static int -compare_strings (const char *s, const char *t) +compare_maybe_null_strings (const char *s, const char *t) { if (s == NULL && t != NULL) return 0; @@ -772,9 +983,10 @@ check_types_equal (struct type *type1, struct type *type2, || TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2)) return Py_NE; - if (!compare_strings (TYPE_TAG_NAME (type1), TYPE_TAG_NAME (type2))) + if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1), + TYPE_TAG_NAME (type2))) return Py_NE; - if (!compare_strings (TYPE_NAME (type1), TYPE_NAME (type2))) + if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2))) return Py_NE; if (TYPE_CODE (type1) == TYPE_CODE_RANGE) @@ -797,7 +1009,8 @@ check_types_equal (struct type *type1, struct type *type2, || FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2) || FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2)) return Py_NE; - if (!compare_strings (FIELD_NAME (*field1), FIELD_NAME (*field2))) + if (!compare_maybe_null_strings (FIELD_NAME (*field1), + FIELD_NAME (*field2))) return Py_NE; switch (FIELD_LOC_KIND (*field1)) { @@ -811,10 +1024,26 @@ check_types_equal (struct type *type1, struct type *type2, return Py_NE; break; case FIELD_LOC_KIND_PHYSNAME: - if (!compare_strings (FIELD_STATIC_PHYSNAME (*field1), - FIELD_STATIC_PHYSNAME (*field2))) + if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1), + FIELD_STATIC_PHYSNAME (*field2))) return Py_NE; break; + case FIELD_LOC_KIND_DWARF_BLOCK: + { + struct dwarf2_locexpr_baton *block1, *block2; + + block1 = FIELD_DWARF_BLOCK (*field1); + block2 = FIELD_DWARF_BLOCK (*field2); + if (block1->per_cu != block2->per_cu + || block1->size != block2->size + || memcmp (block1->data, block2->data, block1->size) != 0) + return Py_NE; + } + break; + default: + internal_error (__FILE__, __LINE__, _("Unsupported field kind " + "%d by check_types_equal"), + FIELD_LOC_KIND (*field1)); } entry.type1 = FIELD_TYPE (*field1); @@ -905,11 +1134,13 @@ typy_richcompare (PyObject *self, PyObject *other, int op) { result = check_types_worklist (&worklist, cache); } - if (except.reason < 0) - result = Py_NE; - + /* check_types_worklist calls several nested Python helper + functions, some of which can raise a GDB Exception, so we + just check and convert here. If there is a GDB exception, a + comparison is not capable (or trusted), so exit. */ bcache_xfree (cache); VEC_free (type_equality_entry_d, worklist); + GDB_PY_HANDLE_EXCEPTION (except); } if (op == result) @@ -992,6 +1223,219 @@ typy_dealloc (PyObject *obj) type->ob_type->tp_free (type); } +/* Return number of fields ("length" of the field dictionary). */ + +static Py_ssize_t +typy_length (PyObject *self) +{ + struct type *type = ((type_object *) self)->type; + + type = typy_get_composite (type); + if (type == NULL) + return -1; + + return TYPE_NFIELDS (type); +} + +/* Implements boolean evaluation of gdb.Type. Handle this like other + Python objects that don't have a meaningful truth value -- all + values are true. */ + +static int +typy_nonzero (PyObject *self) +{ + return 1; +} + +/* Return a gdb.Field object for the field named by the argument. */ + +static PyObject * +typy_getitem (PyObject *self, PyObject *key) +{ + struct type *type = ((type_object *) self)->type; + char *field; + int i; + volatile struct gdb_exception except; + + field = python_string_to_host_string (key); + if (field == NULL) + return NULL; + + /* We want just fields of this type, not of base types, so instead of + using lookup_struct_elt_type, portions of that function are + copied here. */ + + type = typy_get_composite (type); + if (type == NULL) + return NULL; + + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + char *t_field_name = TYPE_FIELD_NAME (type, i); + + if (t_field_name && (strcmp_iw (t_field_name, field) == 0)) + { + return convert_field (type, i); + } + } + PyErr_SetObject (PyExc_KeyError, key); + return NULL; +} + +/* Implement the "get" method on the type object. This is the + same as getitem if the key is present, but returns the supplied + default value or None if the key is not found. */ + +static PyObject * +typy_get (PyObject *self, PyObject *args) +{ + PyObject *key, *defval = Py_None, *result; + + if (!PyArg_UnpackTuple (args, "get", 1, 2, &key, &defval)) + return NULL; + + result = typy_getitem (self, key); + if (result != NULL) + return result; + + /* typy_getitem returned error status. If the exception is + KeyError, clear the exception status and return the defval + instead. Otherwise return the exception unchanged. */ + if (!PyErr_ExceptionMatches (PyExc_KeyError)) + return NULL; + + PyErr_Clear (); + Py_INCREF (defval); + return defval; +} + +/* Implement the "has_key" method on the type object. */ + +static PyObject * +typy_has_key (PyObject *self, PyObject *args) +{ + struct type *type = ((type_object *) self)->type; + const char *field; + int i; + volatile struct gdb_exception except; + + if (!PyArg_ParseTuple (args, "s", &field)) + return NULL; + + /* We want just fields of this type, not of base types, so instead of + using lookup_struct_elt_type, portions of that function are + copied here. */ + + type = typy_get_composite (type); + if (type == NULL) + return NULL; + + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + char *t_field_name = TYPE_FIELD_NAME (type, i); + + if (t_field_name && (strcmp_iw (t_field_name, field) == 0)) + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; +} + +/* Make an iterator object to iterate over keys, values, or items. */ + +static PyObject * +typy_make_iter (PyObject *self, enum gdbpy_iter_kind kind) +{ + typy_iterator_object *typy_iter_obj; + + /* Check that "self" is a structure or union type. */ + if (typy_get_composite (((type_object *) self)->type) == NULL) + return NULL; + + typy_iter_obj = PyObject_New (typy_iterator_object, + &type_iterator_object_type); + if (typy_iter_obj == NULL) + return NULL; + + typy_iter_obj->field = 0; + typy_iter_obj->kind = kind; + Py_INCREF (self); + typy_iter_obj->source = (type_object *) self; + + return (PyObject *) typy_iter_obj; +} + +/* iteritems() method. */ + +static PyObject * +typy_iteritems (PyObject *self, PyObject *args) +{ + return typy_make_iter (self, iter_items); +} + +/* iterkeys() method. */ + +static PyObject * +typy_iterkeys (PyObject *self, PyObject *args) +{ + return typy_make_iter (self, iter_keys); +} + +/* Iterating over the class, same as iterkeys except for the function + signature. */ + +static PyObject * +typy_iter (PyObject *self) +{ + return typy_make_iter (self, iter_keys); +} + +/* itervalues() method. */ + +static PyObject * +typy_itervalues (PyObject *self, PyObject *args) +{ + return typy_make_iter (self, iter_values); +} + +/* Return a reference to the type iterator. */ + +static PyObject * +typy_iterator_iter (PyObject *self) +{ + Py_INCREF (self); + return self; +} + +/* Return the next field in the iteration through the list of fields + of the type. */ + +static PyObject * +typy_iterator_iternext (PyObject *self) +{ + typy_iterator_object *iter_obj = (typy_iterator_object *) self; + struct type *type = iter_obj->source->type; + int i; + PyObject *result; + + if (iter_obj->field < TYPE_NFIELDS (type)) + { + result = make_fielditem (type, iter_obj->field, iter_obj->kind); + if (result != NULL) + iter_obj->field++; + return result; + } + + return NULL; +} + +static void +typy_iterator_dealloc (PyObject *obj) +{ + typy_iterator_object *iter_obj = (typy_iterator_object *) obj; + + Py_DECREF (iter_obj->source); +} + /* Create a new Type referring to TYPE. */ PyObject * type_to_type_object (struct type *type) @@ -1020,10 +1464,10 @@ PyObject * gdbpy_lookup_type (PyObject *self, PyObject *args, PyObject *kw) { static char *keywords[] = { "name", "block", NULL }; - char *type_name = NULL; + const char *type_name = NULL; struct type *type = NULL; PyObject *block_obj = NULL; - struct block *block = NULL; + const struct block *block = NULL; if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O", keywords, &type_name, &block_obj)) @@ -1059,6 +1503,8 @@ gdbpy_initialize_types (void) return; if (PyType_Ready (&field_object_type) < 0) return; + if (PyType_Ready (&type_iterator_object_type) < 0) + return; for (i = 0; pyty_codes[i].name; ++i) { @@ -1072,6 +1518,10 @@ gdbpy_initialize_types (void) Py_INCREF (&type_object_type); PyModule_AddObject (gdb_module, "Type", (PyObject *) &type_object_type); + Py_INCREF (&type_iterator_object_type); + PyModule_AddObject (gdb_module, "TypeIterator", + (PyObject *) &type_iterator_object_type); + Py_INCREF (&field_object_type); PyModule_AddObject (gdb_module, "Field", (PyObject *) &field_object_type); } @@ -1092,15 +1542,39 @@ static PyGetSetDef type_object_getset[] = static PyMethodDef type_object_methods[] = { { "array", typy_array, METH_VARARGS, - "array (N) -> Type\n\ -Return a type which represents an array of N objects of this type." }, + "array ([LOW_BOUND,] HIGH_BOUND) -> Type\n\ +Return a type which represents an array of objects of this type.\n\ +The bounds of the array are [LOW_BOUND, HIGH_BOUND] inclusive.\n\ +If LOW_BOUND is omitted, a value of zero is used." }, + { "__contains__", typy_has_key, METH_VARARGS, + "T.__contains__(k) -> True if T has a field named k, else False" }, { "const", typy_const, METH_NOARGS, "const () -> Type\n\ Return a const variant of this type." }, { "fields", typy_fields, METH_NOARGS, - "field () -> list\n\ -Return a sequence holding all the fields of this type.\n\ -Each field is a dictionary." }, + "fields () -> list\n\ +Return a list holding all the fields of this type.\n\ +Each field is a gdb.Field object." }, + { "get", typy_get, METH_VARARGS, + "T.get(k[,default]) -> returns field named k in T, if it exists;\n\ +otherwise returns default, if supplied, or None if not." }, + { "has_key", typy_has_key, METH_VARARGS, + "T.has_key(k) -> True if T has a field named k, else False" }, + { "items", typy_items, METH_NOARGS, + "items () -> list\n\ +Return a list of (name, field) pairs of this type.\n\ +Each field is a gdb.Field object." }, + { "iteritems", typy_iteritems, METH_NOARGS, + "iteritems () -> an iterator over the (name, field)\n\ +pairs of this type. Each field is a gdb.Field object." }, + { "iterkeys", typy_iterkeys, METH_NOARGS, + "iterkeys () -> an iterator over the field names of this type." }, + { "itervalues", typy_itervalues, METH_NOARGS, + "itervalues () -> an iterator over the fields of this type.\n\ +Each field is a gdb.Field object." }, + { "keys", typy_field_names, METH_NOARGS, + "keys () -> list\n\ +Return a list holding all the fields names of this type." }, { "pointer", typy_pointer, METH_NOARGS, "pointer () -> Type\n\ Return a type of pointer to this type." }, @@ -1122,12 +1596,48 @@ Return the type of a template argument." }, { "unqualified", typy_unqualified, METH_NOARGS, "unqualified () -> Type\n\ Return a variant of this type without const or volatile attributes." }, + { "values", typy_values, METH_NOARGS, + "values () -> list\n\ +Return a list holding all the fields of this type.\n\ +Each field is a gdb.Field object." }, { "volatile", typy_volatile, METH_NOARGS, "volatile () -> Type\n\ Return a volatile variant of this type" }, { NULL } }; +static PyNumberMethods type_object_as_number = { + NULL, /* nb_add */ + NULL, /* nb_subtract */ + NULL, /* nb_multiply */ + NULL, /* nb_divide */ + NULL, /* nb_remainder */ + NULL, /* nb_divmod */ + NULL, /* nb_power */ + NULL, /* nb_negative */ + NULL, /* nb_positive */ + NULL, /* nb_absolute */ + typy_nonzero, /* nb_nonzero */ + NULL, /* nb_invert */ + NULL, /* nb_lshift */ + NULL, /* nb_rshift */ + NULL, /* nb_and */ + NULL, /* nb_xor */ + NULL, /* nb_or */ + NULL, /* nb_coerce */ + NULL, /* nb_int */ + NULL, /* nb_long */ + NULL, /* nb_float */ + NULL, /* nb_oct */ + NULL /* nb_hex */ +}; + +static PyMappingMethods typy_mapping = { + typy_length, + typy_getitem, + NULL /* no "set" method */ +}; + static PyTypeObject type_object_type = { PyObject_HEAD_INIT (NULL) @@ -1141,9 +1651,9 @@ static PyTypeObject type_object_type = 0, /*tp_setattr*/ 0, /*tp_compare*/ 0, /*tp_repr*/ - 0, /*tp_as_number*/ + &type_object_as_number, /*tp_as_number*/ 0, /*tp_as_sequence*/ - 0, /*tp_as_mapping*/ + &typy_mapping, /*tp_as_mapping*/ 0, /*tp_hash */ 0, /*tp_call*/ typy_str, /*tp_str*/ @@ -1156,7 +1666,7 @@ static PyTypeObject type_object_type = 0, /* tp_clear */ typy_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ + typy_iter, /* tp_iter */ 0, /* tp_iternext */ type_object_methods, /* tp_methods */ 0, /* tp_members */ @@ -1213,3 +1723,35 @@ static PyTypeObject field_object_type = 0, /* tp_alloc */ 0, /* tp_new */ }; + +static PyTypeObject type_iterator_object_type = { + PyObject_HEAD_INIT (NULL) + 0, /*ob_size*/ + "gdb.TypeIterator", /*tp_name*/ + sizeof (typy_iterator_object), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + typy_iterator_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + "GDB type iterator object", /*tp_doc */ + 0, /*tp_traverse */ + 0, /*tp_clear */ + 0, /*tp_richcompare */ + 0, /*tp_weaklistoffset */ + typy_iterator_iter, /*tp_iter */ + typy_iterator_iternext, /*tp_iternext */ + 0 /*tp_methods */ +}; diff --git a/contrib/gdb-7/gdb/python/py-utils.c b/contrib/gdb-7/gdb/python/py-utils.c index 601bcb05ea..3579720674 100644 --- a/contrib/gdb-7/gdb/python/py-utils.c +++ b/contrib/gdb-7/gdb/python/py-utils.c @@ -1,6 +1,6 @@ /* General utility routines for GDB/Python. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/python/py-value.c b/contrib/gdb-7/gdb/python/py-value.c index 4381d52039..19423eaf53 100644 --- a/contrib/gdb-7/gdb/python/py-value.c +++ b/contrib/gdb-7/gdb/python/py-value.c @@ -1,6 +1,6 @@ /* Python interface to values. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -209,7 +209,7 @@ valpy_get_address (PyObject *self, void *closure) val_obj->address = value_to_value_object (res_val); } - Py_INCREF (val_obj->address); + Py_XINCREF (val_obj->address); return val_obj->address; } @@ -312,13 +312,18 @@ valpy_lazy_string (PyObject *self, PyObject *args, PyObject *kw) const char *user_encoding = NULL; static char *keywords[] = { "encoding", "length", NULL }; PyObject *str_obj; + volatile struct gdb_exception except; if (!PyArg_ParseTupleAndKeywords (args, kw, "|s" GDB_PY_LL_ARG, keywords, &user_encoding, &length)) return NULL; - if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR) - value = value_ind (value); + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR) + value = value_ind (value); + } + GDB_PY_HANDLE_EXCEPTION (except); str_obj = gdbpy_create_lazy_string_object (value_address (value), length, user_encoding, @@ -510,7 +515,13 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords) volatile struct gdb_exception except; struct value *function = ((value_object *) self)->value; struct value **vargs = NULL; - struct type *ftype = check_typedef (value_type (function)); + struct type *ftype = NULL; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + ftype = check_typedef (value_type (function)); + } + GDB_PY_HANDLE_EXCEPTION (except); if (TYPE_CODE (ftype) != TYPE_CODE_FUNC) { @@ -519,6 +530,13 @@ valpy_call (PyObject *self, PyObject *args, PyObject *keywords) return NULL; } + if (! PyTuple_Check (args)) + { + PyErr_SetString (PyExc_TypeError, + _("Inferior arguments must be provided in a tuple.")); + return NULL; + } + args_count = PyTuple_Size (args); if (args_count > 0) { @@ -553,8 +571,6 @@ static PyObject * valpy_str (PyObject *self) { char *s = NULL; - struct ui_file *stb; - struct cleanup *old_chain; PyObject *result; struct value_print_options opts; volatile struct gdb_exception except; @@ -562,19 +578,19 @@ valpy_str (PyObject *self) get_user_print_options (&opts); opts.deref_ref = 0; - stb = mem_fileopen (); - old_chain = make_cleanup_ui_file_delete (stb); - TRY_CATCH (except, RETURN_MASK_ALL) { + struct ui_file *stb = mem_fileopen (); + struct cleanup *old_chain = make_cleanup_ui_file_delete (stb); + common_val_print (((value_object *) self)->value, stb, 0, &opts, python_language); s = ui_file_xstrdup (stb, NULL); + + do_cleanups (old_chain); } GDB_PY_HANDLE_EXCEPTION (except); - do_cleanups (old_chain); - result = PyUnicode_Decode (s, strlen (s), host_charset (), NULL); xfree (s); @@ -586,13 +602,58 @@ static PyObject * valpy_get_is_optimized_out (PyObject *self, void *closure) { struct value *value = ((value_object *) self)->value; + int opt = 0; + volatile struct gdb_exception except; - if (value_optimized_out (value)) + TRY_CATCH (except, RETURN_MASK_ALL) + { + opt = value_optimized_out (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (opt) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} + +/* Implements gdb.Value.is_lazy. */ +static PyObject * +valpy_get_is_lazy (PyObject *self, void *closure) +{ + struct value *value = ((value_object *) self)->value; + int opt = 0; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + opt = value_lazy (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (opt) Py_RETURN_TRUE; Py_RETURN_FALSE; } +/* Implements gdb.Value.fetch_lazy (). */ +static PyObject * +valpy_fetch_lazy (PyObject *self, PyObject *args) +{ + struct value *value = ((value_object *) self)->value; + volatile struct gdb_exception except; + + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (value_lazy (value)) + value_fetch_lazy (value); + } + GDB_PY_HANDLE_EXCEPTION (except); + + Py_RETURN_NONE; +} + /* Calculate and return the address of the PyObject as the value of the builtin __hash__ call. */ static long @@ -794,33 +855,53 @@ static PyObject * valpy_absolute (PyObject *self) { struct value *value = ((value_object *) self)->value; + volatile struct gdb_exception except; + int isabs = 1; - if (value_less (value, value_zero (value_type (value), not_lval))) - return valpy_negative (self); - else + TRY_CATCH (except, RETURN_MASK_ALL) + { + if (value_less (value, value_zero (value_type (value), not_lval))) + isabs = 0; + } + GDB_PY_HANDLE_EXCEPTION (except); + + if (isabs) return valpy_positive (self); + else + return valpy_negative (self); } /* Implements boolean evaluation of gdb.Value. */ static int valpy_nonzero (PyObject *self) { + volatile struct gdb_exception except; value_object *self_value = (value_object *) self; struct type *type; + int nonzero = 0; /* Appease GCC warning. */ - type = check_typedef (value_type (self_value->value)); + TRY_CATCH (except, RETURN_MASK_ALL) + { + type = check_typedef (value_type (self_value->value)); + + if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR) + nonzero = !!value_as_long (self_value->value); + else if (TYPE_CODE (type) == TYPE_CODE_FLT) + nonzero = value_as_double (self_value->value) != 0; + else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + nonzero = !decimal_is_zero (value_contents (self_value->value), + TYPE_LENGTH (type), + gdbarch_byte_order (get_type_arch (type))); + else + /* All other values are True. */ + nonzero = 1; + } + /* 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 (except); - if (is_integral_type (type) || TYPE_CODE (type) == TYPE_CODE_PTR) - return !!value_as_long (self_value->value); - else if (TYPE_CODE (type) == TYPE_CODE_FLT) - return value_as_double (self_value->value) != 0; - else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT) - return !decimal_is_zero (value_contents (self_value->value), - TYPE_LENGTH (type), - gdbarch_byte_order (get_type_arch (type))); - else - /* All other values are True. */ - return 1; + return nonzero; } /* Implements ~ for value objects. */ @@ -956,7 +1037,6 @@ valpy_richcompare (PyObject *self, PyObject *other, int op) static int is_intlike (struct type *type, int ptr_ok) { - CHECK_TYPEDEF (type); return (TYPE_CODE (type) == TYPE_CODE_INT || TYPE_CODE (type) == TYPE_CODE_ENUM || TYPE_CODE (type) == TYPE_CODE_BOOL @@ -973,16 +1053,12 @@ valpy_int (PyObject *self) LONGEST l = 0; volatile struct gdb_exception except; - CHECK_TYPEDEF (type); - if (!is_intlike (type, 0)) - { - PyErr_SetString (PyExc_RuntimeError, - _("Cannot convert value to int.")); - return NULL; - } - TRY_CATCH (except, RETURN_MASK_ALL) { + CHECK_TYPEDEF (type); + if (!is_intlike (type, 0)) + error (_("Cannot convert value to int.")); + l = value_as_long (value); } GDB_PY_HANDLE_EXCEPTION (except); @@ -999,15 +1075,13 @@ valpy_long (PyObject *self) LONGEST l = 0; volatile struct gdb_exception except; - if (!is_intlike (type, 1)) - { - PyErr_SetString (PyExc_RuntimeError, - _("Cannot convert value to long.")); - return NULL; - } - TRY_CATCH (except, RETURN_MASK_ALL) { + CHECK_TYPEDEF (type); + + if (!is_intlike (type, 1)) + error (_("Cannot convert value to long.")); + l = value_as_long (value); } GDB_PY_HANDLE_EXCEPTION (except); @@ -1024,16 +1098,13 @@ valpy_float (PyObject *self) double d = 0; volatile struct gdb_exception except; - CHECK_TYPEDEF (type); - if (TYPE_CODE (type) != TYPE_CODE_FLT) - { - PyErr_SetString (PyExc_RuntimeError, - _("Cannot convert value to float.")); - return NULL; - } - TRY_CATCH (except, RETURN_MASK_ALL) { + CHECK_TYPEDEF (type); + + if (TYPE_CODE (type) != TYPE_CODE_FLT) + error (_("Cannot convert value to float.")); + d = value_as_double (value); } GDB_PY_HANDLE_EXCEPTION (except); @@ -1234,6 +1305,10 @@ static PyGetSetDef value_object_getset[] = { { "type", valpy_get_type, NULL, "Type of the value.", NULL }, { "dynamic_type", valpy_get_dynamic_type, NULL, "Dynamic type of the value.", NULL }, + { "is_lazy", valpy_get_is_lazy, NULL, + "Boolean telling whether the value is lazy (not fetched yet\n\ +from the inferior). A lazy value is fetched when needed, or when\n\ +the \"fetch_lazy()\" method is called.", NULL }, {NULL} /* Sentinel */ }; @@ -1256,6 +1331,8 @@ Return a lazy string representation of the value." }, { "string", (PyCFunction) valpy_string, METH_VARARGS | METH_KEYWORDS, "string ([encoding] [, errors] [, length]) -> string\n\ Return Unicode string representation of the value." }, + { "fetch_lazy", valpy_fetch_lazy, METH_NOARGS, + "Fetches the value from the inferior, if it was lazy." }, {NULL} /* Sentinel */ }; diff --git a/contrib/gdb-7/gdb/python/python-internal.h b/contrib/gdb-7/gdb/python/python-internal.h index d3cb78854a..328e5d8787 100644 --- a/contrib/gdb-7/gdb/python/python-internal.h +++ b/contrib/gdb-7/gdb/python/python-internal.h @@ -1,6 +1,6 @@ /* Gdb/Python header for private use by Python module. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -41,6 +41,9 @@ around technique as above. */ #undef _FILE_OFFSET_BITS +/* Request clean size types from Python. */ +#define PY_SSIZE_T_CLEAN + /* Include the Python header files using angle brackets rather than double quotes. On case-insensitive filesystems, this prevents us from including our python/python.h header file. */ @@ -101,11 +104,14 @@ typedef unsigned long gdb_py_ulongest; #include "exceptions.h" +enum gdbpy_iter_kind { iter_keys, iter_values, iter_items }; + struct block; struct value; struct language_defn; struct program_space; struct bpstats; +struct inferior; extern PyObject *gdb_module; extern PyTypeObject value_object_type; @@ -114,9 +120,50 @@ extern PyTypeObject symbol_object_type; extern PyTypeObject event_object_type; extern PyTypeObject events_object_type; extern PyTypeObject stop_event_object_type; +extern PyTypeObject breakpoint_object_type; + +typedef struct breakpoint_object +{ + PyObject_HEAD + + /* The breakpoint number according to gdb. */ + int number; + + /* The gdb breakpoint object, or NULL if the breakpoint has been + deleted. */ + struct breakpoint *bp; + + /* 1 is this is a FinishBreakpoint object, 0 otherwise. */ + int is_finish_bp; +} breakpoint_object; + +/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python + exception if it is invalid. */ +#define BPPY_REQUIRE_VALID(Breakpoint) \ + do { \ + if ((Breakpoint)->bp == NULL) \ + return PyErr_Format (PyExc_RuntimeError, \ + _("Breakpoint %d is invalid."), \ + (Breakpoint)->number); \ + } while (0) + +/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python + exception if it is invalid. This macro is for use in setter functions. */ +#define BPPY_SET_REQUIRE_VALID(Breakpoint) \ + do { \ + if ((Breakpoint)->bp == NULL) \ + { \ + PyErr_Format (PyExc_RuntimeError, _("Breakpoint %d is invalid."), \ + (Breakpoint)->number); \ + return -1; \ + } \ + } while (0) + + +/* Variables used to pass information between the Breakpoint + constructor and the breakpoint-created hook function. */ +extern breakpoint_object *bppy_pending_object; -/* Defined in py-breakpoint.c */ -typedef struct breakpoint_object breakpoint_object; typedef struct { @@ -147,17 +194,19 @@ PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length, struct type *type); PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2); PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args); +PyObject *gdbpy_selected_inferior (PyObject *self, PyObject *args); PyObject *gdbpy_string_to_argv (PyObject *self, PyObject *args); PyObject *gdbpy_parameter (PyObject *self, PyObject *args); PyObject *gdbpy_parameter_value (enum var_types type, void *var); -char *gdbpy_parse_command_name (char *text, +char *gdbpy_parse_command_name (const char *name, struct cmd_list_element ***base_list, struct cmd_list_element **start_list); PyObject *symtab_and_line_to_sal_object (struct symtab_and_line sal); PyObject *symtab_to_symtab_object (struct symtab *symtab); PyObject *symbol_to_symbol_object (struct symbol *sym); -PyObject *block_to_block_object (struct block *block, struct objfile *objfile); +PyObject *block_to_block_object (const struct block *block, + struct objfile *objfile); PyObject *value_to_value_object (struct value *v); PyObject *type_to_type_object (struct type *); PyObject *frame_info_to_frame_object (struct frame_info *frame); @@ -173,13 +222,14 @@ thread_object *find_thread_object (ptid_t ptid); PyObject *find_inferior_object (int pid); PyObject *inferior_to_inferior_object (struct inferior *inferior); -struct block *block_object_to_block (PyObject *obj); +const struct block *block_object_to_block (PyObject *obj); struct symbol *symbol_object_to_symbol (PyObject *obj); struct value *value_object_to_value (PyObject *self); struct value *convert_value_from_python (PyObject *obj); struct type *type_object_to_type (PyObject *obj); struct symtab *symtab_object_to_symtab (PyObject *obj); struct symtab_and_line *sal_object_to_symtab_and_line (PyObject *obj); +struct frame_info *frame_object_to_frame_info (PyObject *frame_obj); void gdbpy_initialize_auto_load (void); void gdbpy_initialize_values (void); @@ -194,6 +244,7 @@ void gdbpy_initialize_functions (void); void gdbpy_initialize_pspace (void); void gdbpy_initialize_objfile (void); void gdbpy_initialize_breakpoints (void); +void gdbpy_initialize_finishbreakpoints (void); void gdbpy_initialize_lazy_string (void); void gdbpy_initialize_parameters (void); void gdbpy_initialize_thread (void); @@ -207,6 +258,7 @@ void gdbpy_initialize_breakpoint_event (void); void gdbpy_initialize_continue_event (void); void gdbpy_initialize_exited_event (void); void gdbpy_initialize_thread_event (void); +void gdbpy_initialize_new_objfile_event (void); struct cleanup *make_cleanup_py_decref (PyObject *py); @@ -238,7 +290,7 @@ extern const struct language_defn *python_language; void gdbpy_print_stack (void); void source_python_script_for_objfile (struct objfile *objfile, - FILE *stream, const char *file); + const char *file); PyObject *python_string_to_unicode (PyObject *obj); char *unicode_to_target_string (PyObject *unicode_str); @@ -266,6 +318,9 @@ PyObject *gdbpy_get_varobj_pretty_printer (struct value *value); char *gdbpy_get_display_hint (PyObject *printer); PyObject *gdbpy_default_visualizer (PyObject *self, PyObject *args); +void bpfinishpy_pre_stop_hook (struct breakpoint_object *bp_obj); +void bpfinishpy_post_stop_hook (struct breakpoint_object *bp_obj); + extern PyObject *gdbpy_doc_cst; extern PyObject *gdbpy_children_cst; extern PyObject *gdbpy_to_string_cst; diff --git a/contrib/gdb-7/gdb/python/python.c b/contrib/gdb-7/gdb/python/python.c index 8a7bc66b36..6611c82c85 100644 --- a/contrib/gdb-7/gdb/python/python.c +++ b/contrib/gdb-7/gdb/python/python.c @@ -1,6 +1,6 @@ /* General python/gdb code - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -30,13 +30,30 @@ #include "exceptions.h" #include "event-loop.h" #include "serial.h" +#include "readline/tilde.h" #include "python.h" #include -/* True if we should print the stack when catching a Python error, - false otherwise. */ -static int gdbpy_should_print_stack = 1; +/* Declared constants and enum for python stack printing. */ +static const char python_excp_none[] = "none"; +static const char python_excp_full[] = "full"; +static const char python_excp_message[] = "message"; + +/* "set python print-stack" choices. */ +static const char *python_excp_enums[] = + { + python_excp_none, + python_excp_full, + python_excp_message, + NULL + }; + +/* The exception printing variable. 'full' if we want to print the + error message and stack, 'none' if we want to print nothing, and + 'message' if we only want to print the error message. 'message' is + the default. */ +static const char *gdbpy_should_print_stack = python_excp_message; #ifdef HAVE_PYTHON @@ -51,6 +68,8 @@ static int gdbpy_should_print_stack = 1; #include "version.h" #include "target.h" #include "gdbthread.h" +#include "observer.h" +#include "interps.h" static PyMethodDef GdbMethods[]; @@ -132,6 +151,54 @@ ensure_python_env (struct gdbarch *gdbarch, return make_cleanup (restore_python_env, env); } +/* A wrapper around PyRun_SimpleFile. FILENAME is the name of + the Python script to run. + + One of the parameters of PyRun_SimpleFile is a FILE *. + The problem is that type FILE is extremely system and compiler + dependent. So, unless the Python library has been compiled using + the same build environment as GDB, we run the risk of getting + a crash due to inconsistencies between the definition used by GDB, + and the definition used by Python. A mismatch can very likely + lead to a crash. + + There is also the situation where the Python library and GDB + are using two different versions of the C runtime library. + This is particularly visible on Windows, where few users would + build Python themselves (this is no trivial task on this platform), + and thus use binaries built by someone else instead. Python, + being built with VC, would use one version of the msvcr DLL + (Eg. msvcr100.dll), while MinGW uses msvcrt.dll. A FILE * + from one runtime does not necessarily operate correctly in + the other runtime. + + To work around this potential issue, we create the FILE object + using Python routines, thus making sure that it is compatible + with the Python library. */ + +static void +python_run_simple_file (const char *filename) +{ + char *full_path; + PyObject *python_file; + struct cleanup *cleanup; + + /* Because we have a string for a filename, and are using Python to + open the file, we need to expand any tilde in the path first. */ + full_path = tilde_expand (filename); + cleanup = make_cleanup (xfree, full_path); + python_file = PyFile_FromString (full_path, "r"); + if (! python_file) + { + do_cleanups (cleanup); + gdbpy_print_stack (); + error (_("Error while opening file: %s"), full_path); + } + + make_cleanup_py_decref (python_file); + PyRun_SimpleFile (PyFile_AsFile (python_file), filename); + do_cleanups (cleanup); +} /* Given a command_line, return a command string suitable for passing to Python. Lines in the string are separated by newlines. The @@ -182,10 +249,7 @@ eval_python_from_control_command (struct command_line *cmd) ret = PyRun_SimpleString (script); xfree (script); if (ret) - { - gdbpy_print_stack (); - error (_("Error while executing Python code.")); - } + error (_("Error while executing Python code.")); do_cleanups (cleanup); } @@ -198,15 +262,16 @@ python_command (char *arg, int from_tty) struct cleanup *cleanup; cleanup = ensure_python_env (get_current_arch (), current_language); + + make_cleanup_restore_integer (&interpreter_async); + interpreter_async = 0; + while (arg && *arg && isspace (*arg)) ++arg; if (arg && *arg) { if (PyRun_SimpleString (arg)) - { - gdbpy_print_stack (); - error (_("Error while executing Python code.")); - } + error (_("Error while executing Python code.")); } else { @@ -290,7 +355,8 @@ PyObject * gdbpy_parameter (PyObject *self, PyObject *args) { struct cmd_list_element *alias, *prefix, *cmd; - char *arg, *newarg; + const char *arg; + char *newarg; int found = -1; volatile struct gdb_exception except; @@ -340,7 +406,7 @@ gdbpy_target_wide_charset (PyObject *self, PyObject *args) static PyObject * execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) { - char *arg; + const char *arg; PyObject *from_tty_obj = NULL, *to_string_obj = NULL; int from_tty, to_string; volatile struct gdb_exception except; @@ -376,6 +442,9 @@ execute_gdb_command (PyObject *self, PyObject *args, PyObject *kw) char *copy = xstrdup (arg); struct cleanup *cleanup = make_cleanup (xfree, copy); + make_cleanup_restore_integer (&interpreter_async); + interpreter_async = 0; + prevent_dont_repeat (); if (to_string) result = execute_command_to_string (copy, from_tty); @@ -434,7 +503,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args) struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to appease gcc. */ struct symtab_and_line sal; - char *arg = NULL; + const char *arg = NULL; char *copy = NULL; struct cleanup *cleanups; PyObject *result = NULL; @@ -445,16 +514,15 @@ gdbpy_decode_line (PyObject *self, PyObject *args) if (! PyArg_ParseTuple (args, "|s", &arg)) return NULL; - cleanups = ensure_python_env (get_current_arch (), current_language); + cleanups = make_cleanup (null_cleanup, NULL); TRY_CATCH (except, RETURN_MASK_ALL) { if (arg) { - arg = xstrdup (arg); - make_cleanup (xfree, arg); - copy = arg; - sals = decode_line_1 (©, 0, 0, 0, 0); + copy = xstrdup (arg); + make_cleanup (xfree, copy); + sals = decode_line_1 (©, 0, 0, 0); make_cleanup (xfree, sals.sals); } else @@ -531,7 +599,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args) static PyObject * gdbpy_parse_and_eval (PyObject *self, PyObject *args) { - char *expr_str; + const char *expr_str; struct value *result = NULL; volatile struct gdb_exception except; @@ -540,28 +608,29 @@ gdbpy_parse_and_eval (PyObject *self, PyObject *args) TRY_CATCH (except, RETURN_MASK_ALL) { - result = parse_and_eval (expr_str); + char *copy = xstrdup (expr_str); + struct cleanup *cleanup = make_cleanup (xfree, copy); + + result = parse_and_eval (copy); + do_cleanups (cleanup); } GDB_PY_HANDLE_EXCEPTION (except); return value_to_value_object (result); } -/* Read a file as Python code. STREAM is the input file; FILE is the - name of the file. - STREAM is not closed, that is the caller's responsibility. */ +/* Read a file as Python code. + FILE is the name of the file. + This does not throw any errors. If an exception occurs python will print + the traceback and clear the error indicator. */ void -source_python_script (FILE *stream, const char *file) +source_python_script (const char *file) { struct cleanup *cleanup; cleanup = ensure_python_env (get_current_arch (), current_language); - - /* Note: If an exception occurs python will print the traceback and - clear the error indicator. */ - PyRun_SimpleFile (stream, file); - + python_run_simple_file (file); do_cleanups (cleanup); } @@ -678,6 +747,81 @@ gdbpy_initialize_events (void) } } + + +static void +before_prompt_hook (const char *current_gdb_prompt) +{ + struct cleanup *cleanup; + char *prompt = NULL; + + cleanup = ensure_python_env (get_current_arch (), current_language); + + if (PyObject_HasAttrString (gdb_module, "prompt_hook")) + { + PyObject *hook; + + hook = PyObject_GetAttrString (gdb_module, "prompt_hook"); + if (hook == NULL) + goto fail; + + if (PyCallable_Check (hook)) + { + PyObject *result; + PyObject *current_prompt; + + current_prompt = PyString_FromString (current_gdb_prompt); + if (current_prompt == NULL) + goto fail; + + result = PyObject_CallFunctionObjArgs (hook, current_prompt, NULL); + + Py_DECREF (current_prompt); + + if (result == NULL) + goto fail; + + make_cleanup_py_decref (result); + + /* Return type should be None, or a String. If it is None, + fall through, we will not set a prompt. If it is a + string, set PROMPT. Anything else, set an exception. */ + if (result != Py_None && ! PyString_Check (result)) + { + PyErr_Format (PyExc_RuntimeError, + _("Return from prompt_hook must " \ + "be either a Python string, or None")); + goto fail; + } + + if (result != Py_None) + { + prompt = python_string_to_host_string (result); + + if (prompt == NULL) + goto fail; + else + make_cleanup (xfree, prompt); + } + } + } + + /* If a prompt has been set, PROMPT will not be NULL. If it is + NULL, do not set the prompt. */ + if (prompt != NULL) + set_prompt (prompt); + + do_cleanups (cleanup); + return; + + fail: + gdbpy_print_stack (); + do_cleanups (cleanup); + return; +} + + + /* Printing. */ /* A python function to write a single string using gdb's filtered @@ -687,7 +831,7 @@ gdbpy_initialize_events (void) static PyObject * gdbpy_write (PyObject *self, PyObject *args, PyObject *kw) { - char *arg; + const char *arg; static char *keywords[] = {"text", "stream", NULL }; int stream_type = 0; @@ -747,13 +891,20 @@ gdbpy_flush (PyObject *self, PyObject *args, PyObject *kw) Py_RETURN_NONE; } -/* Print a python exception trace, or print nothing and clear the - python exception, depending on gdbpy_should_print_stack. Only call - this if a python exception is set. */ +/* Print a python exception trace, print just a message, or print + nothing and clear the python exception, depending on + gdbpy_should_print_stack. Only call this if a python exception is + set. */ void gdbpy_print_stack (void) { - if (gdbpy_should_print_stack) + /* Print "none", just clear exception. */ + if (gdbpy_should_print_stack == python_excp_none) + { + PyErr_Clear (); + } + /* Print "full" message and backtrace. */ + else if (gdbpy_should_print_stack == python_excp_full) { PyErr_Print (); /* PyErr_Print doesn't necessarily end output with a newline. @@ -761,8 +912,34 @@ gdbpy_print_stack (void) printf_filtered. */ begin_line (); } + /* Print "message", just error print message. */ else - PyErr_Clear (); + { + PyObject *ptype, *pvalue, *ptraceback; + char *msg = NULL, *type = NULL; + + PyErr_Fetch (&ptype, &pvalue, &ptraceback); + + /* Fetch the error message contained within ptype, pvalue. */ + msg = gdbpy_exception_to_string (ptype, pvalue); + type = gdbpy_obj_to_string (ptype); + if (msg == NULL) + { + /* An error occurred computing the string representation of the + error message. */ + fprintf_filtered (gdb_stderr, + _("Error occurred computing Python error" \ + "message.\n")); + } + else + fprintf_filtered (gdb_stderr, "Python Exception %s %s: \n", + type, msg); + + Py_XDECREF (ptype); + Py_XDECREF (pvalue); + Py_XDECREF (ptraceback); + xfree (msg); + } } @@ -814,21 +991,19 @@ gdbpy_progspaces (PyObject *unused1, PyObject *unused2) source_python_script_for_objfile; it is NULL at other times. */ static struct objfile *gdbpy_current_objfile; -/* Set the current objfile to OBJFILE and then read STREAM,FILE as - Python code. */ +/* Set the current objfile to OBJFILE and then read FILE as Python code. + This does not throw any errors. If an exception occurs python will print + the traceback and clear the error indicator. */ void -source_python_script_for_objfile (struct objfile *objfile, - FILE *stream, const char *file) +source_python_script_for_objfile (struct objfile *objfile, const char *file) { struct cleanup *cleanups; cleanups = ensure_python_env (get_objfile_arch (objfile), current_language); gdbpy_current_objfile = objfile; - /* Note: If an exception occurs python will print the traceback and - clear the error indicator. */ - PyRun_SimpleFile (stream, file); + python_run_simple_file (file); do_cleanups (cleanups); gdbpy_current_objfile = NULL; @@ -904,7 +1079,7 @@ eval_python_from_control_command (struct command_line *cmd) } void -source_python_script (FILE *stream, const char *file) +source_python_script (const char *file) { throw_error (UNSUPPORTED_ERROR, _("Python scripting is not supported in this copy of GDB.")); @@ -929,26 +1104,79 @@ gdbpy_breakpoint_has_py_cond (struct breakpoint_object *bp_obj) #endif /* HAVE_PYTHON */ +/* Support for "mt set python print-stack on|off" is present in gdb 7.4 + to not break Eclipse. + ref: https://bugs.eclipse.org/bugs/show_bug.cgi?id=367788. */ /* Lists for 'maint set python' commands. */ -struct cmd_list_element *set_python_list; -struct cmd_list_element *show_python_list; +static struct cmd_list_element *maint_set_python_list; +static struct cmd_list_element *maint_show_python_list; /* Function for use by 'maint set python' prefix command. */ static void -set_python (char *args, int from_tty) +maint_set_python (char *args, int from_tty) { - help_list (set_python_list, "maintenance set python ", -1, gdb_stdout); + help_list (maint_set_python_list, "maintenance set python ", + class_deprecated, gdb_stdout); } /* Function for use by 'maint show python' prefix command. */ static void -show_python (char *args, int from_tty) +maint_show_python (char *args, int from_tty) +{ + cmd_show_list (maint_show_python_list, from_tty, ""); +} + +/* True if we should print the stack when catching a Python error, + false otherwise. */ +static int gdbpy_should_print_stack_deprecated = 0; + +static void +set_maint_python_print_stack (char *args, int from_tty, + struct cmd_list_element *e) { - cmd_show_list (show_python_list, from_tty, ""); + if (gdbpy_should_print_stack_deprecated) + gdbpy_should_print_stack = python_excp_full; + else + gdbpy_should_print_stack = python_excp_none; +} + +static void +show_maint_python_print_stack (struct ui_file *file, int from_tty, + struct cmd_list_element *c, const char *value) +{ + fprintf_filtered (file, + _("The mode of Python stack printing on error is" + " \"%s\".\n"), + gdbpy_should_print_stack == python_excp_full + ? "on" : "off"); +} + + + +/* Lists for 'set python' commands. */ + +static struct cmd_list_element *user_set_python_list; +static struct cmd_list_element *user_show_python_list; + +/* Function for use by 'set python' prefix command. */ + +static void +user_set_python (char *args, int from_tty) +{ + help_list (user_set_python_list, "set python ", all_commands, + gdb_stdout); +} + +/* Function for use by 'show python' prefix command. */ + +static void +user_show_python (char *args, int from_tty) +{ + cmd_show_list (user_show_python_list, from_tty, ""); } /* Initialize the Python code. */ @@ -959,6 +1187,9 @@ extern initialize_file_ftype _initialize_python; void _initialize_python (void) { + char *cmd_name; + struct cmd_list_element *cmd; + add_com ("python", class_obscure, python_command, #ifdef HAVE_PYTHON _("\ @@ -980,23 +1211,55 @@ This command is only a placeholder.") #endif /* HAVE_PYTHON */ ); - add_prefix_cmd ("python", no_class, show_python, + add_prefix_cmd ("python", no_class, maint_show_python, _("Prefix command for python maintenance settings."), - &show_python_list, "maintenance show python ", 0, + &maint_show_python_list, "maintenance show python ", 0, &maintenance_show_cmdlist); - add_prefix_cmd ("python", no_class, set_python, + add_prefix_cmd ("python", no_class, maint_set_python, _("Prefix command for python maintenance settings."), - &set_python_list, "maintenance set python ", 0, + &maint_set_python_list, "maintenance set python ", 0, &maintenance_set_cmdlist); add_setshow_boolean_cmd ("print-stack", class_maintenance, - &gdbpy_should_print_stack, _("\ + &gdbpy_should_print_stack_deprecated, _("\ Enable or disable printing of Python stack dump on error."), _("\ Show whether Python stack will be printed on error."), _("\ Enables or disables printing of Python stack traces."), - NULL, NULL, - &set_python_list, - &show_python_list); + set_maint_python_print_stack, + show_maint_python_print_stack, + &maint_set_python_list, + &maint_show_python_list); + + /* Deprecate maint set/show python print-stack in favour of + non-maintenance alternatives. */ + cmd_name = "print-stack"; + cmd = lookup_cmd (&cmd_name, maint_set_python_list, "", -1, 0); + deprecate_cmd (cmd, "set python print-stack"); + cmd_name = "print-stack"; /* Reset name. */ + cmd = lookup_cmd (&cmd_name, maint_show_python_list, "", -1, 0); + deprecate_cmd (cmd, "show python print-stack"); + + /* Add set/show python print-stack. */ + add_prefix_cmd ("python", no_class, user_show_python, + _("Prefix command for python preference settings."), + &user_show_python_list, "show python ", 0, + &showlist); + + add_prefix_cmd ("python", no_class, user_set_python, + _("Prefix command for python preference settings."), + &user_set_python_list, "set python ", 0, + &setlist); + + add_setshow_enum_cmd ("print-stack", no_class, python_excp_enums, + &gdbpy_should_print_stack, _("\ +Set mode for Python stack dump on error."), _("\ +Show the mode of Python stack printing on error."), _("\ +none == no stack or message will be printed.\n\ +full == a message and a stack will be printed.\n\ +message == an error message without a stack will be printed."), + NULL, NULL, + &user_set_python_list, + &user_show_python_list); #ifdef HAVE_PYTHON #ifdef WITH_PYTHON_PATH @@ -1060,6 +1323,7 @@ Enables or disables printing of Python stack traces."), gdbpy_initialize_pspace (); gdbpy_initialize_objfile (); gdbpy_initialize_breakpoints (); + gdbpy_initialize_finishbreakpoints (); gdbpy_initialize_lazy_string (); gdbpy_initialize_thread (); gdbpy_initialize_inferior (); @@ -1074,6 +1338,9 @@ Enables or disables printing of Python stack traces."), gdbpy_initialize_continue_event (); gdbpy_initialize_exited_event (); gdbpy_initialize_thread_event (); + gdbpy_initialize_new_objfile_event () ; + + observer_attach_before_prompt (before_prompt_hook); PyRun_SimpleString ("import gdb"); PyRun_SimpleString ("gdb.pretty_printers = []"); @@ -1165,18 +1432,20 @@ def GdbSetPythonDirectory (dir):\n\ sys.path.insert (0, gdb.PYTHONDIR)\n\ \n\ # Tell python where to find submodules of gdb.\n\ - gdb.__path__ = [gdb.PYTHONDIR + '/gdb']\n\ + gdb.__path__ = [os.path.join (gdb.PYTHONDIR, 'gdb')]\n\ \n\ # The gdb module is implemented in C rather than in Python. As a result,\n\ # the associated __init.py__ script is not not executed by default when\n\ # the gdb module gets imported. Execute that script manually if it\n\ # exists.\n\ - ipy = gdb.PYTHONDIR + '/gdb/__init__.py'\n\ + ipy = os.path.join (gdb.PYTHONDIR, 'gdb', '__init__.py')\n\ if os.path.exists (ipy):\n\ execfile (ipy)\n\ \n\ # Install the default gdb.PYTHONDIR.\n\ GdbSetPythonDirectory (gdb.PYTHONDIR)\n\ +# Default prompt hook does nothing.\n\ +prompt_hook = None\n\ "); do_cleanups (cleanup); @@ -1276,6 +1545,9 @@ Arguments are separate by spaces and may be quoted." { "selected_thread", gdbpy_selected_thread, METH_NOARGS, "selected_thread () -> gdb.InferiorThread.\n\ Return the selected thread object." }, + { "selected_inferior", gdbpy_selected_inferior, METH_NOARGS, + "selected_inferior () -> gdb.Inferior.\n\ +Return the selected inferior object." }, { "inferiors", gdbpy_inferiors, METH_NOARGS, "inferiors () -> (gdb.Inferior, ...).\n\ Return a tuple containing all inferiors." }, diff --git a/contrib/gdb-7/gdb/python/python.h b/contrib/gdb-7/gdb/python/python.h index ce0eb351f7..9e461f7ee9 100644 --- a/contrib/gdb-7/gdb/python/python.h +++ b/contrib/gdb-7/gdb/python/python.h @@ -1,6 +1,6 @@ /* Python/gdb header for generic use in gdb - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -30,7 +30,7 @@ extern void finish_python_initialization (void); void eval_python_from_control_command (struct command_line *); -void source_python_script (FILE *stream, const char *file); +void source_python_script (const char *file); int apply_val_pretty_printer (struct type *type, const gdb_byte *valaddr, int embedded_offset, CORE_ADDR address, diff --git a/contrib/gdb-7/gdb/ravenscar-sparc-thread.c b/contrib/gdb-7/gdb/ravenscar-sparc-thread.c index beb6bbc1f0..93af256b51 100644 --- a/contrib/gdb-7/gdb/ravenscar-sparc-thread.c +++ b/contrib/gdb-7/gdb/ravenscar-sparc-thread.c @@ -1,6 +1,6 @@ /* Ravenscar SPARC target support. - Copyright 2004, 2010, 2011 Free Software Foundation, Inc. + Copyright 2004, 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ravenscar-thread.c b/contrib/gdb-7/gdb/ravenscar-thread.c index 173a524667..63ecad5440 100644 --- a/contrib/gdb-7/gdb/ravenscar-thread.c +++ b/contrib/gdb-7/gdb/ravenscar-thread.c @@ -1,6 +1,6 @@ /* Ada Ravenscar thread support. - Copyright 2004, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright 2004, 2009-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -51,6 +51,7 @@ static ptid_t base_ptid; static const char running_thread_name[] = "__gnat_running_thread_table"; static const char known_tasks_name[] = "system__tasking__debug__known_tasks"; +static const char first_task_name[] = "system__tasking__debug__first_task"; static const char ravenscar_runtime_initializer[] = "system__bb__threads__initialize"; @@ -135,10 +136,12 @@ has_ravenscar_runtime (void) lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL); struct minimal_symbol *msym_known_tasks = lookup_minimal_symbol (known_tasks_name, NULL, NULL); + struct minimal_symbol *msym_first_task = + lookup_minimal_symbol (first_task_name, NULL, NULL); struct minimal_symbol *msym_running_thread = get_running_thread_msymbol (); return (msym_ravenscar_runtime_initializer - && msym_known_tasks + && (msym_known_tasks || msym_first_task) && msym_running_thread); } @@ -219,7 +222,7 @@ ravenscar_add_thread (struct ada_task_info *task) static void ravenscar_find_new_threads (struct target_ops *ops) { - ada_build_task_list (0); + ada_build_task_list (); /* Do not clear the thread list before adding the Ada task, to keep the thread that the process stratum has included into it diff --git a/contrib/gdb-7/gdb/ravenscar-thread.h b/contrib/gdb-7/gdb/ravenscar-thread.h index 0e1bfa7d7b..5eeab38b61 100644 --- a/contrib/gdb-7/gdb/ravenscar-thread.h +++ b/contrib/gdb-7/gdb/ravenscar-thread.h @@ -1,6 +1,6 @@ /* Ada Ravenscar thread support. - Copyright 2004, 2010, 2011 Free Software Foundation, Inc. + Copyright 2004, 2010-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/record.c b/contrib/gdb-7/gdb/record.c index 65eaa111a7..e396262a52 100644 --- a/contrib/gdb-7/gdb/record.c +++ b/contrib/gdb-7/gdb/record.c @@ -1,6 +1,6 @@ /* Process record and replay target for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -30,6 +30,8 @@ #include "record.h" #include "elf-bfd.h" #include "gcore.h" +#include "event-loop.h" +#include "inf-loop.h" #include @@ -231,6 +233,7 @@ static int (*record_beneath_to_remove_breakpoint) (struct gdbarch *, static int (*record_beneath_to_stopped_by_watchpoint) (void); static int (*record_beneath_to_stopped_data_address) (struct target_ops *, CORE_ADDR *); +static void (*record_beneath_to_async) (void (*) (enum inferior_event_type, void *), void *); /* Alloc and free functions for record_reg, record_mem, and record_end entries. */ @@ -806,9 +809,22 @@ static int (*tmp_to_remove_breakpoint) (struct gdbarch *, struct bp_target_info *); static int (*tmp_to_stopped_by_watchpoint) (void); static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *); +static int (*tmp_to_stopped_data_address) (struct target_ops *, CORE_ADDR *); +static void (*tmp_to_async) (void (*) (enum inferior_event_type, void *), void *); static void record_restore (void); +/* Asynchronous signal handle registered as event loop source for when + we have pending events ready to be passed to the core. */ + +static struct async_event_handler *record_async_inferior_event_token; + +static void +record_async_inferior_event_handler (gdb_client_data data) +{ + inferior_event_handler (INF_REG_EVENT, NULL); +} + /* Open the process record target. */ static void @@ -852,9 +868,6 @@ record_open_1 (char *name, int from_tty) if (non_stop) error (_("Process record target can't debug inferior in non-stop mode " "(non-stop).")); - if (target_async_permitted) - error (_("Process record target can't debug inferior in asynchronous " - "mode (target-async).")); if (!gdbarch_process_record_p (target_gdbarch)) error (_("Process record: the current architecture doesn't support " @@ -911,6 +924,7 @@ record_open (char *name, int from_tty) tmp_to_remove_breakpoint = NULL; tmp_to_stopped_by_watchpoint = NULL; tmp_to_stopped_data_address = NULL; + tmp_to_async = NULL; /* Set the beneath function pointers. */ for (t = current_target.beneath; t != NULL; t = t->beneath) @@ -943,6 +957,8 @@ record_open (char *name, int from_tty) tmp_to_stopped_by_watchpoint = t->to_stopped_by_watchpoint; if (!tmp_to_stopped_data_address) tmp_to_stopped_data_address = t->to_stopped_data_address; + if (!tmp_to_async) + tmp_to_async = t->to_async; } if (!tmp_to_xfer_partial) error (_("Could not find 'to_xfer_partial' method on the target stack.")); @@ -966,11 +982,17 @@ record_open (char *name, int from_tty) record_beneath_to_remove_breakpoint = tmp_to_remove_breakpoint; record_beneath_to_stopped_by_watchpoint = tmp_to_stopped_by_watchpoint; record_beneath_to_stopped_data_address = tmp_to_stopped_data_address; + record_beneath_to_async = tmp_to_async; if (core_bfd) record_core_open_1 (name, from_tty); else record_open_1 (name, from_tty); + + /* Register extra event sources in the event loop. */ + record_async_inferior_event_token + = create_async_event_handler (record_async_inferior_event_handler, + NULL); } /* "to_close" target method. Close the process record target. */ @@ -1002,10 +1024,34 @@ record_close (int quitting) } record_core_buf_list = NULL; } + + if (record_async_inferior_event_token) + delete_async_event_handler (&record_async_inferior_event_token); } static int record_resume_step = 0; +/* True if we've been resumed, and so each record_wait call should + advance execution. If this is false, record_wait will return a + TARGET_WAITKIND_IGNORE. */ +static int record_resumed = 0; + +/* The execution direction of the last resume we got. This is + necessary for async mode. Vis (order is not strictly accurate): + + 1. user has the global execution direction set to forward + 2. user does a reverse-step command + 3. record_resume is called with global execution direction + temporarily switched to reverse + 4. GDB's execution direction is reverted back to forward + 5. target record notifies event loop there's an event to handle + 6. infrun asks the target which direction was it going, and switches + the global execution direction accordingly (to reverse) + 7. infrun polls an event out of the record target, and handles it + 8. GDB goes back to the event loop, and goto #4. +*/ +static enum exec_direction_kind record_execution_dir = EXEC_FORWARD; + /* "to_resume" target method. Resume the process record target. */ static void @@ -1013,6 +1059,8 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step, enum target_signal signal) { record_resume_step = step; + record_resumed = 1; + record_execution_dir = execution_direction; if (!RECORD_IS_REPLAY) { @@ -1054,6 +1102,16 @@ record_resume (struct target_ops *ops, ptid_t ptid, int step, record_beneath_to_resume (record_beneath_to_resume_ops, ptid, step, signal); } + + /* We are about to start executing the inferior (or simulate it), + let's register it with the event loop. */ + if (target_can_async_p ()) + { + target_async (inferior_event_handler, 0); + /* Notify the event loop there's an event to wait for. We do + most of the work in record_wait. */ + mark_async_event_handler (record_async_inferior_event_token); + } } static int record_get_sig = 0; @@ -1100,17 +1158,27 @@ record_wait_cleanups (void *ignore) where to stop. */ static ptid_t -record_wait (struct target_ops *ops, - ptid_t ptid, struct target_waitstatus *status, - int options) +record_wait_1 (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, + int options) { struct cleanup *set_cleanups = record_gdb_operation_disable_set (); if (record_debug) fprintf_unfiltered (gdb_stdlog, "Process record: record_wait " - "record_resume_step = %d\n", - record_resume_step); + "record_resume_step = %d, record_resumed = %d, direction=%s\n", + record_resume_step, record_resumed, + record_execution_dir == EXEC_FORWARD ? "forward" : "reverse"); + + if (!record_resumed) + { + gdb_assert ((options & TARGET_WNOHANG) != 0); + + /* No interesting event. */ + status->kind = TARGET_WAITKIND_IGNORE; + return minus_one_ptid; + } record_get_sig = 0; signal (SIGINT, record_sig_handler); @@ -1134,12 +1202,20 @@ record_wait (struct target_ops *ops, { ret = record_beneath_to_wait (record_beneath_to_wait_ops, ptid, status, options); + if (status->kind == TARGET_WAITKIND_IGNORE) + { + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + "Process record: record_wait " + "target beneath not done yet\n"); + return ret; + } if (single_step_breakpoints_inserted ()) remove_single_step_breakpoints (); if (record_resume_step) - return ret; + return ret; /* Is this a SIGTRAP? */ if (status->kind == TARGET_WAITKIND_STOPPED @@ -1204,6 +1280,10 @@ record_wait (struct target_ops *ops, set_executing (inferior_ptid, 1); } + if (record_debug) + fprintf_unfiltered (gdb_stdlog, + "Process record: record_wait " + "issuing one more step in the target beneath\n"); record_beneath_to_resume (record_beneath_to_resume_ops, ptid, step, TARGET_SIGNAL_0); @@ -1385,6 +1465,24 @@ replay_out: return inferior_ptid; } +static ptid_t +record_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *status, + int options) +{ + ptid_t return_ptid; + + return_ptid = record_wait_1 (ops, ptid, status, options); + if (status->kind != TARGET_WAITKIND_IGNORE) + { + /* We're reporting a stop. Make sure any spurious + target_wait(WNOHANG) doesn't advance the target until the + core wants us resumed again. */ + record_resumed = 0; + } + return return_ptid; +} + static int record_stopped_by_watchpoint (void) { @@ -1719,6 +1817,37 @@ record_goto_bookmark (gdb_byte *bookmark, int from_tty) return; } +static void +record_async (void (*callback) (enum inferior_event_type event_type, + void *context), void *context) +{ + /* If we're on top of a line target (e.g., linux-nat, remote), then + set it to async mode as well. Will be NULL if we're sitting on + top of the core target, for "record restore". */ + if (record_beneath_to_async != NULL) + record_beneath_to_async (callback, context); +} + +static int +record_can_async_p (void) +{ + /* We only enable async when the user specifically asks for it. */ + return target_async_permitted; +} + +static int +record_is_async_p (void) +{ + /* We only enable async when the user specifically asks for it. */ + return target_async_permitted; +} + +static enum exec_direction_kind +record_execution_direction (void) +{ + return record_execution_dir; +} + static void init_record_ops (void) { @@ -1746,6 +1875,10 @@ init_record_ops (void) /* Add bookmark target methods. */ record_ops.to_get_bookmark = record_get_bookmark; record_ops.to_goto_bookmark = record_goto_bookmark; + record_ops.to_async = record_async; + record_ops.to_can_async_p = record_can_async_p; + record_ops.to_is_async_p = record_is_async_p; + record_ops.to_execution_direction = record_execution_direction; record_ops.to_magic = OPS_MAGIC; } @@ -1756,6 +1889,18 @@ record_core_resume (struct target_ops *ops, ptid_t ptid, int step, enum target_signal signal) { record_resume_step = step; + record_resumed = 1; + record_execution_dir = execution_direction; + + /* We are about to start executing the inferior (or simulate it), + let's register it with the event loop. */ + if (target_can_async_p ()) + { + target_async (inferior_event_handler, 0); + + /* Notify the event loop there's an event to wait for. */ + mark_async_event_handler (record_async_inferior_event_token); + } } /* "to_kill" method for prec over corefile. */ @@ -1955,6 +2100,10 @@ init_record_core_ops (void) /* Add bookmark target methods. */ record_core_ops.to_get_bookmark = record_get_bookmark; record_core_ops.to_goto_bookmark = record_goto_bookmark; + record_core_ops.to_async = record_async; + record_core_ops.to_can_async_p = record_can_async_p; + record_core_ops.to_is_async_p = record_is_async_p; + record_core_ops.to_execution_direction = record_execution_direction; record_core_ops.to_magic = OPS_MAGIC; } diff --git a/contrib/gdb-7/gdb/record.h b/contrib/gdb-7/gdb/record.h index 7ddf548a8a..84396e66cb 100644 --- a/contrib/gdb-7/gdb/record.h +++ b/contrib/gdb-7/gdb/record.h @@ -1,6 +1,6 @@ /* Process record and replay target for GDB, the GNU debugger. - Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 2008-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/regcache.c b/contrib/gdb-7/gdb/regcache.c index 8b4d77ccc0..c716280237 100644 --- a/contrib/gdb-7/gdb/regcache.c +++ b/contrib/gdb-7/gdb/regcache.c @@ -1,7 +1,7 @@ /* Cache and manage the values of registers for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001, - 2002, 2004, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-1987, 1989, 1991, 1994-1996, 1998, 2000-2002, + 2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -30,6 +30,7 @@ #include "gdbcmd.h" /* For maintenanceprintlist. */ #include "observer.h" #include "exceptions.h" +#include "remote.h" /* * DATA STRUCTURE @@ -66,7 +67,7 @@ struct regcache_descr long sizeof_cooked_registers; long sizeof_cooked_register_status; - /* Offset and size (in 8 bit bytes), of reach register in the + /* Offset and size (in 8 bit bytes), of each register in the register cache. All registers (including those in the range [NR_RAW_REGISTERS .. NR_COOKED_REGISTERS) are given an offset. */ @@ -330,7 +331,7 @@ regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, } } -void +static void regcache_restore (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, void *cooked_read_context) @@ -350,9 +351,10 @@ regcache_restore (struct regcache *dst, { if (gdbarch_register_reggroup_p (gdbarch, regnum, restore_reggroup)) { - int valid = cooked_read (cooked_read_context, regnum, buf); + enum register_status status; - if (valid) + status = cooked_read (cooked_read_context, regnum, buf); + if (status == REG_VALID) regcache_cooked_write (dst, regnum, buf); } } @@ -449,17 +451,33 @@ struct regcache_list static struct regcache_list *current_regcache; struct regcache * -get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) +get_thread_arch_aspace_regcache (ptid_t ptid, struct gdbarch *gdbarch, + struct address_space *aspace) { struct regcache_list *list; struct regcache *new_regcache; - struct address_space *aspace; for (list = current_regcache; list; list = list->next) if (ptid_equal (list->regcache->ptid, ptid) && get_regcache_arch (list->regcache) == gdbarch) return list->regcache; + new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0); + new_regcache->ptid = ptid; + + list = xmalloc (sizeof (struct regcache_list)); + list->regcache = new_regcache; + list->next = current_regcache; + current_regcache = list; + + return new_regcache; +} + +struct regcache * +get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) +{ + struct address_space *aspace; + /* For the benefit of "maint print registers" & co when debugging an executable, allow dumping the regcache even when there is no thread selected (target_thread_address_space internal-errors if @@ -470,15 +488,7 @@ get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch) ? NULL : target_thread_address_space (ptid)); - new_regcache = regcache_xmalloc_1 (gdbarch, aspace, 0); - new_regcache->ptid = ptid; - - list = xmalloc (sizeof (struct regcache_list)); - list->regcache = new_regcache; - list->next = current_regcache; - current_regcache = list; - - return new_regcache; + return get_thread_arch_aspace_regcache (ptid, gdbarch, aspace); } static ptid_t current_thread_ptid; @@ -538,7 +548,6 @@ void registers_changed_ptid (ptid_t ptid) { struct regcache_list *list, **list_link; - int wildcard = ptid_equal (ptid, minus_one_ptid); list = current_regcache; list_link = ¤t_regcache; @@ -559,13 +568,13 @@ registers_changed_ptid (ptid_t ptid) list = *list_link; } - if (wildcard || ptid_equal (ptid, current_thread_ptid)) + if (ptid_match (current_thread_ptid, ptid)) { current_thread_ptid = null_ptid; current_thread_arch = NULL; } - if (wildcard || ptid_equal (ptid, inferior_ptid)) + if (ptid_match (inferior_ptid, ptid)) { /* We just deleted the regcache of the current thread. Need to forget about any frames we have cached, too. */ @@ -708,11 +717,66 @@ regcache_cooked_read (struct regcache *regcache, int regnum, gdb_byte *buf) return regcache->register_status[regnum]; } + else if (gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch)) + { + struct value *mark, *computed; + enum register_status result = REG_VALID; + + mark = value_mark (); + + computed = gdbarch_pseudo_register_read_value (regcache->descr->gdbarch, + regcache, regnum); + if (value_entirely_available (computed)) + memcpy (buf, value_contents_raw (computed), + regcache->descr->sizeof_register[regnum]); + else + { + memset (buf, 0, regcache->descr->sizeof_register[regnum]); + result = REG_UNAVAILABLE; + } + + value_free_to_mark (mark); + + return result; + } else return gdbarch_pseudo_register_read (regcache->descr->gdbarch, regcache, regnum, buf); } +struct value * +regcache_cooked_read_value (struct regcache *regcache, int regnum) +{ + gdb_assert (regnum >= 0); + gdb_assert (regnum < regcache->descr->nr_cooked_registers); + + if (regnum < regcache->descr->nr_raw_registers + || (regcache->readonly_p + && regcache->register_status[regnum] != REG_UNKNOWN) + || !gdbarch_pseudo_register_read_value_p (regcache->descr->gdbarch)) + { + struct value *result; + + result = allocate_value (register_type (regcache->descr->gdbarch, + regnum)); + VALUE_LVAL (result) = lval_register; + VALUE_REGNUM (result) = regnum; + + /* It is more efficient in general to do this delegation in this + direction than in the other one, even though the value-based + API is preferred. */ + if (regcache_cooked_read (regcache, regnum, + value_contents_raw (result)) == REG_UNAVAILABLE) + mark_value_bytes_unavailable (result, 0, + TYPE_LENGTH (value_type (result))); + + return result; + } + else + return gdbarch_pseudo_register_read_value (regcache->descr->gdbarch, + regcache, regnum); +} + enum register_status regcache_cooked_read_signed (struct regcache *regcache, int regnum, LONGEST *val) @@ -1053,7 +1117,8 @@ dump_endian_bytes (struct ui_file *file, enum bfd_endian endian, enum regcache_dump_what { regcache_dump_none, regcache_dump_raw, - regcache_dump_cooked, regcache_dump_groups + regcache_dump_cooked, regcache_dump_groups, + regcache_dump_remote }; static void @@ -1251,6 +1316,23 @@ regcache_dump (struct regcache *regcache, struct ui_file *file, } } + /* Remote packet configuration. */ + if (what_to_dump == regcache_dump_remote) + { + if (regnum < 0) + { + fprintf_unfiltered (file, "Rmt Nr g/G Offset"); + } + else if (regnum < regcache->descr->nr_raw_registers) + { + int pnum, poffset; + + if (remote_register_number_and_offset (get_regcache_arch (regcache), regnum, + &pnum, &poffset)) + fprintf_unfiltered (file, "%7d %11d", pnum, poffset); + } + } + fprintf_unfiltered (file, "\n"); } @@ -1309,6 +1391,12 @@ maintenance_print_register_groups (char *args, int from_tty) regcache_print (args, regcache_dump_groups); } +static void +maintenance_print_remote_registers (char *args, int from_tty) +{ + regcache_print (args, regcache_dump_remote); +} + extern initialize_file_ftype _initialize_regcache; /* -Wmissing-prototype */ void @@ -1342,5 +1430,11 @@ _initialize_regcache (void) "including each register's group.\n" "Takes an optional file parameter."), &maintenanceprintlist); + add_cmd ("remote-registers", class_maintenance, + maintenance_print_remote_registers, _("\ +Print the internal register configuration including each register's\n\ +remote register number and buffer offset in the g/G packets.\n\ +Takes an optional file parameter."), + &maintenanceprintlist); } diff --git a/contrib/gdb-7/gdb/regcache.h b/contrib/gdb-7/gdb/regcache.h index 3708c86d64..93b449998e 100644 --- a/contrib/gdb-7/gdb/regcache.h +++ b/contrib/gdb-7/gdb/regcache.h @@ -1,7 +1,7 @@ /* Cache and manage the values of registers for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1989, 1991, 1994, 1995, 1996, 1998, 2000, 2001, - 2002, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-1987, 1989, 1991, 1994-1996, 1998, 2000-2002, + 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -28,6 +28,9 @@ struct address_space; extern struct regcache *get_current_regcache (void); extern struct regcache *get_thread_regcache (ptid_t ptid); extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *); +extern struct regcache *get_thread_arch_aspace_regcache (ptid_t, + struct gdbarch *, + struct address_space *); void regcache_xfree (struct regcache *regcache); struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache); @@ -104,6 +107,12 @@ enum register_status regcache_cooked_read (struct regcache *regcache, void regcache_cooked_write (struct regcache *regcache, int rawnum, const gdb_byte *buf); +/* Read register REGNUM from REGCACHE and return a new value. This + will call mark_value_bytes_unavailable as appropriate. */ + +struct value *regcache_cooked_read_value (struct regcache *regcache, + int regnum); + /* Read a register as a signed/unsigned quantity. */ extern enum register_status regcache_cooked_read_signed (struct regcache *regcache, @@ -165,9 +174,6 @@ typedef enum register_status (regcache_cooked_read_ftype) (void *src, extern void regcache_save (struct regcache *dst, regcache_cooked_read_ftype *cooked_read, void *cooked_read_context); -extern void regcache_restore (struct regcache *dst, - regcache_cooked_read_ftype *cooked_read, - void *cooked_read_context); /* Copy/duplicate the contents of a register cache. By default, the operation is pass-through. Writes to DST and reads from SRC will diff --git a/contrib/gdb-7/gdb/regformats/regdat.sh b/contrib/gdb-7/gdb/regformats/regdat.sh index 5d3cc3bdb5..3ca57fa4be 100755 --- a/contrib/gdb-7/gdb/regformats/regdat.sh +++ b/contrib/gdb-7/gdb/regformats/regdat.sh @@ -1,8 +1,7 @@ #!/bin/sh -u # Register protocol definitions for GDB, the GNU debugger. -# Copyright 2001, 2002, 2007, 2008, 2009, 2010, 2011 -# Free Software Foundation, Inc. +# Copyright 2001-2002, 2007-2012 Free Software Foundation, Inc. # # This file is part of GDB. # diff --git a/contrib/gdb-7/gdb/regformats/regdef.h b/contrib/gdb-7/gdb/regformats/regdef.h index 378a827f11..56c7a9f80d 100644 --- a/contrib/gdb-7/gdb/regformats/regdef.h +++ b/contrib/gdb-7/gdb/regformats/regdef.h @@ -1,6 +1,5 @@ /* Register protocol definition structures for the GNU Debugger - Copyright 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright 2001-2002, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/reggroups.c b/contrib/gdb-7/gdb/reggroups.c index 846b1baf9b..b479050302 100644 --- a/contrib/gdb-7/gdb/reggroups.c +++ b/contrib/gdb-7/gdb/reggroups.c @@ -1,7 +1,6 @@ /* Register groupings for GDB, the GNU debugger. - Copyright (C) 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002-2003, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat. diff --git a/contrib/gdb-7/gdb/reggroups.h b/contrib/gdb-7/gdb/reggroups.h index 8e009b3463..fa62d1e3d4 100644 --- a/contrib/gdb-7/gdb/reggroups.h +++ b/contrib/gdb-7/gdb/reggroups.h @@ -1,7 +1,6 @@ /* Register groupings for GDB, the GNU debugger. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat. diff --git a/contrib/gdb-7/gdb/regset.c b/contrib/gdb-7/gdb/regset.c index 6dfbc8ab23..af8a793b45 100644 --- a/contrib/gdb-7/gdb/regset.c +++ b/contrib/gdb-7/gdb/regset.c @@ -1,7 +1,6 @@ /* Manage register sets. - Copyright (C) 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/regset.h b/contrib/gdb-7/gdb/regset.h index e378f29dec..aabff374e3 100644 --- a/contrib/gdb-7/gdb/regset.h +++ b/contrib/gdb-7/gdb/regset.h @@ -1,7 +1,6 @@ /* Manage register sets. - Copyright (C) 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/remote-fileio.c b/contrib/gdb-7/gdb/remote-fileio.c index 68298e7862..ee43dd686e 100644 --- a/contrib/gdb-7/gdb/remote-fileio.c +++ b/contrib/gdb-7/gdb/remote-fileio.c @@ -1,7 +1,6 @@ /* Remote File-I/O communications - Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2005-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -36,16 +35,7 @@ #include #include #ifdef __CYGWIN__ -#include /* For cygwin_conv_to_full_posix_path. */ -#include -#if CYGWIN_VERSION_DLL_MAKE_COMBINED(CYGWIN_VERSION_API_MAJOR,CYGWIN_VERSION_API_MINOR) < 181 -# define CCP_POSIX_TO_WIN_A 0 -# define CCP_WIN_A_TO_POSIX 2 -# define cygwin_conv_path(op, from, to, size) \ - (op == CCP_WIN_A_TO_POSIX) ? \ - cygwin_conv_to_full_posix_path (from, to) : \ - cygwin_conv_to_win32_path (from, to) -#endif +#include /* For cygwin_conv_path. */ #endif #include @@ -1425,7 +1415,8 @@ remote_fileio_request (char *buf, int ctrlc_pending_p) remote_fio_ctrl_c_flag = 0; remote_fio_no_longjmp = 0; - ex = catch_exceptions (uiout, do_remote_fileio_request, (void *)buf, + ex = catch_exceptions (current_uiout, + do_remote_fileio_request, (void *)buf, RETURN_MASK_ALL); switch (ex) { diff --git a/contrib/gdb-7/gdb/remote-fileio.h b/contrib/gdb-7/gdb/remote-fileio.h index 2f9558968e..e04d052f03 100644 --- a/contrib/gdb-7/gdb/remote-fileio.h +++ b/contrib/gdb-7/gdb/remote-fileio.h @@ -1,7 +1,6 @@ /* Remote File-I/O communications - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/remote.c b/contrib/gdb-7/gdb/remote.c index 243bdd764f..04b818f8b8 100644 --- a/contrib/gdb-7/gdb/remote.c +++ b/contrib/gdb-7/gdb/remote.c @@ -1,8 +1,6 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1988-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -134,8 +132,6 @@ static int remote_is_async_p (void); static void remote_async (void (*callback) (enum inferior_event_type event_type, void *context), void *context); -static int remote_async_mask (int new_mask); - static void remote_detach (struct target_ops *ops, char *args, int from_tty); static void remote_interrupt (int signo); @@ -275,6 +271,10 @@ struct remote_state char *buf; long buf_size; + /* True if we're going through initial connection setup (finding out + about the remote side's threads, relocating symbols, etc.). */ + int starting_up; + /* If we negotiated packet size explicitly (and thus can bypass heuristics for the largest packet size that will not overflow a buffer in the stub), this will be set to that packet size. @@ -325,10 +325,21 @@ struct remote_state /* True if the stub reports support for static tracepoints. */ int static_tracepoints; + /* True if the stub reports support for installing tracepoint while + tracing. */ + int install_in_trace; + /* True if the stub can continue running a trace while GDB is disconnected. */ int disconnected_tracing; + /* True if the stub reports support for enabling and disabling + tracepoints while a trace experiment is running. */ + int enable_disable_tracepoints; + + /* True if the stub can collect strings using tracenz bytecode. */ + int string_tracing; + /* Nonzero if the user has pressed Ctrl-C, but the target hasn't responded to that. */ int ctrlc_pending_p; @@ -535,24 +546,15 @@ compare_pnums (const void *lhs_, const void *rhs_) return 1; } -static void * -init_remote_state (struct gdbarch *gdbarch) +static int +map_regcache_remote_table (struct gdbarch *gdbarch, struct packet_reg *regs) { int regnum, num_remote_regs, offset; - struct remote_state *rs = get_remote_state_raw (); - struct remote_arch_state *rsa; struct packet_reg **remote_regs; - rsa = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct remote_arch_state); - - /* Use the architecture to build a regnum<->pnum table, which will be - 1:1 unless a feature set specifies otherwise. */ - rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, - gdbarch_num_regs (gdbarch), - struct packet_reg); for (regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++) { - struct packet_reg *r = &rsa->regs[regnum]; + struct packet_reg *r = ®s[regnum]; if (register_size (gdbarch, regnum) == 0) /* Do not try to fetch zero-sized (placeholder) registers. */ @@ -568,12 +570,12 @@ init_remote_state (struct gdbarch *gdbarch) number. */ remote_regs = alloca (gdbarch_num_regs (gdbarch) - * sizeof (struct packet_reg *)); + * sizeof (struct packet_reg *)); for (num_remote_regs = 0, regnum = 0; regnum < gdbarch_num_regs (gdbarch); regnum++) - if (rsa->regs[regnum].pnum != -1) - remote_regs[num_remote_regs++] = &rsa->regs[regnum]; + if (regs[regnum].pnum != -1) + remote_regs[num_remote_regs++] = ®s[regnum]; qsort (remote_regs, num_remote_regs, sizeof (struct packet_reg *), compare_pnums); @@ -585,9 +587,55 @@ init_remote_state (struct gdbarch *gdbarch) offset += register_size (gdbarch, remote_regs[regnum]->regnum); } + return offset; +} + +/* Given the architecture described by GDBARCH, return the remote + protocol register's number and the register's offset in the g/G + packets of GDB register REGNUM, in PNUM and POFFSET respectively. + If the target does not have a mapping for REGNUM, return false, + otherwise, return true. */ + +int +remote_register_number_and_offset (struct gdbarch *gdbarch, int regnum, + int *pnum, int *poffset) +{ + int sizeof_g_packet; + struct packet_reg *regs; + struct cleanup *old_chain; + + gdb_assert (regnum < gdbarch_num_regs (gdbarch)); + + regs = xcalloc (gdbarch_num_regs (gdbarch), sizeof (struct packet_reg)); + old_chain = make_cleanup (xfree, regs); + + sizeof_g_packet = map_regcache_remote_table (gdbarch, regs); + + *pnum = regs[regnum].pnum; + *poffset = regs[regnum].offset; + + do_cleanups (old_chain); + + return *pnum != -1; +} + +static void * +init_remote_state (struct gdbarch *gdbarch) +{ + struct remote_state *rs = get_remote_state_raw (); + struct remote_arch_state *rsa; + + rsa = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct remote_arch_state); + + /* Use the architecture to build a regnum<->pnum table, which will be + 1:1 unless a feature set specifies otherwise. */ + rsa->regs = GDBARCH_OBSTACK_CALLOC (gdbarch, + gdbarch_num_regs (gdbarch), + struct packet_reg); + /* Record the maximum possible size of the g packet - it may turn out to be smaller. */ - rsa->sizeof_g_packet = offset; + rsa->sizeof_g_packet = map_regcache_remote_table (gdbarch, rsa->regs); /* Default maximum number of characters in a packet body. Many remote stubs have a hardwired buffer size of 400 bytes @@ -680,8 +728,6 @@ static struct target_ops remote_ops; static struct target_ops extended_remote_ops; -static int remote_async_mask_value = 1; - /* 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 @@ -1199,6 +1245,7 @@ enum { PACKET_qXfer_auxv, PACKET_qXfer_features, PACKET_qXfer_libraries, + PACKET_qXfer_libraries_svr4, PACKET_qXfer_memory_map, PACKET_qXfer_spu_read, PACKET_qXfer_spu_write, @@ -1221,10 +1268,13 @@ enum { PACKET_ConditionalTracepoints, PACKET_FastTracepoints, PACKET_StaticTracepoints, + PACKET_InstallInTrace, PACKET_bc, PACKET_bs, PACKET_TracepointSource, PACKET_QAllow, + PACKET_qXfer_fdpic, + PACKET_QDisableRandomization, PACKET_MAX }; @@ -1559,20 +1609,17 @@ static char *last_pass_packet; it can simply pass through to the inferior without reporting. */ static void -remote_pass_signals (void) +remote_pass_signals (int numsigs, unsigned char *pass_signals) { if (remote_protocol_packets[PACKET_QPassSignals].support != PACKET_DISABLE) { char *pass_packet, *p; - int numsigs = (int) TARGET_SIGNAL_LAST; int count = 0, i; gdb_assert (numsigs < 256); for (i = 0; i < numsigs; i++) { - if (signal_stop_state (i) == 0 - && signal_print_state (i) == 0 - && signal_pass_state (i) == 1) + if (pass_signals[i]) count++; } pass_packet = xmalloc (count * 3 + strlen ("QPassSignals:") + 1); @@ -1580,9 +1627,7 @@ remote_pass_signals (void) p = pass_packet + strlen (pass_packet); for (i = 0; i < numsigs; i++) { - if (signal_stop_state (i) == 0 - && signal_print_state (i) == 0 - && signal_pass_state (i) == 1) + if (pass_signals[i]) { if (i >= 16) *p++ = tohex (i >> 4); @@ -1612,14 +1657,6 @@ remote_pass_signals (void) } } -static void -remote_notice_signals (ptid_t ptid) -{ - /* Update the remote on signals to silently pass, if they've - changed. */ - remote_pass_signals (); -} - /* If PTID is MAGIC_NULL_PTID, don't set any thread. If PTID is MINUS_ONE_PTID, set the thread to -1, so the stub returns the thread. If GEN is set, set the general thread, if not, then set @@ -3097,19 +3134,6 @@ set_stop_requested_callback (struct thread_info *thread, void *data) return 0; } -/* Stub for catch_exception. */ - -struct start_remote_args -{ - int from_tty; - - /* The current target. */ - struct target_ops *target; - - /* Non-zero if this is an extended-remote target. */ - int extended_p; -}; - /* Send interrupt_sequence to remote target. */ static void send_interrupt_sequence (void) @@ -3130,9 +3154,8 @@ send_interrupt_sequence (void) } static void -remote_start_remote (struct ui_out *uiout, void *opaque) +remote_start_remote (int from_tty, struct target_ops *target, int extended_p) { - struct start_remote_args *args = opaque; struct remote_state *rs = get_remote_state (); struct packet_config *noack_config; char *wait_status = NULL; @@ -3145,6 +3168,10 @@ remote_start_remote (struct ui_out *uiout, void *opaque) /* Ack any packet which the remote side has already sent. */ serial_write (remote_desc, "+", 1); + /* Signal other parts that we're going through the initial setup, + and so things may not be stable yet. */ + rs->starting_up = 1; + /* The first packet we send to the target is the optional "supported packets" request. If the target can answer this, it will tell us which later probes to skip. */ @@ -3179,7 +3206,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque) rs->noack_mode = 1; } - if (args->extended_p) + if (extended_p) { /* Tell the remote that we are using the extended protocol. */ putpkt ("!"); @@ -3197,7 +3224,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque) /* On OSs where the list of libraries is global to all processes, we fetch them early. */ if (gdbarch_has_global_solist (target_gdbarch)) - solib_add (NULL, args->from_tty, args->target, auto_solib_add); + solib_add (NULL, from_tty, target, auto_solib_add); if (non_stop) { @@ -3215,7 +3242,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque) controlling. We default to adding them in the running state. The '?' query below will then tell us about which threads are stopped. */ - remote_threads_info (args->target); + remote_threads_info (target); } else if (rs->non_stop_aware) { @@ -3236,11 +3263,12 @@ remote_start_remote (struct ui_out *uiout, void *opaque) { if (rs->buf[0] == 'W' || rs->buf[0] == 'X') { - if (!args->extended_p) + if (!extended_p) error (_("The target is not running (try extended-remote?)")); /* We're connected, but not running. Drop out before we call start_remote. */ + rs->starting_up = 0; return; } else @@ -3270,13 +3298,24 @@ remote_start_remote (struct ui_out *uiout, void *opaque) /* Always add the main thread. */ add_thread_silent (inferior_ptid); + /* init_wait_for_inferior should be called before get_offsets in order + to manage `inserted' flag in bp loc in a correct state. + breakpoint_init_inferior, called from init_wait_for_inferior, set + `inserted' flag to 0, while before breakpoint_re_set, called from + start_remote, set `inserted' flag to 1. In the initialization of + inferior, breakpoint_init_inferior should be called first, and then + breakpoint_re_set can be called. If this order is broken, state of + `inserted' flag is wrong, and cause some problems on breakpoint + manipulation. */ + init_wait_for_inferior (); + get_offsets (); /* Get text, data & bss offsets. */ /* If we could not find a description using qXfer, and we know how to do it some other way, try again. This is not supported for non-stop; it could be, but it is tricky if there are no stopped threads when we connect. */ - if (remote_read_description_p (args->target) + if (remote_read_description_p (target) && gdbarch_target_desc (target_gdbarch) == NULL) { target_clear_description (); @@ -3289,7 +3328,7 @@ remote_start_remote (struct ui_out *uiout, void *opaque) rs->cached_wait_status = 1; immediate_quit--; - start_remote (args->from_tty); /* Initialize gdb process mechanisms. */ + start_remote (from_tty); /* Initialize gdb process mechanisms. */ } else { @@ -3331,11 +3370,12 @@ remote_start_remote (struct ui_out *uiout, void *opaque) if (thread_count () == 0) { - if (!args->extended_p) + if (!extended_p) error (_("The target is not running (try extended-remote?)")); /* We're connected, but not running. Drop out before we call start_remote. */ + rs->starting_up = 0; return; } @@ -3355,10 +3395,8 @@ remote_start_remote (struct ui_out *uiout, void *opaque) the stop reply queue. */ gdb_assert (wait_status == NULL); - /* Update the remote on signals to silently pass, or more - importantly, which to not ignore, in case a previous session - had set some different set of signals to be ignored. */ - remote_pass_signals (); + /* Report all signals during attach/startup. */ + remote_pass_signals (0, NULL); } /* If we connected to a live target, do some additional setup. */ @@ -3390,6 +3428,12 @@ remote_start_remote (struct ui_out *uiout, void *opaque) merge_uploaded_tracepoints (&uploaded_tps); } + /* The thread and inferior lists are now synchronized with the + target, our symbols have been relocated, and we're merged the + target's tracepoints with ours. We're done with basic start + up. */ + rs->starting_up = 0; + /* If breakpoints are global, insert them now. */ if (gdbarch_has_global_breakpoints (target_gdbarch) && breakpoints_always_inserted_mode ()) @@ -3671,6 +3715,16 @@ remote_static_tracepoint_feature (const struct protocol_feature *feature, rs->static_tracepoints = (support == PACKET_ENABLE); } +static void +remote_install_in_trace_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + + rs->install_in_trace = (support == PACKET_ENABLE); +} + static void remote_disconnected_tracing_feature (const struct protocol_feature *feature, enum packet_support support, @@ -3681,6 +3735,26 @@ remote_disconnected_tracing_feature (const struct protocol_feature *feature, rs->disconnected_tracing = (support == PACKET_ENABLE); } +static void +remote_enable_disable_tracepoint_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + + rs->enable_disable_tracepoints = (support == PACKET_ENABLE); +} + +static void +remote_string_tracing_feature (const struct protocol_feature *feature, + enum packet_support support, + const char *value) +{ + struct remote_state *rs = get_remote_state (); + + rs->string_tracing = (support == PACKET_ENABLE); +} + static struct protocol_feature remote_protocol_features[] = { { "PacketSize", PACKET_DISABLE, remote_packet_size, -1 }, { "qXfer:auxv:read", PACKET_DISABLE, remote_supported_packet, @@ -3689,6 +3763,8 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_qXfer_features }, { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_libraries }, + { "qXfer:libraries-svr4:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_libraries_svr4 }, { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet, PACKET_qXfer_memory_map }, { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet, @@ -3717,6 +3793,8 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_FastTracepoints }, { "StaticTracepoints", PACKET_DISABLE, remote_static_tracepoint_feature, PACKET_StaticTracepoints }, + {"InstallInTrace", PACKET_DISABLE, remote_install_in_trace_feature, + PACKET_InstallInTrace}, { "DisconnectedTracing", PACKET_DISABLE, remote_disconnected_tracing_feature, -1 }, { "ReverseContinue", PACKET_DISABLE, remote_supported_packet, @@ -3727,6 +3805,14 @@ static struct protocol_feature remote_protocol_features[] = { PACKET_TracepointSource }, { "QAllow", PACKET_DISABLE, remote_supported_packet, PACKET_QAllow }, + { "EnableDisableTracepoints", PACKET_DISABLE, + remote_enable_disable_tracepoint_feature, -1 }, + { "qXfer:fdpic:read", PACKET_DISABLE, remote_supported_packet, + PACKET_qXfer_fdpic }, + { "QDisableRandomization", PACKET_DISABLE, remote_supported_packet, + PACKET_QDisableRandomization }, + { "tracenz", PACKET_DISABLE, + remote_string_tracing_feature, -1 }, }; static char *remote_support_xml; @@ -4060,14 +4146,12 @@ remote_open_1 (char *name, int from_tty, all the ``target ....'' commands to share a common callback function. See cli-dump.c. */ { - struct gdb_exception ex; - struct start_remote_args args; - - args.from_tty = from_tty; - args.target = target; - args.extended_p = extended_p; + volatile struct gdb_exception ex; - ex = catch_exception (uiout, remote_start_remote, &args, RETURN_MASK_ALL); + TRY_CATCH (ex, RETURN_MASK_ALL) + { + remote_start_remote (from_tty, target, extended_p); + } if (ex.reason < 0) { /* Pop the partially set up target - unless something else did @@ -4528,9 +4612,6 @@ remote_resume (struct target_ops *ops, last_sent_signal = siggnal; last_sent_step = step; - /* Update the inferior on signals to silently pass, if they've changed. */ - remote_pass_signals (); - /* The vCont packet doesn't need to specify threads via Hc. */ /* No reverse support (yet) for vCont. */ if (execution_direction != EXEC_REVERSE) @@ -4850,8 +4931,8 @@ remote_console_output (char *msg) tb[1] = 0; fputs_unfiltered (tb, gdb_stdtarg); } - gdb_flush (gdb_stdtarg); - } + gdb_flush (gdb_stdtarg); +} typedef struct cached_reg { @@ -4869,6 +4950,10 @@ struct stop_reply struct target_waitstatus ws; + /* Expedited registers. This makes remote debugging a bit more + efficient for those targets that provide critical registers as + part of their normal status mechanism (as another roundtrip to + fetch them is avoided). */ VEC(cached_reg_t) *regcache; int stopped_by_watchpoint_p; @@ -6210,7 +6295,7 @@ check_binary_download (CORE_ADDR addr) { if (remote_debug) fprintf_unfiltered (gdb_stdlog, - "binary downloading suppported by target\n"); + "binary downloading supported by target\n"); remote_protocol_packets[PACKET_X].support = PACKET_ENABLE; } break; @@ -6302,7 +6387,7 @@ remote_write_bytes_aux (const char *header, CORE_ADDR memaddr, if (todo <= 0) internal_error (__FILE__, __LINE__, - _("minumum packet size too small to write data")); + _("minimum packet size too small to write data")); /* If we already need another packet, then try to align the end of this packet to a useful boundary. */ @@ -7301,12 +7386,20 @@ getpkt_or_notif_sane (char **buf, long *sizeof_buf, int forever) } +/* A helper function that just calls putpkt; for type correctness. */ + +static int +putpkt_for_catch_errors (void *arg) +{ + return putpkt (arg); +} + static void remote_kill (struct target_ops *ops) { /* Use catch_errors so the user can quit from gdb even when we aren't on speaking terms with the remote system. */ - catch_errors ((catch_errors_ftype *) putpkt, "k", "", RETURN_MASK_ERROR); + catch_errors (putpkt_for_catch_errors, "k", "", RETURN_MASK_ERROR); /* Don't wait for it to die. I'm not really sure it matters whether we do or not. For the existing stubs, kill is a noop. */ @@ -7450,6 +7543,28 @@ extended_remote_mourn (struct target_ops *ops) extended_remote_mourn_1 (ops); } +static int +extended_remote_supports_disable_randomization (void) +{ + return (remote_protocol_packets[PACKET_QDisableRandomization].support + == PACKET_ENABLE); +} + +static void +extended_remote_disable_randomization (int val) +{ + struct remote_state *rs = get_remote_state (); + char *reply; + + sprintf (rs->buf, "QDisableRandomization:%x", val); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (*reply == '\0') + error (_("Target does not support QDisableRandomization.")); + if (strcmp (reply, "OK") != 0) + error (_("Bogus QDisableRandomization reply from target: %s"), reply); +} + static int extended_remote_run (char *args) { @@ -7526,6 +7641,10 @@ extended_remote_create_inferior_1 (char *exec_file, char *args, if (target_can_async_p ()) target_async (inferior_event_handler, 0); + /* Disable address space randomization if requested (and supported). */ + if (extended_remote_supports_disable_randomization ()) + extended_remote_disable_randomization (disable_randomization); + /* Now restart the remote server. */ if (extended_remote_run (args) == -1) { @@ -7737,8 +7856,22 @@ remote_remove_watchpoint (CORE_ADDR addr, int len, int type, int remote_hw_watchpoint_limit = -1; +int remote_hw_watchpoint_length_limit = -1; int remote_hw_breakpoint_limit = -1; +static int +remote_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) +{ + if (remote_hw_watchpoint_length_limit == 0) + return 0; + else if (remote_hw_watchpoint_length_limit < 0) + return 1; + else if (len <= remote_hw_watchpoint_length_limit) + return 1; + else + return 0; +} + static int remote_check_watch_resources (int type, int cnt, int ot) { @@ -8240,6 +8373,11 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, (ops, "libraries", annex, readbuf, offset, len, &remote_protocol_packets[PACKET_qXfer_libraries]); + case TARGET_OBJECT_LIBRARIES_SVR4: + return remote_read_qxfer + (ops, "libraries-svr4", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_libraries_svr4]); + case TARGET_OBJECT_MEMORY_MAP: gdb_assert (annex == NULL); return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len, @@ -8262,6 +8400,10 @@ remote_xfer_partial (struct target_ops *ops, enum target_object object, return remote_read_qxfer (ops, "traceframe-info", annex, readbuf, offset, len, &remote_protocol_packets[PACKET_qXfer_traceframe_info]); + + case TARGET_OBJECT_FDPIC: + return remote_read_qxfer (ops, "fdpic", annex, readbuf, offset, len, + &remote_protocol_packets[PACKET_qXfer_fdpic]); default: return -1; } @@ -9613,6 +9755,13 @@ remote_supports_non_stop (void) return 1; } +static int +remote_supports_disable_randomization (void) +{ + /* Only supported in extended mode. */ + return 0; +} + static int remote_supports_multi_process (void) { @@ -9645,6 +9794,30 @@ remote_supports_static_tracepoints (void) return rs->static_tracepoints; } +static int +remote_supports_install_in_trace (void) +{ + struct remote_state *rs = get_remote_state (); + + return rs->install_in_trace; +} + +static int +remote_supports_enable_disable_tracepoint (void) +{ + struct remote_state *rs = get_remote_state (); + + return rs->enable_disable_tracepoints; +} + +static int +remote_supports_string_tracing (void) +{ + struct remote_state *rs = get_remote_state (); + + return rs->string_tracing; +} + static void remote_trace_init (void) { @@ -9717,9 +9890,9 @@ remote_download_command_source (int num, ULONGEST addr, } static void -remote_download_tracepoint (struct breakpoint *t) +remote_download_tracepoint (struct bp_location *loc) { - struct bp_location *loc; + CORE_ADDR tpaddr; char addrbuf[40]; char buf[2048]; @@ -9730,170 +9903,194 @@ remote_download_tracepoint (struct breakpoint *t) struct agent_expr *aexpr; struct cleanup *aexpr_chain = NULL; char *pkt; - - /* Iterate over all the tracepoint locations. It's up to the target to - notice multiple tracepoint packets with the same number but different - addresses, and treat them as multiple locations. */ - for (loc = t->loc; loc; loc = loc->next) - { - encode_actions (t, loc, &tdp_actions, &stepping_actions); - old_chain = make_cleanup (free_actions_list_cleanup_wrapper, - tdp_actions); - (void) make_cleanup (free_actions_list_cleanup_wrapper, - stepping_actions); - - tpaddr = loc->address; - sprintf_vma (addrbuf, tpaddr); - sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number, - addrbuf, /* address */ - (t->enable_state == bp_enabled ? 'E' : 'D'), - t->step_count, t->pass_count); - /* Fast tracepoints are mostly handled by the target, but we can - tell the target how big of an instruction block should be moved - around. */ - if (t->type == bp_fast_tracepoint) + struct breakpoint *b = loc->owner; + struct tracepoint *t = (struct tracepoint *) b; + + encode_actions (loc->owner, loc, &tdp_actions, &stepping_actions); + old_chain = make_cleanup (free_actions_list_cleanup_wrapper, + tdp_actions); + (void) make_cleanup (free_actions_list_cleanup_wrapper, + stepping_actions); + + tpaddr = loc->address; + sprintf_vma (addrbuf, tpaddr); + sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", b->number, + addrbuf, /* address */ + (b->enable_state == bp_enabled ? 'E' : 'D'), + t->step_count, t->pass_count); + /* Fast tracepoints are mostly handled by the target, but we can + tell the target how big of an instruction block should be moved + around. */ + if (b->type == bp_fast_tracepoint) + { + /* Only test for support at download time; we may not know + target capabilities at definition time. */ + if (remote_supports_fast_tracepoints ()) { - /* Only test for support at download time; we may not know - target capabilities at definition time. */ - if (remote_supports_fast_tracepoints ()) - { - int isize; + int isize; - if (gdbarch_fast_tracepoint_valid_at (target_gdbarch, - tpaddr, &isize, NULL)) - sprintf (buf + strlen (buf), ":F%x", isize); - else - /* If it passed validation at definition but fails now, - something is very wrong. */ - internal_error (__FILE__, __LINE__, - _("Fast tracepoint not " - "valid during download")); - } + if (gdbarch_fast_tracepoint_valid_at (target_gdbarch, + tpaddr, &isize, NULL)) + sprintf (buf + strlen (buf), ":F%x", isize); else - /* Fast tracepoints are functionally identical to regular - tracepoints, so don't take lack of support as a reason to - give up on the trace run. */ - warning (_("Target does not support fast tracepoints, " - "downloading %d as regular tracepoint"), t->number); + /* If it passed validation at definition but fails now, + something is very wrong. */ + internal_error (__FILE__, __LINE__, + _("Fast tracepoint not " + "valid during download")); } - else if (t->type == bp_static_tracepoint) + else + /* Fast tracepoints are functionally identical to regular + tracepoints, so don't take lack of support as a reason to + give up on the trace run. */ + warning (_("Target does not support fast tracepoints, " + "downloading %d as regular tracepoint"), b->number); + } + else if (b->type == bp_static_tracepoint) + { + /* Only test for support at download time; we may not know + target capabilities at definition time. */ + if (remote_supports_static_tracepoints ()) { - /* Only test for support at download time; we may not know - target capabilities at definition time. */ - if (remote_supports_static_tracepoints ()) - { - struct static_tracepoint_marker marker; + struct static_tracepoint_marker marker; - if (target_static_tracepoint_marker_at (tpaddr, &marker)) - strcat (buf, ":S"); - else - error (_("Static tracepoint not valid during download")); - } + if (target_static_tracepoint_marker_at (tpaddr, &marker)) + strcat (buf, ":S"); else - /* Fast tracepoints are functionally identical to regular - tracepoints, so don't take lack of support as a reason - to give up on the trace run. */ - error (_("Target does not support static tracepoints")); + error (_("Static tracepoint not valid during download")); } - /* If the tracepoint has a conditional, make it into an agent - expression and append to the definition. */ - if (loc->cond) + else + /* Fast tracepoints are functionally identical to regular + tracepoints, so don't take lack of support as a reason + to give up on the trace run. */ + error (_("Target does not support static tracepoints")); + } + /* If the tracepoint has a conditional, make it into an agent + expression and append to the definition. */ + if (loc->cond) + { + /* Only test support at download time, we may not know target + capabilities at definition time. */ + if (remote_supports_cond_tracepoints ()) { - /* Only test support at download time, we may not know target - capabilities at definition time. */ - if (remote_supports_cond_tracepoints ()) - { - aexpr = gen_eval_for_expr (tpaddr, loc->cond); - aexpr_chain = make_cleanup_free_agent_expr (aexpr); - sprintf (buf + strlen (buf), ":X%x,", aexpr->len); - pkt = buf + strlen (buf); - for (ndx = 0; ndx < aexpr->len; ++ndx) - pkt = pack_hex_byte (pkt, aexpr->buf[ndx]); - *pkt = '\0'; - do_cleanups (aexpr_chain); - } - else - warning (_("Target does not support conditional tracepoints, " - "ignoring tp %d cond"), t->number); + aexpr = gen_eval_for_expr (tpaddr, loc->cond); + aexpr_chain = make_cleanup_free_agent_expr (aexpr); + sprintf (buf + strlen (buf), ":X%x,", aexpr->len); + pkt = buf + strlen (buf); + for (ndx = 0; ndx < aexpr->len; ++ndx) + pkt = pack_hex_byte (pkt, aexpr->buf[ndx]); + *pkt = '\0'; + do_cleanups (aexpr_chain); } + else + warning (_("Target does not support conditional tracepoints, " + "ignoring tp %d cond"), b->number); + } - if (t->commands || *default_collect) - strcat (buf, "-"); - putpkt (buf); - remote_get_noisy_reply (&target_buf, &target_buf_size); - if (strcmp (target_buf, "OK")) - error (_("Target does not support tracepoints.")); + if (b->commands || *default_collect) + strcat (buf, "-"); + putpkt (buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Target does not support tracepoints.")); - /* do_single_steps (t); */ - if (tdp_actions) + /* do_single_steps (t); */ + if (tdp_actions) + { + for (ndx = 0; tdp_actions[ndx]; ndx++) { - for (ndx = 0; tdp_actions[ndx]; ndx++) - { - QUIT; /* Allow user to bail out with ^C. */ - sprintf (buf, "QTDP:-%x:%s:%s%c", - t->number, addrbuf, /* address */ - tdp_actions[ndx], - ((tdp_actions[ndx + 1] || stepping_actions) - ? '-' : 0)); - putpkt (buf); - remote_get_noisy_reply (&target_buf, - &target_buf_size); - if (strcmp (target_buf, "OK")) - error (_("Error on target while setting tracepoints.")); - } + QUIT; /* Allow user to bail out with ^C. */ + sprintf (buf, "QTDP:-%x:%s:%s%c", + b->number, addrbuf, /* address */ + tdp_actions[ndx], + ((tdp_actions[ndx + 1] || stepping_actions) + ? '-' : 0)); + putpkt (buf); + remote_get_noisy_reply (&target_buf, + &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Error on target while setting tracepoints.")); } - if (stepping_actions) + } + if (stepping_actions) + { + for (ndx = 0; stepping_actions[ndx]; ndx++) { - for (ndx = 0; stepping_actions[ndx]; ndx++) - { - QUIT; /* Allow user to bail out with ^C. */ - sprintf (buf, "QTDP:-%x:%s:%s%s%s", - t->number, addrbuf, /* address */ - ((ndx == 0) ? "S" : ""), - stepping_actions[ndx], - (stepping_actions[ndx + 1] ? "-" : "")); - putpkt (buf); - remote_get_noisy_reply (&target_buf, - &target_buf_size); - if (strcmp (target_buf, "OK")) - error (_("Error on target while setting tracepoints.")); - } + QUIT; /* Allow user to bail out with ^C. */ + sprintf (buf, "QTDP:-%x:%s:%s%s%s", + b->number, addrbuf, /* address */ + ((ndx == 0) ? "S" : ""), + stepping_actions[ndx], + (stepping_actions[ndx + 1] ? "-" : "")); + putpkt (buf); + remote_get_noisy_reply (&target_buf, + &target_buf_size); + if (strcmp (target_buf, "OK")) + error (_("Error on target while setting tracepoints.")); } + } - if (remote_protocol_packets[PACKET_TracepointSource].support - == PACKET_ENABLE) + if (remote_protocol_packets[PACKET_TracepointSource].support + == PACKET_ENABLE) + { + if (b->addr_string) { - if (t->addr_string) - { - strcpy (buf, "QTDPsrc:"); - encode_source_string (t->number, loc->address, - "at", t->addr_string, buf + strlen (buf), - 2048 - strlen (buf)); + strcpy (buf, "QTDPsrc:"); + encode_source_string (b->number, loc->address, + "at", b->addr_string, buf + strlen (buf), + 2048 - strlen (buf)); - putpkt (buf); - remote_get_noisy_reply (&target_buf, &target_buf_size); - if (strcmp (target_buf, "OK")) - warning (_("Target does not support source download.")); - } - if (t->cond_string) - { - strcpy (buf, "QTDPsrc:"); - encode_source_string (t->number, loc->address, - "cond", t->cond_string, buf + strlen (buf), - 2048 - strlen (buf)); - putpkt (buf); - remote_get_noisy_reply (&target_buf, &target_buf_size); - if (strcmp (target_buf, "OK")) - warning (_("Target does not support source download.")); - } - remote_download_command_source (t->number, loc->address, - breakpoint_commands (t)); + putpkt (buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + warning (_("Target does not support source download.")); } - - do_cleanups (old_chain); + if (b->cond_string) + { + strcpy (buf, "QTDPsrc:"); + encode_source_string (b->number, loc->address, + "cond", b->cond_string, buf + strlen (buf), + 2048 - strlen (buf)); + putpkt (buf); + remote_get_noisy_reply (&target_buf, &target_buf_size); + if (strcmp (target_buf, "OK")) + warning (_("Target does not support source download.")); + } + remote_download_command_source (b->number, loc->address, + breakpoint_commands (b)); } + + do_cleanups (old_chain); +} + +static int +remote_can_download_tracepoint (void) +{ + struct remote_state *rs = get_remote_state (); + struct trace_status *ts; + int status; + + /* Don't try to install tracepoints until we've relocated our + symbols, and fetched and merged the target's tracepoint list with + ours. */ + if (rs->starting_up) + return 0; + + ts = current_trace_status (); + status = remote_get_trace_status (ts); + + if (status == -1 || !ts->running_known || !ts->running) + return 0; + + /* If we are in a tracing experiment, but remote stub doesn't support + installing tracepoint in trace, we have to return. */ + if (!remote_supports_install_in_trace ()) + return 0; + + return 1; } + static void remote_download_trace_state_variable (struct trace_state_variable *tsv) { @@ -9915,6 +10112,38 @@ remote_download_trace_state_variable (struct trace_state_variable *tsv) error (_("Error on target while downloading trace state variable.")); } +static void +remote_enable_tracepoint (struct bp_location *location) +{ + struct remote_state *rs = get_remote_state (); + char addr_buf[40]; + + sprintf_vma (addr_buf, location->address); + sprintf (rs->buf, "QTEnable:%x:%s", location->owner->number, addr_buf); + putpkt (rs->buf); + remote_get_noisy_reply (&rs->buf, &rs->buf_size); + if (*rs->buf == '\0') + error (_("Target does not support enabling tracepoints while a trace run is ongoing.")); + if (strcmp (rs->buf, "OK") != 0) + error (_("Error on target while enabling tracepoint.")); +} + +static void +remote_disable_tracepoint (struct bp_location *location) +{ + struct remote_state *rs = get_remote_state (); + char addr_buf[40]; + + sprintf_vma (addr_buf, location->address); + sprintf (rs->buf, "QTDisable:%x:%s", location->owner->number, addr_buf); + putpkt (rs->buf); + remote_get_noisy_reply (&rs->buf, &rs->buf_size); + if (*rs->buf == '\0') + error (_("Target does not support disabling tracepoints while a trace run is ongoing.")); + if (strcmp (rs->buf, "OK") != 0) + error (_("Error on target while disabling tracepoint.")); +} + static void remote_trace_set_readonly_regions (void) { @@ -10017,6 +10246,51 @@ remote_get_trace_status (struct trace_status *ts) return ts->running; } +void +remote_get_tracepoint_status (struct breakpoint *bp, + struct uploaded_tp *utp) +{ + struct remote_state *rs = get_remote_state (); + char *reply; + struct bp_location *loc; + struct tracepoint *tp = (struct tracepoint *) bp; + + if (tp) + { + tp->base.hit_count = 0; + tp->traceframe_usage = 0; + for (loc = tp->base.loc; loc; loc = loc->next) + { + /* If the tracepoint was never downloaded, don't go asking for + any status. */ + if (tp->number_on_target == 0) + continue; + sprintf (rs->buf, "qTP:%x:%s", tp->number_on_target, + phex_nz (loc->address, 0)); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (reply && *reply) + { + if (*reply == 'V') + parse_tracepoint_status (reply + 1, bp, utp); + } + } + } + else if (utp) + { + utp->hit_count = 0; + utp->traceframe_usage = 0; + sprintf (rs->buf, "qTP:%x:%s", utp->number, phex_nz (utp->addr, 0)); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (reply && *reply) + { + if (*reply == 'V') + parse_tracepoint_status (reply + 1, bp, utp); + } + } +} + static void remote_trace_stop (void) { @@ -10146,7 +10420,7 @@ remote_save_trace_data (const char *filename) *p++ = '\0'; putpkt (rs->buf); reply = remote_get_noisy_reply (&target_buf, &target_buf_size); - if (*reply != '\0') + if (*reply == '\0') error (_("Target does not support this command.")); if (strcmp (reply, "OK") != 0) error (_("Bogus reply from target: %s"), reply); @@ -10262,6 +10536,77 @@ remote_traceframe_info (void) return NULL; } +/* Handle the qTMinFTPILen packet. Returns the minimum length of + instruction on which a fast tracepoint may be placed. Returns -1 + if the packet is not supported, and 0 if the minimum instruction + length is unknown. */ + +static int +remote_get_min_fast_tracepoint_insn_len (void) +{ + struct remote_state *rs = get_remote_state (); + char *reply; + + sprintf (rs->buf, "qTMinFTPILen"); + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (*reply == '\0') + return -1; + else + { + ULONGEST min_insn_len; + + unpack_varlen_hex (reply, &min_insn_len); + + return (int) min_insn_len; + } +} + +static int +remote_set_trace_notes (char *user, char *notes, char *stop_notes) +{ + struct remote_state *rs = get_remote_state (); + char *reply; + char *buf = rs->buf; + char *endbuf = rs->buf + get_remote_packet_size (); + int nbytes; + + buf += xsnprintf (buf, endbuf - buf, "QTNotes:"); + if (user) + { + buf += xsnprintf (buf, endbuf - buf, "user:"); + nbytes = bin2hex (user, buf, 0); + buf += 2 * nbytes; + *buf++ = ';'; + } + if (notes) + { + buf += xsnprintf (buf, endbuf - buf, "notes:"); + nbytes = bin2hex (notes, buf, 0); + buf += 2 * nbytes; + *buf++ = ';'; + } + if (stop_notes) + { + buf += xsnprintf (buf, endbuf - buf, "tstop:"); + nbytes = bin2hex (stop_notes, buf, 0); + buf += 2 * nbytes; + *buf++ = ';'; + } + /* Ensure the buffer is terminated. */ + *buf = '\0'; + + putpkt (rs->buf); + reply = remote_get_noisy_reply (&target_buf, &target_buf_size); + if (*reply == '\0') + return 0; + + if (strcmp (reply, "OK") != 0) + error (_("Bogus reply from target: %s"), reply); + + return 1; +} + static void init_remote_ops (void) { @@ -10289,12 +10634,14 @@ Specify the serial device it is connected to\n\ remote_ops.to_can_use_hw_breakpoint = remote_check_watch_resources; remote_ops.to_insert_hw_breakpoint = remote_insert_hw_breakpoint; remote_ops.to_remove_hw_breakpoint = remote_remove_hw_breakpoint; + remote_ops.to_region_ok_for_hw_watchpoint + = remote_region_ok_for_hw_watchpoint; remote_ops.to_insert_watchpoint = remote_insert_watchpoint; remote_ops.to_remove_watchpoint = remote_remove_watchpoint; remote_ops.to_kill = remote_kill; remote_ops.to_load = generic_load; remote_ops.to_mourn_inferior = remote_mourn; - remote_ops.to_notice_signals = remote_notice_signals; + remote_ops.to_pass_signals = remote_pass_signals; remote_ops.to_thread_alive = remote_thread_alive; remote_ops.to_find_new_threads = remote_threads_info; remote_ops.to_pid_to_str = remote_pid_to_str; @@ -10322,18 +10669,25 @@ Specify the serial device it is connected to\n\ remote_ops.to_can_async_p = remote_can_async_p; remote_ops.to_is_async_p = remote_is_async_p; remote_ops.to_async = remote_async; - remote_ops.to_async_mask = remote_async_mask; remote_ops.to_terminal_inferior = remote_terminal_inferior; remote_ops.to_terminal_ours = remote_terminal_ours; remote_ops.to_supports_non_stop = remote_supports_non_stop; remote_ops.to_supports_multi_process = remote_supports_multi_process; + remote_ops.to_supports_disable_randomization + = remote_supports_disable_randomization; + remote_ops.to_supports_enable_disable_tracepoint = remote_supports_enable_disable_tracepoint; + remote_ops.to_supports_string_tracing = remote_supports_string_tracing; remote_ops.to_trace_init = remote_trace_init; remote_ops.to_download_tracepoint = remote_download_tracepoint; + remote_ops.to_can_download_tracepoint = remote_can_download_tracepoint; remote_ops.to_download_trace_state_variable = remote_download_trace_state_variable; + remote_ops.to_enable_tracepoint = remote_enable_tracepoint; + remote_ops.to_disable_tracepoint = remote_disable_tracepoint; remote_ops.to_trace_set_readonly_regions = remote_trace_set_readonly_regions; remote_ops.to_trace_start = remote_trace_start; remote_ops.to_get_trace_status = remote_get_trace_status; + remote_ops.to_get_tracepoint_status = remote_get_tracepoint_status; remote_ops.to_trace_stop = remote_trace_stop; remote_ops.to_trace_find = remote_trace_find; remote_ops.to_get_trace_state_variable_value @@ -10343,8 +10697,10 @@ Specify the serial device it is connected to\n\ remote_ops.to_upload_trace_state_variables = remote_upload_trace_state_variables; remote_ops.to_get_raw_trace_data = remote_get_raw_trace_data; + remote_ops.to_get_min_fast_tracepoint_insn_len = remote_get_min_fast_tracepoint_insn_len; remote_ops.to_set_disconnected_tracing = remote_set_disconnected_tracing; remote_ops.to_set_circular_trace_buffer = remote_set_circular_trace_buffer; + remote_ops.to_set_trace_notes = remote_set_trace_notes; remote_ops.to_core_of_thread = remote_core_of_thread; remote_ops.to_verify_memory = remote_verify_memory; remote_ops.to_get_tib_address = remote_get_tib_address; @@ -10376,6 +10732,8 @@ Specify the serial device it is connected to (e.g. /dev/ttya)."; extended_remote_ops.to_detach = extended_remote_detach; extended_remote_ops.to_attach = extended_remote_attach; extended_remote_ops.to_kill = extended_remote_kill; + extended_remote_ops.to_supports_disable_randomization + = extended_remote_supports_disable_randomization; } static int @@ -10386,7 +10744,7 @@ remote_can_async_p (void) return 0; /* We're async whenever the serial device is. */ - return remote_async_mask_value && serial_can_async_p (remote_desc); + return serial_can_async_p (remote_desc); } static int @@ -10397,7 +10755,7 @@ remote_is_async_p (void) return 0; /* We're async whenever the serial device is. */ - return remote_async_mask_value && serial_is_async_p (remote_desc); + return serial_is_async_p (remote_desc); } /* Pass the SERIAL event on and up to the client. One day this code @@ -10433,10 +10791,6 @@ static void remote_async (void (*callback) (enum inferior_event_type event_type, void *context), void *context) { - if (remote_async_mask_value == 0) - internal_error (__FILE__, __LINE__, - _("Calling remote_async when async is masked")); - if (callback != NULL) { serial_async (remote_desc, remote_async_serial_handler, NULL); @@ -10447,15 +10801,6 @@ remote_async (void (*callback) (enum inferior_event_type event_type, serial_async (remote_desc, NULL, NULL); } -static int -remote_async_mask (int new_mask) -{ - int curr_mask = remote_async_mask_value; - - remote_async_mask_value = new_mask; - return curr_mask; -} - static void set_remote_cmd (char *args, int from_tty) { @@ -10469,6 +10814,7 @@ show_remote_cmd (char *args, int from_tty) the redundant "show remote Z-packet" and the legacy aliases. */ struct cleanup *showlist_chain; struct cmd_list_element *list = remote_show_cmdlist; + struct ui_out *uiout = current_uiout; showlist_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "showlist"); for (; list != NULL; list = list->next) @@ -10587,7 +10933,7 @@ _initialize_remote (void) sigint_remote_token = create_async_signal_handler (async_remote_interrupt, NULL); sigint_remote_twice_token = - create_async_signal_handler (inferior_event_handler_wrapper, NULL); + create_async_signal_handler (async_remote_interrupt_twice, NULL); #if 0 init_remote_threadtests (); @@ -10695,6 +11041,15 @@ Specify a negative limit for unlimited."), number of target hardware watchpoints is %s. */ &remote_set_cmdlist, &remote_show_cmdlist); + add_setshow_zinteger_cmd ("hardware-watchpoint-length-limit", no_class, + &remote_hw_watchpoint_length_limit, _("\ +Set the maximum length (in bytes) of a target hardware watchpoint."), _("\ +Show the maximum length (in bytes) of a target hardware watchpoint."), _("\ +Specify a negative limit for unlimited."), + NULL, NULL, /* FIXME: i18n: The maximum + length (in bytes) of a target + hardware watchpoint is %s. */ + &remote_set_cmdlist, &remote_show_cmdlist); add_setshow_zinteger_cmd ("hardware-breakpoint-limit", no_class, &remote_hw_breakpoint_limit, _("\ Set the maximum number of target hardware breakpoints."), _("\ @@ -10755,6 +11110,9 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_libraries], "qXfer:libraries:read", "library-info", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_libraries_svr4], + "qXfer:libraries-svr4:read", "library-info-svr4", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map], "qXfer:memory-map:read", "memory-map", 0); @@ -10845,9 +11203,18 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL, add_packet_config_cmd (&remote_protocol_packets[PACKET_StaticTracepoints], "StaticTracepoints", "static-tracepoints", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_InstallInTrace], + "InstallInTrace", "install-in-trace", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_statictrace_read], "qXfer:statictrace:read", "read-sdata-object", 0); + add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_fdpic], + "qXfer:fdpic:read", "read-fdpic-loadmap", 0); + + add_packet_config_cmd (&remote_protocol_packets[PACKET_QDisableRandomization], + "QDisableRandomization", "disable-randomization", 0); + /* Keep the old ``set remote Z-packet ...'' working. Each individual Z sub-packet has its own set and show commands, but users may have sets to this variable in their .gdbinit files (or in their diff --git a/contrib/gdb-7/gdb/remote.h b/contrib/gdb-7/gdb/remote.h index 25f5ccc26c..3adc54ee6c 100644 --- a/contrib/gdb-7/gdb/remote.h +++ b/contrib/gdb-7/gdb/remote.h @@ -1,6 +1,5 @@ /* Remote target communications for serial-line targets in custom GDB protocol - Copyright (C) 1999, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999, 2003-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -56,4 +55,8 @@ bfd *remote_bfd_open (const char *remote_file, const char *target); int remote_filename_p (const char *filename); +extern int remote_register_number_and_offset (struct gdbarch *gdbarch, + int regnum, int *pnum, + int *poffset); + #endif diff --git a/contrib/gdb-7/gdb/reverse.c b/contrib/gdb-7/gdb/reverse.c index 61f2e7c50b..042296ee25 100644 --- a/contrib/gdb-7/gdb/reverse.c +++ b/contrib/gdb-7/gdb/reverse.c @@ -1,7 +1,6 @@ /* Reverse execution and reverse debugging. - Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -50,9 +49,6 @@ exec_reverse_once (char *cmd, char *args, int from_tty) enum exec_direction_kind dir = execution_direction; struct cleanup *old_chain; - if (dir == EXEC_ERROR) - error (_("Target %s does not support this command."), target_shortname); - if (dir == EXEC_REVERSE) error (_("Already in reverse mode. Use '%s' or 'set exec-dir forward'."), cmd); @@ -187,7 +183,7 @@ delete_one_bookmark (int num) if (b == bookmark_chain) bookmark_chain = b->next; - /* Find bookmark preceeding "marked" one, so we can unlink. */ + /* Find bookmark preceding "marked" one, so we can unlink. */ if (b) { ALL_BOOKMARKS (b1) diff --git a/contrib/gdb-7/gdb/scm-exp.c b/contrib/gdb-7/gdb/scm-exp.c deleted file mode 100644 index 69eb249fc8..0000000000 --- a/contrib/gdb-7/gdb/scm-exp.c +++ /dev/null @@ -1,502 +0,0 @@ -/* Scheme/Guile language support routines for GDB, the GNU debugger. - - Copyright (C) 1995, 1996, 2000, 2003, 2005, 2008, 2009, 2010 - 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 . */ - -#include "defs.h" -#include "symtab.h" -#include "gdbtypes.h" -#include "expression.h" -#include "parser-defs.h" -#include "language.h" -#include "value.h" -#include "c-lang.h" -#include "scm-lang.h" -#include "scm-tags.h" - -#define USE_EXPRSTRING 0 - -static void scm_lreadparen (int); -static int scm_skip_ws (void); -static void scm_read_token (int, int); -static LONGEST scm_istring2number (char *, int, int); -static LONGEST scm_istr2int (char *, int, int); -static void scm_lreadr (int); - -static LONGEST -scm_istr2int (char *str, int len, int radix) -{ - int i = 0; - LONGEST inum = 0; - int c; - int sign = 0; - - if (0 >= len) - return SCM_BOOL_F; /* zero scm_length */ - switch (str[0]) - { /* leading sign */ - case '-': - case '+': - sign = str[0]; - if (++i == len) - return SCM_BOOL_F; /* bad if lone `+' or `-' */ - } - do - { - switch (c = str[i++]) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - c = c - '0'; - goto accumulate; - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - c = c - 'A' + 10; - goto accumulate; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - c = c - 'a' + 10; - accumulate: - if (c >= radix) - return SCM_BOOL_F; /* bad digit for radix */ - inum *= radix; - inum += c; - break; - default: - return SCM_BOOL_F; /* not a digit */ - } - } - while (i < len); - if (sign == '-') - inum = -inum; - return SCM_MAKINUM (inum); -} - -static LONGEST -scm_istring2number (char *str, int len, int radix) -{ - int i = 0; - char ex = 0; - char ex_p = 0, rx_p = 0; /* Only allow 1 exactness and 1 radix prefix */ -#if 0 - SCM res; -#endif - - if (len == 1) - if (*str == '+' || *str == '-') /* Catches lone `+' and `-' for speed */ - return SCM_BOOL_F; - - while ((len - i) >= 2 && str[i] == '#' && ++i) - switch (str[i++]) - { - case 'b': - case 'B': - if (rx_p++) - return SCM_BOOL_F; - radix = 2; - break; - case 'o': - case 'O': - if (rx_p++) - return SCM_BOOL_F; - radix = 8; - break; - case 'd': - case 'D': - if (rx_p++) - return SCM_BOOL_F; - radix = 10; - break; - case 'x': - case 'X': - if (rx_p++) - return SCM_BOOL_F; - radix = 16; - break; - case 'i': - case 'I': - if (ex_p++) - return SCM_BOOL_F; - ex = 2; - break; - case 'e': - case 'E': - if (ex_p++) - return SCM_BOOL_F; - ex = 1; - break; - default: - return SCM_BOOL_F; - } - - switch (ex) - { - case 1: - return scm_istr2int (&str[i], len - i, radix); - case 0: - return scm_istr2int (&str[i], len - i, radix); -#if 0 - if NFALSEP - (res) return res; -#ifdef FLOATS - case 2: - return scm_istr2flo (&str[i], len - i, radix); -#endif -#endif - } - return SCM_BOOL_F; -} - -static void -scm_read_token (int c, int weird) -{ - while (1) - { - c = *lexptr++; - switch (c) - { - case '[': - case ']': - case '(': - case ')': - case '\"': - case ';': - case ' ': - case '\t': - case '\r': - case '\f': - case '\n': - if (weird) - goto default_case; - case '\0': /* End of line */ - eof_case: - --lexptr; - return; - case '\\': - if (!weird) - goto default_case; - else - { - c = *lexptr++; - if (c == '\0') - goto eof_case; - else - goto default_case; - } - case '}': - if (!weird) - goto default_case; - - c = *lexptr++; - if (c == '#') - return; - else - { - --lexptr; - c = '}'; - goto default_case; - } - - default: - default_case: - ; - } - } -} - -static int -scm_skip_ws (void) -{ - int c; - - while (1) - switch ((c = *lexptr++)) - { - case '\0': - goteof: - return c; - case ';': - lp: - switch ((c = *lexptr++)) - { - case '\0': - goto goteof; - default: - goto lp; - case '\n': - break; - } - case ' ': - case '\t': - case '\r': - case '\f': - case '\n': - break; - default: - return c; - } -} - -static void -scm_lreadparen (int skipping) -{ - for (;;) - { - int c = scm_skip_ws (); - - if (')' == c || ']' == c) - return; - --lexptr; - if (c == '\0') - error ("missing close paren"); - scm_lreadr (skipping); - } -} - -static void -scm_lreadr (int skipping) -{ - int c, j; - struct stoken str; - LONGEST svalue = 0; - -tryagain: - c = *lexptr++; - switch (c) - { - case '\0': - lexptr--; - return; - case '[': - case '(': - scm_lreadparen (skipping); - return; - case ']': - case ')': - error ("unexpected #\\%c", c); - goto tryagain; - case '\'': - case '`': - str.ptr = lexptr - 1; - scm_lreadr (skipping); - if (!skipping) - { - struct value *val = scm_evaluate_string (str.ptr, lexptr - str.ptr); - - if (!is_scmvalue_type (value_type (val))) - error ("quoted scm form yields non-SCM value"); - svalue = extract_signed_integer (value_contents (val), - TYPE_LENGTH (value_type (val)), - gdbarch_byte_order (parse_gdbarch)); - goto handle_immediate; - } - return; - case ',': - c = *lexptr++; - if ('@' != c) - lexptr--; - scm_lreadr (skipping); - return; - case '#': - c = *lexptr++; - switch (c) - { - case '[': - case '(': - scm_lreadparen (skipping); - return; - case 't': - case 'T': - svalue = SCM_BOOL_T; - goto handle_immediate; - case 'f': - case 'F': - svalue = SCM_BOOL_F; - goto handle_immediate; - case 'b': - case 'B': - case 'o': - case 'O': - case 'd': - case 'D': - case 'x': - case 'X': - case 'i': - case 'I': - case 'e': - case 'E': - lexptr--; - c = '#'; - goto num; - case '*': /* bitvector */ - scm_read_token (c, 0); - return; - case '{': - scm_read_token (c, 1); - return; - case '\\': /* character */ - c = *lexptr++; - scm_read_token (c, 0); - return; - case '|': - j = 1; /* here j is the comment nesting depth */ - lp: - c = *lexptr++; - lpc: - switch (c) - { - case '\0': - error ("unbalanced comment"); - default: - goto lp; - case '|': - if ('#' != (c = *lexptr++)) - goto lpc; - if (--j) - goto lp; - break; - case '#': - if ('|' != (c = *lexptr++)) - goto lpc; - ++j; - goto lp; - } - goto tryagain; - case '.': - default: -#if 0 - callshrp: -#endif - scm_lreadr (skipping); - return; - } - case '\"': - while ('\"' != (c = *lexptr++)) - { - if (c == '\\') - switch (c = *lexptr++) - { - case '\0': - error ("non-terminated string literal"); - case '\n': - continue; - case '0': - case 'f': - case 'n': - case 'r': - case 't': - case 'a': - case 'v': - break; - } - } - return; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - case '.': - case '-': - case '+': - num: - { - str.ptr = lexptr - 1; - scm_read_token (c, 0); - if (!skipping) - { - svalue = scm_istring2number (str.ptr, lexptr - str.ptr, 10); - if (svalue != SCM_BOOL_F) - goto handle_immediate; - goto tok; - } - } - return; - case ':': - scm_read_token ('-', 0); - return; -#if 0 - do_symbol: -#endif - default: - str.ptr = lexptr - 1; - scm_read_token (c, 0); - tok: - if (!skipping) - { - str.length = lexptr - str.ptr; - if (str.ptr[0] == '$') - { - write_dollar_variable (str); - return; - } - write_exp_elt_opcode (OP_NAME); - write_exp_string (str); - write_exp_elt_opcode (OP_NAME); - } - return; - } -handle_immediate: - if (!skipping) - { - write_exp_elt_opcode (OP_LONG); - write_exp_elt_type (builtin_scm_type (parse_gdbarch)->builtin_scm); - write_exp_elt_longcst (svalue); - write_exp_elt_opcode (OP_LONG); - } -} - -int -scm_parse (void) -{ - char *start; - - while (*lexptr == ' ') - lexptr++; - start = lexptr; - scm_lreadr (USE_EXPRSTRING); -#if USE_EXPRSTRING - str.length = lexptr - start; - str.ptr = start; - write_exp_elt_opcode (OP_EXPRSTRING); - write_exp_string (str); - write_exp_elt_opcode (OP_EXPRSTRING); -#endif - return 0; -} diff --git a/contrib/gdb-7/gdb/scm-lang.c b/contrib/gdb-7/gdb/scm-lang.c deleted file mode 100644 index 870b1e447b..0000000000 --- a/contrib/gdb-7/gdb/scm-lang.c +++ /dev/null @@ -1,308 +0,0 @@ -/* Scheme/Guile language support routines for GDB, the GNU debugger. - - Copyright (C) 1995, 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, - 2008, 2009, 2010 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 . */ - -#include "defs.h" -#include "symtab.h" -#include "gdbtypes.h" -#include "expression.h" -#include "parser-defs.h" -#include "language.h" -#include "value.h" -#include "c-lang.h" -#include "scm-lang.h" -#include "scm-tags.h" -#include "source.h" -#include "gdb_string.h" -#include "gdbcore.h" -#include "infcall.h" -#include "objfiles.h" - -extern void _initialize_scheme_language (void); -static struct value *scm_lookup_name (struct gdbarch *, char *); -static int in_eval_c (void); - -void -scm_printchar (int c, struct type *type, struct ui_file *stream) -{ - fprintf_filtered (stream, "#\\%c", c); -} - -static void -scm_printstr (struct ui_file *stream, struct type *type, const gdb_byte *string, - unsigned int length, const char *encoding, int force_ellipses, - const struct value_print_options *options) -{ - fprintf_filtered (stream, "\"%s\"", string); -} - -int -is_scmvalue_type (struct type *type) -{ - if (TYPE_NAME (type) && strcmp (TYPE_NAME (type), "SCM") == 0) - { - return 1; - } - return 0; -} - -/* Get the INDEX'th SCM value, assuming SVALUE is the address - of the 0'th one. */ - -LONGEST -scm_get_field (LONGEST svalue, int index, int size, - enum bfd_endian byte_order) -{ - gdb_byte buffer[20]; - - read_memory (SCM2PTR (svalue) + index * size, buffer, size); - return extract_signed_integer (buffer, size, byte_order); -} - -/* Unpack a value of type TYPE in buffer VALADDR as an integer - (if CONTEXT == TYPE_CODE_IN), a pointer (CONTEXT == TYPE_CODE_PTR), - or Boolean (CONTEXT == TYPE_CODE_BOOL). */ - -LONGEST -scm_unpack (struct type *type, const gdb_byte *valaddr, enum type_code context) -{ - if (is_scmvalue_type (type)) - { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - LONGEST svalue - = extract_signed_integer (valaddr, TYPE_LENGTH (type), byte_order); - - if (context == TYPE_CODE_BOOL) - { - if (svalue == SCM_BOOL_F) - return 0; - else - return 1; - } - switch (7 & (int) svalue) - { - case 2: - case 6: /* fixnum */ - return svalue >> 2; - case 4: /* other immediate value */ - if (SCM_ICHRP (svalue)) /* character */ - return SCM_ICHR (svalue); - else if (SCM_IFLAGP (svalue)) - { - switch ((int) svalue) - { -#ifndef SICP - case SCM_EOL: -#endif - case SCM_BOOL_F: - return 0; - case SCM_BOOL_T: - return 1; - } - } - error (_("Value can't be converted to integer.")); - default: - return svalue; - } - } - else - return unpack_long (type, valaddr); -} - -/* True if we're correctly in Guile's eval.c (the evaluator and apply). */ - -static int -in_eval_c (void) -{ - struct symtab_and_line cursal = get_current_source_symtab_and_line (); - - if (cursal.symtab && cursal.symtab->filename) - { - char *filename = cursal.symtab->filename; - int len = strlen (filename); - - if (len >= 6 && strcmp (filename + len - 6, "eval.c") == 0) - return 1; - } - return 0; -} - -/* Lookup a value for the variable named STR. - First lookup in Scheme context (using the scm_lookup_cstr inferior - function), then try lookup_symbol for compiled variables. */ - -static struct value * -scm_lookup_name (struct gdbarch *gdbarch, char *str) -{ - struct value *args[3]; - int len = strlen (str); - struct value *func; - struct value *val; - struct symbol *sym; - - func = find_function_in_inferior ("scm_lookup_cstr", NULL); - - args[0] = value_allocate_space_in_inferior (len); - args[1] = value_from_longest (builtin_type (gdbarch)->builtin_int, len); - write_memory (value_as_long (args[0]), (gdb_byte *) str, len); - - if (in_eval_c () - && (sym = lookup_symbol ("env", - expression_context_block, - VAR_DOMAIN, (int *) NULL)) != NULL) - args[2] = value_of_variable (sym, expression_context_block); - else - /* FIXME in this case, we should try lookup_symbol first */ - args[2] = value_from_longest (builtin_scm_type (gdbarch)->builtin_scm, - SCM_EOL); - - val = call_function_by_hand (func, 3, args); - if (!value_logical_not (val)) - return value_ind (val); - - sym = lookup_symbol (str, - expression_context_block, - VAR_DOMAIN, (int *) NULL); - if (sym) - return value_of_variable (sym, NULL); - error (_("No symbol \"%s\" in current context."), str); -} - -struct value * -scm_evaluate_string (char *str, int len) -{ - struct value *func; - struct value *addr = value_allocate_space_in_inferior (len + 1); - LONGEST iaddr = value_as_long (addr); - - write_memory (iaddr, (gdb_byte *) str, len); - /* FIXME - should find and pass env */ - write_memory (iaddr + len, (gdb_byte *) "", 1); - func = find_function_in_inferior ("scm_evstr", NULL); - return call_function_by_hand (func, 1, &addr); -} - -static struct value * -evaluate_exp (struct type *expect_type, struct expression *exp, - int *pos, enum noside noside) -{ - enum exp_opcode op = exp->elts[*pos].opcode; - int len, pc; - char *str; - - switch (op) - { - case OP_NAME: - pc = (*pos)++; - len = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1); - if (noside == EVAL_SKIP) - goto nosideret; - str = &exp->elts[pc + 2].string; - return scm_lookup_name (exp->gdbarch, str); - case OP_STRING: - pc = (*pos)++; - len = longest_to_int (exp->elts[pc + 1].longconst); - (*pos) += 3 + BYTES_TO_EXP_ELEM (len + 1); - if (noside == EVAL_SKIP) - goto nosideret; - str = &exp->elts[pc + 2].string; - return scm_evaluate_string (str, len); - default:; - } - return evaluate_subexp_standard (expect_type, exp, pos, noside); -nosideret: - return value_from_longest (builtin_type (exp->gdbarch)->builtin_int, 1); -} - -const struct exp_descriptor exp_descriptor_scm = -{ - print_subexp_standard, - operator_length_standard, - operator_check_standard, - op_name_standard, - dump_subexp_body_standard, - evaluate_exp -}; - -const struct language_defn scm_language_defn = -{ - "scheme", /* Language name */ - language_scm, - range_check_off, - type_check_off, - case_sensitive_off, - array_row_major, - macro_expansion_no, - &exp_descriptor_scm, - scm_parse, - c_error, - null_post_parser, - scm_printchar, /* Print a character constant */ - scm_printstr, /* Function to print string constant */ - NULL, /* Function to print a single character */ - c_print_type, /* Print a type using appropriate syntax */ - default_print_typedef, /* Print a typedef using appropriate syntax */ - scm_val_print, /* Print a value using appropriate syntax */ - scm_value_print, /* Print a top-level value */ - NULL, /* Language specific skip_trampoline */ - NULL, /* name_of_this */ - basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ - basic_lookup_transparent_type,/* lookup_transparent_type */ - NULL, /* Language specific symbol demangler */ - NULL, /* Language specific class_name_from_physname */ - NULL, /* expression operators for printing */ - 1, /* c-style arrays */ - 0, /* String lower bound */ - default_word_break_characters, - default_make_symbol_completion_list, - c_language_arch_info, - default_print_array_index, - default_pass_by_reference, - default_get_string, - LANG_MAGIC -}; - -static void * -build_scm_types (struct gdbarch *gdbarch) -{ - struct builtin_scm_type *builtin_scm_type - = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_scm_type); - - builtin_scm_type->builtin_scm - = arch_integer_type (gdbarch, gdbarch_long_bit (gdbarch), 0, "SCM"); - - return builtin_scm_type; -} - -static struct gdbarch_data *scm_type_data; - -const struct builtin_scm_type * -builtin_scm_type (struct gdbarch *gdbarch) -{ - return gdbarch_data (gdbarch, scm_type_data); -} - -void -_initialize_scheme_language (void) -{ - scm_type_data = gdbarch_data_register_post_init (build_scm_types); - - add_language (&scm_language_defn); -} diff --git a/contrib/gdb-7/gdb/scm-lang.h b/contrib/gdb-7/gdb/scm-lang.h deleted file mode 100644 index 1adeee5e63..0000000000 --- a/contrib/gdb-7/gdb/scm-lang.h +++ /dev/null @@ -1,77 +0,0 @@ -/* Scheme/Guile language support routines for GDB, the GNU debugger. - - Copyright (C) 1995, 1996, 1998, 1999, 2000, 2003, 2005, 2008, 2009, 2010 - 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 . */ - -#define SICP -#include "scm-tags.h" -#undef SCM_NCELLP -#define SCM_NCELLP(x) ((SCM_SIZE-1) & (int)(x)) -#define SCM_ITAG8_DATA(X) ((X)>>8) -#define SCM_ICHR(x) ((unsigned char)SCM_ITAG8_DATA(x)) -#define SCM_ICHRP(x) (SCM_ITAG8(x) == scm_tc8_char) -#define scm_tc8_char 0xf4 -#define SCM_IFLAGP(n) ((0x87 & (int)(n))==4) -#define SCM_ISYMNUM(n) ((int)((n)>>9)) -#define SCM_ISYMCHARS(n) (scm_isymnames[SCM_ISYMNUM(n)]) -#define SCM_ILOCP(n) ((0xff & (int)(n))==0xfc) -#define SCM_ITAG8(X) ((int)(X) & 0xff) -#define SCM_TYP7(x) (0x7f & (int)SCM_CAR(x)) -#define SCM_LENGTH(x) (((unsigned long)SCM_CAR(x))>>8) -#define SCM_NCONSP(x) (1 & (int)SCM_CAR(x)) -#define SCM_NECONSP(x) (SCM_NCONSP(x) && (1 != SCM_TYP3(x))) -#define SCM_CAR(x) scm_get_field (x, 0, SCM_SIZE, SCM_BYTE_ORDER) -#define SCM_CDR(x) scm_get_field (x, 1, SCM_SIZE, SCM_BYTE_ORDER) -#define SCM_VELTS(x) ((SCM *)SCM_CDR(x)) -#define SCM_CLOSCAR(x) (SCM_CAR(x)-scm_tc3_closure) -#define SCM_CODE(x) SCM_CAR(SCM_CLOSCAR (x)) -#define SCM_MAKINUM(x) (((x)<<2)+2L) - -/* Forward decls for prototypes */ -struct value; - -extern int scm_value_print (struct value *, struct ui_file *, - const struct value_print_options *); - -extern int scm_val_print (struct type *, const gdb_byte *, int, CORE_ADDR, - struct ui_file *, int, - const struct value *, - const struct value_print_options *); - -extern LONGEST scm_get_field (LONGEST, int, int, enum bfd_endian); - -extern int is_scmvalue_type (struct type *); - -extern void scm_printchar (int, struct type *, struct ui_file *); - -extern struct value *scm_evaluate_string (char *, int); - -extern int scm_parse (void); - -extern LONGEST scm_unpack (struct type *, const gdb_byte *, enum type_code); - -/* Scheme types */ - -struct builtin_scm_type -{ - struct type *builtin_scm; -}; - -/* Return the Scheme type table for the specified architecture. */ -extern const struct builtin_scm_type *builtin_scm_type (struct gdbarch *gdbarch); - diff --git a/contrib/gdb-7/gdb/scm-tags.h b/contrib/gdb-7/gdb/scm-tags.h deleted file mode 100644 index 1019d6f482..0000000000 --- a/contrib/gdb-7/gdb/scm-tags.h +++ /dev/null @@ -1,378 +0,0 @@ -/* This is a minimally edited version of Guile's tags.h. */ -/* classes: h_files */ - -#ifndef TAGSH -#define TAGSH -/* Copyright (C) 1995, 1999, 2008, 2009, 2010 -Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - As a special exception, the Free Software Foundation gives permission - for additional uses of the text contained in its release of GUILE. - - The exception is that, if you link the GUILE library with other files - to produce an executable, this does not by itself cause the - resulting executable to be covered by the GNU General Public License. - Your use of that executable is in no way restricted on account of - linking the GUILE library code into it. - - This exception does not however invalidate any other reasons why - the executable file might be covered by the GNU General Public License. - - This exception applies only to the code released by the - Free Software Foundation under the name GUILE. If you copy - code from other Free Software Foundation releases into a copy of - GUILE, as the General Public License permits, the exception does - not apply to the code that you add in this way. To avoid misleading - anyone as to the status of such modified files, you must delete - this exception notice from them. - - If you write modifications of your own for GUILE, it is your choice - whether to permit this exception to apply to your modifications. - If you do not wish that, delete this exception notice. */ - - -/** This file defines the format of SCM values and cons pairs. - ** It is here that tag bits are assigned for various purposes. - **/ - - -/* Three Bit Tags - - * 000 -- a non-immediate value. Points into the pair heap. - * - * 001 -- a gloc (i.e., a resolved global variable in a CAR in a code graph) - * or the CAR of an object handle (i.e., the tagged pointer to the - * vtable part of a user-defined object). - * - * If X has this tag, the value at CDAR(X - 1) distinguishes - * glocs from object handles. The distinction only needs - * to be made in a few places. Only a few parts of the code know - * about glocs. In most cases, when a value in the CAR of a pair - * has the tag 001, it means that the pair is an object handle. - * - * 010 -- the tag for immediate, exact integers. - * - * 011 -- in the CAR of a pair, this tag indicates that the pair is a closure. - * The remaining bits of the CAR are a pointer into the pair heap - * to the code graph for the closure. - * - * 1xy -- an extension tag which means that there is a five or six bit - * tag to the left of the low three bits. See the nice diagrams - * in ../doc/code.doc if you want to know what the bits mean. - */ - - - - - -#define scm_tc3_cons 0 -#define scm_tc3_cons_gloc 1 -#define scm_tc3_closure 3 - -#define scm_tc7_ssymbol 5 -#define scm_tc7_msymbol 7 -#define scm_tc7_string 13 -#define scm_tc7_bvect 15 -#define scm_tc7_vector 21 -#define scm_tc7_lvector 23 -#define scm_tc7_ivect 29 -#define scm_tc7_uvect 31 -/* spare 37 39 */ -#define scm_tc7_fvect 45 -#define scm_tc7_dvect 47 -#define scm_tc7_cvect 53 -#define scm_tc7_port 55 -#define scm_tc7_contin 61 -#define scm_tc7_cclo 63 -/* spare 69 71 77 79 */ -#define scm_tc7_subr_0 85 -#define scm_tc7_subr_1 87 -#define scm_tc7_cxr 93 -#define scm_tc7_subr_3 95 -#define scm_tc7_subr_2 101 -#define scm_tc7_asubr 103 -#define scm_tc7_subr_1o 109 -#define scm_tc7_subr_2o 111 -#define scm_tc7_lsubr_2 117 -#define scm_tc7_lsubr 119 -#define scm_tc7_rpsubr 125 - -#define scm_tc7_smob 127 -#define scm_tc_free_cell 127 - -#define scm_tc16_flo 0x017f -#define scm_tc_flo 0x017fL - -#define SCM_REAL_PART (1L<<16) -#define SCM_IMAG_PART (2L<<16) -#define scm_tc_dblr (scm_tc16_flo|REAL_PART) -#define scm_tc_dblc (scm_tc16_flo|REAL_PART|IMAG_PART) - -#define scm_tc16_bigpos 0x027f -#define scm_tc16_bigneg 0x037f - -#define scm_tc16_fport (scm_tc7_port + 0*256L) -#define scm_tc16_pipe (scm_tc7_port + 1*256L) -#define scm_tc16_strport (scm_tc7_port + 2*256L) -#define scm_tc16_sfport (scm_tc7_port + 3*256L) - - - -/* For cons pairs with immediate values in the CAR */ -#define scm_tcs_cons_imcar 2:case 4:case 6:case 10:\ - case 12:case 14:case 18:case 20:\ - case 22:case 26:case 28:case 30:\ - case 34:case 36:case 38:case 42:\ - case 44:case 46:case 50:case 52:\ - case 54:case 58:case 60:case 62:\ - case 66:case 68:case 70:case 74:\ - case 76:case 78:case 82:case 84:\ - case 86:case 90:case 92:case 94:\ - case 98:case 100:case 102:case 106:\ - case 108:case 110:case 114:case 116:\ - case 118:case 122:case 124:case 126 - -/* For cons pairs with non-immediate values in the CAR */ -#define scm_tcs_cons_nimcar 0:case 8:case 16:case 24:\ - case 32:case 40:case 48:case 56:\ - case 64:case 72:case 80:case 88:\ - case 96:case 104:case 112:case 120 - -/* A CONS_GLOC occurs in code. It's CAR is a pointer to the - * CDR of a variable. The low order bits of the CAR are 001. - * The CDR of the gloc is the code continuation. - */ -#define scm_tcs_cons_gloc 1:case 9:case 17:case 25:\ - case 33:case 41:case 49:case 57:\ - case 65:case 73:case 81:case 89:\ - case 97:case 105:case 113:case 121 - -#define scm_tcs_closures 3:case 11:case 19:case 27:\ - case 35:case 43:case 51:case 59:\ - case 67:case 75:case 83:case 91:\ - case 99:case 107:case 115:case 123 - -#define scm_tcs_subrs scm_tc7_asubr:case scm_tc7_subr_0:case scm_tc7_subr_1:case scm_tc7_cxr:\ - case scm_tc7_subr_3:case scm_tc7_subr_2:case scm_tc7_rpsubr:case scm_tc7_subr_1o:\ - case scm_tc7_subr_2o:case scm_tc7_lsubr_2:case scm_tc7_lsubr - -#define scm_tcs_symbols scm_tc7_ssymbol:case scm_tc7_msymbol - -#define scm_tcs_bignums tc16_bigpos:case tc16_bigneg - - - -/* References to objects are of type SCM. Values may be non-immediate - * (pointers) or immediate (encoded, immutable, scalar values that fit - * in an SCM variable). - */ - -typedef long SCM; - -/* Cray machines have pointers that are incremented once for each word, - * rather than each byte, the 3 most significant bits encode the byte - * within the word. The following macros deal with this by storing the - * native Cray pointers like the ones that looks like scm expects. This - * is done for any pointers that might appear in the car of a scm_cell, pointers - * to scm_vector elts, functions, &c are not munged. - */ -#ifdef _UNICOS -#define SCM2PTR(x) ((int)(x) >> 3) -#define PTR2SCM(x) (((SCM)(x)) << 3) -#define SCM_POINTERS_MUNGED -#else -#define SCM2PTR(x) (x) -#define PTR2SCM(x) ((SCM)(x)) -#endif /* def _UNICOS */ - - - -/* Immediate? Predicates - */ -#define SCM_IMP(x) (6 & (int)(x)) -#define SCM_NIMP(x) (!SCM_IMP(x)) - - - -enum scm_tags - { - scm_tc8_char = 0xf4 - }; - -#define SCM_ITAG8(X) ((int)(X) & 0xff) -#define SCM_MAKE_ITAG8(X, TAG) (((X)<<8) + TAG) -#define SCM_ITAG8_DATA(X) ((X)>>8) - - - -/* Local Environment Structure - */ -#define SCM_ILOCP(n) ((0xff & (int)(n))==0xfc) -#define SCM_ILOC00 (0x000000fcL) -#define SCM_IDINC (0x00100000L) -#define SCM_ICDR (0x00080000L) -#define SCM_IFRINC (0x00000100L) -#define SCM_IDSTMSK (-SCM_IDINC) -#define SCM_IFRAME(n) ((int)((SCM_ICDR-SCM_IFRINC)>>8) & ((int)(n)>>8)) -#define SCM_IDIST(n) (((unsigned long)(n))>>20) -#define SCM_ICDRP(n) (SCM_ICDR & (n)) - - -/* Immediate Symbols, Special Symbols, Flags (various constants). - */ - -/* ISYMP tests for ISPCSYM and ISYM */ -#define SCM_ISYMP(n) ((0x187 & (int)(n))==4) - -/* IFLAGP tests for ISPCSYM, ISYM and IFLAG */ -#define SCM_IFLAGP(n) ((0x87 & (int)(n))==4) -#define SCM_ISYMNUM(n) ((int)((n)>>9)) -#define SCM_ISYMCHARS(n) (scm_isymnames[SCM_ISYMNUM(n)]) -#define SCM_MAKSPCSYM(n) (((n)<<9)+((n)<<3)+4L) -#define SCM_MAKISYM(n) (((n)<<9)+0x74L) -#define SCM_MAKIFLAG(n) (((n)<<9)+0x174L) - -/* This table must agree with the declarations - * in repl.c: {Names of immediate symbols}. - * - * These are used only in eval but their values - * have to be allocated here. - * - */ - -#define SCM_IM_AND SCM_MAKSPCSYM(0) -#define SCM_IM_BEGIN SCM_MAKSPCSYM(1) -#define SCM_IM_CASE SCM_MAKSPCSYM(2) -#define SCM_IM_COND SCM_MAKSPCSYM(3) -#define SCM_IM_DO SCM_MAKSPCSYM(4) -#define SCM_IM_IF SCM_MAKSPCSYM(5) -#define SCM_IM_LAMBDA SCM_MAKSPCSYM(6) -#define SCM_IM_LET SCM_MAKSPCSYM(7) -#define SCM_IM_LETSTAR SCM_MAKSPCSYM(8) -#define SCM_IM_LETREC SCM_MAKSPCSYM(9) -#define SCM_IM_OR SCM_MAKSPCSYM(10) -#define SCM_IM_QUOTE SCM_MAKSPCSYM(11) -#define SCM_IM_SET SCM_MAKSPCSYM(12) -#define SCM_IM_DEFINE SCM_MAKSPCSYM(13) -#define SCM_IM_APPLY SCM_MAKISYM(14) -#define SCM_IM_CONT SCM_MAKISYM(15) -#define SCM_NUM_ISYMS 16 - -/* Important immediates - */ - -#define SCM_BOOL_F SCM_MAKIFLAG(SCM_NUM_ISYMS+0) -#define SCM_BOOL_T SCM_MAKIFLAG(SCM_NUM_ISYMS+1) -#define SCM_UNDEFINED SCM_MAKIFLAG(SCM_NUM_ISYMS+2) -#define SCM_EOF_VAL SCM_MAKIFLAG(SCM_NUM_ISYMS+3) - -#ifdef SICP -#define SCM_EOL SCM_BOOL_F -#else -#define SCM_EOL SCM_MAKIFLAG(SCM_NUM_ISYMS+4) -#endif - -#define SCM_UNSPECIFIED SCM_MAKIFLAG(SCM_NUM_ISYMS+5) - - - -/* Heap Pairs and the Empty List Predicates - */ -#define SCM_NULLP(x) (SCM_EOL == (x)) -#define SCM_NNULLP(x) (SCM_EOL != (x)) -#define SCM_CELLP(x) (!SCM_NCELLP(x)) -#define SCM_NCELLP(x) ((sizeof(scm_cell)-1) & (int)(x)) - - - -#define SCM_UNBNDP(x) (SCM_UNDEFINED==(x)) - - - -/* Testing and Changing GC Marks in Various Standard Positions - */ -#define SCM_GCMARKP(x) (1 & (int)SCM_CDR(x)) -#define SCM_GC8MARKP(x) (0x80 & (int)SCM_CAR(x)) -#define SCM_SETGCMARK(x) (SCM_CDR(x) |= 1) -#define SCM_CLRGCMARK(x) (SCM_CDR(x) &= ~1L) -#define SCM_SETGC8MARK(x) (SCM_CAR(x) |= 0x80) -#define SCM_CLRGC8MARK(x) (SCM_CAR(x) &= ~0x80L) - - -/* Extracting Tag Bits, With or Without GC Safety and Optional Bits - */ -#define SCM_TYP3(x) (7 & (int)SCM_CAR(x)) -#define SCM_TYP7(x) (0x7f & (int)SCM_CAR(x)) -#define SCM_TYP7S(x) (0x7d & (int)SCM_CAR(x)) -#define SCM_TYP16(x) (0xffff & (int)SCM_CAR(x)) -#define SCM_TYP16S(x) (0xfeff & (int)SCM_CAR(x)) -#define SCM_GCTYP16(x) (0xff7f & (int)SCM_CAR(x)) - - -/* Two slightly extensible types: smobs and ptobs. - - */ -#define SCM_SMOBNUM(x) (0x0ff & (CAR(x)>>8)); -#define SCM_PTOBNUM(x) (0x0ff & (CAR(x)>>8)); - - - - -#define SCM_DIRP(x) (SCM_NIMP(x) && (TYP16(x)==(scm_tc16_dir))) -#define SCM_OPDIRP(x) (SCM_NIMP(x) && (CAR(x)==(scm_tc16_dir | OPN))) - - - -/* Lvectors - */ -#define SCM_LVECTORP(x) (TYP7(x)==tc7_lvector) - - -#if 0 - -/* Sockets - */ -#define tc_socket (tc7_port | OPN) -#define SCM_SOCKP(x) (((0x7f | OPN | RDNG | WRTNG) & CAR(x))==(tc_socket)) -#define SCM_SOCKTYP(x) (CAR(x)>>24) - - - -extern int scm_tc16_key_vector; -#define SCM_KEYVECP(X) (scm_tc16_key_vector == TYP16 (X)) -#define SCM_KEYVECLEN(OBJ) (((unsigned long)CAR (obj)) >> 16) - - -#define SCM_MALLOCDATA(obj) ((char *)CDR(obj)) -#define SCM_MALLOCLEN(obj) (((unsigned long)CAR (obj)) >> 16) -#define SCM_WORDDATA(obj) (CDR (obj)) - - -#define SCM_BYTECODEP(X) ((TYP7 (X) == tc7_cclo) && (CCLO_SUBR (X) == rb_proc)) -#define SCM_BYTECODE_CONSTANTS(X) (VELTS(X)[1]) -#define SCM_BYTECODE_CODE(X) (VELTS(X)[2]) -#define SCM_BYTECODE_NAME(X) (VELTS(X)[3]) -#define SCM_BYTECODE_BCODE(X) (VELTS(X)[4]) -#define SCM_BYTECODE_ELTS 5 - - -#define SCM_FREEP(x) (CAR(x)==tc_free_cell) -#define SCM_NFREEP(x) (!FREEP(x)) - -#endif /* 0 */ - - -#endif /* TAGSH */ diff --git a/contrib/gdb-7/gdb/scm-valprint.c b/contrib/gdb-7/gdb/scm-valprint.c deleted file mode 100644 index c5e1ce105c..0000000000 --- a/contrib/gdb-7/gdb/scm-valprint.c +++ /dev/null @@ -1,462 +0,0 @@ -/* Scheme/Guile language support routines for GDB, the GNU debugger. - - Copyright (C) 1995, 1996, 1998, 1999, 2000, 2001, 2005, 2007, 2008, 2009, - 2010 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 . */ - -#include "defs.h" -#include "symtab.h" -#include "gdbtypes.h" -#include "expression.h" -#include "parser-defs.h" -#include "language.h" -#include "value.h" -#include "scm-lang.h" -#include "valprint.h" -#include "gdbcore.h" -#include "c-lang.h" -#include "infcall.h" -#include "objfiles.h" - -static void scm_ipruk (char *, struct type *, LONGEST, struct ui_file *); -static void scm_scmval_print (struct type *, LONGEST, struct ui_file *, - int, const struct value_print_options *); -static void scm_scmlist_print (struct type *, LONGEST, struct ui_file *, - int, const struct value_print_options *); -static int scm_inferior_print (struct type *, LONGEST, struct ui_file *, - int, const struct value_print_options *); - -/* Prints the SCM value VALUE by invoking the inferior, if appropraite. - Returns >= 0 on success; return -1 if the inferior cannot/should not - print VALUE. */ - -static int -scm_inferior_print (struct type *type, LONGEST value, struct ui_file *stream, - int recurse, const struct value_print_options *options) -{ - struct value *func, *arg, *result; - struct symbol *gdb_output_sym, *gdb_output_len_sym; - char *output; - int ret, output_len; - - func = find_function_in_inferior ("gdb_print", NULL); - arg = value_from_longest (type, value); - - result = call_function_by_hand (func, 1, &arg); - ret = (int) value_as_long (result); - if (ret == 0) - { - /* XXX: Should we cache these symbols? */ - gdb_output_sym = - lookup_symbol_global ("gdb_output", NULL, VAR_DOMAIN); - gdb_output_len_sym = - lookup_symbol_global ("gdb_output_length", NULL, VAR_DOMAIN); - - if ((gdb_output_sym == NULL) || (gdb_output_len_sym == NULL)) - ret = -1; - else - { - struct value *remote_buffer; - - read_memory (SYMBOL_VALUE_ADDRESS (gdb_output_len_sym), - (char *) &output_len, sizeof (output_len)); - - output = (char *) alloca (output_len); - remote_buffer = value_at (type, - SYMBOL_VALUE_ADDRESS (gdb_output_sym)); - read_memory (value_as_address (remote_buffer), - output, output_len); - - ui_file_write (stream, output, output_len); - } - } - - return ret; -} - -/* {Names of immediate symbols} - * This table must agree with the declarations in scm.h: {Immediate Symbols}.*/ - -static char *scm_isymnames[] = -{ - /* This table must agree with the declarations */ - "and", - "begin", - "case", - "cond", - "do", - "if", - "lambda", - "let", - "let*", - "letrec", - "or", - "quote", - "set!", - "define", -#if 0 - "literal-variable-ref", - "literal-variable-set!", -#endif - "apply", - "call-with-current-continuation", - - /* user visible ISYMS */ - /* other keywords */ - /* Flags */ - - "#f", - "#t", - "#", - "#", - "()", - "#" -}; - -static void -scm_scmlist_print (struct type *type, LONGEST svalue, - struct ui_file *stream, int recurse, - const struct value_print_options *options) -{ -#define SCM_SIZE (TYPE_LENGTH (type)) -#define SCM_BYTE_ORDER (gdbarch_byte_order (get_type_arch (type))) - unsigned int more = options->print_max; - - if (recurse > 6) - { - fputs_filtered ("...", stream); - return; - } - scm_scmval_print (type, SCM_CAR (svalue), stream, recurse + 1, options); - svalue = SCM_CDR (svalue); - for (; SCM_NIMP (svalue); svalue = SCM_CDR (svalue)) - { - if (SCM_NECONSP (svalue)) - break; - fputs_filtered (" ", stream); - if (--more == 0) - { - fputs_filtered ("...", stream); - return; - } - scm_scmval_print (type, SCM_CAR (svalue), stream, recurse + 1, options); - } - if (SCM_NNULLP (svalue)) - { - fputs_filtered (" . ", stream); - scm_scmval_print (type, svalue, stream, recurse + 1, options); - } -#undef SCM_BYTE_ORDER -#undef SCM_SIZE -} - -static void -scm_ipruk (char *hdr, struct type *type, LONGEST ptr, - struct ui_file *stream) -{ -#define SCM_SIZE (TYPE_LENGTH (type)) -#define SCM_BYTE_ORDER (gdbarch_byte_order (get_type_arch (type))) - fprintf_filtered (stream, "#", phex_nz (ptr, SCM_SIZE)); -#undef SCM_BYTE_ORDER -#undef SCM_SIZE -} - -static void -scm_scmval_print (struct type *type, LONGEST svalue, - struct ui_file *stream, int recurse, - const struct value_print_options *options) -{ - struct gdbarch *gdbarch = get_type_arch (type); - -#define SCM_SIZE (TYPE_LENGTH (type)) -#define SCM_BYTE_ORDER (gdbarch_byte_order (gdbarch)) -taloop: - switch (7 & (int) svalue) - { - case 2: - case 6: - print_longest (stream, - options->format ? options->format : 'd', - 1, svalue >> 2); - break; - case 4: - if (SCM_ICHRP (svalue)) - { - svalue = SCM_ICHR (svalue); - scm_printchar (svalue, builtin_type (gdbarch)->builtin_char, - stream); - break; - } - else if (SCM_IFLAGP (svalue) - && (SCM_ISYMNUM (svalue) - < (sizeof scm_isymnames / sizeof (char *)))) - { - fputs_filtered (SCM_ISYMCHARS (svalue), stream); - break; - } - else if (SCM_ILOCP (svalue)) - { - fprintf_filtered (stream, "#@%ld%c%ld", - (long) SCM_IFRAME (svalue), - SCM_ICDRP (svalue) ? '-' : '+', - (long) SCM_IDIST (svalue)); - break; - } - else - goto idef; - break; - case 1: - /* gloc */ - svalue = SCM_CAR (svalue - 1); - goto taloop; - default: - idef: - scm_ipruk ("immediate", type, svalue, stream); - break; - case 0: - - switch (SCM_TYP7 (svalue)) - { - case scm_tcs_cons_gloc: - if (SCM_CDR (SCM_CAR (svalue) - 1L) == 0) - { -#if 0 - SCM name; -#endif - - fputs_filtered ("#", phex_nz (svalue, SCM_SIZE)); - break; - } - case scm_tcs_cons_imcar: - case scm_tcs_cons_nimcar: - fputs_filtered ("(", stream); - scm_scmlist_print (type, svalue, stream, recurse + 1, options); - fputs_filtered (")", stream); - break; - case scm_tcs_closures: - fputs_filtered ("#", stream); - break; - case scm_tc7_string: - { - int len = SCM_LENGTH (svalue); - CORE_ADDR addr = (CORE_ADDR) SCM_CDR (svalue); - int i; - int done = 0; - int buf_size; - gdb_byte buffer[64]; - int truncate = options->print_max && len > (int) options->print_max; - if (truncate) - len = options->print_max; - fputs_filtered ("\"", stream); - for (; done < len; done += buf_size) - { - buf_size = min (len - done, 64); - read_memory (addr + done, buffer, buf_size); - - for (i = 0; i < buf_size; ++i) - switch (buffer[i]) - { - case '\"': - case '\\': - fputs_filtered ("\\", stream); - default: - fprintf_filtered (stream, "%c", buffer[i]); - } - } - fputs_filtered (truncate ? "...\"" : "\"", stream); - break; - } - break; - case scm_tcs_symbols: - { - int len = SCM_LENGTH (svalue); - - char *str = alloca (len); - read_memory (SCM_CDR (svalue), (gdb_byte *) str, len + 1); - /* Should handle weird characters FIXME */ - str[len] = '\0'; - fputs_filtered (str, stream); - break; - } - case scm_tc7_vector: - { - int len = SCM_LENGTH (svalue); - int i; - LONGEST elements = SCM_CDR (svalue); - LONGEST val; - - fputs_filtered ("#(", stream); - for (i = 0; i < len; ++i) - { - if (i > 0) - fputs_filtered (" ", stream); - val = scm_get_field (elements, i, SCM_SIZE, SCM_BYTE_ORDER); - scm_scmval_print (type, val, stream, recurse + 1, options); - } - fputs_filtered (")", stream); - } - break; -#if 0 - case tc7_lvector: - { - SCM result; - SCM hook; - - hook = scm_get_lvector_hook (exp, LV_PRINT_FN); - if (hook == BOOL_F) - { - scm_puts ("#", port); - } - else - { - result - = scm_apply (hook, - scm_listify (exp, port, - (writing ? BOOL_T : BOOL_F), - SCM_UNDEFINED), - EOL); - if (result == BOOL_F) - goto punk; - } - break; - } - break; - case tc7_bvect: - case tc7_ivect: - case tc7_uvect: - case tc7_fvect: - case tc7_dvect: - case tc7_cvect: - scm_raprin1 (exp, port, writing); - break; -#endif - case scm_tcs_subrs: - { - int index = SCM_CAR (svalue) >> 8; -#if 1 - char str[20]; - sprintf (str, "#%d", index); -#else - char *str = index ? SCM_CHARS (scm_heap_org + index) : ""; -#define SCM_CHARS(x) ((char *)(SCM_CDR(x))) - char *str = CHARS (SNAME (exp)); -#endif - - fprintf_filtered (stream, "#", - str); - } - break; -#if 0 -#ifdef CCLO - case tc7_cclo: - scm_puts ("#', port); - break; -#endif - case tc7_contin: - fprintf_filtered (stream, "#", - LENGTH (svalue), - (long) CHARS (svalue)); - break; - case tc7_port: - i = PTOBNUM (exp); - if (i < scm_numptob - && scm_ptobs[i].print - && (scm_ptobs[i].print) (exp, port, writing)) - break; - goto punk; - case tc7_smob: - i = SMOBNUM (exp); - if (i < scm_numsmob && scm_smobs[i].print - && (scm_smobs[i].print) (exp, port, writing)) - break; - goto punk; -#endif - default: -#if 0 - punk: -#endif - scm_ipruk ("type", type, svalue, stream); - } - break; - } -#undef SCM_BYTE_ORDER -#undef SCM_SIZE -} - -int -scm_val_print (struct type *type, const gdb_byte *valaddr, - int embedded_offset, CORE_ADDR address, - struct ui_file *stream, int recurse, - const struct value *val, - const struct value_print_options *options) -{ - if (is_scmvalue_type (type) - && value_bits_valid (val, TARGET_CHAR_BIT * embedded_offset, - TARGET_CHAR_BIT * TYPE_LENGTH (type))) - { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); - LONGEST svalue - = extract_signed_integer (valaddr, TYPE_LENGTH (type), byte_order); - - if (scm_inferior_print (type, svalue, stream, recurse, options) >= 0) - { - } - else - { - scm_scmval_print (type, svalue, stream, recurse, options); - } - - gdb_flush (stream); - return (0); - } - else - { - return c_val_print (type, valaddr, 0, address, stream, recurse, - val, options); - } -} - -int -scm_value_print (struct value *val, struct ui_file *stream, - const struct value_print_options *options) -{ - struct value_print_options opts = *options; - - opts.deref_ref = 1; - return (common_val_print (val, stream, 0, &opts, current_language)); -} diff --git a/contrib/gdb-7/gdb/sentinel-frame.c b/contrib/gdb-7/gdb/sentinel-frame.c index 6c2f3e079d..9d1a81e9fa 100644 --- a/contrib/gdb-7/gdb/sentinel-frame.c +++ b/contrib/gdb-7/gdb/sentinel-frame.c @@ -1,8 +1,6 @@ /* Code dealing with register stack frames, for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986-2002, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -48,25 +46,12 @@ sentinel_frame_prev_register (struct frame_info *this_frame, void **this_prologue_cache, int regnum) { - struct gdbarch *gdbarch = get_frame_arch (this_frame); struct frame_unwind_cache *cache = *this_prologue_cache; struct value *value; - struct type *regtype = register_type (gdbarch, regnum); - /* Return the actual value. */ - value = allocate_value (regtype); - VALUE_LVAL (value) = lval_register; - VALUE_REGNUM (value) = regnum; + value = regcache_cooked_read_value (cache->regcache, regnum); VALUE_FRAME_ID (value) = get_frame_id (this_frame); - /* Use the regcache_cooked_read() method so that it, on the fly, - constructs either a raw or pseudo register from the raw - register cache. */ - if (regcache_cooked_read (cache->regcache, - regnum, - value_contents_raw (value)) == REG_UNAVAILABLE) - mark_value_bytes_unavailable (value, 0, TYPE_LENGTH (regtype)); - return value; } diff --git a/contrib/gdb-7/gdb/sentinel-frame.h b/contrib/gdb-7/gdb/sentinel-frame.h index 30c2b85d4f..7bb1e87064 100644 --- a/contrib/gdb-7/gdb/sentinel-frame.h +++ b/contrib/gdb-7/gdb/sentinel-frame.h @@ -1,7 +1,6 @@ /* Code dealing with register stack frames, for GDB, the GNU debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ser-base.c b/contrib/gdb-7/gdb/ser-base.c index 368afa6331..b4399d0c4b 100644 --- a/contrib/gdb-7/gdb/ser-base.c +++ b/contrib/gdb-7/gdb/ser-base.c @@ -1,8 +1,7 @@ /* Generic serial interface functions. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003, - 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998-2001, 2003-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ser-base.h b/contrib/gdb-7/gdb/ser-base.h index 8cbc22585d..ba6849aa8d 100644 --- a/contrib/gdb-7/gdb/ser-base.h +++ b/contrib/gdb-7/gdb/ser-base.h @@ -1,7 +1,6 @@ /* Generic serial interface functions. - Copyright (C) 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ser-pipe.c b/contrib/gdb-7/gdb/ser-pipe.c index 9bf0d04f30..4616a7e9ab 100644 --- a/contrib/gdb-7/gdb/ser-pipe.c +++ b/contrib/gdb-7/gdb/ser-pipe.c @@ -1,6 +1,5 @@ /* Serial interface for a pipe to a separate program - Copyright (C) 1999, 2000, 2001, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2001, 2007-2012 Free Software Foundation, Inc. Contributed by Cygnus Solutions. diff --git a/contrib/gdb-7/gdb/ser-tcp.c b/contrib/gdb-7/gdb/ser-tcp.c index e3d5640504..d96a8e5f46 100644 --- a/contrib/gdb-7/gdb/ser-tcp.c +++ b/contrib/gdb-7/gdb/ser-tcp.c @@ -1,7 +1,7 @@ /* Serial interface for raw TCP connections on Un*x like systems. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2001, 2005, 2006, - 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998-1999, 2001, 2005-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -39,7 +39,9 @@ #ifdef USE_WIN32API #include +#ifndef ETIMEDOUT #define ETIMEDOUT WSAETIMEDOUT +#endif #define close(fd) closesocket (fd) #define ioctl ioctlsocket #else diff --git a/contrib/gdb-7/gdb/ser-tcp.h b/contrib/gdb-7/gdb/ser-tcp.h index c8ce0bf5a6..45881f6f80 100644 --- a/contrib/gdb-7/gdb/ser-tcp.h +++ b/contrib/gdb-7/gdb/ser-tcp.h @@ -1,7 +1,6 @@ /* Serial interface for raw TCP connections on Un*x like systems. - Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ser-unix.c b/contrib/gdb-7/gdb/ser-unix.c index c541452a8c..4aab7cab0f 100644 --- a/contrib/gdb-7/gdb/ser-unix.c +++ b/contrib/gdb-7/gdb/ser-unix.c @@ -1,7 +1,7 @@ /* Serial interface for local (hardwired) serial ports on Un*x like systems - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2003, - 2004, 2005, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998-2001, 2003-2005, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/ser-unix.h b/contrib/gdb-7/gdb/ser-unix.h index 398b5d3565..4037733c23 100644 --- a/contrib/gdb-7/gdb/ser-unix.h +++ b/contrib/gdb-7/gdb/ser-unix.h @@ -1,7 +1,7 @@ /* Serial interface for UN*X file-descriptor based connection. - Copyright (C) 1999, 2000, 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999-2000, 2002, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/serial.c b/contrib/gdb-7/gdb/serial.c index 7c8fbc2c76..868858a8e2 100644 --- a/contrib/gdb-7/gdb/serial.c +++ b/contrib/gdb-7/gdb/serial.c @@ -1,8 +1,6 @@ /* Generic serial interface routines - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1992-2002, 2004-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/serial.h b/contrib/gdb-7/gdb/serial.h index a1eba8d3a6..02a3b2d473 100644 --- a/contrib/gdb-7/gdb/serial.h +++ b/contrib/gdb-7/gdb/serial.h @@ -1,6 +1,6 @@ /* Remote serial support interface definitions for GDB, the GNU Debugger. - Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2004, - 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1996, 1998-2001, 2004-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -278,7 +278,7 @@ struct serial_ops int (*write_prim)(struct serial *scb, const void *buf, size_t count); /* Return that number of bytes that can be read from FD without blocking. Return value of -1 means that the - the read will not block even if less that requested bytes + read will not block even if less that requested bytes are available. */ int (*avail)(struct serial *scb, int fd); diff --git a/contrib/gdb-7/gdb/sim-regno.h b/contrib/gdb-7/gdb/sim-regno.h index 78c3f329d7..506f7022a1 100644 --- a/contrib/gdb-7/gdb/sim-regno.h +++ b/contrib/gdb-7/gdb/sim-regno.h @@ -1,7 +1,6 @@ /* Generic remote debugging interface for simulators. - Copyright (C) 2002, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat, Inc. diff --git a/contrib/gdb-7/gdb/skip.c b/contrib/gdb-7/gdb/skip.c new file mode 100644 index 0000000000..637f4e0c50 --- /dev/null +++ b/contrib/gdb-7/gdb/skip.c @@ -0,0 +1,602 @@ +/* Skipping uninteresting files and functions while stepping. + + Copyright (C) 2011-2012 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "skip.h" +#include "value.h" +#include "valprint.h" +#include "ui-out.h" +#include "gdb_string.h" +#include "symtab.h" +#include "gdbcmd.h" +#include "command.h" +#include "completer.h" +#include "stack.h" +#include "cli/cli-utils.h" +#include "arch-utils.h" +#include "linespec.h" +#include "objfiles.h" +#include "exceptions.h" +#include "breakpoint.h" /* for get_sal_arch () */ + +struct skiplist_entry +{ + int number; + + /* NULL if this isn't a skiplist entry for an entire file. + The skiplist entry owns this pointer. */ + char *filename; + + /* The name of the marked-for-skip function, if this is a skiplist + entry for a function. Note that this might be non-null even if + the pc is 0 if the entry is pending a shared library load. + + The skiplist entry owns this pointer. */ + char *function_name; + + /* 0 if this is a skiplist entry for an entire file, or if this + entry will be on a function, pending a shared library load. */ + CORE_ADDR pc; + + /* Architecture we used to create the skiplist entry. May be null + if the entry is pending a shared library load. */ + struct gdbarch *gdbarch; + + int enabled; + int pending; + + struct skiplist_entry *next; +}; + +static void skip_function_command (char *arg, int from_tty); +static void skip_file_command (char *arg, int from_tty); +static void skip_info (char *arg, int from_tty); + +static void add_skiplist_entry (struct skiplist_entry *e); +static void skip_function_pc (CORE_ADDR pc, char *name, + struct gdbarch *arch, + int pending); + +static struct skiplist_entry *skiplist_entry_chain; +static int skiplist_entry_count; + +#define ALL_SKIPLIST_ENTRIES(E) \ + for (E = skiplist_entry_chain; E; E = E->next) + +#define ALL_SKIPLIST_ENTRIES_SAFE(E,TMP) \ + for (E = skiplist_entry_chain; \ + E ? (TMP = E->next, 1) : 0; \ + E = TMP) + +static void +skip_file_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + struct symtab *symtab; + int pending = 0; + char *filename = 0; + + /* If no argument was given, try to default to the last + displayed codepoint. */ + if (arg == 0) + { + symtab = get_last_displayed_symtab (); + if (symtab == 0) + error (_("No default file now.")); + else + filename = symtab->filename; + } + else + { + symtab = lookup_symtab (arg); + if (symtab == 0) + { + fprintf_filtered (gdb_stderr, _("No source file named %s.\n"), arg); + if (!nquery (_("\ +Ignore file pending future shared library load? "))) + return; + + pending = 1; + filename = arg; + } + else + filename = symtab->filename; + } + + e = XZALLOC (struct skiplist_entry); + e->filename = xstrdup (filename); + e->enabled = 1; + e->pending = pending; + if (symtab != 0) + e->gdbarch = get_objfile_arch (symtab->objfile); + + add_skiplist_entry (e); + + printf_filtered (_("File %s will be skipped when stepping.\n"), filename); +} + +static void +skip_function_command (char *arg, int from_tty) +{ + CORE_ADDR func_pc; + char *name = NULL; + + /* Default to the current function if no argument is given. */ + if (arg == 0) + { + CORE_ADDR pc; + if (!last_displayed_sal_is_valid ()) + error (_("No default function now.")); + + pc = get_last_displayed_addr (); + if (!find_pc_partial_function (pc, &name, &func_pc, 0)) + { + error (_("No function found containing current program point %s."), + paddress (get_current_arch (), pc)); + } + skip_function_pc (func_pc, name, get_current_arch (), 0); + } + else + { + /* Decode arg. We set funfirstline=1 so decode_line_1 will give us the + first line of the function specified, if it can, and so that we'll + reject variable names and the like. */ + + int i; + int pending = 0; + char *orig_arg = arg; /* decode_line_1 modifies the arg pointer. */ + volatile struct gdb_exception decode_exception; + struct symtabs_and_lines sals = { 0 }; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE, 0, 0); + } + + if (decode_exception.reason < 0) + { + if (decode_exception.error != NOT_FOUND_ERROR) + throw_exception (decode_exception); + + fprintf_filtered (gdb_stderr, + _("No function found named %s.\n"), orig_arg); + + if (nquery (_("\ +Ignore function pending future shared library load? "))) + { + /* Add the pending skiplist entry. */ + skip_function_pc (0, orig_arg, 0, 1); + } + + return; + } + + if (sals.nelts > 1) + error (_("Specify just one function at a time.")); + if (strlen (arg) != 0) + error (_("Junk at end of arguments.")); + + /* The pc decode_line_1 gives us is the first line of the function, + but we actually want the line before that. The call to + find_pc_partial_function gets us the value we actually want. */ + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + + if (!find_pc_partial_function (pc, &name, &func_start, 0)) + { + error (_("No function found containing program point %s."), + paddress (arch, pc)); + } + + skip_function_pc (func_start, name, arch, 0); + } + } +} + +static void +skip_info (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int num_printable_entries = 0; + int address_width = 10; + struct value_print_options opts; + struct cleanup *tbl_chain; + + get_user_print_options (&opts); + + /* Count the number of rows in the table and see if we need space for a + 64-bit address anywhere. */ + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + num_printable_entries++; + if (e->gdbarch && gdbarch_addr_bit (e->gdbarch) > 32) + address_width = 18; + } + + if (num_printable_entries == 0) + { + if (arg == 0) + ui_out_message (current_uiout, 0, _("\ +Not skipping any files or functions.\n")); + else + ui_out_message (current_uiout, 0, + _("No skiplist entries found with number %s.\n"), arg); + + return; + } + + if (opts.addressprint) + tbl_chain = make_cleanup_ui_out_table_begin_end (current_uiout, 5, + num_printable_entries, + "SkiplistTable"); + else + tbl_chain + = make_cleanup_ui_out_table_begin_end (current_uiout, 4, + num_printable_entries, + "SkiplistTable"); + + ui_out_table_header (current_uiout, 7, ui_left, "number", "Num"); /* 1 */ + ui_out_table_header (current_uiout, 14, ui_left, "type", "Type"); /* 2 */ + ui_out_table_header (current_uiout, 3, ui_left, "enabled", "Enb"); /* 3 */ + if (opts.addressprint) + { + ui_out_table_header (current_uiout, address_width, ui_left, + "addr", "Address"); /* 4 */ + } + ui_out_table_header (current_uiout, 40, ui_noalign, "what", "What"); /* 5 */ + ui_out_table_body (current_uiout); + + ALL_SKIPLIST_ENTRIES (e) + { + struct cleanup *entry_chain; + + QUIT; + if (arg != 0 && !number_is_in_list (arg, e->number)) + continue; + + entry_chain = make_cleanup_ui_out_tuple_begin_end (current_uiout, + "blklst-entry"); + ui_out_field_int (current_uiout, "number", e->number); /* 1 */ + + if (e->function_name != 0) + ui_out_field_string (current_uiout, "type", "function"); /* 2 */ + else if (e->filename != 0) + ui_out_field_string (current_uiout, "type", "file"); /* 2 */ + else + internal_error (__FILE__, __LINE__, _("\ +Skiplist entry should have either a filename or a function name.")); + + if (e->enabled) + ui_out_field_string (current_uiout, "enabled", "y"); /* 3 */ + else + ui_out_field_string (current_uiout, "enabled", "n"); /* 3 */ + + if (opts.addressprint) + { + if (e->pc != 0) + ui_out_field_core_addr (current_uiout, "addr", + e->gdbarch, e->pc); /* 4 */ + else + ui_out_field_string (current_uiout, "addr", ""); /* 4 */ + } + + if (!e->pending && e->function_name != 0) + { + struct symbol *sym; + + gdb_assert (e->pc != 0); + sym = find_pc_function (e->pc); + if (sym) + ui_out_field_fmt (current_uiout, "what", "%s at %s:%d", + sym->ginfo.name, + sym->symtab->filename, + sym->line); + else + ui_out_field_string (current_uiout, "what", "?"); + } + else if (e->pending && e->function_name != 0) + { + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->function_name); + } + else if (!e->pending && e->filename != 0) + ui_out_field_string (current_uiout, "what", e->filename); + else if (e->pending && e->filename != 0) + ui_out_field_fmt (current_uiout, "what", "%s (PENDING)", + e->filename); + + ui_out_text (current_uiout, "\n"); + do_cleanups (entry_chain); + } + + do_cleanups (tbl_chain); +} + +static void +skip_enable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 1; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_disable_command (char *arg, int from_tty) +{ + struct skiplist_entry *e; + int found = 0; + + ALL_SKIPLIST_ENTRIES (e) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + e->enabled = 0; + found = 1; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +static void +skip_delete_command (char *arg, int from_tty) +{ + struct skiplist_entry *e, *temp, *b_prev; + int found = 0; + + b_prev = 0; + ALL_SKIPLIST_ENTRIES_SAFE (e, temp) + if (arg == 0 || number_is_in_list (arg, e->number)) + { + if (b_prev != 0) + b_prev->next = e->next; + else + skiplist_entry_chain = e->next; + + xfree (e->function_name); + xfree (e->filename); + xfree (e); + found = 1; + } + else + { + b_prev = e; + } + + if (!found) + error (_("No skiplist entries found with number %s."), arg); +} + +/* Create a skiplist entry for the given pc corresponding to the given + function name and add it to the list. */ + +static void +skip_function_pc (CORE_ADDR pc, char *name, struct gdbarch *arch, + int pending) +{ + struct skiplist_entry *e = XZALLOC (struct skiplist_entry); + + e->pc = pc; + e->gdbarch = arch; + e->enabled = 1; + e->pending = pending; + e->function_name = xstrdup (name); + + add_skiplist_entry (e); + + if (!pending) + printf_filtered (_("Function %s at %s will be skipped when stepping.\n"), + name, paddress (get_current_arch (), pc)); + else + printf_filtered (_("Function %s will be skipped when stepping, " + "pending shared library load.\n"), + name); +} + +/* Add the given skiplist entry to our list, and set the entry's number. */ + +static void +add_skiplist_entry (struct skiplist_entry *e) +{ + struct skiplist_entry *e1; + + e->number = ++skiplist_entry_count; + + /* Add to the end of the chain so that the list of + skiplist entries will be in numerical order. */ + + e1 = skiplist_entry_chain; + if (e1 == 0) + skiplist_entry_chain = e; + else + { + while (e1->next) + e1 = e1->next; + e1->next = e; + } +} + +/* Does the given pc correspond to the beginning of a skipped function? */ + +int +function_pc_is_marked_for_skip (CORE_ADDR pc) +{ + int searched_for_sal = 0; + struct symtab_and_line sal; + char *filename = NULL; + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (!e->enabled || e->pending) + continue; + + /* Does the pc we're stepping into match e's stored pc? */ + if (e->pc != 0 && pc == e->pc) + return 1; + + if (e->filename != 0) + { + /* Get the filename corresponding to this pc, if we haven't + * yet. */ + if (!searched_for_sal) + { + sal = find_pc_line (pc, 0); + if (sal.symtab != 0) + filename = sal.symtab->filename; + searched_for_sal = 1; + } + if (filename != 0 && strcmp (filename, e->filename) == 0) + return 1; + } + } + + return 0; +} + +/* Re-set the skip list after symbols have been re-loaded. */ +void +skip_re_set (void) +{ + struct skiplist_entry *e; + + ALL_SKIPLIST_ENTRIES (e) + { + if (e->filename != 0) + { + /* If it's an entry telling us to skip a file, but the entry is + currently pending a solib load, let's see if we now know + about the file. */ + struct symtab *symtab = lookup_symtab (e->filename); + if (symtab != 0) + { + xfree (e->filename); + e->filename = xstrdup (symtab->filename); + e->gdbarch = get_objfile_arch (symtab->objfile); + e->pending = 0; + } + else + { + e->pending = 1; + } + } + else if (e->function_name != 0) + { + char *func_name = e->function_name; + struct symtabs_and_lines sals = { 0 }; + volatile struct gdb_exception decode_exception; + + TRY_CATCH (decode_exception, RETURN_MASK_ERROR) + { + sals = decode_line_1 (&func_name, DECODE_LINE_FUNFIRSTLINE, 0, 0); + } + + if (decode_exception.reason >= 0 + && sals.nelts == 1 && strlen (func_name) == 0) + { + struct symtab_and_line sal = sals.sals[0]; + CORE_ADDR pc = sal.pc; + CORE_ADDR func_start = 0; + struct gdbarch *arch = get_sal_arch (sal); + char *func_name; + + if (find_pc_partial_function (pc, &func_name, &func_start, 0)) + { + e->pending = 0; + e->function_name = xstrdup (func_name); + e->pc = func_start; + e->gdbarch = arch; + } + } + else + { + e->pending = 1; + } + } + } +} + +void +_initialize_step_skip (void) +{ + struct cmd_list_element *c; + + skiplist_entry_chain = 0; + skiplist_entry_count = 0; + + add_prefix_cmd ("skip", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip [FUNCTION NAME]\n\ +If no function name is given, ignore the current function."), + &skiplist, "skip ", 1, &cmdlist); + + c = add_cmd ("file", class_breakpoint, skip_file_command, _("\ +Ignore a file while stepping.\n\ +Usage: skip file [FILENAME]\n\ +If no filename is given, ignore the current file."), + &skiplist); + set_cmd_completer (c, filename_completer); + + c = add_cmd ("function", class_breakpoint, skip_function_command, _("\ +Ignore a function while stepping.\n\ +Usage: skip function [FUNCTION NAME]\n\ +If no function name is given, skip the current function."), + &skiplist); + set_cmd_completer (c, location_completer); + + add_cmd ("enable", class_breakpoint, skip_enable_command, _("\ +Enable skip entries. You can specify numbers (e.g. \"skip enable 1 3\"), \ +ranges (e.g. \"skip enable 4-8\"), or both (e.g. \"skip enable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll enable all skip entries.\n\n\ +Usage: skip enable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("disable", class_breakpoint, skip_disable_command, _("\ +Disable skip entries. You can specify numbers (e.g. \"skip disable 1 3\"), \ +ranges (e.g. \"skip disable 4-8\"), or both (e.g. \"skip disable 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll disable all skip entries.\n\n\ +Usage: skip disable [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_cmd ("delete", class_breakpoint, skip_delete_command, _("\ +Delete skip entries. You can specify numbers (e.g. \"skip delete 1 3\"), \ +ranges (e.g. \"skip delete 4-8\"), or both (e.g. \"skip delete 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll delete all skip entries.\n\n\ +Usage: skip delete [NUMBERS AND/OR RANGES]"), + &skiplist); + + add_info ("skip", skip_info, _("\ +Display the status of skips. You can specify numbers (e.g. \"skip info 1 3\"), \ +ranges (e.g. \"skip info 4-8\"), or both (e.g. \"skip info 1 3 4-8\").\n\n\ +If you don't specify any numbers or ranges, we'll show all skips.\n\n\ +Usage: skip info [NUMBERS AND/OR RANGES]\n\ +The \"Type\" column indicates one of:\n\ +\tfile - ignored file\n\ +\tfunction - ignored function")); +} diff --git a/contrib/gdb-7/gdb/tui/tui-command.h b/contrib/gdb-7/gdb/skip.h similarity index 59% copy from contrib/gdb-7/gdb/tui/tui-command.h copy to contrib/gdb-7/gdb/skip.h index bc2aaa1acd..c1f8185460 100644 --- a/contrib/gdb-7/gdb/tui/tui-command.h +++ b/contrib/gdb-7/gdb/skip.h @@ -1,11 +1,6 @@ -/* Specific command window processing. +/* Header for skipping over uninteresting files and functions when debugging. - Copyright (C) 1998, 1999, 2000, 2001, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. - - Contributed by Hewlett-Packard Company. - - This file is part of GDB. + Copyright (C) 2011-2012 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,9 +15,14 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef TUI_COMMAND_H -#define TUI_COMMAND_H +#if !defined (SKIP_H) +#define SKIP_H + +/* Returns 1 if the given pc is marked for skip and shouldn't be + stepped into. Otherwise, returns 0. */ +int function_pc_is_marked_for_skip (CORE_ADDR pc); -extern unsigned int tui_dispatch_ctrl_char (unsigned int); +/* Re-set the skip list after symbols have been reloaded. */ +void skip_re_set (void); -#endif +#endif /* !defined (SKIP_H) */ diff --git a/contrib/gdb-7/gdb/solib-svr4.c b/contrib/gdb-7/gdb/solib-svr4.c index 30abaa7c81..69d3cb518e 100644 --- a/contrib/gdb-7/gdb/solib-svr4.c +++ b/contrib/gdb-7/gdb/solib-svr4.c @@ -1,8 +1,7 @@ /* Handle SVR4 shared libraries for GDB, the GNU Debugger. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, - 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-1996, 1998-2001, 2003-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -56,20 +55,21 @@ static void svr4_relocate_main_executable (void); struct lm_info { - /* Pointer to copy of link map from inferior. The type is char * - rather than void *, so that we may use byte offsets to find the - various fields without the need for a cast. */ - gdb_byte *lm; - /* Amount by which addresses in the binary should be relocated to - match the inferior. This could most often be taken directly - from lm, but when prelinking is involved and the prelink base - address changes, we may need a different offset, we want to - warn about the difference and compute it only once. */ - CORE_ADDR l_addr; + match the inferior. The direct inferior value is L_ADDR_INFERIOR. + When prelinking is involved and the prelink base address changes, + we may need a different offset - the recomputed offset is in L_ADDR. + It is commonly the same value. It is cached as we want to warn about + the difference and compute it only once. L_ADDR is valid + iff L_ADDR_P. */ + CORE_ADDR l_addr, l_addr_inferior; + unsigned int l_addr_p : 1; /* The target location of lm. */ CORE_ADDR lm_addr; + + /* Values read in from inferior's fields of the same name. */ + CORE_ADDR l_ld, l_next, l_prev, l_name; }; /* On SVR4 systems, a list of symbols in the dynamic linker where @@ -116,8 +116,8 @@ svr4_same_1 (const char *gdb_so_name, const char *inferior_so_name) return 1; /* On Solaris, when starting inferior we think that dynamic linker is - /usr/lib/ld.so.1, but later on, the table of loaded shared libraries - contains /lib/ld.so.1. Sometimes one file is a link to another, but + /usr/lib/ld.so.1, but later on, the table of loaded shared libraries + contains /lib/ld.so.1. Sometimes one file is a link to another, but sometimes they have identical content, but are not linked to each other. We don't restrict this check for Solaris, but the chances of running into this situation elsewhere are very low. */ @@ -140,50 +140,68 @@ svr4_same (struct so_list *gdb, struct so_list *inferior) return (svr4_same_1 (gdb->so_original_name, inferior->so_original_name)); } -/* link map access functions. */ - -static CORE_ADDR -LM_ADDR_FROM_LINK_MAP (struct so_list *so) +static struct lm_info * +lm_info_read (CORE_ADDR lm_addr) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; + gdb_byte *lm; + struct lm_info *lm_info; + struct cleanup *back_to; - return extract_typed_address (so->lm_info->lm + lmo->l_addr_offset, - ptr_type); -} + lm = xmalloc (lmo->link_map_size); + back_to = make_cleanup (xfree, lm); -static int -HAS_LM_DYNAMIC_FROM_LINK_MAP (void) -{ - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); + if (target_read_memory (lm_addr, lm, lmo->link_map_size) != 0) + { + warning (_("Error reading shared library list entry at %s"), + paddress (target_gdbarch, lm_addr)), + lm_info = NULL; + } + else + { + struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - return lmo->l_ld_offset >= 0; + lm_info = xzalloc (sizeof (*lm_info)); + lm_info->lm_addr = lm_addr; + + lm_info->l_addr_inferior = extract_typed_address (&lm[lmo->l_addr_offset], + ptr_type); + lm_info->l_ld = extract_typed_address (&lm[lmo->l_ld_offset], ptr_type); + lm_info->l_next = extract_typed_address (&lm[lmo->l_next_offset], + ptr_type); + lm_info->l_prev = extract_typed_address (&lm[lmo->l_prev_offset], + ptr_type); + lm_info->l_name = extract_typed_address (&lm[lmo->l_name_offset], + ptr_type); + } + + do_cleanups (back_to); + + return lm_info; } -static CORE_ADDR -LM_DYNAMIC_FROM_LINK_MAP (struct so_list *so) +static int +has_lm_dynamic_from_link_map (void) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - return extract_typed_address (so->lm_info->lm + lmo->l_ld_offset, - ptr_type); + return lmo->l_ld_offset >= 0; } static CORE_ADDR -LM_ADDR_CHECK (struct so_list *so, bfd *abfd) +lm_addr_check (struct so_list *so, bfd *abfd) { - if (so->lm_info->l_addr == (CORE_ADDR)-1) + if (!so->lm_info->l_addr_p) { struct bfd_section *dyninfo_sect; CORE_ADDR l_addr, l_dynaddr, dynaddr; - l_addr = LM_ADDR_FROM_LINK_MAP (so); + l_addr = so->lm_info->l_addr_inferior; - if (! abfd || ! HAS_LM_DYNAMIC_FROM_LINK_MAP ()) + if (! abfd || ! has_lm_dynamic_from_link_map ()) goto set_addr; - l_dynaddr = LM_DYNAMIC_FROM_LINK_MAP (so); + l_dynaddr = so->lm_info->l_ld; dyninfo_sect = bfd_get_section_by_name (abfd, ".dynamic"); if (dyninfo_sect == NULL) @@ -237,11 +255,11 @@ LM_ADDR_CHECK (struct so_list *so, bfd *abfd) Even on PPC it must be zero-aligned at least for MINPAGESIZE. */ + l_addr = l_dynaddr - dynaddr; + if ((l_addr & (minpagesize - 1)) == 0 && (l_addr & align) == ((l_dynaddr - dynaddr) & align)) { - l_addr = l_dynaddr - dynaddr; - if (info_verbose) printf_unfiltered (_("Using PIC (Position Independent Code) " "prelink displacement %s for \"%s\".\n"), @@ -249,59 +267,30 @@ LM_ADDR_CHECK (struct so_list *so, bfd *abfd) so->so_name); } else - warning (_(".dynamic section for \"%s\" " - "is not at the expected address " - "(wrong library or version mismatch?)"), so->so_name); + { + /* There is no way to verify the library file matches. prelink + can during prelinking of an unprelinked file (or unprelinking + of a prelinked file) shift the DYNAMIC segment by arbitrary + offset without any page size alignment. There is no way to + find out the ELF header and/or Program Headers for a limited + verification if it they match. One could do a verification + of the DYNAMIC segment. Still the found address is the best + one GDB could find. */ + + warning (_(".dynamic section for \"%s\" " + "is not at the expected address " + "(wrong library or version mismatch?)"), so->so_name); + } } set_addr: so->lm_info->l_addr = l_addr; + so->lm_info->l_addr_p = 1; } return so->lm_info->l_addr; } -static CORE_ADDR -LM_NEXT (struct so_list *so) -{ - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - - return extract_typed_address (so->lm_info->lm + lmo->l_next_offset, - ptr_type); -} - -static CORE_ADDR -LM_PREV (struct so_list *so) -{ - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - - return extract_typed_address (so->lm_info->lm + lmo->l_prev_offset, - ptr_type); -} - -static CORE_ADDR -LM_NAME (struct so_list *so) -{ - struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - struct type *ptr_type = builtin_type (target_gdbarch)->builtin_data_ptr; - - return extract_typed_address (so->lm_info->lm + lmo->l_name_offset, - ptr_type); -} - -static int -IGNORE_FIRST_LINK_MAP_ENTRY (struct so_list *so) -{ - /* Assume that everything is a library if the dynamic loader was loaded - late by a static executable. */ - if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) - return 0; - - return LM_PREV (so) == 0; -} - /* Per pspace SVR4 specific data. */ struct svr4_info @@ -359,97 +348,6 @@ get_svr4_info (void) static int match_main (const char *); -/* - - LOCAL FUNCTION - - bfd_lookup_symbol -- lookup the value for a specific symbol - - SYNOPSIS - - CORE_ADDR bfd_lookup_symbol (bfd *abfd, char *symname) - - DESCRIPTION - - An expensive way to lookup the value of a single symbol for - bfd's that are only temporary anyway. This is used by the - shared library support to find the address of the debugger - notification routine in the shared library. - - The returned symbol may be in a code or data section; functions - will normally be in a code section, but may be in a data section - if this architecture uses function descriptors. - - Note that 0 is specifically allowed as an error return (no - such symbol). - */ - -static CORE_ADDR -bfd_lookup_symbol (bfd *abfd, const char *symname) -{ - long storage_needed; - asymbol *sym; - asymbol **symbol_table; - unsigned int number_of_symbols; - unsigned int i; - struct cleanup *back_to; - CORE_ADDR symaddr = 0; - - storage_needed = bfd_get_symtab_upper_bound (abfd); - - if (storage_needed > 0) - { - symbol_table = (asymbol **) xmalloc (storage_needed); - back_to = make_cleanup (xfree, symbol_table); - number_of_symbols = bfd_canonicalize_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) - { - sym = *symbol_table++; - if (strcmp (sym->name, symname) == 0 - && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0) - { - /* BFD symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - break; - } - } - do_cleanups (back_to); - } - - if (symaddr) - return symaddr; - - /* On FreeBSD, the dynamic linker is stripped by default. So we'll - have to check the dynamic string table too. */ - - storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); - - if (storage_needed > 0) - { - symbol_table = (asymbol **) xmalloc (storage_needed); - back_to = make_cleanup (xfree, symbol_table); - number_of_symbols = bfd_canonicalize_dynamic_symtab (abfd, symbol_table); - - for (i = 0; i < number_of_symbols; i++) - { - sym = *symbol_table++; - - if (strcmp (sym->name, symname) == 0 - && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0) - { - /* BFD symbols are section relative. */ - symaddr = sym->value + sym->section->vma; - break; - } - } - do_cleanups (back_to); - } - - return symaddr; -} - - /* Read program header TYPE from inferior memory. The header is found by scanning the OS auxillary vector. @@ -465,10 +363,11 @@ static gdb_byte * read_program_header (int type, int *p_sect_size, int *p_arch_size) { enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch); - CORE_ADDR at_phdr, at_phent, at_phnum; + CORE_ADDR at_phdr, at_phent, at_phnum, pt_phdr = 0; int arch_size, sect_size; CORE_ADDR sect_addr; gdb_byte *buf; + int pt_phdr_p = 0; /* Get required auxv elements from target. */ if (target_auxv_search (¤t_target, AT_PHDR, &at_phdr) <= 0) @@ -502,12 +401,23 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) /* Search for requested PHDR. */ for (i = 0; i < at_phnum; i++) { + int p_type; + if (target_read_memory (at_phdr + i * sizeof (phdr), (gdb_byte *)&phdr, sizeof (phdr))) return 0; - if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, - 4, byte_order) == type) + p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type, + 4, byte_order); + + if (p_type == PT_PHDR) + { + pt_phdr_p = 1; + pt_phdr = extract_unsigned_integer ((gdb_byte *) phdr.p_vaddr, + 4, byte_order); + } + + if (p_type == type) break; } @@ -528,12 +438,23 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) /* Search for requested PHDR. */ for (i = 0; i < at_phnum; i++) { + int p_type; + if (target_read_memory (at_phdr + i * sizeof (phdr), (gdb_byte *)&phdr, sizeof (phdr))) return 0; - if (extract_unsigned_integer ((gdb_byte *)phdr.p_type, - 4, byte_order) == type) + p_type = extract_unsigned_integer ((gdb_byte *) phdr.p_type, + 4, byte_order); + + if (p_type == PT_PHDR) + { + pt_phdr_p = 1; + pt_phdr = extract_unsigned_integer ((gdb_byte *) phdr.p_vaddr, + 8, byte_order); + } + + if (p_type == type) break; } @@ -547,6 +468,16 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size) 8, byte_order); } + /* PT_PHDR is optional, but we really need it + for PIE to make this work in general. */ + + if (pt_phdr_p) + { + /* at_phdr is real address in memory. pt_phdr is what pheader says it is. + Relocation offset is the difference between the two. */ + sect_addr = sect_addr + (at_phdr - pt_phdr); + } + /* Read in requested program header. */ buf = xmalloc (sect_size); if (target_read_memory (sect_addr, buf, sect_size)) @@ -753,19 +684,8 @@ scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr) return 0; } - -/* - - LOCAL FUNCTION - - elf_locate_base -- locate the base address of dynamic linker structs - for SVR4 elf targets. - - SYNOPSIS - - CORE_ADDR elf_locate_base (void) - - DESCRIPTION +/* Locate the base address of dynamic linker structs for SVR4 elf + targets. For SVR4 elf targets the address of the dynamic linker's runtime structure is contained within the dynamic info section in the @@ -774,9 +694,7 @@ scan_dyntag_auxv (int dyntag, CORE_ADDR *ptr) real address before starting the inferior, we have to read in the dynamic info section from the inferior address space. If there are any errors while trying to find the address, we - silently return 0, otherwise the found address is returned. - - */ + silently return 0, otherwise the found address is returned. */ static CORE_ADDR elf_locate_base (void) @@ -817,17 +735,7 @@ elf_locate_base (void) return 0; } -/* - - LOCAL FUNCTION - - locate_base -- locate the base address of dynamic linker structs - - SYNOPSIS - - CORE_ADDR locate_base (struct svr4_info *) - - DESCRIPTION +/* Locate the base address of dynamic linker structs. For both the SunOS and SVR4 shared library implementations, if the inferior executable has been linked dynamically, there is a single @@ -850,9 +758,7 @@ elf_locate_base (void) to a lot more work to discover the address of the debug base symbol. Because of this complexity, we cache the value we find and return that value on subsequent invocations. Note there is no copy in the - executable symbol tables. - - */ + executable symbol tables. */ static CORE_ADDR locate_base (struct svr4_info *info) @@ -943,7 +849,7 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) struct so_list *new; struct cleanup *old_chain; struct link_map_offsets *lmo; - CORE_ADDR lm_name; + CORE_ADDR name_lm; info = get_svr4_info (); @@ -959,40 +865,20 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) lmo = svr4_fetch_link_map_offsets (); new = XZALLOC (struct so_list); old_chain = make_cleanup (xfree, new); - new->lm_info = xmalloc (sizeof (struct lm_info)); + new->lm_info = lm_info_read (ldsomap); make_cleanup (xfree, new->lm_info); - new->lm_info->l_addr = (CORE_ADDR)-1; - new->lm_info->lm_addr = ldsomap; - new->lm_info->lm = xzalloc (lmo->link_map_size); - make_cleanup (xfree, new->lm_info->lm); - read_memory (ldsomap, new->lm_info->lm, lmo->link_map_size); - lm_name = LM_NAME (new); + name_lm = new->lm_info ? new->lm_info->l_name : 0; do_cleanups (old_chain); - return (lm_name >= vaddr && lm_name < vaddr + size); + return (name_lm >= vaddr && name_lm < vaddr + size); } -/* +/* Implement the "open_symbol_file_object" target_so_ops method. - LOCAL FUNCTION - - open_symbol_file_object - - SYNOPSIS - - void open_symbol_file_object (void *from_tty) - - DESCRIPTION - - If no open symbol file, attempt to locate and open the main symbol - file. On SVR4 systems, this is the first link map entry. If its - name is here, we can open it. Useful when attaching to a process - without first loading its symbol file. - - If FROM_TTYP dereferences to a non-zero integer, allow messages to - be printed. This parameter is a pointer rather than an int because - open_symbol_file_object() is called via catch_errors() and - catch_errors() requires a pointer argument. */ + If no open symbol file, attempt to locate and open the main symbol + file. On SVR4 systems, this is the first link map entry. If its + name is here, we can open it. Useful when attaching to a process + without first loading its symbol file. */ static int open_symbol_file_object (void *from_ttyp) @@ -1010,17 +896,26 @@ open_symbol_file_object (void *from_ttyp) if (symfile_objfile) if (!query (_("Attempt to reload symbols from process? "))) - return 0; + { + do_cleanups (cleanups); + return 0; + } /* Always locate the debug struct, in case it has moved. */ info->debug_base = 0; if (locate_base (info) == 0) - return 0; /* failed somehow... */ + { + do_cleanups (cleanups); + return 0; /* failed somehow... */ + } /* First link map member should be the executable. */ lm = solib_svr4_r_map (info); if (lm == 0) - return 0; /* failed somehow... */ + { + do_cleanups (cleanups); + return 0; /* failed somehow... */ + } /* Read address of name from target memory to GDB. */ read_memory (lm + lmo->l_name_offset, l_name_buf, l_name_size); @@ -1028,11 +923,11 @@ open_symbol_file_object (void *from_ttyp) /* Convert the address to host format. */ l_name = extract_typed_address (l_name_buf, ptr_type); - /* Free l_name_buf. */ - do_cleanups (cleanups); - if (l_name == 0) - return 0; /* No filename. */ + { + do_cleanups (cleanups); + return 0; /* No filename. */ + } /* Now fetch the filename from target memory. */ target_read_string (l_name, &filename, SO_NAME_MAX_PATH_SIZE - 1, &errcode); @@ -1042,118 +937,269 @@ open_symbol_file_object (void *from_ttyp) { warning (_("failed to read exec filename from attached file: %s"), safe_strerror (errcode)); + do_cleanups (cleanups); return 0; } /* Have a pathname: read the symbol file. */ symbol_file_add_main (filename, from_tty); + do_cleanups (cleanups); return 1; } -/* If no shared library information is available from the dynamic - linker, build a fallback list from other sources. */ +/* Data exchange structure for the XML parser as returned by + svr4_current_sos_via_xfer_libraries. */ -static struct so_list * -svr4_default_sos (void) +struct svr4_library_list { - struct svr4_info *info = get_svr4_info (); + struct so_list *head, **tailp; - struct so_list *head = NULL; - struct so_list **link_ptr = &head; + /* Inferior address of struct link_map used for the main executable. It is + NULL if not known. */ + CORE_ADDR main_lm; +}; + +/* Implementation for target_so_ops.free_so. */ + +static void +svr4_free_so (struct so_list *so) +{ + xfree (so->lm_info); +} + +/* Free so_list built so far (called via cleanup). */ - if (info->debug_loader_offset_p) +static void +svr4_free_library_list (void *p_list) +{ + struct so_list *list = *(struct so_list **) p_list; + + while (list != NULL) { - struct so_list *new = XZALLOC (struct so_list); + struct so_list *next = list->next; - new->lm_info = xmalloc (sizeof (struct lm_info)); + svr4_free_so (list); + list = next; + } +} - /* Nothing will ever check the cached copy of the link - map if we set l_addr. */ - new->lm_info->l_addr = info->debug_loader_offset; - new->lm_info->lm_addr = 0; - new->lm_info->lm = NULL; +#ifdef HAVE_LIBEXPAT - strncpy (new->so_name, info->debug_loader_name, - SO_NAME_MAX_PATH_SIZE - 1); - new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - strcpy (new->so_original_name, new->so_name); +#include "xml-support.h" + +/* Handle the start of a element. Note: new elements are added + at the tail of the list, keeping the list in order. */ + +static void +library_list_start_library (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, VEC(gdb_xml_value_s) *attributes) +{ + struct svr4_library_list *list = user_data; + const char *name = xml_find_attribute (attributes, "name")->value; + ULONGEST *lmp = xml_find_attribute (attributes, "lm")->value; + ULONGEST *l_addrp = xml_find_attribute (attributes, "l_addr")->value; + ULONGEST *l_ldp = xml_find_attribute (attributes, "l_ld")->value; + struct so_list *new_elem; + + new_elem = XZALLOC (struct so_list); + new_elem->lm_info = XZALLOC (struct lm_info); + new_elem->lm_info->lm_addr = *lmp; + new_elem->lm_info->l_addr_inferior = *l_addrp; + new_elem->lm_info->l_ld = *l_ldp; + + strncpy (new_elem->so_name, name, sizeof (new_elem->so_name) - 1); + new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0; + strcpy (new_elem->so_original_name, new_elem->so_name); + + *list->tailp = new_elem; + list->tailp = &new_elem->next; +} + +/* Handle the start of a element. */ + +static void +svr4_library_list_start_list (struct gdb_xml_parser *parser, + const struct gdb_xml_element *element, + void *user_data, VEC(gdb_xml_value_s) *attributes) +{ + struct svr4_library_list *list = user_data; + const char *version = xml_find_attribute (attributes, "version")->value; + struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm"); - *link_ptr = new; - link_ptr = &new->next; + if (strcmp (version, "1.0") != 0) + gdb_xml_error (parser, + _("SVR4 Library list has unsupported version \"%s\""), + version); + + if (main_lm) + list->main_lm = *(ULONGEST *) main_lm->value; +} + +/* The allowed elements and attributes for an XML library list. + The root element is a . */ + +static const struct gdb_xml_attribute svr4_library_attributes[] = +{ + { "name", GDB_XML_AF_NONE, NULL, NULL }, + { "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + +static const struct gdb_xml_element svr4_library_list_children[] = +{ + { + "library", svr4_library_attributes, NULL, + GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, + library_list_start_library, NULL + }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +static const struct gdb_xml_attribute svr4_library_list_attributes[] = +{ + { "version", GDB_XML_AF_NONE, NULL, NULL }, + { "main-lm", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, + { NULL, GDB_XML_AF_NONE, NULL, NULL } +}; + +static const struct gdb_xml_element svr4_library_list_elements[] = +{ + { "library-list-svr4", svr4_library_list_attributes, svr4_library_list_children, + GDB_XML_EF_NONE, svr4_library_list_start_list, NULL }, + { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } +}; + +/* Parse qXfer:libraries:read packet into *SO_LIST_RETURN. Return 1 if + + Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such + case. Return 1 if *SO_LIST_RETURN contains the library list, it may be + empty, caller is responsible for freeing all its entries. */ + +static int +svr4_parse_libraries (const char *document, struct svr4_library_list *list) +{ + struct cleanup *back_to = make_cleanup (svr4_free_library_list, + &list->head); + + memset (list, 0, sizeof (*list)); + list->tailp = &list->head; + if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd", + svr4_library_list_elements, document, list) == 0) + { + /* Parsed successfully, keep the result. */ + discard_cleanups (back_to); + return 1; } - return head; + do_cleanups (back_to); + return 0; } -/* LOCAL FUNCTION +/* Attempt to get so_list from target via qXfer:libraries:read packet. - current_sos -- build a list of currently loaded shared objects + Return 0 if packet not supported, *SO_LIST_RETURN is not modified in such + case. Return 1 if *SO_LIST_RETURN contains the library list, it may be + empty, caller is responsible for freeing all its entries. */ - SYNOPSIS +static int +svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list) +{ + char *svr4_library_document; + int result; + struct cleanup *back_to; - struct so_list *current_sos () + /* Fetch the list of shared libraries. */ + svr4_library_document = target_read_stralloc (¤t_target, + TARGET_OBJECT_LIBRARIES_SVR4, + NULL); + if (svr4_library_document == NULL) + return 0; - DESCRIPTION + back_to = make_cleanup (xfree, svr4_library_document); + result = svr4_parse_libraries (svr4_library_document, list); + do_cleanups (back_to); - Build a list of `struct so_list' objects describing the shared - objects currently loaded in the inferior. This list does not - include an entry for the main executable file. + return result; +} - Note that we only gather information directly available from the - inferior --- we don't examine any of the shared library files - themselves. The declaration of `struct so_list' says which fields - we provide values for. */ +#else + +static int +svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list) +{ + return 0; +} + +#endif + +/* If no shared library information is available from the dynamic + linker, build a fallback list from other sources. */ static struct so_list * -svr4_current_sos (void) +svr4_default_sos (void) { - CORE_ADDR lm, prev_lm; - struct so_list *head = 0; - struct so_list **link_ptr = &head; - CORE_ADDR ldsomap = 0; - struct svr4_info *info; + struct svr4_info *info = get_svr4_info (); + struct so_list *new; - info = get_svr4_info (); + if (!info->debug_loader_offset_p) + return NULL; - /* Always locate the debug struct, in case it has moved. */ - info->debug_base = 0; - locate_base (info); + new = XZALLOC (struct so_list); - /* If we can't find the dynamic linker's base structure, this - must not be a dynamically linked executable. Hmm. */ - if (! info->debug_base) - return svr4_default_sos (); + new->lm_info = xzalloc (sizeof (struct lm_info)); - /* Walk the inferior's link map list, and build our list of - `struct so_list' nodes. */ - prev_lm = 0; - lm = solib_svr4_r_map (info); + /* Nothing will ever check the other fields if we set l_addr_p. */ + new->lm_info->l_addr = info->debug_loader_offset; + new->lm_info->l_addr_p = 1; + + strncpy (new->so_name, info->debug_loader_name, SO_NAME_MAX_PATH_SIZE - 1); + new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; + strcpy (new->so_original_name, new->so_name); + + return new; +} + +/* Read the whole inferior libraries chain starting at address LM. Add the + entries to the tail referenced by LINK_PTR_PTR. Ignore the first entry if + IGNORE_FIRST and set global MAIN_LM_ADDR according to it. */ + +static void +svr4_read_so_list (CORE_ADDR lm, struct so_list ***link_ptr_ptr, + int ignore_first) +{ + CORE_ADDR prev_lm = 0, next_lm; - while (lm) + for (; lm != 0; prev_lm = lm, lm = next_lm) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); - struct so_list *new = XZALLOC (struct so_list); - struct cleanup *old_chain = make_cleanup (xfree, new); - CORE_ADDR next_lm; + struct so_list *new; + struct cleanup *old_chain; + int errcode; + char *buffer; - new->lm_info = xmalloc (sizeof (struct lm_info)); - make_cleanup (xfree, new->lm_info); + new = XZALLOC (struct so_list); + old_chain = make_cleanup_free_so (new); - new->lm_info->l_addr = (CORE_ADDR)-1; - new->lm_info->lm_addr = lm; - new->lm_info->lm = xzalloc (lmo->link_map_size); - make_cleanup (xfree, new->lm_info->lm); - - read_memory (lm, new->lm_info->lm, lmo->link_map_size); + new->lm_info = lm_info_read (lm); + if (new->lm_info == NULL) + { + do_cleanups (old_chain); + break; + } - next_lm = LM_NEXT (new); + next_lm = new->lm_info->l_next; - if (LM_PREV (new) != prev_lm) + if (new->lm_info->l_prev != prev_lm) { - warning (_("Corrupted shared library list")); - free_so (new); - next_lm = 0; + warning (_("Corrupted shared library list: %s != %s"), + paddress (target_gdbarch, prev_lm), + paddress (target_gdbarch, new->lm_info->l_prev)); + do_cleanups (old_chain); + break; } /* For SVR4 versions, the first entry in the link map is for the @@ -1161,58 +1207,105 @@ svr4_current_sos (void) SVR4, it has no name. For others (Solaris 2.3 for example), it does have a name, so we can no longer use a missing name to decide when to ignore it. */ - else if (IGNORE_FIRST_LINK_MAP_ENTRY (new) && ldsomap == 0) + if (ignore_first && new->lm_info->l_prev == 0) { + struct svr4_info *info = get_svr4_info (); + info->main_lm_addr = new->lm_info->lm_addr; - free_so (new); + do_cleanups (old_chain); + continue; } - else - { - int errcode; - char *buffer; - - /* Extract this shared object's name. */ - target_read_string (LM_NAME (new), &buffer, - SO_NAME_MAX_PATH_SIZE - 1, &errcode); - if (errcode != 0) - warning (_("Can't read pathname for load map: %s."), - safe_strerror (errcode)); - else - { - strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1); - new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; - strcpy (new->so_original_name, new->so_name); - } - xfree (buffer); - /* If this entry has no name, or its name matches the name - for the main executable, don't include it in the list. */ - if (! new->so_name[0] - || match_main (new->so_name)) - free_so (new); - else - { - new->next = 0; - *link_ptr = new; - link_ptr = &new->next; - } + /* Extract this shared object's name. */ + target_read_string (new->lm_info->l_name, &buffer, + SO_NAME_MAX_PATH_SIZE - 1, &errcode); + if (errcode != 0) + { + warning (_("Can't read pathname for load map: %s."), + safe_strerror (errcode)); + do_cleanups (old_chain); + continue; } - prev_lm = lm; - lm = next_lm; + strncpy (new->so_name, buffer, SO_NAME_MAX_PATH_SIZE - 1); + new->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0'; + strcpy (new->so_original_name, new->so_name); + xfree (buffer); - /* On Solaris, the dynamic linker is not in the normal list of - shared objects, so make sure we pick it up too. Having - symbol information for the dynamic linker is quite crucial - for skipping dynamic linker resolver code. */ - if (lm == 0 && ldsomap == 0) + /* If this entry has no name, or its name matches the name + for the main executable, don't include it in the list. */ + if (! new->so_name[0] || match_main (new->so_name)) { - lm = ldsomap = solib_svr4_r_ldsomap (info); - prev_lm = 0; + do_cleanups (old_chain); + continue; } discard_cleanups (old_chain); + new->next = 0; + **link_ptr_ptr = new; + *link_ptr_ptr = &new->next; } +} + +/* Implement the "current_sos" target_so_ops method. */ + +static struct so_list * +svr4_current_sos (void) +{ + CORE_ADDR lm; + struct so_list *head = NULL; + struct so_list **link_ptr = &head; + struct svr4_info *info; + struct cleanup *back_to; + int ignore_first; + struct svr4_library_list library_list; + + if (svr4_current_sos_via_xfer_libraries (&library_list)) + { + if (library_list.main_lm) + { + info = get_svr4_info (); + info->main_lm_addr = library_list.main_lm; + } + + return library_list.head ? library_list.head : svr4_default_sos (); + } + + info = get_svr4_info (); + + /* Always locate the debug struct, in case it has moved. */ + info->debug_base = 0; + locate_base (info); + + /* If we can't find the dynamic linker's base structure, this + must not be a dynamically linked executable. Hmm. */ + if (! info->debug_base) + return svr4_default_sos (); + + /* Assume that everything is a library if the dynamic loader was loaded + late by a static executable. */ + if (exec_bfd && bfd_get_section_by_name (exec_bfd, ".dynamic") == NULL) + ignore_first = 0; + else + ignore_first = 1; + + back_to = make_cleanup (svr4_free_library_list, &head); + + /* Walk the inferior's link map list, and build our list of + `struct so_list' nodes. */ + lm = solib_svr4_r_map (info); + if (lm) + svr4_read_so_list (lm, &link_ptr, ignore_first); + + /* On Solaris, the dynamic linker is not in the normal list of + shared objects, so make sure we pick it up too. Having + symbol information for the dynamic linker is quite crucial + for skipping dynamic linker resolver code. */ + lm = solib_svr4_r_ldsomap (info); + if (lm) + svr4_read_so_list (lm, &link_ptr, 0); + + discard_cleanups (back_to); if (head == NULL) return svr4_default_sos (); @@ -1299,17 +1392,15 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ) targ); } -/* - - LOCAL FUNCTION - - enable_break -- arrange for dynamic linker to hit breakpoint - - SYNOPSIS +/* Helper function for gdb_bfd_lookup_symbol. */ - int enable_break (void) - - DESCRIPTION +static int +cmp_name_and_sec_flags (asymbol *sym, void *data) +{ + return (strcmp (sym->name, (const char *) data) == 0 + && (sym->section->flags & (SEC_CODE | SEC_DATA)) != 0); +} +/* Arrange for dynamic linker to hit breakpoint. Both the SunOS and the SVR4 dynamic linkers have, as part of their debugger interface, support for arranging for the inferior to hit @@ -1339,8 +1430,7 @@ exec_entry_point (struct bfd *abfd, struct target_ops *targ) The debugger interface structure also contains an enumeration which is set to either RT_ADD or RT_DELETE prior to changing the mapping, depending upon whether or not the library is being mapped or unmapped, - and then set to RT_CONSISTENT after the library is mapped/unmapped. - */ + and then set to RT_CONSISTENT after the library is mapped/unmapped. */ static int enable_break (struct svr4_info *info, int from_tty) @@ -1473,7 +1563,7 @@ enable_break (struct svr4_info *info, int from_tty) { load_addr_found = 1; loader_found_in_list = 1; - load_addr = LM_ADDR_CHECK (so, tmp_bfd); + load_addr = lm_addr_check (so, tmp_bfd); break; } so = so->next; @@ -1558,7 +1648,8 @@ enable_break (struct svr4_info *info, int from_tty) /* Now try to set a breakpoint in the dynamic linker. */ for (bkpt_namep = solib_break_names; *bkpt_namep != NULL; bkpt_namep++) { - sym_addr = bfd_lookup_symbol (tmp_bfd, *bkpt_namep); + sym_addr = gdb_bfd_lookup_symbol (tmp_bfd, cmp_name_and_sec_flags, + (void *) *bkpt_namep); if (sym_addr != 0) break; } @@ -1627,34 +1718,12 @@ enable_break (struct svr4_info *info, int from_tty) return 0; } -/* - - LOCAL FUNCTION - - special_symbol_handling -- additional shared library symbol handling - - SYNOPSIS - - void special_symbol_handling () - - DESCRIPTION - - Once the symbols from a shared object have been loaded in the usual - way, we are called to do any system specific symbol handling that - is needed. - - For SunOS4, this consisted of grunging around in the dynamic - linkers structures to find symbol definitions for "common" symbols - and adding them to the minimal symbol table for the runtime common - objfile. - - However, for SVR4, there's nothing to do. - - */ +/* Implement the "special_symbol_handling" target_so_ops method. */ static void svr4_special_symbol_handling (void) { + /* Nothing to do. */ } /* Read the ELF program headers from ABFD. Return the contents and @@ -1715,7 +1784,7 @@ read_program_headers_from_bfd (bfd *abfd, int *phdrs_size) So, to summarize, relocations are necessary when the start address obtained from the executable is different from the address in auxv AT_ENTRY entry. - + [ The astute reader will note that we also test to make sure that the executable in question has the DYNAMIC flag set. It is my opinion that this test is unnecessary (undesirable even). It @@ -2111,28 +2180,7 @@ svr4_relocate_main_executable (void) } } -/* - - GLOBAL FUNCTION - - svr4_solib_create_inferior_hook -- shared library startup support - - SYNOPSIS - - void svr4_solib_create_inferior_hook (int from_tty) - - DESCRIPTION - - When gdb starts up the inferior, it nurses it along (through the - shell) until it is ready to execute it's first instruction. At this - point, this function gets called via expansion of the macro - SOLIB_CREATE_INFERIOR_HOOK. - - For SunOS executables, this first instruction is typically the - one at "_start", or a similar text label, regardless of whether - the executable is statically or dynamically linked. The runtime - startup code takes care of dynamically linking in any shared - libraries, once gdb allows the inferior to continue. +/* Implement the "create_inferior_hook" target_solib_ops method. For SVR4 executables, this first instruction is either the first instruction in the dynamic linker (for dynamically linked @@ -2143,10 +2191,9 @@ svr4_relocate_main_executable (void) shared libraries, maps in the actual user executable, and then jumps to "start" in the user executable. - For both SunOS shared libraries, and SVR4 shared libraries, we - can arrange to cooperate with the dynamic linker to discover the - names of shared libraries that are dynamically linked, and the - base addresses to which they are linked. + We can arrange to cooperate with the dynamic linker to discover the + names of shared libraries that are dynamically linked, and the base + addresses to which they are linked. This function is responsible for discovering those names and addresses, and saving sufficient information about them to allow @@ -2160,8 +2207,7 @@ svr4_relocate_main_executable (void) handling will probably have to wait until the implementation is changed to use the "breakpoint handler function" method. - Also, what if child has exit()ed? Must exit loop somehow. - */ + Also, what if child has exit()ed? Must exit loop somehow. */ static void svr4_solib_create_inferior_hook (int from_tty) @@ -2207,7 +2253,7 @@ svr4_solib_create_inferior_hook (int from_tty) do { target_resume (pid_to_ptid (-1), 0, tp->suspend.stop_signal); - wait_for_inferior (0); + wait_for_inferior (); } while (tp->suspend.stop_signal != TARGET_SIGNAL_TRAP); inf->control.stop_soon = NO_STOP_QUIETLY; @@ -2227,14 +2273,6 @@ svr4_clear_solib (void) info->debug_loader_name = NULL; } -static void -svr4_free_so (struct so_list *so) -{ - xfree (so->lm_info->lm); - xfree (so->lm_info); -} - - /* Clear any bits of ADDR that wouldn't fit in a target-format data pointer. "Data pointer" here refers to whatever sort of address the dynamic linker uses to manage its sections. At the @@ -2264,9 +2302,9 @@ static void svr4_relocate_section_addresses (struct so_list *so, struct target_section *sec) { - sec->addr = svr4_truncate_ptr (sec->addr + LM_ADDR_CHECK (so, + sec->addr = svr4_truncate_ptr (sec->addr + lm_addr_check (so, sec->bfd)); - sec->endaddr = svr4_truncate_ptr (sec->endaddr + LM_ADDR_CHECK (so, + sec->endaddr = svr4_truncate_ptr (sec->endaddr + lm_addr_check (so, sec->bfd)); } @@ -2337,7 +2375,7 @@ svr4_have_link_map_offsets (void) /* Fetch (and possibly build) an appropriate `struct link_map_offsets' for an ILP32 SVR4 system. */ - + struct link_map_offsets * svr4_ilp32_fetch_link_map_offsets (void) { @@ -2368,7 +2406,7 @@ svr4_ilp32_fetch_link_map_offsets (void) /* Fetch (and possibly build) an appropriate `struct link_map_offsets' for an LP64 SVR4 system. */ - + struct link_map_offsets * svr4_lp64_fetch_link_map_offsets (void) { diff --git a/contrib/gdb-7/gdb/solib-svr4.h b/contrib/gdb-7/gdb/solib-svr4.h index b35f0db602..f9a02c9b50 100644 --- a/contrib/gdb-7/gdb/solib-svr4.h +++ b/contrib/gdb-7/gdb/solib-svr4.h @@ -1,7 +1,6 @@ /* Handle shared libraries for GDB, the GNU Debugger. - Copyright (C) 2000, 2004, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2000, 2004, 2006-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/solib-target.c b/contrib/gdb-7/gdb/solib-target.c index b2d8bc488f..0f3f850a6e 100644 --- a/contrib/gdb-7/gdb/solib-target.c +++ b/contrib/gdb-7/gdb/solib-target.c @@ -1,6 +1,6 @@ /* Definitions for targets which report shared library events. - Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -28,8 +28,6 @@ #include "gdb_string.h" -DEF_VEC_O(CORE_ADDR); - /* Private data for each loaded library. */ struct lm_info { @@ -86,14 +84,14 @@ library_list_start_segment (struct gdb_xml_parser *parser, { VEC(lm_info_p) **list = user_data; struct lm_info *last = VEC_last (lm_info_p, *list); - ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value; + ULONGEST *address_p = xml_find_attribute (attributes, "address")->value; CORE_ADDR address = (CORE_ADDR) *address_p; if (last->section_bases != NULL) gdb_xml_error (parser, _("Library list with both segments and sections")); - VEC_safe_push (CORE_ADDR, last->segment_bases, &address); + VEC_safe_push (CORE_ADDR, last->segment_bases, address); } static void @@ -103,14 +101,14 @@ library_list_start_section (struct gdb_xml_parser *parser, { VEC(lm_info_p) **list = user_data; struct lm_info *last = VEC_last (lm_info_p, *list); - ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value; + ULONGEST *address_p = xml_find_attribute (attributes, "address")->value; CORE_ADDR address = (CORE_ADDR) *address_p; if (last->segment_bases != NULL) gdb_xml_error (parser, _("Library list with both segments and sections")); - VEC_safe_push (CORE_ADDR, last->section_bases, &address); + VEC_safe_push (CORE_ADDR, last->section_bases, address); } /* Handle the start of a element. */ @@ -122,7 +120,7 @@ library_list_start_library (struct gdb_xml_parser *parser, { VEC(lm_info_p) **list = user_data; struct lm_info *item = XZALLOC (struct lm_info); - const char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value; + const char *name = xml_find_attribute (attributes, "name")->value; item->name = xstrdup (name); VEC_safe_push (lm_info_p, *list, item); @@ -150,7 +148,7 @@ library_list_start_list (struct gdb_xml_parser *parser, const struct gdb_xml_element *element, void *user_data, VEC(gdb_xml_value_s) *attributes) { - char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value; + char *version = xml_find_attribute (attributes, "version")->value; if (strcmp (version, "1.0") != 0) gdb_xml_error (parser, @@ -181,17 +179,17 @@ solib_target_free_library_list (void *p) /* The allowed elements and attributes for an XML library list. The root element is a . */ -const struct gdb_xml_attribute segment_attributes[] = { +static const struct gdb_xml_attribute segment_attributes[] = { { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; -const struct gdb_xml_attribute section_attributes[] = { +static const struct gdb_xml_attribute section_attributes[] = { { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; -const struct gdb_xml_element library_children[] = { +static const struct gdb_xml_element library_children[] = { { "segment", segment_attributes, NULL, GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, library_list_start_segment, NULL }, @@ -201,24 +199,24 @@ const struct gdb_xml_element library_children[] = { { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; -const struct gdb_xml_attribute library_attributes[] = { +static const struct gdb_xml_attribute library_attributes[] = { { "name", GDB_XML_AF_NONE, NULL, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; -const struct gdb_xml_element library_list_children[] = { +static const struct gdb_xml_element library_list_children[] = { { "library", library_attributes, library_children, GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL, library_list_start_library, library_list_end_library }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } }; -const struct gdb_xml_attribute library_list_attributes[] = { +static const struct gdb_xml_attribute library_list_attributes[] = { { "version", GDB_XML_AF_NONE, NULL, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; -const struct gdb_xml_element library_list_elements[] = { +static const struct gdb_xml_element library_list_elements[] = { { "library-list", library_list_attributes, library_list_children, GDB_XML_EF_NONE, library_list_start_list, NULL }, { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL } @@ -227,24 +225,20 @@ const struct gdb_xml_element library_list_elements[] = { static VEC(lm_info_p) * solib_target_parse_libraries (const char *library) { - struct gdb_xml_parser *parser; VEC(lm_info_p) *result = NULL; - struct cleanup *before_deleting_result, *back_to; - - back_to = make_cleanup (null_cleanup, NULL); - parser = gdb_xml_create_parser_and_cleanup (_("target library list"), - library_list_elements, &result); - gdb_xml_use_dtd (parser, "library-list.dtd"); - - before_deleting_result = make_cleanup (solib_target_free_library_list, - &result); + struct cleanup *back_to = make_cleanup (solib_target_free_library_list, + &result); - if (gdb_xml_parse (parser, library) == 0) - /* Parsed successfully, don't need to delete the result. */ - discard_cleanups (before_deleting_result); + if (gdb_xml_parse_quick (_("target library list"), "library-list.dtd", + library_list_elements, library, &result) == 0) + { + /* Parsed successfully, keep the result. */ + discard_cleanups (back_to); + return result; + } do_cleanups (back_to); - return result; + return NULL; } #endif @@ -391,7 +385,8 @@ Could not relocate shared library \"%s\": wrong number of ALLOC sections"), gdb_assert (so->addr_low <= so->addr_high); found_range = 1; } - so->lm_info->offsets->offsets[i] = section_bases[bases_index]; + so->lm_info->offsets->offsets[i] + = section_bases[bases_index]; bases_index++; } if (!found_range) @@ -478,7 +473,8 @@ solib_target_in_dynsym_resolve_code (CORE_ADDR pc) struct target_so_ops solib_target_so_ops; -extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */ +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_solib_target; void _initialize_solib_target (void) diff --git a/contrib/gdb-7/gdb/solib-target.h b/contrib/gdb-7/gdb/solib-target.h index 35d5be6b2d..f3e7d74249 100644 --- a/contrib/gdb-7/gdb/solib-target.h +++ b/contrib/gdb-7/gdb/solib-target.h @@ -1,6 +1,6 @@ /* Handle shared libraries for GDB, the GNU Debugger. - Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/solib.c b/contrib/gdb-7/gdb/solib.c index 819eb7dab7..f5917856d1 100644 --- a/contrib/gdb-7/gdb/solib.c +++ b/contrib/gdb-7/gdb/solib.c @@ -1,8 +1,6 @@ /* Handle shared libraries for GDB, the GNU Debugger. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-2003, 2005-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -114,17 +112,10 @@ show_solib_search_path (struct ui_file *file, int from_tty, # define DOS_BASED_FILE_SYSTEM 0 #endif -/* - - GLOBAL FUNCTION - - solib_find -- Find a shared library file. - - SYNOPSIS - - char *solib_find (char *in_pathname, int *fd); - - DESCRIPTION +/* Returns the full pathname of the shared library file, or NULL if + not found. (The pathname is malloc'ed; it needs to be freed by the + caller.) *FD is set to either -1 or an open file handle for the + library. Global variable GDB_SYSROOT is used as a prefix directory to search for shared libraries if they have an absolute path. @@ -146,12 +137,7 @@ show_solib_search_path (struct ui_file *file, int from_tty, * * The last check avoids doing this search when targetting remote * machines since gdb_sysroot will almost always be set. - - RETURNS - - Full pathname of the shared library file, or NULL if not found. - (The pathname is malloc'ed; it needs to be freed by the caller.) - *FD is set to either -1 or an open file handle for the library. */ +*/ char * solib_find (char *in_pathname, int *fd) @@ -254,6 +240,7 @@ solib_find (char *in_pathname, int *fd) if (remote_filename_p (temp_pathname)) { *fd = -1; + do_cleanups (old_chain); return temp_pathname; } @@ -451,33 +438,17 @@ solib_bfd_open (char *pathname) return abfd; } +/* 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 + by the base address at which the shared object was mapped, and then + add the sections to the target's section table. -/* - - LOCAL FUNCTION - - solib_map_sections -- open bfd and build sections for shared lib - - SYNOPSIS - - static int solib_map_sections (struct so_list *so) - - DESCRIPTION - - 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, and then - relocate all the section addresses by the base address at - which the shared object was mapped. - - FIXMES - - In most (all?) cases the shared object file name recorded in the - dynamic linkage tables will be a fully qualified pathname. For + FIXME: In most (all?) cases the shared object file name recorded in + the dynamic linkage tables will be a fully qualified pathname. For cases where it isn't, do we really mimic the systems search mechanism correctly in the below code (particularly the tilde - expansion stuff?). - */ + expansion stuff?). */ static int solib_map_sections (struct so_list *so) @@ -569,17 +540,7 @@ free_so_symbols (struct so_list *so) strcpy (so->so_name, so->so_original_name); } -/* LOCAL FUNCTION - - free_so --- free a `struct so_list' object - - SYNOPSIS - - void free_so (struct so_list *so) - - DESCRIPTION - - Free the storage associated with the `struct so_list' object SO. +/* Free the storage associated with the `struct so_list' object SO. If we have opened a BFD for SO, close it. The caller is responsible for removing SO from whatever list it is @@ -648,7 +609,8 @@ solib_read_symbols (struct so_list *so, int flags) sap = build_section_addr_info_from_section_table (so->sections, so->sections_end); so->objfile = symbol_file_add_from_bfd (so->abfd, - flags, sap, OBJF_SHARED); + flags, sap, OBJF_SHARED, + NULL); so->objfile->addr_low = so->addr_low; free_section_addr_info (sap); } @@ -669,13 +631,21 @@ solib_read_symbols (struct so_list *so, int flags) return 0; } -/* LOCAL FUNCTION +/* Return 1 if KNOWN->objfile is used by any other so_list object in the + SO_LIST_HEAD list. Return 0 otherwise. */ - update_solib_list --- synchronize GDB's shared object list with inferior's +static int +solib_used (const struct so_list *const known) +{ + const struct so_list *pivot; - SYNOPSIS + for (pivot = so_list_head; pivot != NULL; pivot = pivot->next) + if (pivot != known && pivot->objfile == known->objfile) + return 1; + return 0; +} - void update_solib_list (int from_tty, struct target_ops *TARGET) +/* Synchronize GDB's shared object list with inferior's. Extract the list of currently loaded shared objects from the inferior, and compare it with the list of shared objects currently @@ -791,7 +761,8 @@ update_solib_list (int from_tty, struct target_ops *target) *gdb_link = gdb->next; /* Unless the user loaded it explicitly, free SO's objfile. */ - if (gdb->objfile && ! (gdb->objfile->flags & OBJF_USERLOADED)) + if (gdb->objfile && ! (gdb->objfile->flags & OBJF_USERLOADED) + && !solib_used (gdb)) free_objfile (gdb->objfile); /* Some targets' section tables might be referring to @@ -886,18 +857,7 @@ libpthread_solib_p (struct so_list *so) return libpthread_name_p (so->so_name); } -/* GLOBAL FUNCTION - - solib_add -- read in symbol info for newly added shared libraries - - SYNOPSIS - - void solib_add (char *pattern, int from_tty, struct target_ops - *TARGET, int readsyms) - - DESCRIPTION - - Read in symbolic information for any shared objects whose names +/* Read in symbolic information for any shared objects whose names match PATTERN. (If we've already read a shared object's symbol info, leave it alone.) If PATTERN is zero, read them all. @@ -912,6 +872,8 @@ solib_add (char *pattern, int from_tty, { struct so_list *gdb; + current_program_space->solib_add_generation++; + if (pattern) { char *re_err = re_comp (pattern); @@ -978,23 +940,10 @@ solib_add (char *pattern, int from_tty, } } - -/* - - LOCAL FUNCTION - - info_sharedlibrary_command -- code for "info sharedlibrary" - - SYNOPSIS - - static void info_sharedlibrary_command () - - DESCRIPTION - - Walk through the shared library list and print information - about each attached library matching PATTERN. If PATTERN is elided, - print them all. - */ +/* Implement the "info sharedlibrary" command. Walk through the + shared library list and print information about each attached + library matching PATTERN. If PATTERN is elided, print them + all. */ static void info_sharedlibrary_command (char *pattern, int from_tty) @@ -1005,6 +954,7 @@ info_sharedlibrary_command (char *pattern, int from_tty) int nr_libs; struct cleanup *table_cleanup; struct gdbarch *gdbarch = target_gdbarch; + struct ui_out *uiout = current_uiout; if (pattern) { @@ -1120,27 +1070,16 @@ solib_contains_address_p (const struct so_list *const solib, return 0; } -/* - - GLOBAL FUNCTION - - solib_name_from_address -- if an address is in a shared lib, return - its name. - - SYNOPSIS - - char * solib_name_from_address (CORE_ADDR address) +/* If ADDRESS is in a shared lib in program space PSPACE, return its + name. - DESCRIPTION - - Provides a hook for other gdb routines to discover whether or - not a particular address is within the mapped address space of - a shared library. + Provides a hook for other gdb routines to discover whether or not a + particular address is within the mapped address space of a shared + library. For example, this routine is called at one point to disable breakpoints which are in shared libraries that are not currently - mapped in. - */ + mapped in. */ char * solib_name_from_address (struct program_space *pspace, CORE_ADDR address) @@ -1216,20 +1155,10 @@ clear_solib (void) ops->clear_solib (); } -/* GLOBAL FUNCTION - - solib_create_inferior_hook -- shared library startup support - - SYNOPSIS - - void solib_create_inferior_hook (int from_tty) - - DESCRIPTION - - When gdb starts up the inferior, it nurses it along (through the - shell) until it is ready to execute it's first instruction. At this - point, this function gets called via expansion of the macro - SOLIB_CREATE_INFERIOR_HOOK. */ +/* Shared library startup support. When GDB starts up the inferior, + it nurses it along (through the shell) until it is ready to execute + its first instruction. At this point, this function gets + called. */ void solib_create_inferior_hook (int from_tty) @@ -1239,21 +1168,8 @@ solib_create_inferior_hook (int from_tty) ops->solib_create_inferior_hook (from_tty); } -/* GLOBAL FUNCTION - - in_solib_dynsym_resolve_code -- check to see if an address is in - dynamic loader's dynamic symbol - resolution code - - SYNOPSIS - - int in_solib_dynsym_resolve_code (CORE_ADDR pc) - - DESCRIPTION - - Determine if PC is in the dynamic linker's symbol resolution - code. Return 1 if so, 0 otherwise. -*/ +/* Check to see if an address is in the dynamic loader's dynamic + symbol resolution code. Return 1 if so, 0 otherwise. */ int in_solib_dynsym_resolve_code (CORE_ADDR pc) @@ -1263,19 +1179,7 @@ in_solib_dynsym_resolve_code (CORE_ADDR pc) return ops->in_dynsym_resolve_code (pc); } -/* - - LOCAL FUNCTION - - sharedlibrary_command -- handle command to explicitly add library - - SYNOPSIS - - static void sharedlibrary_command (char *args, int from_tty) - - DESCRIPTION - - */ +/* Implements the "sharedlibrary" command. */ static void sharedlibrary_command (char *args, int from_tty) @@ -1284,14 +1188,7 @@ sharedlibrary_command (char *args, int from_tty) solib_add (args, from_tty, (struct target_ops *) 0, 1); } -/* LOCAL FUNCTION - - no_shared_libraries -- handle command to explicitly discard symbols - from shared libraries. - - DESCRIPTION - - Implements the command "nosharedlibrary", which discards symbols +/* 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. */ @@ -1341,7 +1238,8 @@ reload_shared_libraries_1 (int from_tty) || (found_pathname != NULL && filename_cmp (found_pathname, so->so_name) != 0)) { - if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED)) + if (so->objfile && ! (so->objfile->flags & OBJF_USERLOADED) + && !solib_used (so)) free_objfile (so->objfile); remove_target_sections (so->abfd); free_so_symbols (so); @@ -1452,6 +1350,102 @@ solib_global_lookup (const struct objfile *objfile, return NULL; } +/* Lookup the value for a specific symbol from dynamic symbol table. Look + up symbol from ABFD. MATCH_SYM is a callback function to determine + whether to pick up a symbol. DATA is the input of this callback + function. Return NULL if symbol is not found. */ + +CORE_ADDR +gdb_bfd_lookup_symbol_from_symtab (bfd *abfd, + int (*match_sym) (asymbol *, void *), + void *data) +{ + long storage_needed = bfd_get_symtab_upper_bound (abfd); + CORE_ADDR symaddr = 0; + + if (storage_needed > 0) + { + unsigned int i; + + asymbol **symbol_table = (asymbol **) xmalloc (storage_needed); + struct cleanup *back_to = make_cleanup (xfree, symbol_table); + unsigned int number_of_symbols = + bfd_canonicalize_symtab (abfd, symbol_table); + + for (i = 0; i < number_of_symbols; i++) + { + asymbol *sym = *symbol_table++; + + if (match_sym (sym, data)) + { + /* BFD symbols are section relative. */ + symaddr = sym->value + sym->section->vma; + break; + } + } + do_cleanups (back_to); + } + + return symaddr; +} + +/* Lookup the value for a specific symbol from symbol table. Look up symbol + from ABFD. MATCH_SYM is a callback function to determine whether to pick + up a symbol. DATA is the input of this callback function. Return NULL + if symbol is not found. */ + +static CORE_ADDR +bfd_lookup_symbol_from_dyn_symtab (bfd *abfd, + int (*match_sym) (asymbol *, void *), + void *data) +{ + long storage_needed = bfd_get_dynamic_symtab_upper_bound (abfd); + CORE_ADDR symaddr = 0; + + if (storage_needed > 0) + { + unsigned int i; + asymbol **symbol_table = (asymbol **) xmalloc (storage_needed); + struct cleanup *back_to = make_cleanup (xfree, symbol_table); + unsigned int number_of_symbols = + bfd_canonicalize_dynamic_symtab (abfd, symbol_table); + + for (i = 0; i < number_of_symbols; i++) + { + asymbol *sym = *symbol_table++; + + if (match_sym (sym, data)) + { + /* BFD symbols are section relative. */ + symaddr = sym->value + sym->section->vma; + break; + } + } + do_cleanups (back_to); + } + return symaddr; +} + +/* Lookup the value for a specific symbol from symbol table and dynamic + symbol table. Look up symbol from ABFD. MATCH_SYM is a callback + function to determine whether to pick up a symbol. DATA is the + input of this callback function. Return NULL if symbol is not + found. */ + +CORE_ADDR +gdb_bfd_lookup_symbol (bfd *abfd, + int (*match_sym) (asymbol *, void *), + void *data) +{ + CORE_ADDR symaddr = gdb_bfd_lookup_symbol_from_symtab (abfd, match_sym, data); + + /* On FreeBSD, the dynamic linker is stripped by default. So we'll + have to check the dynamic string table too. */ + if (symaddr == 0) + symaddr = bfd_lookup_symbol_from_dyn_symtab (abfd, match_sym, data); + + return symaddr; +} extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */ diff --git a/contrib/gdb-7/gdb/solib.h b/contrib/gdb-7/gdb/solib.h index c473d85578..2c7f4d9256 100644 --- a/contrib/gdb-7/gdb/solib.h +++ b/contrib/gdb-7/gdb/solib.h @@ -1,7 +1,7 @@ /* Shared library declarations for GDB, the GNU Debugger. - Copyright (C) 1992, 1993, 1995, 1998, 1999, 2000, 2001, 2003, 2005, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1992-1993, 1995, 1998-2001, 2003, 2005, 2007-2012 Free + Software Foundation, Inc. This file is part of GDB. @@ -78,4 +78,17 @@ extern void set_solib_ops (struct gdbarch *gdbarch, extern int libpthread_name_p (const char *name); +/* Look up symbol from both symbol table and dynamic string table. */ + +extern CORE_ADDR gdb_bfd_lookup_symbol (bfd *abfd, + int (*match_sym) (asymbol *, void *), + void *data); + +/* Look up symbol from symbol table. */ + +extern CORE_ADDR bfd_lookup_symbol_from_symtab (bfd *abfd, + int (*match_sym) (asymbol *, + void *), + void *data); + #endif /* SOLIB_H */ diff --git a/contrib/gdb-7/gdb/solist.h b/contrib/gdb-7/gdb/solist.h index dad11be46f..7413e3b845 100644 --- a/contrib/gdb-7/gdb/solist.h +++ b/contrib/gdb-7/gdb/solist.h @@ -1,6 +1,6 @@ /* Shared library declarations for GDB, the GNU Debugger. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, - 2001, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1990-1996, 1998-2001, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -96,14 +96,26 @@ struct target_so_ops /* Target dependent code to run after child process fork. */ void (*solib_create_inferior_hook) (int from_tty); - /* Do additional symbol handling, lookup, etc. after symbols - for a shared object have been loaded. */ + /* Do additional symbol handling, lookup, etc. after symbols for a + shared object have been loaded in the usual way. This is + called to do any system specific symbol handling that might be + needed. */ void (*special_symbol_handling) (void); - /* Construct a list of the currently loaded shared objects. */ + /* Construct a list of the currently loaded shared objects. This + list does not include an entry for the main executable file. + + Note that we only gather information directly available from the + inferior --- we don't examine any of the shared library files + themselves. The declaration of `struct so_list' says which fields + we provide values for. */ struct so_list *(*current_sos) (void); - /* Find, open, and read the symbols for the main executable. */ + /* Find, open, and read the symbols for the main executable. If + FROM_TTYP dereferences to a non-zero integer, allow messages to + be printed. This parameter is a pointer rather than an int + because open_symbol_file_object is called via catch_errors and + catch_errors requires a pointer argument. */ int (*open_symbol_file_object) (void *from_ttyp); /* Determine if PC lies in the dynamic symbol resolution code of diff --git a/contrib/gdb-7/gdb/source.c b/contrib/gdb-7/gdb/source.c index 5710f14d3d..909f2523b7 100644 --- a/contrib/gdb-7/gdb/source.c +++ b/contrib/gdb-7/gdb/source.c @@ -1,7 +1,5 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -245,7 +243,7 @@ select_source_symtab (struct symtab *s) if one exists. */ if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0)) { - sals = decode_line_spec (main_name (), 1); + sals = decode_line_spec (main_name (), DECODE_LINE_FUNFIRSTLINE); sal = sals.sals[0]; xfree (sals.sals); current_source_pspace = sal.pspace; @@ -335,6 +333,32 @@ show_directories_command (struct ui_file *file, int from_tty, show_directories_1 (NULL, from_tty); } +/* Forget line positions and file names for the symtabs in a + particular objfile. */ + +void +forget_cached_source_info_for_objfile (struct objfile *objfile) +{ + struct symtab *s; + + ALL_OBJFILE_SYMTABS (objfile, s) + { + if (s->line_charpos != NULL) + { + xfree (s->line_charpos); + s->line_charpos = NULL; + } + if (s->fullname != NULL) + { + xfree (s->fullname); + s->fullname = NULL; + } + } + + if (objfile->sf) + objfile->sf->qf->forget_cached_source_info (objfile); +} + /* Forget what we learned about line positions in source files, and which directories contain them; must check again now since files may be found in a different directory now. */ @@ -343,28 +367,12 @@ void forget_cached_source_info (void) { struct program_space *pspace; - struct symtab *s; struct objfile *objfile; ALL_PSPACES (pspace) ALL_PSPACE_OBJFILES (pspace, objfile) { - for (s = objfile->symtabs; s != NULL; s = s->next) - { - if (s->line_charpos != NULL) - { - xfree (s->line_charpos); - s->line_charpos = NULL; - } - if (s->fullname != NULL) - { - xfree (s->fullname); - s->fullname = NULL; - } - } - - if (objfile->sf) - objfile->sf->qf->forget_cached_source_info (objfile); + forget_cached_source_info_for_objfile (objfile); } last_source_visited = NULL; @@ -1095,6 +1103,7 @@ open_source_file (struct symtab *s) If this function fails to find the file that this symtab represents, NULL will be returned and s->fullname will be set to NULL. */ + char * symtab_to_fullname (struct symtab *s) { @@ -1103,8 +1112,12 @@ symtab_to_fullname (struct symtab *s) if (!s) return NULL; - /* Don't check s->fullname here, the file could have been - deleted/moved/..., look for it again. */ + /* Use cached copy if we have it. + We rely on forget_cached_source_info being called appropriately + to handle cases like the file being moved. */ + if (s->fullname) + return s->fullname; + r = find_and_open_source (s->filename, s->dirname, &s->fullname); if (r >= 0) @@ -1145,30 +1158,6 @@ find_source_lines (struct symtab *s, int desc) if (mtime && mtime < st.st_mtime) warning (_("Source file is more recent than executable.")); -#ifdef LSEEK_NOT_LINEAR - { - char c; - - /* Have to read it byte by byte to find out where the chars live. */ - - line_charpos[0] = lseek (desc, 0, SEEK_CUR); - nlines = 1; - while (myread (desc, &c, 1) > 0) - { - if (c == '\n') - { - if (nlines == lines_allocated) - { - lines_allocated *= 2; - line_charpos = - (int *) xrealloc ((char *) line_charpos, - sizeof (int) * lines_allocated); - } - line_charpos[nlines++] = lseek (desc, 0, SEEK_CUR); - } - } - } -#else /* lseek linear. */ { struct cleanup *old_cleanups; @@ -1207,53 +1196,13 @@ find_source_lines (struct symtab *s, int desc) } do_cleanups (old_cleanups); } -#endif /* lseek linear. */ + s->nlines = nlines; s->line_charpos = (int *) xrealloc ((char *) line_charpos, nlines * sizeof (int)); } -/* Return the character position of a line LINE in symtab S. - Return 0 if anything is invalid. */ - -#if 0 /* Currently unused */ - -int -source_line_charpos (struct symtab *s, int line) -{ - if (!s) - return 0; - if (!s->line_charpos || line <= 0) - return 0; - if (line > s->nlines) - line = s->nlines; - return s->line_charpos[line - 1]; -} - -/* Return the line number of character position POS in symtab S. */ - -int -source_charpos_line (struct symtab *s, int chr) -{ - int line = 0; - int *lnp; - - if (s == 0 || s->line_charpos == 0) - return 0; - lnp = s->line_charpos; - /* Files are usually short, so sequential search is Ok. */ - while (line < s->nlines && *lnp <= chr) - { - line++; - lnp++; - } - if (line >= s->nlines) - line = s->nlines; - return line; -} - -#endif /* 0 */ /* Get full pathname and line number positions for a symtab. @@ -1330,6 +1279,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) FILE *stream; int nlines = stopline - line; struct cleanup *cleanup; + struct ui_out *uiout = current_uiout; /* Regardless of whether we can open the file, set current_source_symtab. */ current_source_symtab = s; @@ -1370,10 +1320,12 @@ print_source_lines_base (struct symtab *s, int line, int stopline, int noerror) print_sys_errmsg (name, errno); } else - ui_out_field_int (uiout, "line", line); - ui_out_text (uiout, "\tin "); - ui_out_field_string (uiout, "file", s->filename); - ui_out_text (uiout, "\n"); + { + ui_out_field_int (uiout, "line", line); + ui_out_text (uiout, "\tin "); + ui_out_field_string (uiout, "file", s->filename); + ui_out_text (uiout, "\n"); + } return; } @@ -1461,12 +1413,14 @@ line_info (char *arg, int from_tty) struct symtab_and_line sal; CORE_ADDR start_pc, end_pc; int i; + struct cleanup *cleanups; init_sal (&sal); /* initialize to zeroes */ if (arg == 0) { sal.symtab = current_source_symtab; + sal.pspace = current_program_space; sal.line = last_line_listed; sals.nelts = 1; sals.sals = (struct symtab_and_line *) @@ -1475,16 +1429,20 @@ line_info (char *arg, int from_tty) } else { - sals = decode_line_spec_1 (arg, 0); + sals = decode_line_spec_1 (arg, DECODE_LINE_LIST_MODE); dont_repeat (); } + cleanups = make_cleanup (xfree, sals.sals); + /* C++ More than one line may have been specified, as when the user specifies an overloaded function name. Print info on them all. */ for (i = 0; i < sals.nelts; i++) { sal = sals.sals[i]; + if (sal.pspace != current_program_space) + continue; if (sal.symtab == 0) { @@ -1550,7 +1508,7 @@ line_info (char *arg, int from_tty) printf_filtered (_("Line number %d is out of range for \"%s\".\n"), sal.line, sal.symtab->filename); } - xfree (sals.sals); + do_cleanups (cleanups); } /* Commands to search the source file for a regexp. */ diff --git a/contrib/gdb-7/gdb/source.h b/contrib/gdb-7/gdb/source.h index 501d0b36b9..3ee8e532bb 100644 --- a/contrib/gdb-7/gdb/source.h +++ b/contrib/gdb-7/gdb/source.h @@ -1,6 +1,5 @@ /* List lines of source files for GDB, the GNU debugger. - Copyright (C) 1999, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1999, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/stabsread.c b/contrib/gdb-7/gdb/stabsread.c index c7d8a6c474..865bac8530 100644 --- a/contrib/gdb-7/gdb/stabsread.c +++ b/contrib/gdb-7/gdb/stabsread.c @@ -1,8 +1,6 @@ /* Support routines for decoding "stabs" debugging information format. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -41,6 +39,7 @@ #include "buildsym.h" #include "complaints.h" #include "demangle.h" +#include "gdb-demangle.h" #include "language.h" #include "doublest.h" #include "cp-abi.h" @@ -729,7 +728,7 @@ define_symbol (CORE_ADDR valu, char *string, int desc, int type, SYMBOL_SET_NAMES (sym, string, p - string, 1, objfile); if (SYMBOL_LANGUAGE (sym) == language_cplus) - cp_scan_for_anonymous_namespaces (sym); + cp_scan_for_anonymous_namespaces (sym, objfile); } p++; @@ -2236,7 +2235,7 @@ rs6000_builtin_type (int typenum, struct objfile *objfile) /* Replace *OLD_NAME with the method name portion of PHYSNAME. */ static void -update_method_name_from_physname (char **old_name, char *physname) +update_method_name_from_physname (char **old_name, const char *physname) { char *method_name; diff --git a/contrib/gdb-7/gdb/stabsread.h b/contrib/gdb-7/gdb/stabsread.h index 92523a9a9a..071552ea1d 100644 --- a/contrib/gdb-7/gdb/stabsread.h +++ b/contrib/gdb-7/gdb/stabsread.h @@ -1,7 +1,6 @@ /* Include file for stabs debugging format support functions. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1986-1997, 1999-2003, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. diff --git a/contrib/gdb-7/gdb/stack.c b/contrib/gdb-7/gdb/stack.c index 0888b69d3f..b15b5fcfa1 100644 --- a/contrib/gdb-7/gdb/stack.c +++ b/contrib/gdb-7/gdb/stack.c @@ -1,8 +1,6 @@ /* Print and select stack frames for GDB, the GNU debugger. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2005, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -47,6 +45,7 @@ #include "cp-support.h" #include "disasm.h" #include "inline-frame.h" +#include "linespec.h" #include "gdb_assert.h" #include @@ -57,13 +56,36 @@ void (*deprecated_selected_frame_level_changed_hook) (int); -/* The possible choices of "set print frame-arguments, and the value +/* The possible choices of "set print frame-arguments", and the value of this setting. */ static const char *print_frame_arguments_choices[] = {"all", "scalars", "none", NULL}; static const char *print_frame_arguments = "scalars"; +/* The possible choices of "set print entry-values", and the value + of this setting. */ + +const char print_entry_values_no[] = "no"; +const char print_entry_values_only[] = "only"; +const char print_entry_values_preferred[] = "preferred"; +const char print_entry_values_if_needed[] = "if-needed"; +const char print_entry_values_both[] = "both"; +const char print_entry_values_compact[] = "compact"; +const char print_entry_values_default[] = "default"; +static const char *print_entry_values_choices[] = +{ + print_entry_values_no, + print_entry_values_only, + print_entry_values_preferred, + print_entry_values_if_needed, + print_entry_values_both, + print_entry_values_compact, + print_entry_values_default, + NULL +}; +const char *print_entry_values = print_entry_values_default; + /* Prototypes for local functions. */ static void print_frame_local_vars (struct frame_info *, int, @@ -73,6 +95,12 @@ static void print_frame (struct frame_info *frame, int print_level, enum print_what print_what, int print_args, struct symtab_and_line sal); +static void set_last_displayed_sal (int valid, + struct program_space *pspace, + CORE_ADDR addr, + struct symtab *symtab, + int line); + /* Zero means do things normally; we are interacting directly with the user. One means print the full filename and linenumber when a frame is printed, and do so in a format emacs18/emacs19.22 can @@ -80,28 +108,15 @@ static void print_frame (struct frame_info *frame, int print_level, cases and in a slightly different syntax. */ int annotation_level = 0; - - -struct print_stack_frame_args -{ - struct frame_info *frame; - int print_level; - enum print_what print_what; - int print_args; -}; - -/* Show or print the frame arguments; stub for catch_errors. */ - -static int -print_stack_frame_stub (void *args) -{ - struct print_stack_frame_args *p = args; - int center = (p->print_what == SRC_LINE || p->print_what == SRC_AND_LOC); - print_frame_info (p->frame, p->print_level, p->print_what, p->print_args); - set_current_sal_from_frame (p->frame, center); - return 0; -} +/* These variables hold the last symtab and line we displayed to the user. + * This is where we insert a breakpoint or a skiplist entry by default. */ +static int last_displayed_sal_valid = 0; +static struct program_space *last_displayed_pspace = 0; +static CORE_ADDR last_displayed_addr = 0; +static struct symtab *last_displayed_symtab = 0; +static int last_displayed_line = 0; + /* Return 1 if we should display the address in addition to the location, because we are in the middle of a statement. */ @@ -137,26 +152,20 @@ void print_stack_frame (struct frame_info *frame, int print_level, enum print_what print_what) { - struct print_stack_frame_args args; + volatile struct gdb_exception e; - args.frame = frame; - args.print_level = print_level; - args.print_what = print_what; /* For mi, alway print location and address. */ - args.print_what = ui_out_is_mi_like_p (uiout) ? LOC_AND_ADDRESS : print_what; - args.print_args = 1; + if (ui_out_is_mi_like_p (current_uiout)) + print_what = LOC_AND_ADDRESS; - catch_errors (print_stack_frame_stub, &args, "", RETURN_MASK_ERROR); -} - -struct print_args_args -{ - struct symbol *func; - struct frame_info *frame; - struct ui_file *stream; -}; + TRY_CATCH (e, RETURN_MASK_ERROR) + { + int center = (print_what == SRC_LINE || print_what == SRC_AND_LOC); -static int print_args_stub (void *args); + print_frame_info (frame, print_level, print_what, 1 /* print_args */); + set_current_sal_from_frame (frame, center); + } +} /* Print nameless arguments of frame FRAME on STREAM, where START is the offset of the first nameless argument, and NUM is the number of @@ -189,6 +198,286 @@ print_frame_nameless_args (struct frame_info *frame, long start, int num, } } +/* Print single argument of inferior function. ARG must be already + read in. + + Errors are printed as if they would be the parameter value. Use zeroed ARG + iff it should not be printed accoring to user settings. */ + +static void +print_frame_arg (const struct frame_arg *arg) +{ + struct ui_out *uiout = current_uiout; + volatile struct gdb_exception except; + struct cleanup *old_chain; + struct ui_stream *stb; + + stb = ui_out_stream_new (uiout); + old_chain = make_cleanup_ui_out_stream_delete (stb); + + gdb_assert (!arg->val || !arg->error); + gdb_assert (arg->entry_kind == print_entry_values_no + || arg->entry_kind == print_entry_values_only + || (!ui_out_is_mi_like_p (uiout) + && arg->entry_kind == print_entry_values_compact)); + + annotate_arg_begin (); + + make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (arg->sym), + SYMBOL_LANGUAGE (arg->sym), DMGL_PARAMS | DMGL_ANSI); + if (arg->entry_kind == print_entry_values_compact) + { + /* It is OK to provide invalid MI-like stream as with + PRINT_ENTRY_VALUE_COMPACT we never use MI. */ + fputs_filtered ("=", stb->stream); + + fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (arg->sym), + SYMBOL_LANGUAGE (arg->sym), + DMGL_PARAMS | DMGL_ANSI); + } + if (arg->entry_kind == print_entry_values_only + || arg->entry_kind == print_entry_values_compact) + fputs_filtered ("@entry", stb->stream); + ui_out_field_stream (uiout, "name", stb); + annotate_arg_name_end (); + ui_out_text (uiout, "="); + + if (!arg->val && !arg->error) + ui_out_text (uiout, "..."); + else + { + if (arg->error) + except.message = arg->error; + else + { + /* TRY_CATCH has two statements, wrap it in a block. */ + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + const struct language_defn *language; + struct value_print_options opts; + + /* Avoid value_print because it will deref ref parameters. We + just want to print their addresses. Print ??? for args whose + address we do not know. We pass 2 as "recurse" to val_print + because our standard indentation here is 4 spaces, and + val_print indents 2 for each recurse. */ + + annotate_arg_value (value_type (arg->val)); + + /* Use the appropriate language to display our symbol, unless the + user forced the language to a specific language. */ + if (language_mode == language_mode_auto) + language = language_def (SYMBOL_LANGUAGE (arg->sym)); + else + language = current_language; + + get_raw_print_options (&opts); + opts.deref_ref = 1; + + /* True in "summary" mode, false otherwise. */ + opts.summary = !strcmp (print_frame_arguments, "scalars"); + + common_val_print (arg->val, stb->stream, 2, &opts, language); + } + } + if (except.message) + fprintf_filtered (stb->stream, _(""), + except.message); + } + + ui_out_field_stream (uiout, "value", stb); + + /* Aleo invoke ui_out_tuple_end. */ + do_cleanups (old_chain); + + annotate_arg_end (); +} + +/* Read in inferior function parameter SYM at FRAME into ARGP. Caller is + responsible for xfree of ARGP->ERROR. This function never throws an + exception. */ + +void +read_frame_arg (struct symbol *sym, struct frame_info *frame, + struct frame_arg *argp, struct frame_arg *entryargp) +{ + struct value *val = NULL, *entryval = NULL; + char *val_error = NULL, *entryval_error = NULL; + int val_equal = 0; + volatile struct gdb_exception except; + + if (print_entry_values != print_entry_values_only + && print_entry_values != print_entry_values_preferred) + { + TRY_CATCH (except, RETURN_MASK_ERROR) + { + val = read_var_value (sym, frame); + } + if (!val) + { + val_error = alloca (strlen (except.message) + 1); + strcpy (val_error, except.message); + } + } + + if (SYMBOL_CLASS (sym) == LOC_COMPUTED + && print_entry_values != print_entry_values_no + && (print_entry_values != print_entry_values_if_needed + || !val || value_optimized_out (val))) + { + TRY_CATCH (except, RETURN_MASK_ERROR) + { + const struct symbol_computed_ops *ops; + + ops = SYMBOL_COMPUTED_OPS (sym); + entryval = ops->read_variable_at_entry (sym, frame); + } + if (!entryval) + { + entryval_error = alloca (strlen (except.message) + 1); + strcpy (entryval_error, except.message); + } + + if (except.error == NO_ENTRY_VALUE_ERROR + || (entryval && value_optimized_out (entryval))) + { + entryval = NULL; + entryval_error = NULL; + } + + if (print_entry_values == print_entry_values_compact + || print_entry_values == print_entry_values_default) + { + /* For MI do not try to use print_entry_values_compact for ARGP. */ + + if (val && entryval && !ui_out_is_mi_like_p (current_uiout)) + { + unsigned len = TYPE_LENGTH (value_type (val)); + + if (!value_optimized_out (val) && value_lazy (val)) + value_fetch_lazy (val); + if (!value_optimized_out (val) && value_lazy (entryval)) + value_fetch_lazy (entryval); + if (!value_optimized_out (val) + && value_available_contents_eq (val, 0, entryval, 0, len)) + { + /* Initialize it just to avoid a GCC false warning. */ + struct value *val_deref = NULL, *entryval_deref; + + /* DW_AT_GNU_call_site_value does match with the current + value. If it is a reference still try to verify if + dereferenced DW_AT_GNU_call_site_data_value does not + differ. */ + + TRY_CATCH (except, RETURN_MASK_ERROR) + { + unsigned len_deref; + + val_deref = coerce_ref (val); + if (value_lazy (val_deref)) + value_fetch_lazy (val_deref); + len_deref = TYPE_LENGTH (value_type (val_deref)); + + entryval_deref = coerce_ref (entryval); + if (value_lazy (entryval_deref)) + value_fetch_lazy (entryval_deref); + + /* If the reference addresses match but dereferenced + content does not match print them. */ + if (val != val_deref + && value_available_contents_eq (val_deref, 0, + entryval_deref, 0, + len_deref)) + val_equal = 1; + } + + /* Value was not a reference; and its content matches. */ + if (val == val_deref) + val_equal = 1; + /* If the dereferenced content could not be fetched do not + display anything. */ + else if (except.error == NO_ENTRY_VALUE_ERROR) + val_equal = 1; + else if (except.message) + { + entryval_error = alloca (strlen (except.message) + 1); + strcpy (entryval_error, except.message); + } + + if (val_equal) + entryval = NULL; + } + } + + /* Try to remove possibly duplicate error message for ENTRYARGP even + in MI mode. */ + + if (val_error && entryval_error + && strcmp (val_error, entryval_error) == 0) + { + entryval_error = NULL; + + /* Do not se VAL_EQUAL as the same error message may be shown for + the entry value even if no entry values are present in the + inferior. */ + } + } + } + + if (entryval == NULL) + { + if (print_entry_values == print_entry_values_preferred) + { + TRY_CATCH (except, RETURN_MASK_ERROR) + { + val = read_var_value (sym, frame); + } + if (!val) + { + val_error = alloca (strlen (except.message) + 1); + strcpy (val_error, except.message); + } + } + if (print_entry_values == print_entry_values_only + || print_entry_values == print_entry_values_both + || (print_entry_values == print_entry_values_preferred + && (!val || value_optimized_out (val)))) + entryval = allocate_optimized_out_value (SYMBOL_TYPE (sym)); + } + if ((print_entry_values == print_entry_values_compact + || print_entry_values == print_entry_values_if_needed + || print_entry_values == print_entry_values_preferred) + && (!val || value_optimized_out (val)) && entryval != NULL) + { + val = NULL; + val_error = NULL; + } + + argp->sym = sym; + argp->val = val; + argp->error = val_error ? xstrdup (val_error) : NULL; + if (!val && !val_error) + argp->entry_kind = print_entry_values_only; + else if ((print_entry_values == print_entry_values_compact + || print_entry_values == print_entry_values_default) && val_equal) + { + argp->entry_kind = print_entry_values_compact; + gdb_assert (!ui_out_is_mi_like_p (current_uiout)); + } + else + argp->entry_kind = print_entry_values_no; + + entryargp->sym = sym; + entryargp->val = entryval; + entryargp->error = entryval_error ? xstrdup (entryval_error) : NULL; + if (!entryval && !entryval_error) + entryargp->entry_kind = print_entry_values_no; + else + entryargp->entry_kind = print_entry_values_only; +} + /* Print the arguments of frame FRAME on STREAM, given the function FUNC running in that frame (as a symbol), where NUM is the number of arguments according to the stack frame (or -1 if the number of @@ -202,6 +491,7 @@ static void print_frame_args (struct symbol *func, struct frame_info *frame, int num, struct ui_file *stream) { + struct ui_out *uiout = current_uiout; int first = 1; /* Offset of next stack argument beyond the one we have seen that is at the highest offset, or -1 if we haven't come to a stack @@ -224,10 +514,11 @@ print_frame_args (struct symbol *func, struct frame_info *frame, struct block *b = SYMBOL_BLOCK_VALUE (func); struct dict_iterator iter; struct symbol *sym; - struct value *val; ALL_BLOCK_SYMBOLS (b, iter, sym) { + struct frame_arg arg, entryarg; + QUIT; /* Keep track of the highest stack argument offset seen, and @@ -340,58 +631,34 @@ print_frame_args (struct symbol *func, struct frame_info *frame, ui_out_text (uiout, ", "); ui_out_wrap_hint (uiout, " "); - annotate_arg_begin (); - - list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); - fprintf_symbol_filtered (stb->stream, SYMBOL_PRINT_NAME (sym), - SYMBOL_LANGUAGE (sym), - DMGL_PARAMS | DMGL_ANSI); - ui_out_field_stream (uiout, "name", stb); - annotate_arg_name_end (); - ui_out_text (uiout, "="); - - if (print_args) - { - /* Avoid value_print because it will deref ref parameters. - We just want to print their addresses. Print ??? for - args whose address we do not know. We pass 2 as - "recurse" to val_print because our standard indentation - here is 4 spaces, and val_print indents 2 for each - recurse. */ - val = read_var_value (sym, frame); + if (!print_args) + { + memset (&arg, 0, sizeof (arg)); + arg.sym = sym; + arg.entry_kind = print_entry_values_no; + memset (&entryarg, 0, sizeof (entryarg)); + entryarg.sym = sym; + entryarg.entry_kind = print_entry_values_no; + } + else + read_frame_arg (sym, frame, &arg, &entryarg); - annotate_arg_value (val == NULL ? NULL : value_type (val)); - - if (val) - { - const struct language_defn *language; - struct value_print_options opts; - - /* Use the appropriate language to display our symbol, - unless the user forced the language to a specific - language. */ - if (language_mode == language_mode_auto) - language = language_def (SYMBOL_LANGUAGE (sym)); - else - language = current_language; - - get_raw_print_options (&opts); - opts.deref_ref = 0; - opts.summary = summary; - common_val_print (val, stb->stream, 2, &opts, language); - ui_out_field_stream (uiout, "value", stb); - } - else - ui_out_text (uiout, "???"); - } - else - ui_out_text (uiout, "..."); + if (arg.entry_kind != print_entry_values_only) + print_frame_arg (&arg); + if (entryarg.entry_kind != print_entry_values_no) + { + if (arg.entry_kind != print_entry_values_only) + { + ui_out_text (uiout, ", "); + ui_out_wrap_hint (uiout, " "); + } - /* Invoke ui_out_tuple_end. */ - do_cleanups (list_chain); + print_frame_arg (&entryarg); + } - annotate_arg_end (); + xfree (arg.error); + xfree (entryarg.error); first = 0; } @@ -415,26 +682,6 @@ print_frame_args (struct symbol *func, struct frame_info *frame, do_cleanups (old_chain); } -/* Stub for catch_errors. */ - -static int -print_args_stub (void *args) -{ - struct print_args_args *p = args; - struct gdbarch *gdbarch = get_frame_arch (p->frame); - int numargs; - - if (gdbarch_frame_num_args_p (gdbarch)) - { - numargs = gdbarch_frame_num_args (gdbarch, p->frame); - gdb_assert (numargs >= 0); - } - else - numargs = -1; - print_frame_args (p->func, p->frame, numargs, p->stream); - return 0; -} - /* Set the current source and line to the location given by frame FRAME, if possible. When CENTER is true, adjust so the relevant line is in the center of the next 'list'. */ @@ -472,26 +719,6 @@ show_disassemble_next_line (struct ui_file *file, int from_tty, value); } -/* Show assembly codes; stub for catch_errors. */ - -struct gdb_disassembly_stub_args -{ - struct gdbarch *gdbarch; - int how_many; - CORE_ADDR low; - CORE_ADDR high; -}; - -static void -gdb_disassembly_stub (void *args) -{ - struct gdb_disassembly_stub_args *p = args; - - gdb_disassembly (p->gdbarch, uiout, 0, - DISASSEMBLY_RAW_INSN, p->how_many, - p->low, p->high); -} - /* Use TRY_CATCH to catch the exception from the gdb_disassembly because it will be broken by filter sometime. */ @@ -500,24 +727,23 @@ do_gdb_disassembly (struct gdbarch *gdbarch, int how_many, CORE_ADDR low, CORE_ADDR high) { volatile struct gdb_exception exception; - struct gdb_disassembly_stub_args args; - args.gdbarch = gdbarch; - args.how_many = how_many; - args.low = low; - args.high = high; - TRY_CATCH (exception, RETURN_MASK_ALL) + TRY_CATCH (exception, RETURN_MASK_ERROR) { - gdb_disassembly_stub (&args); + gdb_disassembly (gdbarch, current_uiout, 0, + DISASSEMBLY_RAW_INSN, how_many, + low, high); + } + if (exception.reason < 0) + { + /* If an exception was thrown while doing the disassembly, print + the error message, to give the user a clue of what happened. */ + exception_print (gdb_stderr, exception); } - /* If an exception was thrown while doing the disassembly, print - the error message, to give the user a clue of what happened. */ - if (exception.reason == RETURN_ERROR) - exception_print (gdb_stderr, exception); } /* Print information about frame FRAME. The output is format according - to PRINT_LEVEL and PRINT_WHAT and PRINT ARGS. The meaning of + to PRINT_LEVEL and PRINT_WHAT and PRINT_ARGS. The meaning of PRINT_WHAT is: SRC_LINE: Print only source line. @@ -535,6 +761,7 @@ print_frame_info (struct frame_info *frame, int print_level, struct symtab_and_line sal; int source_print; int location_print; + struct ui_out *uiout = current_uiout; if (get_frame_type (frame) == DUMMY_FRAME || get_frame_type (frame) == SIGTRAMP_FRAME @@ -658,9 +885,9 @@ print_frame_info (struct frame_info *frame, int print_level, CORE_ADDR pc; if (get_frame_pc_if_available (frame, &pc)) - set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line); + set_last_displayed_sal (1, sal.pspace, pc, sal.symtab, sal.line); else - set_default_breakpoint (0, 0, 0, 0, 0); + set_last_displayed_sal (0, 0, 0, 0, 0); } annotate_frame_end (); @@ -668,6 +895,106 @@ print_frame_info (struct frame_info *frame, int print_level, gdb_flush (gdb_stdout); } +/* Remember the last symtab and line we displayed, which we use e.g. + * as the place to put a breakpoint when the `break' command is + * invoked with no arguments. */ + +static void +set_last_displayed_sal (int valid, struct program_space *pspace, + CORE_ADDR addr, struct symtab *symtab, + int line) +{ + last_displayed_sal_valid = valid; + last_displayed_pspace = pspace; + last_displayed_addr = addr; + last_displayed_symtab = symtab; + last_displayed_line = line; +} + +/* Forget the last sal we displayed. */ + +void +clear_last_displayed_sal (void) +{ + last_displayed_sal_valid = 0; + last_displayed_pspace = 0; + last_displayed_addr = 0; + last_displayed_symtab = 0; + last_displayed_line = 0; +} + +/* Is our record of the last sal we displayed valid? If not, + * the get_last_displayed_* functions will return NULL or 0, as + * appropriate. */ + +int +last_displayed_sal_is_valid (void) +{ + return last_displayed_sal_valid; +} + +/* Get the pspace of the last sal we displayed, if it's valid. */ + +struct program_space * +get_last_displayed_pspace (void) +{ + if (last_displayed_sal_valid) + return last_displayed_pspace; + return 0; +} + +/* Get the address of the last sal we displayed, if it's valid. */ + +CORE_ADDR +get_last_displayed_addr (void) +{ + if (last_displayed_sal_valid) + return last_displayed_addr; + return 0; +} + +/* Get the symtab of the last sal we displayed, if it's valid. */ + +struct symtab* +get_last_displayed_symtab (void) +{ + if (last_displayed_sal_valid) + return last_displayed_symtab; + return 0; +} + +/* Get the line of the last sal we displayed, if it's valid. */ + +int +get_last_displayed_line (void) +{ + if (last_displayed_sal_valid) + return last_displayed_line; + return 0; +} + +/* Get the last sal we displayed, if it's valid. */ + +void +get_last_displayed_sal (struct symtab_and_line *sal) +{ + if (last_displayed_sal_valid) + { + sal->pspace = last_displayed_pspace; + sal->pc = last_displayed_addr; + sal->symtab = last_displayed_symtab; + sal->line = last_displayed_line; + } + else + { + sal->pspace = 0; + sal->pc = 0; + sal->symtab = 0; + sal->line = 0; + } +} + + /* Attempt to obtain the FUNNAME, FUNLANG and optionally FUNCP of the function corresponding to FRAME. */ @@ -767,6 +1094,7 @@ print_frame (struct frame_info *frame, int print_level, struct symtab_and_line sal) { struct gdbarch *gdbarch = get_frame_arch (frame); + struct ui_out *uiout = current_uiout; char *funname = NULL; enum language funlang = language_unknown; struct ui_stream *stb; @@ -818,14 +1146,24 @@ print_frame (struct frame_info *frame, int print_level, ui_out_text (uiout, " ("); if (print_args) { - struct print_args_args args; + struct gdbarch *gdbarch = get_frame_arch (frame); + int numargs; struct cleanup *args_list_chain; + volatile struct gdb_exception e; - args.frame = frame; - args.func = func; - args.stream = gdb_stdout; + if (gdbarch_frame_num_args_p (gdbarch)) + { + numargs = gdbarch_frame_num_args (gdbarch, frame); + gdb_assert (numargs >= 0); + } + else + numargs = -1; + args_list_chain = make_cleanup_ui_out_list_begin_end (uiout, "args"); - catch_errors (print_args_stub, &args, "", RETURN_MASK_ERROR); + TRY_CATCH (e, RETURN_MASK_ERROR) + { + print_frame_args (func, frame, numargs, gdb_stdout); + } /* FIXME: ARGS must be a list. If one argument is a string it will have " that will not be properly escaped. */ /* Invoke ui_out_tuple_end. */ @@ -1134,6 +1472,8 @@ frame_info (char *addr_exp, int from_tty) printf_filtered (_(" Outermost frame: %s\n"), frame_stop_reason_string (reason)); } + else if (get_frame_type (fi) == TAILCALL_FRAME) + puts_filtered (" tail call frame"); else if (get_frame_type (fi) == INLINE_FRAME) printf_filtered (" inlined into frame %d", frame_relative_level (get_prev_frame (fi))); @@ -1398,36 +1738,17 @@ backtrace_command_1 (char *count_exp, int show_locals, int from_tty) enum unwind_stop_reason reason; reason = get_frame_unwind_stop_reason (trailing); - if (reason > UNWIND_FIRST_ERROR) + if (reason >= UNWIND_FIRST_ERROR) printf_filtered (_("Backtrace stopped: %s\n"), frame_stop_reason_string (reason)); } } -struct backtrace_command_args -{ - char *count_exp; - int show_locals; - int from_tty; -}; - -/* Stub for catch_errors. */ - -static int -backtrace_command_stub (void *data) -{ - struct backtrace_command_args *args = data; - - backtrace_command_1 (args->count_exp, args->show_locals, args->from_tty); - return 0; -} - static void backtrace_command (char *arg, int from_tty) { - struct cleanup *old_chain = NULL; + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); int fulltrace_arg = -1, arglen = 0, argc = 0; - struct backtrace_command_args btargs; if (arg) { @@ -1435,7 +1756,7 @@ backtrace_command (char *arg, int from_tty) int i; argv = gdb_buildargv (arg); - old_chain = make_cleanup_freeargv (argv); + make_cleanup_freeargv (argv); argc = 0; for (i = 0; argv[i]; i++) { @@ -1458,7 +1779,8 @@ backtrace_command (char *arg, int from_tty) if (arglen > 0) { arg = xmalloc (arglen + 1); - memset (arg, 0, arglen + 1); + make_cleanup (xfree, arg); + arg[0] = 0; for (i = 0; i < (argc + 1); i++) { if (i != fulltrace_arg) @@ -1473,27 +1795,15 @@ backtrace_command (char *arg, int from_tty) } } - btargs.count_exp = arg; - btargs.show_locals = (fulltrace_arg >= 0); - btargs.from_tty = from_tty; - catch_errors (backtrace_command_stub, &btargs, "", RETURN_MASK_ERROR); - - if (fulltrace_arg >= 0 && arglen > 0) - xfree (arg); + backtrace_command_1 (arg, fulltrace_arg >= 0 /* show_locals */, from_tty); - if (old_chain) - do_cleanups (old_chain); + do_cleanups (old_chain); } static void backtrace_full_command (char *arg, int from_tty) { - struct backtrace_command_args btargs; - - btargs.count_exp = arg; - btargs.show_locals = 1; - btargs.from_tty = from_tty; - catch_errors (backtrace_command_stub, &btargs, "", RETURN_MASK_ERROR); + backtrace_command_1 (arg, 1 /* show_locals */, from_tty); } @@ -2133,20 +2443,25 @@ func_command (char *arg, int from_tty) int i; int level = 1; struct function_bounds *func_bounds = NULL; + struct cleanup *cleanups; if (arg != NULL) return; frame = parse_frame_specification ("0"); - sals = decode_line_spec (arg, 1); + sals = decode_line_spec (arg, DECODE_LINE_FUNFIRSTLINE); + cleanups = make_cleanup (xfree, sals.sals); func_bounds = (struct function_bounds *) xmalloc ( sizeof (struct function_bounds) * sals.nelts); + make_cleanup (xfree, func_bounds); for (i = 0; (i < sals.nelts && !found); i++) { - if (sals.sals[i].pc == 0 - || find_pc_partial_function (sals.sals[i].pc, NULL, - &func_bounds[i].low, - &func_bounds[i].high) == 0) + if (sals.sals[i].pspace != current_program_space) + func_bounds[i].low = func_bounds[i].high = 0; + else if (sals.sals[i].pc == 0 + || find_pc_partial_function (sals.sals[i].pc, NULL, + &func_bounds[i].low, + &func_bounds[i].high) == 0) { func_bounds[i].low = func_bounds[i].high = 0; } @@ -2165,8 +2480,7 @@ func_command (char *arg, int from_tty) } while (!found && level == 0); - if (func_bounds) - xfree (func_bounds); + do_cleanups (cleanups); if (!found) printf_filtered (_("'%s' not within current stack frame.\n"), arg); @@ -2329,4 +2643,17 @@ source line."), show_disassemble_next_line, &setlist, &showlist); disassemble_next_line = AUTO_BOOLEAN_FALSE; + + add_setshow_enum_cmd ("entry-values", class_stack, + print_entry_values_choices, &print_entry_values, + _("Set printing of function arguments at function " + "entry"), + _("Show printing of function arguments at function " + "entry"), + _("\ +GDB can sometimes determine the values of function arguments at entry,\n\ +in addition to their current values. This option tells GDB whether\n\ +to print the current value, the value at entry (marked as val@entry),\n\ +or both. Note that one or both of these values may be ."), + NULL, NULL, &setprintlist, &showprintlist); } diff --git a/contrib/gdb-7/gdb/stack.h b/contrib/gdb-7/gdb/stack.h index 3cce623f1f..172d7c2f26 100644 --- a/contrib/gdb-7/gdb/stack.h +++ b/contrib/gdb-7/gdb/stack.h @@ -1,7 +1,6 @@ /* Stack manipulation commands, for GDB the GNU Debugger. - Copyright (C) 2003, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -38,4 +37,14 @@ void iterate_over_block_local_vars (struct block *block, iterate_over_block_arg_local_vars_cb cb, void *cb_data); +/* Get or set the last displayed symtab and line, which is, e.g. where we set a + * breakpoint when `break' is supplied with no arguments. */ +void clear_last_displayed_sal (void); +int last_displayed_sal_is_valid (void); +struct program_space* get_last_displayed_pspace (void); +CORE_ADDR get_last_displayed_addr (void); +struct symtab* get_last_displayed_symtab (void); +int get_last_displayed_line (void); +void get_last_displayed_sal (struct symtab_and_line *sal); + #endif /* #ifndef STACK_H */ diff --git a/contrib/gdb-7/gdb/std-operator.def b/contrib/gdb-7/gdb/std-operator.def index 267215c8e8..f2f650b01b 100644 --- a/contrib/gdb-7/gdb/std-operator.def +++ b/contrib/gdb-7/gdb/std-operator.def @@ -1,7 +1,7 @@ /* Standard language operator definitions for GDB, the GNU debugger. - Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1989, 1992, 1994, 2000, 2003, 2005, 2007-2012 + Free Software Foundation, Inc. This file is part of GDB. @@ -139,6 +139,12 @@ OP (OP_DOUBLE) use the selected frame. */ OP (OP_VAR_VALUE) +/* OP_VAR_ENTRY_VALUE takes one struct symbol * in the following element, + followed by another OP_VAR_ENTRY_VALUE, making three exp_elements. + somename@entry may mean parameter value as present at the entry of the + current function. Implemented via DW_OP_GNU_entry_value. */ +OP (OP_VAR_ENTRY_VALUE) + /* OP_LAST is followed by an integer in the next exp_element. The integer is zero for the last value printed, or it is the absolute number of a history element. @@ -277,11 +283,6 @@ OP (STRUCTOP_PTR) It just comes in a tight (OP_THIS, OP_THIS) pair. */ OP (OP_THIS) -/* Objective-C: OP_OBJC_SELF is just a placeholder for the class - instance variable. It just comes in a tight (OP_OBJC_SELF, - OP_OBJC_SELF) pair. */ -OP (OP_OBJC_SELF) - /* Objective C: "@selector" pseudo-operator. */ OP (OP_OBJC_SELECTOR) diff --git a/contrib/gdb-7/gdb/std-regs.c b/contrib/gdb-7/gdb/std-regs.c index 1054b89b8f..c5b97d6d71 100644 --- a/contrib/gdb-7/gdb/std-regs.c +++ b/contrib/gdb-7/gdb/std-regs.c @@ -1,7 +1,6 @@ /* Builtin frame register, for GDB, the GNU debugger. - Copyright (C) 2002, 2005, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 2002, 2005, 2007-2012 Free Software Foundation, Inc. Contributed by Red Hat. diff --git a/contrib/gdb-7/gdb/symfile.c b/contrib/gdb-7/gdb/symfile.c index 1478c83c03..45cd175b53 100644 --- a/contrib/gdb-7/gdb/symfile.c +++ b/contrib/gdb-7/gdb/symfile.c @@ -1,8 +1,6 @@ /* Generic symbol file reading for the GNU debugger, GDB. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-2012 Free Software Foundation, Inc. Contributed by Cygnus Support, using pieces from other GDB modules. @@ -56,6 +54,7 @@ #include "elf-bfd.h" #include "solib.h" #include "remote.h" +#include "stack.h" #include #include @@ -527,7 +526,7 @@ relative_addr_info_to_section_offsets (struct section_offsets *section_offsets, struct other_sections *osp; osp = &addrs->other[i]; - if (osp->addr == 0) + if (osp->sectindex == -1) continue; /* Record all sections in offsets. */ @@ -568,10 +567,7 @@ addrs_section_compar (const void *ap, const void *bp) if (retval) return retval; - /* SECTINDEX is undefined iff ADDR is zero. */ - a_idx = a->addr == 0 ? 0 : a->sectindex; - b_idx = b->addr == 0 ? 0 : b->sectindex; - return a_idx - b_idx; + return a->sectindex - b->sectindex; } /* Provide sorted array of pointers to sections of ADDRS. The array is @@ -734,8 +730,7 @@ addr_info_make_relative (struct section_addr_info *addrs, bfd *abfd) bfd_get_filename (abfd)); addrs->other[i].addr = 0; - - /* SECTINDEX is invalid if ADDR is zero. */ + addrs->other[i].sectindex = -1; } } @@ -1067,6 +1062,9 @@ new_symfile_objfile (struct objfile *objfile, int add_flags) syms_from_objfile, above. ADDRS is ignored when SYMFILE_MAINLINE bit is set in ADD_FLAGS. + PARENT is the original objfile if ABFD is a separate debug info file. + Otherwise PARENT is NULL. + Upon success, returns a pointer to the objfile that was added. Upon failure, jumps back to command level (never returns). */ @@ -1076,12 +1074,13 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, struct section_addr_info *addrs, struct section_offsets *offsets, int num_offsets, - int flags) + int flags, struct objfile *parent) { struct objfile *objfile; struct cleanup *my_cleanups; const char *name = bfd_get_filename (abfd); const int from_tty = add_flags & SYMFILE_VERBOSE; + const int mainline = add_flags & SYMFILE_MAINLINE; const int should_print = ((from_tty || info_verbose) && (readnow_symbol_files || (add_flags & SYMFILE_NO_READ) == 0)); @@ -1098,14 +1097,17 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, interactively wiping out any existing symbols. */ if ((have_full_symbols () || have_partial_symbols ()) - && (add_flags & SYMFILE_MAINLINE) + && mainline && from_tty && !query (_("Load new symbol table from \"%s\"? "), name)) error (_("Not confirmed.")); - objfile = allocate_objfile (abfd, flags); + objfile = allocate_objfile (abfd, flags | (mainline ? OBJF_MAINLINE : 0)); discard_cleanups (my_cleanups); + if (parent) + add_separate_debug_objfile (objfile, parent); + /* We either created a new mapped symbol table, mapped an existing symbol table file which has not had initial symbol reading performed, or need to read an unmapped symbol table. */ @@ -1161,8 +1163,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd, time. */ gdb_flush (gdb_stdout); - do_cleanups (my_cleanups); - if (objfile->sf == NULL) { observer_notify_new_objfile (objfile); @@ -1196,11 +1196,10 @@ symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile) (bfd, symfile_flags, sap, NULL, 0, objfile->flags & (OBJF_REORDERED | OBJF_SHARED | OBJF_READNOW - | OBJF_USERLOADED)); + | OBJF_USERLOADED), + objfile); do_cleanups (my_cleanup); - - add_separate_debug_objfile (new_objfile, objfile); } /* Process the symbol file ABFD, as either the main file or as a @@ -1211,10 +1210,10 @@ symbol_file_add_separate (bfd *bfd, int symfile_flags, struct objfile *objfile) struct objfile * symbol_file_add_from_bfd (bfd *abfd, int add_flags, struct section_addr_info *addrs, - int flags) + int flags, struct objfile *parent) { return symbol_file_add_with_addrs_or_offsets (abfd, add_flags, addrs, 0, 0, - flags); + flags, parent); } @@ -1226,7 +1225,7 @@ symbol_file_add (char *name, int add_flags, struct section_addr_info *addrs, int flags) { return symbol_file_add_from_bfd (symfile_bfd_open (name), add_flags, addrs, - flags); + flags, NULL); } @@ -1309,15 +1308,52 @@ get_debug_link_info (struct objfile *objfile, unsigned long *crc32_out) return contents; } +/* Return 32-bit CRC for ABFD. If successful store it to *FILE_CRC_RETURN and + return 1. Otherwise print a warning and return 0. ABFD seek position is + not preserved. */ + +static int +get_file_crc (bfd *abfd, unsigned long *file_crc_return) +{ + unsigned long file_crc = 0; + + if (bfd_seek (abfd, 0, SEEK_SET) != 0) + { + warning (_("Problem reading \"%s\" for CRC: %s"), + bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); + return 0; + } + + for (;;) + { + gdb_byte buffer[8 * 1024]; + bfd_size_type count; + + count = bfd_bread (buffer, sizeof (buffer), abfd); + if (count == (bfd_size_type) -1) + { + warning (_("Problem reading \"%s\" for CRC: %s"), + bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); + return 0; + } + if (count == 0) + break; + file_crc = gnu_debuglink_crc32 (file_crc, buffer, count); + } + + *file_crc_return = file_crc; + return 1; +} + static int separate_debug_file_exists (const char *name, unsigned long crc, struct objfile *parent_objfile) { - unsigned long file_crc = 0; + unsigned long file_crc; + int file_crc_p; bfd *abfd; - gdb_byte buffer[8*1024]; - int count; struct stat parent_stat, abfd_stat; + int verified_as_different; /* Find a separate debug info file as if symbols would be present in PARENT_OBJFILE itself this function would not be called. .gnu_debuglink @@ -1344,25 +1380,46 @@ separate_debug_file_exists (const char *name, unsigned long crc, negatives. */ if (bfd_stat (abfd, &abfd_stat) == 0 - && bfd_stat (parent_objfile->obfd, &parent_stat) == 0 - && abfd_stat.st_dev == parent_stat.st_dev - && abfd_stat.st_ino == parent_stat.st_ino - && abfd_stat.st_ino != 0) + && abfd_stat.st_ino != 0 + && bfd_stat (parent_objfile->obfd, &parent_stat) == 0) { - bfd_close (abfd); - return 0; + if (abfd_stat.st_dev == parent_stat.st_dev + && abfd_stat.st_ino == parent_stat.st_ino) + { + bfd_close (abfd); + return 0; + } + verified_as_different = 1; } + else + verified_as_different = 0; - while ((count = bfd_bread (buffer, sizeof (buffer), abfd)) > 0) - file_crc = gnu_debuglink_crc32 (file_crc, buffer, count); + file_crc_p = get_file_crc (abfd, &file_crc); bfd_close (abfd); + if (!file_crc_p) + return 0; + if (crc != file_crc) { - warning (_("the debug information found in \"%s\"" - " does not match \"%s\" (CRC mismatch).\n"), - name, parent_objfile->name); + /* If one (or both) the files are accessed for example the via "remote:" + gdbserver way it does not support the bfd_stat operation. Verify + whether those two files are not the same manually. */ + + if (!verified_as_different && !parent_objfile->crc32_p) + { + parent_objfile->crc32_p = get_file_crc (parent_objfile->obfd, + &parent_objfile->crc32); + if (!parent_objfile->crc32_p) + return 0; + } + + if (verified_as_different || parent_objfile->crc32 != file_crc) + warning (_("the debug information found in \"%s\"" + " does not match \"%s\" (CRC mismatch).\n"), + name, parent_objfile->name); + return 0; } @@ -1863,7 +1920,7 @@ load_progress (ULONGEST bytes, void *untyped_arg) { /* The write is just starting. Let the user know we've started this section. */ - ui_out_message (uiout, 0, "Loading section %s, size %s lma %s\n", + ui_out_message (current_uiout, 0, "Loading section %s, size %s lma %s\n", args->section_name, hex_string (args->section_size), paddress (target_gdbarch, args->lma)); return; @@ -1975,6 +2032,7 @@ generic_load (char *args, int from_tty) struct cleanup *old_cleanups = make_cleanup (null_cleanup, 0); struct load_section_data cbdata; struct load_progress_data total_progress; + struct ui_out *uiout = current_uiout; CORE_ADDR entry; char **argv; @@ -2102,6 +2160,7 @@ print_transfer_performance (struct ui_file *stream, const struct timeval *end_time) { ULONGEST time_count; + struct ui_out *uiout = current_uiout; /* Compute the elapsed time in milliseconds, as a tradeoff between accuracy and overflow. */ @@ -2253,7 +2312,7 @@ add_symbol_file_command (char *args, int from_tty) } else error (_("USAGE: add-symbol-file " - " [-mapped] [-readnow] [-s ]*")); + " [-readnow] [-s ]*")); } } } @@ -2385,6 +2444,29 @@ reread_symbols (void) exec_file_attach (bfd_get_filename (objfile->obfd), 0); } + /* Keep the calls order approx. the same as in free_objfile. */ + + /* Free the separate debug objfiles. It will be + automatically recreated by sym_read. */ + free_objfile_separate_debug (objfile); + + /* Remove any references to this objfile in the global + value lists. */ + preserve_values (objfile); + + /* Nuke all the state that we will re-read. Much of the following + code which sets things to NULL really is necessary to tell + other parts of GDB that there is nothing currently there. + + Try to keep the freeing order compatible with free_objfile. */ + + if (objfile->sf != NULL) + { + (*objfile->sf->sym_finish) (objfile); + } + + clear_objfile_data (objfile); + /* Clean up any state BFD has sitting around. We don't need to close the descriptor but BFD lacks a way of closing the BFD without closing the descriptor. */ @@ -2410,27 +2492,6 @@ reread_symbols (void) memcpy (offsets, objfile->section_offsets, SIZEOF_N_SECTION_OFFSETS (num_offsets)); - /* Remove any references to this objfile in the global - value lists. */ - preserve_values (objfile); - - /* Nuke all the state that we will re-read. Much of the following - code which sets things to NULL really is necessary to tell - other parts of GDB that there is nothing currently there. - - Try to keep the freeing order compatible with free_objfile. */ - - if (objfile->sf != NULL) - { - (*objfile->sf->sym_finish) (objfile); - } - - clear_objfile_data (objfile); - - /* Free the separate debug objfiles. It will be - automatically recreated by sym_read. */ - free_objfile_separate_debug (objfile); - /* FIXME: Do we have to free a whole linked list, or is this enough? */ if (objfile->global_psymbols.list) @@ -2460,7 +2521,6 @@ reread_symbols (void) objfile->psymtabs = NULL; objfile->psymtabs_addrmap = NULL; objfile->free_psymtabs = NULL; - objfile->cp_namespace_symtab = NULL; objfile->template_symbols = NULL; objfile->msymbols = NULL; objfile->deprecated_sym_private = NULL; @@ -2470,9 +2530,6 @@ reread_symbols (void) memset (&objfile->msymbol_demangled_hash, 0, sizeof (objfile->msymbol_demangled_hash)); - objfile->psymbol_cache = psymbol_bcache_init (); - objfile->macro_cache = bcache_xmalloc (NULL, NULL); - objfile->filename_cache = bcache_xmalloc (NULL, NULL); /* obstack_init also initializes the obstack so it is empty. We could use obstack_specify_allocation but gdb_obstack.h specifies the alloc/dealloc @@ -2781,7 +2838,7 @@ clear_symtab_users (int add_flags) clear_displays (); if ((add_flags & SYMFILE_DEFER_BP_RESET) == 0) breakpoint_re_set (); - set_default_breakpoint (0, NULL, 0, 0, 0); + clear_last_displayed_sal (); clear_pc_function_cache (); observer_notify_new_objfile (NULL); diff --git a/contrib/gdb-7/gdb/symfile.h b/contrib/gdb-7/gdb/symfile.h index dad032031b..604fe16340 100644 --- a/contrib/gdb-7/gdb/symfile.h +++ b/contrib/gdb-7/gdb/symfile.h @@ -1,8 +1,6 @@ /* Definitions for reading symbol files into GDB. - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011 - Free Software Foundation, Inc. + Copyright (C) 1990-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -86,7 +84,7 @@ struct section_addr_info CORE_ADDR addr; char *name; - /* SECTINDEX must be valid for associated BFD if ADDR is not zero. */ + /* SECTINDEX must be valid for associated BFD or set to -1. */ int sectindex; } other[1]; }; @@ -116,6 +114,11 @@ struct symfile_segment_data int *segment_info; }; +/* Callback for quick_symbol_functions->map_symbol_filenames. */ + +typedef void (symbol_filename_ftype) (const char *filename, + const char *fullname, void *data); + /* The "quick" symbol functions exist so that symbol readers can avoiding an initial read of all the symbols. For example, symbol readers might choose to use the "partial symbol table" utilities, @@ -147,22 +150,24 @@ struct quick_symbol_functions /* Forget all cached full file names for OBJFILE. */ void (*forget_cached_source_info) (struct objfile *objfile); - /* Look up the symbol table, in OBJFILE, of a source file named - NAME. If there is no '/' in the name, a match after a '/' in the - symbol table's file name will also work. FULL_PATH is the - absolute file name, and REAL_PATH is the same, run through - gdb_realpath. - - If no such symbol table can be found, returns 0. - - Otherwise, sets *RESULT to the symbol table and returns 1. This - might return 1 and set *RESULT to NULL if the requested file is - an include file that does not have a symtab of its own. */ - int (*lookup_symtab) (struct objfile *objfile, - const char *name, - const char *full_path, - const char *real_path, - struct symtab **result); + /* Expand and iterate over each "partial" symbol table in OBJFILE + where the source file is named NAME. + + If there is no '/' in the name, a match after a '/' in the symbol + table's file name will also work. FULL_PATH is the absolute file + name, and REAL_PATH is the same, run through gdb_realpath. + + If a match is found, the "partial" symbol table is expanded. + Then, this calls iterate_over_some_symtabs (or equivalent) over + all newly-created symbol tables, passing CALLBACK and DATA to it. + The result of this call is returned. */ + int (*map_symtabs_matching_filename) (struct objfile *objfile, + const char *name, + const char *full_path, + const char *real_path, + int (*callback) (struct symtab *, + void *), + void *data); /* Check to see if the symbol is defined in a "partial" symbol table of OBJFILE. KIND should be either GLOBAL_BLOCK or STATIC_BLOCK, @@ -182,7 +187,8 @@ struct quick_symbol_functions doesn't make sense to implement both.) The arguments are as for `lookup_symbol'. */ void (*pre_expand_symtabs_matching) (struct objfile *objfile, - int kind, const char *name, + enum block_enum block_kind, + const char *name, domain_enum domain); /* Print statistics about any indices loaded for OBJFILE. The @@ -216,24 +222,24 @@ struct quick_symbol_functions void (*expand_symtabs_with_filename) (struct objfile *objfile, const char *filename); - /* Return the file name of the file holding the symbol in OBJFILE + /* Return the file name of the file holding the global symbol in OBJFILE named NAME. If no such symbol exists in OBJFILE, return NULL. */ const char *(*find_symbol_file) (struct objfile *objfile, const char *name); /* Find global or static symbols in all tables that are in NAMESPACE and for which MATCH (symbol name, NAME) == 0, passing each to - CALLBACK, reading in partial symbol symbol tables as needed. Look + CALLBACK, reading in partial symbol tables as needed. Look through global symbols if GLOBAL and otherwise static symbols. Passes NAME, NAMESPACE, and DATA to CALLBACK with each symbol found. After each block is processed, passes NULL to CALLBACK. - MATCH must be weaker than strcmp_iw in the sense that - strcmp_iw(x,y) == 0 --> MATCH(x,y) == 0. ORDERED_COMPARE, if - non-null, must be an ordering relation compatible with strcmp_iw - in the sense that - strcmp(x,y) == 0 --> ORDERED_COMPARE(x,y) == 0 + MATCH must be weaker than strcmp_iw_ordered in the sense that + strcmp_iw_ordered(x,y) == 0 --> MATCH(x,y) == 0. ORDERED_COMPARE, + if non-null, must be an ordering relation compatible with + strcmp_iw_ordered in the sense that + strcmp_iw_ordered(x,y) == 0 --> ORDERED_COMPARE(x,y) == 0 and - strcmp(x,y) <= 0 --> ORDERED_COMPARE(x,y) <= 0 - (allowing strcmp(x,y) < 0 while ORDERED_COMPARE(x, y) == 0). + strcmp_iw_ordered(x,y) <= 0 --> ORDERED_COMPARE(x,y) <= 0 + (allowing strcmp_iw_ordered(x,y) < 0 while ORDERED_COMPARE(x, y) == 0). CALLBACK returns 0 to indicate that the scan should continue, or non-zero to indicate that the scan should be terminated. */ @@ -253,9 +259,12 @@ struct quick_symbol_functions Otherwise, if KIND does not match this symbol is skipped. - If even KIND matches, then NAME_MATCHER is called for each symbol defined - in the file. The symbol's "natural" name and DATA are passed to - NAME_MATCHER. + If even KIND matches, then NAME_MATCHER is called for each symbol + defined in the file. The current language, the symbol name and + DATA are passed to NAME_MATCHER. The symbol "natural" name should + be passed to NAME_MATCHER for all languages except Ada, where + the encoded name is passed instead (see la_symbol_name_compare in + struct language_defn for more details on this). If NAME_MATCHER returns zero, then this symbol is skipped. @@ -263,11 +272,12 @@ struct quick_symbol_functions DATA is user data that is passed unmodified to the callback functions. */ - void (*expand_symtabs_matching) (struct objfile *objfile, - int (*file_matcher) (const char *, void *), - int (*name_matcher) (const char *, void *), - domain_enum kind, - void *data); + void (*expand_symtabs_matching) + (struct objfile *objfile, + int (*file_matcher) (const char *, void *), + int (*name_matcher) (const struct language_defn *, const char *, void *), + enum search_domain kind, + void *data); /* Return the symbol table from OBJFILE that contains PC and SECTION. Return NULL if there is no such symbol table. This @@ -282,12 +292,12 @@ struct quick_symbol_functions int warn_if_readin); /* Call a callback for every file defined in OBJFILE whose symtab is - not already read in. FUN is the callback. It is passed the file's name, - the file's full name, and the DATA passed to this function. */ + not already read in. FUN is the callback. It is passed the file's + FILENAME, the file's FULLNAME (if need_fullname is non-zero), and + the DATA passed to this function. */ void (*map_symbol_filenames) (struct objfile *objfile, - void (*fun) (const char *, const char *, - void *), - void *data); + symbol_filename_ftype *fun, void *data, + int need_fullname); }; /* Structure to keep track of symbol reading functions for various @@ -427,7 +437,7 @@ extern struct objfile *symbol_file_add (char *, int, extern struct objfile *symbol_file_add_from_bfd (bfd *, int, struct section_addr_info *, - int); + int, struct objfile *parent); extern void symbol_file_add_separate (bfd *, int, struct objfile *); @@ -552,7 +562,57 @@ extern struct cleanup *increment_reading_symtab (void); /* From dwarf2read.c */ -extern int dwarf2_has_info (struct objfile *); +/* Names for a dwarf2 debugging section. The field NORMAL is the normal + section name (usually from the DWARF standard), while the field COMPRESSED + is the name of compressed sections. If your object file format doesn't + support compressed sections, the field COMPRESSED can be NULL. Likewise, + the debugging section is not supported, the field NORMAL can be NULL too. + It doesn't make sense to have a NULL NORMAL field but a non-NULL COMPRESSED + field. */ + +struct dwarf2_section_names { + const char *normal; + const char *compressed; +}; + +/* List of names for dward2 debugging sections. Also most object file formats + use the standardized (ie ELF) names, some (eg XCOFF) have customized names + due to restrictions. + The table for the standard names is defined in dwarf2read.c. Please + update all instances of dwarf2_debug_sections if you add a field to this + structure. It is always safe to use { NULL, NULL } in this case. */ + +struct dwarf2_debug_sections { + struct dwarf2_section_names info; + struct dwarf2_section_names abbrev; + struct dwarf2_section_names line; + struct dwarf2_section_names loc; + struct dwarf2_section_names macinfo; + struct dwarf2_section_names macro; + struct dwarf2_section_names str; + struct dwarf2_section_names ranges; + struct dwarf2_section_names types; + struct dwarf2_section_names frame; + struct dwarf2_section_names eh_frame; + struct dwarf2_section_names gdb_index; + /* This field has no meaning, but exists solely to catch changes to + this structure which are not reflected in some instance. */ + int sentinel; +}; + +extern int dwarf2_has_info (struct objfile *, + const struct dwarf2_debug_sections *); + +/* Dwarf2 sections that can be accessed by dwarf2_get_section_info. */ +enum dwarf2_section_enum { + DWARF2_DEBUG_FRAME, + DWARF2_EH_FRAME +}; + +extern void dwarf2_get_section_info (struct objfile *, + enum dwarf2_section_enum, + asection **, gdb_byte **, + bfd_size_type *); extern int dwarf2_initialize_objfile (struct objfile *); extern void dwarf2_build_psymtabs (struct objfile *); diff --git a/contrib/gdb-7/gdb/symmisc.c b/contrib/gdb-7/gdb/symmisc.c index 66c2f05adb..daa0b43e19 100644 --- a/contrib/gdb-7/gdb/symmisc.c +++ b/contrib/gdb-7/gdb/symmisc.c @@ -1,8 +1,7 @@ /* Do various things to symbol tables (other than lookup), for GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2000, 2002-2004, 2007-2012 Free Software + Foundation, Inc. This file is part of GDB. @@ -79,46 +78,6 @@ struct print_symbol_args static int print_symbol (void *); -/* Free all the storage associated with the struct symtab <- S. - Note that some symtabs have contents that all live inside one big block of - memory, and some share the contents of another symbol table and so you - should not free the contents on their behalf (except sometimes the - linetable, which maybe per symtab even when the rest is not). - It is s->free_code that says which alternative to use. */ - -void -free_symtab (struct symtab *s) -{ - switch (s->free_code) - { - case free_nothing: - /* All the contents are part of a big block of memory (an obstack), - and some other symtab is in charge of freeing that block. - Therefore, do nothing. */ - break; - - case free_linetable: - /* Everything will be freed either by our `free_func' - or by some other symtab, except for our linetable. - Free that now. */ - if (LINETABLE (s)) - xfree (LINETABLE (s)); - break; - } - - /* If there is a single block of memory to free, free it. */ - if (s->free_func != NULL) - s->free_func (s); - - /* Free source-related stuff. */ - if (s->line_charpos != NULL) - xfree (s->line_charpos); - if (s->fullname != NULL) - xfree (s->fullname); - if (s->debugformat != NULL) - xfree (s->debugformat); - xfree (s); -} void print_symbol_bcache_statistics (void) diff --git a/contrib/gdb-7/gdb/symtab.c b/contrib/gdb-7/gdb/symtab.c index 4c1a78a153..ab6a1aa40c 100644 --- a/contrib/gdb-7/gdb/symtab.c +++ b/contrib/gdb-7/gdb/symtab.c @@ -1,8 +1,6 @@ /* Symbol table lookup for the GNU debugger, GDB. - Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, - 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, - 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1986-2004, 2007-2012 Free Software Foundation, Inc. This file is part of GDB. @@ -81,11 +79,7 @@ static void sources_info (char *, int); static void output_source_filename (const char *, int *); -static int find_line_common (struct linetable *, int, int *); - -/* This one is used by linespec.c */ - -char *operator_chars (char *p, char **end); +static int find_line_common (struct linetable *, int, int *, int); static struct symbol *lookup_symbol_aux (const char *name, const struct block *block, @@ -110,17 +104,17 @@ struct symbol *lookup_symbol_aux_quick (struct objfile *objfile, const char *name, const domain_enum domain); -static void print_symbol_info (domain_enum, - struct symtab *, struct symbol *, int, char *); - static void print_msymbol_info (struct minimal_symbol *); -static void symtab_symbol_info (char *, domain_enum, int); - void _initialize_symtab (void); /* */ +/* Non-zero if a file may be known by two different basenames. + This is the uncommon case, and significantly slows down gdb. + Default set to "off" to not slow down the common case. */ +int basenames_may_differ = 0; + /* Allow the user to configure the debugger behavior with respect to multiple-choice menus when more than one symbol matches during a symbol lookup. */ @@ -151,39 +145,44 @@ multiple_symbols_select_mode (void) const struct block *block_found; -/* 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. */ +/* Check for a symtab of a specific name by searching some symtabs. + This is a helper function for callbacks of iterate_over_symtabs. -struct symtab * -lookup_symtab (const char *name) + The return value, NAME, FULL_PATH, REAL_PATH, CALLBACK, and DATA + are identical to the `map_symtabs_matching_filename' method of + quick_symbol_functions. + + FIRST and AFTER_LAST indicate the range of symtabs to search. + AFTER_LAST is one past the last symtab to search; NULL means to + search until the end of the list. */ + +int +iterate_over_some_symtabs (const char *name, + const char *full_path, + const char *real_path, + int (*callback) (struct symtab *symtab, + void *data), + void *data, + struct symtab *first, + struct symtab *after_last) { - int found; struct symtab *s = NULL; - struct objfile *objfile; - char *real_path = NULL; - char *full_path = NULL; + struct cleanup *cleanup; + const char* base_name = lbasename (name); - /* Here we are interested in canonicalizing an absolute path, not - absolutizing a relative path. */ - if (IS_ABSOLUTE_PATH (name)) + for (s = first; s != NULL && s != after_last; s = s->next) { - full_path = xfullpath (name); - make_cleanup (xfree, full_path); - real_path = gdb_realpath (name); - make_cleanup (xfree, real_path); - } - -got_symtab: - - /* First, search for an exact match. */ + if (FILENAME_CMP (name, s->filename) == 0) + { + if (callback (s, data)) + return 1; + } - ALL_SYMTABS (objfile, s) - { - if (FILENAME_CMP (name, s->filename) == 0) - { - return s; - } + /* Before we invoke realpath, which can get expensive when many + files are involved, do a quick comparison of the basenames. */ + if (! basenames_may_differ + && FILENAME_CMP (base_name, lbasename (s->filename)) != 0) + continue; /* If the user gave us an absolute path, try to find the file in this symtab and use its absolute path. */ @@ -194,7 +193,8 @@ got_symtab: if (fp != NULL && FILENAME_CMP (full_path, fp) == 0) { - return s; + if (callback (s, data)) + return 1; } } @@ -208,52 +208,114 @@ got_symtab: make_cleanup (xfree, rp); if (FILENAME_CMP (real_path, rp) == 0) - { - return s; - } + { + if (callback (s, data)) + return 1; + } } } - } + } /* Now, search for a matching tail (only if name doesn't have any dirs). */ if (lbasename (name) == name) - ALL_SYMTABS (objfile, s) { - if (FILENAME_CMP (lbasename (s->filename), name) == 0) - return s; + for (s = first; s != NULL && s != after_last; s = s->next) + { + if (FILENAME_CMP (lbasename (s->filename), name) == 0) + { + if (callback (s, data)) + return 1; + } + } + } + + return 0; +} + +/* 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 and with the supplied + DATA. If CALLBACK returns true, the search stops. */ + +void +iterate_over_symtabs (const char *name, + int (*callback) (struct symtab *symtab, + void *data), + void *data) +{ + struct symtab *s = NULL; + struct objfile *objfile; + char *real_path = NULL; + char *full_path = NULL; + struct cleanup *cleanups = make_cleanup (null_cleanup, NULL); + + /* Here we are interested in canonicalizing an absolute path, not + absolutizing a relative path. */ + if (IS_ABSOLUTE_PATH (name)) + { + full_path = xfullpath (name); + make_cleanup (xfree, full_path); + real_path = gdb_realpath (name); + make_cleanup (xfree, real_path); } + ALL_OBJFILES (objfile) + { + if (iterate_over_some_symtabs (name, full_path, real_path, callback, data, + objfile->symtabs, NULL)) + { + do_cleanups (cleanups); + return; + } + } + /* Same search rules as above apply here, but now we look thru the psymtabs. */ - found = 0; ALL_OBJFILES (objfile) { if (objfile->sf - && objfile->sf->qf->lookup_symtab (objfile, name, full_path, real_path, - &s)) + && objfile->sf->qf->map_symtabs_matching_filename (objfile, + name, + full_path, + real_path, + callback, + data)) { - found = 1; - break; + do_cleanups (cleanups); + return; } } - if (s != NULL) - return s; - if (!found) - return NULL; + do_cleanups (cleanups); +} + +/* The callback function used by lookup_symtab. */ + +static int +lookup_symtab_callback (struct symtab *symtab, void *data) +{ + struct symtab **result_ptr = data; + + *result_ptr = symtab; + return 1; +} - /* At this point, we have located the psymtab for this file, but - the conversion to a symtab has failed. This usually happens - when we are looking up an include file. In this case, - PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has - been created. So, we need to run through the symtabs again in - order to find the file. - XXX - This is a crock, and should be fixed inside of the the - symbol parsing routines. */ - goto got_symtab; +/* A wrapper for iterate_over_symtabs that returns the first matching + symtab, or NULL. */ + +struct symtab * +lookup_symtab (const char *name) +{ + struct symtab *result = NULL; + + iterate_over_symtabs (name, lookup_symtab_callback, &result); + return result; } + /* Mangle a GDB method stub type. This actually reassembles the pieces of the full method name, which consist of the class name (from T), the unadorned @@ -268,7 +330,7 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id) struct fn_field *f = TYPE_FN_FIELDLIST1 (type, method_id); struct fn_field *method = &f[signature_id]; char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id); - char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id); + const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id); char *newname = type_name_no_tag (type); /* Does the form of physname indicate that it is the full mangled name @@ -988,33 +1050,30 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile) return sym; } -/* Find the definition for a specified symbol name NAME - in domain DOMAIN, visible from lexical block BLOCK. - Returns the struct symbol pointer, or zero if no symbol is found. - C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if - NAME is a field of the current implied argument `this'. If so set - *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. - BLOCK_FOUND is set to the block in which NAME is found (in the case of - a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ - -/* This function has a bunch of loops in it and it would seem to be - attractive to put in some QUIT's (though I'm not really sure - whether it can run long enough to be really important). But there - are a few calls for which it would appear to be bad news to quit - out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note - that there is C++ code below which can error(), but that probably - doesn't affect these calls since they are looking for a known - variable and thus can probably assume it will never hit the C++ - code). */ +/* Compute the demangled form of NAME as used by the various symbol + lookup functions. The result is stored in *RESULT_NAME. Returns a + cleanup which can be used to clean up the result. + + For Ada, this function just sets *RESULT_NAME to NAME, unmodified. + Normally, Ada symbol lookups are performed using the encoded name + rather than the demangled name, and so it might seem to make sense + for this function to return an encoded version of NAME. + Unfortunately, we cannot do this, because this function is used in + circumstances where it is not appropriate to try to encode NAME. + For instance, when displaying the frame info, we demangle the name + of each parameter, and then perform a symbol lookup inside our + function using that demangled name. In Ada, certain functions + have internally-generated parameters whose name contain uppercase + characters. Encoding those name would result in those uppercase + characters to become lowercase, and thus cause the symbol lookup + to fail. */ -struct symbol * -lookup_symbol_in_language (const char *name, const struct block *block, - const domain_enum domain, enum language lang, - int *is_a_field_of_this) +struct cleanup * +demangle_for_lookup (const char *name, enum language lang, + const char **result_name) { char *demangled_name = NULL; const char *modified_name = NULL; - struct symbol *returnval; struct cleanup *cleanup = make_cleanup (null_cleanup, 0); modified_name = name; @@ -1061,18 +1120,37 @@ lookup_symbol_in_language (const char *name, const struct block *block, } } - if (case_sensitivity == case_sensitive_off) - { - char *copy; - int len, i; - - len = strlen (name); - copy = (char *) alloca (len + 1); - for (i= 0; i < len; i++) - copy[i] = tolower (name[i]); - copy[len] = 0; - modified_name = copy; - } + *result_name = modified_name; + return cleanup; +} + +/* Find the definition for a specified symbol name NAME + in domain DOMAIN, visible from lexical block BLOCK. + Returns the struct symbol pointer, or zero if no symbol is found. + C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if + NAME is a field of the current implied argument `this'. If so set + *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero. + BLOCK_FOUND is set to the block in which NAME is found (in the case of + a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */ + +/* This function has a bunch of loops in it and it would seem to be + attractive to put in some QUIT's (though I'm not really sure + whether it can run long enough to be really important). But there + are a few calls for which it would appear to be bad news to quit + out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note + that there is C++ code below which can error(), but that probably + doesn't affect these calls since they are looking for a known + variable and thus can probably assume it will never hit the C++ + code). */ + +struct symbol * +lookup_symbol_in_language (const char *name, const struct block *block, + const domain_enum domain, enum language lang, + int *is_a_field_of_this) +{ + const char *modified_name; + struct symbol *returnval; + struct cleanup *cleanup = demangle_for_lookup (name, lang, &modified_name); returnval = lookup_symbol_aux (modified_name, block, domain, lang, is_a_field_of_this); @@ -1093,6 +1171,31 @@ lookup_symbol (const char *name, const struct block *block, is_a_field_of_this); } +/* Look up the `this' symbol for LANG in BLOCK. Return the symbol if + found, or NULL if not found. */ + +struct symbol * +lookup_language_this (const struct language_defn *lang, + const struct block *block) +{ + if (lang->la_name_of_this == NULL || block == NULL) + return NULL; + + while (block) + { + struct symbol *sym; + + sym = lookup_block_symbol (block, lang->la_name_of_this, VAR_DOMAIN); + if (sym != NULL) + return sym; + if (BLOCK_FUNCTION (block)) + break; + block = BLOCK_SUPERBLOCK (block); + } + + return NULL; +} + /* Behave like lookup_symbol except that NAME is the natural name of the symbol that we're looking for and, if LINKAGE_NAME is non-NULL, ensure that the symbol's linkage name matches as @@ -1126,20 +1229,10 @@ lookup_symbol_aux (const char *name, const struct block *block, langdef = language_def (language); - if (langdef->la_name_of_this != NULL && is_a_field_of_this != NULL - && block != NULL) + if (is_a_field_of_this != NULL) { - struct symbol *sym = NULL; - const struct block *function_block = block; + struct symbol *sym = lookup_language_this (langdef, block); - /* 'this' is only defined in the function's block, so find the - enclosing function block. */ - for (; function_block && !BLOCK_FUNCTION (function_block); - function_block = BLOCK_SUPERBLOCK (function_block)); - - if (function_block && !dict_empty (BLOCK_DICT (function_block))) - sym = lookup_block_symbol (function_block, langdef->la_name_of_this, - VAR_DOMAIN); if (sym) { struct type *t = sym->type; @@ -1751,6 +1844,44 @@ lookup_block_symbol (const struct block *block, const char *name, } } +/* Iterate over the symbols named NAME, matching DOMAIN, starting with + BLOCK. + + For each symbol that matches, CALLBACK is called. The symbol and + DATA are passed to the callback. + + If CALLBACK returns zero, the iteration ends. Otherwise, the + search continues. This function iterates upward through blocks. + When the outermost block has been finished, the function + returns. */ + +void +iterate_over_symbols (const struct block *block, const char *name, + const domain_enum domain, + int (*callback) (struct symbol *, void *), + void *data) +{ + while (block) + { + struct dict_iterator iter; + struct symbol *sym; + + for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter); + sym != NULL; + sym = dict_iter_name_next (name, &iter)) + { + if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), + SYMBOL_DOMAIN (sym), domain)) + { + if (!callback (sym, data)) + return; + } + } + + block = BLOCK_SUPERBLOCK (block); + } +} + /* Find the symtab associated with PC and SECTION. Look through the psymtabs and read in another symtab if necessary. */ @@ -2176,7 +2307,7 @@ find_line_symtab (struct symtab *symtab, int line, /* First try looking it up in the given symtab. */ best_linetable = LINETABLE (symtab); best_symtab = symtab; - best_index = find_line_common (best_linetable, line, &exact); + best_index = find_line_common (best_linetable, line, &exact, 0); if (best_index < 0 || !exact) { /* Didn't find an exact match. So we better keep looking for @@ -2221,7 +2352,7 @@ find_line_symtab (struct symtab *symtab, int line, && FILENAME_CMP (symtab->fullname, s->fullname) != 0) continue; l = LINETABLE (s); - ind = find_line_common (l, line, &exact); + ind = find_line_common (l, line, &exact, 0); if (ind >= 0) { if (exact) @@ -2252,6 +2383,46 @@ done: return best_symtab; } + +/* Given SYMTAB, returns all the PCs function in the symtab that + exactly match LINE. Returns NULL if there are no exact matches, + but updates BEST_ITEM in this case. */ + +VEC (CORE_ADDR) * +find_pcs_for_symtab_line (struct symtab *symtab, int line, + struct linetable_entry **best_item) +{ + int start = 0, ix; + struct symbol *previous_function = NULL; + VEC (CORE_ADDR) *result = NULL; + + /* First, collect all the PCs that are at this line. */ + while (1) + { + int was_exact; + int idx; + + idx = find_line_common (LINETABLE (symtab), line, &was_exact, start); + if (idx < 0) + break; + + if (!was_exact) + { + struct linetable_entry *item = &LINETABLE (symtab)->item[idx]; + + if (*best_item == NULL || item->line < (*best_item)->line) + *best_item = item; + + break; + } + + VEC_safe_push (CORE_ADDR, result, LINETABLE (symtab)->item[idx].pc); + start = idx + 1; + } + + return result; +} + /* Set the PC value for a given source file and line number and return true. Returns zero for invalid line number (and sets the PC to 0). @@ -2320,12 +2491,13 @@ find_line_pc_range (struct symtab_and_line sal, CORE_ADDR *startptr, /* Given a line table and a line number, return the index into the line table for the pc of the nearest line whose number is >= the specified one. Return -1 if none is found. The value is >= 0 if it is an index. + START is the index at which to start searching the line table. Set *EXACT_MATCH nonzero if the value returned is an exact match. */ static int find_line_common (struct linetable *l, int lineno, - int *exact_match) + int *exact_match, int start) { int i; int len; @@ -2345,7 +2517,7 @@ find_line_common (struct linetable *l, int lineno, return -1; len = l->nitems; - for (i = 0; i < len; i++) + for (i = start; i < len; i++) { struct linetable_entry *item = &(l->item[i]); @@ -2541,8 +2713,8 @@ skip_prologue_sal (struct symtab_and_line *sal) /* Check if gdbarch_skip_prologue left us in mid-line, and the next line is still part of the same function. */ if (skip && start_sal.pc != pc - && (sym? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end - && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) + && (sym ? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end + && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym))) : (lookup_minimal_symbol_by_pc_section (start_sal.end, section) == lookup_minimal_symbol_by_pc_section (pc, section)))) { @@ -2625,7 +2797,7 @@ skip_prologue_sal (struct symtab_and_line *sal) some legitimate operator text, return a pointer to the beginning of the substring of the operator text. Otherwise, return "". */ -char * +static char * operator_chars (char *p, char **end) { *end = ""; @@ -2873,7 +3045,8 @@ sources_info (char *ignore, int from_tty) "will be read in on demand:\n\n"); first = 1; - map_partial_symbol_filenames (output_partial_symbol_filename, &first); + map_partial_symbol_filenames (output_partial_symbol_filename, &first, + 1 /*need_fullname*/); printf_filtered ("\n"); } @@ -2974,7 +3147,10 @@ struct search_symbols_data { int nfiles; char **files; - char *regexp; + + /* It is true if PREG contains valid data, false otherwise. */ + unsigned preg_p : 1; + regex_t preg; }; /* A callback for expand_symtabs_matching. */ @@ -2988,21 +3164,22 @@ search_symbols_file_matches (const char *filename, void *user_data) /* A callback for expand_symtabs_matching. */ static int -search_symbols_name_matches (const char *symname, void *user_data) +search_symbols_name_matches (const struct language_defn *language, + const char *symname, void *user_data) { struct search_symbols_data *data = user_data; - return data->regexp == NULL || re_exec (symname); + return !data->preg_p || regexec (&data->preg, symname, 0, NULL, 0) == 0; } /* Search the symbol table for matches to the regular expression REGEXP, returning the results in *MATCHES. Only symbols of KIND are searched: + VARIABLES_DOMAIN - search all symbols, excluding functions, type names, + and constants (enums) FUNCTIONS_DOMAIN - search all functions TYPES_DOMAIN - search all type names - VARIABLES_DOMAIN - search all symbols, excluding functions, type names, - and constants (enums) ALL_DOMAIN - an internal error for this function free_search_symbols should be called when *MATCHES is no longer needed. @@ -3011,7 +3188,8 @@ search_symbols_name_matches (const char *symname, void *user_data) separately alphabetized. */ void -search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], +search_symbols (char *regexp, enum search_domain kind, + int nfiles, char *files[], struct symbol_search **matches) { struct symtab *s; @@ -3025,13 +3203,13 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], char *val; int found_misc = 0; static const enum minimal_symbol_type types[] - = {mst_data, mst_text, mst_abs, mst_unknown}; + = {mst_data, mst_text, mst_abs}; static const enum minimal_symbol_type types2[] - = {mst_bss, mst_file_text, mst_abs, mst_unknown}; + = {mst_bss, mst_file_text, mst_abs}; static const enum minimal_symbol_type types3[] - = {mst_file_data, mst_solib_trampoline, mst_abs, mst_unknown}; + = {mst_file_data, mst_solib_trampoline, mst_abs}; static const enum minimal_symbol_type types4[] - = {mst_file_bss, mst_text_gnu_ifunc, mst_abs, mst_unknown}; + = {mst_file_bss, mst_text_gnu_ifunc, mst_abs}; enum minimal_symbol_type ourtype; enum minimal_symbol_type ourtype2; enum minimal_symbol_type ourtype3; @@ -3039,19 +3217,23 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], struct symbol_search *sr; struct symbol_search *psr; struct symbol_search *tail; - struct cleanup *old_chain = NULL; struct search_symbols_data datum; - if (kind < VARIABLES_DOMAIN || kind >= ALL_DOMAIN) - error (_("must search on specific domain")); + /* OLD_CHAIN .. RETVAL_CHAIN is always freed, RETVAL_CHAIN .. current + CLEANUP_CHAIN is freed only in the case of an error. */ + struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); + struct cleanup *retval_chain; - ourtype = types[(int) (kind - VARIABLES_DOMAIN)]; - ourtype2 = types2[(int) (kind - VARIABLES_DOMAIN)]; - ourtype3 = types3[(int) (kind - VARIABLES_DOMAIN)]; - ourtype4 = types4[(int) (kind - VARIABLES_DOMAIN)]; + gdb_assert (kind <= TYPES_DOMAIN); + + ourtype = types[kind]; + ourtype2 = types2[kind]; + ourtype3 = types3[kind]; + ourtype4 = types4[kind]; sr = *matches = NULL; tail = NULL; + datum.preg_p = 0; if (regexp != NULL) { @@ -3061,6 +3243,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], and or . */ char *opend; char *opname = operator_chars (regexp, &opend); + int errcode; if (*opname) { @@ -3089,8 +3272,18 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], } } - if (0 != (val = re_comp (regexp))) - error (_("Invalid regexp (%s): %s"), val, regexp); + errcode = regcomp (&datum.preg, regexp, + REG_NOSUB | (case_sensitivity == case_sensitive_off + ? REG_ICASE : 0)); + if (errcode != 0) + { + char *err = get_regcomp_error (errcode, &datum.preg); + + make_cleanup (xfree, err); + error (_("Invalid regexp (%s): %s"), err, regexp); + } + datum.preg_p = 1; + make_regfree_cleanup (&datum.preg); } /* Search through the partial symtabs *first* for all symbols @@ -3099,7 +3292,6 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], datum.nfiles = nfiles; datum.files = files; - datum.regexp = regexp; ALL_OBJFILES (objfile) { if (objfile->sf) @@ -3110,6 +3302,8 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], &datum); } + retval_chain = old_chain; + /* Here, we search through the minimal symbol tables for functions and variables that match, and force their symbols to be read. This is in particular necessary for demangled variable names, @@ -3133,8 +3327,9 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], MSYMBOL_TYPE (msymbol) == ourtype3 || MSYMBOL_TYPE (msymbol) == ourtype4) { - if (regexp == NULL - || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0) + if (!datum.preg_p + || regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0, + NULL, 0) == 0) { if (0 == find_pc_symtab (SYMBOL_VALUE_ADDRESS (msymbol))) { @@ -3172,8 +3367,9 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], QUIT; if (file_matches (real_symtab->filename, files, nfiles) - && ((regexp == NULL - || re_exec (SYMBOL_NATURAL_NAME (sym)) != 0) + && ((!datum.preg_p + || regexec (&datum.preg, SYMBOL_NATURAL_NAME (sym), 0, + NULL, 0) == 0) && ((kind == VARIABLES_DOMAIN && SYMBOL_CLASS (sym) != LOC_TYPEDEF && SYMBOL_CLASS (sym) != LOC_UNRESOLVED @@ -3215,7 +3411,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], tail = sort_search_symbols (&dummy, nfound); sr = dummy.next; - old_chain = make_cleanup_free_search_symbols (sr); + make_cleanup_free_search_symbols (sr); } else tail = sort_search_symbols (prevtail, nfound); @@ -3237,8 +3433,9 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], MSYMBOL_TYPE (msymbol) == ourtype3 || MSYMBOL_TYPE (msymbol) == ourtype4) { - if (regexp == NULL - || re_exec (SYMBOL_NATURAL_NAME (msymbol)) != 0) + if (!datum.preg_p + || regexec (&datum.preg, SYMBOL_NATURAL_NAME (msymbol), 0, + NULL, 0) == 0) { /* Functions: Look up by address. */ if (kind != FUNCTIONS_DOMAIN || @@ -3260,7 +3457,7 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], if (tail == NULL) { sr = psr; - old_chain = make_cleanup_free_search_symbols (sr); + make_cleanup_free_search_symbols (sr); } else tail->next = psr; @@ -3272,9 +3469,9 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], } } + discard_cleanups (retval_chain); + do_cleanups (old_chain); *matches = sr; - if (sr != NULL) - discard_cleanups (old_chain); } /* Helper function for symtab_symbol_info, this function uses @@ -3282,7 +3479,8 @@ search_symbols (char *regexp, domain_enum kind, int nfiles, char *files[], regarding the match to gdb_stdout. */ static void -print_symbol_info (domain_enum kind, struct symtab *s, struct symbol *sym, +print_symbol_info (enum search_domain kind, + struct symtab *s, struct symbol *sym, int block, char *last) { if (last == NULL || filename_cmp (last, s->filename) != 0) @@ -3339,16 +3537,18 @@ print_msymbol_info (struct minimal_symbol *msymbol) matches. */ static void -symtab_symbol_info (char *regexp, domain_enum kind, int from_tty) +symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty) { static const char * const classnames[] = - {"variable", "function", "type", "method"}; + {"variable", "function", "type"}; struct symbol_search *symbols; struct symbol_search *p; struct cleanup *old_chain; char *last_filename = NULL; int first = 1; + gdb_assert (kind <= TYPES_DOMAIN); + /* Must make sure that if we're interrupted, symbols gets freed. */ search_symbols (regexp, kind, 0, (char **) NULL, &symbols); old_chain = make_cleanup_free_search_symbols (symbols); @@ -3356,7 +3556,7 @@ symtab_symbol_info (char *regexp, domain_enum kind, int from_tty) printf_filtered (regexp ? "All %ss matching regular expression \"%s\":\n" : "All defined %ss:\n", - classnames[(int) (kind - VARIABLES_DOMAIN)], regexp); + classnames[kind], regexp); for (p = symbols; p != NULL; p = p->next) { @@ -3517,7 +3717,11 @@ rbreak_command (char *regexp, int from_tty) static int compare_symbol_name (const char *name, const char *sym_text, int sym_text_len) { - if (strncmp (name, sym_text, sym_text_len) != 0) + int (*ncmp) (const char *, const char *, size_t); + + ncmp = (case_sensitivity == case_sensitive_on ? strncmp : strncasecmp); + + if (ncmp (name, sym_text, sym_text_len) != 0) return 0; if (sym_text[sym_text_len] == '(') @@ -3535,6 +3739,30 @@ compare_symbol_name (const char *name, const char *sym_text, int sym_text_len) return 1; } +/* Free any memory associated with a completion list. */ + +static void +free_completion_list (char ***list_ptr) +{ + int i = 0; + char **list = *list_ptr; + + while (list[i] != NULL) + { + xfree (list[i]); + i++; + } + xfree (list); +} + +/* Callback for make_cleanup. */ + +static void +do_free_completion_list (void *list) +{ + free_completion_list (list); +} + /* Helper routine for make_symbol_completion_list. */ static int return_val_size; @@ -3733,6 +3961,7 @@ struct add_name_data This adds a macro's name to the current completion list. */ static void add_macro_name (const char *name, const struct macro_definition *ignore, + struct macro_source_file *ignore2, int ignore3, void *user_data) { struct add_name_data *datum = (struct add_name_data *) user_data; @@ -3744,7 +3973,8 @@ add_macro_name (const char *name, const struct macro_definition *ignore, /* A callback for expand_partial_symbol_names. */ static int -expand_partial_symbol_name (const char *name, void *user_data) +expand_partial_symbol_name (const struct language_defn *language, + const char *name, void *user_data) { struct add_name_data *datum = (struct add_name_data *) user_data; @@ -3771,6 +4001,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, /* Length of sym_text. */ int sym_text_len; struct add_name_data datum; + struct cleanup *back_to; /* Now look for the symbol we are supposed to complete on. */ { @@ -3847,6 +4078,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, return_val_index = 0; return_val = (char **) xmalloc ((return_val_size + 1) * sizeof (char *)); return_val[0] = NULL; + back_to = make_cleanup (do_free_completion_list, &return_val); datum.sym_text = sym_text; datum.sym_text_len = sym_text_len; @@ -3956,6 +4188,7 @@ default_make_symbol_completion_list_break_on (char *text, char *word, macro_for_each (macro_user_macros, add_macro_name, &datum); } + discard_cleanups (back_to); return (return_val); } @@ -4205,12 +4438,15 @@ make_source_files_completion_list (char *text, char *word) char **list = (char **) xmalloc (list_alloced * sizeof (char *)); const char *base_name; struct add_partial_filename_data datum; + struct cleanup *back_to; list[0] = NULL; if (!have_full_symbols () && !have_partial_symbols ()) return list; + back_to = make_cleanup (do_free_completion_list, &list); + ALL_SYMTABS (objfile, s) { if (not_interesting_fname (s->filename)) @@ -4245,7 +4481,9 @@ make_source_files_completion_list (char *text, char *word) datum.list = &list; datum.list_used = &list_used; datum.list_alloced = &list_alloced; - map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum); + map_partial_symbol_filenames (maybe_add_partial_symtab_filename, &datum, + 0 /*need_fullname*/); + discard_cleanups (back_to); return list; } @@ -4337,8 +4575,8 @@ in_prologue (struct gdbarch *gdbarch, CORE_ADDR pc, CORE_ADDR func_start) The functions end point and an increasing SAL line are used as indicators of the prologue's endpoint. - This code is based on the function refine_prologue_limit (versions - found in both ia64 and ppc). */ + This code is based on the function refine_prologue_limit + (found in ia64). */ CORE_ADDR skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) @@ -4355,7 +4593,7 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) prologue_sal = find_pc_line (start_pc, 0); if (prologue_sal.line != 0) { - /* For langauges other than assembly, treat two consecutive line + /* For languages other than assembly, treat two consecutive line entries at the same address as a zero-instruction prologue. The GNU assembler emits separate line notes for each instruction in a multi-instruction macro, but compilers generally will not @@ -4434,7 +4672,7 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr) } struct symtabs_and_lines -decode_line_spec (char *string, int funfirstline) +decode_line_spec (char *string, int flags) { struct symtabs_and_lines sals; struct symtab_and_line cursal; @@ -4446,9 +4684,8 @@ decode_line_spec (char *string, int funfirstline) and get a default or it will recursively call us! */ cursal = get_current_source_symtab_and_line (); - sals = decode_line_1 (&string, funfirstline, - cursal.symtab, cursal.line, - NULL); + sals = decode_line_1 (&string, flags, + cursal.symtab, cursal.line); if (*string) error (_("Junk at end of line specification: %s"), string); @@ -4536,212 +4773,6 @@ symtab_observer_executable_changed (void) set_main_name (NULL); } -/* Helper to expand_line_sal below. Appends new sal to SAL, - initializing it from SYMTAB, LINENO and PC. */ -static void -append_expanded_sal (struct symtabs_and_lines *sal, - struct program_space *pspace, - struct symtab *symtab, - int lineno, CORE_ADDR pc) -{ - sal->sals = xrealloc (sal->sals, - sizeof (sal->sals[0]) - * (sal->nelts + 1)); - init_sal (sal->sals + sal->nelts); - sal->sals[sal->nelts].pspace = pspace; - sal->sals[sal->nelts].symtab = symtab; - sal->sals[sal->nelts].section = NULL; - sal->sals[sal->nelts].end = 0; - sal->sals[sal->nelts].line = lineno; - sal->sals[sal->nelts].pc = pc; - ++sal->nelts; -} - -/* Helper to expand_line_sal below. Search in the symtabs for any - linetable entry that exactly matches FULLNAME and LINENO and append - them to RET. If FULLNAME is NULL or if a symtab has no full name, - use FILENAME and LINENO instead. If there is at least one match, - return 1; otherwise, return 0, and return the best choice in BEST_ITEM - and BEST_SYMTAB. */ - -static int -append_exact_match_to_sals (char *filename, char *fullname, int lineno, - struct symtabs_and_lines *ret, - struct linetable_entry **best_item, - struct symtab **best_symtab) -{ - struct program_space *pspace; - struct objfile *objfile; - struct symtab *symtab; - int exact = 0; - int j; - *best_item = 0; - *best_symtab = 0; - - ALL_PSPACES (pspace) - ALL_PSPACE_SYMTABS (pspace, objfile, symtab) - { - if (FILENAME_CMP (filename, symtab->filename) == 0) - { - struct linetable *l; - int len; - - if (fullname != NULL - && symtab_to_fullname (symtab) != NULL - && FILENAME_CMP (fullname, symtab->fullname) != 0) - continue; - l = LINETABLE (symtab); - if (!l) - continue; - len = l->nitems; - - for (j = 0; j < len; j++) - { - struct linetable_entry *item = &(l->item[j]); - - if (item->line == lineno) - { - exact = 1; - append_expanded_sal (ret, objfile->pspace, - symtab, lineno, item->pc); - } - else if (!exact && item->line > lineno - && (*best_item == NULL - || item->line < (*best_item)->line)) - { - *best_item = item; - *best_symtab = symtab; - } - } - } - } - return exact; -} - -/* Compute a set of all sals in all program spaces that correspond to - same file and line as SAL and return those. If there are several - sals that belong to the same block, only one sal for the block is - included in results. */ - -struct symtabs_and_lines -expand_line_sal (struct symtab_and_line sal) -{ - struct symtabs_and_lines ret; - int i, j; - struct objfile *objfile; - int lineno; - int deleted = 0; - struct block **blocks = NULL; - int *filter; - struct cleanup *old_chain; - - ret.nelts = 0; - ret.sals = NULL; - - /* Only expand sals that represent file.c:line. */ - if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0) - { - ret.sals = xmalloc (sizeof (struct symtab_and_line)); - ret.sals[0] = sal; - ret.nelts = 1; - return ret; - } - else - { - struct program_space *pspace; - struct linetable_entry *best_item = 0; - struct symtab *best_symtab = 0; - int exact = 0; - char *match_filename; - - lineno = sal.line; - match_filename = sal.symtab->filename; - - /* We need to find all symtabs for a file which name - is described by sal. We cannot just directly - iterate over symtabs, since a symtab might not be - yet created. We also cannot iterate over psymtabs, - calling PSYMTAB_TO_SYMTAB and working on that symtab, - since PSYMTAB_TO_SYMTAB will return NULL for psymtab - corresponding to an included file. Therefore, we do - first pass over psymtabs, reading in those with - the right name. Then, we iterate over symtabs, knowing - that all symtabs we're interested in are loaded. */ - - old_chain = save_current_program_space (); - ALL_PSPACES (pspace) - { - set_current_program_space (pspace); - ALL_PSPACE_OBJFILES (pspace, objfile) - { - if (objfile->sf) - objfile->sf->qf->expand_symtabs_with_filename (objfile, - sal.symtab->filename); - } - } - do_cleanups (old_chain); - - /* Now search the symtab for exact matches and append them. If - none is found, append the best_item and all its exact - matches. */ - symtab_to_fullname (sal.symtab); - exact = append_exact_match_to_sals (sal.symtab->filename, - sal.symtab->fullname, lineno, - &ret, &best_item, &best_symtab); - if (!exact && best_item) - append_exact_match_to_sals (best_symtab->filename, - best_symtab->fullname, best_item->line, - &ret, &best_item, &best_symtab); - } - - /* For optimized code, compiler can scatter one source line accross - disjoint ranges of PC values, even when no duplicate functions - or inline functions are involved. For example, 'for (;;)' inside - non-template non-inline non-ctor-or-dtor function can result - in two PC ranges. In this case, we don't want to set breakpoint - on first PC of each range. To filter such cases, we use containing - blocks -- for each PC found above we see if there are other PCs - that are in the same block. If yes, the other PCs are filtered out. */ - - old_chain = save_current_program_space (); - filter = alloca (ret.nelts * sizeof (int)); - blocks = alloca (ret.nelts * sizeof (struct block *)); - for (i = 0; i < ret.nelts; ++i) - { - set_current_program_space (ret.sals[i].pspace); - - filter[i] = 1; - blocks[i] = block_for_pc_sect (ret.sals[i].pc, ret.sals[i].section); - - } - do_cleanups (old_chain); - - for (i = 0; i < ret.nelts; ++i) - if (blocks[i] != NULL) - for (j = i+1; j < ret.nelts; ++j) - if (blocks[j] == blocks[i]) - { - filter[j] = 0; - ++deleted; - break; - } - - { - struct symtab_and_line *final = - xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted)); - - for (i = 0, j = 0; i < ret.nelts; ++i) - if (filter[i]) - final[j++] = ret.sals[i]; - - ret.nelts -= deleted; - xfree (ret.sals); - ret.sals = final; - } - - return ret; -} - /* Return 1 if the supplied producer string matches the ARM RealView compiler (armcc). */ @@ -4814,5 +4845,19 @@ Show how the debugger handles ambiguities in expressions."), _("\ Valid values are \"ask\", \"all\", \"cancel\", and the default is \"all\"."), NULL, NULL, &setlist, &showlist); + add_setshow_boolean_cmd ("basenames-may-differ", class_obscure, + &basenames_may_differ, _("\ +Set whether a source file may have multiple base names."), _("\ +Show whether a source file may have multiple base names."), _("\ +(A \"base name\" is the name of a file with the directory part removed.\n\ +Example: The base name of \"/home/user/hello.c\" is \"hello.c\".)\n\ +If set, GDB will canonicalize file names (e.g., expand symlinks)\n\ +before comparing them. Canonicalization is an expensive operation,\n\ +but it allows the same file be known by more than one base name.\n\ +If not set (the default), all source files are assumed to have just\n\ +one base name, and gdb will do file name comparisons more efficiently."), + NULL, NULL, + &setlist, &showlist); + observer_attach_executable_changed (symtab_observer_executable_changed); } diff --git a/contrib/gdb-7/gdb/symtab.h b/contrib/gdb-7/gdb/symtab.h index 9d236850ad..9a26656acd 100644 --- a/contrib/gdb-7/gdb/symtab.h +++ b/contrib/gdb-7/gdb/symtab.h @@ -1,8 +1,7 @@ /* Symbol table definitions for GDB. - Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, - 2011 Free Software Foundation, Inc. + Copyright (C) 1986, 1988-2004, 2007-2012 Free Software Foundation, + Inc. This file is part of GDB. @@ -22,6 +21,8 @@ #if !defined (SYMTAB_H) #define SYMTAB_H 1 +#include "vec.h" + /* Opaque declarations. */ struct ui_file; struct frame_info; @@ -33,6 +34,7 @@ struct blockvector; struct axs_value; struct agent_expr; struct program_space; +struct language_defn; /* Some of the structures in this file are space critical. The space-critical structures are: @@ -243,11 +245,14 @@ extern char *symbol_demangled_name (const struct general_symbol_info *symbol); name if demangle is on and the "mangled" form of the name if demangle is off. In other languages this is just the symbol name. The result should never be NULL. Don't use this for internal - purposes (e.g. storing in a hashtable): it's only suitable for - output. */ + purposes (e.g. storing in a hashtable): it's only suitable for output. + + N.B. symbol may be anything with a ginfo member, + e.g., struct symbol or struct minimal_symbol. */ #define SYMBOL_PRINT_NAME(symbol) \ (demangle ? SYMBOL_NATURAL_NAME (symbol) : SYMBOL_LINKAGE_NAME (symbol)) +extern int demangle; /* Macro that tests a symbol for a match against a specified name string. First test the unencoded name, then looks for and test a C++ encoded @@ -395,25 +400,27 @@ typedef enum domain_enum_tag /* LABEL_DOMAIN may be used for names of labels (for gotos). */ - LABEL_DOMAIN, + LABEL_DOMAIN +} domain_enum; - /* Searching domains. These overlap with VAR_DOMAIN, providing - some granularity with the search_symbols function. */ +/* Searching domains, used for `search_symbols'. Element numbers are + hardcoded in GDB, check all enum uses before changing it. */ +enum search_domain +{ /* Everything in VAR_DOMAIN minus FUNCTIONS_DOMAIN and TYPES_DOMAIN. */ - VARIABLES_DOMAIN, + VARIABLES_DOMAIN = 0, /* All functions -- for some reason not methods, though. */ - FUNCTIONS_DOMAIN, + FUNCTIONS_DOMAIN = 1, /* All defined types */ - TYPES_DOMAIN, + TYPES_DOMAIN = 2, /* Any type. */ - ALL_DOMAIN -} -domain_enum; + ALL_DOMAIN = 3 +}; /* An address-class says where to find the value of a symbol. */ @@ -530,6 +537,12 @@ struct symbol_computed_ops struct value *(*read_variable) (struct symbol * symbol, struct frame_info * frame); + /* Read variable SYMBOL like read_variable at (callee) FRAME's function + entry. SYMBOL should be a function parameter, otherwise + NO_ENTRY_VALUE_ERROR will be thrown. */ + struct value *(*read_variable_at_entry) (struct symbol *symbol, + struct frame_info *frame); + /* Return non-zero if we need a frame to find the value of the SYMBOL. */ int (*read_needs_frame) (struct symbol * symbol); @@ -776,6 +789,11 @@ struct symtab unsigned int locations_valid : 1; + /* DWARF unwinder for this CU is valid even for epilogues (PC at the return + instruction). This is supported by GCC since 4.5.0. */ + + unsigned int epilogue_unwind_valid : 1; + /* The macro table for this symtab. Like the blockvector, this may be shared between different symtabs --- and normally is for all the symtabs in a given compilation unit. */ @@ -789,23 +807,6 @@ struct symtab char *dirname; - /* This component says how to free the data we point to: - free_nothing => do nothing; some other symtab will free - the data this one uses. - free_linetable => free just the linetable. FIXME: Is this redundant - with the primary field? */ - - enum free_code - { - free_nothing, free_linetable - } - free_code; - - /* A function to call to free space, if necessary. This is IN - ADDITION to the action indicated by free_code. */ - - void (*free_func)(struct symtab *symtab); - /* Total number of lines found in source file. */ int nlines; @@ -825,11 +826,11 @@ struct symtab for automated testing of gdb but may also be information that is useful to the user. */ - char *debugformat; + const char *debugformat; /* String of producer version information. May be zero. */ - char *producer; + const char *producer; /* Full name of file as found by searching the source path. NULL if not yet known. */ @@ -840,6 +841,9 @@ struct symtab struct objfile *objfile; + /* struct call_site entries for this compilation unit or NULL. */ + + htab_t call_site_htab; }; #define BLOCKVECTOR(symtab) (symtab)->blockvector @@ -862,18 +866,10 @@ struct symtab /* External variables and functions for the objects described above. */ -/* See the comment in symfile.c about how current_objfile is used. */ - -extern struct objfile *current_objfile; - /* True if we are nested inside psymtab_to_symtab. */ extern int currently_reading_symtab; -/* From utils.c. */ -extern int demangle; -extern int asm_demangle; - /* symtab.c lookup functions */ extern const char multiple_symbols_ask[]; @@ -936,6 +932,9 @@ extern struct symbol *lookup_symbol_aux_block (const char *name, const struct block *block, const domain_enum domain); +extern struct symbol *lookup_language_this (const struct language_defn *lang, + const struct block *block); + /* Lookup a symbol only in the file static scope of all the objfiles. */ struct symbol *lookup_static_symbol_aux (const char *name, @@ -949,11 +948,11 @@ extern struct symbol *lookup_block_symbol (const struct block *, const char *, /* lookup a [struct, union, enum] by name, within a specified block. */ -extern struct type *lookup_struct (char *, struct block *); +extern struct type *lookup_struct (const char *, struct block *); -extern struct type *lookup_union (char *, struct block *); +extern struct type *lookup_union (const char *, struct block *); -extern struct type *lookup_enum (char *, struct block *); +extern struct type *lookup_enum (const char *, struct block *); /* from blockframe.c: */ @@ -1029,6 +1028,13 @@ extern unsigned int msymbol_hash_iw (const char *); extern unsigned int msymbol_hash (const char *); +/* Compute the next hash value from previous HASH and the character C. This + is only a GDB in-memory computed value with no external files compatibility + requirements. */ + +#define SYMBOL_HASH_NEXT(hash, c) \ + ((hash) * 67 + tolower ((unsigned char) (c)) - 113) + extern struct objfile * msymbol_objfile (struct minimal_symbol *sym); extern void @@ -1051,6 +1057,12 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR); +extern void iterate_over_minimal_symbols (struct objfile *objf, + const char *name, + void (*callback) (struct minimal_symbol *, + void *), + void *user_data); + extern int in_gnu_ifunc_stub (CORE_ADDR pc); /* Functions for resolving STT_GNU_IFUNC symbols which are implemented only @@ -1190,8 +1202,6 @@ void maintenance_check_symtabs (char *, int); void maintenance_print_statistics (char *, int); -extern void free_symtab (struct symtab *); - /* Symbol-reading stuff in symfile.c and solib.c. */ extern void clear_solib (void); @@ -1202,6 +1212,7 @@ extern int identify_source_line (struct symtab *, int, int, CORE_ADDR); extern void print_source_lines (struct symtab *, int, int, int); +extern void forget_cached_source_info_for_objfile (struct objfile *); extern void forget_cached_source_info (void); extern void select_source_symtab (struct symtab *); @@ -1272,7 +1283,7 @@ struct symbol_search struct symbol_search *next; }; -extern void search_symbols (char *, domain_enum, int, char **, +extern void search_symbols (char *, enum search_domain, int, char **, struct symbol_search **); extern void free_search_symbols (struct symbol_search *); extern struct cleanup *make_cleanup_free_search_symbols (struct symbol_search @@ -1291,8 +1302,6 @@ struct symbol *lookup_global_symbol_from_objfile (const struct objfile *, const char *name, const domain_enum domain); -extern struct symtabs_and_lines expand_line_sal (struct symtab_and_line sal); - /* Return 1 if the supplied producer string matches the ARM RealView compiler (armcc). */ int producer_is_realview (const char *producer); @@ -1302,4 +1311,33 @@ void fixup_section (struct general_symbol_info *ginfo, struct objfile *lookup_objfile_from_block (const struct block *block); +extern int basenames_may_differ; + +int iterate_over_some_symtabs (const char *name, + const char *full_path, + const char *real_path, + int (*callback) (struct symtab *symtab, + void *data), + void *data, + struct symtab *first, + struct symtab *after_last); + +void iterate_over_symtabs (const char *name, + int (*callback) (struct symtab *symtab, + void *data), + void *data); + +DEF_VEC_I (CORE_ADDR); + +VEC (CORE_ADDR) *find_pcs_for_symtab_line (struct symtab *symtab, int line, + struct linetable_entry **best_entry); + +void iterate_over_symbols (const struct block *block, const char *name, + const domain_enum domain, + int (*callback) (struct symbol *, void *), + void *data); + +struct cleanup *demangle_for_lookup (const char *name, enum language lang, + const char **result_name); + #endif /* !defined(SYMTAB_H) */ diff --git a/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd b/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd index 0735ecddcd..63a1339e08 100644 --- a/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd +++ b/contrib/gdb-7/gdb/syscalls/gdb-syscalls.dtd @@ -1,4 +1,4 @@ -