libdrgn: embed type and object finders in drgn_debug_info

This is preparation for embedding drgn_debug_info in drgn_program and
initializing it earlier.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
Omar Sandoval 2023-09-29 12:00:31 -07:00
parent 085b0bc9db
commit f24805486f
8 changed files with 69 additions and 46 deletions

View File

@ -2105,6 +2105,11 @@ struct drgn_error *drgn_debug_info_create(struct drgn_program *prog,
free(dbinfo);
return drgn_error_libdwfl();
}
drgn_program_add_type_finder_impl(prog, &dbinfo->type_finder,
drgn_debug_info_find_type, dbinfo);
drgn_program_add_object_finder_impl(prog, &dbinfo->object_finder,
drgn_debug_info_find_object,
dbinfo);
drgn_module_table_init(&dbinfo->modules);
c_string_set_init(&dbinfo->module_names);
drgn_dwarf_info_init(dbinfo);

View File

@ -20,8 +20,10 @@
#include "drgn.h"
#include "dwarf_info.h"
#include "hash_table.h"
#include "object_index.h"
#include "orc_info.h"
#include "string_builder.h"
#include "type.h"
#include "vector.h"
struct drgn_elf_file;
@ -133,6 +135,9 @@ struct drgn_debug_info {
/** Program owning this cache. */
struct drgn_program *prog;
struct drgn_type_finder type_finder;
struct drgn_object_finder object_finder;
/** DWARF frontend library handle. */
Dwfl *dwfl;
/** Modules keyed by build ID and address range. */

View File

@ -13,26 +13,28 @@ void drgn_object_index_init(struct drgn_object_index *oindex)
void drgn_object_index_deinit(struct drgn_object_index *oindex)
{
struct drgn_object_finder *finder;
finder = oindex->finders;
struct drgn_object_finder *finder = oindex->finders;
while (finder) {
struct drgn_object_finder *next = finder->next;
free(finder);
if (finder->free)
free(finder);
finder = next;
}
}
struct drgn_error *
drgn_object_index_add_finder(struct drgn_object_index *oindex,
struct drgn_object_finder *finder,
drgn_object_find_fn fn, void *arg)
{
struct drgn_object_finder *finder;
finder = malloc(sizeof(*finder));
if (!finder)
return &drgn_enomem;
if (finder) {
finder->free = false;
} else {
finder = malloc(sizeof(*finder));
if (!finder)
return &drgn_enomem;
finder->free = true;
}
finder->fn = fn;
finder->arg = arg;
finder->next = oindex->finders;
@ -40,13 +42,6 @@ drgn_object_index_add_finder(struct drgn_object_index *oindex,
return NULL;
}
void drgn_object_index_remove_finder(struct drgn_object_index *oindex)
{
struct drgn_object_finder *finder = oindex->finders->next;
free(oindex->finders);
oindex->finders = finder;
}
struct drgn_error *drgn_object_index_find(struct drgn_object_index *oindex,
const char *name,
const char *filename,

View File

@ -35,6 +35,8 @@ struct drgn_object_finder {
void *arg;
/** Next callback to try. */
struct drgn_object_finder *next;
/** Whether this structure needs to be freed. */
bool free;
};
/**
@ -56,14 +58,11 @@ void drgn_object_index_init(struct drgn_object_index *oindex);
/** Deinitialize a @ref drgn_object_index. */
void drgn_object_index_deinit(struct drgn_object_index *oindex);
/** @sa drgn_program_add_object_finder() */
struct drgn_error *
drgn_object_index_add_finder(struct drgn_object_index *oindex,
struct drgn_object_finder *finder,
drgn_object_find_fn fn, void *arg);
/** Remove the most recently added object finding callback. */
void drgn_object_index_remove_finder(struct drgn_object_index *oindex);
/**
* Find an object in a @ref drgn_object_index.
*

View File

@ -189,11 +189,19 @@ drgn_program_add_memory_segment(struct drgn_program *prog, uint64_t address,
physical);
}
struct drgn_error *
drgn_program_add_object_finder_impl(struct drgn_program *prog,
struct drgn_object_finder *finder,
drgn_object_find_fn fn, void *arg)
{
return drgn_object_index_add_finder(&prog->oindex, finder, fn, arg);
}
LIBDRGN_PUBLIC struct drgn_error *
drgn_program_add_object_finder(struct drgn_program *prog,
drgn_object_find_fn fn, void *arg)
{
return drgn_object_index_add_finder(&prog->oindex, fn, arg);
return drgn_program_add_object_finder_impl(prog, NULL, fn, arg);
}
static struct drgn_error *
@ -731,21 +739,6 @@ drgn_program_load_debug_info(struct drgn_program *prog, const char **paths,
err = drgn_debug_info_create(prog, &dbinfo);
if (err)
return err;
err = drgn_program_add_object_finder(prog,
drgn_debug_info_find_object,
dbinfo);
if (err) {
drgn_debug_info_destroy(dbinfo);
return err;
}
err = drgn_program_add_type_finder(prog,
drgn_debug_info_find_type,
dbinfo);
if (err) {
drgn_object_index_remove_finder(&prog->oindex);
drgn_debug_info_destroy(dbinfo);
return err;
}
prog->dbinfo = dbinfo;
}

View File

@ -244,6 +244,11 @@ struct drgn_error *drgn_program_init_kernel(struct drgn_program *prog);
*/
struct drgn_error *drgn_program_init_pid(struct drgn_program *prog, pid_t pid);
struct drgn_error *
drgn_program_add_object_finder_impl(struct drgn_program *prog,
struct drgn_object_finder *finder,
drgn_object_find_fn fn, void *arg);
static inline struct drgn_error *
drgn_program_is_little_endian(struct drgn_program *prog, bool *ret)
{

View File

@ -1307,23 +1307,37 @@ void drgn_program_deinit_types(struct drgn_program *prog)
struct drgn_type_finder *finder = prog->type_finders;
while (finder) {
struct drgn_type_finder *next = finder->next;
free(finder);
if (finder->free)
free(finder);
finder = next;
}
}
struct drgn_error *
drgn_program_add_type_finder_impl(struct drgn_program *prog,
struct drgn_type_finder *finder,
drgn_type_find_fn fn, void *arg)
{
if (finder) {
finder->free = false;
} else {
finder = malloc(sizeof(*finder));
if (!finder)
return &drgn_enomem;
finder->free = true;
}
finder->fn = fn;
finder->arg = arg;
finder->next = prog->type_finders;
prog->type_finders = finder;
return NULL;
}
LIBDRGN_PUBLIC struct drgn_error *
drgn_program_add_type_finder(struct drgn_program *prog, drgn_type_find_fn fn,
void *arg)
{
struct drgn_type_finder *finder = malloc(sizeof(*finder));
if (!finder)
return &drgn_enomem;
finder->fn = fn;
finder->arg = arg;
finder->next = prog->type_finders;
prog->type_finders = finder;
return NULL;
return drgn_program_add_type_finder_impl(prog, NULL, fn, arg);
}
struct drgn_error *drgn_program_find_type_impl(struct drgn_program *prog,

View File

@ -56,8 +56,15 @@ struct drgn_type_finder {
void *arg;
/** Next callback to try. */
struct drgn_type_finder *next;
/** Whether this structure needs to be freed. */
bool free;
};
struct drgn_error *
drgn_program_add_type_finder_impl(struct drgn_program *prog,
struct drgn_type_finder *finder,
drgn_type_find_fn fn, void *arg);
DEFINE_HASH_SET_TYPE(drgn_dedupe_type_set, struct drgn_type *);
/** <tt>(type, member name)</tt> pair. */