X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/2503eb4da1a3a0f30c99e47e5e4ed34deba6074d..986f00b8a57d82825f9e419d48e44c7ca47af7c5:/src/mc/mc_dwarf.c diff --git a/src/mc/mc_dwarf.c b/src/mc/mc_dwarf.c index 11e0b32c11..67eccc48b4 100644 --- a/src/mc/mc_dwarf.c +++ b/src/mc/mc_dwarf.c @@ -74,14 +74,6 @@ static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwar */ static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace); -/** \brief Convert a libdw DWARF expression into a MC representation of the location - * - * \param expr array of DWARf operations - * \param len number of elements - * \return a new MC expression - */ -static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len); - /** \brief Get the DW_TAG_type of the DIE * * \param die DIE @@ -98,7 +90,7 @@ const char* MC_dwarf_attrname(int attr) { switch (attr) { #include "mc_dwarf_attrnames.h" default: - return "DW_AT_unkown"; + return "DW_AT_unknown"; } } @@ -113,14 +105,14 @@ const char* MC_dwarf_tagname(int tag) { case DW_TAG_invalid: return "DW_TAG_invalid"; default: - return "DW_TAG_unkown"; + return "DW_TAG_unknown"; } } /** \brief A class of DWARF tags (DW_TAG_*) */ typedef enum mc_tag_class { - mc_tag_unkonwn, + mc_tag_unknown, mc_tag_type, mc_tag_subprogram, mc_tag_variable, @@ -128,7 +120,7 @@ typedef enum mc_tag_class { mc_tag_namespace } mc_tag_class; -static mc_tag_class MC_dwarg_tag_classify(int tag) { +static mc_tag_class MC_dwarf_tag_classify(int tag) { switch (tag) { case DW_TAG_array_type: @@ -136,6 +128,8 @@ static mc_tag_class MC_dwarg_tag_classify(int tag) { case DW_TAG_enumeration_type: case DW_TAG_typedef: case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: case DW_TAG_string_type: case DW_TAG_structure_type: case DW_TAG_subroutine_type: @@ -171,7 +165,7 @@ static mc_tag_class MC_dwarg_tag_classify(int tag) { return mc_tag_namespace; default: - return mc_tag_unkonwn; + return mc_tag_unknown; } } @@ -267,137 +261,6 @@ static const char* MC_dwarf_at_linkage_name(Dwarf_Die* die) { return name; } -/** \brief Create a location list from a given attribute - * - * \param die the DIE - * \param attr the attribute - * \return MC specific representation of the location list represented by the given attribute - * of the given die - */ -static dw_location_t MC_dwarf_get_location_list(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) { - - dw_location_t location = xbt_new0(s_dw_location_t, 1); - location->type = e_dw_loclist; - xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL); - location->location.loclist = loclist; - - ptrdiff_t offset = 0; - Dwarf_Addr base, start, end; - Dwarf_Op *expr; - size_t len; - - while (1) { - - offset = dwarf_getlocations(attr, offset, &base, &start, &end, &expr, &len); - if (offset==0) - return location; - else if (offset==-1) - xbt_die("Error while loading location list"); - - dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1); - - void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info); - - new_entry->lowpc = (char*) base + start; - new_entry->highpc = (char*) base + end; - new_entry->location = MC_dwarf_get_expression(expr, len); - - xbt_dynar_push(loclist, &new_entry); - - } -} - -/** \brief Find the frame base of a given frame - * - * \param ip Instruction pointer - * \param frame - * \param unw_cursor - */ -void* mc_find_frame_base(void* ip, dw_frame_t frame, unw_cursor_t* unw_cursor) { - switch(frame->frame_base->type) { - case e_dw_loclist: - { - int loclist_cursor; - for(loclist_cursor=0; loclist_cursor < xbt_dynar_length(frame->frame_base->location.loclist); loclist_cursor++){ - dw_location_entry_t entry = xbt_dynar_get_as(frame->frame_base->location.loclist, loclist_cursor, dw_location_entry_t); - if((ip >= entry->lowpc) && (ip < entry->highpc)){ - return (void*) MC_dwarf_resolve_location(unw_cursor, entry->location, NULL); - } - } - return NULL; - } - // Not handled: - default: - return NULL; - } -} - -/** \brief Get the location expression or location list from an attribute - * - * Processes direct expressions as well as location lists. - * - * \param die the DIE - * \param attr the attribute - * \return MC specific representation of the location represented by the given attribute - * of the given die - */ -static dw_location_t MC_dwarf_get_location(mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) { - int form = dwarf_whatform(attr); - switch (form) { - - // The attribute is an DWARF location expression: - case DW_FORM_exprloc: - case DW_FORM_block1: // not in the spec - case DW_FORM_block2: - case DW_FORM_block4: - case DW_FORM_block: - { - Dwarf_Op* expr; - size_t len; - if (dwarf_getlocation(attr, &expr, &len)) - xbt_die("Could not read location expression"); - return MC_dwarf_get_expression(expr, len); - } - - // The attribute is a reference to a location list entry: - case DW_FORM_sec_offset: - case DW_FORM_data1: - case DW_FORM_data2: - case DW_FORM_data4: - case DW_FORM_data8: - { - return MC_dwarf_get_location_list(info, die, attr); - } - break; - - default: - xbt_die("Unexpected form %i list for location in attribute %s of <%p>%s", - form, - MC_dwarf_attrname(attr->code), - (void*) dwarf_dieoffset(die), - MC_dwarf_attr_string(die, DW_AT_name)); - return NULL; - } -} - -/** \brief Get the location expression or location list from an attribute - * - * Processes direct expressions as well as location lists. - * - * \param die the DIE - * \param attribute the attribute code - * \return MC specific representation of the location represented by the given attribute - * of the given die - */ -static dw_location_t MC_dwarf_at_location(mc_object_info_t info, Dwarf_Die* die, int attribute) { - if(!dwarf_hasattr_integrate(die, attribute)) - return xbt_new0(s_dw_location_t, 1); - - Dwarf_Attribute attr; - dwarf_attr_integrate(die, attribute, &attr); - return MC_dwarf_get_location(info, die, &attr); -} - static char* MC_dwarf_at_type(Dwarf_Die* die) { Dwarf_Attribute attr; if (dwarf_hasattr_integrate(die, DW_AT_type)) { @@ -516,38 +379,6 @@ static uint64_t MC_dwarf_array_element_count(Dwarf_Die* die, Dwarf_Die* unit) { return result; } -// ***** Location - -Dwarf_Off MC_dwarf_resolve_location(unw_cursor_t* c, dw_location_t location, void* frame_pointer_address) { - unw_word_t res; - switch (location->type){ - case e_dw_compose: - if (xbt_dynar_length(location->location.compose) > 1){ - return 0; /* TODO : location list with optimizations enabled */ - } - dw_location_t location_entry = xbt_dynar_get_as(location->location.compose, 0, dw_location_t); - switch (location_entry->type){ - case e_dw_register: - unw_get_reg(c, location_entry->location.reg, &res); - return res; - case e_dw_bregister_op: - unw_get_reg(c, location_entry->location.breg_op.reg, &res); - return (Dwarf_Off) ((long)res + location_entry->location.breg_op.offset); - break; - case e_dw_fbregister_op: - if (frame_pointer_address != NULL) - return (Dwarf_Off)((char *)frame_pointer_address + location_entry->location.fbreg_op); - else - return 0; - default: - return 0; /* FIXME : implement other cases (with optimizations enabled) */ - } - break; - default: - return 0; - } -} - // ***** dw_type_t static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwarf_Die* child) { @@ -567,7 +398,7 @@ static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwar Dwarf_Attribute attr; dwarf_attr_integrate(child, DW_AT_data_member_location, &attr); - int form = dwarf_whatform(&attr); + int form = dwarf_whatform(&attr); int klass = MC_dwarf_form_get_class(form); switch (klass) { case MC_DW_CLASS_EXPRLOC: @@ -585,7 +416,7 @@ static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwar if (len==1 && expr[0].atom == DW_OP_plus_uconst) { member->offset = expr[0].number; } else { - xbt_die("Can't groke this location expression yet."); + mc_dwarf_expression_init(&member->location, len, expr); } break; } @@ -621,11 +452,23 @@ static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Di xbt_assert(!type->members); type->members = xbt_dynar_new(sizeof(dw_type_t), (void(*)(void*))dw_type_free); for (res=dwarf_child(die, &child); res==0; res=dwarf_siblingof(&child,&child)) { - if (dwarf_tag(&child)==DW_TAG_member) { + 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) dw_type_t member = xbt_new0(s_dw_type_t, 1); - member->type = -1; - member->id = NULL; + member->type = tag; + + // Global Offset: + member->id = (void *) dwarf_dieoffset(&child); const char* name = MC_dwarf_attr_string(&child, DW_AT_name); if(name) @@ -680,9 +523,24 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwa // Global Offset type->id = (void *) dwarf_dieoffset(die); + const char* prefix = ""; + switch (type->type) { + case DW_TAG_structure_type: + prefix = "struct "; + break; + case DW_TAG_union_type: + prefix = "union "; + break; + case DW_TAG_class_type: + prefix = "class "; + break; + default: + prefix = ""; + } + const char* name = MC_dwarf_attr_string(die, DW_AT_name); if (name!=NULL) { - type->name = xbt_strdup(name); + type->name = namespace ? bprintf("%s%s::%s", prefix, namespace, name) : bprintf("%s%s", prefix, name); } XBT_DEBUG("Processing type <%p>%s", type->id, type->name); @@ -716,7 +574,7 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwa case DW_TAG_class_type: MC_dwarf_add_members(info, die, unit, type); char* new_namespace = namespace == NULL ? xbt_strdup(type->name) - : bprintf("%s::%s", namespace, type->name); + : bprintf("%s::%s", namespace, name); MC_dwarf_handle_children(info, die, unit, frame, new_namespace); free(new_namespace); break; @@ -732,176 +590,21 @@ static void MC_dwarf_handle_type_die(mc_object_info_t info, Dwarf_Die* die, Dwar xbt_dict_set(info->types, key, type, NULL); if(type->name && type->byte_size!=0) { - xbt_dict_set(info->types_by_name, type->name, type, NULL); + xbt_dict_set(info->full_types_by_name, type->name, type, NULL); } } -/** \brief Convert libdw location expresion elment into native one (or NULL in some cases) */ -static dw_location_t MC_dwarf_get_expression_element(Dwarf_Op* op) { - dw_location_t element = xbt_new0(s_dw_location_t, 1); - uint8_t atom = op->atom; - if (atom >= DW_OP_reg0 && atom<= DW_OP_reg31) { - element->type = e_dw_register; - element->location.reg = atom - DW_OP_reg0; - } - else if (atom >= DW_OP_breg0 && atom<= DW_OP_breg31) { - element->type = e_dw_bregister_op; - element->location.reg = atom - DW_OP_breg0; - element->location.breg_op.offset = op->number; - } - else if (atom >= DW_OP_lit0 && atom<= DW_OP_lit31) { - element->type = e_dw_lit; - element->location.reg = atom - DW_OP_lit0; - } - else switch (atom) { - case DW_OP_fbreg: - element->type = e_dw_fbregister_op; - element->location.fbreg_op = op->number; - break; - case DW_OP_piece: - element->type = e_dw_piece; - element->location.piece = op->number; - break; - case DW_OP_plus_uconst: - element->type = e_dw_plus_uconst; - element->location.plus_uconst = op->number; - break; - case DW_OP_abs: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("abs"); - break; - case DW_OP_and: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("and"); - break; - case DW_OP_div: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("div"); - break; - case DW_OP_minus: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("minus"); - break; - case DW_OP_mod: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("mod"); - break; - case DW_OP_mul: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("mul"); - break; - case DW_OP_neg: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("neg"); - break; - case DW_OP_not: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("not"); - break; - case DW_OP_or: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("or"); - break; - case DW_OP_plus: - element->type = e_dw_arithmetic; - element->location.arithmetic = xbt_strdup("plus"); - break; - - case DW_OP_stack_value: - // Why nothing here? - xbt_free(element); - return NULL; - - case DW_OP_deref_size: - element->type = e_dw_deref; - element->location.deref_size = (unsigned int short) op->number; - break; - case DW_OP_deref: - element->type = e_dw_deref; - element->location.deref_size = sizeof(void *); - break; - case DW_OP_constu: - element->type = e_dw_uconstant; - element->location.uconstant.bytes = 1; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_consts: - element->type = e_dw_sconstant; - element->location.uconstant.bytes = 1; - element->location.uconstant.value = (unsigned long int) op->number; - break; - - case DW_OP_const1u: - element->type = e_dw_uconstant; - element->location.uconstant.bytes = 1; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_const2u: - element->type = e_dw_uconstant; - element->location.uconstant.bytes = 2; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_const4u: - element->type = e_dw_uconstant; - element->location.uconstant.bytes = 4; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_const8u: - element->type = e_dw_uconstant; - element->location.uconstant.bytes = 8; - element->location.uconstant.value = (unsigned long int) op->number; - break; - - case DW_OP_const1s: - element->type = e_dw_sconstant; - element->location.uconstant.bytes = 1; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_const2s: - element->type = e_dw_sconstant; - element->location.uconstant.bytes = 2; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_const4s: - element->type = e_dw_sconstant; - element->location.uconstant.bytes = 4; - element->location.uconstant.value = (unsigned long int) op->number; - break; - case DW_OP_const8s: - element->type = e_dw_sconstant; - element->location.uconstant.bytes = 8; - element->location.uconstant.value = (unsigned long int) op->number; - break; - default: - element->type = e_dw_unsupported; - break; - } - return element; -} - -/** \brief Convert libdw location expresion into native one */ -static dw_location_t MC_dwarf_get_expression(Dwarf_Op* expr, size_t len) { - dw_location_t loc = xbt_new0(s_dw_location_t, 1); - loc->type = e_dw_compose; - loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL); - - int i; - for (i=0; i!=len; ++i) { - dw_location_t element = MC_dwarf_get_expression_element(expr+i); - if (element) - xbt_dynar_push(loc->location.compose, &element); - } - - return loc; -} - static int mc_anonymous_variable_index = 0; static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) { - // Drop declaration: + // Skip declarations: if (MC_dwarf_attr_flag(die, DW_AT_declaration, false)) return NULL; + // Skip compile time constants: + if(dwarf_hasattr(die, DW_AT_const_value)) + return NULL; + Dwarf_Attribute attr_location; if (dwarf_attr(die, DW_AT_location, &attr_location)==NULL) { // No location: do not add it ? @@ -917,7 +620,8 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D variable->type_origin = MC_dwarf_at_type(die); - int klass = MC_dwarf_form_get_class(dwarf_whatform(&attr_location)); + int form = dwarf_whatform(&attr_location); + int klass = form == DW_FORM_sec_offset ? MC_DW_CLASS_CONSTANT : MC_dwarf_form_get_class(form); switch (klass) { case MC_DW_CLASS_EXPRLOC: case MC_DW_CLASS_BLOCK: @@ -938,7 +642,7 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D Dwarf_Off base = strcmp(info->file_name, xbt_binary_name) !=0 ? (Dwarf_Off) info->start_exec : 0; variable->address = (void*) (base + offset); } else { - variable->location = MC_dwarf_get_expression(expr, len); + mc_dwarf_location_list_init_from_expression(&variable->locations, len, expr); } break; @@ -946,11 +650,11 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D case MC_DW_CLASS_LOCLISTPTR: case MC_DW_CLASS_CONSTANT: // Reference to location list: - variable->location = MC_dwarf_get_location_list(info, die, &attr_location); + mc_dwarf_location_list_init(&variable->locations, info, die, &attr_location); break; default: - xbt_die("Unexpected calss 0x%x (%i) list for location in <%p>%s", - klass, klass, (void*) variable->dwarf_offset, variable->name); + xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%p>%s", + form, form, klass, klass, (void*) variable->dwarf_offset, variable->name); } // Handle start_scope: @@ -995,6 +699,11 @@ static void MC_dwarf_handle_variable_die(mc_object_info_t info, Dwarf_Die* die, } static void MC_dwarf_handle_subprogram_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t parent_frame, const char* namespace) { + + // (Template) Subprogram declaration: + if (MC_dwarf_attr_flag(die, DW_AT_declaration, false)) + return; + dw_frame_t frame = xbt_new0(s_dw_frame_t, 1); frame->start = dwarf_dieoffset(die); @@ -1011,11 +720,16 @@ static void MC_dwarf_handle_subprogram_die(mc_object_info_t info, Dwarf_Die* die frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp); frame->high_pc = ((char*) base) + MC_dwarf_attr_addr(die, DW_AT_high_pc); frame->low_pc = ((char*) base) + MC_dwarf_attr_addr(die, DW_AT_low_pc); - frame->frame_base = MC_dwarf_at_location(info, die, DW_AT_frame_base); + + Dwarf_Attribute attr_frame_base; + if (dwarf_attr_integrate(die, DW_AT_frame_base, &attr_frame_base)) + mc_dwarf_location_list_init(&frame->frame_base, info, die, &attr_frame_base); + frame->end = -1; // This one is now useless: // Register it: - xbt_dynar_push(info->subprograms, &frame); + const char* key = bprintf("%" PRIx64, (uint64_t) frame->start); + xbt_dict_set(info->subprograms, key, frame, NULL); // Handle children: MC_dwarf_handle_children(info, die, unit, frame, namespace); @@ -1041,7 +755,7 @@ static void MC_dwarf_handle_children(mc_object_info_t info, Dwarf_Die* die, Dwar static void MC_dwarf_handle_die(mc_object_info_t info, Dwarf_Die* die, Dwarf_Die* unit, dw_frame_t frame, const char* namespace) { int tag = dwarf_tag(die); - mc_tag_class klass = MC_dwarg_tag_classify(tag); + mc_tag_class klass = MC_dwarf_tag_classify(tag); switch (klass) { // Type: