mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-05-28 06:03:00 +08:00

Many spots incorrectly use only spaces for indentation (for example, there are a lot of spots in ada-lang.c). I've always found it awkward when I needed to edit one of these spots: do I keep the original wrong indentation, or do I fix it? What if the lines around it are also wrong, do I fix them too? I probably don't want to fix them in the same patch, to avoid adding noise to my patch. So I propose to fix as much as possible once and for all (hopefully). One typical counter argument for this is that it makes code archeology more difficult, because git-blame will show this commit as the last change for these lines. My counter counter argument is: when git-blaming, you often need to do "blame the file at the parent commit" anyway, to go past some other refactor that touched the line you are interested in, but is not the change you are looking for. So you already need a somewhat efficient way to do this. Using some interactive tool, rather than plain git-blame, makes this trivial. For example, I use "tig blame <file>", where going back past the commit that changed the currently selected line is one keystroke. It looks like Magit in Emacs does it too (though I've never used it). Web viewers of Github and Gitlab do it too. My point is that it won't really make archeology more difficult. The other typical counter argument is that it will cause conflicts with existing patches. That's true... but it's a one time cost, and those are not conflicts that are difficult to resolve. I have also tried "git rebase --ignore-whitespace", it seems to work well. Although that will re-introduce the faulty indentation, so one needs to take care of fixing the indentation in the patch after that (which is easy). gdb/ChangeLog: * aarch64-linux-tdep.c: Fix indentation. * aarch64-ravenscar-thread.c: Fix indentation. * aarch64-tdep.c: Fix indentation. * aarch64-tdep.h: Fix indentation. * ada-lang.c: Fix indentation. * ada-lang.h: Fix indentation. * ada-tasks.c: Fix indentation. * ada-typeprint.c: Fix indentation. * ada-valprint.c: Fix indentation. * ada-varobj.c: Fix indentation. * addrmap.c: Fix indentation. * addrmap.h: Fix indentation. * agent.c: Fix indentation. * aix-thread.c: Fix indentation. * alpha-bsd-nat.c: Fix indentation. * alpha-linux-tdep.c: Fix indentation. * alpha-mdebug-tdep.c: Fix indentation. * alpha-nbsd-tdep.c: Fix indentation. * alpha-obsd-tdep.c: Fix indentation. * alpha-tdep.c: Fix indentation. * amd64-bsd-nat.c: Fix indentation. * amd64-darwin-tdep.c: Fix indentation. * amd64-linux-nat.c: Fix indentation. * amd64-linux-tdep.c: Fix indentation. * amd64-nat.c: Fix indentation. * amd64-obsd-tdep.c: Fix indentation. * amd64-tdep.c: Fix indentation. * amd64-windows-tdep.c: Fix indentation. * annotate.c: Fix indentation. * arc-tdep.c: Fix indentation. * arch-utils.c: Fix indentation. * arch/arm-get-next-pcs.c: Fix indentation. * arch/arm.c: Fix indentation. * arm-linux-nat.c: Fix indentation. * arm-linux-tdep.c: Fix indentation. * arm-nbsd-tdep.c: Fix indentation. * arm-pikeos-tdep.c: Fix indentation. * arm-tdep.c: Fix indentation. * arm-tdep.h: Fix indentation. * arm-wince-tdep.c: Fix indentation. * auto-load.c: Fix indentation. * auxv.c: Fix indentation. * avr-tdep.c: Fix indentation. * ax-gdb.c: Fix indentation. * ax-general.c: Fix indentation. * bfin-linux-tdep.c: Fix indentation. * block.c: Fix indentation. * block.h: Fix indentation. * blockframe.c: Fix indentation. * bpf-tdep.c: Fix indentation. * break-catch-sig.c: Fix indentation. * break-catch-syscall.c: Fix indentation. * break-catch-throw.c: Fix indentation. * breakpoint.c: Fix indentation. * breakpoint.h: Fix indentation. * bsd-uthread.c: Fix indentation. * btrace.c: Fix indentation. * build-id.c: Fix indentation. * buildsym-legacy.h: Fix indentation. * buildsym.c: Fix indentation. * c-typeprint.c: Fix indentation. * c-valprint.c: Fix indentation. * c-varobj.c: Fix indentation. * charset.c: Fix indentation. * cli/cli-cmds.c: Fix indentation. * cli/cli-decode.c: Fix indentation. * cli/cli-decode.h: Fix indentation. * cli/cli-script.c: Fix indentation. * cli/cli-setshow.c: Fix indentation. * coff-pe-read.c: Fix indentation. * coffread.c: Fix indentation. * compile/compile-cplus-types.c: Fix indentation. * compile/compile-object-load.c: Fix indentation. * compile/compile-object-run.c: Fix indentation. * completer.c: Fix indentation. * corefile.c: Fix indentation. * corelow.c: Fix indentation. * cp-abi.h: Fix indentation. * cp-namespace.c: Fix indentation. * cp-support.c: Fix indentation. * cp-valprint.c: Fix indentation. * cris-linux-tdep.c: Fix indentation. * cris-tdep.c: Fix indentation. * darwin-nat-info.c: Fix indentation. * darwin-nat.c: Fix indentation. * darwin-nat.h: Fix indentation. * dbxread.c: Fix indentation. * dcache.c: Fix indentation. * disasm.c: Fix indentation. * dtrace-probe.c: Fix indentation. * dwarf2/abbrev.c: Fix indentation. * dwarf2/attribute.c: Fix indentation. * dwarf2/expr.c: Fix indentation. * dwarf2/frame.c: Fix indentation. * dwarf2/index-cache.c: Fix indentation. * dwarf2/index-write.c: Fix indentation. * dwarf2/line-header.c: Fix indentation. * dwarf2/loc.c: Fix indentation. * dwarf2/macro.c: Fix indentation. * dwarf2/read.c: Fix indentation. * dwarf2/read.h: Fix indentation. * elfread.c: Fix indentation. * eval.c: Fix indentation. * event-top.c: Fix indentation. * exec.c: Fix indentation. * exec.h: Fix indentation. * expprint.c: Fix indentation. * f-lang.c: Fix indentation. * f-typeprint.c: Fix indentation. * f-valprint.c: Fix indentation. * fbsd-nat.c: Fix indentation. * fbsd-tdep.c: Fix indentation. * findvar.c: Fix indentation. * fork-child.c: Fix indentation. * frame-unwind.c: Fix indentation. * frame-unwind.h: Fix indentation. * frame.c: Fix indentation. * frv-linux-tdep.c: Fix indentation. * frv-tdep.c: Fix indentation. * frv-tdep.h: Fix indentation. * ft32-tdep.c: Fix indentation. * gcore.c: Fix indentation. * gdb_bfd.c: Fix indentation. * gdbarch.sh: Fix indentation. * gdbarch.c: Re-generate * gdbarch.h: Re-generate. * gdbcore.h: Fix indentation. * gdbthread.h: Fix indentation. * gdbtypes.c: Fix indentation. * gdbtypes.h: Fix indentation. * glibc-tdep.c: Fix indentation. * gnu-nat.c: Fix indentation. * gnu-nat.h: Fix indentation. * gnu-v2-abi.c: Fix indentation. * gnu-v3-abi.c: Fix indentation. * go32-nat.c: Fix indentation. * guile/guile-internal.h: Fix indentation. * guile/scm-cmd.c: Fix indentation. * guile/scm-frame.c: Fix indentation. * guile/scm-iterator.c: Fix indentation. * guile/scm-math.c: Fix indentation. * guile/scm-ports.c: Fix indentation. * guile/scm-pretty-print.c: Fix indentation. * guile/scm-value.c: Fix indentation. * h8300-tdep.c: Fix indentation. * hppa-linux-nat.c: Fix indentation. * hppa-linux-tdep.c: Fix indentation. * hppa-nbsd-nat.c: Fix indentation. * hppa-nbsd-tdep.c: Fix indentation. * hppa-obsd-nat.c: Fix indentation. * hppa-tdep.c: Fix indentation. * hppa-tdep.h: Fix indentation. * i386-bsd-nat.c: Fix indentation. * i386-darwin-nat.c: Fix indentation. * i386-darwin-tdep.c: Fix indentation. * i386-dicos-tdep.c: Fix indentation. * i386-gnu-nat.c: Fix indentation. * i386-linux-nat.c: Fix indentation. * i386-linux-tdep.c: Fix indentation. * i386-nto-tdep.c: Fix indentation. * i386-obsd-tdep.c: Fix indentation. * i386-sol2-nat.c: Fix indentation. * i386-tdep.c: Fix indentation. * i386-tdep.h: Fix indentation. * i386-windows-tdep.c: Fix indentation. * i387-tdep.c: Fix indentation. * i387-tdep.h: Fix indentation. * ia64-libunwind-tdep.c: Fix indentation. * ia64-libunwind-tdep.h: Fix indentation. * ia64-linux-nat.c: Fix indentation. * ia64-linux-tdep.c: Fix indentation. * ia64-tdep.c: Fix indentation. * ia64-tdep.h: Fix indentation. * ia64-vms-tdep.c: Fix indentation. * infcall.c: Fix indentation. * infcmd.c: Fix indentation. * inferior.c: Fix indentation. * infrun.c: Fix indentation. * iq2000-tdep.c: Fix indentation. * language.c: Fix indentation. * linespec.c: Fix indentation. * linux-fork.c: Fix indentation. * linux-nat.c: Fix indentation. * linux-tdep.c: Fix indentation. * linux-thread-db.c: Fix indentation. * lm32-tdep.c: Fix indentation. * m2-lang.c: Fix indentation. * m2-typeprint.c: Fix indentation. * m2-valprint.c: Fix indentation. * m32c-tdep.c: Fix indentation. * m32r-linux-tdep.c: Fix indentation. * m32r-tdep.c: Fix indentation. * m68hc11-tdep.c: Fix indentation. * m68k-bsd-nat.c: Fix indentation. * m68k-linux-nat.c: Fix indentation. * m68k-linux-tdep.c: Fix indentation. * m68k-tdep.c: Fix indentation. * machoread.c: Fix indentation. * macrocmd.c: Fix indentation. * macroexp.c: Fix indentation. * macroscope.c: Fix indentation. * macrotab.c: Fix indentation. * macrotab.h: Fix indentation. * main.c: Fix indentation. * mdebugread.c: Fix indentation. * mep-tdep.c: Fix indentation. * mi/mi-cmd-catch.c: Fix indentation. * mi/mi-cmd-disas.c: Fix indentation. * mi/mi-cmd-env.c: Fix indentation. * mi/mi-cmd-stack.c: Fix indentation. * mi/mi-cmd-var.c: Fix indentation. * mi/mi-cmds.c: Fix indentation. * mi/mi-main.c: Fix indentation. * mi/mi-parse.c: Fix indentation. * microblaze-tdep.c: Fix indentation. * minidebug.c: Fix indentation. * minsyms.c: Fix indentation. * mips-linux-nat.c: Fix indentation. * mips-linux-tdep.c: Fix indentation. * mips-nbsd-tdep.c: Fix indentation. * mips-tdep.c: Fix indentation. * mn10300-linux-tdep.c: Fix indentation. * mn10300-tdep.c: Fix indentation. * moxie-tdep.c: Fix indentation. * msp430-tdep.c: Fix indentation. * namespace.h: Fix indentation. * nat/fork-inferior.c: Fix indentation. * nat/gdb_ptrace.h: Fix indentation. * nat/linux-namespaces.c: Fix indentation. * nat/linux-osdata.c: Fix indentation. * nat/netbsd-nat.c: Fix indentation. * nat/x86-dregs.c: Fix indentation. * nbsd-nat.c: Fix indentation. * nbsd-tdep.c: Fix indentation. * nios2-linux-tdep.c: Fix indentation. * nios2-tdep.c: Fix indentation. * nto-procfs.c: Fix indentation. * nto-tdep.c: Fix indentation. * objfiles.c: Fix indentation. * objfiles.h: Fix indentation. * opencl-lang.c: Fix indentation. * or1k-tdep.c: Fix indentation. * osabi.c: Fix indentation. * osabi.h: Fix indentation. * osdata.c: Fix indentation. * p-lang.c: Fix indentation. * p-typeprint.c: Fix indentation. * p-valprint.c: Fix indentation. * parse.c: Fix indentation. * ppc-linux-nat.c: Fix indentation. * ppc-linux-tdep.c: Fix indentation. * ppc-nbsd-nat.c: Fix indentation. * ppc-nbsd-tdep.c: Fix indentation. * ppc-obsd-nat.c: Fix indentation. * ppc-ravenscar-thread.c: Fix indentation. * ppc-sysv-tdep.c: Fix indentation. * ppc64-tdep.c: Fix indentation. * printcmd.c: Fix indentation. * proc-api.c: Fix indentation. * producer.c: Fix indentation. * producer.h: Fix indentation. * prologue-value.c: Fix indentation. * prologue-value.h: Fix indentation. * psymtab.c: Fix indentation. * python/py-arch.c: Fix indentation. * python/py-bpevent.c: Fix indentation. * python/py-event.c: Fix indentation. * python/py-event.h: Fix indentation. * python/py-finishbreakpoint.c: Fix indentation. * python/py-frame.c: Fix indentation. * python/py-framefilter.c: Fix indentation. * python/py-inferior.c: Fix indentation. * python/py-infthread.c: Fix indentation. * python/py-objfile.c: Fix indentation. * python/py-prettyprint.c: Fix indentation. * python/py-registers.c: Fix indentation. * python/py-signalevent.c: Fix indentation. * python/py-stopevent.c: Fix indentation. * python/py-stopevent.h: Fix indentation. * python/py-threadevent.c: Fix indentation. * python/py-tui.c: Fix indentation. * python/py-unwind.c: Fix indentation. * python/py-value.c: Fix indentation. * python/py-xmethods.c: Fix indentation. * python/python-internal.h: Fix indentation. * python/python.c: Fix indentation. * ravenscar-thread.c: Fix indentation. * record-btrace.c: Fix indentation. * record-full.c: Fix indentation. * record.c: Fix indentation. * reggroups.c: Fix indentation. * regset.h: Fix indentation. * remote-fileio.c: Fix indentation. * remote.c: Fix indentation. * reverse.c: Fix indentation. * riscv-linux-tdep.c: Fix indentation. * riscv-ravenscar-thread.c: Fix indentation. * riscv-tdep.c: Fix indentation. * rl78-tdep.c: Fix indentation. * rs6000-aix-tdep.c: Fix indentation. * rs6000-lynx178-tdep.c: Fix indentation. * rs6000-nat.c: Fix indentation. * rs6000-tdep.c: Fix indentation. * rust-lang.c: Fix indentation. * rx-tdep.c: Fix indentation. * s12z-tdep.c: Fix indentation. * s390-linux-tdep.c: Fix indentation. * score-tdep.c: Fix indentation. * ser-base.c: Fix indentation. * ser-mingw.c: Fix indentation. * ser-uds.c: Fix indentation. * ser-unix.c: Fix indentation. * serial.c: Fix indentation. * sh-linux-tdep.c: Fix indentation. * sh-nbsd-tdep.c: Fix indentation. * sh-tdep.c: Fix indentation. * skip.c: Fix indentation. * sol-thread.c: Fix indentation. * solib-aix.c: Fix indentation. * solib-darwin.c: Fix indentation. * solib-frv.c: Fix indentation. * solib-svr4.c: Fix indentation. * solib.c: Fix indentation. * source.c: Fix indentation. * sparc-linux-tdep.c: Fix indentation. * sparc-nbsd-tdep.c: Fix indentation. * sparc-obsd-tdep.c: Fix indentation. * sparc-ravenscar-thread.c: Fix indentation. * sparc-tdep.c: Fix indentation. * sparc64-linux-tdep.c: Fix indentation. * sparc64-nbsd-tdep.c: Fix indentation. * sparc64-obsd-tdep.c: Fix indentation. * sparc64-tdep.c: Fix indentation. * stabsread.c: Fix indentation. * stack.c: Fix indentation. * stap-probe.c: Fix indentation. * stubs/ia64vms-stub.c: Fix indentation. * stubs/m32r-stub.c: Fix indentation. * stubs/m68k-stub.c: Fix indentation. * stubs/sh-stub.c: Fix indentation. * stubs/sparc-stub.c: Fix indentation. * symfile-mem.c: Fix indentation. * symfile.c: Fix indentation. * symfile.h: Fix indentation. * symmisc.c: Fix indentation. * symtab.c: Fix indentation. * symtab.h: Fix indentation. * target-float.c: Fix indentation. * target.c: Fix indentation. * target.h: Fix indentation. * tic6x-tdep.c: Fix indentation. * tilegx-linux-tdep.c: Fix indentation. * tilegx-tdep.c: Fix indentation. * top.c: Fix indentation. * tracefile-tfile.c: Fix indentation. * tracepoint.c: Fix indentation. * tui/tui-disasm.c: Fix indentation. * tui/tui-io.c: Fix indentation. * tui/tui-regs.c: Fix indentation. * tui/tui-stack.c: Fix indentation. * tui/tui-win.c: Fix indentation. * tui/tui-winsource.c: Fix indentation. * tui/tui.c: Fix indentation. * typeprint.c: Fix indentation. * ui-out.h: Fix indentation. * unittests/copy_bitwise-selftests.c: Fix indentation. * unittests/memory-map-selftests.c: Fix indentation. * utils.c: Fix indentation. * v850-tdep.c: Fix indentation. * valarith.c: Fix indentation. * valops.c: Fix indentation. * valprint.c: Fix indentation. * valprint.h: Fix indentation. * value.c: Fix indentation. * value.h: Fix indentation. * varobj.c: Fix indentation. * vax-tdep.c: Fix indentation. * windows-nat.c: Fix indentation. * windows-tdep.c: Fix indentation. * xcoffread.c: Fix indentation. * xml-syscall.c: Fix indentation. * xml-tdesc.c: Fix indentation. * xstormy16-tdep.c: Fix indentation. * xtensa-config.c: Fix indentation. * xtensa-linux-nat.c: Fix indentation. * xtensa-linux-tdep.c: Fix indentation. * xtensa-tdep.c: Fix indentation. gdbserver/ChangeLog: * ax.cc: Fix indentation. * dll.cc: Fix indentation. * inferiors.h: Fix indentation. * linux-low.cc: Fix indentation. * linux-nios2-low.cc: Fix indentation. * linux-ppc-ipa.cc: Fix indentation. * linux-ppc-low.cc: Fix indentation. * linux-x86-low.cc: Fix indentation. * linux-xtensa-low.cc: Fix indentation. * regcache.cc: Fix indentation. * server.cc: Fix indentation. * tracepoint.cc: Fix indentation. gdbsupport/ChangeLog: * common-exceptions.h: Fix indentation. * event-loop.cc: Fix indentation. * fileio.cc: Fix indentation. * filestuff.cc: Fix indentation. * gdb-dlfcn.cc: Fix indentation. * gdb_string_view.h: Fix indentation. * job-control.cc: Fix indentation. * signals.cc: Fix indentation. Change-Id: I4bad7ae6be0fbe14168b8ebafb98ffe14964a695
1071 lines
28 KiB
C
1071 lines
28 KiB
C
/* Python interface to inferiors.
|
|
|
|
Copyright (C) 2009-2020 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "defs.h"
|
|
#include "gdbcore.h"
|
|
#include "gdbthread.h"
|
|
#include "inferior.h"
|
|
#include "objfiles.h"
|
|
#include "observable.h"
|
|
#include "python-internal.h"
|
|
#include "arch-utils.h"
|
|
#include "language.h"
|
|
#include "gdbsupport/gdb_signals.h"
|
|
#include "py-event.h"
|
|
#include "py-stopevent.h"
|
|
|
|
struct threadlist_entry
|
|
{
|
|
threadlist_entry (gdbpy_ref<thread_object> &&ref)
|
|
: thread_obj (std::move (ref))
|
|
{
|
|
}
|
|
|
|
gdbpy_ref<thread_object> thread_obj;
|
|
struct threadlist_entry *next;
|
|
};
|
|
|
|
struct inferior_object
|
|
{
|
|
PyObject_HEAD
|
|
|
|
/* The inferior we represent. */
|
|
struct inferior *inferior;
|
|
|
|
/* thread_object instances under this inferior. This list owns a
|
|
reference to each object it contains. */
|
|
struct threadlist_entry *threads;
|
|
|
|
/* Number of threads in the list. */
|
|
int nthreads;
|
|
};
|
|
|
|
extern PyTypeObject inferior_object_type
|
|
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("inferior_object");
|
|
|
|
static const struct inferior_data *infpy_inf_data_key;
|
|
|
|
typedef struct {
|
|
PyObject_HEAD
|
|
void *buffer;
|
|
|
|
/* These are kept just for mbpy_str. */
|
|
CORE_ADDR addr;
|
|
CORE_ADDR length;
|
|
} membuf_object;
|
|
|
|
extern PyTypeObject membuf_object_type
|
|
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("membuf_object");
|
|
|
|
/* Require that INFERIOR be a valid inferior ID. */
|
|
#define INFPY_REQUIRE_VALID(Inferior) \
|
|
do { \
|
|
if (!Inferior->inferior) \
|
|
{ \
|
|
PyErr_SetString (PyExc_RuntimeError, \
|
|
_("Inferior no longer exists.")); \
|
|
return NULL; \
|
|
} \
|
|
} while (0)
|
|
|
|
static void
|
|
python_on_normal_stop (struct bpstats *bs, int print_frame)
|
|
{
|
|
enum gdb_signal stop_signal;
|
|
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
if (inferior_ptid == null_ptid)
|
|
return;
|
|
|
|
stop_signal = inferior_thread ()->suspend.stop_signal;
|
|
|
|
gdbpy_enter enter_py (get_current_arch (), current_language);
|
|
|
|
if (emit_stop_event (bs, stop_signal) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
static void
|
|
python_on_resume (ptid_t ptid)
|
|
{
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (target_gdbarch (), current_language);
|
|
|
|
if (emit_continue_event (ptid) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
/* Callback, registered as an observer, that notifies Python listeners
|
|
when an inferior function call is about to be made. */
|
|
|
|
static void
|
|
python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
|
|
{
|
|
gdbpy_enter enter_py (target_gdbarch (), current_language);
|
|
|
|
if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
/* Callback, registered as an observer, that notifies Python listeners
|
|
when an inferior function call has completed. */
|
|
|
|
static void
|
|
python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
|
|
{
|
|
gdbpy_enter enter_py (target_gdbarch (), current_language);
|
|
|
|
if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
/* Callback, registered as an observer, that notifies Python listeners
|
|
when a part of memory has been modified by user action (eg via a
|
|
'set' command). */
|
|
|
|
static void
|
|
python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
|
|
{
|
|
gdbpy_enter enter_py (target_gdbarch (), current_language);
|
|
|
|
if (emit_memory_changed_event (addr, len) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
/* Callback, registered as an observer, that notifies Python listeners
|
|
when a register has been modified by user action (eg via a 'set'
|
|
command). */
|
|
|
|
static void
|
|
python_on_register_change (struct frame_info *frame, int regnum)
|
|
{
|
|
gdbpy_enter enter_py (target_gdbarch (), current_language);
|
|
|
|
if (emit_register_changed_event (frame, regnum) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
static void
|
|
python_inferior_exit (struct inferior *inf)
|
|
{
|
|
const LONGEST *exit_code = NULL;
|
|
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (target_gdbarch (), current_language);
|
|
|
|
if (inf->has_exit_code)
|
|
exit_code = &inf->exit_code;
|
|
|
|
if (emit_exited_event (exit_code, inf) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
/* Callback used to notify Python listeners about new objfiles loaded in the
|
|
inferior. OBJFILE may be NULL which means that the objfile list has been
|
|
cleared (emptied). */
|
|
|
|
static void
|
|
python_new_objfile (struct objfile *objfile)
|
|
{
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (objfile != NULL
|
|
? objfile->arch ()
|
|
: target_gdbarch (),
|
|
current_language);
|
|
|
|
if (objfile == NULL)
|
|
{
|
|
if (emit_clear_objfiles_event () < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
else
|
|
{
|
|
if (emit_new_objfile_event (objfile) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
}
|
|
|
|
/* Return a reference to the Python object of type Inferior
|
|
representing INFERIOR. If the object has already been created,
|
|
return it and increment the reference count, otherwise, create it.
|
|
Return NULL on failure. */
|
|
|
|
gdbpy_ref<inferior_object>
|
|
inferior_to_inferior_object (struct inferior *inferior)
|
|
{
|
|
inferior_object *inf_obj;
|
|
|
|
inf_obj = (inferior_object *) inferior_data (inferior, infpy_inf_data_key);
|
|
if (!inf_obj)
|
|
{
|
|
inf_obj = PyObject_New (inferior_object, &inferior_object_type);
|
|
if (!inf_obj)
|
|
return NULL;
|
|
|
|
inf_obj->inferior = inferior;
|
|
inf_obj->threads = NULL;
|
|
inf_obj->nthreads = 0;
|
|
|
|
/* PyObject_New initializes the new object with a refcount of 1. This
|
|
counts for the reference we are keeping in the inferior data. */
|
|
set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
|
|
}
|
|
|
|
/* We are returning a new reference. */
|
|
gdb_assert (inf_obj != nullptr);
|
|
return gdbpy_ref<inferior_object>::new_reference (inf_obj);
|
|
}
|
|
|
|
/* Called when a new inferior is created. Notifies any Python event
|
|
listeners. */
|
|
static void
|
|
python_new_inferior (struct inferior *inf)
|
|
{
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (python_gdbarch, python_language);
|
|
|
|
if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
|
|
return;
|
|
|
|
gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
|
|
if (inf_obj == NULL)
|
|
{
|
|
gdbpy_print_stack ();
|
|
return;
|
|
}
|
|
|
|
gdbpy_ref<> event = create_event_object (&new_inferior_event_object_type);
|
|
if (event == NULL
|
|
|| evpy_add_attribute (event.get (), "inferior",
|
|
(PyObject *) inf_obj.get ()) < 0
|
|
|| evpy_emit_event (event.get (), gdb_py_events.new_inferior) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
/* Called when an inferior is removed. Notifies any Python event
|
|
listeners. */
|
|
static void
|
|
python_inferior_deleted (struct inferior *inf)
|
|
{
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (python_gdbarch, python_language);
|
|
|
|
if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
|
|
return;
|
|
|
|
gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
|
|
if (inf_obj == NULL)
|
|
{
|
|
gdbpy_print_stack ();
|
|
return;
|
|
}
|
|
|
|
gdbpy_ref<> event = create_event_object (&inferior_deleted_event_object_type);
|
|
if (event == NULL
|
|
|| evpy_add_attribute (event.get (), "inferior",
|
|
(PyObject *) inf_obj.get ()) < 0
|
|
|| evpy_emit_event (event.get (), gdb_py_events.inferior_deleted) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
gdbpy_ref<>
|
|
thread_to_thread_object (thread_info *thr)
|
|
{
|
|
gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
|
|
if (inf_obj == NULL)
|
|
return NULL;
|
|
|
|
for (threadlist_entry *thread = inf_obj->threads;
|
|
thread != NULL;
|
|
thread = thread->next)
|
|
if (thread->thread_obj->thread == thr)
|
|
return gdbpy_ref<>::new_reference ((PyObject *) thread->thread_obj.get ());
|
|
|
|
PyErr_SetString (PyExc_SystemError,
|
|
_("could not find gdb thread object"));
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
add_thread_object (struct thread_info *tp)
|
|
{
|
|
inferior_object *inf_obj;
|
|
struct threadlist_entry *entry;
|
|
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (python_gdbarch, python_language);
|
|
|
|
gdbpy_ref<thread_object> thread_obj = create_thread_object (tp);
|
|
if (thread_obj == NULL)
|
|
{
|
|
gdbpy_print_stack ();
|
|
return;
|
|
}
|
|
|
|
inf_obj = (inferior_object *) thread_obj->inf_obj;
|
|
|
|
entry = new threadlist_entry (std::move (thread_obj));
|
|
entry->next = inf_obj->threads;
|
|
|
|
inf_obj->threads = entry;
|
|
inf_obj->nthreads++;
|
|
|
|
if (evregpy_no_listeners_p (gdb_py_events.new_thread))
|
|
return;
|
|
|
|
gdbpy_ref<> event = create_thread_event_object (&new_thread_event_object_type,
|
|
(PyObject *) inf_obj);
|
|
if (event == NULL
|
|
|| evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
|
|
gdbpy_print_stack ();
|
|
}
|
|
|
|
static void
|
|
delete_thread_object (struct thread_info *tp, int ignore)
|
|
{
|
|
struct threadlist_entry **entry, *tmp;
|
|
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (python_gdbarch, python_language);
|
|
|
|
gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
|
|
if (inf_obj == NULL)
|
|
return;
|
|
|
|
/* Find thread entry in its inferior's thread_list. */
|
|
for (entry = &inf_obj->threads; *entry != NULL; entry =
|
|
&(*entry)->next)
|
|
if ((*entry)->thread_obj->thread == tp)
|
|
break;
|
|
|
|
if (!*entry)
|
|
return;
|
|
|
|
tmp = *entry;
|
|
tmp->thread_obj->thread = NULL;
|
|
|
|
*entry = (*entry)->next;
|
|
inf_obj->nthreads--;
|
|
|
|
delete tmp;
|
|
}
|
|
|
|
static PyObject *
|
|
infpy_threads (PyObject *self, PyObject *args)
|
|
{
|
|
int i;
|
|
struct threadlist_entry *entry;
|
|
inferior_object *inf_obj = (inferior_object *) self;
|
|
PyObject *tuple;
|
|
|
|
INFPY_REQUIRE_VALID (inf_obj);
|
|
|
|
try
|
|
{
|
|
update_thread_list ();
|
|
}
|
|
catch (const gdb_exception &except)
|
|
{
|
|
GDB_PY_HANDLE_EXCEPTION (except);
|
|
}
|
|
|
|
tuple = PyTuple_New (inf_obj->nthreads);
|
|
if (!tuple)
|
|
return NULL;
|
|
|
|
for (i = 0, entry = inf_obj->threads; i < inf_obj->nthreads;
|
|
i++, entry = entry->next)
|
|
{
|
|
PyObject *thr = (PyObject *) entry->thread_obj.get ();
|
|
Py_INCREF (thr);
|
|
PyTuple_SET_ITEM (tuple, i, thr);
|
|
}
|
|
|
|
return tuple;
|
|
}
|
|
|
|
static PyObject *
|
|
infpy_get_num (PyObject *self, void *closure)
|
|
{
|
|
inferior_object *inf = (inferior_object *) self;
|
|
|
|
INFPY_REQUIRE_VALID (inf);
|
|
|
|
return gdb_py_object_from_longest (inf->inferior->num).release ();
|
|
}
|
|
|
|
static PyObject *
|
|
infpy_get_pid (PyObject *self, void *closure)
|
|
{
|
|
inferior_object *inf = (inferior_object *) self;
|
|
|
|
INFPY_REQUIRE_VALID (inf);
|
|
|
|
return gdb_py_object_from_longest (inf->inferior->pid).release ();
|
|
}
|
|
|
|
static PyObject *
|
|
infpy_get_was_attached (PyObject *self, void *closure)
|
|
{
|
|
inferior_object *inf = (inferior_object *) self;
|
|
|
|
INFPY_REQUIRE_VALID (inf);
|
|
if (inf->inferior->attach_flag)
|
|
Py_RETURN_TRUE;
|
|
Py_RETURN_FALSE;
|
|
}
|
|
|
|
/* Getter of gdb.Inferior.progspace. */
|
|
|
|
static PyObject *
|
|
infpy_get_progspace (PyObject *self, void *closure)
|
|
{
|
|
inferior_object *inf = (inferior_object *) self;
|
|
|
|
INFPY_REQUIRE_VALID (inf);
|
|
|
|
program_space *pspace = inf->inferior->pspace;
|
|
gdb_assert (pspace != nullptr);
|
|
|
|
return pspace_to_pspace_object (pspace).release ();
|
|
}
|
|
|
|
/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
|
|
Returns a tuple of all inferiors. */
|
|
PyObject *
|
|
gdbpy_inferiors (PyObject *unused, PyObject *unused2)
|
|
{
|
|
gdbpy_ref<> list (PyList_New (0));
|
|
if (list == NULL)
|
|
return NULL;
|
|
|
|
for (inferior *inf : all_inferiors ())
|
|
{
|
|
gdbpy_ref<inferior_object> inferior = inferior_to_inferior_object (inf);
|
|
|
|
if (inferior == NULL)
|
|
continue;
|
|
|
|
if (PyList_Append (list.get (), (PyObject *) inferior.get ()) != 0)
|
|
return NULL;
|
|
}
|
|
|
|
return PyList_AsTuple (list.get ());
|
|
}
|
|
|
|
/* Membuf and memory manipulation. */
|
|
|
|
/* Implementation of Inferior.read_memory (address, length).
|
|
Returns a Python buffer object with LENGTH bytes of the inferior's
|
|
memory at ADDRESS. Both arguments are integers. Returns NULL on error,
|
|
with a python exception set. */
|
|
static PyObject *
|
|
infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
|
|
{
|
|
CORE_ADDR addr, length;
|
|
gdb::unique_xmalloc_ptr<gdb_byte> buffer;
|
|
PyObject *addr_obj, *length_obj, *result;
|
|
static const char *keywords[] = { "address", "length", NULL };
|
|
|
|
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords,
|
|
&addr_obj, &length_obj))
|
|
return NULL;
|
|
|
|
if (get_addr_from_python (addr_obj, &addr) < 0
|
|
|| get_addr_from_python (length_obj, &length) < 0)
|
|
return NULL;
|
|
|
|
try
|
|
{
|
|
buffer.reset ((gdb_byte *) xmalloc (length));
|
|
|
|
read_memory (addr, buffer.get (), length);
|
|
}
|
|
catch (const gdb_exception &except)
|
|
{
|
|
GDB_PY_HANDLE_EXCEPTION (except);
|
|
}
|
|
|
|
gdbpy_ref<membuf_object> membuf_obj (PyObject_New (membuf_object,
|
|
&membuf_object_type));
|
|
if (membuf_obj == NULL)
|
|
return NULL;
|
|
|
|
membuf_obj->buffer = buffer.release ();
|
|
membuf_obj->addr = addr;
|
|
membuf_obj->length = length;
|
|
|
|
#ifdef IS_PY3K
|
|
result = PyMemoryView_FromObject ((PyObject *) membuf_obj.get ());
|
|
#else
|
|
result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj.get (), 0,
|
|
Py_END_OF_BUFFER);
|
|
#endif
|
|
|
|
return result;
|
|
}
|
|
|
|
/* Implementation of Inferior.write_memory (address, buffer [, length]).
|
|
Writes the contents of BUFFER (a Python object supporting the read
|
|
buffer protocol) at ADDRESS in the inferior's memory. Write LENGTH
|
|
bytes from BUFFER, or its entire contents if the argument is not
|
|
provided. The function returns nothing. Returns NULL on error, with
|
|
a python exception set. */
|
|
static PyObject *
|
|
infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
|
|
{
|
|
struct gdb_exception except;
|
|
Py_ssize_t buf_len;
|
|
const gdb_byte *buffer;
|
|
CORE_ADDR addr, length;
|
|
PyObject *addr_obj, *length_obj = NULL;
|
|
static const char *keywords[] = { "address", "buffer", "length", NULL };
|
|
Py_buffer pybuf;
|
|
|
|
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
|
|
&addr_obj, &pybuf, &length_obj))
|
|
return NULL;
|
|
|
|
Py_buffer_up buffer_up (&pybuf);
|
|
buffer = (const gdb_byte *) pybuf.buf;
|
|
buf_len = pybuf.len;
|
|
|
|
if (get_addr_from_python (addr_obj, &addr) < 0)
|
|
return nullptr;
|
|
|
|
if (!length_obj)
|
|
length = buf_len;
|
|
else if (get_addr_from_python (length_obj, &length) < 0)
|
|
return nullptr;
|
|
|
|
try
|
|
{
|
|
write_memory_with_notification (addr, buffer, length);
|
|
}
|
|
catch (gdb_exception &ex)
|
|
{
|
|
except = std::move (ex);
|
|
}
|
|
|
|
GDB_PY_HANDLE_EXCEPTION (except);
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* Destructor of Membuf objects. */
|
|
static void
|
|
mbpy_dealloc (PyObject *self)
|
|
{
|
|
xfree (((membuf_object *) self)->buffer);
|
|
Py_TYPE (self)->tp_free (self);
|
|
}
|
|
|
|
/* Return a description of the Membuf object. */
|
|
static PyObject *
|
|
mbpy_str (PyObject *self)
|
|
{
|
|
membuf_object *membuf_obj = (membuf_object *) self;
|
|
|
|
return PyString_FromFormat (_("Memory buffer for address %s, \
|
|
which is %s bytes long."),
|
|
paddress (python_gdbarch, membuf_obj->addr),
|
|
pulongest (membuf_obj->length));
|
|
}
|
|
|
|
#ifdef IS_PY3K
|
|
|
|
static int
|
|
get_buffer (PyObject *self, Py_buffer *buf, int flags)
|
|
{
|
|
membuf_object *membuf_obj = (membuf_object *) self;
|
|
int ret;
|
|
|
|
ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer,
|
|
membuf_obj->length, 0,
|
|
PyBUF_CONTIG);
|
|
|
|
/* Despite the documentation saying this field is a "const char *",
|
|
in Python 3.4 at least, it's really a "char *". */
|
|
buf->format = (char *) "c";
|
|
|
|
return ret;
|
|
}
|
|
|
|
#else
|
|
|
|
static Py_ssize_t
|
|
get_read_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
|
|
{
|
|
membuf_object *membuf_obj = (membuf_object *) self;
|
|
|
|
if (segment)
|
|
{
|
|
PyErr_SetString (PyExc_SystemError,
|
|
_("The memory buffer supports only one segment."));
|
|
return -1;
|
|
}
|
|
|
|
*ptrptr = membuf_obj->buffer;
|
|
|
|
return membuf_obj->length;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
get_write_buffer (PyObject *self, Py_ssize_t segment, void **ptrptr)
|
|
{
|
|
return get_read_buffer (self, segment, ptrptr);
|
|
}
|
|
|
|
static Py_ssize_t
|
|
get_seg_count (PyObject *self, Py_ssize_t *lenp)
|
|
{
|
|
if (lenp)
|
|
*lenp = ((membuf_object *) self)->length;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static Py_ssize_t
|
|
get_char_buffer (PyObject *self, Py_ssize_t segment, char **ptrptr)
|
|
{
|
|
void *ptr = NULL;
|
|
Py_ssize_t ret;
|
|
|
|
ret = get_read_buffer (self, segment, &ptr);
|
|
*ptrptr = (char *) ptr;
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* IS_PY3K */
|
|
|
|
/* Implementation of
|
|
gdb.search_memory (address, length, pattern). ADDRESS is the
|
|
address to start the search. LENGTH specifies the scope of the
|
|
search from ADDRESS. PATTERN is the pattern to search for (and
|
|
must be a Python object supporting the buffer protocol).
|
|
Returns a Python Long object holding the address where the pattern
|
|
was located, or if the pattern was not found, returns None. Returns NULL
|
|
on error, with a python exception set. */
|
|
static PyObject *
|
|
infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
|
|
{
|
|
struct gdb_exception except;
|
|
CORE_ADDR start_addr, length;
|
|
static const char *keywords[] = { "address", "length", "pattern", NULL };
|
|
PyObject *start_addr_obj, *length_obj;
|
|
Py_ssize_t pattern_size;
|
|
const gdb_byte *buffer;
|
|
CORE_ADDR found_addr;
|
|
int found = 0;
|
|
Py_buffer pybuf;
|
|
|
|
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
|
|
&start_addr_obj, &length_obj,
|
|
&pybuf))
|
|
return NULL;
|
|
|
|
Py_buffer_up buffer_up (&pybuf);
|
|
buffer = (const gdb_byte *) pybuf.buf;
|
|
pattern_size = pybuf.len;
|
|
|
|
if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
|
|
return nullptr;
|
|
|
|
if (get_addr_from_python (length_obj, &length) < 0)
|
|
return nullptr;
|
|
|
|
if (!length)
|
|
{
|
|
PyErr_SetString (PyExc_ValueError,
|
|
_("Search range is empty."));
|
|
return nullptr;
|
|
}
|
|
/* Watch for overflows. */
|
|
else if (length > CORE_ADDR_MAX
|
|
|| (start_addr + length - 1) < start_addr)
|
|
{
|
|
PyErr_SetString (PyExc_ValueError,
|
|
_("The search range is too large."));
|
|
return nullptr;
|
|
}
|
|
|
|
try
|
|
{
|
|
found = target_search_memory (start_addr, length,
|
|
buffer, pattern_size,
|
|
&found_addr);
|
|
}
|
|
catch (gdb_exception &ex)
|
|
{
|
|
except = std::move (ex);
|
|
}
|
|
|
|
GDB_PY_HANDLE_EXCEPTION (except);
|
|
|
|
if (found)
|
|
return gdb_py_object_from_ulongest (found_addr).release ();
|
|
else
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
|
|
Returns True if this inferior object still exists in GDB. */
|
|
|
|
static PyObject *
|
|
infpy_is_valid (PyObject *self, PyObject *args)
|
|
{
|
|
inferior_object *inf = (inferior_object *) self;
|
|
|
|
if (! inf->inferior)
|
|
Py_RETURN_FALSE;
|
|
|
|
Py_RETURN_TRUE;
|
|
}
|
|
|
|
/* Implementation of gdb.Inferior.thread_from_handle (self, handle)
|
|
-> gdb.InferiorThread. */
|
|
|
|
static PyObject *
|
|
infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
|
|
{
|
|
PyObject *handle_obj;
|
|
inferior_object *inf_obj = (inferior_object *) self;
|
|
static const char *keywords[] = { "handle", NULL };
|
|
|
|
INFPY_REQUIRE_VALID (inf_obj);
|
|
|
|
if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
|
|
return NULL;
|
|
|
|
const gdb_byte *bytes;
|
|
size_t bytes_len;
|
|
Py_buffer_up buffer_up;
|
|
Py_buffer py_buf;
|
|
|
|
if (PyObject_CheckBuffer (handle_obj)
|
|
&& PyObject_GetBuffer (handle_obj, &py_buf, PyBUF_SIMPLE) == 0)
|
|
{
|
|
buffer_up.reset (&py_buf);
|
|
bytes = (const gdb_byte *) py_buf.buf;
|
|
bytes_len = py_buf.len;
|
|
}
|
|
else if (gdbpy_is_value_object (handle_obj))
|
|
{
|
|
struct value *val = value_object_to_value (handle_obj);
|
|
bytes = value_contents_all (val);
|
|
bytes_len = TYPE_LENGTH (value_type (val));
|
|
}
|
|
else
|
|
{
|
|
PyErr_SetString (PyExc_TypeError,
|
|
_("Argument 'handle' must be a thread handle object."));
|
|
|
|
return NULL;
|
|
}
|
|
|
|
try
|
|
{
|
|
struct thread_info *thread_info;
|
|
|
|
thread_info = find_thread_by_handle
|
|
(gdb::array_view<const gdb_byte> (bytes, bytes_len),
|
|
inf_obj->inferior);
|
|
if (thread_info != NULL)
|
|
return thread_to_thread_object (thread_info).release ();
|
|
}
|
|
catch (const gdb_exception &except)
|
|
{
|
|
GDB_PY_HANDLE_EXCEPTION (except);
|
|
}
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
/* Implementation of gdb.Inferior.architecture. */
|
|
|
|
static PyObject *
|
|
infpy_architecture (PyObject *self, PyObject *args)
|
|
{
|
|
inferior_object *inf = (inferior_object *) self;
|
|
|
|
INFPY_REQUIRE_VALID (inf);
|
|
|
|
return gdbarch_to_arch_object (inf->inferior->gdbarch);
|
|
}
|
|
|
|
/* Implement repr() for gdb.Inferior. */
|
|
|
|
static PyObject *
|
|
infpy_repr (PyObject *obj)
|
|
{
|
|
inferior_object *self = (inferior_object *) obj;
|
|
inferior *inf = self->inferior;
|
|
|
|
if (inf == nullptr)
|
|
return PyString_FromString ("<gdb.Inferior (invalid)>");
|
|
|
|
return PyString_FromFormat ("<gdb.Inferior num=%d, pid=%d>",
|
|
inf->num, inf->pid);
|
|
}
|
|
|
|
|
|
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);
|
|
Py_TYPE (obj)->tp_free (obj);
|
|
}
|
|
|
|
/* Clear the INFERIOR pointer in an Inferior object and clear the
|
|
thread list. */
|
|
static void
|
|
py_free_inferior (struct inferior *inf, void *datum)
|
|
{
|
|
struct threadlist_entry *th_entry, *th_tmp;
|
|
|
|
if (!gdb_python_initialized)
|
|
return;
|
|
|
|
gdbpy_enter enter_py (python_gdbarch, python_language);
|
|
gdbpy_ref<inferior_object> inf_obj ((inferior_object *) datum);
|
|
|
|
inf_obj->inferior = NULL;
|
|
|
|
/* Deallocate threads list. */
|
|
for (th_entry = inf_obj->threads; th_entry != NULL;)
|
|
{
|
|
th_tmp = th_entry;
|
|
th_entry = th_entry->next;
|
|
delete th_tmp;
|
|
}
|
|
|
|
inf_obj->nthreads = 0;
|
|
}
|
|
|
|
/* Implementation of gdb.selected_inferior() -> gdb.Inferior.
|
|
Returns the current inferior object. */
|
|
|
|
PyObject *
|
|
gdbpy_selected_inferior (PyObject *self, PyObject *args)
|
|
{
|
|
return ((PyObject *)
|
|
inferior_to_inferior_object (current_inferior ()).release ());
|
|
}
|
|
|
|
int
|
|
gdbpy_initialize_inferior (void)
|
|
{
|
|
if (PyType_Ready (&inferior_object_type) < 0)
|
|
return -1;
|
|
|
|
if (gdb_pymodule_addobject (gdb_module, "Inferior",
|
|
(PyObject *) &inferior_object_type) < 0)
|
|
return -1;
|
|
|
|
infpy_inf_data_key =
|
|
register_inferior_data_with_cleanup (NULL, py_free_inferior);
|
|
|
|
gdb::observers::new_thread.attach (add_thread_object);
|
|
gdb::observers::thread_exit.attach (delete_thread_object);
|
|
gdb::observers::normal_stop.attach (python_on_normal_stop);
|
|
gdb::observers::target_resumed.attach (python_on_resume);
|
|
gdb::observers::inferior_call_pre.attach (python_on_inferior_call_pre);
|
|
gdb::observers::inferior_call_post.attach (python_on_inferior_call_post);
|
|
gdb::observers::memory_changed.attach (python_on_memory_change);
|
|
gdb::observers::register_changed.attach (python_on_register_change);
|
|
gdb::observers::inferior_exit.attach (python_inferior_exit);
|
|
gdb::observers::new_objfile.attach (python_new_objfile);
|
|
gdb::observers::inferior_added.attach (python_new_inferior);
|
|
gdb::observers::inferior_removed.attach (python_inferior_deleted);
|
|
|
|
membuf_object_type.tp_new = PyType_GenericNew;
|
|
if (PyType_Ready (&membuf_object_type) < 0)
|
|
return -1;
|
|
|
|
return gdb_pymodule_addobject (gdb_module, "Membuf",
|
|
(PyObject *) &membuf_object_type);
|
|
}
|
|
|
|
static gdb_PyGetSetDef inferior_object_getset[] =
|
|
{
|
|
{ "num", infpy_get_num, NULL, "ID of inferior, as assigned by GDB.", NULL },
|
|
{ "pid", infpy_get_pid, NULL, "PID of inferior, as assigned by the OS.",
|
|
NULL },
|
|
{ "was_attached", infpy_get_was_attached, NULL,
|
|
"True if the inferior was created using 'attach'.", NULL },
|
|
{ "progspace", infpy_get_progspace, NULL, "Program space of this inferior" },
|
|
{ NULL }
|
|
};
|
|
|
|
static PyMethodDef inferior_object_methods[] =
|
|
{
|
|
{ "is_valid", infpy_is_valid, METH_NOARGS,
|
|
"is_valid () -> Boolean.\n\
|
|
Return true if this inferior is valid, false if not." },
|
|
{ "threads", infpy_threads, METH_NOARGS,
|
|
"Return all the threads of this inferior." },
|
|
{ "read_memory", (PyCFunction) infpy_read_memory,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"read_memory (address, length) -> buffer\n\
|
|
Return a buffer object for reading from the inferior's memory." },
|
|
{ "write_memory", (PyCFunction) infpy_write_memory,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"write_memory (address, buffer [, length])\n\
|
|
Write the given buffer object to the inferior's memory." },
|
|
{ "search_memory", (PyCFunction) infpy_search_memory,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"search_memory (address, length, pattern) -> long\n\
|
|
Return a long with the address of a match, or None." },
|
|
/* thread_from_thread_handle is deprecated. */
|
|
{ "thread_from_thread_handle", (PyCFunction) infpy_thread_from_thread_handle,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"thread_from_thread_handle (handle) -> gdb.InferiorThread.\n\
|
|
Return thread object corresponding to thread handle.\n\
|
|
This method is deprecated - use thread_from_handle instead." },
|
|
{ "thread_from_handle", (PyCFunction) infpy_thread_from_thread_handle,
|
|
METH_VARARGS | METH_KEYWORDS,
|
|
"thread_from_handle (handle) -> gdb.InferiorThread.\n\
|
|
Return thread object corresponding to thread handle." },
|
|
{ "architecture", (PyCFunction) infpy_architecture, METH_NOARGS,
|
|
"architecture () -> gdb.Architecture\n\
|
|
Return architecture of this inferior." },
|
|
{ NULL }
|
|
};
|
|
|
|
PyTypeObject inferior_object_type =
|
|
{
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
"gdb.Inferior", /* tp_name */
|
|
sizeof (inferior_object), /* tp_basicsize */
|
|
0, /* tp_itemsize */
|
|
infpy_dealloc, /* tp_dealloc */
|
|
0, /* tp_print */
|
|
0, /* tp_getattr */
|
|
0, /* tp_setattr */
|
|
0, /* tp_compare */
|
|
infpy_repr, /* 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 inferior object", /* tp_doc */
|
|
0, /* tp_traverse */
|
|
0, /* tp_clear */
|
|
0, /* tp_richcompare */
|
|
0, /* tp_weaklistoffset */
|
|
0, /* tp_iter */
|
|
0, /* tp_iternext */
|
|
inferior_object_methods, /* tp_methods */
|
|
0, /* tp_members */
|
|
inferior_object_getset, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0 /* tp_alloc */
|
|
};
|
|
|
|
#ifdef IS_PY3K
|
|
|
|
static PyBufferProcs buffer_procs =
|
|
{
|
|
get_buffer
|
|
};
|
|
|
|
#else
|
|
|
|
static PyBufferProcs buffer_procs = {
|
|
get_read_buffer,
|
|
get_write_buffer,
|
|
get_seg_count,
|
|
get_char_buffer
|
|
};
|
|
#endif /* IS_PY3K */
|
|
|
|
PyTypeObject membuf_object_type = {
|
|
PyVarObject_HEAD_INIT (NULL, 0)
|
|
"gdb.Membuf", /*tp_name*/
|
|
sizeof (membuf_object), /*tp_basicsize*/
|
|
0, /*tp_itemsize*/
|
|
mbpy_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*/
|
|
mbpy_str, /*tp_str*/
|
|
0, /*tp_getattro*/
|
|
0, /*tp_setattro*/
|
|
&buffer_procs, /*tp_as_buffer*/
|
|
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
|
"GDB memory buffer 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 */
|
|
0, /* tp_getset */
|
|
0, /* tp_base */
|
|
0, /* tp_dict */
|
|
0, /* tp_descr_get */
|
|
0, /* tp_descr_set */
|
|
0, /* tp_dictoffset */
|
|
0, /* tp_init */
|
|
0, /* tp_alloc */
|
|
};
|