From 5f25255261a9dc908c7ba0133de80f05f993c8c5 Mon Sep 17 00:00:00 2001 From: Gabriel Corona Date: Fri, 7 Mar 2014 11:29:07 +0100 Subject: [PATCH 1/1] [mc] Use new DWARF expression code for variables --- src/mc/mc_checkpoint.c | 6 +-- src/mc/mc_dwarf.c | 4 +- src/mc/mc_dwarf_expression.c | 88 ++++++++++++++++++++++++++++++++++++ src/mc/mc_global.c | 5 +- src/mc/mc_hash.c | 4 +- src/mc/mc_private.h | 10 +++- 6 files changed, 107 insertions(+), 10 deletions(-) diff --git a/src/mc/mc_checkpoint.c b/src/mc/mc_checkpoint.c index 3e1f4cb203..6e86b8118d 100644 --- a/src/mc/mc_checkpoint.c +++ b/src/mc/mc_checkpoint.c @@ -275,9 +275,9 @@ static xbt_dynar_t MC_get_local_variables_values(xbt_dynar_t stack_frames){ /* if(current_variable->address!=NULL) { new_var->address = current_variable->address; } else */ - if(current_variable->location != NULL){ - new_var->address = (void*) MC_dwarf_resolve_location( - &(stack_frame->unw_cursor), current_variable->location, (void*)stack_frame->frame_base); + if(current_variable->locations.size != 0){ + new_var->address = (void*) mc_dwarf_resolve_locations(¤t_variable->locations, + &(stack_frame->unw_cursor), (void*)stack_frame->frame_base); } xbt_dynar_push(variables, &new_var); diff --git a/src/mc/mc_dwarf.c b/src/mc/mc_dwarf.c index aa5f9f0f4e..9395335dd6 100644 --- a/src/mc/mc_dwarf.c +++ b/src/mc/mc_dwarf.c @@ -951,7 +951,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; @@ -959,7 +959,7 @@ 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 form 0x%x (%i), class 0x%x (%i) list for location in <%p>%s", diff --git a/src/mc/mc_dwarf_expression.c b/src/mc/mc_dwarf_expression.c index a73ac2f52a..54f0d22e2a 100644 --- a/src/mc/mc_dwarf_expression.c +++ b/src/mc/mc_dwarf_expression.c @@ -236,3 +236,91 @@ Dwarf_Off mc_dwarf_resolve_location(mc_expression_t expression, unw_cursor_t* c, return (Dwarf_Off) state.stack[state.stack_size-1]; } +Dwarf_Off mc_dwarf_resolve_locations(mc_location_list_t locations, unw_cursor_t* c, void* frame_pointer_address) { + + unw_word_t ip; + if(c) { + if(unw_get_reg(c, UNW_REG_IP, &ip)) + xbt_die("Could not resolve IP"); + } + + for(size_t i=0; i!=locations->size; ++i) { + mc_expression_t expression = locations->locations + i; + if( (expression->lowpc==NULL && expression->highpc==NULL) + || (c && ip >= (unw_word_t) expression->lowpc && ip < (unw_word_t) expression->highpc)) { + return mc_dwarf_resolve_location(expression, c, frame_pointer_address); + } + } + xbt_die("Could not resolve location"); +} + +static +void mc_dwarf_expression_clear(mc_expression_t expression) { + free(expression->ops); + expression->ops = NULL; + expression->size = 0; + expression->lowpc = NULL; + expression->highpc = NULL; +} + +void mc_dwarf_location_list_clear(mc_location_list_t list) { + for(size_t i=0; i!=list->size; ++i) { + mc_dwarf_expression_clear(list->locations + i); + } + free(list->locations); + list->locations = NULL; + list->size = 0; +} + +static +void mc_dwarf_expression_init(mc_expression_t expression, size_t len, Dwarf_Op* ops) { + if(expression->ops) { + free(expression->ops); + } + expression->lowpc = NULL; + expression->highpc = NULL; + expression->size = len; + expression->ops = xbt_malloc(len*sizeof(Dwarf_Op)); + memcpy(expression->ops, ops, len*sizeof(Dwarf_Op)); +} + +void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops) { + if(target->locations) { + mc_dwarf_location_list_clear(target); + } + target->size = 1; + target->locations = (mc_expression_t) xbt_malloc(sizeof(s_mc_expression_t)); + mc_dwarf_expression_init(target->locations, len, ops); +} + +void mc_dwarf_location_list_init(mc_location_list_t list, mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr) { + if(list->locations) { + mc_dwarf_location_list_clear(list); + } + list->size = 0; + + ptrdiff_t offset = 0; + Dwarf_Addr base, start, end; + Dwarf_Op *ops; + size_t len; + + while (1) { + + offset = dwarf_getlocations(attr, offset, &base, &start, &end, &ops, &len); + if (offset==0) + return; + else if (offset==-1) + xbt_die("Error while loading location list"); + + int i = list->size; + list->size++; + list->locations = (mc_expression_t) realloc(list->locations, list->size*sizeof(s_mc_expression_t)); + mc_expression_t expression = list->locations + i; + + void* base = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info); + mc_dwarf_expression_init(expression, len, ops); + expression->lowpc = (char*) base + start; + expression->highpc = (char*) base + end; + } + +} diff --git a/src/mc/mc_global.c b/src/mc/mc_global.c index 133343e8ee..c551c72d95 100644 --- a/src/mc/mc_global.c +++ b/src/mc/mc_global.c @@ -185,8 +185,9 @@ void dw_variable_free(dw_variable_t v){ if(v){ xbt_free(v->name); xbt_free(v->type_origin); - if(!v->global) - dw_location_free(v->location); + + if(v->locations.locations) + mc_dwarf_location_list_clear(&v->locations); xbt_free(v); } } diff --git a/src/mc/mc_hash.c b/src/mc/mc_hash.c index 627e708a91..87e724a3ae 100644 --- a/src/mc/mc_hash.c +++ b/src/mc/mc_hash.c @@ -233,14 +233,14 @@ static void mc_hash_stack_frame( XBT_DEBUG("Hash local variable %s without type", variable->name); continue; } - if(variable->location == NULL) { + if(variable->locations.size == 0) { XBT_DEBUG("Hash local variable %s without location", variable->name); continue; } XBT_DEBUG("Hash local variable %s", variable->name); - void* variable_address = (void*) MC_dwarf_resolve_location(unw_cursor, variable->location, frame_pointer); + void* variable_address = (void*) mc_dwarf_resolve_location(&variable->locations, unw_cursor, frame_pointer); dw_type_t type = variable->type; if(type==NULL) { diff --git a/src/mc/mc_private.h b/src/mc/mc_private.h index f8519a5830..63a4b3851a 100644 --- a/src/mc/mc_private.h +++ b/src/mc/mc_private.h @@ -386,6 +386,14 @@ typedef struct s_mc_location_list { mc_expression_t locations; } s_mc_location_list_t, *mc_location_list_t; +Dwarf_Off mc_dwarf_resolve_location(mc_expression_t expression, unw_cursor_t* c, void* frame_pointer_address); +Dwarf_Off mc_dwarf_resolve_locations(mc_location_list_t locations, unw_cursor_t* c, void* frame_pointer_address); + +void mc_dwarf_location_list_clear(mc_location_list_t list); + +void mc_dwarf_location_list_init_from_expression(mc_location_list_t target, size_t len, Dwarf_Op* ops); +void mc_dwarf_location_list_init(mc_location_list_t target, mc_object_info_t info, Dwarf_Die* die, Dwarf_Attribute* attr); + // ***** Deprecated locations: typedef enum { @@ -460,7 +468,7 @@ typedef struct s_dw_variable{ dw_type_t type; // Use either of: - dw_location_t location; + s_mc_location_list_t locations; void* address; size_t start_scope; -- 2.20.1