mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 17:23:06 +00:00
libdrgn: Add find_symbol_by_name to look up ELF symbols
This commit is contained in:
parent
054cb54a01
commit
31d544949f
@ -128,11 +128,13 @@ Programs
|
||||
:raises LookupError: if no objects with the given name are found in
|
||||
the given file
|
||||
|
||||
.. method:: symbol(address)
|
||||
.. method:: symbol(address_or_name, /)
|
||||
|
||||
Get the symbol containing the given address.
|
||||
Get the symbol containing the given address, or the global symbol with
|
||||
the given name.
|
||||
|
||||
:param int address: The address.
|
||||
:param address_or_name: The address or name.
|
||||
:type address_or_name: str or int
|
||||
:rtype: Symbol
|
||||
:raises LookupError: if no symbol contains the given address
|
||||
|
||||
|
@ -1325,6 +1325,17 @@ struct drgn_error *
|
||||
drgn_program_find_symbol_by_address(struct drgn_program *prog, uint64_t address,
|
||||
struct drgn_symbol **ret);
|
||||
|
||||
/**
|
||||
* Get the symbol corresponding to the given name.
|
||||
*
|
||||
* @param[out] ret The returned symbol. It should be freed with @ref
|
||||
* drgn_symbol_destroy().
|
||||
* @return @c NULL on success, non-@c NULL on error.
|
||||
*/
|
||||
struct drgn_error *drgn_program_find_symbol_by_name(struct drgn_program *prog,
|
||||
const char *name,
|
||||
struct drgn_symbol **ret);
|
||||
|
||||
/** Element type and size. */
|
||||
struct drgn_element_info {
|
||||
/** Type of the element. */
|
||||
|
@ -961,6 +961,70 @@ drgn_program_find_symbol_by_address(struct drgn_program *prog, uint64_t address,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct find_symbol_by_name_arg {
|
||||
const char *name;
|
||||
struct drgn_symbol **ret;
|
||||
struct drgn_error *err;
|
||||
bool bad_symtabs;
|
||||
};
|
||||
|
||||
static int find_symbol_by_name_cb(Dwfl_Module *dwfl_module, void **userdatap,
|
||||
const char *module_name, Dwarf_Addr base,
|
||||
void *cb_arg)
|
||||
{
|
||||
struct find_symbol_by_name_arg *arg = cb_arg;
|
||||
int symtab_len, i;
|
||||
|
||||
symtab_len = dwfl_module_getsymtab(dwfl_module);
|
||||
i = dwfl_module_getsymtab_first_global(dwfl_module);
|
||||
if (symtab_len == -1 || i == -1) {
|
||||
arg->bad_symtabs = true;
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
for (; i < symtab_len; i++) {
|
||||
GElf_Sym elf_sym;
|
||||
GElf_Addr elf_addr;
|
||||
const char *name;
|
||||
|
||||
name = dwfl_module_getsym_info(dwfl_module, i, &elf_sym,
|
||||
&elf_addr, NULL, NULL, NULL);
|
||||
if (name && strcmp(arg->name, name) == 0) {
|
||||
struct drgn_symbol *sym;
|
||||
|
||||
sym = malloc(sizeof(*sym));
|
||||
if (sym) {
|
||||
sym->name = name;
|
||||
sym->address = elf_addr;
|
||||
sym->size = elf_sym.st_size;
|
||||
*arg->ret = sym;
|
||||
} else {
|
||||
arg->err = &drgn_enomem;
|
||||
}
|
||||
return DWARF_CB_ABORT;
|
||||
}
|
||||
}
|
||||
return DWARF_CB_OK;
|
||||
}
|
||||
|
||||
LIBDRGN_PUBLIC struct drgn_error *
|
||||
drgn_program_find_symbol_by_name(struct drgn_program *prog,
|
||||
const char *name, struct drgn_symbol **ret)
|
||||
{
|
||||
struct find_symbol_by_name_arg arg = {
|
||||
.name = name,
|
||||
.ret = ret,
|
||||
};
|
||||
|
||||
if (prog->_dicache &&
|
||||
dwfl_getmodules(prog->_dicache->dindex.dwfl, find_symbol_by_name_cb,
|
||||
&arg, 0))
|
||||
return arg.err;
|
||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
||||
"could not find symbol with name '%s'%s", name,
|
||||
arg.bad_symtabs ?
|
||||
" (could not get some symbol tables)" : "");
|
||||
}
|
||||
|
||||
LIBDRGN_PUBLIC struct drgn_error *
|
||||
drgn_program_element_info(struct drgn_program *prog, struct drgn_type *type,
|
||||
struct drgn_element_info *ret)
|
||||
|
@ -718,20 +718,27 @@ static StackTrace *Program_stack_trace(Program *self, PyObject *args,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *Program_symbol(Program *self, PyObject *args, PyObject *kwds)
|
||||
static PyObject *Program_symbol(Program *self, PyObject *arg)
|
||||
{
|
||||
static char *keywords[] = {"address", NULL};
|
||||
struct drgn_error *err;
|
||||
struct index_arg address = {};
|
||||
struct drgn_symbol *sym;
|
||||
PyObject *ret;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&", keywords,
|
||||
index_converter, &address))
|
||||
return NULL;
|
||||
if (PyUnicode_Check(arg)) {
|
||||
const char *name;
|
||||
|
||||
err = drgn_program_find_symbol_by_address(&self->prog, address.uvalue,
|
||||
&sym);
|
||||
name = PyUnicode_AsUTF8(arg);
|
||||
if (!name)
|
||||
return NULL;
|
||||
err = drgn_program_find_symbol_by_name(&self->prog, name, &sym);
|
||||
} else {
|
||||
struct index_arg address = {};
|
||||
|
||||
if (!index_converter(arg, &address))
|
||||
return NULL;
|
||||
err = drgn_program_find_symbol_by_address(&self->prog,
|
||||
address.uvalue, &sym);
|
||||
}
|
||||
if (err)
|
||||
return set_drgn_error(err);
|
||||
ret = Symbol_wrap(sym, self);
|
||||
@ -868,7 +875,7 @@ static PyMethodDef Program_methods[] = {
|
||||
METH_VARARGS | METH_KEYWORDS, drgn_Program_variable_DOC},
|
||||
{"stack_trace", (PyCFunction)Program_stack_trace,
|
||||
METH_VARARGS | METH_KEYWORDS, drgn_Program_stack_trace_DOC},
|
||||
{"symbol", (PyCFunction)Program_symbol, METH_VARARGS | METH_KEYWORDS,
|
||||
{"symbol", (PyCFunction)Program_symbol, METH_O,
|
||||
drgn_Program_symbol_DOC},
|
||||
{},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user