mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
libdrgn: dwarf_index: return indexed DIE entry from drgn_dwarf_index_iterator_next()
For namespace support, we will want to access the struct drgn_dwarf_index_die for namespaces instead of the Dwarf_Die. Split drgn_dwarf_index_get_die() out of drgn_dwarf_index_iterator_next(). Signed-off-by: Omar Sandoval <osandov@osandov.com>
This commit is contained in:
parent
d512964c1e
commit
66ad5077c9
@ -252,26 +252,6 @@ static inline const char *section_end(Elf_Data *data)
|
||||
return (const char *)data->d_buf + data->d_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* An indexed DIE.
|
||||
*
|
||||
* DIEs with the same name but different tags or files are considered distinct.
|
||||
* We only compare the hash of the file name, not the string value, because a
|
||||
* 64-bit collision is unlikely enough, especially when also considering the
|
||||
* name and tag.
|
||||
*/
|
||||
struct drgn_dwarf_index_die {
|
||||
/*
|
||||
* The next DIE with the same name (as an index into
|
||||
* drgn_dwarf_index_shard::dies), or UINT32_MAX if this is the last DIE.
|
||||
*/
|
||||
uint32_t next;
|
||||
uint8_t tag;
|
||||
uint64_t file_name_hash;
|
||||
Dwfl_Module *module;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_die_map, string_hash, string_eq)
|
||||
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_die_vector)
|
||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_specification_map,
|
||||
@ -2619,23 +2599,18 @@ drgn_dwarf_index_iterator_matches_tag(struct drgn_dwarf_index_iterator *it,
|
||||
return false;
|
||||
}
|
||||
|
||||
struct drgn_error *
|
||||
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
||||
Dwarf_Die *die_ret, uint64_t *bias_ret)
|
||||
struct drgn_dwarf_index_die *
|
||||
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it)
|
||||
{
|
||||
struct drgn_dwarf_index *dindex = it->dindex;
|
||||
struct drgn_dwarf_index_die *die;
|
||||
Dwarf *dwarf;
|
||||
Dwarf_Addr bias;
|
||||
|
||||
if (it->any_name) {
|
||||
for (;;) {
|
||||
struct drgn_dwarf_index_shard *shard;
|
||||
|
||||
if (it->shard >= ARRAY_SIZE(dindex->shards))
|
||||
return &drgn_stop;
|
||||
return NULL;
|
||||
|
||||
shard = &dindex->shards[it->shard];
|
||||
struct drgn_dwarf_index_shard *shard =
|
||||
&dindex->shards[it->shard];
|
||||
die = &shard->dies.data[it->index];
|
||||
|
||||
if (++it->index >= shard->dies.size) {
|
||||
@ -2651,12 +2626,11 @@ drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
||||
}
|
||||
} else {
|
||||
for (;;) {
|
||||
struct drgn_dwarf_index_shard *shard;
|
||||
|
||||
if (it->index == UINT32_MAX)
|
||||
return &drgn_stop;
|
||||
return NULL;
|
||||
|
||||
shard = &dindex->shards[it->shard];
|
||||
struct drgn_dwarf_index_shard *shard =
|
||||
&dindex->shards[it->shard];
|
||||
die = &shard->dies.data[it->index];
|
||||
|
||||
it->index = die->next;
|
||||
@ -2665,8 +2639,15 @@ drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
||||
break;
|
||||
}
|
||||
}
|
||||
return die;
|
||||
}
|
||||
|
||||
dwarf = dwfl_module_getdwarf(die->module, &bias);
|
||||
struct drgn_error *drgn_dwarf_index_get_die(struct drgn_dwarf_index_die *die,
|
||||
Dwarf_Die *die_ret,
|
||||
uint64_t *bias_ret)
|
||||
{
|
||||
Dwarf_Addr bias;
|
||||
Dwarf *dwarf = dwfl_module_getdwarf(die->module, &bias);
|
||||
if (!dwarf)
|
||||
return drgn_error_libdwfl();
|
||||
if (!dwarf_offdie(dwarf, die->offset, die_ret))
|
||||
|
@ -62,7 +62,32 @@ extern const Dwfl_Callbacks drgn_dwfl_callbacks;
|
||||
extern const Dwfl_Callbacks drgn_linux_proc_dwfl_callbacks;
|
||||
extern const Dwfl_Callbacks drgn_userspace_core_dump_dwfl_callbacks;
|
||||
|
||||
struct drgn_dwarf_index_die;
|
||||
/*
|
||||
* An indexed DIE.
|
||||
*
|
||||
* DIEs with the same name but different tags or files are considered distinct.
|
||||
* We only compare the hash of the file name, not the string value, because a
|
||||
* 64-bit collision is unlikely enough, especially when also considering the
|
||||
* name and tag.
|
||||
*/
|
||||
struct drgn_dwarf_index_die {
|
||||
/*
|
||||
* The next DIE with the same name (as an index into
|
||||
* drgn_dwarf_index_shard::dies), or UINT32_MAX if this is the last DIE.
|
||||
*/
|
||||
uint32_t next;
|
||||
uint8_t tag;
|
||||
union {
|
||||
/* If tag != DW_TAG_namespace. */
|
||||
uint64_t file_name_hash;
|
||||
/* TODO: explain hash */
|
||||
/* If tag == DW_TAG_namespace. */
|
||||
struct drgn_dwarf_index_namespace *namespace;
|
||||
};
|
||||
Dwfl_Module *module;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
DEFINE_HASH_MAP_TYPE(drgn_dwarf_index_die_map, struct string, uint32_t)
|
||||
DEFINE_VECTOR_TYPE(drgn_dwarf_index_die_vector, struct drgn_dwarf_index_die)
|
||||
|
||||
@ -411,18 +436,24 @@ void drgn_dwarf_index_iterator_init(struct drgn_dwarf_index_iterator *it,
|
||||
* DW_TAG_enumerator DIEs.
|
||||
*
|
||||
* @param[in] it DWARF index iterator.
|
||||
* @return Next DIE, or @c NULL if there are no more matching DIEs.
|
||||
*/
|
||||
struct drgn_dwarf_index_die *
|
||||
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it);
|
||||
|
||||
/**
|
||||
* Get a @c Dwarf_Die from a @ref drgn_dwarf_index_die.
|
||||
*
|
||||
* @param[in] die Indexed DIE.
|
||||
* @param[out] die_ret Returned DIE.
|
||||
* @param[out] bias_ret Returned difference between addresses in the loaded
|
||||
* module and addresses in the debugging information. This may be @c NULL if it
|
||||
* is not needed.
|
||||
* @return @c NULL on success, non-@c NULL on error. In particular, when there
|
||||
* are no more matching DIEs, @p die_ret is not modified and an error with code
|
||||
* @ref DRGN_ERROR_STOP is returned; this @ref DRGN_ERROR_STOP error does not
|
||||
* have to be passed to @ref drgn_error_destroy().
|
||||
* @return @c NULL on success, non-@c NULL on error.
|
||||
*/
|
||||
struct drgn_error *
|
||||
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
||||
Dwarf_Die *die_ret, uint64_t *bias_ret);
|
||||
struct drgn_error *drgn_dwarf_index_get_die(struct drgn_dwarf_index_die *die,
|
||||
Dwarf_Die *die_ret,
|
||||
uint64_t *bias_ret);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -346,29 +346,30 @@ drgn_dwarf_info_cache_find_complete(struct drgn_dwarf_info_cache *dicache,
|
||||
struct drgn_type **ret)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
Dwarf_Die die;
|
||||
struct drgn_qualified_type qualified_type;
|
||||
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name,
|
||||
strlen(name), &tag, 1);
|
||||
/*
|
||||
* Find a matching DIE. Note that drgn_dwarf_index does not contain DIEs
|
||||
* with DW_AT_declaration, so this will always be a complete type.
|
||||
*/
|
||||
err = drgn_dwarf_index_iterator_next(&it, &die, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
struct drgn_dwarf_index_die *index_die =
|
||||
drgn_dwarf_index_iterator_next(&it);
|
||||
if (!index_die)
|
||||
return &drgn_stop;
|
||||
/*
|
||||
* Look for another matching DIE. If there is one, then we can't be sure
|
||||
* which type this is, so leave it incomplete rather than guessing.
|
||||
*/
|
||||
err = drgn_dwarf_index_iterator_next(&it, &die, NULL);
|
||||
if (!err)
|
||||
if (drgn_dwarf_index_iterator_next(&it))
|
||||
return &drgn_stop;
|
||||
else if (err->code != DRGN_ERROR_STOP)
|
||||
return err;
|
||||
|
||||
Dwarf_Die die;
|
||||
err = drgn_dwarf_index_get_die(index_die, &die, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
struct drgn_qualified_type qualified_type;
|
||||
err = drgn_type_from_dwarf(dicache, &die, &qualified_type);
|
||||
if (err)
|
||||
return err;
|
||||
@ -1237,10 +1238,8 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
||||
{
|
||||
struct drgn_error *err;
|
||||
struct drgn_dwarf_info_cache *dicache = arg;
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
Dwarf_Die die;
|
||||
uint64_t tag;
|
||||
|
||||
uint64_t tag;
|
||||
switch (kind) {
|
||||
case DRGN_TYPE_INT:
|
||||
case DRGN_TYPE_BOOL:
|
||||
@ -1266,9 +1265,15 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name, name_len,
|
||||
&tag, 1);
|
||||
while (!(err = drgn_dwarf_index_iterator_next(&it, &die, NULL))) {
|
||||
struct drgn_dwarf_index_die *index_die;
|
||||
while ((index_die = drgn_dwarf_index_iterator_next(&it))) {
|
||||
Dwarf_Die die;
|
||||
err = drgn_dwarf_index_get_die(index_die, &die, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
if (die_matches_filename(&die, filename)) {
|
||||
err = drgn_type_from_dwarf(dicache, &die, ret);
|
||||
if (err)
|
||||
@ -1281,8 +1286,6 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (err && err->code != DRGN_ERROR_STOP)
|
||||
return err;
|
||||
return &drgn_not_found;
|
||||
}
|
||||
|
||||
@ -1436,13 +1439,9 @@ drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename,
|
||||
{
|
||||
struct drgn_error *err;
|
||||
struct drgn_dwarf_info_cache *dicache = arg;
|
||||
uint64_t tags[3];
|
||||
size_t num_tags;
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
Dwarf_Die die;
|
||||
uint64_t bias;
|
||||
|
||||
num_tags = 0;
|
||||
uint64_t tags[3];
|
||||
size_t num_tags = 0;
|
||||
if (flags & DRGN_FIND_OBJECT_CONSTANT)
|
||||
tags[num_tags++] = DW_TAG_enumerator;
|
||||
if (flags & DRGN_FIND_OBJECT_FUNCTION)
|
||||
@ -1450,9 +1449,16 @@ drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename,
|
||||
if (flags & DRGN_FIND_OBJECT_VARIABLE)
|
||||
tags[num_tags++] = DW_TAG_variable;
|
||||
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name,
|
||||
strlen(name), tags, num_tags);
|
||||
while (!(err = drgn_dwarf_index_iterator_next(&it, &die, &bias))) {
|
||||
struct drgn_dwarf_index_die *index_die;
|
||||
while ((index_die = drgn_dwarf_index_iterator_next(&it))) {
|
||||
Dwarf_Die die;
|
||||
uint64_t bias;
|
||||
err = drgn_dwarf_index_get_die(index_die, &die, &bias);
|
||||
if (err)
|
||||
return err;
|
||||
if (!die_matches_filename(&die, filename))
|
||||
continue;
|
||||
switch (dwarf_tag(&die)) {
|
||||
@ -1470,8 +1476,6 @@ drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename,
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
if (err && err->code != DRGN_ERROR_STOP)
|
||||
return err;
|
||||
return &drgn_not_found;
|
||||
}
|
||||
|
||||
|
@ -631,29 +631,26 @@ static void drgn_program_set_language_from_main(struct drgn_program *prog,
|
||||
struct drgn_dwarf_index *dindex)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
|
||||
struct drgn_dwarf_index_iterator it;
|
||||
static const uint64_t tags[] = { DW_TAG_subprogram };
|
||||
|
||||
drgn_dwarf_index_iterator_init(&it, dindex, "main", strlen("main"),
|
||||
tags, ARRAY_SIZE(tags));
|
||||
for (;;) {
|
||||
struct drgn_dwarf_index_die *index_die;
|
||||
while ((index_die = drgn_dwarf_index_iterator_next(&it))) {
|
||||
Dwarf_Die die;
|
||||
const struct drgn_language *lang;
|
||||
|
||||
err = drgn_dwarf_index_iterator_next(&it, &die, NULL);
|
||||
if (err == &drgn_stop) {
|
||||
break;
|
||||
} else if (err) {
|
||||
drgn_error_destroy(err);
|
||||
continue;
|
||||
}
|
||||
|
||||
err = drgn_language_from_die(&die, &lang);
|
||||
err = drgn_dwarf_index_get_die(index_die, &die, NULL);
|
||||
if (err) {
|
||||
drgn_error_destroy(err);
|
||||
continue;
|
||||
}
|
||||
|
||||
const struct drgn_language *lang;
|
||||
err = drgn_language_from_die(&die, &lang);
|
||||
if (err) {
|
||||
drgn_error_destroy(err);
|
||||
continue;
|
||||
}
|
||||
if (lang) {
|
||||
prog->lang = lang;
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user