@@ -24,6 +24,8 @@ struct linetable_entry_object {
PyObject_HEAD
/* The line table source line. */
int line;
+ /* The line table source column. */
+ int col;
/* The pc associated with the source line. */
CORE_ADDR pc;
};
@@ -99,7 +101,7 @@ symtab_to_linetable_object (PyObject *symtab)
and an address. */
static PyObject *
-build_linetable_entry (int line, CORE_ADDR address)
+build_linetable_entry (int line, int col, CORE_ADDR address)
{
linetable_entry_object *obj;
@@ -109,6 +111,7 @@ build_linetable_entry (int line, CORE_ADDR address)
{
obj->line = line;
obj->pc = address;
+ obj->col = col;
}
return (PyObject *) obj;
@@ -121,7 +124,7 @@ build_linetable_entry (int line, CORE_ADDR address)
address. */
static PyObject *
-build_line_table_tuple_from_pcs (int line, const std::vector<CORE_ADDR> &pcs)
+build_line_table_tuple_from_pcs (int line, const symtab& sym, const std::vector<linetable_entry> &pcs)
{
int i;
@@ -133,10 +136,11 @@ build_line_table_tuple_from_pcs (int line, const std::vector<CORE_ADDR> &pcs)
if (tuple == NULL)
return NULL;
+ const auto of = sym.compunit ()->objfile ();
for (i = 0; i < pcs.size (); ++i)
{
- CORE_ADDR pc = pcs[i];
- gdbpy_ref<> obj (build_linetable_entry (line, pc));
+ const auto& lte = pcs[i];
+ gdbpy_ref<> obj (build_linetable_entry (line, lte.col, lte.pc (of)));
if (obj == NULL)
return NULL;
@@ -152,12 +156,10 @@ build_line_table_tuple_from_pcs (int line, const std::vector<CORE_ADDR> &pcs)
in the line table. */
static PyObject *
-ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
+ltpy_get_ltes_for_line (PyObject *self, PyObject *args)
{
struct symtab *symtab;
gdb_py_longest py_line;
- const linetable_entry *best_entry = nullptr;
- std::vector<CORE_ADDR> pcs;
LTPY_REQUIRE_VALID (self, symtab);
@@ -166,14 +168,15 @@ ltpy_get_pcs_for_line (PyObject *self, PyObject *args)
try
{
- pcs = find_pcs_for_symtab_line (symtab, py_line, &best_entry);
+ const auto ltes = find_ltes_for_symtab_line (*symtab, py_line);
+ return build_line_table_tuple_from_pcs (py_line, *symtab, ltes);
}
catch (const gdb_exception &except)
{
GDB_PY_HANDLE_EXCEPTION (except);
}
- return build_line_table_tuple_from_pcs (py_line, pcs);
+ Py_RETURN_NONE;
}
/* Implementation of gdb.LineTable.has_line (self, line) -> Boolean.
@@ -327,6 +330,14 @@ ltpy_entry_get_line (PyObject *self, void *closure)
return gdb_py_object_from_longest (obj->line).release ();
}
+static PyObject *
+ltpy_entry_get_column (PyObject *self, void *closure)
+{
+ linetable_entry_object *obj = (linetable_entry_object *) self;
+
+ return gdb_py_object_from_longest (obj->col).release ();
+}
+
/* Implementation of gdb.LineTableEntry.pc (self) -> Long. Returns a
a long integer associated with the PC of the line table entry. */
@@ -422,7 +433,7 @@ ltpy_iternext (PyObject *self)
}
struct objfile *objfile = symtab->compunit ()->objfile ();
- obj = build_linetable_entry (item->line, item->pc (objfile));
+ obj = build_linetable_entry (item->line, item->col, item->pc (objfile));
iter_obj->current_index++;
return obj;
@@ -451,7 +462,7 @@ GDBPY_INITIALIZE_FILE (gdbpy_initialize_linetable);
static PyMethodDef linetable_object_methods[] = {
- { "line", ltpy_get_pcs_for_line, METH_VARARGS,
+ { "line", ltpy_get_ltes_for_line, METH_VARARGS,
"line (lineno) -> Tuple\n\
Return executable locations for a given source line." },
{ "has_line", ltpy_has_line, METH_VARARGS,
@@ -548,6 +559,8 @@ PyTypeObject ltpy_iterator_object_type = {
static gdb_PyGetSetDef linetable_entry_object_getset[] = {
{ "line", ltpy_entry_get_line, NULL,
"The line number in the source file.", NULL },
+ { "column", ltpy_entry_get_column, NULL,
+ "The column number in the source file", NULL },
{ "pc", ltpy_entry_get_pc, NULL,
"The memory address for this line number.", NULL },
{ NULL } /* Sentinel */
@@ -475,6 +475,39 @@ symtab_to_symtab_object (struct symtab *symtab)
return (PyObject *) symtab_obj;
}
+/* Search for a symtab whose fullname contains FILENAME and return it's
+ linetable. */
+PyObject *
+gdbpy_lookup_linetable_by_filename (PyObject *, PyObject *args, PyObject *kw)
+{
+ const char *arg = nullptr;
+ static const char *keywords[] = { "filename", nullptr };
+
+ if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s", keywords, &arg))
+ {
+ return nullptr;
+ }
+
+ for (objfile *objfile : current_program_space->objfiles ())
+ for (compunit_symtab *cu : objfile->compunits ())
+ for (symtab *s : cu->filetabs ())
+ {
+ const auto name = symtab_to_fullname (s);
+
+ if (strstr (name, arg))
+ {
+ auto symtab_pyobj = symtab_to_symtab_object (s);
+ if (!symtab_pyobj)
+ Py_RETURN_NONE;
+ auto lt_obj = symtab_to_linetable_object (symtab_pyobj);
+ if (!lt_obj)
+ Py_RETURN_NONE;
+ return lt_obj;
+ }
+ }
+ Py_RETURN_NONE;
+}
+
/* Create a new symtab and line (gdb.Symtab_and_line) object
that encapsulates the symtab_and_line structure from GDB. */
PyObject *
@@ -408,6 +408,8 @@ PyObject *gdbpy_convenience_variable (PyObject *self, PyObject *args);
PyObject *gdbpy_set_convenience_variable (PyObject *self, PyObject *args);
PyObject *gdbpy_breakpoints (PyObject *, PyObject *);
PyObject *gdbpy_frame_stop_reason_string (PyObject *, PyObject *);
+PyObject *gdbpy_lookup_linetable_by_filename (PyObject *, PyObject* args,
+ PyObject *kw);
PyObject *gdbpy_lookup_symbol (PyObject *self, PyObject *args, PyObject *kw);
PyObject *gdbpy_lookup_global_symbol (PyObject *self, PyObject *args,
PyObject *kw);
@@ -2573,6 +2573,8 @@ gdbpy_initialized (const struct extension_language_defn *extlang)
PyMethodDef python_GdbMethods[] =
{
+ { "lookup_linetable", (PyCFunction) gdbpy_lookup_linetable_by_filename,
+ METH_VARARGS | METH_KEYWORDS },
{ "history", gdbpy_history, METH_VARARGS,
"Get a value from history" },
{ "add_history", gdbpy_add_history, METH_VARARGS,
@@ -3519,7 +3519,24 @@ find_pcs_for_symtab_line (struct symtab *symtab, int line,
return result;
}
-
+/** Return line table entries for SYMTAB at LINE. */
+
+std::vector<linetable_entry>
+find_ltes_for_symtab_line (const symtab &symtab, int line)
+{
+ auto lte = symtab.linetable ();
+ if (lte == nullptr)
+ return {};
+
+ std::vector<linetable_entry> result;
+ for (auto i = 0; i < lte->nitems; ++i)
+ {
+ if (lte->item[i].line == line)
+ result.push_back (lte->item[i]);
+ }
+ return result;
+}
+
/* Set the PC value for a given source file and line number and return true.
Returns false for invalid line number (and sets the PC to 0).
The source file is specified with a struct symtab. */
@@ -2772,6 +2772,9 @@ void iterate_over_symtabs (const char *name,
std::vector<CORE_ADDR> find_pcs_for_symtab_line
(struct symtab *symtab, int line, const linetable_entry **best_entry);
+std::vector<linetable_entry> find_ltes_for_symtab_line
+ (const symtab &symtab, int line);
+
/* Prototype for callbacks for LA_ITERATE_OVER_SYMBOLS. The callback
is called once per matching symbol SYM. The callback should return
true to indicate that LA_ITERATE_OVER_SYMBOLS should continue