static void handle_die( struct dwarf_subprogram_t **subprograms, Dwarf_Debug dbg, Dwarf_Die cu_die, Dwarf_Die the_die, Dwarf_Unsigned language) { int rc; Dwarf_Error err; Dwarf_Die current_die = the_die; Dwarf_Die child_die = NULL; Dwarf_Die next_die; do { *subprograms = read_cu_entry(*subprograms, dbg, cu_die, current_die, language); /* Recursive call handle_die with child, to continue searching within child dies */ rc = dwarf_child(current_die, &child_die, &err); DWARF_ASSERT(rc, err); if (rc == DW_DLV_OK && child_die) handle_die(subprograms, dbg, cu_die, child_die, language); rc = dwarf_siblingof(dbg, current_die, &next_die, &err); DWARF_ASSERT(rc, err); dwarf_dealloc(dbg, current_die, DW_DLA_DIE); current_die = next_die; } while (rc != DW_DLV_NO_ENTRY); }
BT_HIDDEN int bt_dwarf_die_child(struct bt_dwarf_die *die) { int ret; Dwarf_Die *child_die = NULL; if (!die) { ret = -1; goto error; } child_die = g_new0(Dwarf_Die, 1); if (!child_die) { ret = -1; goto error; } ret = dwarf_child(die->dwarf_die, child_die); if (ret) { /* ret is -1 on error, 1 if no child DIE. */ goto error; } g_free(die->dwarf_die); die->dwarf_die = child_die; die->depth++; return 0; error: g_free(child_die); return ret; }
struct variable* child_variables(Dwarf_Die *parent, Dwarf_Files *files, struct expr_context *ctx, bool params) { int ret; Dwarf_Die die; struct variable *var, *head = NULL, *tail = NULL; int desired_tag = params ? DW_TAG_formal_parameter : DW_TAG_variable; ret = dwarf_child(parent, &die); if (ret != 0) return NULL; do { if (dwarf_tag(&die) == desired_tag) { var = analyze_variable(&die, files, ctx); if (!var) continue; list_append(head, tail, var); } } while (dwarf_siblingof(&die, &die) == 0); return head; }
/** * die_find_child - Generic DIE search function in DIE tree * @rt_die: a root DIE * @callback: a callback function * @data: a user data passed to the callback function * @die_mem: a buffer for result DIE * * Trace DIE tree from @rt_die and call @callback for each child DIE. * If @callback returns DIE_FIND_CB_END, this stores the DIE into * @die_mem and returns it. If @callback returns DIE_FIND_CB_CONTINUE, * this continues to trace the tree. Optionally, @callback can return * DIE_FIND_CB_CHILD and DIE_FIND_CB_SIBLING, those means trace only * the children and trace only the siblings respectively. * Returns NULL if @callback can't find any appropriate DIE. */ Dwarf_Die *die_find_child(Dwarf_Die *rt_die, int (*callback)(Dwarf_Die *, void *), void *data, Dwarf_Die *die_mem) { Dwarf_Die child_die; int ret; ret = dwarf_child(rt_die, die_mem); if (ret != 0) return NULL; do { ret = callback(die_mem, data); if (ret == DIE_FIND_CB_END) return die_mem; if ((ret & DIE_FIND_CB_CHILD) && die_find_child(die_mem, callback, data, &child_die)) { memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); return die_mem; } } while ((ret & DIE_FIND_CB_SIBLING) && dwarf_siblingof(die_mem, die_mem) == 0); return NULL; }
/* Recursively follow the DIE tree */ static int process_die_and_children(Dwarf_Debug dbg, Dwarf_Die in_die) { Dwarf_Die cur_die = in_die; Dwarf_Die child; Dwarf_Die sib_die; int is_function; int ret; ret = process_one_DIE(dbg, in_die, &is_function); if (ret != 0) return 1; while (1) { if (!is_function) /* Assume that there is no nested function, so we ignore the children of a function */ { ret = dwarf_child(cur_die, &child, NULL); if (ret == DW_DLV_ERROR) { fprintf(stderr, "SET dwarf: Error in dwarf_child()\n"); return 1; } /* Recursive call */ if (ret == DW_DLV_OK) { ret = process_die_and_children(dbg, child); dwarf_dealloc(dbg, child, DW_DLA_DIE); if (ret != 0) return 1; } } /* Current DIE has no children */ ret = dwarf_siblingof(dbg, cur_die, &sib_die, NULL); if (ret == DW_DLV_ERROR) { fprintf(stderr, "SET dwarf: Error in dwarf_siblingof()\n"); return 1; } if (cur_die != in_die) dwarf_dealloc(dbg, cur_die, DW_DLA_DIE); if (ret == DW_DLV_NO_ENTRY) { /* Done at this level */ break; } /* ret == DW_DLV_OK */ cur_die = sib_die; ret = process_one_DIE(dbg, cur_die, &is_function); if (ret != 0) return 1; } return 0; }
static struct dwarf_subprogram_t *read_from_cus(Dwarf_Debug dbg) { Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header; Dwarf_Half version_stamp, address_size; Dwarf_Error err; Dwarf_Die no_die = 0, cu_die, child_die, next_die; int ret = DW_DLV_OK; int rc; struct dwarf_subprogram_t *subprograms = NULL; while (ret == DW_DLV_OK) { ret = dwarf_next_cu_header( dbg, &cu_header_length, &version_stamp, &abbrev_offset, &address_size, &next_cu_header, &err); DWARF_ASSERT(ret, err); if (ret == DW_DLV_NO_ENTRY) continue; /* TODO: If the CU can provide an address range then we can skip over * all the entire die if none of our addresses match */ /* Expect the CU to have a single sibling - a DIE */ ret = dwarf_siblingof(dbg, no_die, &cu_die, &err); if (ret == DW_DLV_ERROR) { continue; } DWARF_ASSERT(ret, err); /* Expect the CU DIE to have children */ ret = dwarf_child(cu_die, &child_die, &err); DWARF_ASSERT(ret, err); next_die = child_die; /* Now go over all children DIEs */ do { subprograms = read_cu_entry(subprograms, dbg, cu_die, child_die); rc = dwarf_siblingof(dbg, child_die, &next_die, &err); DWARF_ASSERT(rc, err); dwarf_dealloc(dbg, child_die, DW_DLA_DIE); child_die = next_die; } while (rc != DW_DLV_NO_ENTRY); dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); } return subprograms; }
static void DC_show_info_for_containing_pc_ranges(Dwarf_Die die, int enclosing, unsigned long iaddr){ /*This function visits the children of a die in sequence, *applying the action() function to each*/ Dwarf_Attribute highattr; Dwarf_Attribute lowattr; Dwarf_Addr loval,hival; Dwarf_Bool has; Dwarf_Error error; Dwarf_Half tag; loval = hival = 0x0; int enc = 0; dwarf_tag(die,&tag,&error); if( tag == DW_TAG_variable || tag == DW_TAG_formal_parameter ){ if(enclosing){ char *name; dwarf_diename(die,&name,&error); fprintf(stderr,"%s, ",name); //show_all_attrs(die,0,NULL); } } if( tag == DW_TAG_lexical_block || tag == DW_TAG_subprogram ){ if( dwarf_lowpc(die,&loval,&error) == DW_DLV_OK && dwarf_highpc(die,&hival,&error) == DW_DLV_OK && iaddr >=loval && iaddr <= hival ){ enc = 1; fprintf(stderr,"\n=================================\n"); show_all_attrs(die,0,NULL); fprintf(stderr,"=================================\n"); } } Dwarf_Die kid; if( dwarf_child(die,&kid,&error) == DW_DLV_NO_ENTRY ){ return; } DC_show_info_for_containing_pc_ranges(kid, enc, iaddr); //visit_die(kid,level+1,action,adata); int chret; while( (chret = dwarf_siblingof(d,kid,&kid,&error)) != DW_DLV_NO_ENTRY && chret != DW_DLV_ERROR){ DC_show_info_for_containing_pc_ranges(kid, enc, iaddr); //visit_die(kid,level+1,action,adata); } return; }
static struct dwarf_subprogram_t *read_from_cus(Dwarf_Debug dbg) { Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header; Dwarf_Half version_stamp, address_size; Dwarf_Error err; Dwarf_Die no_die = 0, cu_die, child_die; int ret = DW_DLV_OK; struct dwarf_subprogram_t *subprograms = NULL; Dwarf_Unsigned language = 0; Dwarf_Attribute language_attr = 0; while (ret == DW_DLV_OK) { ret = dwarf_next_cu_header( dbg, &cu_header_length, &version_stamp, &abbrev_offset, &address_size, &next_cu_header, &err); DWARF_ASSERT(ret, err); if (ret == DW_DLV_NO_ENTRY) continue; /* TODO: If the CU can provide an address range then we can skip over * all the entire die if none of our addresses match */ /* Expect the CU to have a single sibling - a DIE */ ret = dwarf_siblingof(dbg, no_die, &cu_die, &err); if (ret == DW_DLV_ERROR) { continue; } DWARF_ASSERT(ret, err); /* Get compilation unit language attribute */ ret = dwarf_attr(cu_die, DW_AT_language, &language_attr, &err); DWARF_ASSERT(ret, err); if (ret != DW_DLV_NO_ENTRY) { /* Get language attribute data */ ret = dwarf_formudata(language_attr, &language, &err); DWARF_ASSERT(ret, err); dwarf_dealloc(dbg, language_attr, DW_DLA_ATTR); } /* Expect the CU DIE to have children */ ret = dwarf_child(cu_die, &child_die, &err); DWARF_ASSERT(ret, err); handle_die(&subprograms, dbg, cu_die, child_die, language); dwarf_dealloc(dbg, cu_die, DW_DLA_DIE); } return subprograms; }
static void DC_get_info_for_scoped_variable(Dwarf_Die die, int enclosing, unsigned long iaddr, const char *varname, Dwarf_Die *retDie){ /*This function visits the children of a die in sequence, *applying the action() function to each*/ Dwarf_Attribute highattr; Dwarf_Attribute lowattr; Dwarf_Addr loval,hival; Dwarf_Bool has; Dwarf_Error error; Dwarf_Half tag; loval = hival = 0x0; int enc = 0; dwarf_tag(die,&tag,&error); if( tag == DW_TAG_variable || tag == DW_TAG_formal_parameter ){ if(enclosing){ char *name; dwarf_diename(die,&name,&error); if(!strncmp(name,varname,strlen(name))){ *retDie = die; return; } } } if( tag == DW_TAG_lexical_block || tag == DW_TAG_subprogram ){ if( dwarf_lowpc(die,&loval,&error) == DW_DLV_OK && dwarf_highpc(die,&hival,&error) == DW_DLV_OK && iaddr >=loval && iaddr <= hival ){ enc = 1; } } Dwarf_Die kid; if( dwarf_child(die,&kid,&error) == DW_DLV_NO_ENTRY ){ return; } DC_get_info_for_scoped_variable(kid, enc, iaddr,varname,retDie); int chret; while( (chret = dwarf_siblingof(d,kid,&kid,&error)) != DW_DLV_NO_ENTRY && chret != DW_DLV_ERROR){ DC_get_info_for_scoped_variable(kid, enc, iaddr,varname,retDie); } return; }
Dwarf_Die DieHolder::get_child(void) { Dwarf_Die child_die = NULL; Dwarf_Error err = NULL; // there may be no child CHECK_DWERR2(dwarf_child(m_die, &child_die, &err) == DW_DLV_ERROR, err, "error when asking for a DIE child"); return child_die; }
static void MC_dwarf_handle_children(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Frame* frame, const char *ns) { // For each child DIE: Dwarf_Die child; int res; for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) MC_dwarf_handle_die(info, &child, unit, frame, ns); }
static void print_vars (unsigned int indent, Dwarf_Die *die) { Dwarf_Die child; if (dwarf_child (die, &child) == 0) do switch (dwarf_tag (&child)) { case DW_TAG_variable: case DW_TAG_formal_parameter: printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "", dwarf_diename (&child), (uint64_t) dwarf_dieoffset (&child)); break; default: break; } while (dwarf_siblingof (&child, &child) == 0); Dwarf_Attribute attr_mem; Dwarf_Die origin; if (dwarf_hasattr (die, DW_AT_abstract_origin) && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem), &origin) != NULL && dwarf_child (&origin, &child) == 0) do switch (dwarf_tag (&child)) { case DW_TAG_variable: case DW_TAG_formal_parameter: printf ("%*s%s (abstract)\n", indent, "", dwarf_diename (&child)); break; default: break; } while (dwarf_siblingof (&child, &child) == 0); }
static Dwarf_Die die_child(dwarf_t *dw, Dwarf_Die die) { Dwarf_Die child; int rc; if ((rc = dwarf_child(die, &child, &dw->dw_err)) == DW_DLV_OK) return (child); else if (rc == DW_DLV_NO_ENTRY) return (NULL); terminate("die %llu: failed to find type child: %s\n", die_off(dw, die), dwarf_errmsg(dw->dw_err)); /*NOTREACHED*/ return (NULL); }
static void get_die_and_siblings(Dwarf_Debug dbg, Dwarf_Die in_die,int in_level, struct srcfilesdata *sf) { int res = DW_DLV_ERROR; Dwarf_Die cur_die=in_die; Dwarf_Die child = 0; Dwarf_Error error; print_die_data(dbg,in_die,in_level,sf); for(;;) { /*edit by liupo*/ //printf("\n-----------SIB-%d----------------\n", in_level); /*end edit*/ Dwarf_Die sib_die = 0; res = dwarf_child(cur_die,&child,&error); if(res == DW_DLV_ERROR) { printf("Error in dwarf_child , level %d \n",in_level); exit(1); } if(res == DW_DLV_OK) { get_die_and_siblings(dbg,child,in_level+1,sf); } /* res == DW_DLV_NO_ENTRY */ res = dwarf_siblingof(dbg,cur_die,&sib_die,&error); if(res == DW_DLV_ERROR) { printf("Error in dwarf_siblingof , level %d \n",in_level); exit(1); } 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 = sib_die; print_die_data(dbg,cur_die,in_level,sf); } return; }
void print_die_rec(Dwarf_Die *die, int lvl) { int ret; Dwarf_Die chdie, sdie; if (!die) return; print_dbg_info(die, lvl); ret = dwarf_child(die, &chdie); if (!ret) print_die_rec(&chdie, lvl+1); ret = dwarf_siblingof(die, &sdie); if (!ret) print_die_rec(&sdie, lvl); }
/** \brief Finds the number of elements in a array type (DW_TAG_array_type) * * The compilation unit might be needed because the default lower * bound depends on the language of the compilation unit. * * \param die the DIE of the DW_TAG_array_type * \param unit the DIE of the compilation unit * \return number of elements in this array type * */ static uint64_t MC_dwarf_array_element_count(Dwarf_Die * die, Dwarf_Die * unit) { xbt_assert(dwarf_tag(die) == DW_TAG_array_type, "MC_dwarf_array_element_count called with DIE of type %s", simgrid::dwarf::tagname(die)); int result = 1; Dwarf_Die child; int res; for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) { int child_tag = dwarf_tag(&child); if (child_tag == DW_TAG_subrange_type || child_tag == DW_TAG_enumeration_type) result *= MC_dwarf_subrange_element_count(&child, unit); } return result; }
BT_HIDDEN int bt_dwarf_die_next(struct bt_dwarf_die *die) { int ret; Dwarf_Die *next_die = NULL; if (!die) { ret = -1; goto error; } next_die = g_new0(Dwarf_Die, 1); if (!next_die) { ret = -1; goto error; } if (die->depth == 0) { ret = dwarf_child(die->dwarf_die, next_die); if (ret) { /* ret is -1 on error, 1 if no child DIE. */ goto error; } die->depth = 1; } else { ret = dwarf_siblingof(die->dwarf_die, next_die); if (ret) { /* ret is -1 on error, 1 if we reached end of * DIEs at this depth. */ goto error; } } g_free(die->dwarf_die); die->dwarf_die = next_die; return 0; error: g_free(next_die); return ret; }
error_t find_var_die(mygdb_info_t* gdb_info, Dwarf_Die func_die, char* var_name){ Dwarf_Half tag; Dwarf_Error err; Dwarf_Die child_die; /* Find compilation unit header */ if (dwarf_tag(func_die, &tag, &err) != DW_DLV_OK) return E_FATAL; /* Can't find var if this isn't a func_die */ if (tag != DW_TAG_subprogram) return E_FATAL; // /* Expect the CU DIE to have children */ if (dwarf_child(func_die, &child_die, &err) == DW_DLV_ERROR) return E_FATAL; /* Now go over all children DIEs */ while (1) { int rc; bool found = false; if( is_right_var(child_die, var_name, &found) == E_FATAL) return E_FATAL; if(found){ return print_local_var(gdb_info, child_die, var_name); } rc = dwarf_siblingof(gdb_info->dbg, child_die, &child_die, &err); if (rc == DW_DLV_ERROR) return E_FATAL; else if (rc == DW_DLV_NO_ENTRY){ printf("Couldn't find var named: %s\n", var_name); return E_NON_FATAL; //var not found! } } return E_FATAL; //if reached here, didnt find var and didnt hit end of dies list } //must have broken something
static void tp_dwarf_child_first(void) { Dwarf_Debug dbg; Dwarf_Error de; Dwarf_Die die, die0; Dwarf_Unsigned cu_next_offset; int r, fd, result, die_cnt; result = TET_UNRESOLVED; TS_DWARF_INIT(dbg, fd, de); tet_infoline("count the number of children of compilation unit DIE"); die_cnt = 0; TS_DWARF_CU_FOREACH(dbg, cu_next_offset, de) { r = dwarf_siblingof(dbg, NULL, &die, &de); if (r == DW_DLV_OK) { r = dwarf_child(die, &die0, &de); while (r == DW_DLV_OK) { if (die0 == NULL) { tet_infoline("dwarf_child or " "dwarf_siblingof return " "DW_DLV_OK while argument die0 " "is not filled in"); result = TET_FAIL; goto done; } die_cnt++; die = die0; r = dwarf_siblingof(dbg, die, &die0, &de); } } if (r == DW_DLV_ERROR) { tet_printf("dwarf_siblingof or dwarf_child failed:" " %s\n", dwarf_errmsg(de)); result = TET_FAIL; goto done; } }
void DwarfDie::scanChildren() const { m_childrenScanned = true; Dwarf_Die childDie; auto res = dwarf_child(m_die, &childDie, nullptr); if (res != DW_DLV_OK) return; const auto handle = dwarfHandle(); forever { m_children.push_back(new DwarfDie(childDie, const_cast<DwarfDie*>(this))); Dwarf_Die siblingDie; res = dwarf_siblingof(handle, childDie, &siblingDie, nullptr); if (res != DW_DLV_OK) return; childDie = siblingDie; } }
/* List all the functions from the file represented by the given descriptor. */ void list_funcs_in_file(Dwarf_Debug dbg, FILE *fp) { Dwarf_Unsigned cu_header_length, abbrev_offset, next_cu_header; Dwarf_Half version_stamp, address_size; Dwarf_Error err; Dwarf_Die no_die = 0, cu_die, child_die; /* Find compilation unit header */ if (dwarf_next_cu_header( dbg, &cu_header_length, &version_stamp, &abbrev_offset, &address_size, &next_cu_header, &err) == DW_DLV_ERROR) die("Error reading DWARF cu header\n"); /* Expect the CU to have a single sibling - a DIE */ if (dwarf_siblingof(dbg, no_die, &cu_die, &err) == DW_DLV_ERROR) die("Error getting sibling of CU\n"); /* Expect the CU DIE to have children */ if (dwarf_child(cu_die, &child_die, &err) == DW_DLV_ERROR) die("Error getting child of CU DIE\n"); /* Now go over all children DIEs */ while (1) { int rc; list_func_in_die(dbg, child_die, fp); rc = dwarf_siblingof(dbg, child_die, &child_die, &err); if (rc == DW_DLV_ERROR) die("Error getting sibling of DIE\n"); else if (rc == DW_DLV_NO_ENTRY) break; /* done */ } }
error_t find_func_die(mygdb_info_t* gdb_info, Dwarf_Die* ret_die){ Dwarf_Error err; //Dwarf_Die child_die; /* Find compilation unit header */ /* Expect the CU DIE to have children */ if (dwarf_child(gdb_info->cu_die, ret_die, &err) == DW_DLV_ERROR) return E_FATAL; struct user_regs_struct regs; if( ptrace(PTRACE_GETREGS, gdb_info->child_pid, NULL, ®s) < 0) return E_FATAL; /* Now go over all children DIEs */ while (1) { int rc; bool found = false; if( ip_in_func(*ret_die, regs.rip - 1, &found) == E_FATAL) return E_FATAL; if(found){ return E_NONE; } rc = dwarf_siblingof(gdb_info->dbg, *ret_die, ret_die, &err); if (rc == DW_DLV_ERROR) return E_FATAL; else if (rc == DW_DLV_NO_ENTRY){ return E_FATAL; //Func not found! } } return E_FATAL; // didnt find func }
Dwarf_Die dwarf_get_next_function(Dwarf_Die previous_die, struct dwarf_compilation_unit * unit){ Dwarf_Half tag = 0; Dwarf_Error error; Dwarf_Die func_die=0; //first, see what type this is dwarf_tag(previous_die,&tag,&error); if (tag == DW_TAG_compile_unit){ //if its the first child, make sure its not a subprogram int res = dwarf_child(unit->root_die,&previous_die,&error); dwarf_tag(previous_die,&tag,&error); //is it a subprogram, if so we are done if (tag == DW_TAG_subprogram){ return previous_die; } } func_die = _get_next_function_helper(previous_die, unit->dbg); if (func_die > 0){ return func_die; } return NULL; }
static Dwarf_Die _get_next_variable(Dwarf_Die die, Dwarf_Die original_die, struct dwarf_compilation_unit * unit){ Dwarf_Die sib_die = 0; Dwarf_Die child = 0; Dwarf_Half tag = 0; Dwarf_Error error; int res; //first, see what type this is dwarf_tag(die,&tag,&error); if ((tag == DW_TAG_variable || tag == DW_TAG_formal_parameter) && die != original_die){ return die; } //go through each child res = dwarf_child(die,&child,&error); if(res == DW_DLV_OK) { Dwarf_Die result = _get_next_variable(child,original_die,unit); if (result > 0){ return result; } } //now do the siblings res = dwarf_siblingof(unit->dbg,die,&sib_die,&error); Dwarf_Die old_die = 0; while(res != DW_DLV_ERROR && (old_die != sib_die)){ old_die=sib_die; if(res == DW_DLV_OK) { dwarf_tag(sib_die,&tag,&error); if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter){ return sib_die; } res = dwarf_siblingof(unit->dbg,sib_die,&sib_die,&error); } } return NULL; }
static void visit_die(Dwarf_Die die, unsigned long level, void (*action)(Dwarf_Die,unsigned long, void *d),void *adata){ /*This function visits the children of a die in sequence, *applying the action() function to each*/ action(die,level,adata); Dwarf_Error error; Dwarf_Die kid; if( dwarf_child(die,&kid,&error) == DW_DLV_NO_ENTRY ){ return; } visit_die(kid,level+1,action,adata); int chret; while( (chret = dwarf_siblingof(d,kid,&kid,&error)) != DW_DLV_NO_ENTRY && chret != DW_DLV_ERROR){ visit_die(kid,level+1,action,adata); } return; }
static VALUE rd_die_children(VALUE self) { rd_die_t *die = GetDie(self); VALUE top; VALUE cu; VALUE ary; Dwarf_Die child; Dwarf_Error err; if (die->children != Qfalse) { return die->children; } top = rb_ivar_get(self, id_at_top); cu = rb_ivar_get(self, id_at_cu); ary = rb_ary_new(); if (chkerr2(dwarf_child(die->die, &child, &err), &err)) { do { rb_ary_push(ary, rd_die_new(die->shared_data, top, cu, child)); } while (chkerr2(dwarf_siblingof(die->shared_data->dbg, child, &child, &err), &err)); } die->children = ary; return ary; }
/* If this type is an HFA small enough to be returned in FP registers, return the number of registers to use. Otherwise 9, or -1 for errors. */ static int hfa_type (Dwarf_Die *typedie, Dwarf_Word size, const Dwarf_Op **locp, int fpregs_used) { /* Descend the type structure, counting elements and finding their types. If we find a datum that's not an FP type (and not quad FP), punt. If we find a datum that's not the same FP type as the first datum, punt. If we count more than eight total homogeneous FP data, punt. */ inline int hfa (const Dwarf_Op *loc, int nregs) { if (fpregs_used == 0) *locp = loc; else if (*locp != loc) return 9; return fpregs_used + nregs; } int tag = DWARF_TAG_OR_RETURN (typedie); switch (tag) { Dwarf_Attribute attr_mem; case -1: return -1; case DW_TAG_base_type:; Dwarf_Word encoding; if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding, &attr_mem), &encoding) != 0) return -1; switch (encoding) { case DW_ATE_float: switch (size) { case 4: /* float */ return hfa (loc_fpreg_4, 1); case 8: /* double */ return hfa (loc_fpreg_8, 1); case 10: /* x86-style long double, not really used */ return hfa (loc_fpreg_10, 1); } break; case DW_ATE_complex_float: switch (size) { case 4 * 2: /* complex float */ return hfa (loc_fpreg_4, 2); case 8 * 2: /* complex double */ return hfa (loc_fpreg_8, 2); case 10 * 2: /* complex long double (x86-style) */ return hfa (loc_fpreg_10, 2); } break; } break; case DW_TAG_structure_type: case DW_TAG_class_type: case DW_TAG_union_type:; Dwarf_Die child_mem; switch (dwarf_child (typedie, &child_mem)) { default: return -1; case 1: /* No children: empty struct. */ break; case 0:; /* Look at each element. */ int max_used = fpregs_used; do switch (dwarf_tag (&child_mem)) { case -1: return -1; case DW_TAG_member:; Dwarf_Die child_type_mem; Dwarf_Die *child_typedie = dwarf_formref_die (dwarf_attr_integrate (&child_mem, DW_AT_type, &attr_mem), &child_type_mem); Dwarf_Word child_size; if (dwarf_aggregate_size (child_typedie, &child_size) != 0) return -1; if (tag == DW_TAG_union_type) { int used = hfa_type (child_typedie, child_size, locp, fpregs_used); if (used < 0 || used > 8) return used; if (used > max_used) max_used = used; } else { fpregs_used = hfa_type (child_typedie, child_size, locp, fpregs_used); if (fpregs_used < 0 || fpregs_used > 8) return fpregs_used; } } while (dwarf_siblingof (&child_mem, &child_mem) == 0); if (tag == DW_TAG_union_type) fpregs_used = max_used; break; } break; case DW_TAG_array_type: if (size == 0) break; Dwarf_Die base_type_mem; Dwarf_Die *base_typedie = dwarf_formref_die (dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem), &base_type_mem); Dwarf_Word base_size; if (dwarf_aggregate_size (base_typedie, &base_size) != 0) return -1; int used = hfa_type (base_typedie, base_size, locp, 0); if (used < 0 || used > 8) return used; if (size % (*locp)[1].number != 0) return 0; fpregs_used += used * (size / (*locp)[1].number); break; default: return 9; } return fpregs_used; }
/** \brief Populate the list of members of a type * * \param info ELF object containing the type DIE * \param die DIE of the type * \param unit DIE of the compilation unit containing the type DIE * \param type the type */ static void MC_dwarf_add_members(simgrid::mc::ObjectInformation* info, Dwarf_Die * die, Dwarf_Die * unit, simgrid::mc::Type* type) { int res; Dwarf_Die child; xbt_assert(type->members.empty()); for (res = dwarf_child(die, &child); res == 0; res = dwarf_siblingof(&child, &child)) { int tag = dwarf_tag(&child); if (tag == DW_TAG_member || tag == DW_TAG_inheritance) { // Skip declarations: if (MC_dwarf_attr_flag(&child, DW_AT_declaration, false)) continue; // Skip compile time constants: if (dwarf_hasattr(&child, DW_AT_const_value)) continue; // TODO, we should use another type (because is is not a type but a member) simgrid::mc::Member member; if (tag == DW_TAG_inheritance) member.flags |= simgrid::mc::Member::INHERITANCE_FLAG; const char *name = MC_dwarf_attr_integrate_string(&child, DW_AT_name); if (name) member.name = name; // Those base names are used by GCC and clang for virtual table pointers // respectively ("__vptr$ClassName", "__vptr.ClassName"): if (boost::algorithm::starts_with(member.name, "__vptr$") || boost::algorithm::starts_with(member.name, "__vptr.")) member.flags |= simgrid::mc::Member::VIRTUAL_POINTER_FLAG; // A cleaner solution would be to check against the type: // --- // tag: DW_TAG_member // name: "_vptr$Foo" // type: // # Type for a pointer to a vtable // tag: DW_TAG_pointer_type // type: // # Type for a vtable: // tag: DW_TAG_pointer_type // name: "__vtbl_ptr_type" // type: // tag: DW_TAG_subroutine_type // type: // tag: DW_TAG_base_type // name: "int" // --- member.byte_size = MC_dwarf_attr_integrate_uint(&child, DW_AT_byte_size, 0); member.type_id = MC_dwarf_at_type(&child); if (dwarf_hasattr(&child, DW_AT_data_bit_offset)) xbt_die("Can't groke DW_AT_data_bit_offset."); MC_dwarf_fill_member_location(type, &member, &child); if (not member.type_id) xbt_die("Missing type for member %s of <%" PRIx64 ">%s", member.name.c_str(), (uint64_t) type->id, type->name.c_str()); type->members.push_back(std::move(member)); } } }
int add_complextype_from_die(Dwarf_Debug dbg, Dwarf_Die parent_die, Dwarf_Die die) { int ret = DW_DLV_ERROR, i, nsib; Dwarf_Error err = 0; Dwarf_Off offset = 0; Dwarf_Half tag = 0; Dwarf_Attribute attr; Dwarf_Unsigned bsz = 0, tid = 0; Dwarf_Die grandchild; basetype_t *t, *t2; ret = dwarf_tag(die, &tag, &err); if (ret != DW_DLV_OK) { derror("error in dwarf_tag()"); goto error; } if ((tag != DW_TAG_array_type) && (tag != DW_TAG_structure_type) && (tag != DW_TAG_typedef) && (tag != DW_TAG_pointer_type)) return -1; switch (tag) { case DW_TAG_array_type: ret = get_offset_tid(die, &offset, &tid); if (ret < 0) { derror("error in get_offset_tid()"); goto error; } // get the child dwarf_child(die, &grandchild, &err); ret = dwarf_attr(grandchild, DW_AT_upper_bound, &attr, &err); if (ret == DW_DLV_ERROR) { derror("error in dwarf_attr(DW_AT_upper_bound)"); goto error; } else if (ret == DW_DLV_OK) get_number(attr, &bsz); else return 0; t = get_or_add_type(offset); snprintf(t->name, 128, "arr%u[]", (unsigned int)offset); t->ohm_type = OHM_TYPE_ARRAY; t->nelem = bsz+1; t2 = get_or_add_type(tid); t->size = t->nelem * get_type_size(t2); t->elems = malloc(sizeof(t)); t->elems[0] = t2; break; case DW_TAG_structure_type: ret = dwarf_die_CU_offset(die, &offset, &err); if (ret != DW_DLV_OK) { derror("error in dwarf_die_CU_offset()"); goto error; } t = get_or_add_type(offset); strncpy(t->name, "struct ", 7); ret = get_child_name(dbg, die, t->name+7, 128); if (ret < 0) strncpy(t->name, "<unknown-struct>", 128); t->ohm_type = OHM_TYPE_STRUCT; ret = dwarf_bytesize(die, &bsz, &err); t->size = ((ret == DW_DLV_OK) ? bsz : 0); // ensure that struct members get added to the table nsib = traverse_die(&add_structmember_from_die, dbg, parent_die, die); if (nsib < 0) goto error; t->nelem = nsib; t->elems = malloc((t->nelem)*sizeof(t)); for (i = 0; i < t->nelem; i++) t->elems[i] = &types_table[types_table_size-t->nelem-1+i]; break; case DW_TAG_typedef: ret = get_offset_tid(die, &offset, &tid); if (ret < 0) { derror("error in get_offset_tid()"); goto error; } t = get_or_add_type(offset); t->ohm_type = OHM_TYPE_ALIAS; t->size = 0; t->nelem = 1; t2 = get_or_add_type(tid); t->elems = malloc(sizeof(t)); t->elems[0] = t2; ret = get_child_name(dbg, die, t->name, 128); if (ret < 0) strncpy(t->name, "<unknown-typedef>", 128); break; case DW_TAG_pointer_type: ret = get_offset_tid(die, &offset, &tid); if (ret < 0) { derror("error in get_offset_tid()"); goto error; } t = get_or_add_type(offset); strncpy(t->name, "ptr", 128); t->ohm_type = OHM_TYPE_PTR; t->nelem = 1; t->size = sizeof(void*); t2 = get_type(tid); t->size = get_type_size(t2); t->elems = malloc(sizeof(t)); t->elems[0] = t2; break; default: break; } return 1; error: derror("error in add_complextype_from_die()"); return -1; }
int main (int argc, char *argv[]) { for (int i = 1; i < argc; ++i) { int fd = open (argv[i], O_RDONLY); Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ); if (dbg != NULL) { Dwarf_Off off = 0; size_t cuhl; Dwarf_Off noff; while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0) { Dwarf_Die die_mem; Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem); Dwarf_Die iter_mem; Dwarf_Die *iter = &iter_mem; dwarf_child (die, &iter_mem); while (1) { if (dwarf_tag (iter) == DW_TAG_variable) { Dwarf_Attribute attr_mem; Dwarf_Die form_mem; dwarf_formref_die (dwarf_attr (iter, DW_AT_type, &attr_mem), &form_mem); } if (dwarf_siblingof (iter, &iter_mem) != 0) break; } off = noff; } off = 0; uint64_t type_sig; while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL, NULL, &type_sig, NULL) == 0) { Dwarf_Die die_mem; Dwarf_Die *die = dwarf_offdie_types (dbg, off + cuhl, &die_mem); if (die == NULL) printf ("fail\n"); else printf ("ok\n"); off = noff; } dwarf_end (dbg); } close (fd); } }