mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 09:43: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;
|
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_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_die_map, string_hash, string_eq)
|
||||||
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_die_vector)
|
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_die_vector)
|
||||||
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_specification_map,
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct drgn_error *
|
struct drgn_dwarf_index_die *
|
||||||
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it)
|
||||||
Dwarf_Die *die_ret, uint64_t *bias_ret)
|
|
||||||
{
|
{
|
||||||
struct drgn_dwarf_index *dindex = it->dindex;
|
struct drgn_dwarf_index *dindex = it->dindex;
|
||||||
struct drgn_dwarf_index_die *die;
|
struct drgn_dwarf_index_die *die;
|
||||||
Dwarf *dwarf;
|
|
||||||
Dwarf_Addr bias;
|
|
||||||
|
|
||||||
if (it->any_name) {
|
if (it->any_name) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct drgn_dwarf_index_shard *shard;
|
|
||||||
|
|
||||||
if (it->shard >= ARRAY_SIZE(dindex->shards))
|
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];
|
die = &shard->dies.data[it->index];
|
||||||
|
|
||||||
if (++it->index >= shard->dies.size) {
|
if (++it->index >= shard->dies.size) {
|
||||||
@ -2651,12 +2626,11 @@ drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct drgn_dwarf_index_shard *shard;
|
|
||||||
|
|
||||||
if (it->index == UINT32_MAX)
|
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];
|
die = &shard->dies.data[it->index];
|
||||||
|
|
||||||
it->index = die->next;
|
it->index = die->next;
|
||||||
@ -2665,8 +2639,15 @@ drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
|||||||
break;
|
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)
|
if (!dwarf)
|
||||||
return drgn_error_libdwfl();
|
return drgn_error_libdwfl();
|
||||||
if (!dwarf_offdie(dwarf, die->offset, die_ret))
|
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_linux_proc_dwfl_callbacks;
|
||||||
extern const Dwfl_Callbacks drgn_userspace_core_dump_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_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)
|
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.
|
* DW_TAG_enumerator DIEs.
|
||||||
*
|
*
|
||||||
* @param[in] it DWARF index iterator.
|
* @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] die_ret Returned DIE.
|
||||||
* @param[out] bias_ret Returned difference between addresses in the loaded
|
* @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
|
* module and addresses in the debugging information. This may be @c NULL if it
|
||||||
* is not needed.
|
* is not needed.
|
||||||
* @return @c NULL on success, non-@c NULL on error. In particular, when there
|
* @return @c NULL on success, non-@c NULL on error.
|
||||||
* 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().
|
|
||||||
*/
|
*/
|
||||||
struct drgn_error *
|
struct drgn_error *drgn_dwarf_index_get_die(struct drgn_dwarf_index_die *die,
|
||||||
drgn_dwarf_index_iterator_next(struct drgn_dwarf_index_iterator *it,
|
Dwarf_Die *die_ret,
|
||||||
Dwarf_Die *die_ret, uint64_t *bias_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_type **ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
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,
|
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name,
|
||||||
strlen(name), &tag, 1);
|
strlen(name), &tag, 1);
|
||||||
/*
|
/*
|
||||||
* Find a matching DIE. Note that drgn_dwarf_index does not contain DIEs
|
* 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.
|
* with DW_AT_declaration, so this will always be a complete type.
|
||||||
*/
|
*/
|
||||||
err = drgn_dwarf_index_iterator_next(&it, &die, NULL);
|
struct drgn_dwarf_index_die *index_die =
|
||||||
if (err)
|
drgn_dwarf_index_iterator_next(&it);
|
||||||
return err;
|
if (!index_die)
|
||||||
|
return &drgn_stop;
|
||||||
/*
|
/*
|
||||||
* Look for another matching DIE. If there is one, then we can't be sure
|
* 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.
|
* which type this is, so leave it incomplete rather than guessing.
|
||||||
*/
|
*/
|
||||||
err = drgn_dwarf_index_iterator_next(&it, &die, NULL);
|
if (drgn_dwarf_index_iterator_next(&it))
|
||||||
if (!err)
|
|
||||||
return &drgn_stop;
|
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);
|
err = drgn_type_from_dwarf(dicache, &die, &qualified_type);
|
||||||
if (err)
|
if (err)
|
||||||
return 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_error *err;
|
||||||
struct drgn_dwarf_info_cache *dicache = arg;
|
struct drgn_dwarf_info_cache *dicache = arg;
|
||||||
struct drgn_dwarf_index_iterator it;
|
|
||||||
Dwarf_Die die;
|
|
||||||
uint64_t tag;
|
|
||||||
|
|
||||||
|
uint64_t tag;
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
case DRGN_TYPE_INT:
|
case DRGN_TYPE_INT:
|
||||||
case DRGN_TYPE_BOOL:
|
case DRGN_TYPE_BOOL:
|
||||||
@ -1266,9 +1265,15 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct drgn_dwarf_index_iterator it;
|
||||||
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name, name_len,
|
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name, name_len,
|
||||||
&tag, 1);
|
&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)) {
|
if (die_matches_filename(&die, filename)) {
|
||||||
err = drgn_type_from_dwarf(dicache, &die, ret);
|
err = drgn_type_from_dwarf(dicache, &die, ret);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1281,8 +1286,6 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err && err->code != DRGN_ERROR_STOP)
|
|
||||||
return err;
|
|
||||||
return &drgn_not_found;
|
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_error *err;
|
||||||
struct drgn_dwarf_info_cache *dicache = arg;
|
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)
|
if (flags & DRGN_FIND_OBJECT_CONSTANT)
|
||||||
tags[num_tags++] = DW_TAG_enumerator;
|
tags[num_tags++] = DW_TAG_enumerator;
|
||||||
if (flags & DRGN_FIND_OBJECT_FUNCTION)
|
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)
|
if (flags & DRGN_FIND_OBJECT_VARIABLE)
|
||||||
tags[num_tags++] = DW_TAG_variable;
|
tags[num_tags++] = DW_TAG_variable;
|
||||||
|
|
||||||
|
struct drgn_dwarf_index_iterator it;
|
||||||
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name,
|
drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name,
|
||||||
strlen(name), tags, num_tags);
|
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))
|
if (!die_matches_filename(&die, filename))
|
||||||
continue;
|
continue;
|
||||||
switch (dwarf_tag(&die)) {
|
switch (dwarf_tag(&die)) {
|
||||||
@ -1470,8 +1476,6 @@ drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename,
|
|||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (err && err->code != DRGN_ERROR_STOP)
|
|
||||||
return err;
|
|
||||||
return &drgn_not_found;
|
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_dwarf_index *dindex)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
|
|
||||||
struct drgn_dwarf_index_iterator it;
|
struct drgn_dwarf_index_iterator it;
|
||||||
static const uint64_t tags[] = { DW_TAG_subprogram };
|
static const uint64_t tags[] = { DW_TAG_subprogram };
|
||||||
|
|
||||||
drgn_dwarf_index_iterator_init(&it, dindex, "main", strlen("main"),
|
drgn_dwarf_index_iterator_init(&it, dindex, "main", strlen("main"),
|
||||||
tags, ARRAY_SIZE(tags));
|
tags, ARRAY_SIZE(tags));
|
||||||
for (;;) {
|
struct drgn_dwarf_index_die *index_die;
|
||||||
|
while ((index_die = drgn_dwarf_index_iterator_next(&it))) {
|
||||||
Dwarf_Die die;
|
Dwarf_Die die;
|
||||||
const struct drgn_language *lang;
|
err = drgn_dwarf_index_get_die(index_die, &die, NULL);
|
||||||
|
|
||||||
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);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
drgn_error_destroy(err);
|
drgn_error_destroy(err);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct drgn_language *lang;
|
||||||
|
err = drgn_language_from_die(&die, &lang);
|
||||||
|
if (err) {
|
||||||
|
drgn_error_destroy(err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (lang) {
|
if (lang) {
|
||||||
prog->lang = lang;
|
prog->lang = lang;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user