Logo AND Algorithmique Numérique Distribuée

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