Logo AND Algorithmique Numérique Distribuée

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