libdwarf
Loading...
Searching...
No Matches
Example walking CUs(d)

Example accessing all CUs looking for specific items(d).

Example accessing all CUs looking for specific items(d).

Loops through as many CUs as needed, stops and returns once a CU provides the desired data.

Assumes certain functions you write to remember the aspect of CUs that matter to you so once found in a cu my_needed_data_exists() or some other function of yours can identify the correct record. (Possibly a DIE global offset. Remember to note if each DIE has is_info TRUE or FALSE so libdwarf can find the DIE properly.)

Depending on your goals in examining the DIE tree it may be helpful to maintain a DIE stack of active DIEs, pushing and popping as you make your way throught the DIE levels.

We assume that on a serious error we will give up (for simplicity here).

We assume the caller to examplecuhdrd() will know what to retrieve (when we return DW_DLV_OK from examplecuhdrd() and that myrecords points to a record with all the data needed by my_needed_data_exists() and recorded by myrecord_data_for_die().

*/
struct myrecords_struct *myrecords;
void myrecord_data_for_die(struct myrecords_struct *myrecords,
int my_needed_data_exists(struct myrecords_struct *myrecords);
/* Loop on DIE tree. */
static void
record_die_and_siblingsd(Dwarf_Debug dbg, Dwarf_Die in_die,
int is_info, int in_level,
struct myrecords_struct *myrec,
Dwarf_Error *error)
{
int res = DW_DLV_OK;
Dwarf_Die cur_die=in_die;
Dwarf_Die child = 0;
myrecord_data_for_die(myrec,in_die);
/* Loop on a list of siblings */
for (;;) {
Dwarf_Die sib_die = 0;
/* Depending on your goals, the in_level,
and the DW_TAG of cur_die, you may want
to skip the dwarf_child call. */
res = dwarf_child(cur_die,&child,error);
if (res == DW_DLV_ERROR) {
printf("Error in dwarf_child , level %d \n",in_level);
exit(EXIT_FAILURE);
}
if (res == DW_DLV_OK) {
record_die_and_siblingsd(dbg,child,is_info,
in_level+1,myrec,error);
/* No longer need 'child' die. */
dwarf_dealloc(dbg,child,DW_DLA_DIE);
child = 0;
}
/* res == DW_DLV_NO_ENTRY or DW_DLV_OK */
res = dwarf_siblingof_b(dbg,cur_die,is_info,&sib_die,error);
if (res == DW_DLV_ERROR) {
exit(EXIT_FAILURE);
}
if (res == DW_DLV_NO_ENTRY) {
/* Done at this level. */
break;
}
/* res == DW_DLV_OK */
if (cur_die != in_die) {
dwarf_dealloc(dbg,cur_die,DW_DLA_DIE);
cur_die = 0;
}
cur_die = sib_die;
myrecord_data_for_die(myrec,sib_die);
}
return;
}
/* Assuming records properly initialized for your use. */
int examplecuhdrd(Dwarf_Debug dbg,
struct myrecords_struct *myrec,
Dwarf_Error *error)
{
Dwarf_Unsigned abbrev_offset = 0;
Dwarf_Half address_size = 0;
Dwarf_Half version_stamp = 0;
Dwarf_Half offset_size = 0;
Dwarf_Half extension_size = 0;
Dwarf_Sig8 signature;
Dwarf_Unsigned typeoffset = 0;
Dwarf_Unsigned next_cu_header = 0;
Dwarf_Half header_cu_type = 0;
Dwarf_Bool is_info = TRUE;
int res = 0;
while(!my_needed_data_exists(myrec)) {
Dwarf_Die no_die = 0;
Dwarf_Die cu_die = 0;
Dwarf_Unsigned cu_header_length = 0;
memset(&signature,0, sizeof(signature));
res = dwarf_next_cu_header_d(dbg,is_info,&cu_header_length,
&version_stamp, &abbrev_offset,
&address_size, &offset_size,
&extension_size,&signature,
&typeoffset, &next_cu_header,
&header_cu_type,error);
if (res == DW_DLV_ERROR) {
return res;
}
if (res == DW_DLV_NO_ENTRY) {
if (is_info == TRUE) {
/* Done with .debug_info, now check for
.debug_types. */
is_info = FALSE;
continue;
}
/* No more CUs to read! Never found
what we were looking for in either
.debug_info or .debug_types. */
return res;
}
/* The CU will have a single sibling, a cu_die.
It is essential to call this right after
a call to dwarf_next_cu_header_d() because
there is no explicit connection provided to
dwarf_siblingof_b(), which returns a DIE
from whatever CU was last accessed by
dwarf_next_cu_header_d()!
The lack of explicit connection was a
design mistake in the API (made in 1992). */
res = dwarf_siblingof_b(dbg,no_die,is_info,
&cu_die,error);
if (res == DW_DLV_ERROR) {
return res;
}
if (res == DW_DLV_NO_ENTRY) {
/* Impossible */
exit(EXIT_FAILURE);
}
record_die_and_siblingsd(dbg,cu_die,is_info,
0, myrec,error);
}
/* Found what we looked for */
return DW_DLV_OK;
}
struct Dwarf_Debug_s * Dwarf_Debug
Definition libdwarf.h:603
struct Dwarf_Die_s * Dwarf_Die
Definition libdwarf.h:613
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
DW_API void dwarf_dealloc_die(Dwarf_Die dw_die)
Deallocate (free) a DIE.
DW_API int dwarf_next_cu_header_d(Dwarf_Debug dw_dbg, Dwarf_Bool dw_is_info, Dwarf_Unsigned *dw_cu_header_length, Dwarf_Half *dw_version_stamp, Dwarf_Off *dw_abbrev_offset, Dwarf_Half *dw_address_size, Dwarf_Half *dw_length_size, Dwarf_Half *dw_extension_size, Dwarf_Sig8 *dw_type_signature, Dwarf_Unsigned *dw_typeoffset, Dwarf_Unsigned *dw_next_cu_header_offset, Dwarf_Half *dw_header_cu_type, Dwarf_Error *dw_error)
Return information on the next CU header(d)
DW_API int dwarf_child(Dwarf_Die dw_die, Dwarf_Die *dw_return_childdie, Dwarf_Error *dw_error)
Return the child DIE, if any. The child may be the first of a list of sibling DIEs.
DW_API int dwarf_siblingof_b(Dwarf_Debug dw_dbg, Dwarf_Die dw_die, Dwarf_Bool dw_is_info, Dwarf_Die *dw_return_siblingdie, Dwarf_Error *dw_error)
Return the first DIE or the next sibling DIE.
DW_API void dwarf_dealloc(Dwarf_Debug dw_dbg, void *dw_space, Dwarf_Unsigned dw_type)
The generic dealloc (free) function. It requires you know the correct DW_DLA value to pass in,...
Definition libdwarf.h:313