Logo AND Algorithmique Numérique Distribuée

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