/* Python interface to inferiors.
- Copyright (C) 2009-2018 Free Software Foundation, Inc.
+ Copyright (C) 2009-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "python-internal.h"
#include "arch-utils.h"
#include "language.h"
-#include "gdb_signals.h"
+#include "gdbsupport/gdb_signals.h"
#include "py-event.h"
#include "py-stopevent.h"
-struct threadlist_entry {
- thread_object *thread_obj;
+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;
};
if (!gdb_python_initialized)
return;
- if (!find_thread_ptid (inferior_ptid))
- return;
+ if (inferior_ptid == null_ptid)
+ return;
stop_signal = inferior_thread ()->suspend.stop_signal;
return;
gdbpy_enter enter_py (objfile != NULL
- ? get_objfile_arch (objfile)
+ ? objfile->arch ()
: target_gdbarch (),
current_language);
return it and increment the reference count, otherwise, create it.
Return NULL on failure. */
-inferior_object *
+gdbpy_ref<inferior_object>
inferior_to_inferior_object (struct inferior *inferior)
{
inferior_object *inf_obj;
{
inf_obj = PyObject_New (inferior_object, &inferior_object_type);
if (!inf_obj)
- return NULL;
+ return NULL;
inf_obj->inferior = inferior;
inf_obj->threads = NULL;
/* 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. */
- Py_INCREF ((PyObject *)inf_obj);
-
- return inf_obj;
+ 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
if (evregpy_no_listeners_p (gdb_py_events.new_inferior))
return;
- gdbpy_ref<inferior_object> inf_obj (inferior_to_inferior_object (inf));
+ gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
if (inf_obj == NULL)
{
gdbpy_print_stack ();
if (evregpy_no_listeners_p (gdb_py_events.inferior_deleted))
return;
- gdbpy_ref<inferior_object> inf_obj (inferior_to_inferior_object (inf));
+ gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (inf);
if (inf_obj == NULL)
{
gdbpy_print_stack ();
gdbpy_print_stack ();
}
-/* Finds the Python Inferior object for the given PID. Returns a
- reference, or NULL if PID does not match any inferior object. */
-
-PyObject *
-find_inferior_object (int pid)
-{
- struct inferior *inf = find_inferior_pid (pid);
-
- if (inf)
- return (PyObject *) inferior_to_inferior_object (inf);
-
- return NULL;
-}
-
-thread_object *
+gdbpy_ref<>
thread_to_thread_object (thread_info *thr)
{
- gdbpy_ref<inferior_object> inf_obj (inferior_to_inferior_object (thr->inf));
+ gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (thr->inf);
if (inf_obj == NULL)
return NULL;
thread != NULL;
thread = thread->next)
if (thread->thread_obj->thread == thr)
- return thread->thread_obj;
+ 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)
{
- thread_object *thread_obj;
inferior_object *inf_obj;
struct threadlist_entry *entry;
gdbpy_enter enter_py (python_gdbarch, python_language);
- thread_obj = create_thread_object (tp);
- if (!thread_obj)
+ 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 = XNEW (struct threadlist_entry);
- entry->thread_obj = thread_obj;
+ entry = new threadlist_entry (std::move (thread_obj));
entry->next = inf_obj->threads;
inf_obj->threads = entry;
return;
gdbpy_ref<> event = create_thread_event_object (&new_thread_event_object_type,
- (PyObject *) thread_obj);
+ (PyObject *) inf_obj);
if (event == NULL
|| evpy_emit_event (event.get (), gdb_py_events.new_thread) < 0)
gdbpy_print_stack ();
gdbpy_enter enter_py (python_gdbarch, python_language);
- gdbpy_ref<inferior_object> inf_obj
- ((inferior_object *) inferior_to_inferior_object (tp->inf));
+ gdbpy_ref<inferior_object> inf_obj = inferior_to_inferior_object (tp->inf);
if (inf_obj == NULL)
return;
*entry = (*entry)->next;
inf_obj->nthreads--;
- Py_DECREF (tmp->thread_obj);
- xfree (tmp);
+ delete tmp;
}
static PyObject *
INFPY_REQUIRE_VALID (inf_obj);
- TRY
+ try
{
update_thread_list ();
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
GDB_PY_HANDLE_EXCEPTION (except);
}
- END_CATCH
tuple = PyTuple_New (inf_obj->nthreads);
if (!tuple)
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);
+ PyObject *thr = (PyObject *) entry->thread_obj.get ();
+ Py_INCREF (thr);
+ PyTuple_SET_ITEM (tuple, i, thr);
}
return tuple;
Py_RETURN_FALSE;
}
-static int
-build_inferior_list (struct inferior *inf, void *arg)
+/* Getter of gdb.Inferior.progspace. */
+
+static PyObject *
+infpy_get_progspace (PyObject *self, void *closure)
{
- PyObject *list = (PyObject *) arg;
- gdbpy_ref<inferior_object> inferior (inferior_to_inferior_object (inf));
+ inferior_object *inf = (inferior_object *) self;
+
+ INFPY_REQUIRE_VALID (inf);
- if (inferior == NULL)
- return 0;
+ program_space *pspace = inf->inferior->pspace;
+ gdb_assert (pspace != nullptr);
- return PyList_Append (list, (PyObject *) inferior.get ()) ? 1 : 0;
+ return pspace_to_pspace_object (pspace).release ();
}
/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
if (list == NULL)
return NULL;
- if (iterate_over_inferiors (build_inferior_list, list.get ()))
- 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 ());
}
infpy_read_memory (PyObject *self, PyObject *args, PyObject *kw)
{
CORE_ADDR addr, length;
- gdb_byte *buffer = NULL;
+ gdb::unique_xmalloc_ptr<gdb_byte> buffer;
PyObject *addr_obj, *length_obj, *result;
static const char *keywords[] = { "address", "length", NULL };
|| get_addr_from_python (length_obj, &length) < 0)
return NULL;
- TRY
+ try
{
- buffer = (gdb_byte *) xmalloc (length);
+ buffer.reset ((gdb_byte *) xmalloc (length));
- read_memory (addr, buffer, length);
+ read_memory (addr, buffer.get (), length);
}
- CATCH (except, RETURN_MASK_ALL)
+ catch (const gdb_exception &except)
{
- xfree (buffer);
GDB_PY_HANDLE_EXCEPTION (except);
}
- END_CATCH
gdbpy_ref<membuf_object> membuf_obj (PyObject_New (membuf_object,
&membuf_object_type));
if (membuf_obj == NULL)
- {
- xfree (buffer);
- return NULL;
- }
+ return NULL;
- membuf_obj->buffer = buffer;
+ membuf_obj->buffer = buffer.release ();
membuf_obj->addr = addr;
membuf_obj->length = length;
static PyObject *
infpy_write_memory (PyObject *self, PyObject *args, PyObject *kw)
{
- struct gdb_exception except = exception_none;
+ 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 };
-#ifdef IS_PY3K
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;
-#else
- if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "Os#|O", keywords,
- &addr_obj, &buffer, &buf_len,
- &length_obj))
- return NULL;
-
- buffer = (const gdb_byte *) buffer;
-#endif
if (get_addr_from_python (addr_obj, &addr) < 0)
- goto fail;
+ return nullptr;
if (!length_obj)
length = buf_len;
else if (get_addr_from_python (length_obj, &length) < 0)
- goto fail;
+ return nullptr;
- TRY
+ try
{
write_memory_with_notification (addr, buffer, length);
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (gdb_exception &ex)
{
- except = ex;
+ except = std::move (ex);
}
- END_CATCH
-#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;
}
/* Destructor of Membuf objects. */
static PyObject *
infpy_search_memory (PyObject *self, PyObject *args, PyObject *kw)
{
- struct gdb_exception except = exception_none;
+ struct gdb_exception except;
CORE_ADDR start_addr, length;
static const char *keywords[] = { "address", "length", "pattern", NULL };
PyObject *start_addr_obj, *length_obj;
const gdb_byte *buffer;
CORE_ADDR found_addr;
int found = 0;
-#ifdef IS_PY3K
Py_buffer pybuf;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OOs*", keywords,
&pybuf))
return NULL;
+ Py_buffer_up buffer_up (&pybuf);
buffer = (const gdb_byte *) pybuf.buf;
pattern_size = pybuf.len;
-#else
- PyObject *pattern;
- const void *vbuffer;
-
- if (!gdb_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, &vbuffer, &pattern_size) == -1)
- return NULL;
-
- buffer = (const gdb_byte *) vbuffer;
-#endif
if (get_addr_from_python (start_addr_obj, &start_addr) < 0)
- goto fail;
+ return nullptr;
if (get_addr_from_python (length_obj, &length) < 0)
- goto fail;
+ return nullptr;
if (!length)
{
PyErr_SetString (PyExc_ValueError,
_("Search range is empty."));
- goto fail;
+ return nullptr;
}
/* Watch for overflows. */
else if (length > CORE_ADDR_MAX
{
PyErr_SetString (PyExc_ValueError,
_("The search range is too large."));
- goto fail;
+ return nullptr;
}
- TRY
+ try
{
found = target_search_memory (start_addr, length,
buffer, pattern_size,
&found_addr);
}
- CATCH (ex, RETURN_MASK_ALL)
+ catch (gdb_exception &ex)
{
- except = ex;
+ except = std::move (ex);
}
- END_CATCH
-#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;
}
/* Implementation of gdb.Inferior.is_valid (self) -> Boolean.
Py_RETURN_TRUE;
}
-/* Implementation of gdb.Inferior.thread_from_thread_handle (self, handle)
+/* Implementation of gdb.Inferior.thread_from_handle (self, handle)
-> gdb.InferiorThread. */
-PyObject *
+static PyObject *
infpy_thread_from_thread_handle (PyObject *self, PyObject *args, PyObject *kw)
{
- PyObject *handle_obj, *result;
+ PyObject *handle_obj;
inferior_object *inf_obj = (inferior_object *) self;
- static const char *keywords[] = { "thread_handle", NULL };
+ static const char *keywords[] = { "handle", NULL };
INFPY_REQUIRE_VALID (inf_obj);
if (! gdb_PyArg_ParseTupleAndKeywords (args, kw, "O", keywords, &handle_obj))
return NULL;
- result = Py_None;
+ const gdb_byte *bytes;
+ size_t bytes_len;
+ Py_buffer_up buffer_up;
+ Py_buffer py_buf;
- if (!gdbpy_is_value_object (handle_obj))
+ 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_obj' must be a thread handle object."));
+ _("Argument 'handle' must be a thread handle object."));
return NULL;
}
- else
+
+ 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)
{
- TRY
- {
- struct thread_info *thread_info;
- struct value *val = value_object_to_value (handle_obj);
-
- thread_info = find_thread_by_handle (val, inf_obj->inferior);
- if (thread_info != NULL)
- {
- result = (PyObject *) thread_to_thread_object (thread_info);
- if (result != NULL)
- Py_INCREF (result);
- }
- }
- CATCH (except, RETURN_MASK_ALL)
- {
- GDB_PY_HANDLE_EXCEPTION (except);
- }
- END_CATCH
+ GDB_PY_HANDLE_EXCEPTION (except);
}
- return result;
+ 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);
}
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
static void
py_free_inferior (struct inferior *inf, void *datum)
{
- gdbpy_ref<inferior_object> inf_obj ((inferior_object *) 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;)
{
- Py_DECREF (th_entry->thread_obj);
-
th_tmp = th_entry;
th_entry = th_entry->next;
- xfree (th_tmp);
+ delete th_tmp;
}
inf_obj->nthreads = 0;
PyObject *
gdbpy_selected_inferior (PyObject *self, PyObject *args)
{
- return (PyObject *) inferior_to_inferior_object (current_inferior ());
+ return ((PyObject *)
+ inferior_to_inferior_object (current_inferior ()).release ());
}
int
if (PyType_Ready (&membuf_object_type) < 0)
return -1;
- return gdb_pymodule_addobject (gdb_module, "Membuf", (PyObject *)
- &membuf_object_type);
+ return gdb_pymodule_addobject (gdb_module, "Membuf",
+ (PyObject *) &membuf_object_type);
}
static gdb_PyGetSetDef inferior_object_getset[] =
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 }
};
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 }
};
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
- 0, /* tp_repr */
+ infpy_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
#else
-/* Python doesn't provide a decent way to get compatibility here. */
-#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,
- /* The cast here works around a difference between Python 2.4 and
- Python 2.5. */
- (CHARBUFFERPROC_NAME) get_char_buffer
+ get_char_buffer
};
#endif /* IS_PY3K */