Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
cbd6cc8b87109597396790738e5e12da5c1114f2
[simgrid.git] / src / mc / mc_global.c
1 /* Copyright (c) 2008-2013 Da SimGrid Team. All rights reserved.            */
2
3 /* This program is free software; you can redistribute it and/or modify it
4  * under the terms of the license (GNU LGPL) which comes with this package. */
5
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <sys/wait.h>
9 #include <sys/time.h>
10
11 #include "simgrid/sg_config.h"
12 #include "../surf/surf_private.h"
13 #include "../simix/smx_private.h"
14 #include "../xbt/mmalloc/mmprivate.h"
15 #include "xbt/fifo.h"
16 #include "mc_private.h"
17 #include "xbt/automaton.h"
18 #include "xbt/dict.h"
19
20 XBT_LOG_NEW_CATEGORY(mc, "All MC categories");
21 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_global, mc,
22                                 "Logging specific to MC (global)");
23
24 /* Configuration support */
25 e_mc_reduce_t mc_reduce_kind=e_mc_reduce_unset;
26
27 int _sg_do_model_check = 0;
28 int _sg_mc_checkpoint=0;
29 char* _sg_mc_property_file=NULL;
30 int _sg_mc_timeout=0;
31 int _sg_mc_max_depth=1000;
32 int _sg_mc_visited=0;
33 char *_sg_mc_dot_output_file = NULL;
34
35 int user_max_depth_reached = 0;
36
37 extern int _sg_init_status;
38 void _mc_cfg_cb_reduce(const char *name, int pos) {
39   if (_sg_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_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_boolean(_sg_cfg_set, name);
57 }
58 void _mc_cfg_cb_property(const char *name, int pos) {
59   if (_sg_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_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_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_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_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 mc_comparison_times_t mc_comp_times = NULL;
98 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   MC_UNSET_RAW_MEM;
1329
1330   if(raw_mem_set)
1331     MC_SET_RAW_MEM;
1332 }
1333
1334 void MC_remove_ignore_heap(void *address, size_t size){
1335
1336   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1337
1338   MC_SET_RAW_MEM;
1339
1340   unsigned int cursor = 0;
1341   int start = 0;
1342   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
1343   mc_heap_ignore_region_t region;
1344   int ignore_found = 0;
1345
1346   while(start <= end){
1347     cursor = (start + end) / 2;
1348     region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
1349     if(region->address == address){
1350       ignore_found = 1;
1351       break;
1352     }else if(region->address < address){
1353       start = cursor + 1;
1354     }else{
1355       if((char * )region->address <= ((char *)address + size)){
1356         ignore_found = 1;
1357         break;
1358       }else{
1359         end = cursor - 1;   
1360       }
1361     }
1362   }
1363   
1364   if(ignore_found == 1){
1365     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
1366     MC_remove_ignore_heap(address, size);
1367   }
1368
1369   MC_UNSET_RAW_MEM;
1370   
1371   if(raw_mem_set)
1372     MC_SET_RAW_MEM;
1373
1374 }
1375
1376 void MC_ignore_global_variable(const char *name){
1377
1378   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1379
1380   MC_SET_RAW_MEM;
1381
1382   if(mc_global_variables_libsimgrid){
1383
1384     unsigned int cursor = 0;
1385     dw_variable_t current_var;
1386     int start = 0;
1387     int end = xbt_dynar_length(mc_global_variables_libsimgrid) - 1;
1388
1389     while(start <= end){
1390       cursor = (start + end) /2;
1391       current_var = (dw_variable_t)xbt_dynar_get_as(mc_global_variables_libsimgrid, cursor, dw_variable_t);
1392       if(strcmp(current_var->name, name) == 0){
1393         xbt_dynar_remove_at(mc_global_variables_libsimgrid, cursor, NULL);
1394         start = 0;
1395         end = xbt_dynar_length(mc_global_variables_libsimgrid) - 1;
1396       }else if(strcmp(current_var->name, name) < 0){
1397         start = cursor + 1;
1398       }else{
1399         end = cursor - 1;
1400       } 
1401     }
1402    
1403   }else{
1404
1405     if(mc_data_bss_comparison_ignore == NULL)
1406       mc_data_bss_comparison_ignore = xbt_dynar_new(sizeof(mc_data_bss_ignore_variable_t), data_bss_ignore_variable_free_voidp);
1407
1408     mc_data_bss_ignore_variable_t var = NULL;
1409     var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1);
1410     var->name = strdup(name);
1411
1412     if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){
1413
1414       xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var);
1415
1416     }else{
1417     
1418       unsigned int cursor = 0;
1419       int start = 0;
1420       int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
1421       mc_data_bss_ignore_variable_t current_var = NULL;
1422
1423       while(start <= end){
1424         cursor = (start + end) / 2;
1425         current_var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
1426         if(strcmp(current_var->name, name) == 0){
1427           data_bss_ignore_variable_free(var);
1428           if(!raw_mem_set)
1429             MC_UNSET_RAW_MEM;
1430           return;
1431         }else if(strcmp(current_var->name, name) < 0){
1432           start = cursor + 1;
1433         }else{
1434           end = cursor - 1;
1435         }
1436       }
1437
1438       if(strcmp(current_var->name, name) < 0)
1439         xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor + 1, &var);
1440       else
1441         xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor, &var);
1442
1443     }
1444   }
1445
1446   MC_UNSET_RAW_MEM;
1447
1448   if(raw_mem_set)
1449     MC_SET_RAW_MEM;
1450 }
1451
1452 void MC_ignore_local_variable(const char *var_name, const char *frame_name){
1453   
1454   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1455
1456   MC_SET_RAW_MEM;
1457
1458   if(mc_local_variables_libsimgrid){
1459     unsigned int cursor = 0;
1460     dw_variable_t current_var;
1461     int start, end;
1462     if(strcmp(frame_name, "*") == 0){ /* Remove variable in all frames */
1463       xbt_dict_cursor_t dict_cursor;
1464       char *current_frame_name;
1465       dw_frame_t frame;
1466       xbt_dict_foreach(mc_local_variables_libsimgrid, dict_cursor, current_frame_name, frame){
1467         start = 0;
1468         end = xbt_dynar_length(frame->variables) - 1;
1469         while(start <= end){
1470           cursor = (start + end) / 2;
1471           current_var = (dw_variable_t)xbt_dynar_get_as(frame->variables, cursor, dw_variable_t); 
1472           if(strcmp(current_var->name, var_name) == 0){
1473             xbt_dynar_remove_at(frame->variables, cursor, NULL);
1474             start = 0;
1475             end = xbt_dynar_length(frame->variables) - 1;
1476           }else if(strcmp(current_var->name, var_name) < 0){
1477             start = cursor + 1;
1478           }else{
1479             end = cursor - 1;
1480           } 
1481         }
1482       }
1483     }else{
1484       xbt_dynar_t variables_list = ((dw_frame_t)xbt_dict_get_or_null(mc_local_variables_libsimgrid, frame_name))->variables;
1485       start = 0;
1486       end = xbt_dynar_length(variables_list) - 1;
1487       while(start <= end){
1488         cursor = (start + end) / 2;
1489         current_var = (dw_variable_t)xbt_dynar_get_as(variables_list, cursor, dw_variable_t);
1490         if(strcmp(current_var->name, var_name) == 0){
1491           xbt_dynar_remove_at(variables_list, cursor, NULL);
1492           start = 0;
1493           end = xbt_dynar_length(variables_list) - 1;
1494         }else if(strcmp(current_var->name, var_name) < 0){
1495           start = cursor + 1;
1496         }else{
1497           end = cursor - 1;
1498         } 
1499       }
1500     } 
1501   }else{
1502
1503     if(mc_stack_comparison_ignore == NULL)
1504       mc_stack_comparison_ignore = xbt_dynar_new(sizeof(mc_stack_ignore_variable_t), stack_ignore_variable_free_voidp);
1505   
1506     mc_stack_ignore_variable_t var = NULL;
1507     var = xbt_new0(s_mc_stack_ignore_variable_t, 1);
1508     var->var_name = strdup(var_name);
1509     var->frame = strdup(frame_name);
1510   
1511     if(xbt_dynar_is_empty(mc_stack_comparison_ignore)){
1512
1513       xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var);
1514
1515     }else{
1516     
1517       unsigned int cursor = 0;
1518       int start = 0;
1519       int end = xbt_dynar_length(mc_stack_comparison_ignore) - 1;
1520       mc_stack_ignore_variable_t current_var = NULL;
1521
1522       while(start <= end){
1523         cursor = (start + end) / 2;
1524         current_var = (mc_stack_ignore_variable_t)xbt_dynar_get_as(mc_stack_comparison_ignore, cursor, mc_stack_ignore_variable_t);
1525         if(strcmp(current_var->frame, frame_name) == 0){
1526           if(strcmp(current_var->var_name, var_name) == 0){
1527             stack_ignore_variable_free(var);
1528             if(!raw_mem_set)
1529               MC_UNSET_RAW_MEM;
1530             return;
1531           }else if(strcmp(current_var->var_name, var_name) < 0){
1532             start = cursor + 1;
1533           }else{
1534             end = cursor - 1;
1535           }
1536         }else if(strcmp(current_var->frame, frame_name) < 0){
1537           start = cursor + 1;
1538         }else{
1539           end = cursor - 1;
1540         }
1541       }
1542
1543       if(strcmp(current_var->frame, frame_name) == 0){
1544         if(strcmp(current_var->var_name, var_name) < 0){
1545           xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
1546         }else{
1547           xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
1548         }
1549       }else if(strcmp(current_var->frame, frame_name) < 0){
1550         xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
1551       }else{
1552         xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
1553       }
1554     }
1555   }
1556
1557   MC_UNSET_RAW_MEM;
1558   
1559   if(raw_mem_set)
1560     MC_SET_RAW_MEM;
1561
1562 }
1563
1564 void MC_new_stack_area(void *stack, char *name, void* context, size_t size){
1565
1566   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1567
1568   MC_SET_RAW_MEM;
1569   if(stacks_areas == NULL)
1570     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
1571   
1572   stack_region_t region = NULL;
1573   region = xbt_new0(s_stack_region_t, 1);
1574   region->address = stack;
1575   region->process_name = strdup(name);
1576   region->context = context;
1577   region->size = size;
1578   region->block = ((char*)stack - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
1579   xbt_dynar_push(stacks_areas, &region);
1580   
1581   MC_UNSET_RAW_MEM;
1582
1583   if(raw_mem_set)
1584     MC_SET_RAW_MEM;
1585 }
1586
1587 void MC_ignore(void *addr, size_t size){
1588
1589   int raw_mem_set= (mmalloc_get_current_heap() == raw_heap);
1590
1591   MC_SET_RAW_MEM;
1592
1593   if(mc_checkpoint_ignore == NULL)
1594     mc_checkpoint_ignore = xbt_dynar_new(sizeof(mc_checkpoint_ignore_region_t), checkpoint_ignore_region_free_voidp);
1595
1596   mc_checkpoint_ignore_region_t region = xbt_new0(s_mc_checkpoint_ignore_region_t, 1);
1597   region->addr = addr;
1598   region->size = size;
1599
1600   if(xbt_dynar_is_empty(mc_checkpoint_ignore)){
1601     xbt_dynar_push(mc_checkpoint_ignore, &region);
1602   }else{
1603      
1604     unsigned int cursor = 0;
1605     int start = 0;
1606     int end = xbt_dynar_length(mc_checkpoint_ignore) -1;
1607     mc_checkpoint_ignore_region_t current_region;
1608
1609     while(start <= end){
1610       cursor = (start + end) / 2;
1611       current_region = (mc_checkpoint_ignore_region_t)xbt_dynar_get_as(mc_checkpoint_ignore, cursor, mc_checkpoint_ignore_region_t);
1612       if(current_region->addr == addr){
1613         if(current_region->size == size){
1614           checkpoint_ignore_region_free(region);
1615           if(!raw_mem_set)
1616             MC_UNSET_RAW_MEM;
1617           return;
1618         }else if(current_region->size < size){
1619           start = cursor + 1;
1620         }else{
1621           end = cursor - 1;
1622         }
1623       }else if(current_region->addr < addr){
1624           start = cursor + 1;
1625       }else{
1626         end = cursor - 1;
1627       }
1628     }
1629
1630      if(current_region->addr == addr){
1631        if(current_region->size < size){
1632         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
1633       }else{
1634         xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
1635       }
1636     }else if(current_region->addr < addr){
1637        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor + 1, &region);
1638     }else{
1639        xbt_dynar_insert_at(mc_checkpoint_ignore, cursor, &region);
1640     }
1641   }
1642
1643   if(!raw_mem_set)
1644     MC_UNSET_RAW_MEM;
1645 }
1646
1647 /*******************************  Initialisation of MC *******************************/
1648 /*********************************************************************************/
1649
1650 static void MC_dump_ignored_local_variables(void){
1651
1652   if(mc_stack_comparison_ignore == NULL || xbt_dynar_is_empty(mc_stack_comparison_ignore))
1653     return;
1654
1655   unsigned int cursor = 0;
1656   mc_stack_ignore_variable_t current_var;
1657
1658   xbt_dynar_foreach(mc_stack_comparison_ignore, cursor, current_var){
1659     MC_ignore_local_variable(current_var->var_name, current_var->frame);
1660   }
1661
1662   xbt_dynar_free(&mc_stack_comparison_ignore);
1663   mc_stack_comparison_ignore = NULL;
1664  
1665 }
1666
1667 static void MC_dump_ignored_global_variables(void){
1668
1669   if(mc_data_bss_comparison_ignore == NULL || xbt_dynar_is_empty(mc_data_bss_comparison_ignore))
1670     return;
1671
1672   unsigned int cursor = 0;
1673   mc_data_bss_ignore_variable_t current_var;
1674
1675   xbt_dynar_foreach(mc_data_bss_comparison_ignore, cursor, current_var){
1676     MC_ignore_global_variable(current_var->name);
1677   } 
1678
1679   xbt_dynar_free(&mc_data_bss_comparison_ignore);
1680   mc_data_bss_comparison_ignore = NULL;
1681
1682 }
1683
1684 void MC_init(){
1685
1686   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1687   
1688   compare = 0;
1689
1690   /* Initialize the data structures that must be persistent across every
1691      iteration of the model-checker (in RAW memory) */
1692
1693   MC_SET_RAW_MEM;
1694
1695   MC_init_memory_map_info();
1696   
1697   mc_local_variables_libsimgrid = xbt_dict_new_homogeneous(NULL);
1698   mc_local_variables_binary = xbt_dict_new_homogeneous(NULL);
1699   mc_global_variables_libsimgrid = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
1700   mc_global_variables_binary = xbt_dynar_new(sizeof(dw_variable_t), dw_variable_free_voidp);
1701   mc_variables_type_libsimgrid = xbt_dict_new_homogeneous(NULL);
1702   mc_variables_type_binary = xbt_dict_new_homogeneous(NULL);
1703
1704   XBT_INFO("Get debug information ...");
1705
1706   /* Get local variables in binary for state equality detection */
1707   xbt_dict_t binary_location_list = MC_dwarf_get_location_list(xbt_binary_name);
1708   MC_dwarf_get_variables(xbt_binary_name, binary_location_list, &mc_local_variables_binary, &mc_global_variables_binary, &mc_variables_type_binary);
1709
1710   /* Get local variables in libsimgrid for state equality detection */
1711   xbt_dict_t libsimgrid_location_list = MC_dwarf_get_location_list(libsimgrid_path);
1712   MC_dwarf_get_variables(libsimgrid_path, libsimgrid_location_list, &mc_local_variables_libsimgrid, &mc_global_variables_libsimgrid, &mc_variables_type_libsimgrid);
1713
1714   xbt_dict_free(&libsimgrid_location_list);
1715   xbt_dict_free(&binary_location_list);
1716
1717   XBT_INFO("Get debug information done !");
1718
1719   /* Remove variables ignored before getting list of variables */
1720   MC_dump_ignored_local_variables();
1721   MC_dump_ignored_global_variables();
1722   
1723   /* Get .plt section (start and end addresses) for data libsimgrid and data program comparison */
1724   MC_get_libsimgrid_plt_section();
1725   MC_get_binary_plt_section();
1726
1727   MC_UNSET_RAW_MEM;
1728
1729    /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
1730   MC_ignore_local_variable("e", "*");
1731   MC_ignore_local_variable("__ex_cleanup", "*");
1732   MC_ignore_local_variable("__ex_mctx_en", "*");
1733   MC_ignore_local_variable("__ex_mctx_me", "*");
1734   MC_ignore_local_variable("__xbt_ex_ctx_ptr", "*");
1735   MC_ignore_local_variable("_log_ev", "*");
1736   MC_ignore_local_variable("_throw_ctx", "*");
1737   MC_ignore_local_variable("ctx", "*");
1738
1739   MC_ignore_local_variable("next_context", "smx_ctx_sysv_suspend_serial");
1740   MC_ignore_local_variable("i", "smx_ctx_sysv_suspend_serial");
1741
1742   /* Ignore local variable about time used for tracing */
1743   MC_ignore_local_variable("start_time", "*"); 
1744
1745   MC_ignore_global_variable("mc_comp_times");
1746   MC_ignore_global_variable("mc_snapshot_comparison_time"); 
1747   MC_ignore_global_variable("mc_time");
1748   MC_ignore_global_variable("smpi_current_rank");
1749   MC_ignore_global_variable("smx_current_context_serial");
1750   MC_ignore_global_variable("smx_current_context_key");
1751   MC_ignore_global_variable("sysv_maestro_context");
1752   MC_ignore_global_variable("counter"); /* Static variable used for tracing */
1753
1754   if(raw_mem_set)
1755     MC_SET_RAW_MEM;
1756
1757 }
1758
1759 static void MC_init_dot_output(){ /* FIXME : more colors */
1760
1761   colors[0] = "blue";
1762   colors[1] = "red";
1763   colors[2] = "green3";
1764   colors[3] = "goldenrod";
1765   colors[4] = "brown";
1766   colors[5] = "purple";
1767   colors[6] = "magenta";
1768   colors[7] = "turquoise4";
1769   colors[8] = "gray25";
1770   colors[9] = "forestgreen";
1771   colors[10] = "hotpink";
1772   colors[11] = "lightblue";
1773   colors[12] = "tan";
1774
1775   dot_output = fopen(_sg_mc_dot_output_file, "w");
1776   
1777   if(dot_output == NULL){
1778     perror("Error open dot output file");
1779     xbt_abort();
1780   }
1781
1782   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");
1783
1784 }
1785
1786 /*******************************  Core of MC *******************************/
1787 /**************************************************************************/
1788
1789 void MC_do_the_modelcheck_for_real() {
1790
1791   MC_SET_RAW_MEM;
1792   mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
1793   MC_UNSET_RAW_MEM;
1794   
1795   if (!_sg_mc_property_file || _sg_mc_property_file[0]=='\0') {
1796     if (mc_reduce_kind==e_mc_reduce_unset)
1797       mc_reduce_kind=e_mc_reduce_dpor;
1798
1799     XBT_INFO("Check a safety property");
1800     MC_modelcheck_safety();
1801
1802   } else  {
1803
1804     if (mc_reduce_kind==e_mc_reduce_unset)
1805       mc_reduce_kind=e_mc_reduce_none;
1806
1807     XBT_INFO("Check the liveness property %s",_sg_mc_property_file);
1808     MC_automaton_load(_sg_mc_property_file);
1809     MC_modelcheck_liveness();
1810   }
1811 }
1812
1813 void MC_modelcheck_safety(void)
1814 {
1815   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1816
1817   /* Check if MC is already initialized */
1818   if (initial_state_safety)
1819     return;
1820
1821   mc_time = xbt_new0(double, simix_process_maxpid);
1822
1823   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
1824   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
1825
1826   /* Initialize the data structures that must be persistent across every
1827      iteration of the model-checker (in RAW memory) */
1828   
1829   MC_SET_RAW_MEM;
1830
1831   /* Initialize statistics */
1832   mc_stats = xbt_new0(s_mc_stats_t, 1);
1833   mc_stats->state_size = 1;
1834
1835   /* Create exploration stack */
1836   mc_stack_safety = xbt_fifo_new();
1837
1838   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
1839     MC_init_dot_output();
1840
1841   MC_UNSET_RAW_MEM;
1842
1843   if(_sg_mc_visited > 0){
1844     MC_init();
1845   }else{
1846     MC_SET_RAW_MEM;
1847     MC_init_memory_map_info();
1848     MC_get_libsimgrid_plt_section();
1849     MC_get_binary_plt_section();
1850     MC_UNSET_RAW_MEM;
1851   }
1852
1853   MC_dpor_init();
1854
1855   MC_SET_RAW_MEM;
1856   /* Save the initial state */
1857   initial_state_safety = xbt_new0(s_mc_global_t, 1);
1858   initial_state_safety->snapshot = MC_take_snapshot();
1859   MC_UNSET_RAW_MEM;
1860
1861   MC_dpor();
1862
1863   if(raw_mem_set)
1864     MC_SET_RAW_MEM;
1865
1866   xbt_abort();
1867   //MC_exit();
1868 }
1869
1870 void MC_modelcheck_liveness(){
1871
1872   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1873
1874   MC_init();
1875
1876   mc_time = xbt_new0(double, simix_process_maxpid);
1877
1878   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
1879   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
1880  
1881   MC_SET_RAW_MEM;
1882  
1883   /* Initialize statistics */
1884   mc_stats = xbt_new0(s_mc_stats_t, 1);
1885   mc_stats->state_size = 1;
1886
1887   /* Create exploration stack */
1888   mc_stack_liveness = xbt_fifo_new();
1889
1890   /* Create the initial state */
1891   initial_state_liveness = xbt_new0(s_mc_global_t, 1);
1892
1893   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
1894     MC_init_dot_output();
1895   
1896   MC_UNSET_RAW_MEM;
1897
1898   MC_ddfs_init();
1899
1900   /* We're done */
1901   MC_print_statistics(mc_stats);
1902   xbt_free(mc_time);
1903
1904   if(raw_mem_set)
1905     MC_SET_RAW_MEM;
1906
1907 }
1908
1909
1910 void MC_exit(void)
1911 {
1912   xbt_free(mc_time);
1913   MC_memory_exit();
1914   //xbt_abort();
1915 }
1916
1917 int SIMIX_pre_mc_random(smx_simcall_t simcall, int min, int max){
1918
1919   return simcall->mc_value;
1920 }
1921
1922
1923 int MC_random(int min, int max)
1924 {
1925   /*FIXME: return mc_current_state->executed_transition->random.value;*/
1926   return simcall_mc_random(min, max);
1927 }
1928
1929 /**
1930  * \brief Schedules all the process that are ready to run
1931  */
1932 void MC_wait_for_requests(void)
1933 {
1934   smx_process_t process;
1935   smx_simcall_t req;
1936   unsigned int iter;
1937
1938   while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
1939     SIMIX_process_runall();
1940     xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
1941       req = &process->simcall;
1942       if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
1943         SIMIX_simcall_pre(req, 0);
1944     }
1945   }
1946 }
1947
1948 int MC_deadlock_check()
1949 {
1950   int deadlock = FALSE;
1951   smx_process_t process;
1952   if(xbt_swag_size(simix_global->process_list)){
1953     deadlock = TRUE;
1954     xbt_swag_foreach(process, simix_global->process_list){
1955       if(process->simcall.call != SIMCALL_NONE
1956          && MC_request_is_enabled(&process->simcall)){
1957         deadlock = FALSE;
1958         break;
1959       }
1960     }
1961   }
1962   return deadlock;
1963 }
1964
1965 /**
1966  * \brief Re-executes from the state at position start all the transitions indicated by
1967  *        a given model-checker stack.
1968  * \param stack The stack with the transitions to execute.
1969  * \param start Start index to begin the re-execution.
1970  */
1971 void MC_replay(xbt_fifo_t stack, int start)
1972 {
1973   int raw_mem = (mmalloc_get_current_heap() == raw_heap);
1974
1975   int value, i = 1, count = 1;
1976   char *req_str;
1977   smx_simcall_t req = NULL, saved_req = NULL;
1978   xbt_fifo_item_t item, start_item;
1979   mc_state_t state;
1980   smx_process_t process = NULL;
1981
1982   XBT_DEBUG("**** Begin Replay ****");
1983
1984   if(start == -1){
1985     /* Restore the initial state */
1986     MC_restore_snapshot(initial_state_safety->snapshot);
1987     /* At the moment of taking the snapshot the raw heap was set, so restoring
1988      * it will set it back again, we have to unset it to continue  */
1989     MC_UNSET_RAW_MEM;
1990   }
1991
1992   start_item = xbt_fifo_get_last_item(stack);
1993   if(start != -1){
1994     while (i != start){
1995       start_item = xbt_fifo_get_prev_item(start_item);
1996       i++;
1997     }
1998   }
1999
2000   MC_SET_RAW_MEM;
2001   xbt_dict_reset(first_enabled_state);
2002   xbt_swag_foreach(process, simix_global->process_list){
2003     if(MC_process_is_enabled(process)){
2004       char *key = bprintf("%lu", process->pid);
2005       char *data = bprintf("%d", count);
2006       xbt_dict_set(first_enabled_state, key, data, NULL);
2007       xbt_free(key);
2008     }
2009   }
2010   MC_UNSET_RAW_MEM;
2011   
2012
2013   /* Traverse the stack from the state at position start and re-execute the transitions */
2014   for (item = start_item;
2015        item != xbt_fifo_get_first_item(stack);
2016        item = xbt_fifo_get_prev_item(item)) {
2017
2018     state = (mc_state_t) xbt_fifo_get_item_content(item);
2019     saved_req = MC_state_get_executed_request(state, &value);
2020    
2021     MC_SET_RAW_MEM;
2022     char *key = bprintf("%lu", saved_req->issuer->pid);
2023     xbt_dict_remove(first_enabled_state, key); 
2024     xbt_free(key);
2025     MC_UNSET_RAW_MEM;
2026    
2027     if(saved_req){
2028       /* because we got a copy of the executed request, we have to fetch the  
2029          real one, pointed by the request field of the issuer process */
2030       req = &saved_req->issuer->simcall;
2031
2032       /* Debug information */
2033       if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
2034         req_str = MC_request_to_string(req, value);
2035         XBT_DEBUG("Replay: %s (%p)", req_str, state);
2036         xbt_free(req_str);
2037       }
2038     }
2039     
2040     SIMIX_simcall_pre(req, value);
2041     MC_wait_for_requests();
2042
2043     count++;
2044
2045     MC_SET_RAW_MEM;
2046     /* Insert in dict all enabled processes */
2047     xbt_swag_foreach(process, simix_global->process_list){
2048       if(MC_process_is_enabled(process) /*&& !MC_state_process_is_done(state, process)*/){
2049         char *key = bprintf("%lu", process->pid);
2050         if(xbt_dict_get_or_null(first_enabled_state, key) == NULL){
2051           char *data = bprintf("%d", count);
2052           xbt_dict_set(first_enabled_state, key, data, NULL);
2053         }
2054         xbt_free(key);
2055       }
2056     }
2057     MC_UNSET_RAW_MEM;
2058          
2059     /* Update statistics */
2060     mc_stats->visited_states++;
2061     mc_stats->executed_transitions++;
2062
2063   }
2064
2065   XBT_DEBUG("**** End Replay ****");
2066
2067   if(raw_mem)
2068     MC_SET_RAW_MEM;
2069   else
2070     MC_UNSET_RAW_MEM;
2071   
2072
2073 }
2074
2075 void MC_replay_liveness(xbt_fifo_t stack, int all_stack)
2076 {
2077
2078   initial_state_liveness->raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2079
2080   int value;
2081   char *req_str;
2082   smx_simcall_t req = NULL, saved_req = NULL;
2083   xbt_fifo_item_t item;
2084   mc_state_t state;
2085   mc_pair_t pair;
2086   int depth = 1;
2087
2088   XBT_DEBUG("**** Begin Replay ****");
2089
2090   /* Restore the initial state */
2091   MC_restore_snapshot(initial_state_liveness->snapshot);
2092
2093   /* At the moment of taking the snapshot the raw heap was set, so restoring
2094    * it will set it back again, we have to unset it to continue  */
2095   if(!initial_state_liveness->raw_mem_set)
2096     MC_UNSET_RAW_MEM;
2097
2098   if(all_stack){
2099
2100     item = xbt_fifo_get_last_item(stack);
2101
2102     while(depth <= xbt_fifo_size(stack)){
2103
2104       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
2105       state = (mc_state_t) pair->graph_state;
2106
2107       if(pair->requests > 0){
2108    
2109         saved_req = MC_state_get_executed_request(state, &value);
2110         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
2111       
2112         if(saved_req != NULL){
2113           /* because we got a copy of the executed request, we have to fetch the  
2114              real one, pointed by the request field of the issuer process */
2115           req = &saved_req->issuer->simcall;
2116           //XBT_DEBUG("Req->call %u", req->call);
2117   
2118           /* Debug information */
2119           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
2120             req_str = MC_request_to_string(req, value);
2121             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
2122             xbt_free(req_str);
2123           }
2124   
2125         }
2126  
2127         SIMIX_simcall_pre(req, value);
2128         MC_wait_for_requests();
2129       }
2130
2131       depth++;
2132     
2133       /* Update statistics */
2134       mc_stats->visited_pairs++;
2135       mc_stats->executed_transitions++;
2136
2137       item = xbt_fifo_get_prev_item(item);
2138     }
2139
2140   }else{
2141
2142     /* Traverse the stack from the initial state and re-execute the transitions */
2143     for (item = xbt_fifo_get_last_item(stack);
2144          item != xbt_fifo_get_first_item(stack);
2145          item = xbt_fifo_get_prev_item(item)) {
2146
2147       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
2148       state = (mc_state_t) pair->graph_state;
2149
2150       if(pair->requests > 0){
2151    
2152         saved_req = MC_state_get_executed_request(state, &value);
2153         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
2154       
2155         if(saved_req != NULL){
2156           /* because we got a copy of the executed request, we have to fetch the  
2157              real one, pointed by the request field of the issuer process */
2158           req = &saved_req->issuer->simcall;
2159           //XBT_DEBUG("Req->call %u", req->call);
2160   
2161           /* Debug information */
2162           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
2163             req_str = MC_request_to_string(req, value);
2164             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
2165             xbt_free(req_str);
2166           }
2167   
2168         }
2169  
2170         SIMIX_simcall_pre(req, value);
2171         MC_wait_for_requests();
2172       }
2173
2174       depth++;
2175     
2176       /* Update statistics */
2177       mc_stats->visited_pairs++;
2178       mc_stats->executed_transitions++;
2179     }
2180   }  
2181
2182   XBT_DEBUG("**** End Replay ****");
2183
2184   if(initial_state_liveness->raw_mem_set)
2185     MC_SET_RAW_MEM;
2186   else
2187     MC_UNSET_RAW_MEM;
2188   
2189 }
2190
2191 /**
2192  * \brief Dumps the contents of a model-checker's stack and shows the actual
2193  *        execution trace
2194  * \param stack The stack to dump
2195  */
2196 void MC_dump_stack_safety(xbt_fifo_t stack)
2197 {
2198   
2199   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2200
2201   MC_show_stack_safety(stack);
2202
2203   if(!_sg_mc_checkpoint){
2204
2205     mc_state_t state;
2206
2207     MC_SET_RAW_MEM;
2208     while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
2209       MC_state_delete(state);
2210     MC_UNSET_RAW_MEM;
2211
2212   }
2213
2214   if(raw_mem_set)
2215     MC_SET_RAW_MEM;
2216   else
2217     MC_UNSET_RAW_MEM;
2218   
2219 }
2220
2221
2222 void MC_show_stack_safety(xbt_fifo_t stack)
2223 {
2224
2225   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2226
2227   MC_SET_RAW_MEM;
2228
2229   int value;
2230   mc_state_t state;
2231   xbt_fifo_item_t item;
2232   smx_simcall_t req;
2233   char *req_str = NULL;
2234   
2235   for (item = xbt_fifo_get_last_item(stack);
2236        (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
2237         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
2238     req = MC_state_get_executed_request(state, &value);
2239     if(req){
2240       req_str = MC_request_to_string(req, value);
2241       XBT_INFO("%s", req_str);
2242       xbt_free(req_str);
2243     }
2244   }
2245
2246   if(!raw_mem_set)
2247     MC_UNSET_RAW_MEM;
2248 }
2249
2250 void MC_show_deadlock(smx_simcall_t req)
2251 {
2252   /*char *req_str = NULL;*/
2253   XBT_INFO("**************************");
2254   XBT_INFO("*** DEAD-LOCK DETECTED ***");
2255   XBT_INFO("**************************");
2256   XBT_INFO("Locked request:");
2257   /*req_str = MC_request_to_string(req);
2258     XBT_INFO("%s", req_str);
2259     xbt_free(req_str);*/
2260   XBT_INFO("Counter-example execution trace:");
2261   MC_dump_stack_safety(mc_stack_safety);
2262   MC_print_statistics(mc_stats);
2263 }
2264
2265
2266 void MC_show_stack_liveness(xbt_fifo_t stack){
2267   int value;
2268   mc_pair_t pair;
2269   xbt_fifo_item_t item;
2270   smx_simcall_t req;
2271   char *req_str = NULL;
2272   
2273   for (item = xbt_fifo_get_last_item(stack);
2274        (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item)))
2275         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
2276     req = MC_state_get_executed_request(pair->graph_state, &value);
2277     if(req){
2278       if(pair->requests>0){
2279         req_str = MC_request_to_string(req, value);
2280         XBT_INFO("%s", req_str);
2281         xbt_free(req_str);
2282       }else{
2283         XBT_INFO("End of system requests but evolution in Büchi automaton");
2284       }
2285     }
2286   }
2287 }
2288
2289 void MC_dump_stack_liveness(xbt_fifo_t stack){
2290
2291   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2292
2293   mc_pair_t pair;
2294
2295   MC_SET_RAW_MEM;
2296   while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
2297     MC_pair_delete(pair);
2298   MC_UNSET_RAW_MEM;
2299
2300   if(raw_mem_set)
2301     MC_SET_RAW_MEM;
2302
2303 }
2304
2305
2306 void MC_print_statistics(mc_stats_t stats)
2307 {
2308   if(stats->expanded_pairs == 0){
2309     XBT_INFO("Expanded states = %lu", stats->expanded_states);
2310     XBT_INFO("Visited states = %lu", stats->visited_states);
2311   }else{
2312     XBT_INFO("Expanded pairs = %lu", stats->expanded_pairs);
2313     XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
2314   }
2315   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
2316   MC_SET_RAW_MEM;
2317   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
2318     fprintf(dot_output, "}\n");
2319     fclose(dot_output);
2320   }
2321   MC_UNSET_RAW_MEM;
2322 }
2323
2324 void MC_assert(int prop)
2325 {
2326   if (MC_is_active() && !prop){
2327     XBT_INFO("**************************");
2328     XBT_INFO("*** PROPERTY NOT VALID ***");
2329     XBT_INFO("**************************");
2330     XBT_INFO("Counter-example execution trace:");
2331     MC_dump_stack_safety(mc_stack_safety);
2332     MC_print_statistics(mc_stats);
2333     xbt_abort();
2334   }
2335 }
2336
2337 void MC_cut(void){
2338   user_max_depth_reached = 1;
2339 }
2340
2341 void MC_process_clock_add(smx_process_t process, double amount)
2342 {
2343   mc_time[process->pid] += amount;
2344 }
2345
2346 double MC_process_clock_get(smx_process_t process)
2347 {
2348   if(mc_time){
2349     if(process != NULL)
2350       return mc_time[process->pid];
2351     else 
2352       return -1;
2353   }else{
2354     return 0;
2355   }
2356 }
2357
2358 void MC_automaton_load(const char *file){
2359
2360   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2361
2362   MC_SET_RAW_MEM;
2363
2364   if (_mc_property_automaton == NULL)
2365     _mc_property_automaton = xbt_automaton_new();
2366   
2367   xbt_automaton_load(_mc_property_automaton,file);
2368
2369   MC_UNSET_RAW_MEM;
2370
2371   if(raw_mem_set)
2372     MC_SET_RAW_MEM;
2373
2374 }
2375
2376 void MC_automaton_new_propositional_symbol(const char* id, void* fct) {
2377
2378   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
2379
2380   MC_SET_RAW_MEM;
2381
2382   if (_mc_property_automaton == NULL)
2383     _mc_property_automaton = xbt_automaton_new();
2384
2385   xbt_automaton_propositional_symbol_new(_mc_property_automaton,id,fct);
2386
2387   MC_UNSET_RAW_MEM;
2388
2389   if(raw_mem_set)
2390     MC_SET_RAW_MEM;
2391   
2392 }
2393
2394
2395