Logo AND Algorithmique Numérique Distribuée

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