Logo AND Algorithmique Numérique Distribuée

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