Logo AND Algorithmique Numérique Distribuée

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