Skip to content

Commit

Permalink
Allow naming and configuring order of object finders
Browse files Browse the repository at this point in the history
This one doesn't need any changes to the callback signature, just the
new interface. We also keep add_object_finder() for compatibility.

Signed-off-by: Omar Sandoval <[email protected]>
  • Loading branch information
osandov committed Jun 5, 2024
1 parent 5b18f6e commit 2d8aeac
Show file tree
Hide file tree
Showing 15 changed files with 290 additions and 264 deletions.
59 changes: 51 additions & 8 deletions _drgn.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,49 @@ class Program:
def enabled_type_finders(self) -> List[str]:
"""Return the names of enabled type finders, in order."""
...
def register_object_finder(
self,
name: str,
fn: Callable[[Program, str, FindObjectFlags, Optional[str]], Optional[Object]],
*,
enable_index: Optional[int] = None,
) -> None:
"""
Register a callback for finding objects in the program.
This does not enable the finder unless *enable_index* is given.
:param name: Finder name.
:param fn: Callable taking the program, name, :class:`FindObjectFlags`,
and filename: ``(prog, name, flags, filename)``. The filename
should be matched with :func:`filename_matches()`. This should
return an :class:`Object` or ``None`` if not found.
:param enable_index: Insert the finder into the list of enabled object
finders at the given index. If -1 or greater than the number of
enabled finders, insert it at the end. If ``None`` or not given,
don't enable the finder.
:raises ValueError: if there is already a finder with the given name
"""
...
def registered_object_finders(self) -> Set[str]:
"""Return the names of all registered object finders."""
...
def set_enabled_object_finders(self, names: Sequence[str]) -> None:
"""
Set the list of enabled object finders.
Finders are called in the same order as the list until an object is found.
Finders that are not in the list are not called.
:param names: Names of finders to enable, in order.
:raises ValueError: if no finder has a given name or the same name is
given more than once
"""
...
def enabled_object_finders(self) -> List[str]:
"""Return the names of enabled object finders, in order."""
...
def register_symbol_finder(
self,
name: str,
Expand Down Expand Up @@ -563,16 +606,16 @@ class Program:
fn: Callable[[Program, str, FindObjectFlags, Optional[str]], Optional[Object]],
) -> None:
"""
Register a callback for finding objects in the program.
Deprecated method to register and enable a callback for finding objects
in the program.
Callbacks are called in reverse order of the order they were added
until the object is found. So, more recently added callbacks take
precedence.
.. deprecated:: 0.0.27
Use :meth:`register_object_finder()` instead.
:param fn: Callable taking a program, name, :class:`FindObjectFlags`,
and filename: ``(prog, name, flags, filename)``. The filename
should be matched with :func:`filename_matches()`. This should
return an :class:`Object` or ``None`` if not found.
The differences from :meth:`register_object_finder()` are:
1. A name for the finder is generated from *fn*.
2. The finder is always enabled before any existing finders.
"""
...
def set_core_dump(self, path: Union[Path, int]) -> None:
Expand Down
2 changes: 1 addition & 1 deletion docs/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ program "memory":
run_interactive(prog, banner_func=lambda _: "BTRFS debugger")
:meth:`drgn.Program.register_type_finder()` and
:meth:`drgn.Program.add_object_finder()` are the equivalent methods for
:meth:`drgn.Program.register_object_finder()` are the equivalent methods for
plugging in types and objects.

