Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
model-checker : fix memory leaks in heap comparison
[simgrid.git] / src / xbt / mmalloc / mm_diff.c
1 /* mm_diff - Memory snapshooting and comparison                             */
2
3 /* Copyright (c) 2008-2012. The SimGrid Team. All rights reserved.          */
4
5 /* This program is free software; you can redistribute it and/or modify it
6  * under the terms of the license (GNU LGPL) which comes with this package. */
7
8 #include "xbt/ex_interface.h" /* internals of backtrace setup */
9 #include "xbt/str.h"
10 #include "mc/mc.h"
11 #include "xbt/mmalloc.h"
12
13 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mm_diff, xbt,
14                                 "Logging specific to mm_diff in mmalloc");
15
16 extern char *xbt_binary_name;
17
18 xbt_dynar_t mc_comparison_ignore;
19 xbt_dynar_t stacks_areas;
20
21 static void heap_area_pair_free(heap_area_pair_t pair);
22 static void heap_area_pair_free_voidp(void *d);
23 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2);
24 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2);
25 static heap_area_t new_heap_area(int block, int fragment);
26
27 static int compare_area(void *area1, void* area2, size_t size, xbt_dynar_t previous, int check_ignore);
28 static void match_equals(xbt_dynar_t list, xbt_dynar_t *equals);
29
30 static int in_mc_comparison_ignore(int block, int fragment);
31 static size_t heap_comparison_ignore(void *address);
32 static void add_heap_equality(xbt_dynar_t *equals, void *a1, void *a2);
33 static void remove_heap_equality(xbt_dynar_t *equals, int address, void *a);
34
35 static char* is_stack(void *address);
36
37 void mmalloc_backtrace_block_display(void* heapinfo, int block){
38
39   xbt_ex_t e;
40
41   if (((malloc_info *)heapinfo)[block].busy_block.bt_size == 0) {
42     fprintf(stderr, "No backtrace available for that block, sorry.\n");
43     return;
44   }
45
46   memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_block.bt),sizeof(void*)*XBT_BACKTRACE_SIZE);
47   e.used = ((malloc_info *)heapinfo)[block].busy_block.bt_size;
48
49   xbt_ex_setup_backtrace(&e);
50   if (e.used == 0) {
51     fprintf(stderr, "(backtrace not set)\n");
52   } else if (e.bt_strings == NULL) {
53     fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet");
54   } else {
55     int i;
56
57     fprintf(stderr, "Backtrace of where the block %d was malloced (%d frames):\n", block ,e.used);
58     for (i = 0; i < e.used; i++)       /* no need to display "xbt_backtrace_display" */{
59       fprintf(stderr, "%d ---> %s\n",i, e.bt_strings[i] + 4);
60     }
61   }
62
63 }
64
65 void mmalloc_backtrace_fragment_display(void* heapinfo, int block, int frag){
66
67   xbt_ex_t e;
68
69   memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_frag.bt[frag]),sizeof(void*)*XBT_BACKTRACE_SIZE);
70   e.used = XBT_BACKTRACE_SIZE;
71
72   xbt_ex_setup_backtrace(&e);
73   if (e.used == 0) {
74     fprintf(stderr, "(backtrace not set)\n");
75   } else if (e.bt_strings == NULL) {
76     fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet");
77   } else {
78     int i;
79
80     fprintf(stderr, "Backtrace of where the fragment %d in block %d was malloced (%d frames):\n", frag, block ,e.used);
81     for (i = 0; i < e.used; i++)       /* no need to display "xbt_backtrace_display" */{
82       fprintf(stderr, "%d ---> %s\n",i, e.bt_strings[i] + 4);
83     }
84   }
85
86 }
87
88 void mmalloc_backtrace_display(void *addr){
89
90   size_t block, frag_nb;
91   int type;
92   
93   xbt_mheap_t heap = __mmalloc_current_heap ?: (xbt_mheap_t) mmalloc_preinit();
94
95   block = (((char*) (addr) - (char*) heap -> heapbase) / BLOCKSIZE + 1);
96
97   type = heap->heapinfo[block].type;
98
99   switch(type){
100   case -1 : /* Free block */
101     fprintf(stderr, "Asked to display the backtrace of a block that is free. I'm puzzled\n");
102     xbt_abort();
103     break; 
104   case 0: /* Large block */
105     mmalloc_backtrace_block_display(heap->heapinfo, block);
106     break;
107   default: /* Fragmented block */
108     frag_nb = RESIDUAL(addr, BLOCKSIZE) >> type;
109     if(heap->heapinfo[block].busy_frag.frag_size[frag_nb] == -1){
110       fprintf(stderr , "Asked to display the backtrace of a fragment that is free. I'm puzzled\n");
111       xbt_abort();
112     }
113     mmalloc_backtrace_fragment_display(heap->heapinfo, block, frag_nb);
114     break;
115   }
116
117 }
118
119
120 void *s_heap, *heapbase1, *heapbase2;
121 malloc_info *heapinfo1, *heapinfo2;
122 size_t heaplimit, heapsize1, heapsize2;
123
124 int ignore_done;
125
126 int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t *stack1, xbt_dynar_t *stack2, xbt_dynar_t *equals){
127
128   if(heap1 == NULL && heap1 == NULL){
129     XBT_DEBUG("Malloc descriptors null");
130     return 0;
131   }
132
133   if(heap1->heaplimit != heap2->heaplimit){
134     XBT_DEBUG("Different limit of valid info table indices");
135     return 1;
136   }
137
138   /* Heap information */
139   heaplimit = ((struct mdesc *)heap1)->heaplimit;
140
141   s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
142
143   heapbase1 = (char *)heap1 + BLOCKSIZE;
144   heapbase2 = (char *)heap2 + BLOCKSIZE;
145
146   heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap)));
147   heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap)));
148
149   heapsize1 = heap1->heapsize;
150   heapsize2 = heap2->heapsize;
151
152   /* Start comparison */
153   size_t i1, i2, j1, j2, k, current_block, current_fragment;
154   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
155   void *real_addr_block1, *real_addr_block2;
156   char *stack_name;
157   int nb_block1=0, nb_frag1=0, nb_block2=0, nb_frag2=0;
158
159   xbt_dynar_t previous = xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
160
161   int equal, res_compare;
162
163   ignore_done = 0;
164
165   /* Init equal information */
166   i1 = 1;
167
168   while(i1<=heaplimit){
169     if(heapinfo1[i1].type == 0){
170       if(heapinfo1[i1].busy_block.busy_size > 0)
171         nb_block1++;
172       heapinfo1[i1].busy_block.equal_to = NULL;
173     }
174     if(heapinfo1[i1].type > 0){
175       for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){
176         if(heapinfo1[i1].busy_frag.frag_size[j1] > 0)
177           nb_frag1++;
178         heapinfo1[i1].busy_frag.equal_to[j1] = NULL;
179       }
180     }
181     i1++; 
182   }
183
184   i2 = 1;
185
186   while(i2<=heaplimit){
187     if(heapinfo2[i2].type == 0){
188       if(heapinfo2[i2].busy_block.busy_size > 0)
189         nb_block2++;
190       heapinfo2[i2].busy_block.equal_to = NULL;
191     }
192     if(heapinfo2[i2].type > 0){
193       for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){
194         if(heapinfo2[i2].busy_frag.frag_size[j2] > 0)
195           nb_frag2++;
196         heapinfo2[i2].busy_frag.equal_to[j2] = NULL;
197       }
198     }
199     i2++; 
200   }
201
202   if(nb_block1 != nb_block2 || nb_frag1 != nb_frag2){
203     XBT_DEBUG("Different number of busy blocks (%d - %d) or busy fragments (%d - %d)", nb_block1, nb_block2, nb_frag1, nb_frag2);
204     return 1;
205   }
206
207   /* Check busy blocks*/
208
209   i1 = 1;
210
211   while(i1 <= heaplimit){
212
213     current_block = i1;
214
215     if(heapinfo1[i1].type == -1){ /* Free block */
216       i1++;
217       continue;
218     }
219
220     addr_block1 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)heapbase1));
221     real_addr_block1 = (char*)((xbt_mheap_t)s_heap)->heapbase + (((char *)addr_block1) - (char *)heapbase1);
222
223     if(heapinfo1[i1].type == 0){  /* Large block */
224       
225       if((stack_name = is_stack(real_addr_block1)) != NULL){
226         stack_region_t stack = xbt_new0(s_stack_region_t, 1);
227         stack->address = addr_block1;
228         stack->process_name = strdup(stack_name);
229         stack->size = heapinfo1[i1].busy_block.busy_size;
230         xbt_dynar_push(*stack1, &stack);
231       }
232
233       if(heapinfo1[i1].busy_block.busy_size == 0){
234         i1++;
235         continue;
236       }
237
238       if(heapinfo1[i1].busy_block.equal_to != NULL){
239         i1++;
240         continue;
241       }
242     
243       i2 = 1;
244       equal = 0;
245   
246       /* Try first to associate to same block in the other heap */
247       if(heapinfo2[current_block].type == heapinfo1[current_block].type){
248
249         if(heapinfo2[current_block].busy_block.equal_to == NULL){  
250         
251           if(heapinfo1[current_block].busy_block.busy_size == heapinfo2[current_block].busy_block.busy_size){
252
253             addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)heapbase2));
254             real_addr_block2 = (char*)((xbt_mheap_t)s_heap)->heapbase + (((char *)addr_block2) - (char *)heapbase2);
255           
256             if((stack_name = is_stack(real_addr_block2)) != NULL){
257               stack_region_t stack = xbt_new0(s_stack_region_t, 1);
258               stack->address = addr_block2;
259               stack->process_name = strdup(stack_name);
260               stack->size = heapinfo2[current_block].busy_block.busy_size;
261               xbt_dynar_push(*stack2, &stack);
262             }
263         
264             add_heap_area_pair(previous, current_block, -1, current_block, -1);
265         
266             if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
267               if(in_mc_comparison_ignore((int)current_block, -1))
268                 res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 1);
269               else
270                 res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 0);
271             }else{
272               res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 0);
273             }
274         
275             if(res_compare == 0){
276               for(k=1; k < heapinfo2[current_block].busy_block.size; k++)
277                 heapinfo2[current_block+k].busy_block.equal_to = new_heap_area(i1, -1);
278               for(k=1; k < heapinfo1[current_block].busy_block.size; k++)
279                 heapinfo1[current_block+k].busy_block.equal_to = new_heap_area(i1, -1);
280               equal = 1;
281               match_equals(previous, equals);
282               i1 = i1 + heapinfo1[current_block].busy_block.size;
283             }
284         
285             xbt_dynar_reset(previous);
286         
287           }
288
289         }
290         
291       }
292
293       while(i2 <= heaplimit && !equal){
294
295         addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)heapbase2));        
296         real_addr_block2 = (char*)((xbt_mheap_t)s_heap)->heapbase + (((char *)addr_block2) - (char *)heapbase2);
297         
298         if((stack_name = is_stack(real_addr_block2)) != NULL){
299           stack_region_t stack = xbt_new0(s_stack_region_t, 1);
300           stack->address = addr_block2;
301           stack->process_name = strdup(stack_name);
302           stack->size = heapinfo2[i2].busy_block.busy_size;
303           xbt_dynar_push(*stack2, &stack);
304         }
305            
306         if(i2 == current_block){
307           i2++;
308           continue;
309         }
310
311         if(heapinfo2[i2].type != 0){
312           i2++;
313           continue;
314         }
315
316         if(heapinfo2[i2].busy_block.equal_to != NULL){         
317           i2++;
318           continue;
319         }
320         
321         if(heapinfo1[i1].busy_block.size != heapinfo2[i2].busy_block.size){
322           i2++;
323           continue;
324         }
325         
326         if(heapinfo1[i1].busy_block.busy_size != heapinfo2[i2].busy_block.busy_size){
327           i2++;
328           continue;
329         }
330
331         /* Comparison */
332         add_heap_area_pair(previous, i1, -1, i2, -1);
333         
334         if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
335           if(in_mc_comparison_ignore((int)i1, -1))
336             res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 1);
337           else
338             res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 0);
339         }else{
340           res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 0);
341         }
342         
343         if(res_compare == 0){
344           for(k=1; k < heapinfo2[i2].busy_block.size; k++)
345             heapinfo2[i2+k].busy_block.equal_to = new_heap_area(i1, -1);
346           for(k=1; k < heapinfo1[i1].busy_block.size; k++)
347             heapinfo1[i1+k].busy_block.equal_to = new_heap_area(i2, -1);
348           equal = 1;
349           match_equals(previous, equals);
350           i1 = i1 + heapinfo1[i1].busy_block.size;
351         }
352
353         xbt_dynar_reset(previous);
354
355         i2++;
356
357       }
358
359       if(!equal)
360         i1++;
361       
362     }else{ /* Fragmented block */
363
364       for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){
365
366         current_fragment = j1;
367
368         if(heapinfo1[i1].busy_frag.frag_size[j1] == -1) /* Free fragment */
369           continue;
370
371         if(heapinfo1[i1].busy_frag.equal_to[j1] != NULL)
372           continue;
373
374         addr_frag1 = (void*) ((char *)addr_block1 + (j1 << heapinfo1[i1].type));
375
376         i2 = 1;
377         equal = 0;
378         
379         /* Try first to associate to same fragment in the other heap */
380         if(heapinfo2[current_block].type == heapinfo1[current_block].type){
381
382           if(heapinfo2[current_block].busy_frag.equal_to[current_fragment] == NULL){  
383           
384               if(heapinfo1[current_block].busy_frag.frag_size[current_fragment] == heapinfo2[current_block].busy_frag.frag_size[current_fragment]){
385
386                 addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)heapbase2));
387                 addr_frag2 = (void*) ((char *)addr_block2 + (current_fragment << heapinfo2[current_block].type));
388                
389                 add_heap_area_pair(previous, current_block, current_fragment, current_block, current_fragment);
390             
391                 if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
392                   if(in_mc_comparison_ignore((int)current_block, (int)current_fragment))
393                     res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 1);
394                   else
395                     res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 0);
396                 }else{
397                   res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 0);
398                 }
399
400                 if(res_compare == 0){
401                   equal = 1;
402                   match_equals(previous, equals);
403                 }
404             
405                 xbt_dynar_reset(previous);
406             
407               }
408
409             }
410
411         }
412
413         while(i2 <= heaplimit && !equal){
414
415           
416           if(heapinfo2[i2].type <= 0){
417             i2++;
418             continue;
419           }
420
421           for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){
422
423             if(heapinfo2[i2].type == heapinfo1[i1].type && i2 == current_block && j2 == current_fragment)
424               continue;
425
426             if(heapinfo2[i2].busy_frag.equal_to[j2] != NULL)                
427               continue;              
428              
429             if(heapinfo1[i1].busy_frag.frag_size[j1] != heapinfo2[i2].busy_frag.frag_size[j2]) /* Different size_used */    
430               continue;
431              
432             addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)heapbase2));
433             addr_frag2 = (void*) ((char *)addr_block2 + (j2 << heapinfo2[i2].type));
434              
435             /* Comparison */
436             add_heap_area_pair(previous, i1, j1, i2, j2);
437             
438             if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
439               if(in_mc_comparison_ignore((int)i1, (int)j1))
440                 res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 1);
441               else
442                 res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 0);
443             }else{
444               res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 0);
445             }
446
447             if(res_compare == 0){
448               equal = 1;
449               match_equals(previous, equals);
450               break;
451             }
452
453             xbt_dynar_reset(previous);
454
455           }
456
457           i2++;
458
459         }
460
461       }
462
463       i1++;
464       
465     }
466
467   }
468
469   /* All blocks/fragments are equal to another block/fragment ? */
470   size_t i = 1, j = 0;
471   int nb_diff1 = 0, nb_diff2 = 0;
472  
473   while(i<heaplimit){
474     if(heapinfo1[i].type == 0){
475       if(heapinfo1[i].busy_block.busy_size > 0){
476         if(heapinfo1[i].busy_block.equal_to == NULL){
477           if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
478             addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
479             XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block1, heapinfo1[i].busy_block.busy_size);
480             mmalloc_backtrace_block_display((void*)heapinfo1, i);
481           }
482           nb_diff1++;
483         }else{
484           xbt_free(heapinfo1[i].busy_block.equal_to);
485         }
486       }
487     }
488     if(heapinfo1[i].type > 0){
489       addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
490       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
491         if(heapinfo1[i].busy_frag.frag_size[j] > 0){
492           if(heapinfo1[i].busy_frag.equal_to[j] == NULL){
493             if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
494               addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type));
495               XBT_DEBUG("Block %zu, Fragment %zu (%p) not found (size used = %d)", i, j, addr_frag1, heapinfo1[i].busy_frag.frag_size[j]);
496               mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j);
497             }
498             nb_diff1++;
499           }else{
500             xbt_free(heapinfo1[i].busy_frag.equal_to[j]);
501           }
502         }
503       }
504     }
505     
506     i++; 
507   }
508
509   XBT_DEBUG("Different blocks or fragments in heap1 : %d", nb_diff1);
510
511   i = 1;
512
513   while(i<heaplimit){
514     if(heapinfo2[i].type == 0){
515       if(heapinfo2[i].busy_block.busy_size > 0){
516         if(heapinfo2[i].busy_block.equal_to == NULL){
517           if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
518             addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
519             XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block2, heapinfo2[i].busy_block.busy_size);
520             mmalloc_backtrace_block_display((void*)heapinfo2, i);
521           }
522           nb_diff2++;
523         }else{
524           xbt_free(heapinfo2[i].busy_block.equal_to);
525         }
526       }
527     }
528     if(heapinfo2[i].type > 0){
529       addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
530       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo2[i].type); j++){
531         if(heapinfo2[i].busy_frag.frag_size[j] > 0){
532           if(heapinfo2[i].busy_frag.equal_to[j] == NULL){
533             if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
534               addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type));
535               XBT_DEBUG( "Block %zu, Fragment %zu (%p) not found (size used = %d)", i, j, addr_frag2, heapinfo2[i].busy_frag.frag_size[j]);
536               mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j);
537             }
538             nb_diff2++;
539           }else{
540             xbt_free(heapinfo2[i].busy_frag.equal_to[j]);
541           }
542         }
543       }
544     }
545     i++; 
546   }
547
548   XBT_DEBUG("Different blocks or fragments in heap2 : %d", nb_diff2);
549
550   xbt_dynar_free(&previous);
551
552   return ((nb_diff1 > 0) || (nb_diff2 > 0));
553
554 }
555
556 static heap_area_t new_heap_area(int block, int fragment){
557   heap_area_t area = NULL;
558   area = xbt_new0(s_heap_area_t, 1);
559   area->block = block;
560   area->fragment = fragment;
561   return area;
562 }
563
564 static int in_mc_comparison_ignore(int block, int fragment){
565
566   unsigned int cursor = 0;
567   int start = 0;
568   int end = xbt_dynar_length(mc_comparison_ignore) - 1;
569   mc_ignore_region_t region;
570
571   while(start <= end){
572     cursor = (start + end) / 2;
573     region = (mc_ignore_region_t)xbt_dynar_get_as(mc_comparison_ignore, cursor, mc_ignore_region_t);
574     if(region->block == block){
575       if(region->fragment == fragment)
576         return 1;
577       if(region->fragment < fragment)
578         start = cursor + 1;
579       if(region->fragment > fragment)
580         end = cursor - 1;
581     }
582     if(region->block < block)
583       start = cursor + 1;
584     if(region->block > block)
585       end = cursor - 1; 
586   }
587
588   return 0;
589 }
590
591 static size_t heap_comparison_ignore(void *address){
592   unsigned int cursor = 0;
593   int start = 0;
594   int end = xbt_dynar_length(mc_comparison_ignore) - 1;
595   mc_ignore_region_t region;
596
597   while(start <= end){
598     cursor = (start + end) / 2;
599     region = (mc_ignore_region_t)xbt_dynar_get_as(mc_comparison_ignore, cursor, mc_ignore_region_t);
600     if(region->address == address)
601       return region->size;
602     if(region->address < address)
603       start = cursor + 1;
604     if(region->address > address)
605       end = cursor - 1;   
606   }
607
608   return 0;
609 }
610
611
612 static int compare_area(void *area1, void* area2, size_t size, xbt_dynar_t previous, int check_ignore){
613
614   size_t i = 0, pointer_align = 0, ignore1 = 0, ignore2 = 0;
615   void *address_pointed1, *address_pointed2, *addr_block_pointed1, *addr_block_pointed2, *addr_frag_pointed1, *addr_frag_pointed2;
616   size_t block_pointed1, block_pointed2, frag_pointed1, frag_pointed2;
617   int res_compare;
618   void *current_area1, *current_area2;
619  
620   while(i<size){
621
622     if(check_ignore){
623
624       current_area1 = (char*)((xbt_mheap_t)s_heap)->heapbase + ((((char *)area1) + i) - (char *)heapbase1);
625       if((ignore1 = heap_comparison_ignore(current_area1)) > 0){
626         current_area2 = (char*)((xbt_mheap_t)s_heap)->heapbase + ((((char *)area2) + i) - (char *)heapbase2);
627         if((ignore2 = heap_comparison_ignore(current_area2))  == ignore1){
628           i = i + ignore2;
629           ignore_done++;
630           continue;
631         }
632       }
633
634     }
635    
636     if(memcmp(((char *)area1) + i, ((char *)area2) + i, 1) != 0){
637
638       /* Check pointer difference */
639       pointer_align = (i / sizeof(void*)) * sizeof(void*);
640       address_pointed1 = *((void **)((char *)area1 + pointer_align));
641       address_pointed2 = *((void **)((char *)area2 + pointer_align));
642
643       /* Get pointed blocks number */ 
644       block_pointed1 = ((char*)address_pointed1 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
645       block_pointed2 = ((char*)address_pointed2 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
646
647       /* Check if valid blocks number */
648       if((char *)address_pointed1 < (char*)((xbt_mheap_t)s_heap)->heapbase || block_pointed1 > heapsize1 || block_pointed1 < 1 || (char *)address_pointed2 < (char*)((xbt_mheap_t)s_heap)->heapbase || block_pointed2 > heapsize2 || block_pointed2 < 1)
649         return 1;
650
651       if(heapinfo1[block_pointed1].type == heapinfo2[block_pointed2].type){ /* Same type of block (large or fragmented) */
652
653         addr_block_pointed1 = ((void*) (((ADDR2UINT(block_pointed1)) - 1) * BLOCKSIZE + (char*)heapbase1));
654         addr_block_pointed2 = ((void*) (((ADDR2UINT(block_pointed2)) - 1) * BLOCKSIZE + (char*)heapbase2));
655         
656         if(heapinfo1[block_pointed1].type == 0){ /* Large block */
657
658           if(heapinfo1[block_pointed1].busy_block.size != heapinfo2[block_pointed2].busy_block.size){
659             return 1;
660           }
661
662           if(heapinfo1[block_pointed1].busy_block.busy_size != heapinfo2[block_pointed2].busy_block.busy_size){
663             return 1;
664           }
665
666           if(add_heap_area_pair(previous, block_pointed1, -1, block_pointed2, -1)){
667
668             if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
669               if(in_mc_comparison_ignore(block_pointed1, -1))
670                 res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 1);
671               else
672                 res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 0);
673             }else{
674               res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 0);
675             }
676             
677             if(res_compare == 1)    
678               return 1;
679            
680           }
681           
682         }else{ /* Fragmented block */
683
684           /* Get pointed fragments number */ 
685           frag_pointed1 = ((uintptr_t) (ADDR2UINT (address_pointed1) % (BLOCKSIZE))) >> heapinfo1[block_pointed1].type;
686           frag_pointed2 = ((uintptr_t) (ADDR2UINT (address_pointed2) % (BLOCKSIZE))) >> heapinfo2[block_pointed2].type;
687          
688           if(heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1] != heapinfo2[block_pointed2].busy_frag.frag_size[frag_pointed2]) /* Different size_used */    
689             return 1;
690             
691           addr_frag_pointed1 = (void*) ((char *)addr_block_pointed1 + (frag_pointed1 << heapinfo1[block_pointed1].type));
692           addr_frag_pointed2 = (void*) ((char *)addr_block_pointed2 + (frag_pointed2 << heapinfo2[block_pointed2].type));
693
694           if(add_heap_area_pair(previous, block_pointed1, frag_pointed1, block_pointed2, frag_pointed2)){
695
696             if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
697               if(in_mc_comparison_ignore(block_pointed1, frag_pointed1))
698                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 1);
699               else
700                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
701             }else{
702               res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
703             }
704
705             if(res_compare == 1)
706               return 1;
707            
708           }
709           
710         }
711           
712       }else{
713
714         if((heapinfo1[block_pointed1].type > 0) && (heapinfo2[block_pointed2].type > 0)){
715           
716           addr_block_pointed1 = ((void*) (((ADDR2UINT(block_pointed1)) - 1) * BLOCKSIZE + (char*)heapbase1));
717           addr_block_pointed2 = ((void*) (((ADDR2UINT(block_pointed2)) - 1) * BLOCKSIZE + (char*)heapbase2));
718        
719           frag_pointed1 = ((uintptr_t) (ADDR2UINT (address_pointed1) % (BLOCKSIZE))) >> heapinfo1[block_pointed1].type;
720           frag_pointed2 = ((uintptr_t) (ADDR2UINT (address_pointed2) % (BLOCKSIZE))) >> heapinfo2[block_pointed2].type;
721
722           if(heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1] != heapinfo2[block_pointed2].busy_frag.frag_size[frag_pointed2]) /* Different size_used */  
723             return 1;
724
725           addr_frag_pointed1 = (void*) ((char *)addr_block_pointed1 + (frag_pointed1 << heapinfo1[block_pointed1].type));
726           addr_frag_pointed2 = (void*) ((char *)addr_block_pointed2 + (frag_pointed2 << heapinfo2[block_pointed2].type));
727
728           if(add_heap_area_pair(previous, block_pointed1, frag_pointed1, block_pointed2, frag_pointed2)){
729
730             if(ignore_done < xbt_dynar_length(mc_comparison_ignore)){
731               if(in_mc_comparison_ignore(block_pointed1, frag_pointed1))
732                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 1);
733               else
734                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
735             }else{
736               res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
737             }
738             
739             if(res_compare == 1)
740               return 1;
741            
742           }
743
744         }else{
745           return 1;
746         }
747
748       }
749
750       i = pointer_align + sizeof(void *);
751       
752     }else{
753
754       i++;
755
756     }
757   }
758
759   return 0;
760   
761
762 }
763
764 static void heap_area_pair_free(heap_area_pair_t pair){
765   if (pair){
766     free(pair);
767     pair = NULL;
768   }
769 }
770
771 static void heap_area_pair_free_voidp(void *d)
772 {
773   heap_area_pair_free((heap_area_pair_t) * (void **) d);
774 }
775
776 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){
777
778   if(is_new_heap_area_pair(list, block1, fragment1, block2, fragment2)){
779     heap_area_pair_t pair = NULL;
780     pair = xbt_new0(s_heap_area_pair_t, 1);
781     pair->block1 = block1;
782     pair->fragment1 = fragment1;
783     pair->block2 = block2;
784     pair->fragment2 = fragment2;
785     
786     xbt_dynar_push(list, &pair); 
787
788     return 1;
789   }
790
791   return 0;
792 }
793  
794 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){
795   
796   unsigned int cursor = 0;
797   heap_area_pair_t current_pair;
798
799   xbt_dynar_foreach(list, cursor, current_pair){
800     if(current_pair->block1 == block1 && current_pair->block2 == block2 && current_pair->fragment1 == fragment1 && current_pair->fragment2 == fragment2)
801       return 0; 
802   }
803   
804   return 1;
805 }
806
807 static void match_equals(xbt_dynar_t list, xbt_dynar_t *equals){
808
809   unsigned int cursor = 0;
810   heap_area_pair_t current_pair;
811   heap_area_t previous_area;
812
813   void *real_addr_block1, *real_addr_block2, *real_addr_frag1, *real_addr_frag2;
814
815   xbt_dynar_foreach(list, cursor, current_pair){
816
817     if(current_pair->fragment1 != -1){
818
819       real_addr_block1 = ((void*) (((ADDR2UINT((size_t)current_pair->block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
820       real_addr_frag1 = (void*) ((char *)real_addr_block1 + (current_pair->fragment1 << heapinfo1[current_pair->block1].type));
821       real_addr_block2 = ((void*) (((ADDR2UINT((size_t)current_pair->block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
822       real_addr_frag2 = (void*) ((char *)real_addr_block2 + (current_pair->fragment2 << heapinfo2[current_pair->block2].type));
823
824       if(heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1] != NULL){    
825         remove_heap_equality(equals, 1, real_addr_frag1);
826         previous_area = heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1];
827         xbt_free( heapinfo2[previous_area->block].busy_frag.equal_to[previous_area->fragment]);
828         heapinfo2[previous_area->block].busy_frag.equal_to[previous_area->fragment] = NULL;
829         xbt_free(heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1]); 
830       }
831       if(heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2] != NULL){        
832         remove_heap_equality(equals, 2, real_addr_frag2); 
833         previous_area = heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2];
834         xbt_free(heapinfo1[previous_area->block].busy_frag.equal_to[previous_area->fragment]);
835         heapinfo1[previous_area->block].busy_frag.equal_to[previous_area->fragment] = NULL;
836         xbt_free(heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2]);
837       }
838       
839       if(real_addr_frag1 != real_addr_frag2)
840         add_heap_equality(equals, real_addr_frag1, real_addr_frag2);
841
842       heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1] = new_heap_area(current_pair->block2, current_pair->fragment2);
843       heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2] = new_heap_area(current_pair->block1, current_pair->fragment1);
844
845     }else{
846
847       real_addr_block1 = ((void*) (((ADDR2UINT((size_t)current_pair->block1)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
848       real_addr_block2 = ((void*) (((ADDR2UINT((size_t)current_pair->block2)) - 1) * BLOCKSIZE + (char*)((xbt_mheap_t)s_heap)->heapbase));
849
850       if(heapinfo1[current_pair->block1].busy_block.equal_to != NULL){
851         remove_heap_equality(equals, 1, real_addr_block1);
852         previous_area = heapinfo1[current_pair->block1].busy_block.equal_to;
853         xbt_free(heapinfo2[previous_area->block].busy_block.equal_to);
854         heapinfo2[previous_area->block].busy_block.equal_to = NULL; 
855         xbt_free(heapinfo1[current_pair->block1].busy_block.equal_to);
856       }
857       if(heapinfo2[current_pair->block2].busy_block.equal_to != NULL){
858         remove_heap_equality(equals, 2, real_addr_block2);
859         previous_area = heapinfo2[current_pair->block2].busy_block.equal_to;
860         xbt_free(heapinfo1[previous_area->block].busy_block.equal_to);
861         heapinfo1[previous_area->block].busy_block.equal_to = NULL;
862         xbt_free(heapinfo2[current_pair->block2].busy_block.equal_to);
863       }
864       
865       if(real_addr_block1 != real_addr_block2)
866         add_heap_equality(equals, real_addr_block1, real_addr_block2);
867
868       heapinfo1[current_pair->block1].busy_block.equal_to = new_heap_area(current_pair->block2, current_pair->fragment2);
869       heapinfo2[current_pair->block2].busy_block.equal_to = new_heap_area(current_pair->block1, current_pair->fragment1);
870
871     }
872   }
873
874
875 }
876
877 #ifndef max
878 #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
879 #endif
880
881 int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){
882
883   if(heap1 == NULL && heap1 == NULL){
884     XBT_DEBUG("Malloc descriptors null");
885     return 0;
886   }
887
888   if(heap1->heaplimit != heap2->heaplimit){
889     XBT_DEBUG("Different limit of valid info table indices");
890     return 1;
891   }
892
893   /* Heap information */
894   heaplimit = ((struct mdesc *)heap1)->heaplimit;
895
896   s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
897
898   heapbase1 = (char *)heap1 + BLOCKSIZE;
899   heapbase2 = (char *)heap2 + BLOCKSIZE;
900
901   heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap)));
902   heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap)));
903
904   heapsize1 = heap1->heapsize;
905   heapsize2 = heap2->heapsize;
906
907   /* Start comparison */
908   size_t i, j, k;
909   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
910
911   int distance = 0;
912
913   /* Check busy blocks*/
914
915   i = 1;
916
917   while(i <= heaplimit){
918
919     addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
920     addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
921
922     if(heapinfo1[i].type != heapinfo2[i].type){
923   
924       distance += BLOCKSIZE;
925       XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i, heapinfo1[i].type, heapinfo2[i].type, distance);
926       i++;
927     
928     }else{
929
930       if(heapinfo1[i].type == -1){ /* Free block */
931         i++;
932         continue;
933       }
934
935       if(heapinfo1[i].type == 0){ /* Large block */
936        
937         if(heapinfo1[i].busy_block.size != heapinfo2[i].busy_block.size){
938           distance += BLOCKSIZE * max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
939           i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
940           XBT_DEBUG("Different larger of cluster at block %zu : %zu - %zu -> distance = %d", i, heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size, distance);
941           continue;
942         }
943
944         /*if(heapinfo1[i].busy_block.busy_size != heapinfo2[i].busy_block.busy_size){
945           distance += max(heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size);
946           i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
947           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);
948           continue;
949           }*/
950
951         k = 0;
952
953         //while(k < (heapinfo1[i].busy_block.busy_size)){
954         while(k < heapinfo1[i].busy_block.size * BLOCKSIZE){
955           if(memcmp((char *)addr_block1 + k, (char *)addr_block2 + k, 1) != 0){
956             distance ++;
957           }
958           k++;
959         } 
960
961         i++;
962
963       }else { /* Fragmented block */
964
965         for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
966
967           addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type));
968           addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type));
969
970           if(heapinfo1[i].busy_frag.frag_size[j] == 0 && heapinfo2[i].busy_frag.frag_size[j] == 0){
971             continue;
972           }
973           
974           
975           /*if(heapinfo1[i].busy_frag.frag_size[j] != heapinfo2[i].busy_frag.frag_size[j]){
976             distance += max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j]);
977             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); 
978             continue;
979             }*/
980    
981           k=0;
982
983           //while(k < max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j])){
984           while(k < (BLOCKSIZE / (BLOCKSIZE >> heapinfo1[i].type))){
985             if(memcmp((char *)addr_frag1 + k, (char *)addr_frag2 + k, 1) != 0){
986               distance ++;
987             }
988             k++;
989           }
990
991         }
992
993         i++;
994
995       }
996       
997     }
998
999   }
1000
1001   return distance;
1002   
1003 }
1004
1005 static char * is_stack(void *address){
1006   unsigned int cursor = 0;
1007   stack_region_t stack;
1008
1009   xbt_dynar_foreach(stacks_areas, cursor, stack){
1010     if(address == stack->address)
1011       return stack->process_name;
1012   }
1013
1014   return NULL;
1015 }
1016
1017 static void add_heap_equality(xbt_dynar_t *equals, void *a1, void *a2){
1018   
1019   heap_equality_t he = xbt_new0(s_heap_equality_t, 1);
1020   he->address1 = a1;
1021   he->address2 = a2;
1022
1023   if(xbt_dynar_is_empty(*equals)){
1024
1025     xbt_dynar_insert_at(*equals, 0, &he);
1026   
1027   }else{
1028
1029     unsigned int cursor = 0;
1030     int start = 0;
1031     int end = xbt_dynar_length(*equals) - 1;
1032     heap_equality_t current_equality = NULL;
1033
1034     while(start <= end){
1035       cursor = (start + end) / 2;
1036       current_equality = (heap_equality_t)xbt_dynar_get_as(*equals, cursor, heap_equality_t);
1037       if(current_equality->address1 == a1){
1038         if(current_equality->address2 == a2)
1039           return;
1040         if(current_equality->address2 < a2)
1041           start = cursor + 1;
1042         if(current_equality->address2 > a2)
1043           end = cursor - 1;
1044       }
1045       if(current_equality->address1 < a1)
1046         start = cursor + 1;
1047       if(current_equality->address1 > a1)
1048         end = cursor - 1; 
1049     }
1050   
1051     if(current_equality->address1 < a1)
1052       xbt_dynar_insert_at(*equals, cursor + 1 , &he);
1053     else
1054        xbt_dynar_insert_at(*equals, cursor, &he); 
1055
1056   }
1057
1058 }
1059
1060 static void remove_heap_equality(xbt_dynar_t *equals, int address, void *a){
1061   
1062   unsigned int cursor = 0;
1063   heap_equality_t current_equality;
1064   int found = 0;
1065
1066   if(address == 1){
1067
1068     int start = 0;
1069     int end = xbt_dynar_length(*equals) - 1;
1070
1071
1072     while(start <= end && found == 0){
1073       cursor = (start + end) / 2;
1074       current_equality = (heap_equality_t)xbt_dynar_get_as(*equals, cursor, heap_equality_t);
1075       if(current_equality->address1 == a)
1076         found = 1;
1077       if(current_equality->address1 < a)
1078         start = cursor + 1;
1079       if(current_equality->address1 > a)
1080         end = cursor - 1; 
1081     }
1082
1083     if(found == 1)
1084       xbt_dynar_remove_at(*equals, cursor, NULL);
1085   
1086   }else{
1087
1088     xbt_dynar_foreach(*equals, cursor, current_equality){
1089       if(current_equality->address2 == a){
1090         found = 1;
1091         break;
1092       }
1093     }
1094
1095     if(found == 1)
1096       xbt_dynar_remove_at(*equals, cursor, NULL);
1097
1098   }
1099
1100   
1101 }
1102
1103 int is_free_area(void *area, xbt_mheap_t heap){
1104
1105   void *sheap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
1106   malloc_info *heapinfo = (malloc_info *)((char *)heap + ((uintptr_t)((char *)heap->heapinfo - (char *)sheap)));
1107   size_t heapsize = heap->heapsize;
1108
1109   /* Get block number */ 
1110   size_t block = ((char*)area - (char*)((xbt_mheap_t)sheap)->heapbase) / BLOCKSIZE + 1;
1111   size_t fragment;
1112
1113   /* Check if valid block number */
1114   if((char *)area < (char*)((xbt_mheap_t)sheap)->heapbase || block > heapsize || block < 1)
1115     return 0;
1116
1117   if(heapinfo[block].type < 0)
1118     return 1;
1119
1120   if(heapinfo[block].type == 0)
1121     return 0;
1122
1123   if(heapinfo[block].type > 0){
1124     fragment = ((uintptr_t) (ADDR2UINT(area) % (BLOCKSIZE))) >> heapinfo[block].type;
1125     if(heapinfo[block].busy_frag.frag_size[fragment] == 0)
1126       return 1;  
1127   }
1128
1129   return 0;
1130   
1131
1132
1133 }