Logo AND Algorithmique Numérique Distribuée

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