Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] Deduplicate address location resolution in MC_dwarf_resolve_location()
[simgrid.git] / src / mc / mc_global.c
1 /* Copyright (c) 2008-2013. The SimGrid Team.
2  * All rights reserved.                                                     */
3
4 /* This program is free software; you can redistribute it and/or modify it
5  * under the terms of the license (GNU LGPL) which comes with this package. */
6
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <sys/wait.h>
10 #include <sys/time.h>
11 #include <libgen.h>
12
13 #include "simgrid/sg_config.h"
14 #include "../surf/surf_private.h"
15 #include "../simix/smx_private.h"
16 #include "../xbt/mmalloc/mmprivate.h"
17 #include "xbt/fifo.h"
18 #include "mc_private.h"
19 #include "xbt/automaton.h"
20 #include "xbt/dict.h"
21
22 static void MC_post_process_types(mc_object_info_t info);
23
24 XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
25 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
26                                 "Logging specific to MC (global)");
27
28 /* Configuration support */
29 e_mc_reduce_t mc_reduce_kind=e_mc_reduce_unset;
30
31 int _sg_do_model_check = 0;
32 int _sg_mc_checkpoint=0;
33 char* _sg_mc_property_file=NULL;
34 int _sg_mc_timeout=0;
35 int _sg_mc_max_depth=1000;
36 int _sg_mc_visited=0;
37 char *_sg_mc_dot_output_file = NULL;
38
39 int user_max_depth_reached = 0;
40
41 void _mc_cfg_cb_reduce(const char *name, int pos) {
42   if (_sg_cfg_init_status && !_sg_do_model_check) {
43     xbt_die("You are specifying a reduction strategy after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
44   }
45   char *val= xbt_cfg_get_string(_sg_cfg_set, name);
46   if (!strcasecmp(val,"none")) {
47     mc_reduce_kind = e_mc_reduce_none;
48   } else if (!strcasecmp(val,"dpor")) {
49     mc_reduce_kind = e_mc_reduce_dpor;
50   } else {
51     xbt_die("configuration option %s can only take 'none' or 'dpor' as a value",name);
52   }
53 }
54
55 void _mc_cfg_cb_checkpoint(const char *name, int pos) {
56   if (_sg_cfg_init_status && !_sg_do_model_check) {
57     xbt_die("You are specifying a checkpointing value after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
58   }
59   _sg_mc_checkpoint = xbt_cfg_get_int(_sg_cfg_set, name);
60 }
61 void _mc_cfg_cb_property(const char *name, int pos) {
62   if (_sg_cfg_init_status && !_sg_do_model_check) {
63     xbt_die("You are specifying a property after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
64   }
65   _sg_mc_property_file= xbt_cfg_get_string(_sg_cfg_set, name);
66 }
67
68 void _mc_cfg_cb_timeout(const char *name, int pos) {
69   if (_sg_cfg_init_status && !_sg_do_model_check) {
70     xbt_die("You are specifying a value to enable/disable timeout for wait requests after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
71   }
72   _sg_mc_timeout= xbt_cfg_get_boolean(_sg_cfg_set, name);
73 }
74
75 void _mc_cfg_cb_max_depth(const char *name, int pos) {
76   if (_sg_cfg_init_status && !_sg_do_model_check) {
77     xbt_die("You are specifying a max depth value after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
78   }
79   _sg_mc_max_depth= xbt_cfg_get_int(_sg_cfg_set, name);
80 }
81
82 void _mc_cfg_cb_visited(const char *name, int pos) {
83   if (_sg_cfg_init_status && !_sg_do_model_check) {
84     xbt_die("You are specifying a number of stored visited states after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
85   }
86   _sg_mc_visited= xbt_cfg_get_int(_sg_cfg_set, name);
87 }
88
89 void _mc_cfg_cb_dot_output(const char *name, int pos) {
90   if (_sg_cfg_init_status && !_sg_do_model_check) {
91     xbt_die("You are specifying a file name for a dot output of graph state after the initialization (through MSG_config?), but model-checking was not activated at config time (through --cfg=model-check:1). This won't work, sorry.");
92   }
93   _sg_mc_dot_output_file= xbt_cfg_get_string(_sg_cfg_set, name);
94 }
95
96 /* MC global data structures */
97 mc_state_t mc_current_state = NULL;
98 char mc_replay_mode = FALSE;
99 double *mc_time = NULL;
100 __thread mc_comparison_times_t mc_comp_times = NULL;
101 __thread double mc_snapshot_comparison_time;
102 mc_stats_t mc_stats = NULL;
103
104 /* Safety */
105 xbt_fifo_t mc_stack_safety = NULL;
106 mc_global_t initial_state_safety = NULL;
107
108 /* Liveness */
109 xbt_fifo_t mc_stack_liveness = NULL;
110 mc_global_t initial_state_liveness = NULL;
111 int compare;
112
113 xbt_automaton_t _mc_property_automaton = NULL;
114
115 /* Variables */
116 mc_object_info_t mc_libsimgrid_info = NULL;
117 mc_object_info_t mc_binary_info = NULL;
118
119 /* Ignore mechanism */
120 xbt_dynar_t mc_stack_comparison_ignore;
121 xbt_dynar_t mc_data_bss_comparison_ignore;
122 extern xbt_dynar_t mc_heap_comparison_ignore;
123 extern xbt_dynar_t stacks_areas;
124
125 /* Dot output */
126 FILE *dot_output = NULL;
127 const char* colors[13];
128
129
130 /*******************************  DWARF Information *******************************/
131 /**********************************************************************************/
132
133 /************************** Free functions *************************/
134
135 static void dw_location_free(dw_location_t l){
136   if(l){
137     if(l->type == e_dw_loclist)
138       xbt_dynar_free(&(l->location.loclist));
139     else if(l->type == e_dw_compose)
140       xbt_dynar_free(&(l->location.compose));
141     else if(l->type == e_dw_arithmetic)
142       xbt_free(l->location.arithmetic);
143   
144     xbt_free(l);
145   }
146 }
147
148 static void dw_location_entry_free(dw_location_entry_t e){
149   dw_location_free(e->location);
150   xbt_free(e);
151 }
152
153 void dw_type_free(dw_type_t t){
154   xbt_free(t->name);
155   xbt_free(t->dw_type_id);
156   xbt_dynar_free(&(t->members));
157   xbt_free(t);
158 }
159
160 static void dw_type_free_voidp(void *t){
161   dw_type_free((dw_type_t) * (void **) t);
162 }
163
164 static void dw_variable_free(dw_variable_t v){
165   if(v){
166     xbt_free(v->name);
167     xbt_free(v->type_origin);
168     if(!v->global)
169       dw_location_free(v->address.location);
170     xbt_free(v);
171   }
172 }
173
174 static void dw_variable_free_voidp(void *t){
175   dw_variable_free((dw_variable_t) * (void **) t);
176 }
177
178 // object_info
179
180 mc_object_info_t MC_new_object_info(void) {
181   mc_object_info_t res = xbt_new(s_mc_object_info_t, 1);
182   res->file_name = NULL;
183   res->start_text = NULL;
184   res->start_data = NULL;
185   res->start_bss = NULL;
186   res->start_plt = NULL;
187   res->end_plt = NULL;
188   res->start_got_plt = NULL;
189   res->end_got_plt = NULL;
190   res->local_variables = xbt_dict_new_homogeneous(NULL);
191   res->global_variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
192   res->types = xbt_dict_new_homogeneous(NULL);
193   return res;
194 }
195
196 void MC_free_object_info(mc_object_info_t* info) {
197   xbt_free(&(*info)->file_name);
198   xbt_dict_free(&(*info)->local_variables);
199   xbt_dynar_free(&(*info)->global_variables);
200   xbt_dict_free(&(*info)->types);
201   xbt_free(info);
202   info = NULL;
203 }
204
205 /*************************************************************************/
206
207 static dw_location_t MC_dwarf_get_location(xbt_dict_t location_list, char *expr){
208
209   dw_location_t loc = xbt_new0(s_dw_location_t, 1);
210
211   if(location_list != NULL){
212     
213     char *key = bprintf("%d", (int)strtoul(expr, NULL, 16));
214     loc->type = e_dw_loclist;
215     loc->location.loclist =  (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
216     if(loc->location.loclist == NULL)
217       XBT_INFO("Key not found in loclist");
218     xbt_free(key);
219     return loc;
220
221   }else{
222
223     int cursor = 0;
224     char *tok = NULL, *tok2 = NULL; 
225     
226     xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
227     xbt_dynar_t tokens2;
228
229     loc->type = e_dw_compose;
230     loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
231
232     while(cursor < xbt_dynar_length(tokens1)){
233
234       tok = xbt_dynar_get_as(tokens1, cursor, char*);
235       tokens2 = xbt_str_split(tok, " ");
236       tok2 = xbt_dynar_get_as(tokens2, 0, char*);
237       
238       if(strncmp(tok2, "DW_OP_reg", 9) == 0){
239         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
240         new_element->type = e_dw_register;
241         new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
242         xbt_dynar_push(loc->location.compose, &new_element);     
243       }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
244         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
245         new_element->type = e_dw_fbregister_op;
246         new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
247         xbt_dynar_push(loc->location.compose, &new_element);
248       }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
249         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
250         new_element->type = e_dw_bregister_op;
251         new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
252         new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
253         xbt_dynar_push(loc->location.compose, &new_element);
254       }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
255         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
256         new_element->type = e_dw_lit;
257         new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
258         xbt_dynar_push(loc->location.compose, &new_element);
259       }else if(strcmp(tok2, "DW_OP_piece:") == 0){
260         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
261         new_element->type = e_dw_piece;
262         new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
263         xbt_dynar_push(loc->location.compose, &new_element);
264       }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
265         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
266         new_element->type = e_dw_plus_uconst;
267         new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
268         xbt_dynar_push(loc->location.compose, &new_element);
269       }else if(strcmp(tok, "DW_OP_abs") == 0 || 
270                strcmp(tok, "DW_OP_and") == 0 ||
271                strcmp(tok, "DW_OP_div") == 0 ||
272                strcmp(tok, "DW_OP_minus") == 0 ||
273                strcmp(tok, "DW_OP_mod") == 0 ||
274                strcmp(tok, "DW_OP_mul") == 0 ||
275                strcmp(tok, "DW_OP_neg") == 0 ||
276                strcmp(tok, "DW_OP_not") == 0 ||
277                strcmp(tok, "DW_OP_or") == 0 ||
278                strcmp(tok, "DW_OP_plus") == 0){               
279         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
280         new_element->type = e_dw_arithmetic;
281         new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
282         xbt_dynar_push(loc->location.compose, &new_element);
283       }else if(strcmp(tok, "DW_OP_stack_value") == 0){
284       }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
285         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
286         new_element->type = e_dw_deref;
287         new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
288         xbt_dynar_push(loc->location.compose, &new_element);
289       }else if(strcmp(tok, "DW_OP_deref") == 0){
290         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
291         new_element->type = e_dw_deref;
292         new_element->location.deref_size = sizeof(void *);
293         xbt_dynar_push(loc->location.compose, &new_element);
294       }else if(strcmp(tok2, "DW_OP_constu:") == 0){
295         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
296         new_element->type = e_dw_uconstant;
297         new_element->location.uconstant.bytes = 1;
298         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
299         xbt_dynar_push(loc->location.compose, &new_element);
300       }else if(strcmp(tok2, "DW_OP_consts:") == 0){
301         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
302         new_element->type = e_dw_sconstant;
303         new_element->location.sconstant.bytes = 1;
304         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
305         xbt_dynar_push(loc->location.compose, &new_element);
306       }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
307                strcmp(tok2, "DW_OP_const2u:") == 0 ||
308                strcmp(tok2, "DW_OP_const4u:") == 0 ||
309                strcmp(tok2, "DW_OP_const8u:") == 0){
310         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
311         new_element->type = e_dw_uconstant;
312         new_element->location.uconstant.bytes = tok2[11] - '0';
313         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
314         xbt_dynar_push(loc->location.compose, &new_element);
315       }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
316                strcmp(tok, "DW_OP_const2s") == 0 ||
317                strcmp(tok, "DW_OP_const4s") == 0 ||
318                strcmp(tok, "DW_OP_const8s") == 0){
319         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
320         new_element->type = e_dw_sconstant;
321         new_element->location.sconstant.bytes = tok2[11] - '0';
322         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
323         xbt_dynar_push(loc->location.compose, &new_element);
324       }else{
325         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
326         new_element->type = e_dw_unsupported;
327         xbt_dynar_push(loc->location.compose, &new_element);
328       }
329
330       cursor++;
331       xbt_dynar_free(&tokens2);
332
333     }
334     
335     xbt_dynar_free(&tokens1);
336
337     return loc;
338     
339   }
340
341 }
342
343 /** @brief Extract the location lists from an ELF file (.debug_loc)
344  *
345  *  @return A map from the offset in the list (in hexadecimal string)
346  *          into a location list (dynar of dw_location_entry_t).
347  */
348 static xbt_dict_t MC_dwarf_get_location_list(const char *elf_file){
349
350   char *command = bprintf("LANG=C objdump -Wo %s", elf_file);
351
352   FILE *fp = popen(command, "r");
353
354   if(fp == NULL){
355     perror("popen for objdump failed");
356     xbt_abort();
357   }
358
359   int debug = 0; /*Detect if the program has been compiled with -g */
360
361   xbt_dict_t location_list = xbt_dict_new_homogeneous(NULL);
362   char *line = NULL, *loc_expr = NULL;
363   ssize_t read;
364   size_t n = 0;
365   int cursor_remove;
366   xbt_dynar_t split = NULL;
367
368   while ((read = xbt_getline(&line, &n, fp)) != -1) {
369
370     /* Wipeout the new line character */
371     line[read - 1] = '\0';
372
373     xbt_str_trim(line, NULL);
374     
375     if(n == 0)
376       continue;
377
378     if(strlen(line) == 0)
379       continue;
380
381     if(debug == 0){
382
383       if(strncmp(line, elf_file, strlen(elf_file)) == 0)
384         continue;
385       
386       if(strncmp(line, "Contents", 8) == 0)
387         continue;
388
389       if(strncmp(line, "Offset", 6) == 0){
390         debug = 1;
391         continue;
392       }
393     }
394
395     if(debug == 0){
396       XBT_INFO("Your program must be compiled with -g");
397       xbt_abort();
398     }
399
400     xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
401
402     xbt_str_strip_spaces(line);
403     split = xbt_str_split(line, " ");
404
405     char *key = NULL;
406     while(read != -1 && strcmp("<End", (char *)xbt_dynar_get_as(split, 1, char *)) != 0){
407       
408       // Take the key from the first line of the list:
409       if(key==NULL){
410         key = bprintf("%d", (int)strtoul((char *)xbt_dynar_get_as(split, 0, char *), NULL, 16));
411       }
412
413       dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
414       new_entry->lowpc = strtoul((char *)xbt_dynar_get_as(split, 1, char *), NULL, 16);
415       new_entry->highpc = strtoul((char *)xbt_dynar_get_as(split, 2, char *), NULL, 16);
416       
417       cursor_remove =0;
418       while(cursor_remove < 3){
419         xbt_dynar_remove_at(split, 0, NULL);
420         cursor_remove++;
421       }
422
423       loc_expr = xbt_str_join(split, " ");
424       xbt_str_ltrim(loc_expr, "(");
425       xbt_str_rtrim(loc_expr, ")");
426       new_entry->location = MC_dwarf_get_location(NULL, loc_expr);
427
428       xbt_dynar_push(loclist, &new_entry);
429
430       xbt_dynar_free(&split);
431       free(loc_expr);
432
433       read = xbt_getline(&line, &n, fp);
434       if(read != -1){
435         line[read - 1] = '\0';
436         xbt_str_strip_spaces(line);
437         split = xbt_str_split(line, " ");
438       }
439
440     }
441
442
443     xbt_dict_set(location_list, key, loclist, NULL);
444     xbt_free(key);
445     
446     xbt_dynar_free(&split);
447
448   }
449
450   xbt_free(line);
451   xbt_free(command);
452   pclose(fp);
453
454   return location_list;
455 }
456
457 /** \brief Finds a frame (DW_TAG_subprogram) from an DWARF offset in the rangd of this subprogram
458  *
459  * The offset can be an offset of a child DW_TAG_variable.
460  */
461 static dw_frame_t MC_dwarf_get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset){
462
463   xbt_dict_cursor_t cursor = NULL;
464   char *name;
465   dw_frame_t res;
466
467   xbt_dict_foreach(all_variables, cursor, name, res) {
468     if(offset >= res->start && offset < res->end){
469       xbt_dict_cursor_free(&cursor);
470       return res;
471     }
472   }
473
474   xbt_dict_cursor_free(&cursor);
475   return NULL;
476   
477 }
478
479 static dw_variable_t MC_dwarf_get_variable_by_name(dw_frame_t frame, char *var){
480
481   unsigned int cursor = 0;
482   dw_variable_t current_var;
483
484   xbt_dynar_foreach(frame->variables, cursor, current_var){
485     if(strcmp(var, current_var->name) == 0)
486       return current_var;
487   }
488
489   return NULL;
490 }
491
492 static int MC_dwarf_get_variable_index(xbt_dynar_t variables, char* var, void *address){
493
494   if(xbt_dynar_is_empty(variables))
495     return 0;
496
497   unsigned int cursor = 0;
498   int start = 0;
499   int end = xbt_dynar_length(variables) - 1;
500   dw_variable_t var_test = NULL;
501
502   while(start <= end){
503     cursor = (start + end) / 2;
504     var_test = (dw_variable_t)xbt_dynar_get_as(variables, cursor, dw_variable_t);
505     if(strcmp(var_test->name, var) < 0){
506       start = cursor + 1;
507     }else if(strcmp(var_test->name, var) > 0){
508       end = cursor - 1;
509     }else{
510       if(address){ /* global variable */
511         if(var_test->address.address == address)
512           return -1;
513         if(var_test->address.address > address)
514           end = cursor - 1;
515         else
516           start = cursor + 1;
517       }else{ /* local variable */
518         return -1;
519       }
520     }
521   }
522
523   if(strcmp(var_test->name, var) == 0){
524     if(address && var_test->address.address < address)
525       return cursor+1;
526     else
527       return cursor;
528   }else if(strcmp(var_test->name, var) < 0)
529     return cursor+1;
530   else
531     return cursor;
532
533 }
534
535 /** \brief Fill DWARf debug infomations (types, frames, variables ...). */
536 void MC_dwarf_get_variables(mc_object_info_t info) {
537   if(MC_USE_LIBDW_TYPES)
538     MC_dwarf_get_variables_libdw(info);
539   mc_object_info_t result = info;
540   const char *elf_file = info->file_name;
541
542   xbt_dict_t location_list = MC_dwarf_get_location_list(elf_file);
543
544   char *command = bprintf("LANG=C objdump -Wi %s", elf_file);
545   
546   FILE *fp = popen(command, "r");
547
548   if(fp == NULL)
549     perror("popen for objdump failed");
550
551   xbt_dict_t *local_variables = &result->local_variables;
552   xbt_dynar_t *global_variables = &result->global_variables;
553   xbt_dict_t *types = &result->types;
554
555   char *line = NULL, *origin, *abstract_origin, *current_frame = NULL, 
556     *subprogram_name = NULL, *subprogram_start = NULL, *subprogram_end = NULL,
557     *node_type = NULL, *location_type = NULL, *variable_name = NULL, 
558     *loc_expr = NULL, *name = NULL, *end =NULL, *type_origin = NULL, *global_address = NULL, 
559     *parent_value = NULL;
560
561   ssize_t read =0;
562   size_t n = 0;
563   int global_variable = 0, parent = 0, new_frame = 0, new_variable = 1, size = 0, 
564     is_pointer = 0, struct_decl = 0, member_end = 0,
565     enumeration_size = 0, subrange = 0, union_decl = 0, offset = 0, index = 0;
566   
567   xbt_dynar_t split = NULL, split2 = NULL;
568
569   xbt_dict_t variables_origin = xbt_dict_new_homogeneous(xbt_free);
570   xbt_dict_t subprograms_origin = xbt_dict_new_homogeneous(xbt_free);
571
572   dw_frame_t variable_frame, subroutine_frame = NULL;
573
574   e_dw_type_type type_type = -1;
575
576   read = xbt_getline(&line, &n, fp);
577
578   while (read != -1) {
579
580     /* Wipeout the new line character */
581     line[read - 1] = '\0';
582   
583     if(n == 0 || strlen(line) == 0){
584       read = xbt_getline(&line, &n, fp);
585       continue;
586     }
587
588     xbt_str_ltrim(line, NULL);
589     xbt_str_strip_spaces(line);
590     
591     if(line[0] != '<'){
592       read = xbt_getline(&line, &n, fp);
593       continue;
594     }
595     
596     xbt_dynar_free(&split);
597     split = xbt_str_split(line, " ");
598
599     /* Get node type */
600     node_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
601
602     if(strcmp(node_type, "(DW_TAG_subprogram)") == 0){ /* New frame */
603       /* We build/complete a dw_frame_t object
604        * and append it if necessary to the local_variables dictionnary */
605
606       dw_frame_t frame = NULL;
607
608       strtok(xbt_dynar_get_as(split, 0, char *), "<");
609       subprogram_start = xbt_strdup(strtok(NULL, "<"));
610       xbt_str_rtrim(subprogram_start, ">:");
611
612       read = xbt_getline(&line, &n, fp);
613    
614       while(read != -1){
615
616         /* Wipeout the new line character */
617         line[read - 1] = '\0';
618
619         if(n == 0 || strlen(line) == 0){
620           read = xbt_getline(&line, &n, fp);
621           continue;
622         }
623         
624         xbt_dynar_free(&split);
625         xbt_str_rtrim(line, NULL);
626         xbt_str_strip_spaces(line);
627         split = xbt_str_split(line, " ");
628           
629         node_type = xbt_dynar_get_as(split, 1, char *);
630
631         if(strncmp(node_type, "DW_AT_", 6) != 0)
632           break;
633
634         if(strcmp(node_type, "DW_AT_sibling") == 0){
635
636           subprogram_end = xbt_strdup(xbt_dynar_get_as(split, 3, char*));
637           xbt_str_ltrim(subprogram_end, "<0x");
638           xbt_str_rtrim(subprogram_end, ">");
639           
640         }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){ /* Frame already in dict */
641           
642           new_frame = 0;
643           abstract_origin = xbt_strdup(xbt_dynar_get_as(split, 2, char*));
644           xbt_str_ltrim(abstract_origin, "<0x");
645           xbt_str_rtrim(abstract_origin, ">");
646           subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, abstract_origin);
647           frame = xbt_dict_get_or_null(*local_variables, subprogram_name); 
648           xbt_free(abstract_origin);
649
650         }else if(strcmp(node_type, "DW_AT_name") == 0){
651
652           new_frame = 1;
653           xbt_free(current_frame);
654           frame = xbt_new0(s_dw_frame_t, 1);
655           frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); 
656           frame->variables = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
657           frame->frame_base = xbt_new0(s_dw_location_t, 1); 
658           current_frame = strdup(frame->name);
659
660           xbt_dict_set(subprograms_origin, subprogram_start, xbt_strdup(frame->name), NULL);
661         
662         }else if(strcmp(node_type, "DW_AT_frame_base") == 0){
663
664           location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
665
666           if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
667
668             frame->frame_base = MC_dwarf_get_location(location_list, xbt_dynar_get_as(split, 3, char *));
669              
670           }else{
671                 
672             xbt_str_strip_spaces(line);
673             split2 = xbt_str_split(line, "(");
674             xbt_dynar_remove_at(split2, 0, NULL);
675             loc_expr = xbt_str_join(split2, " ");
676             xbt_str_rtrim(loc_expr, ")");
677             frame->frame_base = MC_dwarf_get_location(NULL, loc_expr);
678             xbt_dynar_free(&split2);
679             xbt_free(loc_expr);
680
681           }
682  
683         }else if(strcmp(node_type, "DW_AT_low_pc") == 0){
684           
685           if(frame != NULL)
686             frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
687
688         }else if(strcmp(node_type, "DW_AT_high_pc") == 0){
689
690           if(frame != NULL)
691             frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
692
693         }else if(strcmp(node_type, "DW_AT_MIPS_linkage_name:") == 0){
694
695           xbt_free(frame->name);
696           xbt_free(current_frame);
697           frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));   
698           current_frame = strdup(frame->name);
699           xbt_dict_set(subprograms_origin, subprogram_start, xbt_strdup(frame->name), NULL);
700
701         }
702
703         read = xbt_getline(&line, &n, fp);
704
705       }
706  
707       if(new_frame == 1){
708         frame->start = strtoul(subprogram_start, NULL, 16);
709         if(subprogram_end != NULL)
710           frame->end = strtoul(subprogram_end, NULL, 16);
711         xbt_dict_set(*local_variables, frame->name, frame, NULL);
712       }
713
714       xbt_free(subprogram_start);
715       xbt_free(subprogram_end);
716       subprogram_end = NULL;
717         
718
719     }else if(strcmp(node_type, "(DW_TAG_variable)") == 0){ /* New variable */
720       /* We build a dw_variable_t object and append it either to
721          the list of variables of the frame (local variable)
722          or to the list of global variables (global variables). */
723
724       dw_variable_t var = NULL;
725       
726       parent_value = strdup(xbt_dynar_get_as(split, 0, char *));
727       parent_value = strtok(parent_value,"<");
728       xbt_str_rtrim(parent_value, ">");
729       parent = atoi(parent_value);
730       xbt_free(parent_value);
731
732       if(parent == 1)
733         global_variable = 1;
734     
735       strtok(xbt_dynar_get_as(split, 0, char *), "<");
736       origin = xbt_strdup(strtok(NULL, "<"));
737       xbt_str_rtrim(origin, ">:");
738       
739       read = xbt_getline(&line, &n, fp);
740       
741       while(read != -1){
742
743         /* Wipeout the new line character */
744         line[read - 1] = '\0'; 
745
746         if(n == 0 || strlen(line) == 0){
747           read = xbt_getline(&line, &n, fp);
748           continue;
749         }
750     
751         xbt_dynar_free(&split);
752         xbt_str_rtrim(line, NULL);
753         xbt_str_strip_spaces(line);
754         split = xbt_str_split(line, " ");
755   
756         node_type = xbt_dynar_get_as(split, 1, char *);
757
758         if(strncmp(node_type, "DW_AT_", 6) != 0)
759           break;
760
761         if(strcmp(node_type, "DW_AT_name") == 0){
762
763           var = xbt_new0(s_dw_variable_t, 1);
764           var->dwarf_offset = 0;
765           var->name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));
766           xbt_dict_set(variables_origin, origin, xbt_strdup(var->name), NULL);
767          
768         }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){
769
770           new_variable = 0;
771
772           abstract_origin = xbt_dynar_get_as(split, 2, char *);
773           xbt_str_ltrim(abstract_origin, "<0x");
774           xbt_str_rtrim(abstract_origin, ">");
775           
776           variable_name = (char *)xbt_dict_get_or_null(variables_origin, abstract_origin);
777           variable_frame = MC_dwarf_get_frame_by_offset(*local_variables, strtoul(abstract_origin, NULL, 16));
778           var = MC_dwarf_get_variable_by_name(variable_frame, variable_name); 
779
780         }else if(strcmp(node_type, "DW_AT_location") == 0){
781
782           if(var != NULL){
783
784             if(!global_variable){
785
786               location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
787
788               if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
789                 var->address.location = MC_dwarf_get_location(location_list, xbt_dynar_get_as(split, 3, char *));
790               }else{
791                 xbt_str_strip_spaces(line);
792                 split2 = xbt_str_split(line, "(");
793                 xbt_dynar_remove_at(split2, 0, NULL);
794                 loc_expr = xbt_str_join(split2, " ");
795                 xbt_str_rtrim(loc_expr, ")");
796                 if(strncmp("DW_OP_addr", loc_expr, 10) == 0){
797                   global_variable = 1;
798                   xbt_dynar_free(&split2);
799                   split2 = xbt_str_split(loc_expr, " ");
800                   if(strcmp(elf_file, xbt_binary_name) != 0)
801                     var->address.address = (char *) info->start_text + (long)((void *)strtoul(xbt_dynar_get_as(split2, xbt_dynar_length(split2) - 1, char*), NULL, 16));
802                   else
803                     // Why is it different ?
804                     var->address.address = (void *)strtoul(xbt_dynar_get_as(split2, xbt_dynar_length(split2) - 1, char*), NULL, 16);
805                 }else{
806                   var->address.location = MC_dwarf_get_location(NULL, loc_expr);
807                 }
808                 xbt_dynar_free(&split2);
809                 xbt_free(loc_expr);
810               }
811             }else{
812               global_address = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));
813               xbt_str_rtrim(global_address, ")");
814               if(strcmp(elf_file, xbt_binary_name) != 0)
815                 var->address.address = (char *) info->start_text + (long)((void *)strtoul(global_address, NULL, 16));
816               else
817                 // Why is it different ?
818                 var->address.address = (void *)strtoul(global_address, NULL, 16);
819               xbt_free(global_address);
820               global_address = NULL;
821             }
822
823           }
824                    
825         }else if(strcmp(node_type, "DW_AT_type") == 0){
826           
827           type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *));
828           xbt_str_ltrim(type_origin, "<0x");
829           xbt_str_rtrim(type_origin, ">");
830         
831         }else if(strcmp(node_type, "DW_AT_declaration") == 0){
832
833           new_variable = 0;
834           if(new_variable){
835             dw_variable_free(var);
836             var = NULL;
837           }
838         
839         }else if(strcmp(node_type, "DW_AT_artificial") == 0){
840           
841           new_variable = 0;
842           if(new_variable){
843             dw_variable_free(var);
844             var = NULL;
845           }
846         
847         }
848
849         read = xbt_getline(&line, &n, fp);
850  
851       }
852
853       if(new_variable == 1){
854         
855         if(!global_variable){
856           variable_frame = xbt_dict_get_or_null(*local_variables, current_frame);
857           var->type_origin = strdup(type_origin);
858           var->global = 0;
859           index = MC_dwarf_get_variable_index(variable_frame->variables, var->name, NULL);
860           if(index != -1)
861             xbt_dynar_insert_at(variable_frame->variables, index, &var);
862         }else{
863           var->type_origin = strdup(type_origin);
864           var->global = 1;
865           index = MC_dwarf_get_variable_index(*global_variables, var->name, var->address.address);
866           if(index != -1)
867             xbt_dynar_insert_at(*global_variables, index, &var); 
868         }
869
870          xbt_free(type_origin);
871          type_origin = NULL;
872       }
873
874       global_variable = 0;
875       new_variable = 1;
876
877     }else if(strcmp(node_type, "(DW_TAG_inlined_subroutine)") == 0){
878       /* Update the information on the frame (we should duplicate it instead). */
879
880       read = xbt_getline(&line, &n, fp);
881
882       while(read != -1){
883
884         /* Wipeout the new line character */
885         line[read - 1] = '\0'; 
886
887         if(n == 0 || strlen(line) == 0){
888           read = xbt_getline(&line, &n, fp);
889           continue;
890         }
891
892         xbt_dynar_free(&split);
893         xbt_str_rtrim(line, NULL);
894         xbt_str_strip_spaces(line);
895         split = xbt_str_split(line, " ");
896         
897         if(strncmp(xbt_dynar_get_as(split, 1, char *), "DW_AT_", 6) != 0)
898           break;
899           
900         node_type = xbt_dynar_get_as(split, 1, char *);
901
902         if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){
903
904           origin = xbt_dynar_get_as(split, 2, char *);
905           xbt_str_ltrim(origin, "<0x");
906           xbt_str_rtrim(origin, ">");
907           
908           subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, origin);
909           subroutine_frame = xbt_dict_get_or_null(*local_variables, subprogram_name);
910         
911         }else if(strcmp(node_type, "DW_AT_low_pc") == 0){
912
913           subroutine_frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
914
915         }else if(strcmp(node_type, "DW_AT_high_pc") == 0){
916
917           subroutine_frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
918         }
919
920         read = xbt_getline(&line, &n, fp);
921       
922       }
923
924     }else if(!MC_USE_LIBDW_TYPES&&(strcmp(node_type, "(DW_TAG_base_type)") == 0
925              || strcmp(node_type, "(DW_TAG_enumeration_type)") == 0
926              || strcmp(node_type, "(DW_TAG_typedef)") == 0
927              || strcmp(node_type, "(DW_TAG_const_type)") == 0
928              || strcmp(node_type, "(DW_TAG_subroutine_type)") == 0
929              || strcmp(node_type, "(DW_TAG_volatile_type)") == 0
930              || (is_pointer = !strcmp(node_type, "(DW_TAG_pointer_type)")))){
931
932       /* Create the and add it to the types dictionnary */
933
934       if(strcmp(node_type, "(DW_TAG_base_type)") == 0)
935         type_type = DW_TAG_base_type;
936       else if(strcmp(node_type, "(DW_TAG_enumeration_type)") == 0)
937         type_type = DW_TAG_enumeration_type;
938       else if(strcmp(node_type, "(DW_TAG_typedef)") == 0)
939         type_type = DW_TAG_typedef;
940       else if(strcmp(node_type, "(DW_TAG_const_type)") == 0)
941         type_type = DW_TAG_const_type;
942       else if(strcmp(node_type, "(DW_TAG_pointer_type)") == 0)
943         type_type = DW_TAG_pointer_type;
944       else if(strcmp(node_type, "(DW_TAG_subroutine_type)") == 0)
945         type_type = DW_TAG_subroutine_type;
946       else if(strcmp(node_type, "(DW_TAG_volatile_type)") == 0)
947         type_type = DW_TAG_volatile_type;
948
949       strtok(xbt_dynar_get_as(split, 0, char *), "<");
950       origin = strdup(strtok(NULL, "<"));
951       xbt_str_rtrim(origin, ">:");
952       
953       read = xbt_getline(&line, &n, fp);
954       
955       while(read != -1){
956         
957          /* Wipeout the new line character */
958         line[read - 1] = '\0'; 
959
960         if(n == 0 || strlen(line) == 0){
961           read = xbt_getline(&line, &n, fp);
962           continue;
963         }
964
965         xbt_dynar_free(&split);
966         xbt_str_rtrim(line, NULL);
967         xbt_str_strip_spaces(line);
968         split = xbt_str_split(line, " ");
969         
970         if(strncmp(xbt_dynar_get_as(split, 1, char *), "DW_AT_", 6) != 0)
971           break;
972
973         node_type = xbt_dynar_get_as(split, 1, char *);
974
975         if(strcmp(node_type, "DW_AT_byte_size") == 0){
976           size = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10);
977           if(type_type == DW_TAG_enumeration_type)
978             enumeration_size = size;
979         }else if(strcmp(node_type, "DW_AT_name") == 0){
980           end = xbt_str_join(split, " ");
981           xbt_dynar_free(&split);
982           split = xbt_str_split(end, "):");
983           xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL);
984           name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*));
985         }else if(strcmp(node_type, "DW_AT_type") == 0){
986           type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *));
987           xbt_str_ltrim(type_origin, "<0x");
988           xbt_str_rtrim(type_origin, ">");
989         }
990         
991         read = xbt_getline(&line, &n, fp);
992       }
993
994       dw_type_t type = xbt_new0(s_dw_type_t, 1);
995       type->type = type_type;
996       if(name)
997         type->name = xbt_strdup(name);
998       else
999         type->name = xbt_strdup("undefined");
1000       type->is_pointer_type = is_pointer;
1001       type->id = (void *)strtoul(origin, NULL, 16);
1002       if(type_origin)
1003         type->dw_type_id = xbt_strdup(type_origin);
1004
1005       type->byte_size = size;
1006       // Not relevant:
1007       type->element_count = -1;
1008
1009       type->members = NULL;
1010
1011       xbt_dict_set(*types, origin, type, NULL); 
1012
1013       xbt_free(name);
1014       name = NULL;
1015       xbt_free(type_origin);
1016       type_origin = NULL;
1017       xbt_free(end);
1018       end = NULL;
1019
1020       is_pointer = 0;
1021       size = 0;
1022       xbt_free(origin);
1023
1024     }else if(strcmp(node_type, "(DW_TAG_structure_type)") == 0 || strcmp(node_type, "(DW_TAG_union_type)") == 0){
1025       
1026       if(strcmp(node_type, "(DW_TAG_structure_type)") == 0)
1027         struct_decl = 1;
1028       else
1029         union_decl = 1;
1030
1031       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1032       origin = strdup(strtok(NULL, "<"));
1033       xbt_str_rtrim(origin, ">:");
1034       
1035       read = xbt_getline(&line, &n, fp);
1036
1037       dw_type_t type = NULL;
1038
1039       while(read != -1){
1040       
1041         while(read != -1){
1042         
1043           /* Wipeout the new line character */
1044           line[read - 1] = '\0'; 
1045
1046           if(n == 0 || strlen(line) == 0){
1047             read = xbt_getline(&line, &n, fp);
1048             continue;
1049           }
1050
1051           xbt_dynar_free(&split);
1052           xbt_str_rtrim(line, NULL);
1053           xbt_str_strip_spaces(line);
1054           split = xbt_str_split(line, " ");
1055         
1056           node_type = xbt_dynar_get_as(split, 1, char *);
1057
1058           if(strncmp(node_type, "DW_AT_", 6) != 0){
1059             member_end = 1;
1060             break;
1061           }
1062
1063           if(strcmp(node_type, "DW_AT_byte_size") == 0){
1064             size = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10);
1065           }else if(strcmp(node_type, "DW_AT_name") == 0){
1066             xbt_free(end);
1067             end = xbt_str_join(split, " ");
1068             xbt_dynar_free(&split);
1069             split = xbt_str_split(end, "):");
1070             xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL);
1071             name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*));
1072           }else if(strcmp(node_type, "DW_AT_type") == 0){
1073             type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *));
1074             xbt_str_ltrim(type_origin, "<0x");
1075             xbt_str_rtrim(type_origin, ">");
1076           }else if(strcmp(node_type, "DW_AT_data_member_location:") == 0){
1077             xbt_free(end);
1078             end = xbt_str_join(split, " ");
1079             xbt_dynar_free(&split);
1080             split = xbt_str_split(end, "DW_OP_plus_uconst:");
1081             xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), NULL);
1082             xbt_str_rtrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), ")");
1083             offset = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10);
1084           }
1085
1086           read = xbt_getline(&line, &n, fp);
1087           
1088         }
1089
1090         if(member_end && type){         
1091           member_end = 0;
1092           
1093           // Why are we not simply referencing, the DW_AT_type?
1094           dw_type_t member_type = xbt_new0(s_dw_type_t, 1);
1095           member_type->name = xbt_strdup(name);
1096           member_type->byte_size = size;
1097           member_type->element_count = -1;
1098           member_type->is_pointer_type = is_pointer;
1099           member_type->id = (void *)strtoul(origin, NULL, 16);
1100           member_type->offset = offset;
1101           if(type_origin)
1102             member_type->dw_type_id = xbt_strdup(type_origin);
1103
1104           xbt_dynar_push(type->members, &member_type);
1105
1106           xbt_free(name);
1107           name = NULL;
1108           xbt_free(end);
1109           end = NULL;
1110           xbt_free(type_origin);
1111           type_origin = NULL;
1112           size = 0;
1113           offset = 0;
1114
1115           xbt_free(origin);
1116           origin = NULL;
1117           strtok(xbt_dynar_get_as(split, 0, char *), "<");
1118           origin = strdup(strtok(NULL, "<"));
1119           xbt_str_rtrim(origin, ">:");
1120
1121         }
1122
1123         if(struct_decl || union_decl){
1124           type = xbt_new0(s_dw_type_t, 1);
1125           if(struct_decl)
1126             type->type = DW_TAG_structure_type;
1127           else
1128             type->type = DW_TAG_union_type;
1129           type->name = xbt_strdup(name);
1130           type->byte_size = size;
1131           type->element_count = -1;
1132           type->is_pointer_type = is_pointer;
1133           type->id = (void *)strtoul(origin, NULL, 16);
1134           if(type_origin)
1135             type->dw_type_id = xbt_strdup(type_origin);
1136           type->members = xbt_dynar_new(sizeof(dw_type_t), dw_type_free_voidp);
1137           
1138           xbt_dict_set(*types, origin, type, NULL); 
1139           
1140           xbt_free(name);
1141           name = NULL;
1142           xbt_free(end);
1143           end = NULL;
1144           xbt_free(type_origin);
1145           type_origin = NULL;
1146           size = 0;
1147           struct_decl = 0;
1148           union_decl = 0;
1149
1150         }
1151
1152         if(strcmp(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), "(DW_TAG_member)") != 0)
1153           break;  
1154
1155         read = xbt_getline(&line, &n, fp);
1156     
1157       }
1158
1159       xbt_free(origin);
1160       origin = NULL;
1161
1162     }else if(strcmp(node_type, "(DW_TAG_array_type)") == 0){
1163       
1164       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1165       origin = strdup(strtok(NULL, "<"));
1166       xbt_str_rtrim(origin, ">:");
1167       
1168       read = xbt_getline(&line, &n, fp);
1169
1170       dw_type_t type = NULL;
1171
1172       // Read DW_TAG_subrange_type children:
1173       while(read != -1){
1174       
1175         // Read attributes of the DW_TAG_subrange_type:
1176         while(read != -1){
1177         
1178           /* Wipeout the new line character */
1179           line[read - 1] = '\0'; 
1180
1181           if(n == 0 || strlen(line) == 0){
1182             read = xbt_getline(&line, &n, fp);
1183             continue;
1184           }
1185
1186           xbt_dynar_free(&split);
1187           xbt_str_rtrim(line, NULL);
1188           xbt_str_strip_spaces(line);
1189           split = xbt_str_split(line, " ");
1190         
1191           node_type = xbt_dynar_get_as(split, 1, char *);
1192
1193           if(strncmp(node_type, "DW_AT_", 6) != 0)
1194             break;
1195
1196           if(strcmp(node_type, "DW_AT_upper_bound") == 0){
1197             size = strtol(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL, 10);
1198           }else if(strcmp(node_type, "DW_AT_name") == 0){
1199             end = xbt_str_join(split, " ");
1200             xbt_dynar_free(&split);
1201             split = xbt_str_split(end, "):");
1202             xbt_str_ltrim(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*), NULL);
1203             name = xbt_strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char*));
1204           }else if(strcmp(node_type, "DW_AT_type") == 0){
1205             type_origin = xbt_strdup(xbt_dynar_get_as(split, 3, char *));
1206             xbt_str_ltrim(type_origin, "<0x");
1207             xbt_str_rtrim(type_origin, ">");
1208           }
1209
1210           read = xbt_getline(&line, &n, fp);
1211           
1212         }
1213
1214         if(strcmp(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), "(DW_TAG_subrange_type)") == 0){
1215           subrange = 1;         
1216         }
1217
1218         if(subrange && type){         
1219           type->element_count = size;
1220
1221           xbt_free(name);
1222           name = NULL;
1223           xbt_free(end);
1224           end = NULL;
1225           xbt_free(type_origin);
1226           type_origin = NULL;
1227           size = 0;
1228
1229           xbt_free(origin);
1230           origin = NULL;
1231           strtok(xbt_dynar_get_as(split, 0, char *), "<");
1232           origin = strdup(strtok(NULL, "<"));
1233           xbt_str_rtrim(origin, ">:");
1234
1235         }else {
1236           
1237           type = xbt_new0(s_dw_type_t, 1);
1238           type->type = DW_TAG_array_type;
1239           type->name = xbt_strdup(name);
1240           type->is_pointer_type = is_pointer;
1241           type->id = (void *)strtoul(origin, NULL, 16);
1242           if(type_origin)
1243             type->dw_type_id = xbt_strdup(type_origin);
1244           type->members = NULL;
1245
1246           // Filled in a post processing step:
1247           type-> byte_size = 0;
1248           
1249           xbt_dict_set(*types, origin, type, NULL); 
1250           
1251           xbt_free(name);
1252           name = NULL;
1253           xbt_free(end);
1254           end = NULL;
1255           xbt_free(type_origin);
1256           type_origin = NULL;
1257           size = 0;
1258         }
1259
1260         if(strcmp(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *), "(DW_TAG_subrange_type)") != 0)
1261           break;  
1262
1263         read = xbt_getline(&line, &n, fp);
1264     
1265       }
1266
1267       xbt_free(origin);
1268       origin = NULL;
1269
1270     }else{
1271
1272       read = xbt_getline(&line, &n, fp);
1273
1274     }
1275
1276   }
1277   
1278   xbt_dynar_free(&split);
1279   xbt_dict_free(&variables_origin);
1280   xbt_dict_free(&subprograms_origin);
1281   xbt_free(line);
1282   xbt_free(command);
1283   xbt_dict_free(&location_list);
1284
1285   pclose(fp);
1286
1287   MC_post_process_types(info);
1288 }
1289
1290 static void MC_post_process_array_size(mc_object_info_t info, dw_type_t type) {
1291   xbt_assert(type->dw_type_id, "No base type for array <%p>%s", type->id, type->name);
1292   dw_type_t subtype = xbt_dict_get_or_null(info->types, type->dw_type_id);
1293   xbt_assert(subtype, "Unkown base type <%s> for array <%p>%s", type->dw_type_id, type->id, type->name);
1294   if(subtype->type==DW_TAG_array_type && type->byte_size==0) {
1295           MC_post_process_array_size(info, subtype);
1296   }
1297   type->byte_size = type->element_count*subtype->byte_size;
1298 }
1299
1300 static void MC_post_process_types(mc_object_info_t info) {
1301   xbt_dict_cursor_t cursor;
1302   char *origin;
1303   dw_type_t type;
1304   xbt_dict_foreach(info->types, cursor, origin, type){
1305     if(type->type==DW_TAG_array_type && type->byte_size==0)
1306       MC_post_process_array_size(info, type);
1307   }
1308 }
1309
1310 /*******************************  Ignore mechanism *******************************/
1311 /*********************************************************************************/
1312
1313 xbt_dynar_t mc_checkpoint_ignore;
1314
1315 typedef struct s_mc_stack_ignore_variable{
1316   char *var_name;
1317   char *frame;
1318 }s_mc_stack_ignore_variable_t, *mc_stack_ignore_variable_t;
1319
1320 typedef struct s_mc_data_bss_ignore_variable{
1321   char *name;
1322 }s_mc_data_bss_ignore_variable_t, *mc_data_bss_ignore_variable_t;
1323
1324 /**************************** Free functions ******************************/
1325
1326 static void stack_ignore_variable_free(mc_stack_ignore_variable_t v){
1327   xbt_free(v->var_name);
1328   xbt_free(v->frame);
1329   xbt_free(v);
1330 }
1331
1332 static void stack_ignore_variable_free_voidp(void *v){
1333   stack_ignore_variable_free((mc_stack_ignore_variable_t) * (void **) v);
1334 }
1335
1336 void heap_ignore_region_free(mc_heap_ignore_region_t r){
1337   xbt_free(r);
1338 }
1339
1340 void heap_ignore_region_free_voidp(void *r){
1341   heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
1342 }
1343
1344 static void data_bss_ignore_variable_free(mc_data_bss_ignore_variable_t v){
1345   xbt_free(v->name);
1346   xbt_free(v);
1347 }
1348
1349 static void data_bss_ignore_variable_free_voidp(void *v){
1350   data_bss_ignore_variable_free((mc_data_bss_ignore_variable_t) * (void **) v);
1351 }
1352
1353 static void checkpoint_ignore_region_free(mc_checkpoint_ignore_region_t r){
1354   xbt_free(r);
1355 }
1356
1357 static void checkpoint_ignore_region_free_voidp(void *r){
1358   checkpoint_ignore_region_free((mc_checkpoint_ignore_region_t) * (void **) r);
1359 }
1360
1361 /***********************************************************************/
1362
1363 void MC_ignore_heap(void *address, size_t size){
1364
1365   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1366
1367   MC_SET_RAW_MEM;
1368
1369   mc_heap_ignore_region_t region = NULL;
1370   region = xbt_new0(s_mc_heap_ignore_region_t, 1);
1371   region->address = address;
1372   region->size = size;
1373   
1374   region->block = ((char*)address - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
1375   
1376   if(((xbt_mheap_t)std_heap)->heapinfo[region->block].type == 0){
1377     region->fragment = -1;
1378     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore++;
1379   }else{
1380     region->fragment = ((uintptr_t) (ADDR2UINT (address) % (BLOCKSIZE))) >> ((xbt_mheap_t)std_heap)->heapinfo[region->block].type;
1381     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
1382   }
1383   
1384   if(mc_heap_comparison_ignore == NULL){
1385     mc_heap_comparison_ignore = xbt_dynar_new(sizeof(mc_heap_ignore_region_t), heap_ignore_region_free_voidp);
1386     xbt_dynar_push(mc_heap_comparison_ignore, &region);
1387     if(!raw_mem_set)
1388       MC_UNSET_RAW_MEM;
1389     return;
1390   }
1391
1392   unsigned int cursor = 0;
1393   mc_heap_ignore_region_t current_region = NULL;
1394   int start = 0;
1395   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
1396   
1397   while(start <= end){
1398     cursor = (start + end) / 2;
1399     current_region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
1400     if(current_region->address == address){
1401       heap_ignore_region_free(region);
1402       if(!raw_mem_set)
1403         MC_UNSET_RAW_MEM;
1404       return;
1405     }else if(current_region->address < address){
1406       start = cursor + 1;
1407     }else{
1408       end = cursor - 1;
1409     }   
1410   }
1411
1412   if(current_region->address < address)
1413     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
1414   else
1415     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
1416
1417   if(!raw_mem_set)
1418     MC_UNSET_RAW_MEM;
1419 }
1420
1421 void MC_remove_ignore_heap(void *address, size_t size){
1422
1423   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1424
1425   MC_SET_RAW_MEM;
1426
1427   unsigned int cursor = 0;
1428   int start = 0;
1429   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
1430   mc_heap_ignore_region_t region;
1431   int ignore_found = 0;
1432
1433   while(start <= end){
1434     cursor = (start + end) / 2;
1435     region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
1436     if(region->address == address){
1437       ignore_found = 1;
1438       break;
1439     }else if(region->address < address){
1440       start = cursor + 1;
1441     }else{
1442       if((char * )region->address <= ((char *)address + size)){
1443         ignore_found = 1;
1444         break;
1445       }else{
1446         end = cursor - 1;   
1447       }
1448     }
1449   }
1450   
1451   if(ignore_found == 1){
1452     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
1453     MC_remove_ignore_heap(address, size);
1454   }
1455
1456   if(!raw_mem_set)
1457     MC_UNSET_RAW_MEM;
1458
1459 }
1460
1461 void MC_ignore_global_variable(const char *name){
1462
1463   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1464
1465   MC_SET_RAW_MEM;
1466
1467   if(mc_libsimgrid_info){
1468
1469     unsigned int cursor = 0;
1470     dw_variable_t current_var;
1471     int start = 0;
1472     int end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
1473
1474     while(start <= end){
1475       cursor = (start + end) /2;
1476       current_var = (dw_variable_t)xbt_dynar_get_as(mc_libsimgrid_info->global_variables, cursor, dw_variable_t);
1477       if(strcmp(current_var->name, name) == 0){
1478         xbt_dynar_remove_at(mc_libsimgrid_info->global_variables, cursor, NULL);
1479         start = 0;
1480         end = xbt_dynar_length(mc_libsimgrid_info->global_variables) - 1;
1481       }else if(strcmp(current_var->name, name) < 0){
1482         start = cursor + 1;
1483       }else{
1484         end = cursor - 1;
1485       } 
1486     }
1487    
1488   }else{
1489
1490     if(mc_data_bss_comparison_ignore == NULL)
1491       mc_data_bss_comparison_ignore = xbt_dynar_new(sizeof(mc_data_bss_ignore_variable_t), data_bss_ignore_variable_free_voidp);
1492
1493     mc_data_bss_ignore_variable_t var = NULL;
1494     var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1);
1495     var->name = strdup(name);
1496
1497     if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){
1498
1499       xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var);
1500
1501     }else{
1502     
1503       unsigned int cursor = 0;
1504       int start = 0;
1505       int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
1506       mc_data_bss_ignore_variable_t current_var = NULL;
1507
1508       while(start <= end){
1509         cursor = (start + end) / 2;
1510         current_var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
1511         if(strcmp(current_var->name, name) == 0){
1512           data_bss_ignore_variable_free(var);
1513           if(!raw_mem_set)
1514             MC_UNSET_RAW_MEM;
1515           return;
1516         }else if(strcmp(current_var->name, name) < 0){
1517           start = cursor + 1;
1518         }else{
1519           end = cursor - 1;
1520         }
1521       }
1522
1523       if(strcmp(current_var->name, name) < 0)
1524         xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor + 1, &var);
1525       else
1526         xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor, &var);
1527
1528     }
1529   }
1530
1531   if(!raw_mem_set)
1532     MC_UNSET_RAW_MEM;
1533 }
1534
1535 void MC_ignore_local_variable(const char *var_name, const char *frame_name){
1536   
1537   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1538
1539   MC_SET_RAW_MEM;
1540
1541   if(mc_libsimgrid_info){
1542     unsigned int cursor = 0;
1543     dw_variable_t current_var;
1544     int start, end;
1545     if(strcmp(frame_name, "*") == 0){ /* Remove variable in all frames */
1546       xbt_dict_cursor_t dict_cursor;
1547       char *current_frame_name;
1548       dw_frame_t frame;
1549       xbt_dict_foreach(mc_libsimgrid_info->local_variables, dict_cursor, current_frame_name, frame){
1550         start = 0;
1551         end = xbt_dynar_length(frame->variables) - 1;
1552         while(start <= end){
1553           cursor = (start + end) / 2;
1554           current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
1555           if(strcmp(current_var->name, var_name) == 0){
1556             xbt_dynar_remove_at(frame->variables, cursor, NULL);
1557             start = 0;
1558             end = xbt_dynar_length(frame->variables) - 1;
1559           }else if(strcmp(current_var->name, var_name) < 0){
1560             start = cursor + 1;
1561           }else{
1562             end = cursor - 1;
1563           } 
1564         }
1565       }
1566        xbt_dict_foreach(mc_binary_info->local_variables, dict_cursor, current_frame_name, frame){
1567         start = 0;
1568         end = xbt_dynar_length(frame->variables) - 1;
1569         while(start <= end){
1570           cursor = (start + end) / 2;
1571           current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
1572           if(strcmp(current_var->name, var_name) == 0){
1573             xbt_dynar_remove_at(frame->variables, cursor, NULL);
1574             start = 0;
1575             end = xbt_dynar_length(frame->variables) - 1;
1576           }else if(strcmp(current_var->name, var_name) < 0){
1577             start = cursor + 1;
1578           }else{
1579             end = cursor - 1;
1580           } 
1581         }
1582       }
1583     }else{
1584       xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(
1585                                       mc_libsimgrid_info->local_variables, frame_name))->variables;
1586       start = 0;
1587       end = xbt_dynar_length(variables_list) - 1;
1588       while(start <= end){
1589         cursor = (start + end) / 2;
1590         current_var = (dw_variable_t)xbt_dynar_get_as(variables_list, cursor, dw_variable_t);
1591         if(strcmp(current_var->name, var_name) == 0){
1592           xbt_dynar_remove_at(variables_list, cursor, NULL);
1593           start = 0;
1594           end = xbt_dynar_length(variables_list) - 1;
1595         }else if(strcmp(current_var->name, var_name) < 0){
1596           start = cursor + 1;
1597         }else{
1598           end = cursor - 1;
1599         } 
1600       }
1601     } 
1602   }else{
1603
1604     if(mc_stack_comparison_ignore == NULL)
1605       mc_stack_comparison_ignore = xbt_dynar_new(sizeof(mc_stack_ignore_variable_t), stack_ignore_variable_free_voidp);
1606   
1607     mc_stack_ignore_variable_t var = NULL;
1608     var = xbt_new0(s_mc_stack_ignore_variable_t, 1);
1609     var->var_name = strdup(var_name);
1610     var->frame = strdup(frame_name);
1611   
1612     if(xbt_dynar_is_empty(mc_stack_comparison_ignore)){
1613
1614       xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var);
1615
1616     }else{
1617     
1618       unsigned int cursor = 0;
1619       int start = 0;
1620       int end = xbt_dynar_length(mc_stack_comparison_ignore) - 1;
1621       mc_stack_ignore_variable_t current_var = NULL;
1622
1623       while(start <= end){
1624         cursor = (start + end) / 2;
1625         current_var = (mc_stack_ignore_variable_t)xbt_dynar_get_as(mc_stack_comparison_ignore, cursor, mc_stack_ignore_variable_t);
1626         if(strcmp(current_var->frame, frame_name) == 0){
1627           if(strcmp(current_var->var_name, var_name) == 0){
1628             stack_ignore_variable_free(var);
1629             if(!raw_mem_set)
1630               MC_UNSET_RAW_MEM;
1631             return;
1632           }else if(strcmp(current_var->var_name, var_name) < 0){
1633             start = cursor + 1;
1634           }else{
1635             end = cursor - 1;
1636           }
1637         }else if(strcmp(current_var->frame, frame_name) < 0){
1638           start = cursor + 1;
1639         }else{
1640           end = cursor - 1;
1641         }
1642       }
1643
1644       if(strcmp(current_var->frame, frame_name) == 0){
1645         if(strcmp(current_var->var_name, var_name) < 0){
1646           xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
1647         }else{
1648           xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
1649         }
1650       }else if(strcmp(current_var->frame, frame_name) < 0){
1651         xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
1652       }else{
1653         xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
1654       }
1655     }
1656   }
1657
1658   if(!raw_mem_set)
1659     MC_UNSET_RAW_MEM;
1660
1661 }
1662
1663 void MC_new_stack_area(void *stack, char *name, void* context, size_t size){
1664
1665   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1666
1667   MC_SET_RAW_MEM;
1668
1669   if(stacks_areas == NULL)
1670     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
1671   
1672   stack_region_t region = NULL;
1673   region = xbt_new0(s_stack_region_t, 1);
1674   region->address = stack;
1675   region->process_name = strdup(name);
1676   region->context = context;
1677   region->size = size;
1678   region->block = ((char*)stack - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
1679   xbt_dynar_push(stacks_areas, &region);
1680
1681   if(!raw_mem_set)
1682     MC_UNSET_RAW_MEM;
1683 }
1684
1685 void MC_ignore(void *addr, size_t size){
1686
1687   int raw_mem_set= (mmalloc_get_current_heap() == raw_heap);
1688
1689   MC_SET_RAW_MEM;
1690
1691   if(mc_checkpoint_ignore == NULL)
1692     mc_checkpoint_ignore = xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t), checkpoint_ignore_region_free_voidp);
1693
1694   mc_checkpoint_ignore_region_t region = xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
1695   region->addr = addr;
1696   region->size = size;
1697
1698   if(xbt_dynar_is_empty(mc_checkpoint_ignore)){
1699     xbt_dynar_push(mc_checkpoint_ignore, &region);
1700   }else{
1701      
1702     unsigned int cursor = 0;
1703     int start = 0;
1704     int end = xbt_dynar_length(mc_checkpoint_ignore) -1;
1705     mc_checkpoint_ignore_region_t current_region = NULL;
1706
1707     while(start <= end){
1708       cursor = (start + end) / 2;
1709       current_region = (mc_checkpoint_ignore_region_t)xbt_dynar_get_as(mc_checkpoint_ignore, cursor, mc_checkpoint_ignore_region_t);
1710       if(current_region->addr == addr){
1711         if(current_region->size == size){
1712           checkpoint_ignore_region_free(region);
1713           if(!raw_mem_set)
1714             MC_UNSET_RAW_MEM;
1715           return;
1716         }else if(current_region->size < size){
1717           start = cursor + 1;
1718         }else{
1719           end = cursor - 1;
1720         }
1721       }else if(current_region->addr < addr){
1722           start = cursor + 1;
1723       }else{
1724         end = cursor - 1;
1725       }
1726     }
1727
1728      if(current_region->addr == addr){
1729        if(current_region->size < size){
1730         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
1731       }else{
1732         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
1733       }
1734     }else if(current_region->addr < addr){
1735        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
1736     }else{
1737        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
1738     }
1739   }
1740
1741   if(!raw_mem_set)
1742     MC_UNSET_RAW_MEM;
1743 }
1744
1745 /*******************************  Initialisation of MC *******************************/
1746 /*********************************************************************************/
1747
1748 static void MC_dump_ignored_local_variables(void){
1749
1750   if(mc_stack_comparison_ignore == NULL || xbt_dynar_is_empty(mc_stack_comparison_ignore))
1751     return;
1752
1753   unsigned int cursor = 0;
1754   mc_stack_ignore_variable_t current_var;
1755
1756   xbt_dynar_foreach(mc_stack_comparison_ignore, cursor, current_var){
1757     MC_ignore_local_variable(current_var->var_name, current_var->frame);
1758   }
1759
1760   xbt_dynar_free(&mc_stack_comparison_ignore);
1761   mc_stack_comparison_ignore = NULL;
1762  
1763 }
1764
1765 static void MC_dump_ignored_global_variables(void){
1766
1767   if(mc_data_bss_comparison_ignore == NULL || xbt_dynar_is_empty(mc_data_bss_comparison_ignore))
1768     return;
1769
1770   unsigned int cursor = 0;
1771   mc_data_bss_ignore_variable_t current_var;
1772
1773   xbt_dynar_foreach(mc_data_bss_comparison_ignore, cursor, current_var){
1774     MC_ignore_global_variable(current_var->name);
1775   } 
1776
1777   xbt_dynar_free(&mc_data_bss_comparison_ignore);
1778   mc_data_bss_comparison_ignore = NULL;
1779
1780 }
1781
1782 static void MC_init_debug_info();
1783 static void MC_init_debug_info() {
1784   XBT_INFO("Get debug information ...");
1785
1786   memory_map_t maps = MC_get_memory_map();
1787
1788   /* Get local variables for state equality detection */
1789   mc_binary_info = MC_find_object_info(maps, xbt_binary_name);
1790   mc_libsimgrid_info = MC_find_object_info(maps, libsimgrid_path);
1791
1792   MC_free_memory_map(maps);
1793   XBT_INFO("Get debug information done !");
1794 }
1795
1796 void MC_init(){
1797
1798   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1799
1800   compare = 0;
1801
1802   /* Initialize the data structures that must be persistent across every
1803      iteration of the model-checker (in RAW memory) */
1804
1805   MC_SET_RAW_MEM;
1806
1807   MC_init_memory_map_info();
1808   MC_init_debug_info();
1809
1810   /* Remove variables ignored before getting list of variables */
1811   MC_dump_ignored_local_variables();
1812   MC_dump_ignored_global_variables();
1813
1814    /* Init parmap */
1815   parmap = xbt_parmap_mc_new(xbt_os_get_numcores(), XBT_PARMAP_DEFAULT);
1816
1817   MC_UNSET_RAW_MEM;
1818
1819    /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
1820   MC_ignore_local_variable("e", "*");
1821   MC_ignore_local_variable("__ex_cleanup", "*");
1822   MC_ignore_local_variable("__ex_mctx_en", "*");
1823   MC_ignore_local_variable("__ex_mctx_me", "*");
1824   MC_ignore_local_variable("__xbt_ex_ctx_ptr", "*");
1825   MC_ignore_local_variable("_log_ev", "*");
1826   MC_ignore_local_variable("_throw_ctx", "*");
1827   MC_ignore_local_variable("ctx", "*");
1828
1829   MC_ignore_local_variable("next_context", "smx_ctx_sysv_suspend_serial");
1830   MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
1831
1832   /* Ignore local variable about time used for tracing */
1833   MC_ignore_local_variable("start_time", "*"); 
1834
1835   MC_ignore_global_variable("mc_comp_times");
1836   MC_ignore_global_variable("mc_snapshot_comparison_time"); 
1837   MC_ignore_global_variable("mc_time");
1838   MC_ignore_global_variable("smpi_current_rank");
1839   MC_ignore_global_variable("counter"); /* Static variable used for tracing */
1840   MC_ignore_global_variable("maestro_stack_start");
1841   MC_ignore_global_variable("maestro_stack_end");
1842
1843   MC_ignore_heap(&(simix_global->process_to_run), sizeof(simix_global->process_to_run));
1844   MC_ignore_heap(&(simix_global->process_that_ran), sizeof(simix_global->process_that_ran));
1845   MC_ignore_heap(simix_global->process_to_run, sizeof(*(simix_global->process_to_run)));
1846   MC_ignore_heap(simix_global->process_that_ran, sizeof(*(simix_global->process_that_ran)));
1847   
1848   smx_process_t process;
1849   xbt_swag_foreach(process, simix_global->process_list){
1850     MC_ignore_heap(&(process->process_hookup), sizeof(process->process_hookup));
1851   }
1852
1853   if(raw_mem_set)
1854     MC_SET_RAW_MEM;
1855
1856 }
1857
1858 static void MC_init_dot_output(){ /* FIXME : more colors */
1859
1860   colors[0] = "blue";
1861   colors[1] = "red";
1862   colors[2] = "green3";
1863   colors[3] = "goldenrod";
1864   colors[4] = "brown";
1865   colors[5] = "purple";
1866   colors[6] = "magenta";
1867   colors[7] = "turquoise4";
1868   colors[8] = "gray25";
1869   colors[9] = "forestgreen";
1870   colors[10] = "hotpink";
1871   colors[11] = "lightblue";
1872   colors[12] = "tan";
1873
1874   dot_output = fopen(_sg_mc_dot_output_file, "w");
1875   
1876   if(dot_output == NULL){
1877     perror("Error open dot output file");
1878     xbt_abort();
1879   }
1880
1881   fprintf(dot_output, "digraph graphname{\n fixedsize=true; rankdir=TB; ranksep=.25; edge [fontsize=12]; node [fontsize=10, shape=circle,width=.5 ]; graph [resolution=20, fontsize=10];\n");
1882
1883 }
1884
1885 /*******************************  Core of MC *******************************/
1886 /**************************************************************************/
1887
1888 void MC_do_the_modelcheck_for_real() {
1889
1890   MC_SET_RAW_MEM;
1891   mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
1892   MC_UNSET_RAW_MEM;
1893   
1894   if (!_sg_mc_property_file || _sg_mc_property_file[0]=='\0') {
1895     if (mc_reduce_kind==e_mc_reduce_unset)
1896       mc_reduce_kind=e_mc_reduce_dpor;
1897
1898     XBT_INFO("Check a safety property");
1899     MC_modelcheck_safety();
1900
1901   } else  {
1902
1903     if (mc_reduce_kind==e_mc_reduce_unset)
1904       mc_reduce_kind=e_mc_reduce_none;
1905
1906     XBT_INFO("Check the liveness property %s",_sg_mc_property_file);
1907     MC_automaton_load(_sg_mc_property_file);
1908     MC_modelcheck_liveness();
1909   }
1910 }
1911
1912 void MC_modelcheck_safety(void)
1913 {
1914   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1915
1916   /* Check if MC is already initialized */
1917   if (initial_state_safety)
1918     return;
1919
1920   mc_time = xbt_new0(double, simix_process_maxpid);
1921
1922   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
1923   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
1924
1925   /* Initialize the data structures that must be persistent across every
1926      iteration of the model-checker (in RAW memory) */
1927   
1928   MC_SET_RAW_MEM;
1929
1930   /* Initialize statistics */
1931   mc_stats = xbt_new0(s_mc_stats_t, 1);
1932   mc_stats->state_size = 1;
1933
1934   /* Create exploration stack */
1935   mc_stack_safety = xbt_fifo_new();
1936
1937   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
1938     MC_init_dot_output();
1939
1940   MC_UNSET_RAW_MEM;
1941
1942   if(_sg_mc_visited > 0){
1943     MC_init();
1944   }else{
1945     MC_SET_RAW_MEM;
1946     MC_init_memory_map_info();
1947     MC_init_debug_info();
1948     MC_UNSET_RAW_MEM;
1949   }
1950
1951   MC_dpor_init();
1952
1953   MC_SET_RAW_MEM;
1954   /* Save the initial state */
1955   initial_state_safety = xbt_new0(s_mc_global_t, 1);
1956   initial_state_safety->snapshot = MC_take_snapshot(0);
1957   MC_UNSET_RAW_MEM;
1958
1959   MC_dpor();
1960
1961   if(raw_mem_set)
1962     MC_SET_RAW_MEM;
1963
1964   xbt_abort();
1965   //MC_exit();
1966 }
1967
1968 void MC_modelcheck_liveness(){
1969
1970   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1971
1972   MC_init();
1973
1974   mc_time = xbt_new0(double, simix_process_maxpid);
1975
1976   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
1977   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
1978  
1979   MC_SET_RAW_MEM;
1980  
1981   /* Initialize statistics */
1982   mc_stats = xbt_new0(s_mc_stats_t, 1);
1983   mc_stats->state_size = 1;
1984
1985   /* Create exploration stack */
1986   mc_stack_liveness = xbt_fifo_new();
1987
1988   /* Create the initial state */
1989   initial_state_liveness = xbt_new0(s_mc_global_t, 1);
1990
1991   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
1992     MC_init_dot_output();
1993   
1994   MC_UNSET_RAW_MEM;
1995
1996   MC_ddfs_init();
1997
1998   /* We're done */
1999   MC_print_statistics(mc_stats);
2000   xbt_free(mc_time);
2001
2002   if(raw_mem_set)
2003     MC_SET_RAW_MEM;
2004
2005 }
2006
2007
2008 void MC_exit(void)
2009 {
2010   xbt_free(mc_time);
2011   MC_memory_exit();
2012   //xbt_abort();
2013 }
2014
2015 int SIMIX_pre_mc_random(smx_simcall_t simcall, int min, int max){
2016
2017   return simcall->mc_value;
2018 }
2019
2020
2021 int MC_random(int min, int max)
2022 {
2023   /*FIXME: return mc_current_state->executed_transition->random.value;*/
2024   return simcall_mc_random(min, max);
2025 }
2026
2027 /**
2028  * \brief Schedules all the process that are ready to run
2029  */
2030 void MC_wait_for_requests(void)
2031 {
2032   smx_process_t process;
2033   smx_simcall_t req;
2034   unsigned int iter;
2035
2036   while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
2037     SIMIX_process_runall();
2038     xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
2039       req = &process->simcall;
2040       if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
2041         SIMIX_simcall_pre(req, 0);
2042     }
2043   }
2044 }
2045
2046 int MC_deadlock_check()
2047 {
2048   int deadlock = FALSE;
2049   smx_process_t process;
2050   if(xbt_swag_size(simix_global->process_list)){
2051     deadlock = TRUE;
2052     xbt_swag_foreach(process, simix_global->process_list){
2053       if(process->simcall.call != SIMCALL_NONE
2054          && MC_request_is_enabled(&process->simcall)){
2055         deadlock = FALSE;
2056         break;
2057       }
2058     }
2059   }
2060   return deadlock;
2061 }
2062
2063 /**
2064  * \brief Re-executes from the state at position start all the transitions indicated by
2065  *        a given model-checker stack.
2066  * \param stack The stack with the transitions to execute.
2067  * \param start Start index to begin the re-execution.
2068  */
2069 void MC_replay(xbt_fifo_t stack, int start)
2070 {
2071   int raw_mem = (mmalloc_get_current_heap() == raw_heap);
2072
2073   int value, i = 1, count = 1;
2074   char *req_str;
2075   smx_simcall_t req = NULL, saved_req = NULL;
2076   xbt_fifo_item_t item, start_item;
2077   mc_state_t state;
2078   smx_process_t process = NULL;
2079
2080   XBT_DEBUG("**** Begin Replay ****");
2081
2082   if(start == -1){
2083     /* Restore the initial state */
2084     MC_restore_snapshot(initial_state_safety->snapshot);
2085     /* At the moment of taking the snapshot the raw heap was set, so restoring
2086      * it will set it back again, we have to unset it to continue  */
2087     MC_UNSET_RAW_MEM;
2088   }
2089
2090   start_item = xbt_fifo_get_last_item(stack);
2091   if(start != -1){
2092     while (i != start){
2093       start_item = xbt_fifo_get_prev_item(start_item);
2094       i++;
2095     }
2096   }
2097
2098   MC_SET_RAW_MEM;
2099   xbt_dict_reset(first_enabled_state);
2100   xbt_swag_foreach(process, simix_global->process_list){
2101     if(MC_process_is_enabled(process)){
2102       char *key = bprintf("%lu", process->pid);
2103       char *data = bprintf("%d", count);
2104       xbt_dict_set(first_enabled_state, key, data, NULL);
2105       xbt_free(key);
2106     }
2107   }
2108   MC_UNSET_RAW_MEM;
2109   
2110
2111   /* Traverse the stack from the state at position start and re-execute the transitions */
2112   for (item = start_item;
2113        item != xbt_fifo_get_first_item(stack);
2114        item = xbt_fifo_get_prev_item(item)) {
2115
2116     state = (mc_state_t) xbt_fifo_get_item_content(item);
2117     saved_req = MC_state_get_executed_request(state, &value);
2118    
2119     MC_SET_RAW_MEM;
2120     char *key = bprintf("%lu", saved_req->issuer->pid);
2121     xbt_dict_remove(first_enabled_state, key); 
2122     xbt_free(key);
2123     MC_UNSET_RAW_MEM;
2124    
2125     if(saved_req){
2126       /* because we got a copy of the executed request, we have to fetch the  
2127          real one, pointed by the request field of the issuer process */
2128       req = &saved_req->issuer->simcall;
2129
2130       /* Debug information */
2131       if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
2132         req_str = MC_request_to_string(req, value);
2133         XBT_DEBUG("Replay: %s (%p)", req_str, state);
2134         xbt_free(req_str);
2135       }
2136     }
2137     
2138     SIMIX_simcall_pre(req, value);
2139     MC_wait_for_requests();
2140
2141     count++;
2142
2143     MC_SET_RAW_MEM;
2144     /* Insert in dict all enabled processes */
2145     xbt_swag_foreach(process, simix_global->process_list){
2146       if(MC_process_is_enabled(process) /*&& !MC_state_process_is_done(state, process)*/){
2147         char *key = bprintf("%lu", process->pid);
2148         if(xbt_dict_get_or_null(first_enabled_state, key) == NULL){
2149           char *data = bprintf("%d", count);
2150           xbt_dict_set(first_enabled_state, key, data, NULL);
2151         }
2152         xbt_free(key);
2153       }
2154     }
2155     MC_UNSET_RAW_MEM;
2156          
2157     /* Update statistics */
2158     mc_stats->visited_states++;
2159     mc_stats->executed_transitions++;
2160
2161   }
2162
2163   XBT_DEBUG("**** End Replay ****");
2164
2165   if(raw_mem)
2166     MC_SET_RAW_MEM;
2167   else
2168     MC_UNSET_RAW_MEM;
2169   
2170
2171 }
2172
2173 void MC_replay_liveness(xbt_fifo_t stack, int all_stack)
2174 {
2175
2176   initial_state_liveness->raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2177
2178   int value;
2179   char *req_str;
2180   smx_simcall_t req = NULL, saved_req = NULL;
2181   xbt_fifo_item_t item;
2182   mc_state_t state;
2183   mc_pair_t pair;
2184   int depth = 1;
2185
2186   XBT_DEBUG("**** Begin Replay ****");
2187
2188   /* Restore the initial state */
2189   MC_restore_snapshot(initial_state_liveness->snapshot);
2190
2191   /* At the moment of taking the snapshot the raw heap was set, so restoring
2192    * it will set it back again, we have to unset it to continue  */
2193   if(!initial_state_liveness->raw_mem_set)
2194     MC_UNSET_RAW_MEM;
2195
2196   if(all_stack){
2197
2198     item = xbt_fifo_get_last_item(stack);
2199
2200     while(depth <= xbt_fifo_size(stack)){
2201
2202       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
2203       state = (mc_state_t) pair->graph_state;
2204
2205       if(pair->requests > 0){
2206    
2207         saved_req = MC_state_get_executed_request(state, &value);
2208         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
2209       
2210         if(saved_req != NULL){
2211           /* because we got a copy of the executed request, we have to fetch the  
2212              real one, pointed by the request field of the issuer process */
2213           req = &saved_req->issuer->simcall;
2214           //XBT_DEBUG("Req->call %u", req->call);
2215   
2216           /* Debug information */
2217           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
2218             req_str = MC_request_to_string(req, value);
2219             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
2220             xbt_free(req_str);
2221           }
2222   
2223         }
2224  
2225         SIMIX_simcall_pre(req, value);
2226         MC_wait_for_requests();
2227       }
2228
2229       depth++;
2230     
2231       /* Update statistics */
2232       mc_stats->visited_pairs++;
2233       mc_stats->executed_transitions++;
2234
2235       item = xbt_fifo_get_prev_item(item);
2236     }
2237
2238   }else{
2239
2240     /* Traverse the stack from the initial state and re-execute the transitions */
2241     for (item = xbt_fifo_get_last_item(stack);
2242          item != xbt_fifo_get_first_item(stack);
2243          item = xbt_fifo_get_prev_item(item)) {
2244
2245       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
2246       state = (mc_state_t) pair->graph_state;
2247
2248       if(pair->requests > 0){
2249    
2250         saved_req = MC_state_get_executed_request(state, &value);
2251         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
2252       
2253         if(saved_req != NULL){
2254           /* because we got a copy of the executed request, we have to fetch the  
2255              real one, pointed by the request field of the issuer process */
2256           req = &saved_req->issuer->simcall;
2257           //XBT_DEBUG("Req->call %u", req->call);
2258   
2259           /* Debug information */
2260           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
2261             req_str = MC_request_to_string(req, value);
2262             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
2263             xbt_free(req_str);
2264           }
2265   
2266         }
2267  
2268         SIMIX_simcall_pre(req, value);
2269         MC_wait_for_requests();
2270       }
2271
2272       depth++;
2273     
2274       /* Update statistics */
2275       mc_stats->visited_pairs++;
2276       mc_stats->executed_transitions++;
2277     }
2278   }  
2279
2280   XBT_DEBUG("**** End Replay ****");
2281
2282   if(initial_state_liveness->raw_mem_set)
2283     MC_SET_RAW_MEM;
2284   else
2285     MC_UNSET_RAW_MEM;
2286   
2287 }
2288
2289 /**
2290  * \brief Dumps the contents of a model-checker's stack and shows the actual
2291  *        execution trace
2292  * \param stack The stack to dump
2293  */
2294 void MC_dump_stack_safety(xbt_fifo_t stack)
2295 {
2296   
2297   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2298
2299   MC_show_stack_safety(stack);
2300
2301   if(!_sg_mc_checkpoint){
2302
2303     mc_state_t state;
2304
2305     MC_SET_RAW_MEM;
2306     while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
2307       MC_state_delete(state);
2308     MC_UNSET_RAW_MEM;
2309
2310   }
2311
2312   if(raw_mem_set)
2313     MC_SET_RAW_MEM;
2314   else
2315     MC_UNSET_RAW_MEM;
2316   
2317 }
2318
2319
2320 void MC_show_stack_safety(xbt_fifo_t stack)
2321 {
2322
2323   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2324
2325   MC_SET_RAW_MEM;
2326
2327   int value;
2328   mc_state_t state;
2329   xbt_fifo_item_t item;
2330   smx_simcall_t req;
2331   char *req_str = NULL;
2332   
2333   for (item = xbt_fifo_get_last_item(stack);
2334        (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
2335         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
2336     req = MC_state_get_executed_request(state, &value);
2337     if(req){
2338       req_str = MC_request_to_string(req, value);
2339       XBT_INFO("%s", req_str);
2340       xbt_free(req_str);
2341     }
2342   }
2343
2344   if(!raw_mem_set)
2345     MC_UNSET_RAW_MEM;
2346 }
2347
2348 void MC_show_deadlock(smx_simcall_t req)
2349 {
2350   /*char *req_str = NULL;*/
2351   XBT_INFO("**************************");
2352   XBT_INFO("*** DEAD-LOCK DETECTED ***");
2353   XBT_INFO("**************************");
2354   XBT_INFO("Locked request:");
2355   /*req_str = MC_request_to_string(req);
2356     XBT_INFO("%s", req_str);
2357     xbt_free(req_str);*/
2358   XBT_INFO("Counter-example execution trace:");
2359   MC_dump_stack_safety(mc_stack_safety);
2360   MC_print_statistics(mc_stats);
2361 }
2362
2363
2364 void MC_show_stack_liveness(xbt_fifo_t stack){
2365   int value;
2366   mc_pair_t pair;
2367   xbt_fifo_item_t item;
2368   smx_simcall_t req;
2369   char *req_str = NULL;
2370   
2371   for (item = xbt_fifo_get_last_item(stack);
2372        (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item)))
2373         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
2374     req = MC_state_get_executed_request(pair->graph_state, &value);
2375     if(req){
2376       if(pair->requests>0){
2377         req_str = MC_request_to_string(req, value);
2378         XBT_INFO("%s", req_str);
2379         xbt_free(req_str);
2380       }else{
2381         XBT_INFO("End of system requests but evolution in Büchi automaton");
2382       }
2383     }
2384   }
2385 }
2386
2387 void MC_dump_stack_liveness(xbt_fifo_t stack){
2388
2389   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2390
2391   mc_pair_t pair;
2392
2393   MC_SET_RAW_MEM;
2394   while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
2395     MC_pair_delete(pair);
2396   MC_UNSET_RAW_MEM;
2397
2398   if(raw_mem_set)
2399     MC_SET_RAW_MEM;
2400
2401 }
2402
2403
2404 void MC_print_statistics(mc_stats_t stats)
2405 {
2406   if(stats->expanded_pairs == 0){
2407     XBT_INFO("Expanded states = %lu", stats->expanded_states);
2408     XBT_INFO("Visited states = %lu", stats->visited_states);
2409   }else{
2410     XBT_INFO("Expanded pairs = %lu", stats->expanded_pairs);
2411     XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
2412   }
2413   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
2414   MC_SET_RAW_MEM;
2415   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
2416     fprintf(dot_output, "}\n");
2417     fclose(dot_output);
2418   }
2419   MC_UNSET_RAW_MEM;
2420 }
2421
2422 void MC_assert(int prop)
2423 {
2424   if (MC_is_active() && !prop){
2425     XBT_INFO("**************************");
2426     XBT_INFO("*** PROPERTY NOT VALID ***");
2427     XBT_INFO("**************************");
2428     XBT_INFO("Counter-example execution trace:");
2429     MC_dump_stack_safety(mc_stack_safety);
2430     MC_print_statistics(mc_stats);
2431     xbt_abort();
2432   }
2433 }
2434
2435 void MC_cut(void){
2436   user_max_depth_reached = 1;
2437 }
2438
2439 void MC_process_clock_add(smx_process_t process, double amount)
2440 {
2441   mc_time[process->pid] += amount;
2442 }
2443
2444 double MC_process_clock_get(smx_process_t process)
2445 {
2446   if(mc_time){
2447     if(process != NULL)
2448       return mc_time[process->pid];
2449     else 
2450       return -1;
2451   }else{
2452     return 0;
2453   }
2454 }
2455
2456 void MC_automaton_load(const char *file){
2457
2458   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2459
2460   MC_SET_RAW_MEM;
2461
2462   if (_mc_property_automaton == NULL)
2463     _mc_property_automaton = xbt_automaton_new();
2464   
2465   xbt_automaton_load(_mc_property_automaton,file);
2466
2467   MC_UNSET_RAW_MEM;
2468
2469   if(raw_mem_set)
2470     MC_SET_RAW_MEM;
2471
2472 }
2473
2474 void MC_automaton_new_propositional_symbol(const char* id, void* fct) {
2475
2476   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2477
2478   MC_SET_RAW_MEM;
2479
2480   if (_mc_property_automaton == NULL)
2481     _mc_property_automaton = xbt_automaton_new();
2482
2483   xbt_automaton_propositional_symbol_new(_mc_property_automaton,id,fct);
2484
2485   MC_UNSET_RAW_MEM;
2486
2487   if(raw_mem_set)
2488     MC_SET_RAW_MEM;
2489   
2490 }
2491
2492
2493