Logo AND Algorithmique Numérique Distribuée

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