char *libsimgrid_path;
-static void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
-
/************************************ Free functions **************************************/
/*****************************************************************************************/
// TODO, support "switch type" (looking up the type in another lib) when possible
}
-static void MC_post_process_types(mc_object_info_t info) {
+void MC_post_process_types(mc_object_info_t info) {
xbt_dict_cursor_t cursor = NULL;
char *origin;
dw_type_t type;
}
}
-/** \brief Finds informations about a given shared object/executable */
-mc_object_info_t MC_find_object_info(memory_map_t maps, char* name) {
- mc_object_info_t result = MC_new_object_info();
- result->file_name = xbt_strdup(name);
- MC_find_object_address(maps, result);
- MC_dwarf_get_variables(result);
- MC_post_process_types(result);
- return result;
-}
-
/** \brief Fills the position of the .bss and .data sections. */
-static void MC_find_object_address(memory_map_t maps, mc_object_info_t result) {
+void MC_find_object_address(memory_map_t maps, mc_object_info_t result) {
unsigned int i = 0;
s_map_region_t reg;
unw_cursor_t c;
- char frame_name[256];
+ dw_frame_t test = MC_find_function_by_ip(&MC_unwind_stack_frames);
+ xbt_assert(test);
int ret;
for(ret = unw_init_local(&c, (unw_context_t *)stack_context); ret >= 0; ret = unw_step(&c)){
stack_frame->unw_cursor = c;
- unw_get_reg(&c, UNW_REG_IP, &stack_frame->ip);
- unw_get_reg(&c, UNW_REG_SP, &stack_frame->sp);
+ unw_word_t ip, sp;
+
+ unw_get_reg(&c, UNW_REG_IP, &ip);
+ unw_get_reg(&c, UNW_REG_SP, &sp);
- unw_word_t off;
- unw_get_proc_name(&c, frame_name, sizeof (frame_name), &off);
- stack_frame->frame_name = xbt_strdup(frame_name);
+ stack_frame->ip = ip;
+ stack_frame->sp = sp;
- dw_frame_t frame;
- if((long)stack_frame->ip > (long) mc_libsimgrid_info->start_exec)
- frame = xbt_dict_get_or_null(mc_libsimgrid_info->local_variables, frame_name);
- else
- frame = xbt_dict_get_or_null(mc_binary_info->local_variables, frame_name);
+ // TODO, use real addresses in frame_t instead of fixing it here
+
+ dw_frame_t frame = MC_find_function_by_ip((void*) ip);
stack_frame->frame = frame;
- if(frame != NULL){
- unw_word_t normalized_ip = (unw_word_t)frame->low_pc + (unw_word_t)off;
+ if(frame) {
+ stack_frame->frame_name = xbt_strdup(frame->name);
+
+ mc_object_info_t info = MC_ip_find_object_info((void*)ip);
+
+ // This is the instruction pointer as present in the DWARF of the object:
+ // Relocated addresses are offset for shared objets and constant for executables objects.
+ // See DWARF4 spec 7.5
+ unw_word_t normalized_ip;
+ if(info->flags & MC_OBJECT_INFO_EXECUTABLE) {
+ normalized_ip = ip;
+ } else {
+ void* base = MC_object_base_address(info);
+ normalized_ip = (unw_word_t) ip - (unw_word_t) base;
+ }
+
stack_frame->frame_base = (unw_word_t)mc_find_frame_base(normalized_ip, frame, &c);
} else {
stack_frame->frame_base = 0;
}
/* Stop before context switch with maestro */
- if(!strcmp(frame_name, "smx_ctx_sysv_wrapper"))
+ if(frame!=NULL && frame->name!=NULL && !strcmp(frame->name, "smx_ctx_sysv_wrapper"))
break;
}
case DW_TAG_shared_type:
MC_dwarf_handle_type_die(info, die, unit);
break;
- case DW_TAG_inlined_subroutine:
case DW_TAG_subprogram:
MC_dwarf_handle_subprogram_die(info, die, unit, frame);
return;
dw_variable_free((dw_variable_t) * (void **) t);
}
-// object_info
+// ***** object_info
mc_object_info_t MC_new_object_info(void) {
mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
return res;
}
+
void MC_free_object_info(mc_object_info_t* info) {
xbt_free(&(*info)->file_name);
xbt_dict_free(&(*info)->local_variables);
xbt_dict_free(&(*info)->types);
xbt_dict_free(&(*info)->types_by_name);
xbt_free(info);
+ xbt_dynar_free(&(*info)->functions_index);
*info = NULL;
}
+// ***** Helpers
+
+void* MC_object_base_address(mc_object_info_t info) {
+ void* result = info->start_exec;
+ if(info->start_rw!=NULL && result > (void*) info->start_rw) result = info->start_rw;
+ if(info->start_ro!=NULL && result > (void*) info->start_ro) result = info->start_ro;
+ return result;
+}
+
+// ***** Functions index
+
+static int MC_compare_frame_index_items(mc_function_index_item_t a, mc_function_index_item_t b) {
+ if(a->low_pc < b->low_pc)
+ return -1;
+ else if(a->low_pc == b->low_pc)
+ return 0;
+ else
+ return 1;
+}
+
+static void MC_make_functions_index(mc_object_info_t info) {
+ xbt_dynar_t index = xbt_dynar_new(sizeof(s_mc_function_index_item_t), NULL);
+
+ // The base address of the function must be used to offset the addresses.
+ // This should be fixed this in the frame_t structure instead.
+ // Relocated addresses are offset for shared objets and constant for executables objects.
+ // See DWARF4 spec 7.5
+ void* offset = info->flags & MC_OBJECT_INFO_EXECUTABLE ? 0 : MC_object_base_address(info);
+
+ // Populate the array:
+ dw_frame_t frame = NULL;
+ xbt_dict_cursor_t cursor = NULL;
+ const char* name = NULL;
+ xbt_dict_foreach(info->local_variables, cursor, name, frame) {
+ if(frame->low_pc==NULL)
+ continue;
+ s_mc_function_index_item_t entry;
+ entry.low_pc = (char*) frame->low_pc + (unsigned long) offset;
+ entry.high_pc = (char*) frame->high_pc + (unsigned long) offset;
+ entry.function = frame;
+ xbt_dynar_push(index, &entry);
+ }
+
+ mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(index, 0);
+
+ // Sort the array by low_pc:
+ qsort(base,
+ xbt_dynar_length(index),
+ sizeof(s_mc_function_index_item_t),
+ (int (*)(const void *, const void *))MC_compare_frame_index_items);
+
+ info->functions_index = index;
+}
+
+mc_object_info_t MC_ip_find_object_info(void* ip) {
+ mc_object_info_t infos[2] = { mc_binary_info, mc_libsimgrid_info };
+ size_t n = 2;
+ size_t i;
+ for(i=0; i!=n; ++i) {
+ if(ip >= (void*)infos[i]->start_exec && ip <= (void*)infos[i]->end_exec) {
+ return infos[i];
+ }
+ }
+ return NULL;
+}
+
+static dw_frame_t MC_find_function_by_ip_and_object(void* ip, mc_object_info_t info) {
+ xbt_dynar_t dynar = info->functions_index;
+ mc_function_index_item_t base = (mc_function_index_item_t) xbt_dynar_get_ptr(dynar, 0);
+ int i = 0;
+ int j = xbt_dynar_length(dynar) - 1;
+ while(j>=i) {
+ int k = i + ((j-i)/2);
+ if(ip < base[k].low_pc) {
+ j = k-1;
+ } else if(ip > base[k].high_pc) {
+ i = k+1;
+ } else {
+ return base[k].function;
+ }
+ }
+ return NULL;
+}
+
+dw_frame_t MC_find_function_by_ip(void* ip) {
+ mc_object_info_t info = MC_ip_find_object_info(ip);
+ if(info==NULL)
+ return NULL;
+ else
+ return MC_find_function_by_ip_and_object(ip, info);
+}
+
+/** \brief Finds informations about a given shared object/executable */
+mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable) {
+ mc_object_info_t result = MC_new_object_info();
+ if(executable)
+ result->flags |= MC_OBJECT_INFO_EXECUTABLE;
+ result->file_name = xbt_strdup(name);
+ MC_find_object_address(maps, result);
+ MC_dwarf_get_variables(result);
+ MC_post_process_types(result);
+ MC_make_functions_index(result);
+ return result;
+}
+
/*************************************************************************/
static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
memory_map_t maps = MC_get_memory_map();
/* Get local variables for state equality detection */
- mc_binary_info = MC_find_object_info(maps, xbt_binary_name);
- mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path);
+ mc_binary_info = MC_find_object_info(maps, xbt_binary_name, 1);
+ mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path, 0);
MC_free_memory_map(maps);
XBT_INFO("Get debug information done !");
#include "xbt/parmap.h"
typedef struct s_dw_frame s_dw_frame_t, *dw_frame_t;
+typedef struct s_mc_function_index_item s_mc_function_index_item_t, *mc_function_index_item_t;
/****************************** Snapshots ***********************************/
/********************************** Variables with DWARF **********************************/
+#define MC_OBJECT_INFO_EXECUTABLE 1
+
struct s_mc_object_info {
+ size_t flags;
char* file_name;
char *start_exec, *end_exec; // Executable segment
char *start_rw, *end_rw; // Read-write segment
xbt_dynar_t global_variables; // xbt_dynar_t<dw_variable_t>
xbt_dict_t types; // xbt_dict_t<origin as hexadecimal string, dw_type_t>
xbt_dict_t types_by_name; // xbt_dict_t<name, dw_type_t> (full defined type only)
+
+ // Here we sort the minimal information for an efficient (and cache-efficient)
+ // lookup of a function given an instruction pointer.
+ // The entries are sorted by low_pc and a binary search can be used to look them up.
+ xbt_dynar_t functions_index;
};
mc_object_info_t MC_new_object_info(void);
-mc_object_info_t MC_find_object_info(memory_map_t maps, char* name);
+mc_object_info_t MC_find_object_info(memory_map_t maps, char* name, int executable);
void MC_free_object_info(mc_object_info_t* p);
void MC_dwarf_get_variables(mc_object_info_t info);
const char* MC_dwarf_attrname(int attr);
const char* MC_dwarf_tagname(int tag);
+dw_frame_t MC_find_function_by_ip(void* ip);
+mc_object_info_t MC_ip_find_object_info(void* ip);
+
extern mc_object_info_t mc_libsimgrid_info;
extern mc_object_info_t mc_binary_info;
+void MC_find_object_address(memory_map_t maps, mc_object_info_t result);
+void MC_post_process_types(mc_object_info_t info);
+
typedef enum {
e_dw_loclist,
e_dw_register,
unsigned long int end; /* Dwarf offset of the next sibling */
};
+struct s_mc_function_index_item {
+ void* low_pc, *high_pc;
+ dw_frame_t function;
+};
+
void dw_type_free(dw_type_t t);
void dw_variable_free(dw_variable_t v);
void dw_variable_free_voidp(void *t);
void MC_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
void MC_dwarf_register_non_global_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame, dw_variable_t variable);
+void* MC_object_base_address(mc_object_info_t info);
/********************************** DWARF **********************************/