diff options
| author | Mark Wielaard <[email protected]> | 2018-05-29 23:49:21 +0200 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2018-05-31 17:03:19 +0200 |
| commit | 7d6fe0a39f6ae5c516ffd63558e12b24297bf982 (patch) | |
| tree | 30469e6da3f107797bb69a1d0a480eafc4ba50fd /libdw/libdw_findcu.c | |
| parent | b37feac1a8ceebb0748cb28d219aa8387d0885dd (diff) | |
libdw: Handle split Dwarf Dies in dwarf_die_addr_die.
dwarf_die_addr_die can be used to turn an Dwarf_Die addr back into a
full Dwarf_Die, just given the original Dwarf debug handle. This now
also works for Dwarf_Dies which originated from a split Dwarf. Whenever
a split Dwarf_CU is found the Dwarf it originated from is registered
with the Dwarf that the skeleton Dwarf_CU came from. All registered
split Dwarfs are then searched by dwarf_die_addr_die if the addr didn't
match the main Dwarf or the alt Dwarf.
One limitation in this implementation is that only DIEs that come from
the main .debug_info in the .dwo are supported. Theoretically there could
also be DIEs in an .debug_type or from other/multiple (comdat) sections.
New tests are added for dwarf-4, dwarf-5, split-dwarf-4, split-dwarf-5
and version 4 and 5 dwo files.
Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libdw/libdw_findcu.c')
| -rw-r--r-- | libdw/libdw_findcu.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c index 9d231999..2f5c6c42 100644 --- a/libdw/libdw_findcu.c +++ b/libdw/libdw_findcu.c @@ -61,6 +61,40 @@ findcu_cb (const void *arg1, const void *arg2) return 0; } +int +__libdw_finddbg_cb (const void *arg1, const void *arg2) +{ + Dwarf *dbg1 = (Dwarf *) arg1; + Dwarf *dbg2 = (Dwarf *) arg2; + + Elf_Data *dbg1_data = dbg1->sectiondata[IDX_debug_info]; + unsigned char *dbg1_start = dbg1_data->d_buf; + size_t dbg1_size = dbg1_data->d_size; + + Elf_Data *dbg2_data = dbg2->sectiondata[IDX_debug_info]; + unsigned char *dbg2_start = dbg2_data->d_buf; + size_t dbg2_size = dbg2_data->d_size; + + /* Find out which of the two arguments is the search value. It has + a size of 0. */ + if (dbg1_size == 0) + { + if (dbg1_start < dbg2_start) + return -1; + if (dbg1_start >= dbg2_start + dbg2_size) + return 1; + } + else + { + if (dbg2_start < dbg1_start) + return 1; + if (dbg2_start >= dbg1_start + dbg1_size) + return -1; + } + + return 0; +} + struct Dwarf_CU * internal_function __libdw_intern_next_unit (Dwarf *dbg, bool debug_types) @@ -247,3 +281,18 @@ __libdw_findcu_addr (Dwarf *dbg, void *addr) return NULL; } + +Dwarf * +internal_function +__libdw_find_split_dbg_addr (Dwarf *dbg, void *addr) +{ + /* XXX Assumes split DWARF only has CUs in main IDX_debug_info. */ + Elf_Data fake_data = { .d_buf = addr, .d_size = 0 }; + Dwarf fake = { .sectiondata[IDX_debug_info] = &fake_data }; + Dwarf **found = tfind (&fake, &dbg->split_tree, __libdw_finddbg_cb); + + if (found != NULL) + return *found; + + return NULL; +} |
