Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
[mc] In MC_ignore, keep the zeroed data out of the main snapshot
[simgrid.git] / src / mc / mc_diff.c
1 /* mc_diff - Memory snapshooting and comparison                             */
2
3 /* Copyright (c) 2008-2014. The SimGrid Team.
4  * All rights reserved.                                                     */
5
6 /* This program is free software; you can redistribute it and/or modify it
7  * under the terms of the license (GNU LGPL) which comes with this package. */
8
9 #include "xbt/ex_interface.h"   /* internals of backtrace setup */
10 #include "xbt/str.h"
11 #include "mc/mc.h"
12 #include "xbt/mmalloc.h"
13 #include "mc/datatypes.h"
14 #include "mc/mc_private.h"
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mc_diff, xbt,
17                                 "Logging specific to mc_diff in mc");
18
19 xbt_dynar_t mc_heap_comparison_ignore;
20 xbt_dynar_t stacks_areas;
21 void *maestro_stack_start, *maestro_stack_end;
22
23
24 /********************************* Backtrace ***********************************/
25 /******************************************************************************/
26
27 static void mmalloc_backtrace_block_display(void *heapinfo, int block)
28 {
29
30   /* xbt_ex_t e; */
31
32   /* if (((malloc_info *)heapinfo)[block].busy_block.bt_size == 0) { */
33   /*   fprintf(stderr, "No backtrace available for that block, sorry.\n"); */
34   /*   return; */
35   /* } */
36
37   /* memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_block.bt),sizeof(void*)*XBT_BACKTRACE_SIZE); */
38   /* e.used = ((malloc_info *)heapinfo)[block].busy_block.bt_size; */
39
40   /* xbt_ex_setup_backtrace(&e); */
41   /* if (e.used == 0) { */
42   /*   fprintf(stderr, "(backtrace not set)\n"); */
43   /* } else if (e.bt_strings == NULL) { */
44   /*   fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet"); */
45   /* } else { */
46   /*   int i; */
47
48   /*   fprintf(stderr, "Backtrace of where the block %d was malloced (%d frames):\n", block ,e.used); */
49   /*   for (i = 0; i < e.used; i++)       /\* no need to display "xbt_backtrace_display" *\/{ */
50   /*     fprintf(stderr, "%d ---> %s\n",i, e.bt_strings[i] + 4); */
51   /*   } */
52   /* } */
53 }
54
55 static void mmalloc_backtrace_fragment_display(void *heapinfo, int block,
56                                                int frag)
57 {
58
59   /* xbt_ex_t e; */
60
61   /* memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_frag.bt[frag]),sizeof(void*)*XBT_BACKTRACE_SIZE); */
62   /* e.used = XBT_BACKTRACE_SIZE; */
63
64   /* xbt_ex_setup_backtrace(&e); */
65   /* if (e.used == 0) { */
66   /*   fprintf(stderr, "(backtrace not set)\n"); */
67   /* } else if (e.bt_strings == NULL) { */
68   /*   fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet"); */
69   /* } else { */
70   /*   int i; */
71
72   /*   fprintf(stderr, "Backtrace of where the fragment %d in block %d was malloced (%d frames):\n", frag, block ,e.used); */
73   /*   for (i = 0; i < e.used; i++)       /\* no need to display "xbt_backtrace_display" *\/{ */
74   /*     fprintf(stderr, "%d ---> %s\n",i, e.bt_strings[i] + 4); */
75   /*   } */
76   /* } */
77
78 }
79
80 static void mmalloc_backtrace_display(void *addr)
81 {
82
83   /* size_t block, frag_nb; */
84   /* int type; */
85
86   /* xbt_mheap_t heap = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit(); */
87
88   /* block = (((char*) (addr) - (char*) heap -> heapbase) / BLOCKSIZE + 1); */
89
90   /* type = heap->heapinfo[block].type; */
91
92   /* switch(type){ */
93   /* case -1 : /\* Free block *\/ */
94   /*   fprintf(stderr, "Asked to display the backtrace of a block that is free. I'm puzzled\n"); */
95   /*   xbt_abort(); */
96   /*   break;  */
97   /* case 0: /\* Large block *\/ */
98   /*   mmalloc_backtrace_block_display(heap->heapinfo, block); */
99   /*   break; */
100   /* default: /\* Fragmented block *\/ */
101   /*   frag_nb = RESIDUAL(addr, BLOCKSIZE) >> type; */
102   /*   if(heap->heapinfo[block].busy_frag.frag_size[frag_nb] == -1){ */
103   /*     fprintf(stderr , "Asked to display the backtrace of a fragment that is free. I'm puzzled\n"); */
104   /*     xbt_abort(); */
105   /*   } */
106   /*   mmalloc_backtrace_fragment_display(heap->heapinfo, block, frag_nb); */
107   /*   break; */
108   /* } */
109 }
110
111
112 static int compare_backtrace(int b1, int f1, int b2, int f2)
113 {
114   /*int i = 0;
115      if(f1 != -1){
116      for(i=0; i< XBT_BACKTRACE_SIZE; i++){
117      if(heapinfo1[b1].busy_frag.bt[f1][i] != heapinfo2[b2].busy_frag.bt[f2][i]){
118      //mmalloc_backtrace_fragment_display((void*)heapinfo1, b1, f1);
119      //mmalloc_backtrace_fragment_display((void*)heapinfo2, b2, f2);
120      return 1;
121      }
122      }
123      }else{
124      for(i=0; i< heapinfo1[b1].busy_block.bt_size; i++){
125      if(heapinfo1[b1].busy_block.bt[i] != heapinfo2[b2].busy_block.bt[i]){
126      //mmalloc_backtrace_block_display((void*)heapinfo1, b1);
127      //mmalloc_backtrace_block_display((void*)heapinfo2, b2);
128      return 1;
129      }
130      }
131      } */
132   return 0;
133 }
134
135
136 /*********************************** Heap comparison ***********************************/
137 /***************************************************************************************/
138
139 typedef char *type_name;
140
141 struct s_mc_diff {
142   /** \brief Base address of the real heap */
143   void *s_heap;
144   /** \brief Base address of the first heap snapshot */
145   void *heapbase1;
146   /** \brief Base address of the second heap snapshot */
147   void *heapbase2;
148   malloc_info *heapinfo1, *heapinfo2;
149   size_t heaplimit;
150   // Number of blocks in the heaps:
151   size_t heapsize1, heapsize2;
152   xbt_dynar_t to_ignore1, to_ignore2;
153   s_heap_area_t *equals_to1, *equals_to2;
154   dw_type_t *types1, *types2;
155   size_t available;
156 };
157
158 #define equals_to1_(i,j) equals_to1[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
159 #define equals_to2_(i,j) equals_to2[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
160 #define types1_(i,j) types1[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
161 #define types2_(i,j) types2[ MAX_FRAGMENT_PER_BLOCK*(i) + (j)]
162
163 __thread struct s_mc_diff *mc_diff_info = NULL;
164
165 /*********************************** Free functions ************************************/
166
167 static void heap_area_pair_free(heap_area_pair_t pair)
168 {
169   xbt_free(pair);
170   pair = NULL;
171 }
172
173 static void heap_area_pair_free_voidp(void *d)
174 {
175   heap_area_pair_free((heap_area_pair_t) * (void **) d);
176 }
177
178 static void heap_area_free(heap_area_t area)
179 {
180   xbt_free(area);
181   area = NULL;
182 }
183
184 /************************************************************************************/
185
186 static s_heap_area_t make_heap_area(int block, int fragment)
187 {
188   s_heap_area_t area;
189   area.valid = 1;
190   area.block = block;
191   area.fragment = fragment;
192   return area;
193 }
194
195
196 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1,
197                                  int block2, int fragment2)
198 {
199
200   unsigned int cursor = 0;
201   heap_area_pair_t current_pair;
202
203   xbt_dynar_foreach(list, cursor, current_pair) {
204     if (current_pair->block1 == block1 && current_pair->block2 == block2
205         && current_pair->fragment1 == fragment1
206         && current_pair->fragment2 == fragment2)
207       return 0;
208   }
209
210   return 1;
211 }
212
213 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1,
214                               int block2, int fragment2)
215 {
216
217   if (is_new_heap_area_pair(list, block1, fragment1, block2, fragment2)) {
218     heap_area_pair_t pair = NULL;
219     pair = xbt_new0(s_heap_area_pair_t, 1);
220     pair->block1 = block1;
221     pair->fragment1 = fragment1;
222     pair->block2 = block2;
223     pair->fragment2 = fragment2;
224
225     xbt_dynar_push(list, &pair);
226
227     return 1;
228   }
229
230   return 0;
231 }
232
233 static ssize_t heap_comparison_ignore_size(xbt_dynar_t ignore_list,
234                                            void *address)
235 {
236
237   unsigned int cursor = 0;
238   int start = 0;
239   int end = xbt_dynar_length(ignore_list) - 1;
240   mc_heap_ignore_region_t region;
241
242   while (start <= end) {
243     cursor = (start + end) / 2;
244     region =
245         (mc_heap_ignore_region_t) xbt_dynar_get_as(ignore_list, cursor,
246                                                    mc_heap_ignore_region_t);
247     if (region->address == address)
248       return region->size;
249     if (region->address < address)
250       start = cursor + 1;
251     if (region->address > address)
252       end = cursor - 1;
253   }
254
255   return -1;
256 }
257
258 static int is_stack(void *address)
259 {
260   unsigned int cursor = 0;
261   stack_region_t stack;
262
263   xbt_dynar_foreach(stacks_areas, cursor, stack) {
264     if (address == stack->address)
265       return 1;
266   }
267
268   return 0;
269 }
270
271 static int is_block_stack(int block)
272 {
273   unsigned int cursor = 0;
274   stack_region_t stack;
275
276   xbt_dynar_foreach(stacks_areas, cursor, stack) {
277     if (block == stack->block)
278       return 1;
279   }
280
281   return 0;
282 }
283
284 static void match_equals(struct s_mc_diff *state, xbt_dynar_t list)
285 {
286
287   unsigned int cursor = 0;
288   heap_area_pair_t current_pair;
289
290   xbt_dynar_foreach(list, cursor, current_pair) {
291
292     if (current_pair->fragment1 != -1) {
293
294       state->equals_to1_(current_pair->block1, current_pair->fragment1) =
295           make_heap_area(current_pair->block2, current_pair->fragment2);
296       state->equals_to2_(current_pair->block2, current_pair->fragment2) =
297           make_heap_area(current_pair->block1, current_pair->fragment1);
298
299     } else {
300
301       state->equals_to1_(current_pair->block1, 0) =
302           make_heap_area(current_pair->block2, current_pair->fragment2);
303       state->equals_to2_(current_pair->block2, 0) =
304           make_heap_area(current_pair->block1, current_pair->fragment1);
305
306     }
307
308   }
309 }
310
311 /** Check whether two blocks are known to be matching
312  *
313  *  @param state  State used
314  *  @param b1     Block of state 1
315  *  @param b2     Block of state 2
316  *  @return       if the blocks are known to be matching
317  */
318 static int equal_blocks(struct s_mc_diff *state, int b1, int b2)
319 {
320
321   if (state->equals_to1_(b1, 0).block == b2
322       && state->equals_to2_(b2, 0).block == b1)
323     return 1;
324
325   return 0;
326 }
327
328 /** Check whether two fragments are known to be matching
329  *
330  *  @param state  State used
331  *  @param b1     Block of state 1
332  *  @param f1     Fragment of state 1
333  *  @param b2     Block of state 2
334  *  @param f2     Fragment of state 2
335  *  @return       if the fragments are known to be matching
336  */
337 static int equal_fragments(struct s_mc_diff *state, int b1, int f1, int b2,
338                            int f2)
339 {
340
341   if (state->equals_to1_(b1, f1).block == b2
342       && state->equals_to1_(b1, f1).fragment == f2
343       && state->equals_to2_(b2, f2).block == b1
344       && state->equals_to2_(b2, f2).fragment == f1)
345     return 1;
346
347   return 0;
348 }
349
350 int init_heap_information(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t i1,
351                           xbt_dynar_t i2)
352 {
353   if (mc_diff_info == NULL) {
354     mc_diff_info = xbt_new0(struct s_mc_diff, 1);
355     mc_diff_info->equals_to1 = NULL;
356     mc_diff_info->equals_to2 = NULL;
357     mc_diff_info->types1 = NULL;
358     mc_diff_info->types2 = NULL;
359   }
360   struct s_mc_diff *state = mc_diff_info;
361
362   if ((((struct mdesc *) heap1)->heaplimit !=
363        ((struct mdesc *) heap2)->heaplimit)
364       ||
365       ((((struct mdesc *) heap1)->heapsize !=
366         ((struct mdesc *) heap2)->heapsize)))
367     return -1;
368
369   state->heaplimit = ((struct mdesc *) heap1)->heaplimit;
370
371   // Mamailloute in order to find the base address of the main heap:
372   state->s_heap =
373       (char *) mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize;
374
375   state->heapbase1 = (char *) heap1 + BLOCKSIZE;
376   state->heapbase2 = (char *) heap2 + BLOCKSIZE;
377
378   state->heapinfo1 =
379       (malloc_info *) ((char *) heap1 +
380                        ((uintptr_t)
381                         ((char *) ((struct mdesc *) heap1)->heapinfo -
382                          (char *) state->s_heap)));
383   state->heapinfo2 =
384       (malloc_info *) ((char *) heap2 +
385                        ((uintptr_t)
386                         ((char *) ((struct mdesc *) heap2)->heapinfo -
387                          (char *) state->s_heap)));
388
389   state->heapsize1 = heap1->heapsize;
390   state->heapsize2 = heap2->heapsize;
391
392   state->to_ignore1 = i1;
393   state->to_ignore2 = i2;
394
395   if (state->heaplimit > state->available) {
396     state->equals_to1 =
397         realloc(state->equals_to1,
398                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
399                 sizeof(s_heap_area_t));
400     state->types1 =
401         realloc(state->types1,
402                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
403                 sizeof(type_name *));
404     state->equals_to2 =
405         realloc(state->equals_to2,
406                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
407                 sizeof(s_heap_area_t));
408     state->types2 =
409         realloc(state->types2,
410                 state->heaplimit * MAX_FRAGMENT_PER_BLOCK *
411                 sizeof(type_name *));
412     state->available = state->heaplimit;
413   }
414
415   memset(state->equals_to1, 0,
416          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(s_heap_area_t));
417   memset(state->equals_to2, 0,
418          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(s_heap_area_t));
419   memset(state->types1, 0,
420          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(type_name *));
421   memset(state->types2, 0,
422          state->heaplimit * MAX_FRAGMENT_PER_BLOCK * sizeof(type_name *));
423
424   if (MC_is_active()) {
425     MC_ignore_global_variable("mc_diff_info");
426   }
427
428   return 0;
429
430 }
431
432 void reset_heap_information()
433 {
434
435 }
436
437 int mmalloc_compare_heap(mc_snapshot_t snapshot1, mc_snapshot_t snapshot2,
438                          xbt_mheap_t heap1, xbt_mheap_t heap2)
439 {
440
441   struct s_mc_diff *state = mc_diff_info;
442
443   if (heap1 == NULL && heap2 == NULL) {
444     XBT_DEBUG("Malloc descriptors null");
445     return 0;
446   }
447
448   /* Start comparison */
449   size_t i1, i2, j1, j2, k;
450   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
451   int nb_diff1 = 0, nb_diff2 = 0;
452
453   xbt_dynar_t previous =
454       xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
455
456   int equal, res_compare = 0;
457
458   /* Check busy blocks */
459
460   i1 = 1;
461
462   while (i1 <= state->heaplimit) {
463
464     if (state->heapinfo1[i1].type == -1) {      /* Free block */
465       i1++;
466       continue;
467     }
468
469     addr_block1 =
470         ((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
471                    (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
472
473     if (state->heapinfo1[i1].type == 0) {       /* Large block */
474
475       if (is_stack(addr_block1)) {
476         for (k = 0; k < state->heapinfo1[i1].busy_block.size; k++)
477           state->equals_to1_(i1 + k, 0) = make_heap_area(i1, -1);
478         for (k = 0; k < state->heapinfo2[i1].busy_block.size; k++)
479           state->equals_to2_(i1 + k, 0) = make_heap_area(i1, -1);
480         i1 += state->heapinfo1[i1].busy_block.size;
481         continue;
482       }
483
484       if (state->equals_to1_(i1, 0).valid) {
485         i1++;
486         continue;
487       }
488
489       i2 = 1;
490       equal = 0;
491       res_compare = 0;
492
493       /* Try first to associate to same block in the other heap */
494       if (state->heapinfo2[i1].type == state->heapinfo1[i1].type) {
495
496         if (state->equals_to2_(i1, 0).valid == 0) {
497
498           addr_block2 =
499               ((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
500                          (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
501
502           res_compare =
503               compare_heap_area(addr_block1, addr_block2, snapshot1, snapshot2,
504                                 NULL, NULL, 0);
505
506           if (res_compare != 1) {
507             for (k = 1; k < state->heapinfo2[i1].busy_block.size; k++)
508               state->equals_to2_(i1 + k, 0) = make_heap_area(i1, -1);
509             for (k = 1; k < state->heapinfo1[i1].busy_block.size; k++)
510               state->equals_to1_(i1 + k, 0) = make_heap_area(i1, -1);
511             equal = 1;
512             i1 += state->heapinfo1[i1].busy_block.size;
513           }
514
515           xbt_dynar_reset(previous);
516
517         }
518
519       }
520
521       while (i2 <= state->heaplimit && !equal) {
522
523         addr_block2 =
524             ((void *) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE +
525                        (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
526
527         if (i2 == i1) {
528           i2++;
529           continue;
530         }
531
532         if (state->heapinfo2[i2].type != 0) {
533           i2++;
534           continue;
535         }
536
537         if (state->equals_to2_(i2, 0).valid) {
538           i2++;
539           continue;
540         }
541
542         res_compare =
543             compare_heap_area(addr_block1, addr_block2, snapshot1, snapshot2,
544                               NULL, NULL, 0);
545
546         if (res_compare != 1) {
547           for (k = 1; k < state->heapinfo2[i2].busy_block.size; k++)
548             state->equals_to2_(i2 + k, 0) = make_heap_area(i1, -1);
549           for (k = 1; k < state->heapinfo1[i1].busy_block.size; k++)
550             state->equals_to1_(i1 + k, 0) = make_heap_area(i2, -1);
551           equal = 1;
552           i1 += state->heapinfo1[i1].busy_block.size;
553         }
554
555         xbt_dynar_reset(previous);
556
557         i2++;
558
559       }
560
561       if (!equal) {
562         XBT_DEBUG("Block %zu not found (size_used = %zu, addr = %p)", i1,
563                   state->heapinfo1[i1].busy_block.busy_size, addr_block1);
564         i1 = state->heaplimit + 1;
565         nb_diff1++;
566         //i1++;
567       }
568
569     } else {                    /* Fragmented block */
570
571       for (j1 = 0; j1 < (size_t) (BLOCKSIZE >> state->heapinfo1[i1].type); j1++) {
572
573         if (state->heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */
574           continue;
575
576         if (state->equals_to1_(i1, j1).valid)
577           continue;
578
579         addr_frag1 =
580             (void *) ((char *) addr_block1 + (j1 << state->heapinfo1[i1].type));
581
582         i2 = 1;
583         equal = 0;
584
585         /* Try first to associate to same fragment in the other heap */
586         if (state->heapinfo2[i1].type == state->heapinfo1[i1].type) {
587
588           if (state->equals_to2_(i1, j1).valid == 0) {
589
590             addr_block2 =
591                 ((void *) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE +
592                            (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
593             addr_frag2 =
594                 (void *) ((char *) addr_block2 +
595                           (j1 << ((xbt_mheap_t) state->s_heap)->heapinfo[i1].
596                            type));
597
598             res_compare =
599                 compare_heap_area(addr_frag1, addr_frag2, snapshot1, snapshot2,
600                                   NULL, NULL, 0);
601
602             if (res_compare != 1)
603               equal = 1;
604
605             xbt_dynar_reset(previous);
606
607           }
608
609         }
610
611         while (i2 <= state->heaplimit && !equal) {
612
613           if (state->heapinfo2[i2].type <= 0) {
614             i2++;
615             continue;
616           }
617
618           for (j2 = 0; j2 < (size_t) (BLOCKSIZE >> state->heapinfo2[i2].type);
619                j2++) {
620
621             if (i2 == i1 && j2 == j1)
622               continue;
623
624             if (state->equals_to2_(i2, j2).valid)
625               continue;
626
627             addr_block2 =
628                 ((void *) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE +
629                            (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
630             addr_frag2 =
631                 (void *) ((char *) addr_block2 +
632                           (j2 << ((xbt_mheap_t) state->s_heap)->heapinfo[i2].
633                            type));
634
635             res_compare =
636                 compare_heap_area(addr_frag1, addr_frag2, snapshot2, snapshot2,
637                                   NULL, NULL, 0);
638
639             if (res_compare != 1) {
640               equal = 1;
641               xbt_dynar_reset(previous);
642               break;
643             }
644
645             xbt_dynar_reset(previous);
646
647           }
648
649           i2++;
650
651         }
652
653         if (!equal) {
654           XBT_DEBUG
655               ("Block %zu, fragment %zu not found (size_used = %zd, address = %p)\n",
656                i1, j1, state->heapinfo1[i1].busy_frag.frag_size[j1],
657                addr_frag1);
658           i2 = state->heaplimit + 1;
659           i1 = state->heaplimit + 1;
660           nb_diff1++;
661           break;
662         }
663
664       }
665
666       i1++;
667
668     }
669
670   }
671
672   /* All blocks/fragments are equal to another block/fragment ? */
673   size_t i = 1, j = 0;
674   void *real_addr_frag1 = NULL, *real_addr_block1 = NULL, *real_addr_block2 =
675       NULL, *real_addr_frag2 = NULL;
676
677   while (i <= state->heaplimit) {
678     if (state->heapinfo1[i].type == 0) {
679       if (i1 == state->heaplimit) {
680         if (state->heapinfo1[i].busy_block.busy_size > 0) {
681           if (state->equals_to1_(i, 0).valid == 0) {
682             if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
683               addr_block1 =
684                   ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
685                              (char *) state->heapbase1));
686               XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i,
687                         addr_block1, state->heapinfo1[i].busy_block.busy_size);
688               //mmalloc_backtrace_block_display((void*)heapinfo1, i);
689             }
690             nb_diff1++;
691           }
692         }
693       }
694     }
695     if (state->heapinfo1[i].type > 0) {
696       addr_block1 =
697           ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
698                      (char *) state->heapbase1));
699       real_addr_block1 =
700           ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
701                      (char *) ((struct mdesc *) state->s_heap)->heapbase));
702       for (j = 0; j < (size_t) (BLOCKSIZE >> state->heapinfo1[i].type); j++) {
703         if (i1 == state->heaplimit) {
704           if (state->heapinfo1[i].busy_frag.frag_size[j] > 0) {
705             if (state->equals_to1_(i, j).valid == 0) {
706               if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
707                 addr_frag1 =
708                     (void *) ((char *) addr_block1 +
709                               (j << state->heapinfo1[i].type));
710                 real_addr_frag1 =
711                     (void *) ((char *) real_addr_block1 +
712                               (j << ((struct mdesc *) state->s_heap)->
713                                heapinfo[i].type));
714                 XBT_DEBUG
715                     ("Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)",
716                      i, j, addr_frag1, real_addr_frag1,
717                      state->heapinfo1[i].busy_frag.frag_size[j]);
718                 //mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j);
719               }
720               nb_diff1++;
721             }
722           }
723         }
724       }
725     }
726     i++;
727   }
728
729   if (i1 == state->heaplimit)
730     XBT_DEBUG("Number of blocks/fragments not found in heap1 : %d", nb_diff1);
731
732   i = 1;
733
734   while (i <= state->heaplimit) {
735     if (state->heapinfo2[i].type == 0) {
736       if (i1 == state->heaplimit) {
737         if (state->heapinfo2[i].busy_block.busy_size > 0) {
738           if (state->equals_to2_(i, 0).valid == 0) {
739             if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
740               addr_block2 =
741                   ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
742                              (char *) state->heapbase2));
743               XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i,
744                         addr_block2, state->heapinfo2[i].busy_block.busy_size);
745               //mmalloc_backtrace_block_display((void*)heapinfo2, i);
746             }
747             nb_diff2++;
748           }
749         }
750       }
751     }
752     if (state->heapinfo2[i].type > 0) {
753       addr_block2 =
754           ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
755                      (char *) state->heapbase2));
756       real_addr_block2 =
757           ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
758                      (char *) ((struct mdesc *) state->s_heap)->heapbase));
759       for (j = 0; j < (size_t) (BLOCKSIZE >> state->heapinfo2[i].type); j++) {
760         if (i1 == state->heaplimit) {
761           if (state->heapinfo2[i].busy_frag.frag_size[j] > 0) {
762             if (state->equals_to2_(i, j).valid == 0) {
763               if (XBT_LOG_ISENABLED(mc_diff, xbt_log_priority_debug)) {
764                 addr_frag2 =
765                     (void *) ((char *) addr_block2 +
766                               (j << state->heapinfo2[i].type));
767                 real_addr_frag2 =
768                     (void *) ((char *) real_addr_block2 +
769                               (j << ((struct mdesc *) state->s_heap)->
770                                heapinfo[i].type));
771                 XBT_DEBUG
772                     ("Block %zu, Fragment %zu (%p - %p) not found (size used = %zd)",
773                      i, j, addr_frag2, real_addr_frag2,
774                      state->heapinfo2[i].busy_frag.frag_size[j]);
775                 //mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j);
776               }
777               nb_diff2++;
778             }
779           }
780         }
781       }
782     }
783     i++;
784   }
785
786   if (i1 == state->heaplimit)
787     XBT_DEBUG("Number of blocks/fragments not found in heap2 : %d", nb_diff2);
788
789   xbt_dynar_free(&previous);
790   real_addr_frag1 = NULL, real_addr_block1 = NULL, real_addr_block2 =
791       NULL, real_addr_frag2 = NULL;
792
793   return ((nb_diff1 > 0) || (nb_diff2 > 0));
794 }
795
796 /**
797  *
798  * @param state
799  * @param real_area1     Process address for state 1
800  * @param real_area2     Process address for state 2
801  * @param area1          Snapshot address for state 1
802  * @param area2          Snapshot address for state 2
803  * @param snapshot1      Snapshot of state 1
804  * @param snapshot2      Snapshot of state 2
805  * @param previous
806  * @param size
807  * @param check_ignore
808  */
809 static int compare_heap_area_without_type(struct s_mc_diff *state,
810                                           void *real_area1, void *real_area2,
811                                           void *area1, void *area2,
812                                           mc_snapshot_t snapshot1,
813                                           mc_snapshot_t snapshot2,
814                                           xbt_dynar_t previous, int size,
815                                           int check_ignore)
816 {
817
818   int i = 0;
819   void *addr_pointed1, *addr_pointed2;
820   int pointer_align, res_compare;
821   ssize_t ignore1, ignore2;
822
823   while (i < size) {
824
825     if (check_ignore > 0) {
826       if ((ignore1 =
827            heap_comparison_ignore_size(state->to_ignore1,
828                                        (char *) real_area1 + i)) != -1) {
829         if ((ignore2 =
830              heap_comparison_ignore_size(state->to_ignore2,
831                                          (char *) real_area2 + i)) == ignore1) {
832           if (ignore1 == 0) {
833             check_ignore--;
834             return 0;
835           } else {
836             i = i + ignore2;
837             check_ignore--;
838             continue;
839           }
840         }
841       }
842     }
843
844     if (memcmp(((char *) area1) + i, ((char *) area2) + i, 1) != 0) {
845
846       pointer_align = (i / sizeof(void *)) * sizeof(void *);
847       addr_pointed1 = *((void **) ((char *) area1 + pointer_align));
848       addr_pointed2 = *((void **) ((char *) area2 + pointer_align));
849
850       if (addr_pointed1 > maestro_stack_start
851           && addr_pointed1 < maestro_stack_end
852           && addr_pointed2 > maestro_stack_start
853           && addr_pointed2 < maestro_stack_end) {
854         i = pointer_align + sizeof(void *);
855         continue;
856       } else if (addr_pointed1 > state->s_heap
857                  && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
858                  && addr_pointed2 > state->s_heap
859                  && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2)) {
860         // Both addreses are in the heap:
861         res_compare =
862             compare_heap_area(addr_pointed1, addr_pointed2, snapshot1,
863                               snapshot2, previous, NULL, 0);
864         if (res_compare == 1) {
865           return res_compare;
866         }
867         i = pointer_align + sizeof(void *);
868         continue;
869       } else {
870         return 1;
871       }
872
873     }
874
875     i++;
876
877   }
878
879   return 0;
880
881 }
882
883 /**
884  *
885  * @param state
886  * @param real_area1     Process address for state 1
887  * @param real_area2     Process address for state 2
888  * @param area1          Snapshot address for state 1
889  * @param area2          Snapshot address for state 2
890  * @param snapshot1      Snapshot of state 1
891  * @param snapshot2      Snapshot of state 2
892  * @param previous
893  * @param type_id
894  * @param area_size      either a byte_size or an elements_count (?)
895  * @param check_ignore
896  * @param pointer_level
897  * @return               0 (same), 1 (different), -1 (unknown)
898  */
899 static int compare_heap_area_with_type(struct s_mc_diff *state,
900                                        void *real_area1, void *real_area2,
901                                        void *area1, void *area2,
902                                        mc_snapshot_t snapshot1,
903                                        mc_snapshot_t snapshot2,
904                                        xbt_dynar_t previous, dw_type_t type,
905                                        int area_size, int check_ignore,
906                                        int pointer_level)
907 {
908
909   if (is_stack(real_area1) && is_stack(real_area2))
910     return 0;
911
912   ssize_t ignore1, ignore2;
913
914   if ((check_ignore > 0)
915       && ((ignore1 = heap_comparison_ignore_size(state->to_ignore1, real_area1))
916           > 0)
917       && ((ignore2 = heap_comparison_ignore_size(state->to_ignore2, real_area2))
918           == ignore1)) {
919     return 0;
920   }
921
922   dw_type_t subtype, subsubtype;
923   int res, elm_size, i;
924   unsigned int cursor = 0;
925   dw_type_t member;
926   void *addr_pointed1, *addr_pointed2;;
927
928   switch (type->type) {
929   case DW_TAG_unspecified_type:
930     return 1;
931
932   case DW_TAG_base_type:
933     if (type->name != NULL && strcmp(type->name, "char") == 0) {        /* String, hence random (arbitrary ?) size */
934       if (real_area1 == real_area2)
935         return -1;
936       else
937         return (memcmp(area1, area2, area_size) != 0);
938     } else {
939       if (area_size != -1 && type->byte_size != area_size)
940         return -1;
941       else {
942         return (memcmp(area1, area2, type->byte_size) != 0);
943       }
944     }
945     break;
946   case DW_TAG_enumeration_type:
947     if (area_size != -1 && type->byte_size != area_size)
948       return -1;
949     else
950       return (memcmp(area1, area2, type->byte_size) != 0);
951     break;
952   case DW_TAG_typedef:
953   case DW_TAG_const_type:
954   case DW_TAG_volatile_type:
955     return compare_heap_area_with_type(state, real_area1, real_area2, area1,
956                                        area2, snapshot1, snapshot2, previous,
957                                        type->subtype, area_size, check_ignore,
958                                        pointer_level);
959     break;
960   case DW_TAG_array_type:
961     subtype = type->subtype;
962     switch (subtype->type) {
963     case DW_TAG_unspecified_type:
964       return 1;
965
966     case DW_TAG_base_type:
967     case DW_TAG_enumeration_type:
968     case DW_TAG_pointer_type:
969     case DW_TAG_reference_type:
970     case DW_TAG_rvalue_reference_type:
971     case DW_TAG_structure_type:
972     case DW_TAG_class_type:
973     case DW_TAG_union_type:
974       if (subtype->full_type)
975         subtype = subtype->full_type;
976       elm_size = subtype->byte_size;
977       break;
978       // TODO, just remove the type indirection?
979     case DW_TAG_const_type:
980     case DW_TAG_typedef:
981     case DW_TAG_volatile_type:
982       subsubtype = subtype->subtype;
983       if (subsubtype->full_type)
984         subsubtype = subsubtype->full_type;
985       elm_size = subsubtype->byte_size;
986       break;
987     default:
988       return 0;
989       break;
990     }
991     for (i = 0; i < type->element_count; i++) {
992       // TODO, add support for variable stride (DW_AT_byte_stride)
993       res =
994           compare_heap_area_with_type(state,
995                                       (char *) real_area1 + (i * elm_size),
996                                       (char *) real_area2 + (i * elm_size),
997                                       (char *) area1 + (i * elm_size),
998                                       (char *) area2 + (i * elm_size),
999                                       snapshot1, snapshot2, previous,
1000                                       type->subtype, subtype->byte_size,
1001                                       check_ignore, pointer_level);
1002       if (res == 1)
1003         return res;
1004     }
1005     break;
1006   case DW_TAG_reference_type:
1007   case DW_TAG_rvalue_reference_type:
1008   case DW_TAG_pointer_type:
1009     if (type->subtype && type->subtype->type == DW_TAG_subroutine_type) {
1010       addr_pointed1 = *((void **) (area1));
1011       addr_pointed2 = *((void **) (area2));
1012       return (addr_pointed1 != addr_pointed2);;
1013     } else {
1014       pointer_level++;
1015       if (pointer_level > 1) {  /* Array of pointers */
1016         for (i = 0; i < (area_size / sizeof(void *)); i++) {
1017           addr_pointed1 = *((void **) ((char *) area1 + (i * sizeof(void *))));
1018           addr_pointed2 = *((void **) ((char *) area2 + (i * sizeof(void *))));
1019           if (addr_pointed1 > state->s_heap
1020               && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
1021               && addr_pointed2 > state->s_heap
1022               && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
1023             res =
1024                 compare_heap_area(addr_pointed1, addr_pointed2, snapshot1,
1025                                   snapshot2, previous, type->subtype,
1026                                   pointer_level);
1027           else
1028             res = (addr_pointed1 != addr_pointed2);
1029           if (res == 1)
1030             return res;
1031         }
1032       } else {
1033         addr_pointed1 = *((void **) (area1));
1034         addr_pointed2 = *((void **) (area2));
1035         if (addr_pointed1 > state->s_heap
1036             && addr_pointed1 < mc_snapshot_get_heap_end(snapshot1)
1037             && addr_pointed2 > state->s_heap
1038             && addr_pointed2 < mc_snapshot_get_heap_end(snapshot2))
1039           return compare_heap_area(addr_pointed1, addr_pointed2, snapshot1,
1040                                    snapshot2, previous, type->subtype,
1041                                    pointer_level);
1042         else
1043           return (addr_pointed1 != addr_pointed2);
1044       }
1045     }
1046     break;
1047   case DW_TAG_structure_type:
1048   case DW_TAG_class_type:
1049     if (type->full_type)
1050       type = type->full_type;
1051     if (area_size != -1 && type->byte_size != area_size) {
1052       if (area_size > type->byte_size && area_size % type->byte_size == 0) {
1053         for (i = 0; i < (area_size / type->byte_size); i++) {
1054           res =
1055               compare_heap_area_with_type(state,
1056                                           (char *) real_area1 +
1057                                           (i * type->byte_size),
1058                                           (char *) real_area2 +
1059                                           (i * type->byte_size),
1060                                           (char *) area1 +
1061                                           (i * type->byte_size),
1062                                           (char *) area2 +
1063                                           (i * type->byte_size), snapshot1,
1064                                           snapshot2, previous, type, -1,
1065                                           check_ignore, 0);
1066           if (res == 1)
1067             return res;
1068         }
1069       } else {
1070         return -1;
1071       }
1072     } else {
1073       cursor = 0;
1074       xbt_dynar_foreach(type->members, cursor, member) {
1075         // TODO, optimize this? (for the offset case)
1076         char *real_member1 =
1077             mc_member_resolve(real_area1, type, member, snapshot1);
1078         char *real_member2 =
1079             mc_member_resolve(real_area2, type, member, snapshot2);
1080         char *member1 =
1081             mc_translate_address((uintptr_t) real_member1, snapshot1);
1082         char *member2 =
1083             mc_translate_address((uintptr_t) real_member2, snapshot2);
1084         res =
1085             compare_heap_area_with_type(state, real_member1, real_member2,
1086                                         member1, member2, snapshot1, snapshot2,
1087                                         previous, member->subtype, -1,
1088                                         check_ignore, 0);
1089         if (res == 1) {
1090           return res;
1091         }
1092       }
1093     }
1094     break;
1095   case DW_TAG_union_type:
1096     return compare_heap_area_without_type(state, real_area1, real_area2, area1,
1097                                           area2, snapshot1, snapshot2, previous,
1098                                           type->byte_size, check_ignore);
1099     break;
1100   default:
1101     break;
1102   }
1103
1104   return 0;
1105
1106 }
1107
1108 /** Infer the type of a part of the block from the type of the block
1109  *
1110  * TODO, handle DW_TAG_array_type as well as arrays of the object ((*p)[5], p[5])
1111  *
1112  * TODO, handle subfields ((*p).bar.foo, (*p)[5].bar…)
1113  *
1114  * @param  type_id            DWARF type ID of the root address
1115  * @param  area_size
1116  * @return                    DWARF type ID for given offset
1117  */
1118 static dw_type_t get_offset_type(void *real_base_address, dw_type_t type,
1119                                  int offset, int area_size,
1120                                  mc_snapshot_t snapshot)
1121 {
1122
1123   // Beginning of the block, the infered variable type if the type of the block:
1124   if (offset == 0)
1125     return type;
1126
1127   switch (type->type) {
1128   case DW_TAG_structure_type:
1129   case DW_TAG_class_type:
1130     if (type->full_type)
1131       type = type->full_type;
1132
1133     if (area_size != -1 && type->byte_size != area_size) {
1134       if (area_size > type->byte_size && area_size % type->byte_size == 0)
1135         return type;
1136       else
1137         return NULL;
1138     } else {
1139       unsigned int cursor = 0;
1140       dw_type_t member;
1141       xbt_dynar_foreach(type->members, cursor, member) {
1142
1143         if (!member->location.size) {
1144           // We have the offset, use it directly (shortcut):
1145           if (member->offset == offset)
1146             return member->subtype;
1147         } else {
1148           char *real_member =
1149               mc_member_resolve(real_base_address, type, member, snapshot);
1150           if (real_member - (char *) real_base_address == offset)
1151             return member->subtype;
1152         }
1153
1154       }
1155       return NULL;
1156     }
1157     break;
1158   default:
1159     /* FIXME : other cases ? */
1160     return NULL;
1161     break;
1162   }
1163 }
1164
1165 /**
1166  *
1167  * @param area1          Process address for state 1
1168  * @param area2          Process address for state 2
1169  * @param snapshot1      Snapshot of state 1
1170  * @param snapshot2      Snapshot of state 2
1171  * @param previous       Pairs of blocks already compared on the current path (or NULL)
1172  * @param type_id        Type of variable
1173  * @param pointer_level
1174  * @return 0 (same), 1 (different), -1
1175  */
1176 int compare_heap_area(void *area1, void *area2, mc_snapshot_t snapshot1,
1177                       mc_snapshot_t snapshot2, xbt_dynar_t previous,
1178                       dw_type_t type, int pointer_level)
1179 {
1180
1181   struct s_mc_diff *state = mc_diff_info;
1182
1183   int res_compare;
1184   ssize_t block1, frag1, block2, frag2;
1185   ssize_t size;
1186   int check_ignore = 0;
1187
1188   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2, *real_addr_block1,
1189       *real_addr_block2, *real_addr_frag1, *real_addr_frag2;
1190   void *area1_to_compare, *area2_to_compare;
1191   int type_size = -1;
1192   int offset1 = 0, offset2 = 0;
1193   int new_size1 = -1, new_size2 = -1;
1194   dw_type_t new_type1 = NULL, new_type2 = NULL;
1195
1196   int match_pairs = 0;
1197
1198   if (previous == NULL) {
1199     previous =
1200         xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
1201     match_pairs = 1;
1202   }
1203   // Get block number:
1204   block1 =
1205       ((char *) area1 -
1206        (char *) ((xbt_mheap_t) state->s_heap)->heapbase) / BLOCKSIZE + 1;
1207   block2 =
1208       ((char *) area2 -
1209        (char *) ((xbt_mheap_t) state->s_heap)->heapbase) / BLOCKSIZE + 1;
1210
1211   // If either block is a stack block:
1212   if (is_block_stack((int) block1) && is_block_stack((int) block2)) {
1213     add_heap_area_pair(previous, block1, -1, block2, -1);
1214     if (match_pairs) {
1215       match_equals(state, previous);
1216       xbt_dynar_free(&previous);
1217     }
1218     return 0;
1219   }
1220   // If either block is not in the expected area of memory:
1221   if (((char *) area1 < (char *) ((xbt_mheap_t) state->s_heap)->heapbase)
1222       || (block1 > state->heapsize1) || (block1 < 1)
1223       || ((char *) area2 < (char *) ((xbt_mheap_t) state->s_heap)->heapbase)
1224       || (block2 > state->heapsize2) || (block2 < 1)) {
1225     if (match_pairs) {
1226       xbt_dynar_free(&previous);
1227     }
1228     return 1;
1229   }
1230   // Snapshot address of the block:
1231   addr_block1 =
1232       ((void *) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE +
1233                  (char *) state->heapbase1));
1234   addr_block2 =
1235       ((void *) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE +
1236                  (char *) state->heapbase2));
1237
1238   // Process address of the block:
1239   real_addr_block1 =
1240       ((void *) (((ADDR2UINT(block1)) - 1) * BLOCKSIZE +
1241                  (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
1242   real_addr_block2 =
1243       ((void *) (((ADDR2UINT(block2)) - 1) * BLOCKSIZE +
1244                  (char *) ((xbt_mheap_t) state->s_heap)->heapbase));
1245
1246   if (type) {
1247
1248     if (type->full_type)
1249       type = type->full_type;
1250
1251     // This assume that for "boring" types (volatile ...) byte_size is absent:
1252     while (type->byte_size == 0 && type->subtype != NULL)
1253       type = type->subtype;
1254
1255     // Find type_size:
1256     if ((type->type == DW_TAG_pointer_type)
1257         || ((type->type == DW_TAG_base_type) && type->name != NULL
1258             && (!strcmp(type->name, "char"))))
1259       type_size = -1;
1260     else
1261       type_size = type->byte_size;
1262
1263   }
1264
1265   if ((state->heapinfo1[block1].type == -1) && (state->heapinfo2[block2].type == -1)) { /* Free block */
1266
1267     if (match_pairs) {
1268       match_equals(state, previous);
1269       xbt_dynar_free(&previous);
1270     }
1271     return 0;
1272
1273   } else if ((state->heapinfo1[block1].type == 0) && (state->heapinfo2[block2].type == 0)) {    /* Complete block */
1274
1275     // TODO, lookup variable type from block type as done for fragmented blocks
1276
1277     if (state->equals_to1_(block1, 0).valid
1278         && state->equals_to2_(block2, 0).valid) {
1279       if (equal_blocks(state, block1, block2)) {
1280         if (match_pairs) {
1281           match_equals(state, previous);
1282           xbt_dynar_free(&previous);
1283         }
1284         return 0;
1285       }
1286     }
1287
1288     if (type_size != -1) {
1289       if (type_size != state->heapinfo1[block1].busy_block.busy_size
1290           && type_size != state->heapinfo2[block2].busy_block.busy_size
1291           && type->name != NULL && !strcmp(type->name, "s_smx_context")) {
1292         if (match_pairs) {
1293           match_equals(state, previous);
1294           xbt_dynar_free(&previous);
1295         }
1296         return -1;
1297       }
1298     }
1299
1300     if (state->heapinfo1[block1].busy_block.size !=
1301         state->heapinfo2[block2].busy_block.size) {
1302       if (match_pairs) {
1303         xbt_dynar_free(&previous);
1304       }
1305       return 1;
1306     }
1307
1308     if (state->heapinfo1[block1].busy_block.busy_size !=
1309         state->heapinfo2[block2].busy_block.busy_size) {
1310       if (match_pairs) {
1311         xbt_dynar_free(&previous);
1312       }
1313       return 1;
1314     }
1315
1316     if (!add_heap_area_pair(previous, block1, -1, block2, -1)) {
1317       if (match_pairs) {
1318         match_equals(state, previous);
1319         xbt_dynar_free(&previous);
1320       }
1321       return 0;
1322     }
1323
1324     size = state->heapinfo1[block1].busy_block.busy_size;
1325
1326     // Remember (basic) type inference.
1327     // The current data structure only allows us to do this for the whole block.
1328     if (type != NULL && area1 == real_addr_block1) {
1329       state->types1_(block1, 0) = type;
1330     }
1331     if (type != NULL && area2 == real_addr_block2) {
1332       state->types2_(block2, 0) = type;
1333     }
1334
1335     if (size <= 0) {
1336       if (match_pairs) {
1337         match_equals(state, previous);
1338         xbt_dynar_free(&previous);
1339       }
1340       return 0;
1341     }
1342
1343     frag1 = -1;
1344     frag2 = -1;
1345
1346     area1_to_compare = addr_block1;
1347     area2_to_compare = addr_block2;
1348
1349     if ((state->heapinfo1[block1].busy_block.ignore > 0)
1350         && (state->heapinfo2[block2].busy_block.ignore ==
1351             state->heapinfo1[block1].busy_block.ignore))
1352       check_ignore = state->heapinfo1[block1].busy_block.ignore;
1353
1354   } else if ((state->heapinfo1[block1].type > 0) && (state->heapinfo2[block2].type > 0)) {      /* Fragmented block */
1355
1356     // Fragment number:
1357     frag1 =
1358         ((uintptr_t) (ADDR2UINT(area1) % (BLOCKSIZE))) >> state->
1359         heapinfo1[block1].type;
1360     frag2 =
1361         ((uintptr_t) (ADDR2UINT(area2) % (BLOCKSIZE))) >> state->
1362         heapinfo2[block2].type;
1363
1364     // Snapshot address of the fragment:
1365     addr_frag1 =
1366         (void *) ((char *) addr_block1 +
1367                   (frag1 << state->heapinfo1[block1].type));
1368     addr_frag2 =
1369         (void *) ((char *) addr_block2 +
1370                   (frag2 << state->heapinfo2[block2].type));
1371
1372     // Process address of the fragment:
1373     real_addr_frag1 =
1374         (void *) ((char *) real_addr_block1 +
1375                   (frag1 << ((xbt_mheap_t) state->s_heap)->heapinfo[block1].
1376                    type));
1377     real_addr_frag2 =
1378         (void *) ((char *) real_addr_block2 +
1379                   (frag2 << ((xbt_mheap_t) state->s_heap)->heapinfo[block2].
1380                    type));
1381
1382     // Check the size of the fragments against the size of the type:
1383     if (type_size != -1) {
1384       if (state->heapinfo1[block1].busy_frag.frag_size[frag1] == -1
1385           || state->heapinfo2[block2].busy_frag.frag_size[frag2] == -1) {
1386         if (match_pairs) {
1387           match_equals(state, previous);
1388           xbt_dynar_free(&previous);
1389         }
1390         return -1;
1391       }
1392       if (type_size != state->heapinfo1[block1].busy_frag.frag_size[frag1]
1393           || type_size != state->heapinfo2[block2].busy_frag.frag_size[frag2]) {
1394         if (match_pairs) {
1395           match_equals(state, previous);
1396           xbt_dynar_free(&previous);
1397         }
1398         return -1;
1399       }
1400     }
1401     // Check if the blocks are already matched together:
1402     if (state->equals_to1_(block1, frag1).valid
1403         && state->equals_to2_(block2, frag2).valid) {
1404       if (equal_fragments(state, block1, frag1, block2, frag2)) {
1405         if (match_pairs) {
1406           match_equals(state, previous);
1407           xbt_dynar_free(&previous);
1408         }
1409         return 0;
1410       }
1411     }
1412     // Compare the size of both fragments:
1413     if (state->heapinfo1[block1].busy_frag.frag_size[frag1] !=
1414         state->heapinfo2[block2].busy_frag.frag_size[frag2]) {
1415       if (type_size == -1) {
1416         if (match_pairs) {
1417           match_equals(state, previous);
1418           xbt_dynar_free(&previous);
1419         }
1420         return -1;
1421       } else {
1422         if (match_pairs) {
1423           xbt_dynar_free(&previous);
1424         }
1425         return 1;
1426       }
1427     }
1428     // Size of the fragment:
1429     size = state->heapinfo1[block1].busy_frag.frag_size[frag1];
1430
1431     // Remember (basic) type inference.
1432     // The current data structure only allows us to do this for the whole block.
1433     if (type != NULL && area1 == real_addr_frag1) {
1434       state->types1_(block1, frag1) = type;
1435     }
1436     if (type != NULL && area2 == real_addr_frag2) {
1437       state->types2_(block2, frag2) = type;
1438     }
1439     // The type of the variable is already known:
1440     if (type) {
1441       new_type1 = type;
1442       new_type2 = type;
1443     }
1444     // Type inference from the block type.
1445     else if (state->types1_(block1, frag1) != NULL
1446              || state->types2_(block2, frag2) != NULL) {
1447
1448       offset1 = (char *) area1 - (char *) real_addr_frag1;
1449       offset2 = (char *) area2 - (char *) real_addr_frag2;
1450
1451       if (state->types1_(block1, frag1) != NULL
1452           && state->types2_(block2, frag2) != NULL) {
1453         new_type1 =
1454             get_offset_type(real_addr_frag1, state->types1_(block1, frag1),
1455                             offset1, size, snapshot1);
1456         new_type2 =
1457             get_offset_type(real_addr_frag2, state->types2_(block2, frag2),
1458                             offset1, size, snapshot2);
1459       } else if (state->types1_(block1, frag1) != NULL) {
1460         new_type1 =
1461             get_offset_type(real_addr_frag1, state->types1_(block1, frag1),
1462                             offset1, size, snapshot1);
1463         new_type2 =
1464             get_offset_type(real_addr_frag2, state->types1_(block1, frag1),
1465                             offset2, size, snapshot2);
1466       } else if (state->types2_(block2, frag2) != NULL) {
1467         new_type1 =
1468             get_offset_type(real_addr_frag1, state->types2_(block2, frag2),
1469                             offset1, size, snapshot1);
1470         new_type2 =
1471             get_offset_type(real_addr_frag2, state->types2_(block2, frag2),
1472                             offset2, size, snapshot2);
1473       } else {
1474         if (match_pairs) {
1475           match_equals(state, previous);
1476           xbt_dynar_free(&previous);
1477         }
1478         return -1;
1479       }
1480
1481       if (new_type1 != NULL && new_type2 != NULL && new_type1 != new_type2) {
1482
1483         type = new_type1;
1484         while (type->byte_size == 0 && type->subtype != NULL)
1485           type = type->subtype;
1486         new_size1 = type->byte_size;
1487
1488         type = new_type2;
1489         while (type->byte_size == 0 && type->subtype != NULL)
1490           type = type->subtype;
1491         new_size2 = type->byte_size;
1492
1493       } else {
1494         if (match_pairs) {
1495           match_equals(state, previous);
1496           xbt_dynar_free(&previous);
1497         }
1498         return -1;
1499       }
1500     }
1501
1502     area1_to_compare = (char *) addr_frag1 + offset1;
1503     area2_to_compare = (char *) addr_frag2 + offset2;
1504
1505     if (new_size1 > 0 && new_size1 == new_size2) {
1506       type = new_type1;
1507       size = new_size1;
1508     }
1509
1510     if (offset1 == 0 && offset2 == 0) {
1511       if (!add_heap_area_pair(previous, block1, frag1, block2, frag2)) {
1512         if (match_pairs) {
1513           match_equals(state, previous);
1514           xbt_dynar_free(&previous);
1515         }
1516         return 0;
1517       }
1518     }
1519
1520     if (size <= 0) {
1521       if (match_pairs) {
1522         match_equals(state, previous);
1523         xbt_dynar_free(&previous);
1524       }
1525       return 0;
1526     }
1527
1528     if ((state->heapinfo1[block1].busy_frag.ignore[frag1] > 0)
1529         && (state->heapinfo2[block2].busy_frag.ignore[frag2] ==
1530             state->heapinfo1[block1].busy_frag.ignore[frag1]))
1531       check_ignore = state->heapinfo1[block1].busy_frag.ignore[frag1];
1532
1533   } else {
1534
1535     if (match_pairs) {
1536       xbt_dynar_free(&previous);
1537     }
1538     return 1;
1539
1540   }
1541
1542
1543   /* Start comparison */
1544   if (type) {
1545     res_compare =
1546         compare_heap_area_with_type(state, area1, area2, area1_to_compare,
1547                                     area2_to_compare, snapshot1, snapshot2,
1548                                     previous, type, size, check_ignore,
1549                                     pointer_level);
1550   } else {
1551     res_compare =
1552         compare_heap_area_without_type(state, area1, area2, area1_to_compare,
1553                                        area2_to_compare, snapshot1, snapshot2,
1554                                        previous, size, check_ignore);
1555   }
1556   if (res_compare == 1) {
1557     if (match_pairs)
1558       xbt_dynar_free(&previous);
1559     return res_compare;
1560   }
1561
1562   if (match_pairs) {
1563     match_equals(state, previous);
1564     xbt_dynar_free(&previous);
1565   }
1566
1567   return 0;
1568 }
1569
1570 /*********************************************** Miscellaneous ***************************************************/
1571 /****************************************************************************************************************/
1572
1573 // Not used:
1574 static int get_pointed_area_size(void *area, int heap)
1575 {
1576
1577   struct s_mc_diff *state = mc_diff_info;
1578
1579   int block, frag;
1580   malloc_info *heapinfo;
1581
1582   if (heap == 1)
1583     heapinfo = state->heapinfo1;
1584   else
1585     heapinfo = state->heapinfo2;
1586
1587   block =
1588       ((char *) area -
1589        (char *) ((xbt_mheap_t) state->s_heap)->heapbase) / BLOCKSIZE + 1;
1590
1591   if (((char *) area < (char *) ((xbt_mheap_t) state->s_heap)->heapbase)
1592       || (block > state->heapsize1) || (block < 1))
1593     return -1;
1594
1595   if (heapinfo[block].type == -1) {     /* Free block */
1596     return -1;
1597   } else if (heapinfo[block].type == 0) {       /* Complete block */
1598     return (int) heapinfo[block].busy_block.busy_size;
1599   } else {
1600     frag =
1601         ((uintptr_t) (ADDR2UINT(area) % (BLOCKSIZE))) >> heapinfo[block].type;
1602     return (int) heapinfo[block].busy_frag.frag_size[frag];
1603   }
1604
1605 }
1606
1607 // Not used:
1608 char *get_type_description(mc_object_info_t info, char *type_name)
1609 {
1610
1611   xbt_dict_cursor_t dict_cursor;
1612   char *type_origin;
1613   dw_type_t type;
1614
1615   xbt_dict_foreach(info->types, dict_cursor, type_origin, type) {
1616     if (type->name && (strcmp(type->name, type_name) == 0)
1617         && type->byte_size > 0) {
1618       xbt_dict_cursor_free(&dict_cursor);
1619       return type_origin;
1620     }
1621   }
1622
1623   xbt_dict_cursor_free(&dict_cursor);
1624   return NULL;
1625 }
1626
1627
1628 #ifndef max
1629 #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
1630 #endif
1631
1632 // Not used:
1633 int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2)
1634 {
1635
1636   struct s_mc_diff *state = mc_diff_info;
1637
1638   if (heap1 == NULL && heap1 == NULL) {
1639     XBT_DEBUG("Malloc descriptors null");
1640     return 0;
1641   }
1642
1643   if (heap1->heaplimit != heap2->heaplimit) {
1644     XBT_DEBUG("Different limit of valid info table indices");
1645     return 1;
1646   }
1647
1648   /* Heap information */
1649   state->heaplimit = ((struct mdesc *) heap1)->heaplimit;
1650
1651
1652   // Mamailloute in order to find the base address of the main heap:
1653   state->s_heap =
1654       (char *) mmalloc_get_current_heap() - STD_HEAP_SIZE - xbt_pagesize;
1655
1656   state->heapbase1 = (char *) heap1 + BLOCKSIZE;
1657   state->heapbase2 = (char *) heap2 + BLOCKSIZE;
1658
1659   state->heapinfo1 =
1660       (malloc_info *) ((char *) heap1 +
1661                        ((uintptr_t)
1662                         ((char *) heap1->heapinfo - (char *) state->s_heap)));
1663   state->heapinfo2 =
1664       (malloc_info *) ((char *) heap2 +
1665                        ((uintptr_t)
1666                         ((char *) heap2->heapinfo - (char *) state->s_heap)));
1667
1668   state->heapsize1 = heap1->heapsize;
1669   state->heapsize2 = heap2->heapsize;
1670
1671   /* Start comparison */
1672   size_t i, j, k;
1673   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
1674
1675   int distance = 0;
1676
1677   /* Check busy blocks */
1678
1679   i = 1;
1680
1681   while (i <= state->heaplimit) {
1682
1683     addr_block1 =
1684         ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
1685                    (char *) state->heapbase1));
1686     addr_block2 =
1687         ((void *) (((ADDR2UINT(i)) - 1) * BLOCKSIZE +
1688                    (char *) state->heapbase2));
1689
1690     if (state->heapinfo1[i].type != state->heapinfo2[i].type) {
1691
1692       distance += BLOCKSIZE;
1693       XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i,
1694                 state->heapinfo1[i].type, state->heapinfo2[i].type, distance);
1695       i++;
1696
1697     } else {
1698
1699       if (state->heapinfo1[i].type == -1) {     /* Free block */
1700         i++;
1701         continue;
1702       }
1703
1704       if (state->heapinfo1[i].type == 0) {      /* Large block */
1705
1706         if (state->heapinfo1[i].busy_block.size !=
1707             state->heapinfo2[i].busy_block.size) {
1708           distance +=
1709               BLOCKSIZE * max(state->heapinfo1[i].busy_block.size,
1710                               state->heapinfo2[i].busy_block.size);
1711           i += max(state->heapinfo1[i].busy_block.size,
1712                    state->heapinfo2[i].busy_block.size);
1713           XBT_DEBUG
1714               ("Different larger of cluster at block %zu : %zu - %zu -> distance = %d",
1715                i, state->heapinfo1[i].busy_block.size,
1716                state->heapinfo2[i].busy_block.size, distance);
1717           continue;
1718         }
1719
1720         /*if(heapinfo1[i].busy_block.busy_size != heapinfo2[i].busy_block.busy_size){
1721            distance += max(heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size);
1722            i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
1723            XBT_DEBUG("Different size used oin large cluster at block %zu : %zu - %zu -> distance = %d", i, heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size, distance);
1724            continue;
1725            } */
1726
1727         k = 0;
1728
1729         //while(k < (heapinfo1[i].busy_block.busy_size)){
1730         while (k < state->heapinfo1[i].busy_block.size * BLOCKSIZE) {
1731           if (memcmp((char *) addr_block1 + k, (char *) addr_block2 + k, 1) !=
1732               0) {
1733             distance++;
1734           }
1735           k++;
1736         }
1737
1738         i++;
1739
1740       } else {                  /* Fragmented block */
1741
1742         for (j = 0; j < (size_t) (BLOCKSIZE >> state->heapinfo1[i].type); j++) {
1743
1744           addr_frag1 =
1745               (void *) ((char *) addr_block1 + (j << state->heapinfo1[i].type));
1746           addr_frag2 =
1747               (void *) ((char *) addr_block2 + (j << state->heapinfo2[i].type));
1748
1749           if (state->heapinfo1[i].busy_frag.frag_size[j] == 0
1750               && state->heapinfo2[i].busy_frag.frag_size[j] == 0) {
1751             continue;
1752           }
1753
1754
1755           /*if(heapinfo1[i].busy_frag.frag_size[j] != heapinfo2[i].busy_frag.frag_size[j]){
1756              distance += max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j]);
1757              XBT_DEBUG("Different size used in fragment %zu in block %zu : %d - %d -> distance = %d", j, i, heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j], distance); 
1758              continue;
1759              } */
1760
1761           k = 0;
1762
1763           //while(k < max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j])){
1764           while (k < (BLOCKSIZE / (BLOCKSIZE >> state->heapinfo1[i].type))) {
1765             if (memcmp((char *) addr_frag1 + k, (char *) addr_frag2 + k, 1) !=
1766                 0) {
1767               distance++;
1768             }
1769             k++;
1770           }
1771
1772         }
1773
1774         i++;
1775
1776       }
1777
1778     }
1779
1780   }
1781
1782   return distance;
1783
1784 }