gdb, python: use gdbarch_iterate_over_objfiles_in_search_order

The implementation of gdb.lookup_objfile() iterates over all objfiles and
compares their name or build id to the user-provided search string.

This will cause problems when supporting linker namespaces as the first
objfile in any namespace will be found.  Instead, use
gdbarch_iterate_over_objfiles_in_search_order to only consider the
namespace of gdb.current_objfile() for the search, which defaults to the
initial namespace when gdb.current_objfile() is None.
This commit is contained in:
Markus Metzger
2022-04-11 16:44:36 +02:00
parent fb4f3f38e9
commit 85933f7c91
3 changed files with 64 additions and 65 deletions

View File

@ -24,6 +24,7 @@
#include "language.h" #include "language.h"
#include "build-id.h" #include "build-id.h"
#include "symtab.h" #include "symtab.h"
#include "python.h"
struct objfile_object struct objfile_object
{ {
@ -584,57 +585,6 @@ objfpy_build_id_matches (const struct bfd_build_id *build_id,
return 1; 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)
{
for (objfile *objfile : current_program_space->objfiles ())
{
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)
{
for (objfile *objfile : current_program_space->objfiles ())
{
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.get ());
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. */ /* Implementation of gdb.lookup_objfile. */
PyObject * PyObject *
@ -644,7 +594,6 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
const char *name; const char *name;
PyObject *by_build_id_obj = NULL; PyObject *by_build_id_obj = NULL;
int by_build_id; int by_build_id;
struct objfile *objfile;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords, if (!gdb_PyArg_ParseTupleAndKeywords (args, kw, "s|O!", keywords,
&name, &PyBool_Type, &by_build_id_obj)) &name, &PyBool_Type, &by_build_id_obj))
@ -660,17 +609,64 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
by_build_id = cmp; by_build_id = cmp;
} }
if (by_build_id) if (by_build_id && !objfpy_build_id_ok (name))
{ {
if (!objfpy_build_id_ok (name)) PyErr_SetString (PyExc_TypeError, _("Not a valid build id."));
{ return NULL;
PyErr_SetString (PyExc_TypeError, _("Not a valid build id."));
return NULL;
}
objfile = objfpy_lookup_objfile_by_build_id (name);
} }
struct objfile *objfile = nullptr;
if (by_build_id)
gdbarch_iterate_over_objfiles_in_search_order
(target_gdbarch (),
[&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
return 0;
bfd *obfd = obj->obfd.get ();
if (obfd == nullptr)
return 0;
const bfd_build_id *obfd_build_id = build_id_bfd_get (obfd);
if (obfd_build_id == nullptr)
return 0;
if (!objfpy_build_id_matches (obfd_build_id, name))
return 0;
objfile = obj;
return 1;
}, gdbpy_current_objfile);
else else
objfile = objfpy_lookup_objfile_by_name (name); gdbarch_iterate_over_objfiles_in_search_order
(target_gdbarch (),
[&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
return 0;
if ((obj->flags & OBJF_NOT_FILENAME) != 0)
return 0;
const char *filename = objfile_filename (obj);
if (filename != NULL
&& compare_filenames_for_search (filename, name))
{
objfile = obj;
return 1;
}
if (compare_filenames_for_search (obj->original_name, name))
{
objfile = obj;
return 1;
}
return 0;
}, gdbpy_current_objfile);
if (objfile != NULL) if (objfile != NULL)
return objfile_to_objfile_object (objfile).release (); return objfile_to_objfile_object (objfile).release ();

View File

@ -1583,11 +1583,8 @@ gdbpy_current_language (PyObject *unused1, PyObject *unused2)
/* The "current" objfile. This is set when gdb detects that a new /* See python.h. */
objfile has been loaded. It is only set for the duration of a call to struct objfile *gdbpy_current_objfile;
gdbpy_source_objfile_script and gdbpy_execute_objfile_script; it is NULL
at other times. */
static struct objfile *gdbpy_current_objfile;
/* Set the current objfile to OBJFILE and then read FILE named FILENAME /* Set the current objfile to OBJFILE and then read FILE named FILENAME
as Python code. This does not throw any errors. If an exception as Python code. This does not throw any errors. If an exception

View File

@ -28,4 +28,10 @@ extern const struct extension_language_defn extension_language_python;
/* Command element for the 'python' command. */ /* Command element for the 'python' command. */
extern cmd_list_element *python_cmd_element; extern cmd_list_element *python_cmd_element;
/* The "current" objfile. This is set when gdb detects that a new
objfile has been loaded. It is only set for the duration of a call to
gdbpy_source_objfile_script and gdbpy_execute_objfile_script; it is NULL
at other times. */
extern struct objfile *gdbpy_current_objfile;
#endif /* PYTHON_PYTHON_H */ #endif /* PYTHON_PYTHON_H */