libdwarf
Loading...
Searching...
No Matches
Reading .debug_names data

Example access to .debug_names.

This is accessing DWARF5 .debug_names, a section intended to provide fast access to DIEs.

It bears a strong resemblance to what libdwarf does in dwarf_global.c.

Making this a single (long) function here, though that is not how libdwarf or dwarfdump are written.

That is just one possible sort of access. There are many, and we would love to hear suggestions for specific new API functions in the library.

There is a wealth of information in .debug_names and the following is all taken care of for you by dwarf_get_globals().

*/
#define MAXPAIRS 8 /* The standard defines 5.*/
int exampledebugnames(Dwarf_Debug dbg,
Dwarf_Unsigned *dnentrycount,
Dwarf_Error *error)
{
int res = DW_DLV_OK;
Dwarf_Unsigned offset = 0;
Dwarf_Unsigned new_offset = 0;
for ( ;res == DW_DLV_OK; offset = new_offset) {
Dwarf_Unsigned comp_unit_count = 0;
Dwarf_Unsigned local_type_unit_count = 0;
Dwarf_Unsigned foreign_type_unit_count = 0;
Dwarf_Unsigned bucket_count = 0;
Dwarf_Unsigned name_count = 0;
Dwarf_Unsigned abbrev_table_size = 0;
Dwarf_Unsigned entry_pool_size = 0;
Dwarf_Unsigned augmentation_string_size = 0;
char *aug_string = 0;
Dwarf_Unsigned section_size = 0;
Dwarf_Half table_version = 0;
Dwarf_Half offset_size = 0;
res = dwarf_dnames_header(dbg,offset,&dn,
&new_offset,error);
if (res == DW_DLV_ERROR) {
/* Something wrong. */
return res;
}
if (res == DW_DLV_NO_ENTRY) {
/* Done. Normal end of the .debug_names section. */
break;
}
*dnentrycount += 1;
res = dwarf_dnames_sizes(dn,&comp_unit_count,
&local_type_unit_count,
&foreign_type_unit_count,
&bucket_count,
&name_count,&abbrev_table_size,
&entry_pool_size,&augmentation_string_size,
&aug_string,
&section_size,&table_version,
&offset_size,
error);
if (res != DW_DLV_OK) {
/* Something wrong. */
return res;
}
/* name indexes start with one */
for (i = 1 ; i <= name_count; ++i) {
/* dnames_name data */
Dwarf_Unsigned bucketnum = 0;
Dwarf_Unsigned hashvalunsign = 0;
Dwarf_Unsigned offset_to_debug_str = 0;
char *ptrtostr = 0;
Dwarf_Unsigned offset_in_entrypool = 0;
Dwarf_Unsigned abbrev_code = 0;
Dwarf_Half abbrev_tag = 0;
Dwarf_Half nt_idxattr_array[MAXPAIRS];
Dwarf_Half nt_form_array[MAXPAIRS];
Dwarf_Unsigned attr_count = 0;
/* dnames_entrypool data */
Dwarf_Half tag = 0;
Dwarf_Bool single_cu_case = 0;
Dwarf_Unsigned single_cu_offset = 0;
Dwarf_Unsigned value_count = 0;
Dwarf_Unsigned index_of_abbrev = 0;
Dwarf_Unsigned offset_of_initial_value = 0;
Dwarf_Unsigned offset_next_entry_pool = 0;
Dwarf_Half idx_array[MAXPAIRS];
Dwarf_Half form_array[MAXPAIRS];
Dwarf_Unsigned offsets_array[MAXPAIRS];
Dwarf_Sig8 signatures_array[MAXPAIRS];
Dwarf_Unsigned cu_table_index = 0;
Dwarf_Unsigned tu_table_index = 0;
Dwarf_Unsigned local_die_offset = 0;
Dwarf_Unsigned parent_index = 0;
Dwarf_Sig8 parenthash;
(void)parent_index; /* avoids warning */
(void)local_die_offset; /* avoids warning */
(void)tu_table_index; /* avoids warning */
(void)cu_table_index; /* avoids warning */
memset(&parenthash,0,sizeof(parenthash));
/* This gets us the entry pool offset we need.
we provide idxattr and nt_form arrays (need
not be initialized) and on return
attr_count of those arrays are filled in.
if attr_count < array_size then array_size
is too small and things will not go well!
See the count of DW_IDX entries in dwarf.h
and make the arrays (say) 2 or more larger
ensuring against future new DW_IDX index
attributes..
ptrtostring is the name in the Names Table. */
res = dwarf_dnames_name(dn,i,
&bucketnum, &hashvalunsign,
&offset_to_debug_str,&ptrtostr,
&offset_in_entrypool, &abbrev_code,
&abbrev_tag,
MAXPAIRS,
nt_idxattr_array, nt_form_array,
&attr_count,error);
if (res == DW_DLV_NO_ENTRY) {
/* past end. Normal. */
break;
}
if (res == DW_DLV_ERROR) {
return res;
}
/* Check attr_count < MAXPAIRS ! */
/* Now check the value of TAG to ensure it
is something of interest as data or function.
Plausible choices: */
switch (abbrev_tag) {
case DW_TAG_subprogram:
case DW_TAG_variable:
case DW_TAG_label:
case DW_TAG_member:
case DW_TAG_common_block:
case DW_TAG_enumerator:
case DW_TAG_namelist:
case DW_TAG_module:
break;
default:
/* Not data or variable DIE involved.
Loop on the next i */
continue;
}
/* We need the number of values for this name
from this call. tag will match abbrev_tag. */
offset_in_entrypool,
&abbrev_code,&tag,&value_count,&index_of_abbrev,
&offset_of_initial_value,
error);
if (res != DW_DLV_OK) {
return res;
}
/* This gets us an actual array of values
as the library combines abbreviations,
IDX attributes and values. We use
the idx_array and form_array data
created above. */
index_of_abbrev,
offset_of_initial_value,
value_count,
idx_array,
form_array,
offsets_array,
signatures_array,
&single_cu_case,&single_cu_offset,
&offset_next_entry_pool,
error);
if (res != DW_DLV_OK) {
return res;
}
for (j = 0; j < value_count; ++j) {
Dwarf_Half idx = idx_array[j];
switch(idx) {
case DW_IDX_compile_unit:
cu_table_index = offsets_array[j];
break;
case DW_IDX_die_offset:
local_die_offset = offsets_array[j];
break;
/* The following are not meaninful when
reading globals. */
case DW_IDX_type_unit:
tu_table_index = offsets_array[j];
break;
case DW_IDX_parent:
parent_index = offsets_array[j];
break;
case DW_IDX_type_hash:
parenthash = signatures_array[j];
break;
default:
/* Not handled DW_IDX_GNU... */
break;
}
}
/* Now do something with the data aggregated */
}
}
return DW_DLV_OK;
}
struct Dwarf_Debug_s * Dwarf_Debug
Definition libdwarf.h:603
struct Dwarf_Dnames_Head_s * Dwarf_Dnames_Head
Definition libdwarf.h:709
struct Dwarf_Error_s * Dwarf_Error
Definition libdwarf.h:597
unsigned short Dwarf_Half
Definition libdwarf.h:203
unsigned long long Dwarf_Unsigned
Definition libdwarf.h:196
int Dwarf_Bool
Definition libdwarf.h:202
int dwarf_dnames_name(Dwarf_Dnames_Head dw_dn, Dwarf_Unsigned dw_name_index, Dwarf_Unsigned *dw_bucket_number, Dwarf_Unsigned *dw_hash_value, Dwarf_Unsigned *dw_offset_to_debug_str, char **dw_ptrtostr, Dwarf_Unsigned *dw_offset_in_entrypool, Dwarf_Unsigned *dw_abbrev_number, Dwarf_Half *dw_abbrev_tag, Dwarf_Unsigned dw_array_size, Dwarf_Half *dw_idxattr_array, Dwarf_Half *dw_form_array, Dwarf_Unsigned *dw_idxattr_count, Dwarf_Error *dw_error)
Retrieve a name table entry.
int dwarf_dnames_entrypool(Dwarf_Dnames_Head dw_dn, Dwarf_Unsigned dw_offset_in_entrypool, Dwarf_Unsigned *dw_abbrev_code, Dwarf_Half *dw_tag, Dwarf_Unsigned *dw_value_count, Dwarf_Unsigned *dw_index_of_abbrev, Dwarf_Unsigned *dw_offset_of_initial_value, Dwarf_Error *dw_error)
Return a the set of values from an entrypool entry.
int dwarf_dnames_header(Dwarf_Debug dw_dbg, Dwarf_Off dw_starting_offset, Dwarf_Dnames_Head *dw_dn, Dwarf_Off *dw_offset_of_next_table, Dwarf_Error *dw_error)
Open access to a .debug_names table.
int dwarf_dnames_entrypool_values(Dwarf_Dnames_Head dw_dn, Dwarf_Unsigned dw_index_of_abbrev, Dwarf_Unsigned dw_offset_in_entrypool_of_values, Dwarf_Unsigned dw_arrays_length, Dwarf_Half *dw_array_idx_number, Dwarf_Half *dw_array_form, Dwarf_Unsigned *dw_array_of_offsets, Dwarf_Sig8 *dw_array_of_signatures, Dwarf_Bool *dw_single_cu, Dwarf_Unsigned *dw_cu_offset, Dwarf_Unsigned *dw_offset_of_next_entrypool, Dwarf_Error *dw_error)
Return the value set defined by this entry.
int dwarf_dnames_sizes(Dwarf_Dnames_Head dw_dn, Dwarf_Unsigned *dw_comp_unit_count, Dwarf_Unsigned *dw_local_type_unit_count, Dwarf_Unsigned *dw_foreign_type_unit_count, Dwarf_Unsigned *dw_bucket_count, Dwarf_Unsigned *dw_name_count, Dwarf_Unsigned *dw_abbrev_table_size, Dwarf_Unsigned *dw_entry_pool_size, Dwarf_Unsigned *dw_augmentation_string_size, char **dw_augmentation_string, Dwarf_Unsigned *dw_section_size, Dwarf_Half *dw_table_version, Dwarf_Half *dw_offset_size, Dwarf_Error *dw_error)
Sizes and counts from the debug names table.
void dwarf_dealloc_dnames(Dwarf_Dnames_Head dw_dn)
Frees all the malloc data associated with dw_dn.
Definition libdwarf.h:313