Logo AND Algorithmique Numérique Distribuée

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