+
+/************************** Free functions *************************/
+
+void mc_frame_free(dw_frame_t frame)
+{
+ xbt_free(frame->name);
+ mc_dwarf_location_list_clear(&(frame->frame_base));
+ xbt_dynar_free(&(frame->variables));
+ xbt_dynar_free(&(frame->scopes));
+ xbt_free(frame);
+}
+
+void dw_type_free(dw_type_t t)
+{
+ xbt_free(t->name);
+ xbt_free(t->dw_type_id);
+ xbt_dynar_free(&(t->members));
+ mc_dwarf_expression_clear(&t->location);
+ xbt_free(t);
+}
+
+void dw_variable_free(dw_variable_t v)
+{
+ if (v) {
+ xbt_free(v->name);
+ xbt_free(v->type_origin);
+
+ if (v->locations.locations)
+ mc_dwarf_location_list_clear(&v->locations);
+ xbt_free(v);
+ }
+}
+
+void dw_variable_free_voidp(void *t)
+{
+ dw_variable_free((dw_variable_t) * (void **) t);
+}
+
+// ***** object_info
+
+
+
+mc_object_info_t MC_new_object_info(void)
+{
+ mc_object_info_t res = xbt_new0(s_mc_object_info_t, 1);
+ res->subprograms = xbt_dict_new_homogeneous((void (*)(void *)) mc_frame_free);
+ res->global_variables =
+ xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
+ res->types = xbt_dict_new_homogeneous((void (*)(void *)) dw_type_free);
+ res->full_types_by_name = xbt_dict_new_homogeneous(NULL);
+ return res;
+}
+
+void MC_free_object_info(mc_object_info_t * info)
+{
+ xbt_free(&(*info)->file_name);
+ xbt_dict_free(&(*info)->subprograms);
+ xbt_dynar_free(&(*info)->global_variables);
+ xbt_dict_free(&(*info)->types);
+ xbt_dict_free(&(*info)->full_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)
+{
+ if (info->flags & MC_OBJECT_INFO_EXECUTABLE)
+ return 0;
+ 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);
+
+ // Populate the array:
+ dw_frame_t frame = NULL;
+ xbt_dict_cursor_t cursor;
+ char *key;
+ xbt_dict_foreach(info->subprograms, cursor, key, frame) {
+ if (frame->low_pc == NULL)
+ continue;
+ s_mc_function_index_item_t entry;
+ entry.low_pc = frame->low_pc;
+ entry.high_pc = frame->high_pc;
+ 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;
+}
+
+static void MC_post_process_variables(mc_object_info_t info)
+{
+ unsigned cursor = 0;
+ dw_variable_t variable = NULL;
+ xbt_dynar_foreach(info->global_variables, cursor, variable) {
+ if (variable->type_origin) {
+ variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+ }
+ }
+}
+
+static void mc_post_process_scope(mc_object_info_t info, dw_frame_t scope)
+{
+
+ if (scope->tag == DW_TAG_inlined_subroutine) {
+
+ // Attach correct namespaced name in inlined subroutine:
+ char *key = bprintf("%" PRIx64, (uint64_t) scope->abstract_origin_id);
+ dw_frame_t abstract_origin = xbt_dict_get_or_null(info->subprograms, key);
+ xbt_assert(abstract_origin, "Could not lookup abstract origin %s", key);
+ xbt_free(key);
+ scope->name = xbt_strdup(abstract_origin->name);
+
+ }
+ // Direct:
+ unsigned cursor = 0;
+ dw_variable_t variable = NULL;
+ xbt_dynar_foreach(scope->variables, cursor, variable) {
+ if (variable->type_origin) {
+ variable->type = xbt_dict_get_or_null(info->types, variable->type_origin);
+ }
+ }
+
+ // Recursive post-processing of nested-scopes:
+ dw_frame_t nested_scope = NULL;
+ xbt_dynar_foreach(scope->scopes, cursor, nested_scope)
+ mc_post_process_scope(info, nested_scope);
+
+}
+
+static void MC_post_process_functions(mc_object_info_t info)
+{
+ xbt_dict_cursor_t cursor;
+ char *key;
+ dw_frame_t subprogram = NULL;
+ xbt_dict_foreach(info->subprograms, cursor, key, subprogram) {
+ mc_post_process_scope(info, subprogram);
+ }
+}
+
+
+/** \brief Fill/lookup the "subtype" field.
+ */
+static void MC_resolve_subtype(mc_object_info_t info, dw_type_t type)
+{
+
+ if (type->dw_type_id == NULL)
+ return;
+ type->subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
+ if (type->subtype == NULL)
+ return;
+ if (type->subtype->byte_size != 0)
+ return;
+ if (type->subtype->name == NULL)
+ return;
+ // Try to find a more complete description of the type:
+ // We need to fix in order to support C++.
+
+ dw_type_t subtype =
+ xbt_dict_get_or_null(info->full_types_by_name, type->subtype->name);
+ if (subtype != NULL) {
+ type->subtype = subtype;
+ }
+
+}
+
+static void MC_post_process_types(mc_object_info_t info)
+{
+ xbt_dict_cursor_t cursor = NULL;
+ char *origin;
+ dw_type_t type;
+
+ // Lookup "subtype" field:
+ xbt_dict_foreach(info->types, cursor, origin, type) {
+ MC_resolve_subtype(info, type);
+
+ dw_type_t member;
+ unsigned int i = 0;
+ if (type->members != NULL)
+ xbt_dynar_foreach(type->members, i, member) {
+ MC_resolve_subtype(info, member);
+ }
+ }
+}
+
+/** \brief Finds informations about a given shared object/executable */
+mc_object_info_t MC_find_object_info(memory_map_t maps, const 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_post_process_variables(result);
+ MC_post_process_functions(result);
+ MC_make_functions_index(result);
+ return result;
+}
+
+/*************************************************************************/
+
+static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char *var,
+ void *address)
+{
+
+ if (xbt_dynar_is_empty(variables))
+ return 0;
+
+ unsigned int cursor = 0;
+ int start = 0;
+ int end = xbt_dynar_length(variables) - 1;
+ dw_variable_t var_test = NULL;
+
+ while (start <= end) {
+ cursor = (start + end) / 2;
+ var_test =
+ (dw_variable_t) xbt_dynar_get_as(variables, cursor, dw_variable_t);
+ if (strcmp(var_test->name, var) < 0) {
+ start = cursor + 1;
+ } else if (strcmp(var_test->name, var) > 0) {
+ end = cursor - 1;
+ } else {
+ if (address) { /* global variable */
+ if (var_test->address == address)
+ return -1;
+ if (var_test->address > address)
+ end = cursor - 1;
+ else
+ start = cursor + 1;
+ } else { /* local variable */
+ return -1;
+ }
+ }
+ }
+
+ if (strcmp(var_test->name, var) == 0) {
+ if (address && var_test->address < address)
+ return cursor + 1;
+ else
+ return cursor;
+ } else if (strcmp(var_test->name, var) < 0)
+ return cursor + 1;
+ else
+ return cursor;
+
+}
+
+void MC_dwarf_register_global_variable(mc_object_info_t info,
+ dw_variable_t variable)
+{
+ int index =
+ MC_dwarf_get_variable_index(info->global_variables, variable->name,
+ variable->address);
+ if (index != -1)
+ xbt_dynar_insert_at(info->global_variables, index, &variable);
+ // TODO, else ?
+}
+
+void MC_dwarf_register_non_global_variable(mc_object_info_t info,
+ dw_frame_t frame,
+ dw_variable_t variable)
+{
+ xbt_assert(frame, "Frame is NULL");
+ int index =
+ MC_dwarf_get_variable_index(frame->variables, variable->name, NULL);
+ if (index != -1)
+ xbt_dynar_insert_at(frame->variables, index, &variable);
+ // TODO, else ?
+}
+
+void MC_dwarf_register_variable(mc_object_info_t info, dw_frame_t frame,
+ dw_variable_t variable)
+{
+ if (variable->global)
+ MC_dwarf_register_global_variable(info, variable);
+ else if (frame == NULL)
+ xbt_die("No frame for this local variable");
+ else
+ MC_dwarf_register_non_global_variable(info, frame, variable);
+}
+
+void MC_post_process_object_info(mc_process_t process, mc_object_info_t info)
+{
+ xbt_dict_cursor_t cursor = NULL;
+ char *key = NULL;
+ dw_type_t type = NULL;
+ xbt_dict_foreach(info->types, cursor, key, type) {
+
+ dw_type_t subtype = type;
+ while (subtype->type == DW_TAG_typedef || subtype->type == DW_TAG_volatile_type
+ || subtype->type == DW_TAG_const_type) {
+ if (subtype->subtype)
+ subtype = subtype->subtype;
+ else
+ break;
+ }
+
+ // Resolve full_type:
+ if (subtype->name && subtype->byte_size == 0) {
+ for (size_t i = 0; i != process->object_infos_size; ++i) {
+ dw_type_t same_type =
+ xbt_dict_get_or_null(process->object_infos[i]->full_types_by_name,
+ subtype->name);
+ if (same_type && same_type->name && same_type->byte_size) {
+ type->full_type = same_type;
+ break;
+ }
+ }
+ } else type->full_type = subtype;
+
+ }
+}