+/* Dot output */
+FILE *dot_output = NULL;
+const char* colors[13];
+
+
+/******************************* DWARF Information *******************************/
+/**********************************************************************************/
+
+/************************** Free functions *************************/
+
+static void dw_location_free(dw_location_t l){
+ if(l){
+ if(l->type == e_dw_loclist)
+ xbt_dynar_free(&(l->location.loclist));
+ else if(l->type == e_dw_compose)
+ xbt_dynar_free(&(l->location.compose));
+ else if(l->type == e_dw_arithmetic)
+ xbt_free(l->location.arithmetic);
+
+ xbt_free(l);
+ }
+}
+
+static void dw_location_entry_free(dw_location_entry_t e){
+ dw_location_free(e->location);
+ xbt_free(e);
+}
+
+void dw_type_free(dw_type_t t){
+ xbt_free(t->name);
+ xbt_free(t->dw_type_id);
+ xbt_dynar_free(&(t->members));
+ xbt_free(t);
+}
+
+static void dw_type_free_voidp(void *t){
+ dw_type_free((dw_type_t) * (void **) t);
+}
+
+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->address.location);
+ 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_new(s_mc_object_info_t, 1);
+ res->file_name = NULL;
+ res->start_text = NULL;
+ res->start_data = NULL;
+ res->start_bss = NULL;
+ res->local_variables = xbt_dict_new_homogeneous(NULL);
+ res->global_variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
+ res->types = 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)->local_variables);
+ xbt_dynar_free(&(*info)->global_variables);
+ xbt_dict_free(&(*info)->types);
+ xbt_free(info);
+ *info = NULL;
+}
+
+/*************************************************************************/
+
+static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
+
+ dw_location_t loc = xbt_new0(s_dw_location_t, 1);
+
+ if(location_list != NULL){
+
+ char *key = bprintf("%d", (int)strtoul(expr, NULL, 16));
+ loc->type = e_dw_loclist;
+ loc->location.loclist = (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
+ if(loc->location.loclist == NULL)
+ XBT_INFO("Key not found in loclist");
+ xbt_free(key);
+ return loc;
+
+ }else{
+
+ int cursor = 0;
+ char *tok = NULL, *tok2 = NULL;
+
+ xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
+ xbt_dynar_t tokens2;
+
+ loc->type = e_dw_compose;
+ loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
+
+ while(cursor < xbt_dynar_length(tokens1)){
+
+ tok = xbt_dynar_get_as(tokens1, cursor, char*);
+ tokens2 = xbt_str_split(tok, " ");
+ tok2 = xbt_dynar_get_as(tokens2, 0, char*);
+
+ if(strncmp(tok2, "DW_OP_reg", 9) == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_register;
+ new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_fbregister_op;
+ new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_bregister_op;
+ new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
+ new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_lit;
+ new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_piece:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_piece;
+ new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_plus_uconst;
+ new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_abs") == 0 ||
+ strcmp(tok, "DW_OP_and") == 0 ||
+ strcmp(tok, "DW_OP_div") == 0 ||
+ strcmp(tok, "DW_OP_minus") == 0 ||
+ strcmp(tok, "DW_OP_mod") == 0 ||
+ strcmp(tok, "DW_OP_mul") == 0 ||
+ strcmp(tok, "DW_OP_neg") == 0 ||
+ strcmp(tok, "DW_OP_not") == 0 ||
+ strcmp(tok, "DW_OP_or") == 0 ||
+ strcmp(tok, "DW_OP_plus") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_arithmetic;
+ new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_stack_value") == 0){
+ }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_deref;
+ new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_deref") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_deref;
+ new_element->location.deref_size = sizeof(void *);
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_constu:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_uconstant;
+ new_element->location.uconstant.bytes = 1;
+ new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_consts:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_sconstant;
+ new_element->location.sconstant.bytes = 1;
+ new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
+ strcmp(tok2, "DW_OP_const2u:") == 0 ||
+ strcmp(tok2, "DW_OP_const4u:") == 0 ||
+ strcmp(tok2, "DW_OP_const8u:") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_uconstant;
+ new_element->location.uconstant.bytes = tok2[11] - '0';
+ new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
+ strcmp(tok, "DW_OP_const2s") == 0 ||
+ strcmp(tok, "DW_OP_const4s") == 0 ||
+ strcmp(tok, "DW_OP_const8s") == 0){
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_sconstant;
+ new_element->location.sconstant.bytes = tok2[11] - '0';
+ new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }else{
+ dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
+ new_element->type = e_dw_unsupported;
+ xbt_dynar_push(loc->location.compose, &new_element);
+ }
+
+ cursor++;
+ xbt_dynar_free(&tokens2);
+
+ }
+
+ xbt_dynar_free(&tokens1);
+
+ return loc;
+
+ }
+
+}
+
+
+/** \brief Finds a frame (DW_TAG_subprogram) from an DWARF offset in the rangd of this subprogram
+ *
+ * The offset can be an offset of a child DW_TAG_variable.