Logo AND Algorithmique Numérique Distribuée

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