Logo AND Algorithmique Numérique Distribuée

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