X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;ds=inline;f=gdb%2Fpython%2Fpy-objfile.c;h=5dc9ae65ed986a6c562ee529e339fe1e837941be;hb=c74f7d1c6c5a968330208757f476c67a4bb66643;hp=732edb0077f56787d561965272df716326ff4730;hpb=f92adf3ccc9f87786c3ed6ca1bf2ced52cfbcd62;p=binutils-gdb.git diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c index 732edb0077f..5dc9ae65ed9 100644 --- a/gdb/python/py-objfile.c +++ b/gdb/python/py-objfile.c @@ -1,6 +1,6 @@ /* Python interface to objfiles. - Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2008-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -22,6 +22,8 @@ #include "charset.h" #include "objfiles.h" #include "language.h" +#include "build-id.h" +#include "symtab.h" typedef struct { @@ -30,50 +32,213 @@ typedef struct /* The corresponding objfile. */ struct objfile *objfile; + /* Dictionary holding user-added attributes. + This is the __dict__ attribute of the object. */ + PyObject *dict; + /* The pretty-printer list of functions. */ PyObject *printers; + + /* The frame filter list of functions. */ + PyObject *frame_filters; + + /* The list of frame unwinders. */ + PyObject *frame_unwinders; + + /* The type-printer list. */ + PyObject *type_printers; + + /* The debug method matcher list. */ + PyObject *xmethods; } objfile_object; -static PyTypeObject objfile_object_type; +extern PyTypeObject objfile_object_type + CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("objfile_object"); static const struct objfile_data *objfpy_objfile_data_key; +/* Require that OBJF be a valid objfile. */ +#define OBJFPY_REQUIRE_VALID(obj) \ + do { \ + if (!(obj)->objfile) \ + { \ + PyErr_SetString (PyExc_RuntimeError, \ + _("Objfile no longer exists.")); \ + return NULL; \ + } \ + } while (0) + /* An Objfile method which returns the objfile's file name, or None. */ + static PyObject * objfpy_get_filename (PyObject *self, void *closure) { objfile_object *obj = (objfile_object *) self; - if (obj->objfile && obj->objfile->name) - return PyString_Decode (obj->objfile->name, strlen (obj->objfile->name), + + if (obj->objfile) + return PyString_Decode (objfile_name (obj->objfile), + strlen (objfile_name (obj->objfile)), host_charset (), NULL); Py_RETURN_NONE; } +/* An Objfile method which returns the objfile's file name, as specified + by the user, or None. */ + +static PyObject * +objfpy_get_username (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + + if (obj->objfile) + { + const char *username = obj->objfile->original_name; + + return PyString_Decode (username, strlen (username), + host_charset (), NULL); + } + + Py_RETURN_NONE; +} + +/* If SELF is a separate debug-info file, return the "backlink" field. + Otherwise return None. */ + +static PyObject * +objfpy_get_owner (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + struct objfile *objfile = obj->objfile; + struct objfile *owner; + + OBJFPY_REQUIRE_VALID (obj); + + owner = objfile->separate_debug_objfile_backlink; + if (owner != NULL) + { + PyObject *result = objfile_to_objfile_object (owner); + + Py_XINCREF (result); + return result; + } + Py_RETURN_NONE; +} + +/* An Objfile method which returns the objfile's build id, or None. */ + +static PyObject * +objfpy_get_build_id (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + struct objfile *objfile = obj->objfile; + const struct bfd_build_id *build_id = NULL; + + OBJFPY_REQUIRE_VALID (obj); + + TRY + { + build_id = build_id_bfd_get (objfile->obfd); + } + CATCH (except, RETURN_MASK_ALL) + { + GDB_PY_HANDLE_EXCEPTION (except); + } + END_CATCH + + if (build_id != NULL) + { + char *hex_form = make_hex_string (build_id->data, build_id->size); + PyObject *result; + + result = PyString_Decode (hex_form, strlen (hex_form), + host_charset (), NULL); + xfree (hex_form); + return result; + } + + Py_RETURN_NONE; +} + +/* An Objfile method which returns the objfile's progspace, or None. */ + +static PyObject * +objfpy_get_progspace (PyObject *self, void *closure) +{ + objfile_object *obj = (objfile_object *) self; + + if (obj->objfile) + { + PyObject *pspace = pspace_to_pspace_object (obj->objfile->pspace); + + Py_XINCREF (pspace); + return pspace; + } + + Py_RETURN_NONE; +} + static void objfpy_dealloc (PyObject *o) { objfile_object *self = (objfile_object *) o; + + Py_XDECREF (self->dict); Py_XDECREF (self->printers); - self->ob_type->tp_free ((PyObject *) self); + Py_XDECREF (self->frame_filters); + Py_XDECREF (self->frame_unwinders); + Py_XDECREF (self->type_printers); + Py_XDECREF (self->xmethods); + Py_TYPE (self)->tp_free (self); +} + +/* Initialize an objfile_object. + The result is a boolean indicating success. */ + +static int +objfpy_initialize (objfile_object *self) +{ + self->objfile = NULL; + self->dict = NULL; + + self->printers = PyList_New (0); + if (self->printers == NULL) + return 0; + + self->frame_filters = PyDict_New (); + if (self->frame_filters == NULL) + return 0; + + self->frame_unwinders = PyList_New (0); + if (self->frame_unwinders == NULL) + return 0; + + self->type_printers = PyList_New (0); + if (self->type_printers == NULL) + return 0; + + self->xmethods = PyList_New (0); + if (self->xmethods == NULL) + return 0; + + return 1; } static PyObject * objfpy_new (PyTypeObject *type, PyObject *args, PyObject *keywords) { objfile_object *self = (objfile_object *) type->tp_alloc (type, 0); + if (self) { - self->objfile = NULL; - - self->printers = PyList_New (0); - if (!self->printers) + if (!objfpy_initialize (self)) { Py_DECREF (self); return NULL; } } + return (PyObject *) self; } @@ -81,6 +246,7 @@ PyObject * objfpy_get_printers (PyObject *o, void *ignore) { objfile_object *self = (objfile_object *) o; + Py_INCREF (self->printers); return self->printers; } @@ -90,6 +256,7 @@ objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) { PyObject *tmp; objfile_object *self = (objfile_object *) o; + if (! value) { PyErr_SetString (PyExc_TypeError, @@ -113,6 +280,333 @@ objfpy_set_printers (PyObject *o, PyObject *value, void *ignore) return 0; } +/* Return the Python dictionary attribute containing frame filters for + this object file. */ +PyObject * +objfpy_get_frame_filters (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + + Py_INCREF (self->frame_filters); + return self->frame_filters; +} + +/* Set this object file's frame filters dictionary to FILTERS. */ +static int +objfpy_set_frame_filters (PyObject *o, PyObject *filters, void *ignore) +{ + PyObject *tmp; + objfile_object *self = (objfile_object *) o; + + if (! filters) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete the frame filters attribute.")); + return -1; + } + + if (! PyDict_Check (filters)) + { + PyErr_SetString (PyExc_TypeError, + _("The frame_filters attribute must be a dictionary.")); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->frame_filters; + Py_INCREF (filters); + self->frame_filters = filters; + Py_XDECREF (tmp); + + return 0; +} + +/* Return the frame unwinders attribute for this object file. */ + +PyObject * +objfpy_get_frame_unwinders (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + + Py_INCREF (self->frame_unwinders); + return self->frame_unwinders; +} + +/* Set this object file's frame unwinders list to UNWINDERS. */ + +static int +objfpy_set_frame_unwinders (PyObject *o, PyObject *unwinders, void *ignore) +{ + PyObject *tmp; + objfile_object *self = (objfile_object *) o; + + if (!unwinders) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete the frame unwinders attribute.")); + return -1; + } + + if (!PyList_Check (unwinders)) + { + PyErr_SetString (PyExc_TypeError, + _("The frame_unwinders attribute must be a list.")); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->frame_unwinders; + Py_INCREF (unwinders); + self->frame_unwinders = unwinders; + Py_XDECREF (tmp); + + return 0; +} + +/* Get the 'type_printers' attribute. */ + +static PyObject * +objfpy_get_type_printers (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + + Py_INCREF (self->type_printers); + return self->type_printers; +} + +/* Get the 'xmethods' attribute. */ + +PyObject * +objfpy_get_xmethods (PyObject *o, void *ignore) +{ + objfile_object *self = (objfile_object *) o; + + Py_INCREF (self->xmethods); + return self->xmethods; +} + +/* Set the 'type_printers' attribute. */ + +static int +objfpy_set_type_printers (PyObject *o, PyObject *value, void *ignore) +{ + PyObject *tmp; + objfile_object *self = (objfile_object *) o; + + if (! value) + { + PyErr_SetString (PyExc_TypeError, + _("Cannot delete the type_printers attribute.")); + return -1; + } + + if (! PyList_Check (value)) + { + PyErr_SetString (PyExc_TypeError, + _("The type_printers attribute must be a list.")); + return -1; + } + + /* Take care in case the LHS and RHS are related somehow. */ + tmp = self->type_printers; + Py_INCREF (value); + self->type_printers = value; + Py_XDECREF (tmp); + + return 0; +} + +/* Implementation of gdb.Objfile.is_valid (self) -> Boolean. + Returns True if this object file still exists in GDB. */ + +static PyObject * +objfpy_is_valid (PyObject *self, PyObject *args) +{ + objfile_object *obj = (objfile_object *) self; + + if (! obj->objfile) + Py_RETURN_FALSE; + + Py_RETURN_TRUE; +} + +/* Implementation of gdb.Objfile.add_separate_debug_file (self) -> Boolean. */ + +static PyObject * +objfpy_add_separate_debug_file (PyObject *self, PyObject *args, PyObject *kw) +{ + static char *keywords[] = { "file_name", NULL }; + objfile_object *obj = (objfile_object *) self; + const char *file_name; + int symfile_flags = 0; + + OBJFPY_REQUIRE_VALID (obj); + + if (!PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &file_name)) + return NULL; + + TRY + { + bfd *abfd = symfile_bfd_open (file_name); + + symbol_file_add_separate (abfd, file_name, symfile_flags, obj->objfile); + } + CATCH (except, RETURN_MASK_ALL) + { + GDB_PY_HANDLE_EXCEPTION (except); + } + END_CATCH + + Py_RETURN_NONE; +} + +/* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it. + Return non-zero if STRING is a potentially valid build id. */ + +static int +objfpy_build_id_ok (const char *string) +{ + size_t i, n = strlen (string); + + if (n % 2 != 0) + return 0; + for (i = 0; i < n; ++i) + { + if (!isxdigit (string[i])) + return 0; + } + return 1; +} + +/* Subroutine of gdbpy_lookup_objfile_by_build_id to simplify it. + Returns non-zero if BUILD_ID matches STRING. + It is assumed that objfpy_build_id_ok (string) returns TRUE. */ + +static int +objfpy_build_id_matches (const struct bfd_build_id *build_id, + const char *string) +{ + size_t i; + + if (strlen (string) != 2 * build_id->size) + return 0; + + for (i = 0; i < build_id->size; ++i) + { + char c1 = string[i * 2], c2 = string[i * 2 + 1]; + int byte = (host_hex_value (c1) << 4) | host_hex_value (c2); + + if (byte != build_id->data[i]) + return 0; + } + + return 1; +} + +/* Subroutine of gdbpy_lookup_objfile to simplify it. + Look up an objfile by its file name. */ + +static struct objfile * +objfpy_lookup_objfile_by_name (const char *name) +{ + struct objfile *objfile; + + ALL_OBJFILES (objfile) + { + const char *filename; + + if ((objfile->flags & OBJF_NOT_FILENAME) != 0) + continue; + /* Don't return separate debug files. */ + if (objfile->separate_debug_objfile_backlink != NULL) + continue; + + filename = objfile_filename (objfile); + if (filename != NULL && compare_filenames_for_search (filename, name)) + return objfile; + if (compare_filenames_for_search (objfile->original_name, name)) + return objfile; + } + + return NULL; +} + +/* Subroutine of gdbpy_lookup_objfile to simplify it. + Look up an objfile by its build id. */ + +static struct objfile * +objfpy_lookup_objfile_by_build_id (const char *build_id) +{ + struct objfile *objfile; + + ALL_OBJFILES (objfile) + { + const struct bfd_build_id *obfd_build_id; + + if (objfile->obfd == NULL) + continue; + /* Don't return separate debug files. */ + if (objfile->separate_debug_objfile_backlink != NULL) + continue; + obfd_build_id = build_id_bfd_get (objfile->obfd); + if (obfd_build_id == NULL) + continue; + if (objfpy_build_id_matches (obfd_build_id, build_id)) + return objfile; + } + + return NULL; +} + +/* Implementation of gdb.lookup_objfile. */ + +PyObject * +gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw) +{ + static char *keywords[] = { "name", "by_build_id", NULL }; + const char *name; + PyObject *by_build_id_obj = NULL; + int by_build_id; + struct objfile *objfile; + + if (! PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords, + &name, &PyBool_Type, &by_build_id_obj)) + return NULL; + + by_build_id = 0; + if (by_build_id_obj != NULL) + { + int cmp = PyObject_IsTrue (by_build_id_obj); + + if (cmp < 0) + return NULL; + by_build_id = cmp; + } + + if (by_build_id) + { + if (!objfpy_build_id_ok (name)) + { + PyErr_SetString (PyExc_TypeError, _("Not a valid build id.")); + return NULL; + } + objfile = objfpy_lookup_objfile_by_build_id (name); + } + else + objfile = objfpy_lookup_objfile_by_name (name); + + if (objfile != NULL) + { + PyObject *result = objfile_to_objfile_object (objfile); + + Py_XINCREF (result); + return result; + } + + PyErr_SetString (PyExc_ValueError, _("Objfile not found.")); + return NULL; +} + /* Clear the OBJFILE pointer in an Objfile object and remove the @@ -133,6 +627,7 @@ py_free_objfile (struct objfile *objfile, void *datum) representing OBJFILE. If the object has already been created, return it. Otherwise, create it. Return NULL and set the Python error on failure. */ + PyObject * objfile_to_objfile_object (struct objfile *objfile) { @@ -144,15 +639,13 @@ objfile_to_objfile_object (struct objfile *objfile) object = PyObject_New (objfile_object, &objfile_object_type); if (object) { - object->objfile = objfile; - - object->printers = PyList_New (0); - if (!object->printers) + if (!objfpy_initialize (object)) { Py_DECREF (object); return NULL; } + object->objfile = objfile; set_objfile_data (objfile, objfpy_objfile_data_key, object); } } @@ -160,34 +653,66 @@ objfile_to_objfile_object (struct objfile *objfile) return (PyObject *) object; } -void +int gdbpy_initialize_objfile (void) { objfpy_objfile_data_key = register_objfile_data_with_cleanup (NULL, py_free_objfile); if (PyType_Ready (&objfile_object_type) < 0) - return; + return -1; - Py_INCREF (&objfile_object_type); - PyModule_AddObject (gdb_module, "Objfile", (PyObject *) &objfile_object_type); + return gdb_pymodule_addobject (gdb_module, "Objfile", + (PyObject *) &objfile_object_type); } +static PyMethodDef objfile_object_methods[] = +{ + { "is_valid", objfpy_is_valid, METH_NOARGS, + "is_valid () -> Boolean.\n\ +Return true if this object file is valid, false if not." }, + + { "add_separate_debug_file", (PyCFunction) objfpy_add_separate_debug_file, + METH_VARARGS | METH_KEYWORDS, + "add_separate_debug_file (file_name).\n\ +Add FILE_NAME to the list of files containing debug info for the objfile." }, + + { NULL } +}; + static PyGetSetDef objfile_getset[] = { + { "__dict__", gdb_py_generic_dict, NULL, + "The __dict__ for this objfile.", &objfile_object_type }, { "filename", objfpy_get_filename, NULL, "The objfile's filename, or None.", NULL }, + { "username", objfpy_get_username, NULL, + "The name of the objfile as provided by the user, or None.", NULL }, + { "owner", objfpy_get_owner, NULL, + "The objfile owner of separate debug info objfiles, or None.", + NULL }, + { "build_id", objfpy_get_build_id, NULL, + "The objfile's build id, or None.", NULL }, + { "progspace", objfpy_get_progspace, NULL, + "The objfile's progspace, or None.", NULL }, { "pretty_printers", objfpy_get_printers, objfpy_set_printers, "Pretty printers.", NULL }, + { "frame_filters", objfpy_get_frame_filters, + objfpy_set_frame_filters, "Frame Filters.", NULL }, + { "frame_unwinders", objfpy_get_frame_unwinders, + objfpy_set_frame_unwinders, "Frame Unwinders", NULL }, + { "type_printers", objfpy_get_type_printers, objfpy_set_type_printers, + "Type printers.", NULL }, + { "xmethods", objfpy_get_xmethods, NULL, + "Debug methods.", NULL }, { NULL } }; -static PyTypeObject objfile_object_type = +PyTypeObject objfile_object_type = { - PyObject_HEAD_INIT (NULL) - 0, /*ob_size*/ + PyVarObject_HEAD_INIT (NULL, 0) "gdb.Objfile", /*tp_name*/ sizeof (objfile_object), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -214,14 +739,14 @@ static PyTypeObject objfile_object_type = 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + objfile_object_methods, /* tp_methods */ 0, /* tp_members */ objfile_getset, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ + offsetof (objfile_object, dict), /* tp_dictoffset */ 0, /* tp_init */ 0, /* tp_alloc */ objfpy_new, /* tp_new */