Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'master' into hypervisor
[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[13];
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
663   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
664
665   MC_SET_RAW_MEM;
666
667   int value;
668   mc_state_t state;
669   xbt_fifo_item_t item;
670   smx_simcall_t req;
671   char *req_str = NULL;
672   
673   for (item = xbt_fifo_get_last_item(stack);
674        (item ? (state = (mc_state_t) (xbt_fifo_get_item_content(item)))
675         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
676     req = MC_state_get_executed_request(state, &value);
677     if(req){
678       req_str = MC_request_to_string(req, value);
679       XBT_INFO("%s", req_str);
680       xbt_free(req_str);
681     }
682   }
683
684   if(!raw_mem_set)
685     MC_UNSET_RAW_MEM;
686 }
687
688 void MC_show_deadlock(smx_simcall_t req)
689 {
690   /*char *req_str = NULL;*/
691   XBT_INFO("**************************");
692   XBT_INFO("*** DEAD-LOCK DETECTED ***");
693   XBT_INFO("**************************");
694   XBT_INFO("Locked request:");
695   /*req_str = MC_request_to_string(req);
696     XBT_INFO("%s", req_str);
697     xbt_free(req_str);*/
698   XBT_INFO("Counter-example execution trace:");
699   MC_dump_stack_safety(mc_stack_safety);
700   MC_print_statistics(mc_stats);
701 }
702
703
704 void MC_show_stack_liveness(xbt_fifo_t stack){
705   int value;
706   mc_pair_t pair;
707   xbt_fifo_item_t item;
708   smx_simcall_t req;
709   char *req_str = NULL;
710   
711   for (item = xbt_fifo_get_last_item(stack);
712        (item ? (pair = (mc_pair_t) (xbt_fifo_get_item_content(item)))
713         : (NULL)); item = xbt_fifo_get_prev_item(item)) {
714     req = MC_state_get_executed_request(pair->graph_state, &value);
715     if(req){
716       if(pair->requests>0){
717         req_str = MC_request_to_string(req, value);
718         XBT_INFO("%s", req_str);
719         xbt_free(req_str);
720       }else{
721         XBT_INFO("End of system requests but evolution in Büchi automaton");
722       }
723     }
724   }
725 }
726
727 void MC_dump_stack_liveness(xbt_fifo_t stack){
728
729   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
730
731   mc_pair_t pair;
732
733   MC_SET_RAW_MEM;
734   while ((pair = (mc_pair_t) xbt_fifo_pop(stack)) != NULL)
735     MC_pair_delete(pair);
736   MC_UNSET_RAW_MEM;
737
738   if(raw_mem_set)
739     MC_SET_RAW_MEM;
740
741 }
742
743
744 void MC_print_statistics(mc_stats_t stats)
745 {
746   if(stats->expanded_pairs == 0){
747     XBT_INFO("Expanded states = %lu", stats->expanded_states);
748     XBT_INFO("Visited states = %lu", stats->visited_states);
749   }else{
750     XBT_INFO("Expanded pairs = %lu", stats->expanded_pairs);
751     XBT_INFO("Visited pairs = %lu", stats->visited_pairs);
752   }
753   XBT_INFO("Executed transitions = %lu", stats->executed_transitions);
754   MC_SET_RAW_MEM;
755   if((_sg_mc_dot_output_file != NULL) && (_sg_mc_dot_output_file[0]!='\0')){
756     fprintf(dot_output, "}\n");
757     fclose(dot_output);
758   }
759   MC_UNSET_RAW_MEM;
760 }
761
762 void MC_assert(int prop)
763 {
764   if (MC_is_active() && !prop){
765     XBT_INFO("**************************");
766     XBT_INFO("*** PROPERTY NOT VALID ***");
767     XBT_INFO("**************************");
768     XBT_INFO("Counter-example execution trace:");
769     MC_dump_stack_safety(mc_stack_safety);
770     MC_print_statistics(mc_stats);
771     xbt_abort();
772   }
773 }
774
775 static void MC_assert_pair(int prop){
776   if (MC_is_active() && !prop) {
777     XBT_INFO("**************************");
778     XBT_INFO("*** PROPERTY NOT VALID ***");
779     XBT_INFO("**************************");
780     //XBT_INFO("Counter-example execution trace:");
781     MC_show_stack_liveness(mc_stack_liveness);
782     //MC_dump_snapshot_stack(mc_snapshot_stack);
783     MC_print_statistics(mc_stats);
784     xbt_abort();
785   }
786 }
787
788 void MC_process_clock_add(smx_process_t process, double amount)
789 {
790   mc_time[process->pid] += amount;
791 }
792
793 double MC_process_clock_get(smx_process_t process)
794 {
795   if(mc_time){
796     if(process != NULL)
797       return mc_time[process->pid];
798     else 
799       return -1;
800   }else{
801     return 0;
802   }
803 }
804
805 void MC_automaton_load(const char *file){
806
807   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
808
809   MC_SET_RAW_MEM;
810
811   if (_mc_property_automaton == NULL)
812     _mc_property_automaton = xbt_automaton_new();
813   
814   xbt_automaton_load(_mc_property_automaton,file);
815
816   MC_UNSET_RAW_MEM;
817
818   if(raw_mem_set)
819     MC_SET_RAW_MEM;
820
821 }
822
823 void MC_automaton_new_propositional_symbol(const char* id, void* fct) {
824
825   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
826
827   MC_SET_RAW_MEM;
828
829   if (_mc_property_automaton == NULL)
830     _mc_property_automaton = xbt_automaton_new();
831
832   xbt_automaton_propositional_symbol_new(_mc_property_automaton,id,fct);
833
834   MC_UNSET_RAW_MEM;
835
836   if(raw_mem_set)
837     MC_SET_RAW_MEM;
838   
839 }
840
841 /************ MC_ignore ***********/ 
842
843 void heap_ignore_region_free(mc_heap_ignore_region_t r){
844   xbt_free(r);
845 }
846
847 void heap_ignore_region_free_voidp(void *r){
848   heap_ignore_region_free((mc_heap_ignore_region_t) * (void **) r);
849 }
850
851 void MC_ignore_heap(void *address, size_t size){
852
853   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
854
855   MC_SET_RAW_MEM;
856
857   mc_heap_ignore_region_t region = NULL;
858   region = xbt_new0(s_mc_heap_ignore_region_t, 1);
859   region->address = address;
860   region->size = size;
861   
862   region->block = ((char*)address - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
863   
864   if(((xbt_mheap_t)std_heap)->heapinfo[region->block].type == 0){
865     region->fragment = -1;
866     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_block.ignore++;
867   }else{
868     region->fragment = ((uintptr_t) (ADDR2UINT (address) % (BLOCKSIZE))) >> ((xbt_mheap_t)std_heap)->heapinfo[region->block].type;
869     ((xbt_mheap_t)std_heap)->heapinfo[region->block].busy_frag.ignore[region->fragment]++;
870   }
871   
872   if(mc_heap_comparison_ignore == NULL){
873     mc_heap_comparison_ignore = xbt_dynar_new(sizeof(mc_heap_ignore_region_t), heap_ignore_region_free_voidp);
874     xbt_dynar_push(mc_heap_comparison_ignore, &region);
875     if(!raw_mem_set)
876       MC_UNSET_RAW_MEM;
877     return;
878   }
879
880   unsigned int cursor = 0;
881   mc_heap_ignore_region_t current_region = NULL;
882   int start = 0;
883   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
884   
885   while(start <= end){
886     cursor = (start + end) / 2;
887     current_region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
888     if(current_region->address == address){
889       heap_ignore_region_free(region);
890       if(!raw_mem_set)
891         MC_UNSET_RAW_MEM;
892       return;
893     }
894     if(current_region->address < address)
895       start = cursor + 1;
896     if(current_region->address > address)
897       end = cursor - 1;   
898   }
899
900   if(current_region->address < address)
901     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor + 1, &region);
902   else
903     xbt_dynar_insert_at(mc_heap_comparison_ignore, cursor, &region);
904
905   MC_UNSET_RAW_MEM;
906
907   if(raw_mem_set)
908     MC_SET_RAW_MEM;
909 }
910
911 void MC_remove_ignore_heap(void *address, size_t size){
912
913   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
914
915   MC_SET_RAW_MEM;
916
917   unsigned int cursor = 0;
918   int start = 0;
919   int end = xbt_dynar_length(mc_heap_comparison_ignore) - 1;
920   mc_heap_ignore_region_t region;
921   int ignore_found = 0;
922
923   while(start <= end){
924     cursor = (start + end) / 2;
925     region = (mc_heap_ignore_region_t)xbt_dynar_get_as(mc_heap_comparison_ignore, cursor, mc_heap_ignore_region_t);
926     if(region->address == address){
927       ignore_found = 1;
928       break;
929     }
930     if(region->address < address)
931       start = cursor + 1;
932     if(region->address > address){
933       if((char * )region->address <= ((char *)address + size)){
934         ignore_found = 1;
935         break;
936       }else
937         end = cursor - 1;   
938     }
939   }
940   
941   if(ignore_found == 1){
942     xbt_dynar_remove_at(mc_heap_comparison_ignore, cursor, NULL);
943     MC_remove_ignore_heap(address, size);
944   }
945
946   MC_UNSET_RAW_MEM;
947   
948   if(raw_mem_set)
949     MC_SET_RAW_MEM;
950
951 }
952
953 void data_bss_ignore_variable_free(mc_data_bss_ignore_variable_t v){
954   xbt_free(v);
955 }
956
957 void data_bss_ignore_variable_free_voidp(void *v){
958   data_bss_ignore_variable_free((mc_data_bss_ignore_variable_t) * (void **) v);
959 }
960
961 void MC_ignore_data_bss(void *address, size_t size){
962
963   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
964
965   MC_SET_RAW_MEM;
966   
967   if(mc_data_bss_comparison_ignore == NULL)
968     mc_data_bss_comparison_ignore = xbt_dynar_new(sizeof(mc_data_bss_ignore_variable_t), data_bss_ignore_variable_free_voidp);
969
970   mc_data_bss_ignore_variable_t var = NULL;
971   var = xbt_new0(s_mc_data_bss_ignore_variable_t, 1);
972   var->address = address;
973   var->size = size;
974
975   if(xbt_dynar_is_empty(mc_data_bss_comparison_ignore)){
976
977     xbt_dynar_insert_at(mc_data_bss_comparison_ignore, 0, &var);
978
979   }else{
980     
981     unsigned int cursor = 0;
982     int start = 0;
983     int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
984     mc_data_bss_ignore_variable_t current_var = NULL;
985
986     while(start <= end){
987       cursor = (start + end) / 2;
988       current_var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
989       if(current_var->address == address){
990         data_bss_ignore_variable_free(var);
991         MC_UNSET_RAW_MEM;
992         if(raw_mem_set)
993           MC_SET_RAW_MEM;
994         return;
995       }
996       if(current_var->address < address)
997         start = cursor + 1;
998       if(current_var->address > address)
999         end = cursor - 1;
1000     }
1001
1002     if(current_var->address < address)
1003       xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor + 1, &var);
1004     else
1005       xbt_dynar_insert_at(mc_data_bss_comparison_ignore, cursor, &var);
1006
1007   }
1008
1009   /* Remove variable from mc_global_variables */
1010
1011   if(mc_global_variables != NULL){
1012
1013     unsigned int cursor = 0;
1014     int start = 0;
1015     int end = xbt_dynar_length(mc_global_variables) - 1;
1016     global_variable_t current_var;
1017     int var_found;
1018
1019     while(start <= end){
1020       cursor = (start + end) / 2;
1021       current_var = (global_variable_t)xbt_dynar_get_as(mc_global_variables, cursor, global_variable_t);
1022       if(current_var->address == var->address){
1023         var_found = 1;
1024         break;
1025       }
1026       if(current_var->address < address)
1027         start = cursor + 1;
1028       if(current_var->address > address)
1029         end = cursor - 1;
1030     }
1031
1032     if(var_found)
1033       xbt_dynar_remove_at(mc_global_variables, cursor, NULL);
1034     
1035   }
1036
1037   MC_UNSET_RAW_MEM;
1038
1039   if(raw_mem_set)
1040     MC_SET_RAW_MEM;
1041 }
1042
1043 static size_t data_bss_ignore_size(void *address){
1044   unsigned int cursor = 0;
1045   int start = 0;
1046   int end = xbt_dynar_length(mc_data_bss_comparison_ignore) - 1;
1047   mc_data_bss_ignore_variable_t var;
1048
1049   while(start <= end){
1050     cursor = (start + end) / 2;
1051     var = (mc_data_bss_ignore_variable_t)xbt_dynar_get_as(mc_data_bss_comparison_ignore, cursor, mc_data_bss_ignore_variable_t);
1052     if(var->address == address)
1053       return var->size;
1054     if(var->address < address){
1055       if((void *)((char *)var->address + var->size) > address)
1056         return (char *)var->address + var->size - (char*)address;
1057       else
1058         start = cursor + 1;
1059     }
1060     if(var->address > address)
1061       end = cursor - 1;   
1062   }
1063
1064   return 0;
1065 }
1066
1067 void stack_ignore_variable_free(mc_stack_ignore_variable_t v){
1068   xbt_free(v->var_name);
1069   xbt_free(v->frame);
1070   xbt_free(v);
1071 }
1072
1073 void stack_ignore_variable_free_voidp(void *v){
1074   stack_ignore_variable_free((mc_stack_ignore_variable_t) * (void **) v);
1075 }
1076
1077 void MC_ignore_stack(const char *var_name, const char *frame_name){
1078   
1079   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1080
1081   MC_SET_RAW_MEM;
1082
1083   if(mc_stack_comparison_ignore == NULL)
1084     mc_stack_comparison_ignore = xbt_dynar_new(sizeof(mc_stack_ignore_variable_t), stack_ignore_variable_free_voidp);
1085   
1086   mc_stack_ignore_variable_t var = NULL;
1087   var = xbt_new0(s_mc_stack_ignore_variable_t, 1);
1088   var->var_name = strdup(var_name);
1089   var->frame = strdup(frame_name);
1090   
1091   if(xbt_dynar_is_empty(mc_stack_comparison_ignore)){
1092
1093     xbt_dynar_insert_at(mc_stack_comparison_ignore, 0, &var);
1094
1095   }else{
1096     
1097     unsigned int cursor = 0;
1098     int start = 0;
1099     int end = xbt_dynar_length(mc_stack_comparison_ignore) - 1;
1100     mc_stack_ignore_variable_t current_var = NULL;
1101
1102     while(start <= end){
1103       cursor = (start + end) / 2;
1104       current_var = (mc_stack_ignore_variable_t)xbt_dynar_get_as(mc_stack_comparison_ignore, cursor, mc_stack_ignore_variable_t);
1105       if(strcmp(current_var->frame, frame_name) == 0){
1106         if(strcmp(current_var->var_name, var_name) == 0){
1107           stack_ignore_variable_free(var);
1108           MC_UNSET_RAW_MEM;
1109           if(raw_mem_set)
1110             MC_SET_RAW_MEM;
1111           return;
1112         }
1113         if(strcmp(current_var->var_name, var_name) < 0)
1114           start = cursor + 1;
1115         if(strcmp(current_var->var_name, var_name) > 0)
1116           end = cursor - 1;
1117       }
1118       if(strcmp(current_var->frame, frame_name) < 0)
1119         start = cursor + 1;
1120       if(strcmp(current_var->frame, frame_name) > 0)
1121         end = cursor - 1;
1122     }
1123
1124     if(strcmp(current_var->frame, frame_name) < 0)
1125       xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor + 1, &var);
1126     else
1127       xbt_dynar_insert_at(mc_stack_comparison_ignore, cursor, &var);
1128
1129   }
1130
1131  /* Remove variable from mc_local_variables */
1132
1133   if(mc_local_variables != NULL){
1134
1135     if(strcmp(frame_name, "*") != 0){
1136       dw_frame_t frame = xbt_dict_get_or_null(mc_local_variables, frame_name);
1137       if(frame != NULL)
1138         xbt_dict_remove(frame->variables, var_name);
1139     }
1140
1141   }
1142
1143   MC_UNSET_RAW_MEM;
1144   
1145   if(raw_mem_set)
1146     MC_SET_RAW_MEM;
1147
1148 }
1149
1150 void MC_new_stack_area(void *stack, char *name, void* context, size_t size){
1151
1152   int raw_mem_set = (mmalloc_get_current_heap() == raw_heap);
1153
1154   MC_SET_RAW_MEM;
1155   if(stacks_areas == NULL)
1156     stacks_areas = xbt_dynar_new(sizeof(stack_region_t), NULL);
1157   
1158   stack_region_t region = NULL;
1159   region = xbt_new0(s_stack_region_t, 1);
1160   region->address = stack;
1161   region->process_name = strdup(name);
1162   region->context = context;
1163   region->size = size;
1164   region->block = ((char*)stack - (char*)((xbt_mheap_t)std_heap)->heapbase) / BLOCKSIZE + 1;
1165   xbt_dynar_push(stacks_areas, &region);
1166   
1167   MC_UNSET_RAW_MEM;
1168
1169   if(raw_mem_set)
1170     MC_SET_RAW_MEM;
1171 }
1172
1173 /************ DWARF ***********/
1174
1175 xbt_dict_t MC_get_location_list(const char *elf_file){
1176
1177   char *command = bprintf("objdump -Wo %s", elf_file);
1178
1179   FILE *fp = popen(command, "r");
1180
1181   if(fp == NULL){
1182     perror("popen for objdump failed");
1183     xbt_abort();
1184   }
1185
1186   int debug = 0; /*Detect if the program has been compiled with -g */
1187
1188   xbt_dict_t location_list = xbt_dict_new_homogeneous(NULL);
1189   char *line = NULL, *loc_expr = NULL;
1190   ssize_t read;
1191   size_t n = 0;
1192   int cursor_remove;
1193   xbt_dynar_t split = NULL;
1194
1195   while ((read = xbt_getline(&line, &n, fp)) != -1) {
1196
1197     /* Wipeout the new line character */
1198     line[read - 1] = '\0';
1199
1200     xbt_str_trim(line, NULL);
1201     
1202     if(n == 0)
1203       continue;
1204
1205     if(strlen(line) == 0)
1206       continue;
1207
1208     if(debug == 0){
1209
1210       if(strncmp(line, elf_file, strlen(elf_file)) == 0)
1211         continue;
1212       
1213       if(strncmp(line, "Contents", 8) == 0)
1214         continue;
1215
1216       if(strncmp(line, "Offset", 6) == 0){
1217         debug = 1;
1218         continue;
1219       }
1220     }
1221
1222     if(debug == 0){
1223       XBT_INFO("Your program must be compiled with -g");
1224       xbt_abort();
1225     }
1226
1227     xbt_dynar_t loclist = xbt_dynar_new(sizeof(dw_location_entry_t), NULL);
1228
1229     xbt_str_strip_spaces(line);
1230     split = xbt_str_split(line, " ");
1231
1232     while(read != -1 && strcmp("<End", (char *)xbt_dynar_get_as(split, 1, char *)) != 0){
1233       
1234       dw_location_entry_t new_entry = xbt_new0(s_dw_location_entry_t, 1);
1235       new_entry->lowpc = strtoul((char *)xbt_dynar_get_as(split, 1, char *), NULL, 16);
1236       new_entry->highpc = strtoul((char *)xbt_dynar_get_as(split, 2, char *), NULL, 16);
1237       
1238       cursor_remove =0;
1239       while(cursor_remove < 3){
1240         xbt_dynar_remove_at(split, 0, NULL);
1241         cursor_remove++;
1242       }
1243
1244       loc_expr = xbt_str_join(split, " ");
1245       xbt_str_ltrim(loc_expr, "(");
1246       xbt_str_rtrim(loc_expr, ")");
1247       new_entry->location = get_location(NULL, loc_expr);
1248
1249       xbt_dynar_push(loclist, &new_entry);
1250
1251       xbt_dynar_free(&split);
1252       free(loc_expr);
1253
1254       read = xbt_getline(&line, &n, fp);
1255       if(read != -1){
1256         line[read - 1] = '\0';
1257         xbt_str_strip_spaces(line);
1258         split = xbt_str_split(line, " ");
1259       }
1260
1261     }
1262
1263
1264     char *key = bprintf("%d", (int)strtoul((char *)xbt_dynar_get_as(split, 0, char *), NULL, 16));
1265     xbt_dict_set(location_list, key, loclist, NULL);
1266     xbt_free(key);
1267     
1268     xbt_dynar_free(&split);
1269
1270   }
1271
1272   xbt_free(line);
1273   xbt_free(command);
1274   pclose(fp);
1275
1276   return location_list;
1277 }
1278
1279 static dw_frame_t get_frame_by_offset(xbt_dict_t all_variables, unsigned long int offset){
1280
1281   xbt_dict_cursor_t cursor = NULL;
1282   char *name;
1283   dw_frame_t res;
1284
1285   xbt_dict_foreach(all_variables, cursor, name, res) {
1286     if(offset >= res->start && offset < res->end){
1287       xbt_dict_cursor_free(&cursor);
1288       return res;
1289     }
1290   }
1291
1292   xbt_dict_cursor_free(&cursor);
1293   return NULL;
1294   
1295 }
1296
1297 void MC_get_local_variables(const char *elf_file, xbt_dict_t location_list, xbt_dict_t *all_variables){
1298
1299   char *command = bprintf("objdump -Wi %s", elf_file);
1300   
1301   FILE *fp = popen(command, "r");
1302
1303   if(fp == NULL)
1304     perror("popen for objdump failed");
1305
1306   char *line = NULL, *origin, *abstract_origin, *current_frame = NULL;
1307   ssize_t read =0;
1308   size_t n = 0;
1309   int valid_variable = 1;
1310   char *node_type = NULL, *location_type = NULL, *variable_name = NULL, *loc_expr = NULL;
1311   xbt_dynar_t split = NULL, split2 = NULL;
1312
1313   xbt_dict_t variables_origin = xbt_dict_new_homogeneous(NULL);
1314   xbt_dict_t subprograms_origin = xbt_dict_new_homogeneous(NULL);
1315   char *subprogram_name = NULL, *subprogram_start = NULL, *subprogram_end = NULL;
1316   int new_frame = 0, new_variable = 0;
1317   dw_frame_t variable_frame, subroutine_frame = NULL;
1318
1319   read = xbt_getline(&line, &n, fp);
1320
1321   while (read != -1) {
1322
1323     if(n == 0){
1324       read = xbt_getline(&line, &n, fp);
1325       continue;
1326     }
1327  
1328     /* Wipeout the new line character */
1329     line[read - 1] = '\0';
1330    
1331     if(strlen(line) == 0){
1332       read = xbt_getline(&line, &n, fp);
1333       continue;
1334     }
1335
1336     xbt_str_ltrim(line, NULL);
1337     xbt_str_strip_spaces(line);
1338     
1339     if(line[0] != '<'){
1340       read = xbt_getline(&line, &n, fp);
1341       continue;
1342     }
1343     
1344     xbt_dynar_free(&split);
1345     split = xbt_str_split(line, " ");
1346
1347     /* Get node type */
1348     node_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
1349
1350     if(strcmp(node_type, "(DW_TAG_subprogram)") == 0){ /* New frame */
1351
1352       dw_frame_t frame = NULL;
1353
1354       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1355       subprogram_start = strdup(strtok(NULL, "<"));
1356       xbt_str_rtrim(subprogram_start, ">:");
1357
1358       read = xbt_getline(&line, &n, fp);
1359    
1360       while(read != -1){
1361
1362         if(n == 0){
1363           read = xbt_getline(&line, &n, fp);
1364           continue;
1365         }
1366
1367         /* Wipeout the new line character */
1368         line[read - 1] = '\0';
1369         
1370         if(strlen(line) == 0){
1371           read = xbt_getline(&line, &n, fp);
1372           continue;
1373         }
1374       
1375         xbt_dynar_free(&split);
1376         xbt_str_rtrim(line, NULL);
1377         xbt_str_strip_spaces(line);
1378         split = xbt_str_split(line, " ");
1379           
1380         node_type = xbt_dynar_get_as(split, 1, char *);
1381
1382         if(strncmp(node_type, "DW_AT_", 6) != 0)
1383           break;
1384
1385         if(strcmp(node_type, "DW_AT_sibling") == 0){
1386
1387           subprogram_end = strdup(xbt_dynar_get_as(split, 3, char*));
1388           xbt_str_ltrim(subprogram_end, "<0x");
1389           xbt_str_rtrim(subprogram_end, ">");
1390           
1391         }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){ /* Frame already in dict */
1392           
1393           new_frame = 0;
1394           abstract_origin = strdup(xbt_dynar_get_as(split, 2, char*));
1395           xbt_str_ltrim(abstract_origin, "<0x");
1396           xbt_str_rtrim(abstract_origin, ">");
1397           subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, abstract_origin);
1398           frame = xbt_dict_get_or_null(*all_variables, subprogram_name); 
1399           xbt_free(abstract_origin);
1400
1401         }else if(strcmp(node_type, "DW_AT_name") == 0){
1402
1403           new_frame = 1;
1404           xbt_free(current_frame);
1405           frame = xbt_new0(s_dw_frame_t, 1);
1406           frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *)); 
1407           frame->variables = xbt_dict_new_homogeneous(NULL);
1408           frame->frame_base = xbt_new0(s_dw_location_t, 1); 
1409           current_frame = strdup(frame->name);
1410
1411           xbt_dict_set(subprograms_origin, subprogram_start, frame->name, NULL);
1412         
1413         }else if(strcmp(node_type, "DW_AT_frame_base") == 0){
1414
1415           location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
1416
1417           if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
1418
1419             frame->frame_base = get_location(location_list, xbt_dynar_get_as(split, 3, char *));
1420              
1421           }else{
1422                 
1423             xbt_str_strip_spaces(line);
1424             split2 = xbt_str_split(line, "(");
1425             xbt_dynar_remove_at(split2, 0, NULL);
1426             loc_expr = xbt_str_join(split2, " ");
1427             xbt_str_rtrim(loc_expr, ")");
1428             frame->frame_base = get_location(NULL, loc_expr);
1429             xbt_dynar_free(&split2);
1430             xbt_free(loc_expr);
1431
1432           }
1433  
1434         }else if(strcmp(node_type, "DW_AT_low_pc") == 0){
1435           
1436           if(frame != NULL)
1437             frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1438
1439         }else if(strcmp(node_type, "DW_AT_high_pc") == 0){
1440
1441           if(frame != NULL)
1442             frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1443
1444         }else if(strcmp(node_type, "DW_AT_MIPS_linkage_name:") == 0){
1445
1446           xbt_free(frame->name);
1447           xbt_free(current_frame);
1448           frame->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));   
1449           current_frame = strdup(frame->name);
1450           xbt_dict_set(subprograms_origin, subprogram_start, frame->name, NULL);
1451
1452         }
1453
1454         read = xbt_getline(&line, &n, fp);
1455
1456       }
1457  
1458       if(new_frame == 1){
1459         frame->start = strtoul(subprogram_start, NULL, 16);
1460         if(subprogram_end != NULL)
1461           frame->end = strtoul(subprogram_end, NULL, 16);
1462         xbt_dict_set(*all_variables, frame->name, frame, NULL);
1463       }
1464
1465       xbt_free(subprogram_start);
1466       xbt_free(subprogram_end);
1467       subprogram_end = NULL;
1468         
1469
1470     }else if(strcmp(node_type, "(DW_TAG_variable)") == 0){ /* New variable */
1471
1472       dw_local_variable_t var = NULL;
1473       
1474       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1475       origin = strdup(strtok(NULL, "<"));
1476       xbt_str_rtrim(origin, ">:");
1477       
1478       read = xbt_getline(&line, &n, fp);
1479       
1480       while(read != -1){
1481
1482         if(n == 0){
1483           read = xbt_getline(&line, &n, fp);
1484           continue;
1485         }
1486
1487         /* Wipeout the new line character */
1488         line[read - 1] = '\0'; 
1489
1490         if(strlen(line) == 0){
1491           read = xbt_getline(&line, &n, fp);
1492           continue;
1493         }
1494        
1495         xbt_dynar_free(&split);
1496         xbt_str_rtrim(line, NULL);
1497         xbt_str_strip_spaces(line);
1498         split = xbt_str_split(line, " ");
1499   
1500         node_type = xbt_dynar_get_as(split, 1, char *);
1501
1502         if(strncmp(node_type, "DW_AT_", 6) != 0)
1503           break;
1504
1505         if(strcmp(node_type, "DW_AT_name") == 0){
1506
1507           new_variable = 1;
1508           var = xbt_new0(s_dw_local_variable_t, 1);
1509           var->name = strdup(xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *));
1510
1511           xbt_dict_set(variables_origin, origin, var->name, NULL);
1512          
1513         }else if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){
1514
1515           new_variable = 0;
1516           abstract_origin = xbt_dynar_get_as(split, 2, char *);
1517           xbt_str_ltrim(abstract_origin, "<0x");
1518           xbt_str_rtrim(abstract_origin, ">");
1519           
1520           variable_name = (char *)xbt_dict_get_or_null(variables_origin, abstract_origin);
1521           variable_frame = get_frame_by_offset(*all_variables, strtoul(abstract_origin, NULL, 16));
1522           var = xbt_dict_get_or_null(variable_frame->variables, variable_name);   
1523
1524         }else if(strcmp(node_type, "DW_AT_location") == 0){
1525
1526           if(valid_variable == 1 && var != NULL){
1527
1528             var->location = xbt_new0(s_dw_location_t, 1);
1529
1530             location_type = xbt_dynar_get_as(split, xbt_dynar_length(split) - 1, char *);
1531
1532             if(strcmp(location_type, "list)") == 0){ /* Search location in location list */
1533
1534               var->location = get_location(location_list, xbt_dynar_get_as(split, 3, char *));
1535              
1536             }else{
1537                 
1538               xbt_str_strip_spaces(line);
1539               split2 = xbt_str_split(line, "(");
1540               xbt_dynar_remove_at(split2, 0, NULL);
1541               loc_expr = xbt_str_join(split2, " ");
1542               xbt_str_rtrim(loc_expr, ")");
1543               var->location = get_location(NULL, loc_expr);
1544               xbt_dynar_free(&split2);
1545               xbt_free(loc_expr);
1546
1547             }
1548
1549           }
1550            
1551         }else if(strcmp(node_type, "DW_AT_external") == 0){
1552
1553           valid_variable = 0;
1554         
1555         }
1556
1557         read = xbt_getline(&line, &n, fp);
1558  
1559       }
1560
1561       if(new_variable == 1 && valid_variable == 1){
1562         
1563         variable_frame = xbt_dict_get_or_null(*all_variables, current_frame);
1564         xbt_dict_set(variable_frame->variables, var->name, var, NULL);
1565       }
1566
1567       valid_variable = 1;
1568       new_variable = 0;
1569
1570     }else if(strcmp(node_type, "(DW_TAG_inlined_subroutine)") == 0){
1571
1572       strtok(xbt_dynar_get_as(split, 0, char *), "<");
1573       origin = strdup(strtok(NULL, "<"));
1574       xbt_str_rtrim(origin, ">:");
1575
1576       read = xbt_getline(&line, &n, fp);
1577
1578       while(read != -1){
1579
1580         /* Wipeout the new line character */
1581         line[read - 1] = '\0'; 
1582
1583         if(n == 0){
1584           read = xbt_getline(&line, &n, fp);
1585           continue;
1586         }
1587
1588         if(strlen(line) == 0){
1589           read = xbt_getline(&line, &n, fp);
1590           continue;
1591         }
1592
1593         xbt_dynar_free(&split);
1594         xbt_str_rtrim(line, NULL);
1595         xbt_str_strip_spaces(line);
1596         split = xbt_str_split(line, " ");
1597         
1598         if(strncmp(xbt_dynar_get_as(split, 1, char *), "DW_AT_", 6) != 0)
1599           break;
1600           
1601         node_type = xbt_dynar_get_as(split, 1, char *);
1602
1603         if(strcmp(node_type, "DW_AT_abstract_origin:") == 0){
1604
1605           origin = xbt_dynar_get_as(split, 2, char *);
1606           xbt_str_ltrim(origin, "<0x");
1607           xbt_str_rtrim(origin, ">");
1608           
1609           subprogram_name = (char *)xbt_dict_get_or_null(subprograms_origin, origin);
1610           subroutine_frame = xbt_dict_get_or_null(*all_variables, subprogram_name);
1611         
1612         }else if(strcmp(node_type, "DW_AT_low_pc") == 0){
1613
1614           subroutine_frame->low_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1615
1616         }else if(strcmp(node_type, "DW_AT_high_pc") == 0){
1617
1618           subroutine_frame->high_pc = (void *)strtoul(xbt_dynar_get_as(split, 3, char *), NULL, 16);
1619         }
1620
1621         read = xbt_getline(&line, &n, fp);
1622       
1623       }
1624
1625     }else{
1626
1627       read = xbt_getline(&line, &n, fp);
1628
1629     }
1630
1631   }
1632   
1633   xbt_dynar_free(&split);
1634   xbt_free(line);
1635   xbt_free(command);
1636   pclose(fp);
1637   
1638 }
1639
1640 static dw_location_t get_location(xbt_dict_t location_list, char *expr){
1641
1642   dw_location_t loc = xbt_new0(s_dw_location_t, 1);
1643
1644   if(location_list != NULL){
1645     
1646     char *key = bprintf("%d", (int)strtoul(expr, NULL, 16));
1647     loc->type = e_dw_loclist;
1648     loc->location.loclist =  (xbt_dynar_t)xbt_dict_get_or_null(location_list, key);
1649     if(loc->location.loclist == NULL)
1650       XBT_INFO("Key not found in loclist");
1651     xbt_free(key);
1652     return loc;
1653
1654   }else{
1655
1656     int cursor = 0;
1657     char *tok = NULL, *tok2 = NULL; 
1658     
1659     xbt_dynar_t tokens1 = xbt_str_split(expr, ";");
1660     xbt_dynar_t tokens2;
1661
1662     loc->type = e_dw_compose;
1663     loc->location.compose = xbt_dynar_new(sizeof(dw_location_t), NULL);
1664
1665     while(cursor < xbt_dynar_length(tokens1)){
1666
1667       tok = xbt_dynar_get_as(tokens1, cursor, char*);
1668       tokens2 = xbt_str_split(tok, " ");
1669       tok2 = xbt_dynar_get_as(tokens2, 0, char*);
1670       
1671       if(strncmp(tok2, "DW_OP_reg", 9) == 0){
1672         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1673         new_element->type = e_dw_register;
1674         new_element->location.reg = atoi(strtok(tok2, "DW_OP_reg"));
1675         xbt_dynar_push(loc->location.compose, &new_element);     
1676       }else if(strcmp(tok2, "DW_OP_fbreg:") == 0){
1677         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1678         new_element->type = e_dw_fbregister_op;
1679         new_element->location.fbreg_op = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1680         xbt_dynar_push(loc->location.compose, &new_element);
1681       }else if(strncmp(tok2, "DW_OP_breg", 10) == 0){
1682         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1683         new_element->type = e_dw_bregister_op;
1684         new_element->location.breg_op.reg = atoi(strtok(tok2, "DW_OP_breg"));
1685         new_element->location.breg_op.offset = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1686         xbt_dynar_push(loc->location.compose, &new_element);
1687       }else if(strncmp(tok2, "DW_OP_lit", 9) == 0){
1688         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1689         new_element->type = e_dw_lit;
1690         new_element->location.lit = atoi(strtok(tok2, "DW_OP_lit"));
1691         xbt_dynar_push(loc->location.compose, &new_element);
1692       }else if(strcmp(tok2, "DW_OP_piece:") == 0){
1693         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1694         new_element->type = e_dw_piece;
1695         new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1696         /*if(strlen(xbt_dynar_get_as(tokens2, 1, char*)) > 1)
1697           new_element->location.piece = atoi(xbt_dynar_get_as(tokens2, 1, char*));
1698         else
1699         new_element->location.piece = xbt_dynar_get_as(tokens2, 1, char*)[0] - '0';*/
1700         xbt_dynar_push(loc->location.compose, &new_element);
1701       }else if(strcmp(tok2, "DW_OP_plus_uconst:") == 0){
1702         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1703         new_element->type = e_dw_plus_uconst;
1704         new_element->location.plus_uconst = atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char *));
1705         xbt_dynar_push(loc->location.compose, &new_element);
1706       }else if(strcmp(tok, "DW_OP_abs") == 0 || 
1707                strcmp(tok, "DW_OP_and") == 0 ||
1708                strcmp(tok, "DW_OP_div") == 0 ||
1709                strcmp(tok, "DW_OP_minus") == 0 ||
1710                strcmp(tok, "DW_OP_mod") == 0 ||
1711                strcmp(tok, "DW_OP_mul") == 0 ||
1712                strcmp(tok, "DW_OP_neg") == 0 ||
1713                strcmp(tok, "DW_OP_not") == 0 ||
1714                strcmp(tok, "DW_OP_or") == 0 ||
1715                strcmp(tok, "DW_OP_plus") == 0){               
1716         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1717         new_element->type = e_dw_arithmetic;
1718         new_element->location.arithmetic = strdup(strtok(tok2, "DW_OP_"));
1719         xbt_dynar_push(loc->location.compose, &new_element);
1720       }else if(strcmp(tok, "DW_OP_stack_value") == 0){
1721       }else if(strcmp(tok2, "DW_OP_deref_size:") == 0){
1722         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1723         new_element->type = e_dw_deref;
1724         new_element->location.deref_size = (unsigned int short) atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*));
1725         /*if(strlen(xbt_dynar_get_as(tokens, ++cursor, char*)) > 1)
1726           new_element->location.deref_size = atoi(xbt_dynar_get_as(tokens, cursor, char*));
1727         else
1728         new_element->location.deref_size = xbt_dynar_get_as(tokens, cursor, char*)[0] - '0';*/
1729         xbt_dynar_push(loc->location.compose, &new_element);
1730       }else if(strcmp(tok, "DW_OP_deref") == 0){
1731         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1732         new_element->type = e_dw_deref;
1733         new_element->location.deref_size = sizeof(void *);
1734         xbt_dynar_push(loc->location.compose, &new_element);
1735       }else if(strcmp(tok2, "DW_OP_constu:") == 0){
1736         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1737         new_element->type = e_dw_uconstant;
1738         new_element->location.uconstant.bytes = 1;
1739         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1740         /*if(strlen(xbt_dynar_get_as(tokens, ++cursor, char*)) > 1)
1741           new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens, cursor, char*)));
1742         else
1743         new_element->location.uconstant.value = (unsigned long int)(xbt_dynar_get_as(tokens, cursor, char*)[0] - '0');*/
1744         xbt_dynar_push(loc->location.compose, &new_element);
1745       }else if(strcmp(tok2, "DW_OP_consts:") == 0){
1746         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1747         new_element->type = e_dw_sconstant;
1748         new_element->location.sconstant.bytes = 1;
1749         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1750         xbt_dynar_push(loc->location.compose, &new_element);
1751       }else if(strcmp(tok2, "DW_OP_const1u:") == 0 ||
1752                strcmp(tok2, "DW_OP_const2u:") == 0 ||
1753                strcmp(tok2, "DW_OP_const4u:") == 0 ||
1754                strcmp(tok2, "DW_OP_const8u:") == 0){
1755         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1756         new_element->type = e_dw_uconstant;
1757         new_element->location.uconstant.bytes = tok2[11] - '0';
1758         new_element->location.uconstant.value = (unsigned long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1759         /*if(strlen(xbt_dynar_get_as(tokens, ++cursor, char*)) > 1)
1760           new_element->location.constant.value = atoi(xbt_dynar_get_as(tokens, cursor, char*));
1761         else
1762         new_element->location.constant.value = xbt_dynar_get_as(tokens, cursor, char*)[0] - '0';*/
1763         xbt_dynar_push(loc->location.compose, &new_element);
1764       }else if(strcmp(tok, "DW_OP_const1s") == 0 ||
1765                strcmp(tok, "DW_OP_const2s") == 0 ||
1766                strcmp(tok, "DW_OP_const4s") == 0 ||
1767                strcmp(tok, "DW_OP_const8s") == 0){
1768         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1769         new_element->type = e_dw_sconstant;
1770         new_element->location.sconstant.bytes = tok2[11] - '0';
1771         new_element->location.sconstant.value = (long int)(atoi(xbt_dynar_get_as(tokens2, xbt_dynar_length(tokens2) - 1, char*)));
1772         xbt_dynar_push(loc->location.compose, &new_element);
1773       }else{
1774         dw_location_t new_element = xbt_new0(s_dw_location_t, 1);
1775         new_element->type = e_dw_unsupported;
1776         xbt_dynar_push(loc->location.compose, &new_element);
1777       }
1778
1779       cursor++;
1780       xbt_dynar_free(&tokens2);
1781
1782     }
1783     
1784     xbt_dynar_free(&tokens1);
1785
1786     return loc;
1787     
1788   }
1789
1790 }
1791
1792
1793 void print_local_variables(xbt_dict_t list){
1794   
1795   dw_location_entry_t entry;
1796   dw_location_t location_entry;
1797   unsigned int cursor3 = 0, cursor4 = 0;
1798   xbt_dict_cursor_t cursor = 0, cursor2 = 0;
1799
1800   char *frame_name, *variable_name;
1801   dw_frame_t current_frame;
1802   dw_local_variable_t current_variable;
1803
1804   xbt_dict_foreach(list, cursor, frame_name, current_frame){ 
1805     fprintf(stderr, "Frame name : %s\n", current_frame->name);
1806     fprintf(stderr, "Location type : %d\n", current_frame->frame_base->type);
1807     xbt_dict_foreach((xbt_dict_t)current_frame->variables, cursor2, variable_name, current_variable){
1808       fprintf(stderr, "Name : %s\n", current_variable->name);
1809       if(current_variable->location == NULL)
1810         continue;
1811       fprintf(stderr, "Location type : %d\n", current_variable->location->type);
1812       switch(current_variable->location->type){
1813       case e_dw_loclist :
1814         xbt_dynar_foreach(current_variable->location->location.loclist, cursor3, entry){
1815           fprintf(stderr, "Lowpc : %lx, Highpc : %lx,", entry->lowpc, entry->highpc);
1816           switch(entry->location->type){
1817           case e_dw_register :
1818             fprintf(stderr, " Location : in register %d\n", entry->location->location.reg);
1819             break;
1820           case e_dw_bregister_op:
1821             fprintf(stderr, " Location : Add %d to the value in register %d\n", entry->location->location.breg_op.offset, entry->location->location.breg_op.reg);
1822             break;
1823           case e_dw_lit:
1824             fprintf(stderr, "Value already kwnown : %d\n", entry->location->location.lit);
1825             break;
1826           case e_dw_fbregister_op:
1827             fprintf(stderr, " Location : %d bytes from logical frame pointer\n", entry->location->location.fbreg_op);
1828             break;
1829           case e_dw_compose:
1830             fprintf(stderr, " Location :\n");
1831             xbt_dynar_foreach(entry->location->location.compose, cursor4, location_entry){
1832               switch(location_entry->type){
1833               case e_dw_register :
1834                 fprintf(stderr, " %d) in register %d\n", cursor4 + 1, location_entry->location.reg);
1835                 break;
1836               case e_dw_bregister_op:
1837                 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);
1838                 break;
1839               case e_dw_lit:
1840                 fprintf(stderr, "%d) Value already kwnown : %d\n", cursor4 + 1, location_entry->location.lit);
1841                 break;
1842               case e_dw_fbregister_op:
1843                 fprintf(stderr, " %d) %d bytes from logical frame pointer\n", cursor4 + 1, location_entry->location.fbreg_op);
1844                 break;
1845               case e_dw_deref:
1846                 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);
1847                 break;
1848               case e_dw_arithmetic :
1849                 fprintf(stderr, "%d) arithmetic operation : %s\n", cursor4 + 1, location_entry->location.arithmetic);
1850                 break;
1851               case e_dw_piece:
1852                 fprintf(stderr, "%d) The %d byte(s) previous value\n", cursor4 + 1, location_entry->location.piece);
1853                 break;
1854               case e_dw_uconstant :
1855                 fprintf(stderr, "%d) Unsigned constant %lu\n", cursor4 + 1, location_entry->location.uconstant.value);
1856                 break;
1857               case e_dw_sconstant :
1858                 fprintf(stderr, "%d) Signed constant %lu\n", cursor4 + 1, location_entry->location.sconstant.value);
1859                 break;
1860               default :
1861                 fprintf(stderr, "%d) Location type not supported\n", cursor4 + 1);
1862                 break;
1863               }
1864             }
1865             break;
1866           default:
1867             fprintf(stderr, "Location type not supported\n");
1868             break;
1869           }
1870         }
1871         break;
1872       case e_dw_compose:
1873         cursor4 = 0;
1874         fprintf(stderr, "Location :\n");
1875         xbt_dynar_foreach(current_variable->location->location.compose, cursor4, location_entry){
1876           switch(location_entry->type){
1877           case e_dw_register :
1878             fprintf(stderr, " %d) in register %d\n", cursor4 + 1, location_entry->location.reg);
1879             break;
1880           case e_dw_bregister_op:
1881             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);
1882             break;
1883           case e_dw_lit:
1884             fprintf(stderr, "%d) Value already kwnown : %d\n", cursor4 + 1, location_entry->location.lit);
1885             break;
1886           case e_dw_fbregister_op:
1887             fprintf(stderr, " %d) %d bytes from logical frame pointer\n", cursor4 + 1, location_entry->location.fbreg_op);
1888             break;
1889           case e_dw_deref:
1890             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);
1891             break;
1892           case e_dw_arithmetic :
1893             fprintf(stderr, "%d) arithmetic operation : %s\n", cursor4 + 1, location_entry->location.arithmetic);
1894             break;
1895           case e_dw_piece:
1896             fprintf(stderr, "%d) The %d byte(s) previous value\n", cursor4 + 1, location_entry->location.piece);
1897             break;
1898           case e_dw_uconstant :
1899             fprintf(stderr, "%d) Unsigned constant %lu\n", cursor4 + 1, location_entry->location.uconstant.value);
1900             break;
1901           case e_dw_sconstant :
1902             fprintf(stderr, "%d) Signed constant %lu\n", cursor4 + 1, location_entry->location.sconstant.value);
1903             break;
1904           default :
1905             fprintf(stderr, "%d) Location type not supported\n", cursor4 + 1);
1906             break;
1907           }
1908         }
1909         break;
1910       default :
1911         fprintf(stderr, "Location type not supported\n");
1912         break;
1913       }
1914     }
1915   }
1916
1917 }
1918
1919 static void MC_get_global_variables(char *elf_file){
1920
1921   FILE *fp;
1922
1923   char *command = bprintf("objdump -t -j .data -j .bss %s", elf_file);
1924
1925   fp = popen(command, "r");
1926
1927   if(fp == NULL){
1928     perror("popen failed");
1929     xbt_abort();
1930   }
1931
1932   if(mc_global_variables == NULL)
1933     mc_global_variables = xbt_dynar_new(sizeof(global_variable_t), global_variable_free_voidp);
1934
1935   char *line = NULL;
1936   ssize_t read;
1937   size_t n = 0;
1938
1939   xbt_dynar_t line_tokens = NULL;
1940   unsigned long offset;
1941
1942   int type = strcmp(elf_file, xbt_binary_name); /* 0 = binary, other = libsimgrid */
1943
1944   while ((read = xbt_getline(&line, &n, fp)) != -1){
1945
1946     if(n == 0)
1947       continue;
1948
1949      /* Wipeout the new line character */
1950     line[read - 1] = '\0';
1951
1952     xbt_str_strip_spaces(line);
1953     xbt_str_ltrim(line, NULL);
1954
1955     line_tokens = xbt_str_split(line, NULL);
1956
1957     if(xbt_dynar_length(line_tokens) <= 4 || strcmp(xbt_dynar_get_as(line_tokens, 0, char *), "SYMBOL") == 0)
1958       continue;
1959
1960     if((strncmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), "__gcov", 6) == 0)
1961        || (strncmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), "gcov", 4) == 0)
1962        || (strcmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), ".data") == 0)
1963        || (strcmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), ".bss") == 0)
1964        || (strncmp(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*), "stderr", 6) == 0)
1965        || ((size_t)strtoul(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 2, char*), NULL, 16) == 0))
1966       continue;
1967
1968     global_variable_t var = xbt_new0(s_global_variable_t, 1);
1969
1970     if(type == 0){
1971       var->address = (void *)strtoul(xbt_dynar_get_as(line_tokens, 0, char*), NULL, 16);
1972     }else{
1973       offset = strtoul(xbt_dynar_get_as(line_tokens, 0, char*), NULL, 16);
1974       var->address = (char *)start_text_libsimgrid+offset;
1975     }
1976
1977     var->size = (size_t)strtoul(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 2, char*), NULL, 16);
1978     var->name = strdup(xbt_dynar_get_as(line_tokens, xbt_dynar_length(line_tokens) - 1, char*));
1979
1980     if(data_bss_ignore_size(var->address) > 0){
1981       global_variable_free(var);
1982     }else{
1983       if(xbt_dynar_is_empty(mc_global_variables)){
1984         xbt_dynar_push(mc_global_variables, &var);
1985       }else{
1986         unsigned int cursor = 0;
1987         int start = 0;
1988         int end = xbt_dynar_length(mc_global_variables) - 1;
1989         global_variable_t current_var = NULL;
1990       
1991         while(start <= end){
1992           cursor = (start + end) / 2;
1993           current_var = (global_variable_t)xbt_dynar_get_as(mc_global_variables, cursor, global_variable_t);
1994           if(current_var->address == var->address)
1995             break;
1996           if(current_var->address < var->address)
1997             start = cursor + 1;
1998           if(current_var->address > var->address)
1999             end = cursor - 1;
2000         }
2001  
2002         if(current_var->address < var->address)
2003           xbt_dynar_insert_at(mc_global_variables, cursor + 1, &var);
2004         else
2005           xbt_dynar_insert_at(mc_global_variables, cursor, &var);
2006       }
2007     }
2008
2009     xbt_dynar_free(&line_tokens);
2010
2011   }
2012
2013   xbt_free(command);
2014   xbt_free(line);
2015   pclose(fp);
2016
2017 }
2018
2019 void global_variable_free(global_variable_t v){
2020   xbt_free(v->name);
2021   xbt_free(v);
2022 }
2023
2024 void global_variable_free_voidp(void *v){
2025   global_variable_free((global_variable_t) * (void **) v);
2026 }