gdb/python/py-inferior.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "gdbcore.h"
- #include "gdbthread.h"
- #include "inferior.h"
- #include "objfiles.h"
- #include "observer.h"
- #include "python-internal.h"
- #include "arch-utils.h"
- #include "language.h"
- #include "gdb_signals.h"
- #include "py-event.h"
- #include "py-stopevent.h"
- struct threadlist_entry {
- thread_object *thread_obj;
- struct threadlist_entry *next;
- };
- typedef struct
- {
- PyObject_HEAD
-
- struct inferior *inferior;
-
- struct threadlist_entry *threads;
-
- int nthreads;
- } inferior_object;
- static 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;
-
- CORE_ADDR addr;
- CORE_ADDR length;
- } membuf_object;
- static PyTypeObject membuf_object_type
- CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("membuf_object");
- #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)
- {
- struct cleanup *cleanup;
- enum gdb_signal stop_signal;
- if (!gdb_python_initialized)
- return;
- if (!find_thread_ptid (inferior_ptid))
- return;
- stop_signal = inferior_thread ()->suspend.stop_signal;
- cleanup = ensure_python_env (get_current_arch (), current_language);
- if (emit_stop_event (bs, stop_signal) < 0)
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- }
- static void
- python_on_resume (ptid_t ptid)
- {
- struct cleanup *cleanup;
- if (!gdb_python_initialized)
- return;
- cleanup = ensure_python_env (target_gdbarch (), current_language);
- if (emit_continue_event (ptid) < 0)
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- }
- static void
- python_on_inferior_call_pre (ptid_t thread, CORE_ADDR address)
- {
- struct cleanup *cleanup;
- cleanup = ensure_python_env (target_gdbarch (), current_language);
- if (emit_inferior_call_event (INFERIOR_CALL_PRE, thread, address) < 0)
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- }
- static void
- python_on_inferior_call_post (ptid_t thread, CORE_ADDR address)
- {
- struct cleanup *cleanup;
- cleanup = ensure_python_env (target_gdbarch (), current_language);
- if (emit_inferior_call_event (INFERIOR_CALL_POST, thread, address) < 0)
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- }
- static void
- python_on_memory_change (struct inferior *inferior, CORE_ADDR addr, ssize_t len, const bfd_byte *data)
- {
- struct cleanup *cleanup;
- cleanup = ensure_python_env (target_gdbarch (), current_language);
- if (emit_memory_changed_event (addr, len) < 0)
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- }
- static void
- python_on_register_change (struct frame_info *frame, int regnum)
- {
- struct cleanup *cleanup;
- cleanup = ensure_python_env (target_gdbarch (), current_language);
- if (emit_register_changed_event (frame, regnum) < 0)
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- }
- static void
- python_inferior_exit (struct inferior *inf)
- {
- struct cleanup *cleanup;
- const LONGEST *exit_code = NULL;
- if (!gdb_python_initialized)
- return;
- cleanup = ensure_python_env (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 ();
- do_cleanups (cleanup);
- }
- static void
- python_new_objfile (struct objfile *objfile)
- {
- struct cleanup *cleanup;
- if (!gdb_python_initialized)
- return;
- cleanup = ensure_python_env (objfile != NULL
- ? get_objfile_arch (objfile)
- : 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 ();
- }
- do_cleanups (cleanup);
- }
- PyObject *
- inferior_to_inferior_object (struct inferior *inferior)
- {
- inferior_object *inf_obj;
- inf_obj = 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;
- set_inferior_data (inferior, infpy_inf_data_key, inf_obj);
- }
- else
- Py_INCREF ((PyObject *)inf_obj);
- return (PyObject *) inf_obj;
- }
- PyObject *
- find_inferior_object (int pid)
- {
- struct inferior *inf = find_inferior_pid (pid);
- if (inf)
- return inferior_to_inferior_object (inf);
- return NULL;
- }
- thread_object *
- find_thread_object (ptid_t ptid)
- {
- int pid;
- struct threadlist_entry *thread;
- PyObject *inf_obj;
- thread_object *found = NULL;
- pid = ptid_get_pid (ptid);
- if (pid == 0)
- return NULL;
- inf_obj = find_inferior_object (pid);
- 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;
- }
- static void
- add_thread_object (struct thread_info *tp)
- {
- struct cleanup *cleanup;
- thread_object *thread_obj;
- inferior_object *inf_obj;
- struct threadlist_entry *entry;
- if (!gdb_python_initialized)
- return;
- cleanup = ensure_python_env (python_gdbarch, python_language);
- thread_obj = create_thread_object (tp);
- if (!thread_obj)
- {
- gdbpy_print_stack ();
- do_cleanups (cleanup);
- return;
- }
- inf_obj = (inferior_object *) thread_obj->inf_obj;
- entry = xmalloc (sizeof (struct threadlist_entry));
- entry->thread_obj = thread_obj;
- entry->next = inf_obj->threads;
- inf_obj->threads = entry;
- inf_obj->nthreads++;
- do_cleanups (cleanup);
- }
- static void
- delete_thread_object (struct thread_info *tp, int ignore)
- {
- struct cleanup *cleanup;
- inferior_object *inf_obj;
- struct threadlist_entry **entry, *tmp;
- if (!gdb_python_initialized)
- return;
- cleanup = ensure_python_env (python_gdbarch, python_language);
- inf_obj
- = (inferior_object *) find_inferior_object (ptid_get_pid (tp->ptid));
- if (!inf_obj)
- {
- do_cleanups (cleanup);
- return;
- }
-
- for (entry = &inf_obj->threads; *entry != NULL; entry =
- &(*entry)->next)
- if ((*entry)->thread_obj->thread == tp)
- break;
- if (!*entry)
- {
- Py_DECREF (inf_obj);
- do_cleanups (cleanup);
- return;
- }
- tmp = *entry;
- tmp->thread_obj->thread = NULL;
- *entry = (*entry)->next;
- inf_obj->nthreads--;
- Py_DECREF (tmp->thread_obj);
- Py_DECREF (inf_obj);
- xfree (tmp);
- do_cleanups (cleanup);
- }
- static PyObject *
- infpy_threads (PyObject *self, PyObject *args)
- {
- int i;
- struct threadlist_entry *entry;
- inferior_object *inf_obj = (inferior_object *) self;
- PyObject *tuple;
- volatile struct gdb_exception except;
- INFPY_REQUIRE_VALID (inf_obj);
- TRY_CATCH (except, RETURN_MASK_ALL)
- update_thread_list ();
- 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)
- {
- Py_INCREF (entry->thread_obj);
- PyTuple_SET_ITEM (tuple, i, (PyObject *) entry->thread_obj);
- }
- return tuple;
- }
- static PyObject *
- infpy_get_num (PyObject *self, void *closure)
- {
- inferior_object *inf = (inferior_object *) self;
- INFPY_REQUIRE_VALID (inf);
- return PyLong_FromLong (inf->inferior->num);
- }
- static PyObject *
- infpy_get_pid (PyObject *self, void *closure)
- {
- inferior_object *inf = (inferior_object *) self;
- INFPY_REQUIRE_VALID (inf);
- return PyLong_FromLong (inf->inferior->pid);
- }
- 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;
- }
- static int
- 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;
- success = PyList_Append (list, inferior);
- Py_DECREF (inferior);
- if (success)
- return 1;
- return 0;
- }
- PyObject *
- gdbpy_inferiors (PyObject *unused, PyObject *unused2)
- {
- PyObject *list, *tuple;
- list = PyList_New (0);
- if (!list)
- return NULL;
- if (iterate_over_inferiors (build_inferior_list, list))
- {
- Py_DECREF (list);
- return NULL;
- }
- tuple = PyList_AsTuple (list);
- Py_DECREF (list);
- return tuple;
- }
- static PyObject *
- infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
- {
- CORE_ADDR addr, length;
- void *buffer = NULL;
- membuf_object *membuf_obj;
- PyObject *addr_obj, *length_obj, *result;
- volatile struct gdb_exception except;
- static char *keywords[] = { "address", "length", NULL };
- if (! 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_CATCH (except, RETURN_MASK_ALL)
- {
- buffer = xmalloc (length);
- read_memory (addr, buffer, length);
- }
- if (except.reason < 0)
- {
- xfree (buffer);
- GDB_PY_HANDLE_EXCEPTION (except);
- }
- membuf_obj = PyObject_New (membuf_object, &membuf_object_type);
- if (membuf_obj == NULL)
- {
- xfree (buffer);
- return NULL;
- }
- membuf_obj->buffer = buffer;
- membuf_obj->addr = addr;
- membuf_obj->length = length;
- #ifdef IS_PY3K
- result = PyMemoryView_FromObject ((PyObject *) membuf_obj);
- #else
- result = PyBuffer_FromReadWriteObject ((PyObject *) membuf_obj, 0,
- Py_END_OF_BUFFER);
- #endif
- Py_DECREF (membuf_obj);
- return result;
- }
- static PyObject *
- infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
- {
- Py_ssize_t buf_len;
- const char *buffer;
- CORE_ADDR addr, length;
- PyObject *addr_obj, *length_obj = NULL;
- volatile struct gdb_exception except;
- static char *keywords[] = { "address", "buffer", "length", NULL };
- #ifdef IS_PY3K
- Py_buffer pybuf;
- if (! PyArg_ParseTupleAndKeywords (args, kw, "Os*|O", keywords,
- &addr_obj, &pybuf,
- &length_obj))
- return NULL;
- buffer = pybuf.buf;
- buf_len = pybuf.len;
- #else
- if (! PyArg_ParseTupleAndKeywords (args, kw, "Os#|O", keywords,
- &addr_obj, &buffer, &buf_len,
- &length_obj))
- return NULL;
- #endif
- if (get_addr_from_python (addr_obj, &addr) < 0)
- goto fail;
- if (!length_obj)
- length = buf_len;
- else if (get_addr_from_python (length_obj, &length) < 0)
- goto fail;
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- write_memory_with_notification (addr, (gdb_byte *) buffer, length);
- }
- #ifdef IS_PY3K
- PyBuffer_Release (&pybuf);
- #endif
- GDB_PY_HANDLE_EXCEPTION (except);
- Py_RETURN_NONE;
- fail:
- #ifdef IS_PY3K
- PyBuffer_Release (&pybuf);
- #endif
- return NULL;
- }
- static void
- mbpy_dealloc (PyObject *self)
- {
- xfree (((membuf_object *) self)->buffer);
- Py_TYPE (self)->tp_free (self);
- }
- 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);
- buf->format = "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
- static PyObject *
- infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
- {
- CORE_ADDR start_addr, length;
- static char *keywords[] = { "address", "length", "pattern", NULL };
- PyObject *start_addr_obj, *length_obj;
- volatile struct gdb_exception except;
- Py_ssize_t pattern_size;
- const void *buffer;
- CORE_ADDR found_addr;
- int found = 0;
- #ifdef IS_PY3K
- Py_buffer pybuf;
- if (! PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
- &start_addr_obj, &length_obj,
- &pybuf))
- return NULL;
- buffer = pybuf.buf;
- pattern_size = pybuf.len;
- #else
- PyObject *pattern;
- if (! PyArg_ParseTupleAndKeywords (args, kw, "OOO", keywords,
- &start_addr_obj, &length_obj,
- &pattern))
- return NULL;
- if (!PyObject_CheckReadBuffer (pattern))
- {
- PyErr_SetString (PyExc_RuntimeError,
- _("The pattern is not a Python buffer."));
- return NULL;
- }
- if (PyObject_AsReadBuffer (pattern, &buffer, &pattern_size) == -1)
- return NULL;
- #endif
- if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
- goto fail;
- if (get_addr_from_python (length_obj, &length) < 0)
- goto fail;
- if (!length)
- {
- PyErr_SetString (PyExc_ValueError,
- _("Search range is empty."));
- goto fail;
- }
-
- else if (length > CORE_ADDR_MAX
- || (start_addr + length - 1) < start_addr)
- {
- PyErr_SetString (PyExc_ValueError,
- _("The search range is too large."));
- goto fail;
- }
- TRY_CATCH (except, RETURN_MASK_ALL)
- {
- found = target_search_memory (start_addr, length,
- buffer, pattern_size,
- &found_addr);
- }
- #ifdef IS_PY3K
- PyBuffer_Release (&pybuf);
- #endif
- GDB_PY_HANDLE_EXCEPTION (except);
- if (found)
- return PyLong_FromLong (found_addr);
- else
- Py_RETURN_NONE;
- fail:
- #ifdef IS_PY3K
- PyBuffer_Release (&pybuf);
- #endif
- return NULL;
- }
- static PyObject *
- infpy_is_valid (PyObject *self, PyObject *args)
- {
- inferior_object *inf = (inferior_object *) self;
- if (! inf->inferior)
- Py_RETURN_FALSE;
- 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);
- }
- static void
- py_free_inferior (struct inferior *inf, void *datum)
- {
- struct cleanup *cleanup;
- inferior_object *inf_obj = datum;
- struct threadlist_entry *th_entry, *th_tmp;
- if (!gdb_python_initialized)
- return;
- cleanup = ensure_python_env (python_gdbarch, python_language);
- inf_obj->inferior = NULL;
-
- for (th_entry = inf_obj->threads; th_entry != NULL;)
- {
- Py_DECREF (th_entry->thread_obj);
- th_tmp = th_entry;
- th_entry = th_entry->next;
- xfree (th_tmp);
- }
- inf_obj->nthreads = 0;
- Py_DECREF ((PyObject *) inf_obj);
- do_cleanups (cleanup);
- }
- PyObject *
- gdbpy_selected_inferior (PyObject *self, PyObject *args)
- {
- return inferior_to_inferior_object (current_inferior ());
- }
- 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);
- observer_attach_new_thread (add_thread_object);
- observer_attach_thread_exit (delete_thread_object);
- observer_attach_normal_stop (python_on_normal_stop);
- observer_attach_target_resumed (python_on_resume);
- observer_attach_inferior_call_pre (python_on_inferior_call_pre);
- observer_attach_inferior_call_post (python_on_inferior_call_post);
- observer_attach_memory_changed (python_on_memory_change);
- observer_attach_register_changed (python_on_register_change);
- 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 -1;
- return gdb_pymodule_addobject (gdb_module, "Membuf", (PyObject *)
- &membuf_object_type);
- }
- static 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 },
- { 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." },
- { NULL }
- };
- static PyTypeObject inferior_object_type =
- {
- PyVarObject_HEAD_INIT (NULL, 0)
- "gdb.Inferior",
- sizeof (inferior_object),
- 0,
- infpy_dealloc,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER,
- "GDB inferior object",
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- inferior_object_methods,
- 0,
- inferior_object_getset,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0
- };
- #ifdef IS_PY3K
- static PyBufferProcs buffer_procs =
- {
- get_buffer
- };
- #else
- #if HAVE_LIBPYTHON2_4
- #define CHARBUFFERPROC_NAME getcharbufferproc
- #else
- #define CHARBUFFERPROC_NAME charbufferproc
- #endif
- static PyBufferProcs buffer_procs = {
- get_read_buffer,
- get_write_buffer,
- get_seg_count,
-
- (CHARBUFFERPROC_NAME) get_char_buffer
- };
- #endif
- static PyTypeObject membuf_object_type = {
- PyVarObject_HEAD_INIT (NULL, 0)
- "gdb.Membuf",
- sizeof (membuf_object),
- 0,
- mbpy_dealloc,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- mbpy_str,
- 0,
- 0,
- &buffer_procs,
- Py_TPFLAGS_DEFAULT,
- "GDB memory buffer object",
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- };