Logo AND Algorithmique Numérique Distribuée

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