Environment Variables
Expand Down
2 changes: 0 additions & 2 deletions libdrgn/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ libdrgnimpl_la_SOURCES = $(ARCH_DEFS_PYS:_defs.py=.c) \
nstring.h \
object.c \
object.h \
object_index.c \
object_index.h \
openmp.c \
openmp.h \
orc.h \
Expand Down
9 changes: 6 additions & 3 deletions libdrgn/debug_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -2187,9 +2187,12 @@ void drgn_debug_info_init(struct drgn_debug_info *dbinfo,
drgn_program_register_type_finder_impl(prog, &dbinfo->type_finder,
"dwarf", &type_finder_ops,
dbinfo, 0);
drgn_program_add_object_finder_impl(prog, &dbinfo->object_finder,
drgn_debug_info_find_object,
dbinfo);
const struct drgn_object_finder_ops object_finder_ops = {
.find = drgn_debug_info_find_object,
};
drgn_program_register_object_finder_impl(prog, &dbinfo->object_finder,
"dwarf", &object_finder_ops,
dbinfo, 0);
const struct drgn_symbol_finder_ops symbol_finder_ops = {
.find = elf_symbols_search,
};
Expand Down
6 changes: 3 additions & 3 deletions libdrgn/debug_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "drgn.h"
#include "dwarf_info.h"
#include "hash_table.h"
#include "object_index.h"
#include "object.h"
#include "orc_info.h"
#include "string_builder.h"
#include "symbol.h"
Expand Down Expand Up @@ -253,13 +253,13 @@ struct drgn_error *
drgn_debug_info_main_language(struct drgn_debug_info *dbinfo,
const struct drgn_language **ret);

/** @ref drgn_type_find_fn() that uses debugging information. */
/** @ref drgn_type_finder_ops::find() that uses debugging information. */
struct drgn_error *drgn_debug_info_find_type(uint64_t kinds, const char *name,
size_t name_len,
const char *filename, void *arg,
struct drgn_qualified_type *ret);

/** @ref drgn_object_find_fn() that uses debugging information. */
/** @ref drgn_object_finder_ops::find() that uses debugging information. */
struct drgn_error *
drgn_debug_info_find_object(const char *name, size_t name_len,
const char *filename,
Expand Down
98 changes: 75 additions & 23 deletions libdrgn/drgn.h
Original file line number Diff line number Diff line change
Expand Up @@ -685,38 +685,90 @@ enum drgn_find_object_flags {
DRGN_FIND_OBJECT_ANY = (1 << 3) - 1,
};

/** Object finder callback table. */
struct drgn_object_finder_ops {
/**
* Callback to destroy the object finder.
*
* This may be @c NULL.
*
* @param[in] arg Argument passed to @ref
* drgn_program_register_object_finder().
*/
void (*destroy)(void *arg);
/**
* Callback for finding an object.
*
* @param[in] name Name of object. This is @em not null-terminated.
* @param[in] name_len Length of @p name.
* @param[in] filename Filename containing the object definition or @c
* NULL. This should be matched with @ref drgn_filename_matches().
* @param[in] flags Flags indicating what kind of object to look for.
* @param[in] arg Argument passed to @ref
* drgn_program_register_object_finder().
* @param[out] ret Returned object. This must only be modified on
* success.
* @return @c NULL on success, non-@c NULL on error. In particular, if
* the object is not found, this should return &@ref drgn_not_found; any
* other errors are considered fatal.
*/
struct drgn_error *(*find)(const char *name, size_t name_len,
const char *filename,
enum drgn_find_object_flags flags,
void *arg, struct drgn_object *ret);
};

/**
* Callback for finding an object.
* Register an object finding callback.
*
* @param[in] name Name of object. This is @em not null-terminated.
* @param[in] name_len Length of @p name.
* @param[in] filename Filename containing the object definition or @c NULL.
* This should be matched with @ref drgn_filename_matches().
* @param[in] flags Flags indicating what kind of object to look for.
* @param[in] arg Argument passed to @ref drgn_program_add_object_finder().
* @param[out] ret Returned object. This must only be modified on success.
* @return @c NULL on success, non-@c NULL on error. In particular, if the
* object is not found, this should return &@ref drgn_not_found; any other
* errors are considered fatal.
* @param[in] name Finder name. This is copied.
* @param[in] ops Callback table. This is copied.
* @param[in] arg Argument to pass to callbacks.
* @param[in] enable_index Insert the finder into the list of enabled finders at
* the given index. If @ref DRGN_HANDLER_REGISTER_ENABLE_LAST or greater than
* the number of enabled finders, insert it at the end. If @ref
* DRGN_HANDLER_REGISTER_DONT_ENABLE, don’t enable the finder.
*/
typedef struct drgn_error *
(*drgn_object_find_fn)(const char *name, size_t name_len, const char *filename,
enum drgn_find_object_flags flags, void *arg,
struct drgn_object *ret);
struct drgn_error *
drgn_program_register_object_finder(struct drgn_program *prog, const char *name,
const struct drgn_object_finder_ops *ops,
void *arg, size_t enable_index);

/**
* Register a object finding callback.
* Get the names of all registered object finders.
*
* Callbacks are called in reverse order of the order they were added until the
* object is found. So, more recently added callbacks take precedence.
* The order of the names is arbitrary.
*
* @param[in] fn The callback.
* @param[in] arg Argument to pass to @p fn.
* @return @c NULL on success, non-@c NULL on error.
* @param[out] names_ret Returned array of names.
* @param[out] count_ret Returned number of names in @p names_ret.
*/
struct drgn_error *
drgn_program_add_object_finder(struct drgn_program *prog,
drgn_object_find_fn fn, void *arg);
drgn_program_registered_object_finders(struct drgn_program *prog,
const char ***names_ret,
size_t *count_ret);

/**
* Set the list of enabled object finders.
*
* Finders are called in the same order as the list until a object is found.
*
* @param[in] names Names of finders to enable, in order.
* @param[in] count Number of names in @p names.
*/
struct drgn_error *
drgn_program_set_enabled_object_finders(struct drgn_program *prog,
const char * const *names,
size_t count);

/**
* Get the names of enabled object finders, in order.
*
* @param[out] names_ret Returned array of names.
* @param[out] count_ret Returned number of names in @p names_ret.
*/
struct drgn_error *
drgn_program_enabled_object_finders(struct drgn_program *prog,
const char ***names_ret, size_t *count_ret);

/**
* Set a @ref drgn_program to a core dump.
Expand Down
6 changes: 4 additions & 2 deletions libdrgn/linux_kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,10 @@ static struct drgn_error *linux_kernel_get_vmemmap(struct drgn_program *prog,
struct drgn_error *drgn_program_finish_set_kernel(struct drgn_program *prog)
{
struct drgn_error *err;
err = drgn_program_add_object_finder(prog, linux_kernel_object_find,
prog);
const struct drgn_object_finder_ops ops = {
.find = linux_kernel_object_find,
};
err = drgn_program_register_object_finder(prog, "linux", &ops, prog, 0);
if (err)
return err;
if (!prog->lang)
Expand Down
6 changes: 6 additions & 0 deletions libdrgn/object.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@
* @{
*/

struct drgn_object_finder {
struct drgn_handler handler;
struct drgn_object_finder_ops ops;
void *arg;
};

/** Allocate a zero-initialized @ref drgn_value. */
static inline bool drgn_value_zalloc(uint64_t size, union drgn_value *value_ret,
char **buf_ret)
Expand Down
94 changes: 0 additions & 94 deletions libdrgn/object_index.c

This file was deleted.

Loading

0 comments on commit 2d8aeac

Please sign in to comment.