X-Git-Url: http://info.iut-bm.univ-fcomte.fr/pub/gitweb/simgrid.git/blobdiff_plain/19ae8582cb401f7b1b6d2f7e3ca00e79ce78e8bb..276b87ef25a4bce97dfec6020bc7e6d5a0ec837c:/src/mc/mc_dwarf.c diff --git a/src/mc/mc_dwarf.c b/src/mc/mc_dwarf.c index 34a511d128..cc9a8eb8cc 100644 --- a/src/mc/mc_dwarf.c +++ b/src/mc/mc_dwarf.c @@ -1,9 +1,11 @@ -/* Copyright (c) 2008-2013. The SimGrid Team. +/* Copyright (c) 2008-2014. The SimGrid Team. * All rights reserved. */ + /* This program is free software; you can redistribute it and/or modify it * under the terms of the license (GNU LGPL) which comes with this package. */ #include +#define DW_LANG_Objc DW_LANG_ObjC /* fix spelling error in older dwarf.h */ #include #include #include @@ -273,23 +275,40 @@ static const char* MC_dwarf_at_linkage_name(Dwarf_Die* die) { return name; } +static Dwarf_Off MC_dwarf_attr_dieoffset(Dwarf_Die* die, int attribute) { + Dwarf_Attribute attr; + if (dwarf_hasattr_integrate(die, attribute)) { + dwarf_attr_integrate(die, attribute, &attr); + Dwarf_Die subtype_die; + if (dwarf_formref_die(&attr, &subtype_die)==NULL) { + xbt_die("Could not find DIE"); + } + return dwarf_dieoffset(&subtype_die); + } + else return 0; +} + +static Dwarf_Off MC_dwarf_attr_integrate_dieoffset(Dwarf_Die* die, int attribute) { + Dwarf_Attribute attr; + if (dwarf_hasattr_integrate(die, attribute)) { + dwarf_attr_integrate(die, DW_AT_type, &attr); + Dwarf_Die subtype_die; + if (dwarf_formref_die(&attr, &subtype_die)==NULL) { + xbt_die("Could not find DIE"); + } + return dwarf_dieoffset(&subtype_die); + } + else return 0; +} + /** \brief Find the type/subtype (DW_AT_type) for a DIE * * \param dit the DIE * \return DW_AT_type reference as a global offset in hexadecimal (or NULL) */ static char* MC_dwarf_at_type(Dwarf_Die* die) { - Dwarf_Attribute attr; - if (dwarf_hasattr_integrate(die, DW_AT_type)) { - dwarf_attr_integrate(die, DW_AT_type, &attr); - Dwarf_Die subtype_die; - if (dwarf_formref_die(&attr, &subtype_die)==NULL) { - xbt_die("Could not find DIE for type"); - } - Dwarf_Off subtype_global_offset = dwarf_dieoffset(&subtype_die); - return bprintf("%" PRIx64 , subtype_global_offset); - } - else return NULL; + Dwarf_Off offset = MC_dwarf_attr_integrate_dieoffset(die, DW_AT_type); + return offset == 0 ? NULL : bprintf("%" PRIx64 , offset); } static uint64_t MC_dwarf_attr_integrate_addr(Dwarf_Die* die, int attribute) { @@ -436,8 +455,8 @@ static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwar if (!dwarf_hasattr_integrate(child, DW_AT_data_member_location)) { if (type->type != DW_TAG_union_type) { xbt_die( - "Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%p>%s", - member->name, type->id, type->name); + "Missing DW_AT_data_member_location field in DW_TAG_member %s of type <%"PRIx64">%s", + member->name, (uint64_t) type->id, type->name); } else { return; } @@ -456,9 +475,9 @@ static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwar size_t len; if (dwarf_getlocation(&attr, &expr, &len)) { xbt_die( - "Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%p>%s", + "Could not read location expression DW_AT_data_member_location in DW_TAG_member %s of type <%"PRIx64">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name), - type->id, type->name); + (uint64_t) type->id, type->name); } if (len==1 && expr[0].atom == DW_OP_plus_uconst) { member->offset = expr[0].number; @@ -474,9 +493,9 @@ static void MC_dwarf_fill_member_location(dw_type_t type, dw_type_t member, Dwar if (!dwarf_formudata(&attr, &offset)) member->offset = offset; else - xbt_die("Cannot get %s location <%p>%s", + xbt_die("Cannot get %s location <%"PRIx64">%s", MC_dwarf_attr_integrate_string(child, DW_AT_name), - type->id, type->name); + (uint64_t) type->id, type->name); break; } case MC_DW_CLASS_LOCLISTPTR: @@ -526,7 +545,7 @@ static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Di member->type = tag; // Global Offset: - member->id = (void *) dwarf_dieoffset(&child); + member->id = dwarf_dieoffset(&child); const char* name = MC_dwarf_attr_integrate_string(&child, DW_AT_name); if(name) @@ -548,7 +567,7 @@ static void MC_dwarf_add_members(mc_object_info_t info, Dwarf_Die* die, Dwarf_Di MC_dwarf_fill_member_location(type, member, &child); if (!member->dw_type_id) { - xbt_die("Missing type for member %s of <%p>%s", member->name, type->id, type->name); + xbt_die("Missing type for member %s of <%"PRIx64">%s", member->name, (uint64_t) type->id, type->name); } xbt_dynar_push(type->members, &member); @@ -567,7 +586,7 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwa dw_type_t type = xbt_new0(s_dw_type_t, 1); type->type = -1; - type->id = NULL; + type->id = 0; type->name = NULL; type->byte_size = 0; type->element_count = -1; @@ -579,7 +598,7 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwa type->type = dwarf_tag(die); // Global Offset - type->id = (void *) dwarf_dieoffset(die); + type->id = dwarf_dieoffset(die); const char* prefix = ""; switch (type->type) { @@ -601,8 +620,6 @@ static dw_type_t MC_dwarf_die_to_type(mc_object_info_t info, Dwarf_Die* die, Dwa 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); - type->dw_type_id = MC_dwarf_at_type(die); // Computation of the byte_size; @@ -673,6 +690,7 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D dw_variable_t variable = xbt_new0(s_dw_variable_t, 1); variable->dwarf_offset = dwarf_dieoffset(die); variable->global = frame == NULL; // Can be override base on DW_AT_location + variable->object_info = info; const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name); variable->name = xbt_strdup(name); @@ -690,15 +708,14 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D size_t len; if (dwarf_getlocation(&attr_location, &expr, &len)) { xbt_die( - "Could not read location expression in DW_AT_location of variable <%p>%s", - (void*) variable->dwarf_offset, variable->name); + "Could not read location expression in DW_AT_location of variable <%"PRIx64">%s", + (uint64_t) variable->dwarf_offset, variable->name); } if (len==1 && expr[0].atom == DW_OP_addr) { variable->global = 1; - Dwarf_Off offset = expr[0].number; - // TODO, Why is this different base on the object? - Dwarf_Off base = strcmp(info->file_name, xbt_binary_name) !=0 ? (Dwarf_Off) info->start_exec : 0; + uintptr_t offset = (uintptr_t) expr[0].number; + uintptr_t base = (uintptr_t) MC_object_base_address(info); variable->address = (void*) (base + offset); } else { mc_dwarf_location_list_init_from_expression(&variable->locations, len, expr); @@ -712,8 +729,8 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D mc_dwarf_location_list_init(&variable->locations, info, die, &attr_location); break; default: - 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); + xbt_die("Unexpected form 0x%x (%i), class 0x%x (%i) list for location in <%"PRIx64">%s", + form, form, klass, klass, (uint64_t) variable->dwarf_offset, variable->name); } // Handle start_scope: @@ -729,6 +746,7 @@ static dw_variable_t MC_die_to_variable(mc_object_info_t info, Dwarf_Die* die, D variable->start_scope = dwarf_formudata(&attr, &value) == 0 ? (size_t) value : 0; break; } + case MC_DW_CLASS_RANGELISTPTR: // TODO default: xbt_die("Unhandled form 0x%x, class 0x%X for DW_AT_start_scope of variable %s", form, klass, name==NULL ? "?" : name); @@ -777,21 +795,59 @@ static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die* die, Dwa dw_frame_t frame = xbt_new0(s_dw_frame_t, 1); frame->tag = tag; - frame->start = dwarf_dieoffset(die); + frame->id = dwarf_dieoffset(die); + frame->object_info = info; - const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name); - if(name) + if(klass==mc_tag_subprogram) { + const char* name = MC_dwarf_attr_integrate_string(die, DW_AT_name); frame->name = namespace ? bprintf("%s::%s", namespace, name) : xbt_strdup(name); + } + + frame->abstract_origin_id = MC_dwarf_attr_dieoffset(die, DW_AT_abstract_origin); // This is the base address for DWARF addresses. // Relocated addresses are offset from this base address. // See DWARF4 spec 7.5 - void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info); + void* base = MC_object_base_address(info); // Variables are filled in the (recursive) call of MC_dwarf_handle_children: frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp); - frame->high_pc = ((char*) base) + MC_dwarf_attr_integrate_addr(die, DW_AT_high_pc); - frame->low_pc = ((char*) base) + MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc); + + // TODO, support DW_AT_ranges + uint64_t low_pc = MC_dwarf_attr_integrate_addr(die, DW_AT_low_pc); + frame->low_pc = low_pc ? ((char*) base) + low_pc : 0; + if(low_pc) { + // DW_AT_high_pc: + Dwarf_Attribute attr; + if(!dwarf_attr_integrate(die, DW_AT_high_pc, &attr)) { + xbt_die("Missing DW_AT_high_pc matching with DW_AT_low_pc"); + } + + Dwarf_Sword offset; + Dwarf_Addr high_pc; + + switch(MC_dwarf_form_get_class(dwarf_whatform(&attr))) { + + // DW_AT_high_pc if an offset from the low_pc: + case MC_DW_CLASS_CONSTANT: + + if (dwarf_formsdata(&attr, &offset) !=0) + xbt_die("Could not read constant"); + frame->high_pc = (void*) ((char*)frame->low_pc + offset); + break; + + // DW_AT_high_pc is a relocatable address: + case MC_DW_CLASS_ADDRESS: + if (dwarf_formaddr(&attr, &high_pc) != 0) + xbt_die("Could not read address"); + frame->high_pc = ((char*) base) + high_pc; + break; + + default: + xbt_die("Unexpected class for DW_AT_high_pc"); + + } + } if(klass==mc_tag_subprogram) { Dwarf_Attribute attr_frame_base; @@ -803,7 +859,7 @@ static void MC_dwarf_handle_scope_die(mc_object_info_t info, Dwarf_Die* die, Dwa // Register it: if(klass==mc_tag_subprogram) { - char* key = bprintf("%" PRIx64, (uint64_t) frame->start); + char* key = bprintf("%" PRIx64, (uint64_t) frame->id); xbt_dict_set(info->subprograms, key, frame, NULL); xbt_free(key); } else if(klass==mc_tag_scope) {