Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
970ef80e3f414e1ae0ac48662a7595824d13cd2e
[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 extern int _sg_init_status;
36 void _mc_cfg_cb_reduce(const char *name, int pos) {
37   if (_sg_init_status && !_sg_do_model_check) {
38     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.");
39   }
40   char *val= xbt_cfg_get_string(_sg_cfg_set, name);
41   if (!strcasecmp(val,"none")) {
42     mc_reduce_kind = e_mc_reduce_none;
43   } else if (!strcasecmp(val,"dpor")) {
44     mc_reduce_kind = e_mc_reduce_dpor;
45   } else {
46     xbt_die("configuration option %s can only take 'none' or 'dpor' as a value",name);
47   }
48 }
49
50 void _mc_cfg_cb_checkpoint(const char *name, int pos) {
51   if (_sg_init_status && !_sg_do_model_check) {
52     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.");
53   }
54   _sg_mc_checkpoint = xbt_cfg_get_int(_sg_cfg_set, name);
55 }
56 void _mc_cfg_cb_property(const char *name, int pos) {
57   if (_sg_init_status && !_sg_do_model_check) {
58     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.");
59   }
60   _sg_mc_property_file= xbt_cfg_get_string(_sg_cfg_set, name);
61 }
62
63 void _mc_cfg_cb_timeout(const char *name, int pos) {
64   if (_sg_init_status && !_sg_do_model_check) {
65     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.");
66   }
67   _sg_mc_timeout= xbt_cfg_get_int(_sg_cfg_set, name);
68 }
69
70 void _mc_cfg_cb_max_depth(const char *name, int pos) {
71   if (_sg_init_status && !_sg_do_model_check) {
72     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.");
73   }
74   _sg_mc_max_depth= xbt_cfg_get_int(_sg_cfg_set, name);
75 }
76
77 void _mc_cfg_cb_visited(const char *name, int pos) {
78   if (_sg_init_status && !_sg_do_model_check) {
79     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.");
80   }
81   _sg_mc_visited= xbt_cfg_get_int(_sg_cfg_set, name);
82 }
83
84 void _mc_cfg_cb_dot_output(const char *name, int pos) {
85   if (_sg_init_status && !_sg_do_model_check) {
86     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.");
87   }
88   _sg_mc_dot_output_file= xbt_cfg_get_string(_sg_cfg_set, name);
89 }
90
91 /* MC global data structures */
92
93 mc_state_t mc_current_state = NULL;
94 char mc_replay_mode = FALSE;
95 double *mc_time = NULL;
96 mc_comparison_times_t mc_comp_times = NULL;
97 double mc_snapshot_comparison_time;
98 mc_stats_t mc_stats = NULL;
99
100 /* Safety */
101
102 xbt_fifo_t mc_stack_safety = NULL;
103 mc_global_t initial_state_safety = NULL;
104
105 /* Liveness */
106
107 xbt_fifo_t mc_stack_liveness = NULL;
108 mc_global_t initial_state_liveness = NULL;
109 int compare;
110
111 /* Local */
112 xbt_dict_t mc_local_variables = NULL;
113 /* Global */
114 xbt_dynar_t mc_global_variables = NULL;
115
116 /* Ignore mechanism */
117 xbt_dynar_t mc_stack_comparison_ignore;
118 xbt_dynar_t mc_data_bss_comparison_ignore;
119 extern xbt_dynar_t mc_heap_comparison_ignore;
120 extern xbt_dynar_t stacks_areas;
121
122 FILE *dot_output = NULL;
123 const char* colors[10];
124
125 xbt_automaton_t _mc_property_automaton = NULL;
126
127 /* Static functions */
128
129 static void MC_assert_pair(int prop);
130 static dw_location_t get_location(xbt_dict_t location_list, char *expr);
131 static dw_frame_t get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset);
132 static size_t data_bss_ignore_size(void *address);
133 static void MC_get_global_variables(char *elf_file);
134
135 void MC_do_the_modelcheck_for_real() {
136
137   MC_SET_RAW_MEM;
138   mc_comp_times = xbt_new0(s_mc_comparison_times_t, 1);
139   MC_UNSET_RAW_MEM;
140   
141   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0'))
142     MC_init_dot_output();
143
144   if (!_sg_mc_property_file || _sg_mc_property_file[0]=='\0') {
145     if (mc_reduce_kind==e_mc_reduce_unset)
146       mc_reduce_kind=e_mc_reduce_dpor;
147
148     XBT_INFO("Check a safety property");
149     MC_modelcheck_safety();
150
151   } else  {
152
153     if (mc_reduce_kind==e_mc_reduce_unset)
154       mc_reduce_kind=e_mc_reduce_none;
155
156     XBT_INFO("Check the liveness property %s",_sg_mc_property_file);
157     MC_automaton_load(_sg_mc_property_file);
158     MC_modelcheck_liveness();
159   }
160 }
161
162
163 void MC_compare(void){
164   compare = 1;
165 }
166
167 void MC_init(){
168
169   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
170   
171   compare = 0;
172
173   /* Initialize the data structures that must be persistent across every
174      iteration of the model-checker (in RAW memory) */
175
176   MC_SET_RAW_MEM;
177
178   MC_init_memory_map_info();
179   
180   mc_local_variables = xbt_dict_new_homogeneous(NULL);
181
182   /* Get local variables in binary for state equality detection */
183   xbt_dict_t binary_location_list = MC_get_location_list(xbt_binary_name);
184   MC_get_local_variables(xbt_binary_name, binary_location_list, &mc_local_variables);
185
186   /* Get local variables in libsimgrid for state equality detection */
187   xbt_dict_t libsimgrid_location_list = MC_get_location_list(libsimgrid_path);
188   MC_get_local_variables(libsimgrid_path, libsimgrid_location_list, &mc_local_variables);
189
190   xbt_dict_free(&libsimgrid_location_list);
191   xbt_dict_free(&binary_location_list);
192   
193   /* Get .plt section (start and end addresses) for data libsimgrid and data program comparison */
194   get_libsimgrid_plt_section();
195   get_binary_plt_section();
196
197   /* Get global variables */
198   MC_get_global_variables(xbt_binary_name);
199   MC_get_global_variables(libsimgrid_path);
200
201   MC_UNSET_RAW_MEM;
202
203    /* Ignore some variables from xbt/ex.h used by exception e for stacks comparison */
204   MC_ignore_stack("e", "*");
205   MC_ignore_stack("__ex_cleanup", "*");
206   MC_ignore_stack("__ex_mctx_en", "*");
207   MC_ignore_stack("__ex_mctx_me", "*");
208   MC_ignore_stack("__xbt_ex_ctx_ptr", "*");
209   MC_ignore_stack("_log_ev", "*");
210   MC_ignore_stack("_throw_ctx", "*");
211   MC_ignore_stack("ctx", "*");
212
213   MC_ignore_stack("next_context", "smx_ctx_sysv_suspend_serial");
214   MC_ignore_stack("i", "smx_ctx_sysv_suspend_serial");
215
216   MC_ignore_data_bss(&mc_comp_times, sizeof(mc_comp_times));
217   MC_ignore_data_bss(&mc_snapshot_comparison_time, sizeof(mc_snapshot_comparison_time)); 
218   MC_ignore_data_bss(&mc_time, sizeof(mc_time));
219
220   if(raw_mem_set)
221     MC_SET_RAW_MEM;
222
223 }
224
225 void MC_init_dot_output(){
226
227   colors[0] = "blue";
228   colors[1] = "red";
229   colors[2] = "green";
230   colors[3] = "pink";
231   colors[4] = "brown";
232   colors[5] = "purple";
233   colors[6] = "yellow";
234   colors[7] = "orange";
235   
236   dot_output = fopen(_sg_mc_dot_output_file, "w");
237   
238   if(dot_output == NULL){
239     perror("Error open dot output file");
240     xbt_abort();
241   }
242
243   fprintf(dot_output, "digraph graphname{\n fixedsize=true; rankdir=TB; ranksep=.20; edge [fontsize=12]; node [fontsize=10, shape=circle,width=.5 ]; graph [resolution=20, fontsize=10];\n");
244
245 }
246
247 void MC_modelcheck_safety(void)
248 {
249   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
250
251   /* Check if MC is already initialized */
252   if (initial_state_safety)
253     return;
254
255   mc_time = xbt_new0(double, simix_process_maxpid);
256
257   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
258   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
259
260   /* Initialize the data structures that must be persistent across every
261      iteration of the model-checker (in RAW memory) */
262   
263   MC_SET_RAW_MEM;
264
265   /* Initialize statistics */
266   mc_stats = xbt_new0(s_mc_stats_t, 1);
267   mc_stats->state_size = 1;
268
269   /* Create exploration stack */
270   mc_stack_safety = xbt_fifo_new();
271
272   MC_UNSET_RAW_MEM;
273
274   if(_sg_mc_visited > 0){
275     MC_init();
276   }else{
277     MC_SET_RAW_MEM;
278     MC_init_memory_map_info();
279     get_libsimgrid_plt_section();
280     get_binary_plt_section();
281     MC_UNSET_RAW_MEM;
282   }
283
284   MC_dpor_init();
285
286   MC_SET_RAW_MEM;
287   /* Save the initial state */
288   initial_state_safety = xbt_new0(s_mc_global_t, 1);
289   initial_state_safety->snapshot = MC_take_snapshot();
290   MC_UNSET_RAW_MEM;
291
292   MC_dpor();
293
294   if(raw_mem_set)
295     MC_SET_RAW_MEM;
296
297   MC_exit();
298 }
299
300 void MC_modelcheck_liveness(){
301
302   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
303
304   MC_init();
305
306   mc_time = xbt_new0(double, simix_process_maxpid);
307
308   /* mc_time refers to clock for each process -> ignore it for heap comparison */  
309   MC_ignore_heap(mc_time, simix_process_maxpid * sizeof(double));
310  
311   MC_SET_RAW_MEM;
312  
313   /* Initialize statistics */
314   mc_stats = xbt_new0(s_mc_stats_t, 1);
315   mc_stats->state_size = 1;
316
317   /* Create exploration stack */
318   mc_stack_liveness = xbt_fifo_new();
319
320   /* Create the initial state */
321   initial_state_liveness = xbt_new0(s_mc_global_t, 1);
322
323   MC_UNSET_RAW_MEM;
324
325   MC_ddfs_init();
326
327   /* We're done */
328   MC_print_statistics(mc_stats);
329   xbt_free(mc_time);
330
331   if(raw_mem_set)
332     MC_SET_RAW_MEM;
333
334 }
335
336
337 void MC_exit(void)
338 {
339   MC_SET_RAW_MEM;
340   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
341     fprintf(dot_output, "}\n");
342     fclose(dot_output);
343   }
344   MC_UNSET_RAW_MEM;
345
346   xbt_free(mc_time);
347   MC_memory_exit();
348   xbt_abort();
349 }
350
351 int SIMIX_pre_mc_random(smx_simcall_t simcall){
352
353   return simcall->mc_value;
354 }
355
356
357 int MC_random(void)
358 {
359   /*FIXME: return mc_current_state->executed_transition->random.value;*/
360   return simcall_mc_random();
361 }
362
363 /**
364  * \brief Schedules all the process that are ready to run
365  */
366 void MC_wait_for_requests(void)
367 {
368   smx_process_t process;
369   smx_simcall_t req;
370   unsigned int iter;
371
372   while (!xbt_dynar_is_empty(simix_global->process_to_run)) {
373     SIMIX_process_runall();
374     xbt_dynar_foreach(simix_global->process_that_ran, iter, process) {
375       req = &process->simcall;
376       if (req->call != SIMCALL_NONE && !MC_request_is_visible(req))
377         SIMIX_simcall_pre(req, 0);
378     }
379   }
380 }
381
382 int MC_deadlock_check()
383 {
384   int deadlock = FALSE;
385   smx_process_t process;
386   if(xbt_swag_size(simix_global->process_list)){
387     deadlock = TRUE;
388     xbt_swag_foreach(process, simix_global->process_list){
389       if(process->simcall.call != SIMCALL_NONE
390          && MC_request_is_enabled(&process->simcall)){
391         deadlock = FALSE;
392         break;
393       }
394     }
395   }
396   return deadlock;
397 }
398
399 /**
400  * \brief Re-executes from the state at position start all the transitions indicated by
401  *        a given model-checker stack.
402  * \param stack The stack with the transitions to execute.
403  * \param start Start index to begin the re-execution.
404  */
405 void MC_replay(xbt_fifo_t stack, int start)
406 {
407   int raw_mem = (mmalloc_get_current_heap() == raw_heap);
408
409   int value, i = 1;
410   char *req_str;
411   smx_simcall_t req = NULL, saved_req = NULL;
412   xbt_fifo_item_t item, start_item;
413   mc_state_t state;
414
415   XBT_DEBUG("**** Begin Replay ****");
416
417   if(start == -1){
418     /* Restore the initial state */
419     MC_restore_snapshot(initial_state_safety->snapshot);
420     /* At the moment of taking the snapshot the raw heap was set, so restoring
421      * it will set it back again, we have to unset it to continue  */
422     MC_UNSET_RAW_MEM;
423   }
424
425   start_item = xbt_fifo_get_last_item(stack);
426   if(start != -1){
427     while (i != start){
428       start_item = xbt_fifo_get_prev_item(start_item);
429       i++;
430     }
431   }
432
433   /* Traverse the stack from the state at position start and re-execute the transitions */
434   for (item = start_item;
435        item != xbt_fifo_get_first_item(stack);
436        item = xbt_fifo_get_prev_item(item)) {
437
438     state = (mc_state_t) xbt_fifo_get_item_content(item);
439     saved_req = MC_state_get_executed_request(state, &value);
440    
441     if(saved_req){
442       /* because we got a copy of the executed request, we have to fetch the  
443          real one, pointed by the request field of the issuer process */
444       req = &saved_req->issuer->simcall;
445
446       /* Debug information */
447       if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
448         req_str = MC_request_to_string(req, value);
449         XBT_DEBUG("Replay: %s (%p)", req_str, state);
450         xbt_free(req_str);
451       }
452     }
453          
454     SIMIX_simcall_pre(req, value);
455     MC_wait_for_requests();
456          
457     /* Update statistics */
458     mc_stats->visited_states++;
459     mc_stats->executed_transitions++;
460   }
461   XBT_DEBUG("**** End Replay ****");
462
463   if(raw_mem)
464     MC_SET_RAW_MEM;
465   else
466     MC_UNSET_RAW_MEM;
467   
468
469 }
470
471 void MC_replay_liveness(xbt_fifo_t stack, int all_stack)
472 {
473
474   initial_state_liveness->raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
475
476   int value;
477   char *req_str;
478   smx_simcall_t req = NULL, saved_req = NULL;
479   xbt_fifo_item_t item;
480   mc_state_t state;
481   mc_pair_t pair;
482   int depth = 1;
483
484   XBT_DEBUG("**** Begin Replay ****");
485
486   /* Restore the initial state */
487   MC_restore_snapshot(initial_state_liveness->snapshot);
488
489   /* At the moment of taking the snapshot the raw heap was set, so restoring
490    * it will set it back again, we have to unset it to continue  */
491   if(!initial_state_liveness->raw_mem_set)
492     MC_UNSET_RAW_MEM;
493
494   if(all_stack){
495
496     item = xbt_fifo_get_last_item(stack);
497
498     while(depth <= xbt_fifo_size(stack)){
499
500       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
501       state = (mc_state_t) pair->graph_state;
502
503       if(pair->requests > 0){
504    
505         saved_req = MC_state_get_executed_request(state, &value);
506         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
507       
508         if(saved_req != NULL){
509           /* because we got a copy of the executed request, we have to fetch the  
510              real one, pointed by the request field of the issuer process */
511           req = &saved_req->issuer->simcall;
512           //XBT_DEBUG("Req->call %u", req->call);
513   
514           /* Debug information */
515           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
516             req_str = MC_request_to_string(req, value);
517             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
518             xbt_free(req_str);
519           }
520   
521         }
522  
523         SIMIX_simcall_pre(req, value);
524         MC_wait_for_requests();
525       }
526
527       depth++;
528     
529       /* Update statistics */
530       mc_stats->visited_states++;
531       mc_stats->executed_transitions++;
532
533       item = xbt_fifo_get_prev_item(item);
534     }
535
536   }else{
537
538     /* Traverse the stack from the initial state and re-execute the transitions */
539     for (item = xbt_fifo_get_last_item(stack);
540          item != xbt_fifo_get_first_item(stack);
541          item = xbt_fifo_get_prev_item(item)) {
542
543       pair = (mc_pair_t) xbt_fifo_get_item_content(item);
544       state = (mc_state_t) pair->graph_state;
545
546       if(pair->requests > 0){
547    
548         saved_req = MC_state_get_executed_request(state, &value);
549         //XBT_DEBUG("SavedReq->call %u", saved_req->call);
550       
551         if(saved_req != NULL){
552           /* because we got a copy of the executed request, we have to fetch the  
553              real one, pointed by the request field of the issuer process */
554           req = &saved_req->issuer->simcall;
555           //XBT_DEBUG("Req->call %u", req->call);
556   
557           /* Debug information */
558           if(XBT_LOG_ISENABLED(mc_global, xbt_log_priority_debug)){
559             req_str = MC_request_to_string(req, value);
560             XBT_DEBUG("Replay (depth = %d) : %s (%p)", depth, req_str, state);
561             xbt_free(req_str);
562           }
563   
564         }
565  
566         SIMIX_simcall_pre(req, value);
567         MC_wait_for_requests();
568       }
569
570       depth++;
571     
572       /* Update statistics */
573       mc_stats->visited_states++;
574       mc_stats->executed_transitions++;
575     }
576   }  
577
578   XBT_DEBUG("**** End Replay ****");
579
580   if(initial_state_liveness->raw_mem_set)
581     MC_SET_RAW_MEM;
582   else
583     MC_UNSET_RAW_MEM;
584   
585 }
586
587 /**
588  * \brief Dumps the contents of a model-checker's stack and shows the actual
589  *        execution trace
590  * \param stack The stack to dump
591  */
592 void MC_dump_stack_safety(xbt_fifo_t stack)
593 {
594   
595   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
596
597   MC_show_stack_safety(stack);
598
599   if(!_sg_mc_checkpoint){
600
601     mc_state_t state;
602
603     MC_SET_RAW_MEM;
604     while ((state = (mc_state_t) xbt_fifo_pop(stack)) != NULL)
605       MC_state_delete(state);
606     MC_UNSET_RAW_MEM;
607
608   }
609
610   if(raw_mem_set)
611     MC_SET_RAW_MEM;
612   else
613     MC_UNSET_RAW_MEM;
614   
615 }
616
617
618 void MC_show_stack_safety(xbt_fifo_t stack)
619 {
620   int value;
621   mc_state_t state;
622   xbt_fifo_item_t item;
623   smx_simcall_t req;
624   char *req_str = NULL;
625   
626   for (item = xbt_fifo_get_last_item(stack);
627        (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
628         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
629     req = MC_state_get_executed_request(state, &value);
630     if(req){
631       req_str = MC_request_to_string(req, value);
632       XBT_INFO("%s", req_str);
633       xbt_free(req_str);
634     }
635   }
636 }
637
638 void MC_show_deadlock(smx_simcall_t req)
639 {
640   /*char *req_str = NULL;*/
641   XBT_INFO("**************************");
642   XBT_INFO("*** DEAD-LOCK DETECTED ***");
643   XBT_INFO("**************************");
644   XBT_INFO("Locked request:");
645   /*req_str = MC_request_to_string(req);
646     XBT_INFO("%s", req_str);
647     xbt_free(req_str);*/
648   XBT_INFO("Counter-example execution trace:");
649   MC_dump_stack_safety(mc_stack_safety);
650 }
651
652
653 void MC_show_stack_liveness(xbt_fifo_t stack){
654   int value;
655   mc_pair_t pair;
656   xbt_fifo_item_t item;
657   smx_simcall_t req;
658   char *req_str = NULL;
659   
660   for (item = xbt_fifo_get_last_item(stack);
661        (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item)))
662         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
663     req = MC_state_get_executed_request(pair->graph_state, &value);
664     if(req){
665       if(pair->requests>0){
666         req_str = MC_request_to_string(req, value);
667         XBT_INFO("%s", req_str);
668         xbt_free(req_str);
669       }else{
670         XBT_INFO("End of system requests but evolution in Büchi automaton");
671       }
672     }
673   }
674 }
675
676 void MC_dump_stack_liveness(xbt_fifo_t stack){
677
678   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
679
680   mc_pair_t pair;
681
682   MC_SET_RAW_MEM;
683   while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
684     MC_pair_delete(pair);
685   MC_UNSET_RAW_MEM;
686
687   if(raw_mem_set)
688     MC_SET_RAW_MEM;
689
690 }
691
692
693 void MC_print_statistics(mc_stats_t stats)
694 {
695   //XBT_INFO("State space size ~= %lu", stats->state_size);
696   XBT_INFO("Expanded states = %lu", stats->expanded_states);
697   XBT_INFO("Visited states = %lu", stats->visited_states);
698   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
699   XBT_INFO("Expanded / Visited = %lf",
700            (double) stats->visited_states / stats->expanded_states);
701   /*XBT_INFO("Exploration coverage = %lf",
702     (double)stats->expanded_states / stats->state_size); */
703 }
704
705 void MC_assert(int prop)
706 {
707   if (MC_is_active() && !prop){
708     XBT_INFO("**************************");
709     XBT_INFO("*** PROPERTY NOT VALID ***");
710     XBT_INFO("**************************");
711     XBT_INFO("Counter-example execution trace:");
712     MC_dump_stack_safety(mc_stack_safety);
713     MC_print_statistics(mc_stats);
714     xbt_abort();
715   }
716 }
717
718 static void MC_assert_pair(int prop){
719   if (MC_is_active() && !prop) {
720     XBT_INFO("**************************");
721     XBT_INFO("*** PROPERTY NOT VALID ***");
722     XBT_INFO("**************************");
723     //XBT_INFO("Counter-example execution trace:");
724     MC_show_stack_liveness(mc_stack_liveness);
725     //MC_dump_snapshot_stack(mc_snapshot_stack);
726     MC_print_statistics(mc_stats);
727     xbt_abort();
728   }
729 }
730
731 void MC_process_clock_add(smx_process_t process, double amount)
732 {
733   mc_time[process->pid] += amount;
734 }
735
736 double MC_process_clock_get(smx_process_t process)
737 {
738   if(mc_time){
739     if(process != NULL)
740       return mc_time[process->pid];
741     else 
742       return -1;
743   }else{
744     return 0;
745   }
746 }
747
748 void MC_automaton_load(const char *file){
749
750   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
751
752   MC_SET_RAW_MEM;
753
754   if (_mc_property_automaton == NULL)
755     _mc_property_automaton = xbt_automaton_new();
756   
757   xbt_automaton_load(_mc_property_automaton,file);
758
759   MC_UNSET_RAW_MEM;
760
761   if(raw_mem_set)
762     MC_SET_RAW_MEM;
763
764 }
765
766 void MC_automaton_new_propositional_symbol(const char* id, void* fct) {
767
768   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
769
770   MC_SET_RAW_MEM;
771
772   if (_mc_property_automaton == NULL)
773     _mc_property_automaton = xbt_automaton_new();
774
775   xbt_automaton_propositional_symbol_new(_mc_property_automaton,id,fct);
776
777   MC_UNSET_RAW_MEM;
778
779   if(raw_mem_set)
780     MC_SET_RAW_MEM;
781   
782 }
783
784 /************ MC_ignore ***********/ 
785
786 void heap_ignore_region_free(mc_heap_ignore_region_t r){
787   xbt_free(r);
788 }
789
790 void heap_ignore_region_free_voidp(void *r){
791   heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
792 }
793
794 void MC_ignore_heap(void *address, size_t size){
795
796   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
797
798   MC_SET_RAW_MEM;
799
800   mc_heap_ignore_region_t region = NULL;
801   region = xbt_new0(s_mc_heap_ignore_region_t, 1);
802   region->address = address;
803   region->size = size;
804   
805   region->block = ((char*)address - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
806   
807   if(((xbt_mheap_t)std_heap)->heapinfo[region->block].type == 0){
808     region->fragment = -1;
809     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore = 1;
810   }else{
811     region->fragment = ((uintptr_t) (ADDR2UINT (address) % (BLOCKSIZE))) >> ((xbt_mheap_t)std_heap)->heapinfo[region->block].type;
812     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment] = 1;
813   }
814   
815   if(mc_heap_comparison_ignore == NULL){
816     mc_heap_comparison_ignore = xbt_dynar_new(sizeof(mc_heap_ignore_region_t), heap_ignore_region_free_voidp);
817     xbt_dynar_push(mc_heap_comparison_ignore, &region);
818     if(!raw_mem_set)
819       MC_UNSET_RAW_MEM;
820     return;
821   }
822
823   unsigned int cursor = 0;
824   mc_heap_ignore_region_t current_region;
825   int start = 0;
826   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
827   
828   while(start <= end){
829     cursor = (start + end) / 2;
830     current_region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
831     if(current_region->address == address){
832       heap_ignore_region_free(region);
833       if(!raw_mem_set)
834         MC_UNSET_RAW_MEM;
835       return;
836     }
837     if(current_region->address < address)
838       start = cursor + 1;
839     if(current_region->address > address)
840       end = cursor - 1;   
841   }
842
843   if(current_region->address < address)
844     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
845   else
846     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
847
848   MC_UNSET_RAW_MEM;
849
850   if(raw_mem_set)
851     MC_SET_RAW_MEM;
852 }
853
854 void MC_remove_ignore_heap(void *address, size_t size){
855
856   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
857
858   MC_SET_RAW_MEM;
859
860   unsigned int cursor = 0;
861   int start = 0;
862   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
863   mc_heap_ignore_region_t region;
864   int ignore_found = 0;
865
866   while(start <= end){
867     cursor = (start + end) / 2;
868     region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
869     if(region->address == address){
870       ignore_found = 1;
871       break;
872     }
873     if(region->address < address)
874       start = cursor + 1;
875     if(region->address > address){
876       if((char * )region->address <= ((char *)address + size)){
877         ignore_found = 1;
878         break;
879       }else
880         end = cursor - 1;   
881     }
882   }
883   
884   if(ignore_found == 1){
885     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
886     MC_remove_ignore_heap(address, size);
887   }
888
889   MC_UNSET_RAW_MEM;
890   
891   if(raw_mem_set)
892     MC_SET_RAW_MEM;
893
894 }
895
896 void MC_ignore_data_bss(void *address, size_t size){
897
898   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
899
900   MC_SET_RAW_MEM;
901   
902   if(mc_data_bss_comparison_ignore == NULL)
903     mc_data_bss_comparison_ignore = xbt_dynar_new(sizeof(mc_data_bss_ignore_variable_t), NULL);
904
905   mc_data_bss_ignore_variable_t var = NULL;
906   var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1);
907   var->address = address;
908   var->size = size;
909
910   if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){
911
912     xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var);
913
914   }else{
915     
916     unsigned int cursor = 0;
917     int start = 0;
918     int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
919     mc_data_bss_ignore_variable_t current_var = NULL;
920
921     while(start <= end){
922       cursor = (start + end) / 2;
923       current_var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
924       if(current_var->address == address){
925         MC_UNSET_RAW_MEM;
926         if(raw_mem_set)
927           MC_SET_RAW_MEM;
928         return;
929       }
930       if(current_var->address < address)
931         start = cursor + 1;
932       if(current_var->address > address)
933         end = cursor - 1;
934     }
935
936     if(current_var->address < address)
937       xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor + 1, &var);
938     else
939       xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor, &var);
940
941   }
942
943   /* Remove variable from mc_global_variables */
944
945   if(mc_global_variables != NULL){
946
947     unsigned int cursor = 0;
948     int start = 0;
949     int end = xbt_dynar_length(mc_global_variables) - 1;
950     global_variable_t current_var;
951     int var_found;
952
953     while(start <= end){
954       cursor = (start + end) / 2;
955       current_var = (global_variable_t)xbt_dynar_get_as(mc_global_variables, cursor, global_variable_t);
956       if(current_var->address == var->address){
957         var_found = 1;
958         break;
959       }
960       if(current_var->address < address)
961         start = cursor + 1;
962       if(current_var->address > address)
963         end = cursor - 1;
964     }
965
966     if(var_found)
967       xbt_dynar_remove_at(mc_global_variables, cursor, NULL);
968     
969   }
970
971   MC_UNSET_RAW_MEM;
972
973   if(raw_mem_set)
974     MC_SET_RAW_MEM;
975 }
976
977 static size_t data_bss_ignore_size(void *address){
978   unsigned int cursor = 0;
979   int start = 0;
980   int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
981   mc_data_bss_ignore_variable_t var;
982
983   while(start <= end){
984     cursor = (start + end) / 2;
985     var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
986     if(var->address == address)
987       return var->size;
988     if(var->address < address){
989       if((void *)((char *)var->address + var->size) > address)
990         return (char *)var->address + var->size - (char*)address;
991       else
992         start = cursor + 1;
993     }
994     if(var->address > address)
995       end = cursor - 1;   
996   }
997
998   return 0;
999 }
1000
1001
1002
1003 void MC_ignore_stack(const char *var_name, const char *frame_name){
1004   
1005   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1006
1007   MC_SET_RAW_MEM;
1008
1009   if(mc_stack_comparison_ignore == NULL)
1010     mc_stack_comparison_ignore = xbt_dynar_new(sizeof(mc_stack_ignore_variable_t), NULL);
1011
1012   if(xbt_dynar_is_empty(mc_stack_comparison_ignore)){
1013
1014     mc_stack_ignore_variable_t var = NULL;
1015     var = xbt_new0(s_mc_stack_ignore_variable_t, 1);
1016     var->var_name = strdup(var_name);
1017     var->frame = strdup(frame_name);
1018
1019     xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var);
1020
1021   }else{
1022     
1023     unsigned int cursor = 0;
1024     int start = 0;
1025     int end = xbt_dynar_length(mc_stack_comparison_ignore) - 1;
1026     mc_stack_ignore_variable_t current_var = NULL;
1027
1028     while(start <= end){
1029       cursor = (start + end) / 2;
1030       current_var = (mc_stack_ignore_variable_t)xbt_dynar_get_as(mc_stack_comparison_ignore, cursor, mc_stack_ignore_variable_t);
1031       if(strcmp(current_var->frame, frame_name) == 0){
1032         if(strcmp(current_var->var_name, var_name) == 0){
1033           MC_UNSET_RAW_MEM;
1034           if(raw_mem_set)
1035             MC_SET_RAW_MEM;
1036           return;
1037         }
1038         if(strcmp(current_var->var_name, var_name) < 0)
1039           start = cursor + 1;
1040         if(strcmp(current_var->var_name, var_name) > 0)
1041           end = cursor - 1;
1042       }
1043       if(strcmp(current_var->frame, frame_name) < 0)
1044         start = cursor + 1;
1045       if(strcmp(current_var->frame, frame_name) > 0)
1046         end = cursor - 1;
1047     }
1048
1049     mc_stack_ignore_variable_t var = NULL;
1050     var = xbt_new0(s_mc_stack_ignore_variable_t, 1);
1051     var->var_name = strdup(var_name);
1052     var->frame = strdup(frame_name);
1053
1054     if(strcmp(current_var->frame, frame_name) < 0)
1055       xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
1056     else
1057       xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
1058
1059   }
1060
1061  /* Remove variable from mc_local_variables */
1062
1063   if(mc_local_variables != NULL){
1064
1065     if(strcmp(frame_name, "*") != 0){
1066       dw_frame_t frame = xbt_dict_get_or_null(mc_local_variables, frame_name);
1067       if(frame != NULL)
1068         xbt_dict_remove(frame->variables, var_name);
1069     }
1070
1071   }
1072
1073   MC_UNSET_RAW_MEM;
1074   
1075   if(raw_mem_set)
1076     MC_SET_RAW_MEM;
1077
1078 }
1079
1080 void MC_new_stack_area(void *stack, char *name, void* context, size_t size){
1081
1082   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1083
1084   MC_SET_RAW_MEM;
1085   if(stacks_areas == NULL)
1086     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
1087   
1088   stack_region_t region = NULL;
1089   region = xbt_new0(s_stack_region_t, 1);
1090   region->address = stack;
1091   region->process_name = strdup(name);
1092   region->context = context;
1093   region->size = size;
1094   region->block = ((char*)stack - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
1095   xbt_dynar_push(stacks_areas, &region);
1096   
1097   MC_UNSET_RAW_MEM;
1098
1099   if(raw_mem_set)
1100     MC_SET_RAW_MEM;
1101 }
1102
1103 /************ DWARF ***********/
1104
1105 xbt_dict_t MC_get_location_list(const char *elf_file){
1106
1107   char *command = bprintf("objdump -Wo %s", elf_file);
1108
1109   FILE *fp = popen(command, "r");
1110
1111   if(fp == NULL){
1112     perror("popen for objdump failed");
1113     xbt_abort();
1114   }
1115
1116   int debug = 0; /*Detect if the program has been compiled with -g */
1117
1118   xbt_dict_t location_list = xbt_dict_new_homogeneous(NULL);
1119   char *line = NULL, *loc_expr = NULL;
1120   ssize_t read;
1121   size_t n = 0;
1122   int cursor_remove;
1123   xbt_dynar_t split = NULL;
1124
1125   while ((read = xbt_getline(&line, &n, fp)) != -1) {
1126
1127     /* Wipeout the new line character */
1128     line[read - 1] = '\0';
1129
1130     xbt_str_trim(line, NULL);
1131     
1132     if(n == 0)
1133       continue;
1134
1135     if(strlen(line) == 0)
1136       continue;
1137
1138     if(debug == 0){
1139
1140       if(strncmp(line, elf_file, strlen(elf_file)) == 0)
1141         continue;
1142       
1143       if(strncmp(line, "Contents", 8) == 0)
1144         continue;
1145
1146       if(strncmp(line, "Offset", 6) == 0){
1147         debug = 1;
1148         continue;
1149       }
1150     }
1151
1152     if(debug == 0){
1153       XBT_INFO("Your program must be compiled with -g");
1154       xbt_abort();
1155     }
1156
1157     xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
1158
1159     xbt_str_strip_spaces(line);
1160     split = xbt_str_split(line, " ");
1161
1162     while(read != -1 && strcmp("<End", (char *)xbt_dynar_get_as(split, 1, char *)) != 0){
1163       
1164       dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
1165       new_entry->lowpc = strtoul((char *)xbt_dynar_get_as(split, 1, char *), NULL, 16);
1166       new_entry->highpc = strtoul((char *)xbt_dynar_get_as(split, 2, char *), NULL, 16);
1167       
1168       cursor_remove =0;
1169       while(cursor_remove < 3){
1170         xbt_dynar_remove_at(split, 0, NULL);
1171         cursor_remove++;
1172       }
1173
1174       loc_expr = xbt_str_join(split, " ");
1175       xbt_str_ltrim(loc_expr, "(");
1176       xbt_str_rtrim(loc_expr, ")");
1177       new_entry->location = get_location(NULL, loc_expr);
1178
1179       xbt_dynar_push(loclist, &new_entry);
1180
1181       xbt_dynar_free(&split);
1182       free(loc_expr);
1183
1184       read = xbt_getline(&line, &n, fp);
1185       if(read != -1){
1186         line[read - 1] = '\0';
1187         xbt_str_strip_spaces(line);
1188         split = xbt_str_split(line, " ");
1189       }
1190
1191     }
1192
1193
1194     char *key = bprintf("%d", (int)strtoul((char *)xbt_dynar_get_as(split, 0, char *), NULL, 16));
1195     xbt_dict_set(location_list, key, loclist, NULL);
1196     xbt_free(key);
1197     
1198     xbt_dynar_free(&split);
1199
1200   }
1201
1202   xbt_free(line);
1203   xbt_free(command);
1204   pclose(fp);
1205
1206   return location_list;
1207 }
1208
1209 static dw_frame_t get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset){
1210
1211   xbt_dict_cursor_t cursor = NULL;
1212   char *name;
1213   dw_frame_t res;
1214
1215   xbt_dict_foreach(all_variables, cursor, name, res) {
1216     if(offset >= res->start && offset < res->end){
1217       xbt_dict_cursor_free(&cursor);
1218       return res;
1219     }
1220   }
1221
1222   xbt_dict_cursor_free(&cursor);
1223   return NULL;
1224   
1225 }
1226
1227 void MC_get_local_variables(const char *elf_file, xbt_dict_t location_list, xbt_dict_t *all_variables){
1228
1229   char *command = bprintf("objdump -Wi %s", elf_file);
1230   
1231   FILE *fp = popen(command, "r");
1232
1233   if(fp == NULL)
1234     perror("popen for objdump failed");
1235
1236   char *line = NULL, *origin, *abstract_origin, *current_frame = NULL;
1237   ssize_t read =0;
1238   size_t n = 0;
1239   int valid_variable = 1;
1240   char *node_type = NULL, *location_type = NULL, *variable_name = NULL, *loc_expr = NULL;
1241   xbt_dynar_t split = NULL, split2 = NULL;
1242
1243   xbt_dict_t variables_origin = xbt_dict_new_homogeneous(NULL);
1244   xbt_dict_t subprograms_origin = xbt_dict_new_homogeneous(NULL);
1245   char *subprogram_name = NULL, *subprogram_start = NULL, *subprogram_end = NULL;
1246   int new_frame = 0, new_variable = 0;
1247   dw_frame_t variable_frame, subroutine_frame = NULL;
1248
1249   read = xbt_getline(&line, &n, fp);
1250
1251   while (read != -1) {
1252
1253     if(n == 0){
1254       read = xbt_getline(&line, &n, fp);
1255       continue;
1256     }
1257  
1258     /* Wipeout the new line character */
1259     line[read - 1] = '\0';
1260    
1261     if(strlen(line) == 0){
1262       read = xbt_getline(&line, &n, fp);
1263       continue;
1264     }
1265
1266     xbt_str_ltrim(line, NULL);
1267     xbt_str_strip_spaces(line);
1268     
1269     if(line[0] != '<'){
1270       read = xbt_getline(&line, &n, fp);
1271       continue;
1272     }
1273     
1274     xbt_dynar_free(&split);
1275     split = xbt_str_split(line, " ");
1276
1277     /* Get node type */
1278     node_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
1279
1280     if(strcmp(node_type, "(DW_TAG_subprogram)") == 0){ /* New frame */
1281
1282       dw_frame_t frame = NULL;
1283
1284       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1285       subprogram_start = strdup(strtok(NULL, "<"));
1286       xbt_str_rtrim(subprogram_start, ">:");
1287
1288       read = xbt_getline(&line, &n, fp);
1289    
1290       while(read != -1){
1291
1292         if(n == 0){
1293           read = xbt_getline(&line, &n, fp);
1294           continue;
1295         }
1296
1297         /* Wipeout the new line character */
1298         line[read - 1] = '\0';
1299         
1300         if(strlen(line) == 0){
1301           read = xbt_getline(&line, &n, fp);
1302           continue;
1303         }
1304       
1305         xbt_dynar_free(&split);
1306         xbt_str_rtrim(line, NULL);
1307         xbt_str_strip_spaces(line);
1308         split = xbt_str_split(line, " ");
1309           
1310         node_type = xbt_dynar_get_as(split, 1, char *);
1311
1312         if(strncmp(node_type, "DW_AT_", 6) != 0)
1313           break;
1314
1315         if(strcmp(node_type, "DW_AT_sibling") == 0){
1316
1317           subprogram_end = strdup(xbt_dynar_get_as(split, 3, char*));
1318           xbt_str_ltrim(subprogram_end, "<0x");
1319           xbt_str_rtrim(subprogram_end, ">");
1320           
1321         }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){ /* Frame already in dict */
1322           
1323           new_frame = 0;
1324           abstract_origin = strdup(xbt_dynar_get_as(split, 2, char*));
1325           xbt_str_ltrim(abstract_origin, "<0x");
1326           xbt_str_rtrim(abstract_origin, ">");
1327           subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, abstract_origin);
1328           frame = xbt_dict_get_or_null(*all_variables, subprogram_name); 
1329           xbt_free(abstract_origin);
1330
1331         }else if(strcmp(node_type, "DW_AT_name") == 0){
1332
1333           new_frame = 1;
1334           xbt_free(current_frame);
1335           frame = xbt_new0(s_dw_frame_t, 1);
1336           frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); 
1337           frame->variables = xbt_dict_new_homogeneous(NULL);
1338           frame->frame_base = xbt_new0(s_dw_location_t, 1); 
1339           current_frame = strdup(frame->name);
1340
1341           xbt_dict_set(subprograms_origin, subprogram_start, frame->name, NULL);
1342         
1343         }else if(strcmp(node_type, "DW_AT_frame_base") == 0){
1344
1345           location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
1346
1347           if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
1348
1349             frame->frame_base = get_location(location_list, xbt_dynar_get_as(split, 3, char *));
1350              
1351           }else{
1352                 
1353             xbt_str_strip_spaces(line);
1354             split2 = xbt_str_split(line, "(");
1355             xbt_dynar_remove_at(split2, 0, NULL);
1356             loc_expr = xbt_str_join(split2, " ");
1357             xbt_str_rtrim(loc_expr, ")");
1358             frame->frame_base = get_location(NULL, loc_expr);
1359             xbt_dynar_free(&split2);
1360             xbt_free(loc_expr);
1361
1362           }
1363  
1364         }else if(strcmp(node_type, "DW_AT_low_pc") == 0){
1365           
1366           if(frame != NULL)
1367             frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1368
1369         }else if(strcmp(node_type, "DW_AT_high_pc") == 0){
1370
1371           if(frame != NULL)
1372             frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1373
1374         }else if(strcmp(node_type, "DW_AT_MIPS_linkage_name:") == 0){
1375
1376           xbt_free(frame->name);
1377           xbt_free(current_frame);
1378           frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));   
1379           current_frame = strdup(frame->name);
1380           xbt_dict_set(subprograms_origin, subprogram_start, frame->name, NULL);
1381
1382         }
1383
1384         read = xbt_getline(&line, &n, fp);
1385
1386       }
1387  
1388       if(new_frame == 1){
1389         frame->start = strtoul(subprogram_start, NULL, 16);
1390         if(subprogram_end != NULL)
1391           frame->end = strtoul(subprogram_end, NULL, 16);
1392         xbt_dict_set(*all_variables, frame->name, frame, NULL);
1393       }
1394
1395       xbt_free(subprogram_start);
1396       xbt_free(subprogram_end);
1397       subprogram_end = NULL;
1398         
1399
1400     }else if(strcmp(node_type, "(DW_TAG_variable)") == 0){ /* New variable */
1401
1402       dw_local_variable_t var = NULL;
1403       
1404       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1405       origin = strdup(strtok(NULL, "<"));
1406       xbt_str_rtrim(origin, ">:");
1407       
1408       read = xbt_getline(&line, &n, fp);
1409       
1410       while(read != -1){
1411
1412         if(n == 0){
1413           read = xbt_getline(&line, &n, fp);
1414           continue;
1415         }
1416
1417         /* Wipeout the new line character */
1418         line[read - 1] = '\0'; 
1419
1420         if(strlen(line) == 0){
1421           read = xbt_getline(&line, &n, fp);
1422           continue;
1423         }
1424        
1425         xbt_dynar_free(&split);
1426         xbt_str_rtrim(line, NULL);
1427         xbt_str_strip_spaces(line);
1428         split = xbt_str_split(line, " ");
1429   
1430         node_type = xbt_dynar_get_as(split, 1, char *);
1431
1432         if(strncmp(node_type, "DW_AT_", 6) != 0)
1433           break;
1434
1435         if(strcmp(node_type, "DW_AT_name") == 0){
1436
1437           new_variable = 1;
1438           var = xbt_new0(s_dw_local_variable_t, 1);
1439           var->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));
1440
1441           xbt_dict_set(variables_origin, origin, var->name, NULL);
1442          
1443         }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){
1444
1445           new_variable = 0;
1446           abstract_origin = xbt_dynar_get_as(split, 2, char *);
1447           xbt_str_ltrim(abstract_origin, "<0x");
1448           xbt_str_rtrim(abstract_origin, ">");
1449           
1450           variable_name = (char *)xbt_dict_get_or_null(variables_origin, abstract_origin);
1451           variable_frame = get_frame_by_offset(*all_variables, strtoul(abstract_origin, NULL, 16));
1452           var = xbt_dict_get_or_null(variable_frame->variables, variable_name);   
1453
1454         }else if(strcmp(node_type, "DW_AT_location") == 0){
1455
1456           if(valid_variable == 1 && var != NULL){
1457
1458             var->location = xbt_new0(s_dw_location_t, 1);
1459
1460             location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
1461
1462             if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
1463
1464               var->location = get_location(location_list, xbt_dynar_get_as(split, 3, char *));
1465              
1466             }else{
1467                 
1468               xbt_str_strip_spaces(line);
1469               split2 = xbt_str_split(line, "(");
1470               xbt_dynar_remove_at(split2, 0, NULL);
1471               loc_expr = xbt_str_join(split2, " ");
1472               xbt_str_rtrim(loc_expr, ")");
1473               var->location = get_location(NULL, loc_expr);
1474               xbt_dynar_free(&split2);
1475               xbt_free(loc_expr);
1476
1477             }
1478
1479           }
1480            
1481         }else if(strcmp(node_type, "DW_AT_external") == 0){
1482
1483           valid_variable = 0;
1484         
1485         }
1486
1487         read = xbt_getline(&line, &n, fp);
1488  
1489       }
1490
1491       if(new_variable == 1 && valid_variable == 1){
1492         
1493         variable_frame = xbt_dict_get_or_null(*all_variables, current_frame);
1494         xbt_dict_set(variable_frame->variables, var->name, var, NULL);
1495       }
1496
1497       valid_variable = 1;
1498       new_variable = 0;
1499
1500     }else if(strcmp(node_type, "(DW_TAG_inlined_subroutine)") == 0){
1501
1502       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1503       origin = strdup(strtok(NULL, "<"));
1504       xbt_str_rtrim(origin, ">:");
1505
1506       read = xbt_getline(&line, &n, fp);
1507
1508       while(read != -1){
1509
1510         /* Wipeout the new line character */
1511         line[read - 1] = '\0'; 
1512
1513         if(n == 0){
1514           read = xbt_getline(&line, &n, fp);
1515           continue;
1516         }
1517
1518         if(strlen(line) == 0){
1519           read = xbt_getline(&line, &n, fp);
1520           continue;
1521         }
1522
1523         xbt_dynar_free(&split);
1524         xbt_str_rtrim(line, NULL);
1525         xbt_str_strip_spaces(line);
1526         split = xbt_str_split(line, " ");
1527         
1528         if(strncmp(xbt_dynar_get_as(split, 1, char *), "DW_AT_", 6) != 0)
1529           break;
1530           
1531         node_type = xbt_dynar_get_as(split, 1, char *);
1532
1533         if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){
1534
1535           origin = xbt_dynar_get_as(split, 2, char *);
1536           xbt_str_ltrim(origin, "<0x");
1537           xbt_str_rtrim(origin, ">");
1538           
1539           subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, origin);
1540           subroutine_frame = xbt_dict_get_or_null(*all_variables, subprogram_name);
1541         
1542         }else if(strcmp(node_type, "DW_AT_low_pc") == 0){
1543
1544           subroutine_frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1545
1546         }else if(strcmp(node_type, "DW_AT_high_pc") == 0){
1547
1548           subroutine_frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1549         }
1550
1551         read = xbt_getline(&line, &n, fp);
1552       
1553       }
1554
1555     }else{
1556
1557       read = xbt_getline(&line, &n, fp);
1558
1559     }
1560
1561   }
1562   
1563   xbt_dynar_free(&split);
1564   xbt_free(line);
1565   xbt_free(command);
1566   pclose(fp);
1567   
1568 }
1569
1570 static dw_location_t get_location(xbt_dict_t location_list, char *expr){
1571
1572   dw_location_t loc = xbt_new0(s_dw_location_t, 1);
1573
1574   if(location_list != NULL){
1575     
1576     char *key = bprintf("%d", (int)strtoul(expr, NULL, 16));
1577     loc->type = e_dw_loclist;
1578     loc->location.loclist =  (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
1579     if(loc->location.loclist == NULL)
1580       XBT_INFO("Key not found in loclist");
1581     xbt_free(key);
1582     return loc;
1583
1584   }else{
1585
1586     int cursor = 0;
1587     char *tok = NULL, *tok2 = NULL; 
1588     
1589     xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
1590     xbt_dynar_t tokens2;
1591
1592     loc->type = e_dw_compose;
1593     loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
1594
1595     while(cursor < xbt_dynar_length(tokens1)){
1596
1597       tok = xbt_dynar_get_as(tokens1, cursor, char*);
1598       tokens2 = xbt_str_split(tok, " ");
1599       tok2 = xbt_dynar_get_as(tokens2, 0, char*);
1600       
1601       if(strncmp(tok2, "DW_OP_reg", 9) == 0){
1602         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1603         new_element->type = e_dw_register;
1604         new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
1605         xbt_dynar_push(loc->location.compose, &new_element);     
1606       }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
1607         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1608         new_element->type = e_dw_fbregister_op;
1609         new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1610         xbt_dynar_push(loc->location.compose, &new_element);
1611       }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
1612         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1613         new_element->type = e_dw_bregister_op;
1614         new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
1615         new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1616         xbt_dynar_push(loc->location.compose, &new_element);
1617       }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
1618         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1619         new_element->type = e_dw_lit;
1620         new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
1621         xbt_dynar_push(loc->location.compose, &new_element);
1622       }else if(strcmp(tok2, "DW_OP_piece:") == 0){
1623         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1624         new_element->type = e_dw_piece;
1625         new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1626         /*if(strlen(xbt_dynar_get_as(tokens2, 1, char*)) > 1)
1627           new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, 1, char*));
1628         else
1629         new_element->location.piece = xbt_dynar_get_as(tokens2, 1, char*)[0] - '0';*/
1630         xbt_dynar_push(loc->location.compose, &new_element);
1631       }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
1632         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1633         new_element->type = e_dw_plus_uconst;
1634         new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
1635         xbt_dynar_push(loc->location.compose, &new_element);
1636       }else if(strcmp(tok, "DW_OP_abs") == 0 || 
1637                strcmp(tok, "DW_OP_and") == 0 ||
1638                strcmp(tok, "DW_OP_div") == 0 ||
1639                strcmp(tok, "DW_OP_minus") == 0 ||
1640                strcmp(tok, "DW_OP_mod") == 0 ||
1641                strcmp(tok, "DW_OP_mul") == 0 ||
1642                strcmp(tok, "DW_OP_neg") == 0 ||
1643                strcmp(tok, "DW_OP_not") == 0 ||
1644                strcmp(tok, "DW_OP_or") == 0 ||
1645                strcmp(tok, "DW_OP_plus") == 0){               
1646         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1647         new_element->type = e_dw_arithmetic;
1648         new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
1649         xbt_dynar_push(loc->location.compose, &new_element);
1650       }else if(strcmp(tok, "DW_OP_stack_value") == 0){
1651       }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
1652         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1653         new_element->type = e_dw_deref;
1654         new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1655         /*if(strlen(xbt_dynar_get_as(tokens, ++cursor, char*)) > 1)
1656           new_element->location.deref_size = atoi(xbt_dynar_get_as(tokens, cursor, char*));
1657         else
1658         new_element->location.deref_size = xbt_dynar_get_as(tokens, cursor, char*)[0] - '0';*/
1659         xbt_dynar_push(loc->location.compose, &new_element);
1660       }else if(strcmp(tok, "DW_OP_deref") == 0){
1661         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1662         new_element->type = e_dw_deref;
1663         new_element->location.deref_size = sizeof(void *);
1664         xbt_dynar_push(loc->location.compose, &new_element);
1665       }else if(strcmp(tok2, "DW_OP_constu:") == 0){
1666         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1667         new_element->type = e_dw_uconstant;
1668         new_element->location.uconstant.bytes = 1;
1669         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1670         /*if(strlen(xbt_dynar_get_as(tokens, ++cursor, char*)) > 1)
1671           new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens, cursor, char*)));
1672         else
1673         new_element->location.uconstant.value = (unsigned long int)(xbt_dynar_get_as(tokens, cursor, char*)[0] - '0');*/
1674         xbt_dynar_push(loc->location.compose, &new_element);
1675       }else if(strcmp(tok2, "DW_OP_consts:") == 0){
1676         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1677         new_element->type = e_dw_sconstant;
1678         new_element->location.sconstant.bytes = 1;
1679         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1680         xbt_dynar_push(loc->location.compose, &new_element);
1681       }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
1682                strcmp(tok2, "DW_OP_const2u:") == 0 ||
1683                strcmp(tok2, "DW_OP_const4u:") == 0 ||
1684                strcmp(tok2, "DW_OP_const8u:") == 0){
1685         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1686         new_element->type = e_dw_uconstant;
1687         new_element->location.uconstant.bytes = tok2[11] - '0';
1688         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1689         /*if(strlen(xbt_dynar_get_as(tokens, ++cursor, char*)) > 1)
1690           new_element->location.constant.value = atoi(xbt_dynar_get_as(tokens, cursor, char*));
1691         else
1692         new_element->location.constant.value = xbt_dynar_get_as(tokens, cursor, char*)[0] - '0';*/
1693         xbt_dynar_push(loc->location.compose, &new_element);
1694       }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
1695                strcmp(tok, "DW_OP_const2s") == 0 ||
1696                strcmp(tok, "DW_OP_const4s") == 0 ||
1697                strcmp(tok, "DW_OP_const8s") == 0){
1698         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1699         new_element->type = e_dw_sconstant;
1700         new_element->location.sconstant.bytes = tok2[11] - '0';
1701         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1702         xbt_dynar_push(loc->location.compose, &new_element);
1703       }else{
1704         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1705         new_element->type = e_dw_unsupported;
1706         xbt_dynar_push(loc->location.compose, &new_element);
1707       }
1708
1709       cursor++;
1710       xbt_dynar_free(&tokens2);
1711
1712     }
1713     
1714     xbt_dynar_free(&tokens1);
1715
1716     return loc;
1717     
1718   }
1719
1720 }
1721
1722
1723 void print_local_variables(xbt_dict_t list){
1724   
1725   dw_location_entry_t entry;
1726   dw_location_t location_entry;
1727   unsigned int cursor3 = 0, cursor4 = 0;
1728   xbt_dict_cursor_t cursor = 0, cursor2 = 0;
1729
1730   char *frame_name, *variable_name;
1731   dw_frame_t current_frame;
1732   dw_local_variable_t current_variable;
1733
1734   xbt_dict_foreach(list, cursor, frame_name, current_frame){ 
1735     fprintf(stderr, "Frame name : %s\n", current_frame->name);
1736     fprintf(stderr, "Location type : %d\n", current_frame->frame_base->type);
1737     xbt_dict_foreach((xbt_dict_t)current_frame->variables, cursor2, variable_name, current_variable){
1738       fprintf(stderr, "Name : %s\n", current_variable->name);
1739       if(current_variable->location == NULL)
1740         continue;
1741       fprintf(stderr, "Location type : %d\n", current_variable->location->type);
1742       switch(current_variable->location->type){
1743       case e_dw_loclist :
1744         xbt_dynar_foreach(current_variable->location->location.loclist, cursor3, entry){
1745           fprintf(stderr, "Lowpc : %lx, Highpc : %lx,", entry->lowpc, entry->highpc);
1746           switch(entry->location->type){
1747           case e_dw_register :
1748             fprintf(stderr, " Location : in register %d\n", entry->location->location.reg);
1749             break;
1750           case e_dw_bregister_op:
1751             fprintf(stderr, " Location : Add %d to the value in register %d\n", entry->location->location.breg_op.offset, entry->location->location.breg_op.reg);
1752             break;
1753           case e_dw_lit:
1754             fprintf(stderr, "Value already kwnown : %d\n", entry->location->location.lit);
1755             break;
1756           case e_dw_fbregister_op:
1757             fprintf(stderr, " Location : %d bytes from logical frame pointer\n", entry->location->location.fbreg_op);
1758             break;
1759           case e_dw_compose:
1760             fprintf(stderr, " Location :\n");
1761             xbt_dynar_foreach(entry->location->location.compose, cursor4, location_entry){
1762               switch(location_entry->type){
1763               case e_dw_register :
1764                 fprintf(stderr, " %d) in register %d\n", cursor4 + 1, location_entry->location.reg);
1765                 break;
1766               case e_dw_bregister_op:
1767                 fprintf(stderr, " %d) add %d to the value in register %d\n", cursor4 + 1, location_entry->location.breg_op.offset, location_entry->location.breg_op.reg);
1768                 break;
1769               case e_dw_lit:
1770                 fprintf(stderr, "%d) Value already kwnown : %d\n", cursor4 + 1, location_entry->location.lit);
1771                 break;
1772               case e_dw_fbregister_op:
1773                 fprintf(stderr, " %d) %d bytes from logical frame pointer\n", cursor4 + 1, location_entry->location.fbreg_op);
1774                 break;
1775               case e_dw_deref:
1776                 fprintf(stderr, " %d) Pop the stack entry and treats it as an address (size of data %d)\n", cursor4 + 1, location_entry->location.deref_size);
1777                 break;
1778               case e_dw_arithmetic :
1779                 fprintf(stderr, "%d) arithmetic operation : %s\n", cursor4 + 1, location_entry->location.arithmetic);
1780                 break;
1781               case e_dw_piece:
1782                 fprintf(stderr, "%d) The %d byte(s) previous value\n", cursor4 + 1, location_entry->location.piece);
1783                 break;
1784               case e_dw_uconstant :
1785                 fprintf(stderr, "%d) Unsigned constant %lu\n", cursor4 + 1, location_entry->location.uconstant.value);
1786                 break;
1787               case e_dw_sconstant :
1788                 fprintf(stderr, "%d) Signed constant %lu\n", cursor4 + 1, location_entry->location.sconstant.value);
1789                 break;
1790               default :
1791                 fprintf(stderr, "%d) Location type not supported\n", cursor4 + 1);
1792                 break;
1793               }
1794             }
1795             break;
1796           default:
1797             fprintf(stderr, "Location type not supported\n");
1798             break;
1799           }
1800         }
1801         break;
1802       case e_dw_compose:
1803         cursor4 = 0;
1804         fprintf(stderr, "Location :\n");
1805         xbt_dynar_foreach(current_variable->location->location.compose, cursor4, location_entry){
1806           switch(location_entry->type){
1807           case e_dw_register :
1808             fprintf(stderr, " %d) in register %d\n", cursor4 + 1, location_entry->location.reg);
1809             break;
1810           case e_dw_bregister_op:
1811             fprintf(stderr, " %d) add %d to the value in register %d\n", cursor4 + 1, location_entry->location.breg_op.offset, location_entry->location.breg_op.reg);
1812             break;
1813           case e_dw_lit:
1814             fprintf(stderr, "%d) Value already kwnown : %d\n", cursor4 + 1, location_entry->location.lit);
1815             break;
1816           case e_dw_fbregister_op:
1817             fprintf(stderr, " %d) %d bytes from logical frame pointer\n", cursor4 + 1, location_entry->location.fbreg_op);
1818             break;
1819           case e_dw_deref:
1820             fprintf(stderr, " %d) Pop the stack entry and treats it as an address (size of data %d)\n", cursor4 + 1, location_entry->location.deref_size);
1821             break;
1822           case e_dw_arithmetic :
1823             fprintf(stderr, "%d) arithmetic operation : %s\n", cursor4 + 1, location_entry->location.arithmetic);
1824             break;
1825           case e_dw_piece:
1826             fprintf(stderr, "%d) The %d byte(s) previous value\n", cursor4 + 1, location_entry->location.piece);
1827             break;
1828           case e_dw_uconstant :
1829             fprintf(stderr, "%d) Unsigned constant %lu\n", cursor4 + 1, location_entry->location.uconstant.value);
1830             break;
1831           case e_dw_sconstant :
1832             fprintf(stderr, "%d) Signed constant %lu\n", cursor4 + 1, location_entry->location.sconstant.value);
1833             break;
1834           default :
1835             fprintf(stderr, "%d) Location type not supported\n", cursor4 + 1);
1836             break;
1837           }
1838         }
1839         break;
1840       default :
1841         fprintf(stderr, "Location type not supported\n");
1842         break;
1843       }
1844     }
1845   }
1846
1847 }
1848
1849 static void MC_get_global_variables(char *elf_file){
1850
1851   FILE *fp;
1852
1853   char *command = bprintf("objdump -t -j .data -j .bss %s", elf_file);
1854
1855   fp = popen(command, "r");
1856
1857   if(fp == NULL){
1858     perror("popen failed");
1859     xbt_abort();
1860   }
1861
1862   if(mc_global_variables == NULL)
1863     mc_global_variables = xbt_dynar_new(sizeof(global_variable_t), global_variable_free_voidp);
1864
1865   char *line = NULL;
1866   ssize_t read;
1867   size_t n = 0;
1868
1869   xbt_dynar_t line_tokens = NULL;
1870   unsigned long offset;
1871
1872   int type = strcmp(elf_file, xbt_binary_name); /* 0 = binary, other = libsimgrid */
1873
1874   while ((read = xbt_getline(&line, &n, fp)) != -1){
1875
1876     if(n == 0)
1877       continue;
1878
1879      /* Wipeout the new line character */
1880     line[read - 1] = '\0';
1881
1882     xbt_str_strip_spaces(line);
1883     xbt_str_ltrim(line, NULL);
1884
1885     line_tokens = xbt_str_split(line, NULL);
1886
1887     if(xbt_dynar_length(line_tokens) <= 4 || strcmp(xbt_dynar_get_as(line_tokens, 0, char *), "SYMBOL") == 0)
1888       continue;
1889
1890     if((strncmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), "__gcov", 6) == 0)
1891        || (strncmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), "gcov", 4) == 0)
1892        || (strcmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), ".data") == 0)
1893        || (strcmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), ".bss") == 0)
1894        || (strncmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), "stderr", 6) == 0)
1895        || ((size_t)strtoul(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 2, char*), NULL, 16) == 0))
1896       continue;
1897
1898     global_variable_t var = xbt_new0(s_global_variable_t, 1);
1899
1900     if(type == 0){
1901       var->address = (void *)strtoul(xbt_dynar_get_as(line_tokens, 0, char*), NULL, 16);
1902     }else{
1903       offset = strtoul(xbt_dynar_get_as(line_tokens, 0, char*), NULL, 16);
1904       var->address = (char *)start_text_libsimgrid+offset;
1905     }
1906
1907     var->size = (size_t)strtoul(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 2, char*), NULL, 16);
1908     var->name = strdup(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*));
1909
1910     if(data_bss_ignore_size(var->address) > 0){
1911       global_variable_free(var);
1912     }else{
1913       if(xbt_dynar_is_empty(mc_global_variables)){
1914         xbt_dynar_push(mc_global_variables, &var);
1915       }else{
1916         unsigned int cursor = 0;
1917         int start = 0;
1918         int end = xbt_dynar_length(mc_global_variables) - 1;
1919         global_variable_t current_var = NULL;
1920       
1921         while(start <= end){
1922           cursor = (start + end) / 2;
1923           current_var = (global_variable_t)xbt_dynar_get_as(mc_global_variables, cursor, global_variable_t);
1924           if(current_var->address == var->address)
1925             break;
1926           if(current_var->address < var->address)
1927             start = cursor + 1;
1928           if(current_var->address > var->address)
1929             end = cursor - 1;
1930         }
1931  
1932         if(current_var->address < var->address)
1933           xbt_dynar_insert_at(mc_global_variables, cursor + 1, &var);
1934         else
1935           xbt_dynar_insert_at(mc_global_variables, cursor, &var);
1936       }
1937     }
1938
1939     xbt_dynar_free(&line_tokens);
1940
1941   }
1942
1943   xbt_free(command);
1944   xbt_free(line);
1945   pclose(fp);
1946
1947 }
1948
1949 void global_variable_free(global_variable_t v){
1950   xbt_free(v->name);
1951   xbt_free(v);
1952 }
1953
1954 void global_variable_free_voidp(void *v){
1955   global_variable_free((global_variable_t) * (void **) v);
1956 }