From: Jan Vrany Date: Thu, 21 Nov 2024 12:31:21 +0000 (+0000) Subject: gdb/python: allow instantiation of gdb.LineTable objects X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=171a85e2619bf1898efbb6e50bed381296caf870;p=thirdparty%2Fbinutils-gdb.git gdb/python: allow instantiation of gdb.LineTable objects This commit allows users to instantiate gdb.LineTable objects. This is a step towards a Python support for dynamically generated code (JIT) in GDB. Reviewed-By: Eli Zaretskii --- diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 7d7441b66ca..4f92fcf24fc 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -6728,6 +6728,14 @@ Line: 45 Address: 0x400615L In addition to being able to iterate over a @code{LineTable}, it also has the following direct access methods: +@defun LineTable.__init__ (symtab, entries) +Creates a new @code{LineTable} object and associate it with given +@var{symtab}. Old linetable that might already be associated with @var{symtab} +is discarded. The @var{entries} argument is a list of @code{LineTableEntry} +objects that constitute the newly created line table. Line table entries +do not need to be sorted. +@end defun + @defun LineTable.line (line) Return a Python @code{Tuple} of @code{LineTableEntry} objects for any entries in the line table for the given @var{line}, which specifies diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c index 83a32389132..4e93feabee8 100644 --- a/gdb/python/py-linetable.c +++ b/gdb/python/py-linetable.c @@ -17,7 +17,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include #include "python-internal.h" +#include "objfiles.h" struct linetable_entry_object { PyObject_HEAD @@ -294,6 +296,102 @@ ltpy_is_valid (PyObject *self, PyObject *args) Py_RETURN_TRUE; } +/* Object initializer; creates new linetable. + + Use: __init__(SYMTAB, ENTRIES). */ + +static int +ltpy_init (PyObject *zelf, PyObject *args, PyObject *kw) +{ + struct linetable_object *self = (struct linetable_object*) zelf; + + static const char *keywords[] = { "symtab", "entries", nullptr }; + PyObject *symtab_obj; + PyObject *entries; + + if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "OO", keywords, + &symtab_obj, &entries)) + return -1; + + struct symtab *symtab = symtab_object_to_symtab (symtab_obj); + if (symtab == nullptr) + { + PyErr_Format (PyExc_TypeError, + _("The symtab argument is not valid gdb.Symtab.")); + return -1; + } + + if (!PyList_Check (entries)) + { + PyErr_Format (PyExc_TypeError, + _("The entries parameter is not a list.")); + return -1; + } + + struct objfile *objfile = symtab->compunit ()->objfile (); + + /* Commit 1acc9dca "Change linetables to be objfile-independent" + changed linetables so that entries contain relative of objfile's + text section offset. Since the objfile has been created dynamically + and may not have "text" section offset initialized, we do it here. + + Note that here no section is added to objfile (since that requires + having bfd_section first), only text offset. */ + if (objfile->sect_index_text == -1) + { + objfile->section_offsets.push_back (0); + objfile->sect_index_text = objfile->section_offsets.size () - 1; + } + CORE_ADDR text_section_offset = objfile->text_section_offset (); + + long nentries = PyList_Size (entries); + long linetable_size + = sizeof (struct linetable) + + std::max(nentries - 1, 0L) * sizeof (struct linetable_entry); + struct linetable *linetable + = (struct linetable *)obstack_alloc (&(objfile->objfile_obstack), + linetable_size); + linetable->nitems = nentries; + for (int i = 0; i < nentries; i++) + { + linetable_entry_object *entry_obj + = (linetable_entry_object *)PyList_GetItem (entries, i); + ; + if (! PyObject_TypeCheck (entry_obj , &linetable_entry_object_type)) + { + PyErr_Format (PyExc_TypeError, + _("Element at %d of entries argument is not a " + "gdb.LineTableEntry object"), i); + return -1; + } + + /* Since PC of entries passed to this function are "unrelocated", + we compensate here. */ + CORE_ADDR pc ((CORE_ADDR)entry_obj->pc - text_section_offset); + + linetable->item[i].line = entry_obj->line; + linetable->item[i].set_unrelocated_pc (unrelocated_addr (pc)); + linetable->item[i].is_stmt = entry_obj->is_stmt; + linetable->item[i].prologue_end = entry_obj->prologue_end; + linetable->item[i].epilogue_begin = entry_obj->epilogue_begin; + } + /* Now sort the entries in increasing PC order. */ + if (nentries > 0) + { + auto linetable_entry_ordering = [] (const struct linetable_entry &e1, + const struct linetable_entry &e2) + { + return e1.unrelocated_pc () < e2.unrelocated_pc (); + }; + std::sort (&(linetable->item[0]), &(linetable->item[nentries]), + linetable_entry_ordering); + } + symtab->set_linetable (linetable); + self->symtab = symtab_obj; + Py_INCREF (symtab_obj); + + return 0; +} /* Deconstructor for the line table object. Decrement the reference to the symbol table object before calling the default free. */ @@ -302,7 +400,8 @@ ltpy_dealloc (PyObject *self) { linetable_object *obj = (linetable_object *) self; - Py_DECREF (obj->symtab); + if (obj->symtab) + Py_DECREF (obj->symtab); Py_TYPE (self)->tp_free (self); } @@ -591,8 +690,9 @@ PyTypeObject linetable_object_type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - 0, /* tp_init */ + ltpy_init, /* tp_init */ 0, /* tp_alloc */ + PyType_GenericNew /* tp_new */ }; static PyMethodDef ltpy_iterator_methods[] = { diff --git a/gdb/testsuite/gdb.python/py-linetable.exp b/gdb/testsuite/gdb.python/py-linetable.exp index e14a3bc1a0d..1c94a0b97c9 100644 --- a/gdb/testsuite/gdb.python/py-linetable.exp +++ b/gdb/testsuite/gdb.python/py-linetable.exp @@ -39,12 +39,12 @@ gdb_py_test_silent_cmd "python lt = gdb.selected_frame().find_sal().symtab.linet gdb_test_multiline "input simple command" \ "python" "" \ - "def list_lines():" "" \ + "def list_lines(lt):" "" \ " for l in lt:" "" \ " print ('L' + str(l.line) + ' A ' + hex(l.pc))" "" \ "end" "" -gdb_test "python list_lines()" \ +gdb_test "python list_lines(lt)" \ "L20 A $hex.*L21 A $hex.*L22 A $hex.*L24 A $hex.*L25 A $hex.*L40 A $hex.*L42 A $hex.*L44 A $hex.*L42 A $hex.*L46 A $hex.*" \ "test linetable iterator addr" gdb_test "python print(len(lt.line(42)))" "2" \ @@ -106,3 +106,31 @@ gdb_test "python print( gdb.LineTableEntry('xx', 123456).pc)" \ gdb_test "python print( gdb.LineTableEntry(10, 123456, prologue_end = True).prologue_end)" \ "True" \ "test prologue_end keyword argument" + +# Test gdb.LineTable.__init__(). To do so, we create new compunit and new +# symtab. +gdb_py_test_silent_cmd "python cu = gdb.Compunit(\"dynamic_cu\", gdb.Objfile(\"dynamic_objf\"), 0x100, 0x200)" \ + "create new compunit" 1 +gdb_py_test_silent_cmd "python st = gdb.Symtab(\"dynamic_st\", cu)" \ + "create new symtab" 1 +gdb_test "python lt2 = gdb.LineTable(st, \[gdb.LineTableEntry(10, 0x123)\]); print(lt)" \ + "