Logo AND Algorithmique Numérique Distribuée

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