Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
8bc6173235b254e7c6e127a9bb77c6e38f1a4f98
[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 mmalloc_ignore;
19 xbt_dynar_t stacks_areas;
20
21 typedef struct s_heap_area_pair{
22   int block1;
23   int fragment1;
24   int block2;
25   int fragment2;
26 }s_heap_area_pair_t, *heap_area_pair_t;
27
28 static void heap_area_pair_free(heap_area_pair_t pair);
29 static void heap_area_pair_free_voidp(void *d);
30 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2);
31 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2);
32
33 static int compare_area(void *area1, void* area2, size_t size, xbt_dynar_t previous, int check_ignore);
34 static void match_equals(xbt_dynar_t list);
35
36 static int in_mmalloc_ignore(int block, int fragment);
37 static size_t heap_comparison_ignore(void *address);
38
39 static char* is_stack(void *address);
40
41 void mmalloc_backtrace_block_display(void* heapinfo, int block){
42
43   xbt_ex_t e;
44
45   if (((malloc_info *)heapinfo)[block].busy_block.bt_size == 0) {
46     XBT_DEBUG("No backtrace available for that block, sorry.");
47     return;
48   }
49
50   memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_block.bt),sizeof(void*)*XBT_BACKTRACE_SIZE);
51   e.used = ((malloc_info *)heapinfo)[block].busy_block.bt_size;
52
53   xbt_ex_setup_backtrace(&e);
54   if (e.used == 0) {
55     XBT_DEBUG("(backtrace not set)");
56   } else if (e.bt_strings == NULL) {
57     XBT_DEBUG("(backtrace not ready to be computed. %s)",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet");
58   } else {
59     int i;
60
61     XBT_DEBUG("Backtrace of where the block %d was malloced (%d frames):", block ,e.used);
62     for (i = 0; i < e.used; i++)       /* no need to display "xbt_backtrace_display" */{
63       XBT_DEBUG("%d ---> %s",i, e.bt_strings[i] + 4);
64     }
65   }
66
67 }
68
69 void mmalloc_backtrace_fragment_display(void* heapinfo, int block, int frag){
70
71   xbt_ex_t e;
72
73   memcpy(&e.bt,&(((malloc_info *)heapinfo)[block].busy_frag.bt[frag]),sizeof(void*)*XBT_BACKTRACE_SIZE);
74   e.used = XBT_BACKTRACE_SIZE;
75
76   xbt_ex_setup_backtrace(&e);
77   if (e.used == 0) {
78     XBT_DEBUG("(backtrace not set)");
79   } else if (e.bt_strings == NULL) {
80     XBT_DEBUG("(backtrace not ready to be computed. %s)",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet");
81   } else {
82     int i;
83
84     XBT_DEBUG("Backtrace of where the fragment %d in block %d was malloced (%d frames):", frag, block ,e.used);
85     for (i = 0; i < e.used; i++)       /* no need to display "xbt_backtrace_display" */{
86       XBT_DEBUG("%d ---> %s",i, e.bt_strings[i] + 4);
87     }
88   }
89
90 }
91
92 void *s_heap, *heapbase1, *heapbase2;
93 malloc_info *heapinfo1, *heapinfo2;
94 size_t heaplimit, heapsize1, heapsize2;
95
96 int ignore_done;
97
98 int mmalloc_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2, xbt_dynar_t *stack1, xbt_dynar_t *stack2){
99
100   if(heap1 == NULL && heap1 == NULL){
101     XBT_DEBUG("Malloc descriptors null");
102     return 0;
103   }
104
105   if(heap1->heaplimit != heap2->heaplimit){
106     XBT_DEBUG("Different limit of valid info table indices");
107     return 1;
108   }
109
110   /* Heap information */
111   heaplimit = ((struct mdesc *)heap1)->heaplimit;
112
113   s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
114
115   heapbase1 = (char *)heap1 + BLOCKSIZE;
116   heapbase2 = (char *)heap2 + BLOCKSIZE;
117
118   heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap)));
119   heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap)));
120
121   heapsize1 = heap1->heapsize;
122   heapsize2 = heap2->heapsize;
123
124   /* Start comparison */
125   size_t i1, i2, j1, j2, k, current_block, current_fragment;
126   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
127   void *real_addr_block1, *real_addr_block2;
128   char *stack_name;
129
130   xbt_dynar_t previous = xbt_dynar_new(sizeof(heap_area_pair_t), heap_area_pair_free_voidp);
131
132   int equal, res_compare;
133
134   ignore_done = 0;
135
136   /* Init equal information */
137   i1 = 1;
138
139   while(i1<=heaplimit){
140     if(heapinfo1[i1].type == 0){
141       heapinfo1[i1].busy_block.equal_to = -1;
142     }
143     if(heapinfo1[i1].type > 0){
144       for(j1=0; j1 < MAX_FRAGMENT_PER_BLOCK; j1++){
145         heapinfo1[i1].busy_frag.equal_to[j1] = -1;
146       }
147     }
148     i1++; 
149   }
150
151   i2 = 1;
152
153   while(i2<=heaplimit){
154     if(heapinfo2[i2].type == 0){
155       heapinfo2[i2].busy_block.equal_to = -1;
156     }
157     if(heapinfo2[i2].type > 0){
158       for(j2=0; j2 < MAX_FRAGMENT_PER_BLOCK; j2++){
159         heapinfo2[i2].busy_frag.equal_to[j2] = -1;
160       }
161     }
162     i2++; 
163   }
164
165   /* Check busy blocks*/
166
167   i1 = 1;
168
169   while(i1 <= heaplimit){
170
171     current_block = i1;
172
173     if(heapinfo1[i1].type == -1){ /* Free block */
174       i1++;
175       continue;
176     }
177
178     addr_block1 = ((void*) (((ADDR2UINT(i1)) - 1) * BLOCKSIZE + (char*)heapbase1));
179
180     if(heapinfo1[i1].type == 0){  /* Large block */
181       
182       real_addr_block1 = (char*)((xbt_mheap_t)s_heap)->heapbase + (((char *)addr_block1) - (char *)heapbase1);
183
184       if((stack_name = is_stack(real_addr_block1)) != NULL){
185         stack_region_t stack = xbt_new0(s_stack_region_t, 1);
186         stack->address = addr_block1;
187         stack->process_name = strdup(stack_name);
188         xbt_dynar_push(*stack1, &stack);
189       }
190
191       if(heapinfo1[i1].busy_block.busy_size == 0){
192         i1++;
193         continue;
194       }
195       
196       i2 = 1;
197       equal = 0;
198       
199       /* Try first to associate to same block in the other heap */
200       if(heapinfo2[current_block].type == heapinfo1[current_block].type){
201         
202         if(heapinfo1[current_block].busy_block.busy_size == heapinfo2[current_block].busy_block.busy_size){
203
204           addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)heapbase2));
205
206           real_addr_block2 = (char*)((xbt_mheap_t)s_heap)->heapbase + (((char *)addr_block2) - (char *)heapbase2);
207           
208           if((stack_name = is_stack(real_addr_block2)) != NULL){
209             stack_region_t stack = xbt_new0(s_stack_region_t, 1);
210             stack->address = addr_block2;
211             stack->process_name = strdup(stack_name);
212             xbt_dynar_push(*stack2, &stack);
213           }
214
215         
216           add_heap_area_pair(previous, current_block, -1, current_block, -1);
217           
218           if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
219             if(in_mmalloc_ignore((int)current_block, -1))
220               res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 1);
221             else
222               res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 0);
223           }else{
224             res_compare = compare_area(addr_block1, addr_block2, heapinfo1[current_block].busy_block.busy_size, previous, 0);
225           }
226           
227           if(res_compare == 0){
228             for(k=1; k < heapinfo2[current_block].busy_block.size; k++)
229               heapinfo2[current_block+k].busy_block.equal_to = 1 ;
230             for(k=1; k < heapinfo1[current_block].busy_block.size; k++)
231               heapinfo1[current_block+k].busy_block.equal_to = 1 ;
232             equal = 1;
233             match_equals(previous);
234             i1 = i1 + heapinfo1[i1].busy_block.size;
235           }
236
237           xbt_dynar_reset(previous);
238           
239         }
240
241       }
242
243       while(i2 <= heaplimit && !equal){
244
245         addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)heapbase2));
246         
247         real_addr_block2 = (char*)((xbt_mheap_t)s_heap)->heapbase + (((char *)addr_block2) - (char *)heapbase2);
248         
249         if((stack_name = is_stack(real_addr_block2)) != NULL){
250           stack_region_t stack = xbt_new0(s_stack_region_t, 1);
251           stack->address = addr_block2;
252           stack->process_name = strdup(stack_name);
253           xbt_dynar_push(*stack2, &stack);
254         }
255            
256         if(i2 == current_block){
257           i2++;
258           continue;
259         }
260
261         if(heapinfo2[i2].type != 0){
262           i2++;
263           continue;
264         }
265
266         if(heapinfo2[i2].busy_block.equal_to == 1){         
267           i2++;
268           continue;
269         }
270         
271         if(heapinfo1[i1].busy_block.size != heapinfo2[i2].busy_block.size){
272           i2++;
273           continue;
274         }
275         
276         if(heapinfo1[i1].busy_block.busy_size != heapinfo2[i2].busy_block.busy_size){
277           i2++;
278           continue;
279         }
280
281         /* Comparison */
282         add_heap_area_pair(previous, i1, -1, i2, -1);
283         
284         if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
285           if(in_mmalloc_ignore((int)i1, -1))
286             res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 1);
287           else
288             res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 0);
289         }else{
290           res_compare = compare_area(addr_block1, addr_block2, heapinfo1[i1].busy_block.busy_size, previous, 0);
291         }
292         
293         if(!res_compare){
294           for(k=1; k < heapinfo2[i2].busy_block.size; k++)
295             heapinfo2[i2+k].busy_block.equal_to = 1;
296           for(k=1; k < heapinfo1[i1].busy_block.size; k++)
297             heapinfo1[i1+k].busy_block.equal_to = 1;
298           equal = 1;
299           match_equals(previous);
300         }
301
302         xbt_dynar_reset(previous);
303
304         i2++;
305
306       }
307
308       if(!equal)
309         i1++;
310       
311     }else{ /* Fragmented block */
312
313       for(j1=0; j1 < (size_t) (BLOCKSIZE >> heapinfo1[i1].type); j1++){
314
315         current_fragment = j1;
316
317         if(heapinfo1[i1].busy_frag.frag_size[j1] == 0) /* Free fragment */
318           continue;
319         
320         addr_frag1 = (void*) ((char *)addr_block1 + (j1 << heapinfo1[i1].type));
321
322         i2 = 1;
323         equal = 0;
324         
325         /* Try first to associate to same fragment in the other heap */
326         if(heapinfo2[current_block].type == heapinfo1[current_block].type){
327           
328           if(heapinfo1[current_block].busy_frag.frag_size[current_fragment] == heapinfo2[current_block].busy_frag.frag_size[current_fragment]){
329
330             addr_block2 = ((void*) (((ADDR2UINT(current_block)) - 1) * BLOCKSIZE + (char*)heapbase2));
331             addr_frag2 = (void*) ((char *)addr_block2 + (current_fragment << heapinfo2[current_block].type));
332
333             add_heap_area_pair(previous, current_block, current_fragment, current_block, current_fragment);
334             
335             if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
336               if(in_mmalloc_ignore((int)current_block, (int)current_fragment))
337                 res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 1);
338               else
339                 res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 0);
340             }else{
341               res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[current_block].busy_frag.frag_size[current_fragment], previous, 0);
342             }
343
344             if(res_compare == 0){
345               equal = 1;
346               match_equals(previous);
347             }
348             
349             xbt_dynar_reset(previous);
350             
351           }
352
353         }
354
355
356         while(i2 <= heaplimit && !equal){
357           
358           if(heapinfo2[i2].type <= 0){
359             i2++;
360             continue;
361           }
362
363           for(j2=0; j2 < (size_t) (BLOCKSIZE >> heapinfo2[i2].type); j2++){
364
365             if(heapinfo2[i2].type == heapinfo1[i1].type && i2 == current_block && j2 == current_fragment)
366               continue;
367
368             if(heapinfo2[i2].busy_frag.equal_to[j2] == 1)                
369               continue;              
370              
371             if(heapinfo1[i1].busy_frag.frag_size[j1] != heapinfo2[i2].busy_frag.frag_size[j2]) /* Different size_used */    
372               continue;
373              
374             addr_block2 = ((void*) (((ADDR2UINT(i2)) - 1) * BLOCKSIZE + (char*)heapbase2));
375             addr_frag2 = (void*) ((char *)addr_block2 + (j2 << heapinfo2[i2].type));
376              
377             /* Comparison */
378             add_heap_area_pair(previous, i1, j1, i2, j2);
379             
380             if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
381               if(in_mmalloc_ignore((int)i1, (int)j1))
382                 res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 1);
383               else
384                 res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 0);
385             }else{
386               res_compare = compare_area(addr_frag1, addr_frag2, heapinfo1[i1].busy_frag.frag_size[j1], previous, 0);
387             }
388
389             if(!res_compare){
390               equal = 1;
391               match_equals(previous);
392               xbt_dynar_reset(previous);
393               break;
394             }
395
396             xbt_dynar_reset(previous);
397
398           }
399
400           i2++;
401
402         }
403
404       }
405
406       i1++;
407       
408     }
409
410   }
411
412   /* All blocks/fragments are equal to another block/fragment ? */
413   size_t i = 1, j = 0;
414   int nb_diff1 = 0, nb_diff2 = 0;
415  
416   while(i<heaplimit){
417     if(heapinfo1[i].type == 0){
418       if(heapinfo1[i].busy_block.busy_size > 0){
419         if(heapinfo1[i].busy_block.equal_to == -1){
420           if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
421             addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
422             XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block1, heapinfo1[i].busy_block.busy_size);
423             mmalloc_backtrace_block_display((void*)heapinfo1, i);
424           }
425           nb_diff1++;
426         }
427       }
428     }
429     if(heapinfo1[i].type > 0){
430       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
431         if(heapinfo1[i].busy_frag.frag_size[j] > 0){
432           if(heapinfo1[i].busy_frag.equal_to[j] == -1){
433             if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
434               addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
435               addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type));
436               XBT_DEBUG("Block %zu, Fragment %zu (%p) not found (size used = %d)", i, j, addr_frag1, heapinfo1[i].busy_frag.frag_size[j]);
437               mmalloc_backtrace_fragment_display((void*)heapinfo1, i, j);
438             }
439             nb_diff1++;
440           }
441         }
442       }
443     }
444     
445     i++; 
446   }
447
448   XBT_DEBUG("Different blocks or fragments in heap1 : %d\n", nb_diff1);
449
450   i = 1;
451
452   while(i<heaplimit){
453     if(heapinfo2[i].type == 0){
454       if(heapinfo2[i].busy_block.busy_size > 0){
455         if(heapinfo2[i].busy_block.equal_to == -1){
456           if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
457             addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
458             XBT_DEBUG("Block %zu (%p) not found (size used = %zu)", i, addr_block2, heapinfo2[i].busy_block.busy_size);
459             mmalloc_backtrace_block_display((void*)heapinfo2, i);
460           }
461           nb_diff2++;
462         }
463       }
464     }
465     if(heapinfo2[i].type > 0){
466       for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo2[i].type); j++){
467         if(heapinfo2[i].busy_frag.frag_size[j] > 0){
468           if(heapinfo2[i].busy_frag.equal_to[j] == -1){
469             if(XBT_LOG_ISENABLED(mm_diff, xbt_log_priority_debug)){
470               addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
471               addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type));
472               XBT_DEBUG( "Block %zu, Fragment %zu (%p) not found (size used = %d)", i, j, addr_frag2, heapinfo2[i].busy_frag.frag_size[j]);
473               mmalloc_backtrace_fragment_display((void*)heapinfo2, i, j);
474             }
475             nb_diff2++;
476           }
477         }
478       }
479     }
480     i++; 
481   }
482
483   XBT_DEBUG("Different blocks or fragments in heap2 : %d\n", nb_diff2);
484
485   xbt_dynar_free(&previous);
486  
487   return ((nb_diff1 > 0) || (nb_diff2 > 0));
488
489 }
490
491 static int in_mmalloc_ignore(int block, int fragment){
492
493   unsigned int cursor = 0;
494   int start = 0;
495   int end = xbt_dynar_length(mmalloc_ignore) - 1;
496   mc_ignore_region_t region;
497
498   while(start <= end){
499     cursor = (start + end) / 2;
500     region = (mc_ignore_region_t)xbt_dynar_get_as(mmalloc_ignore, cursor, mc_ignore_region_t);
501     if(region->block == block){
502       if(region->fragment == fragment)
503         return 1;
504       if(region->fragment < fragment)
505         start = cursor + 1;
506       if(region->fragment > fragment)
507         end = cursor - 1;
508     }
509     if(region->block < block)
510       start = cursor + 1;
511     if(region->block > block)
512       end = cursor - 1; 
513   }
514
515   return 0;
516 }
517
518 static size_t heap_comparison_ignore(void *address){
519   unsigned int cursor = 0;
520   int start = 0;
521   int end = xbt_dynar_length(mmalloc_ignore) - 1;
522   mc_ignore_region_t region;
523
524   while(start <= end){
525     cursor = (start + end) / 2;
526     region = (mc_ignore_region_t)xbt_dynar_get_as(mmalloc_ignore, cursor, mc_ignore_region_t);
527     if(region->address == address)
528       return region->size;
529     if(region->address < address)
530       start = cursor + 1;
531     if(region->address > address)
532       end = cursor - 1;   
533   }
534
535   return 0;
536 }
537
538
539 static int compare_area(void *area1, void* area2, size_t size, xbt_dynar_t previous, int check_ignore){
540
541   size_t i = 0, pointer_align = 0, ignore1 = 0, ignore2 = 0;
542   void *address_pointed1, *address_pointed2, *addr_block_pointed1, *addr_block_pointed2, *addr_frag_pointed1, *addr_frag_pointed2;
543   size_t block_pointed1, block_pointed2, frag_pointed1, frag_pointed2;
544   int res_compare;
545   void *current_area1, *current_area2;
546  
547   while(i<size){
548
549     if(check_ignore){
550
551       current_area1 = (char*)((xbt_mheap_t)s_heap)->heapbase + ((((char *)area1) + i) - (char *)heapbase1);
552       if((ignore1 = heap_comparison_ignore(current_area1)) > 0){
553         current_area2 = (char*)((xbt_mheap_t)s_heap)->heapbase + ((((char *)area2) + i) - (char *)heapbase2);
554         if((ignore2 = heap_comparison_ignore(current_area2))  == ignore1){
555           i = i + ignore2;
556           ignore_done++;
557           continue;
558         }
559       }
560
561     }
562    
563     if(memcmp(((char *)area1) + i, ((char *)area2) + i, 1) != 0){
564
565       /* Check pointer difference */
566       pointer_align = (i / sizeof(void*)) * sizeof(void*);
567       address_pointed1 = *((void **)((char *)area1 + pointer_align));
568       address_pointed2 = *((void **)((char *)area2 + pointer_align));
569
570       /* Get pointed blocks number */ 
571       block_pointed1 = ((char*)address_pointed1 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
572       block_pointed2 = ((char*)address_pointed2 - (char*)((xbt_mheap_t)s_heap)->heapbase) / BLOCKSIZE + 1;
573
574       /* Check if valid blocks number */
575       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)
576         return 1;
577
578       if(heapinfo1[block_pointed1].type == heapinfo2[block_pointed2].type){ /* Same type of block (large or fragmented) */
579
580         addr_block_pointed1 = ((void*) (((ADDR2UINT(block_pointed1)) - 1) * BLOCKSIZE + (char*)heapbase1));
581         addr_block_pointed2 = ((void*) (((ADDR2UINT(block_pointed2)) - 1) * BLOCKSIZE + (char*)heapbase2));
582         
583         if(heapinfo1[block_pointed1].type == 0){ /* Large block */
584
585           if(heapinfo1[block_pointed1].busy_block.size != heapinfo2[block_pointed2].busy_block.size){
586             return 1;
587           }
588
589           if(heapinfo1[block_pointed1].busy_block.busy_size != heapinfo2[block_pointed2].busy_block.busy_size){
590             return 1;
591           }
592
593           if(add_heap_area_pair(previous, block_pointed1, -1, block_pointed2, -1)){
594
595             if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
596               if(in_mmalloc_ignore(block_pointed1, -1))
597                 res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 1);
598               else
599                 res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 0);
600             }else{
601               res_compare = compare_area(addr_block_pointed1, addr_block_pointed2, heapinfo1[block_pointed1].busy_block.busy_size, previous, 0);
602             }
603             
604             if(res_compare)    
605               return 1;
606            
607           }
608           
609         }else{ /* Fragmented block */
610
611           /* Get pointed fragments number */ 
612           frag_pointed1 = ((uintptr_t) (ADDR2UINT (address_pointed1) % (BLOCKSIZE))) >> heapinfo1[block_pointed1].type;
613           frag_pointed2 = ((uintptr_t) (ADDR2UINT (address_pointed2) % (BLOCKSIZE))) >> heapinfo2[block_pointed2].type;
614          
615           if(heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1] != heapinfo2[block_pointed2].busy_frag.frag_size[frag_pointed2]) /* Different size_used */    
616             return 1;
617             
618           addr_frag_pointed1 = (void*) ((char *)addr_block_pointed1 + (frag_pointed1 << heapinfo1[block_pointed1].type));
619           addr_frag_pointed2 = (void*) ((char *)addr_block_pointed2 + (frag_pointed2 << heapinfo2[block_pointed2].type));
620
621           if(add_heap_area_pair(previous, block_pointed1, frag_pointed1, block_pointed2, frag_pointed2)){
622
623             if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
624               if(in_mmalloc_ignore(block_pointed1, frag_pointed1))
625                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 1);
626               else
627                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
628             }else{
629               res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
630             }
631
632             if(res_compare)
633               return 1;
634            
635           }
636           
637         }
638           
639       }else{
640
641         if((heapinfo1[block_pointed1].type > 0) && (heapinfo2[block_pointed2].type > 0)){
642           
643           addr_block_pointed1 = ((void*) (((ADDR2UINT(block_pointed1)) - 1) * BLOCKSIZE + (char*)heapbase1));
644           addr_block_pointed2 = ((void*) (((ADDR2UINT(block_pointed2)) - 1) * BLOCKSIZE + (char*)heapbase2));
645        
646           frag_pointed1 = ((uintptr_t) (ADDR2UINT (address_pointed1) % (BLOCKSIZE))) >> heapinfo1[block_pointed1].type;
647           frag_pointed2 = ((uintptr_t) (ADDR2UINT (address_pointed2) % (BLOCKSIZE))) >> heapinfo2[block_pointed2].type;
648
649           if(heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1] != heapinfo2[block_pointed2].busy_frag.frag_size[frag_pointed2]) /* Different size_used */    
650             return 1;
651
652           addr_frag_pointed1 = (void*) ((char *)addr_block_pointed1 + (frag_pointed1 << heapinfo1[block_pointed1].type));
653           addr_frag_pointed2 = (void*) ((char *)addr_block_pointed2 + (frag_pointed2 << heapinfo2[block_pointed2].type));
654
655           if(add_heap_area_pair(previous, block_pointed1, frag_pointed1, block_pointed2, frag_pointed2)){
656
657             if(ignore_done < xbt_dynar_length(mmalloc_ignore)){
658               if(in_mmalloc_ignore(block_pointed1, frag_pointed1))
659                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 1);
660               else
661                 res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
662             }else{
663               res_compare = compare_area(addr_frag_pointed1, addr_frag_pointed2, heapinfo1[block_pointed1].busy_frag.frag_size[frag_pointed1], previous, 0);
664             }
665             
666             if(res_compare)
667               return 1;
668            
669           }
670
671         }else{
672           return 1;
673         }
674
675       }
676
677       i = pointer_align + sizeof(void *);
678       
679     }else{
680
681       i++;
682
683     }
684   }
685
686   return 0;
687   
688
689 }
690
691 static void heap_area_pair_free(heap_area_pair_t pair){
692   if (pair){
693     free(pair);
694     pair = NULL;
695   }
696 }
697
698 static void heap_area_pair_free_voidp(void *d)
699 {
700   heap_area_pair_free((heap_area_pair_t) * (void **) d);
701 }
702
703 static int add_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){
704
705   if(is_new_heap_area_pair(list, block1, fragment1, block2, fragment2)){
706     heap_area_pair_t pair = NULL;
707     pair = xbt_new0(s_heap_area_pair_t, 1);
708     pair->block1 = block1;
709     pair->fragment1 = fragment1;
710     pair->block2 = block2;
711     pair->fragment2 = fragment2;
712     
713     xbt_dynar_push(list, &pair); 
714
715     return 1;
716   }
717
718   return 0;
719 }
720  
721 static int is_new_heap_area_pair(xbt_dynar_t list, int block1, int fragment1, int block2, int fragment2){
722   
723   unsigned int cursor = 0;
724   heap_area_pair_t current_pair;
725
726   xbt_dynar_foreach(list, cursor, current_pair){
727     if(current_pair->block1 == block1 && current_pair->block2 == block2 && current_pair->fragment1 == fragment1 && current_pair->fragment2 == fragment2)
728       return 0; 
729   }
730   
731   return 1;
732 }
733
734 static void match_equals(xbt_dynar_t list){
735
736   unsigned int cursor = 0;
737   heap_area_pair_t current_pair;
738
739   xbt_dynar_foreach(list, cursor, current_pair){
740     if(current_pair->fragment1 != -1){
741       heapinfo1[current_pair->block1].busy_frag.equal_to[current_pair->fragment1] = 1;
742       heapinfo2[current_pair->block2].busy_frag.equal_to[current_pair->fragment2] = 1;
743     }else{
744       heapinfo1[current_pair->block1].busy_block.equal_to = 1;
745       heapinfo2[current_pair->block2].busy_block.equal_to = 1;
746     }
747   }
748
749 }
750
751 #ifndef max
752         #define max( a, b ) ( ((a) > (b)) ? (a) : (b) )
753 #endif
754
755 int mmalloc_linear_compare_heap(xbt_mheap_t heap1, xbt_mheap_t heap2){
756
757   if(heap1 == NULL && heap1 == NULL){
758     XBT_DEBUG("Malloc descriptors null");
759     return 0;
760   }
761
762   if(heap1->heaplimit != heap2->heaplimit){
763     XBT_DEBUG("Different limit of valid info table indices");
764     return 1;
765   }
766
767   /* Heap information */
768   heaplimit = ((struct mdesc *)heap1)->heaplimit;
769
770   s_heap = (char *)mmalloc_get_current_heap() - STD_HEAP_SIZE - getpagesize();
771
772   heapbase1 = (char *)heap1 + BLOCKSIZE;
773   heapbase2 = (char *)heap2 + BLOCKSIZE;
774
775   heapinfo1 = (malloc_info *)((char *)heap1 + ((uintptr_t)((char *)heap1->heapinfo - (char *)s_heap)));
776   heapinfo2 = (malloc_info *)((char *)heap2 + ((uintptr_t)((char *)heap2->heapinfo - (char *)s_heap)));
777
778   heapsize1 = heap1->heapsize;
779   heapsize2 = heap2->heapsize;
780
781   /* Start comparison */
782   size_t i, j, k;
783   void *addr_block1, *addr_block2, *addr_frag1, *addr_frag2;
784
785   int distance = 0;
786
787   /* Check busy blocks*/
788
789   i = 1;
790
791   while(i <= heaplimit){
792
793     addr_block1 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase1));
794     addr_block2 = ((void*) (((ADDR2UINT(i)) - 1) * BLOCKSIZE + (char*)heapbase2));
795
796     if(heapinfo1[i].type != heapinfo2[i].type){
797   
798       distance += BLOCKSIZE;
799       XBT_DEBUG("Different type of blocks (%zu) : %d - %d -> distance = %d", i, heapinfo1[i].type, heapinfo2[i].type, distance);
800       i++;
801     
802     }else{
803
804       if(heapinfo1[i].type == -1){ /* Free block */
805         i++;
806         continue;
807       }
808
809       if(heapinfo1[i].type == 0){ /* Large block */
810        
811         if(heapinfo1[i].busy_block.size != heapinfo2[i].busy_block.size){
812           distance += BLOCKSIZE * max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
813           i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
814           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);
815           continue;
816         }
817
818         /*if(heapinfo1[i].busy_block.busy_size != heapinfo2[i].busy_block.busy_size){
819           distance += max(heapinfo1[i].busy_block.busy_size, heapinfo2[i].busy_block.busy_size);
820           i += max(heapinfo1[i].busy_block.size, heapinfo2[i].busy_block.size);
821           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);
822           continue;
823           }*/
824
825         k = 0;
826
827         //while(k < (heapinfo1[i].busy_block.busy_size)){
828         while(k < heapinfo1[i].busy_block.size * BLOCKSIZE){
829           if(memcmp((char *)addr_block1 + k, (char *)addr_block2 + k, 1) != 0){
830             distance ++;
831           }
832           k++;
833         } 
834
835         i++;
836
837       }else { /* Fragmented block */
838
839         for(j=0; j < (size_t) (BLOCKSIZE >> heapinfo1[i].type); j++){
840
841           addr_frag1 = (void*) ((char *)addr_block1 + (j << heapinfo1[i].type));
842           addr_frag2 = (void*) ((char *)addr_block2 + (j << heapinfo2[i].type));
843
844           if(heapinfo1[i].busy_frag.frag_size[j] == 0 && heapinfo2[i].busy_frag.frag_size[j] == 0){
845             continue;
846           }
847           
848           
849           /*if(heapinfo1[i].busy_frag.frag_size[j] != heapinfo2[i].busy_frag.frag_size[j]){
850             distance += max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j]);
851             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); 
852             continue;
853             }*/
854    
855           k=0;
856
857           //while(k < max(heapinfo1[i].busy_frag.frag_size[j], heapinfo2[i].busy_frag.frag_size[j])){
858           while(k < (BLOCKSIZE / (BLOCKSIZE >> heapinfo1[i].type))){
859             if(memcmp((char *)addr_frag1 + k, (char *)addr_frag2 + k, 1) != 0){
860               distance ++;
861             }
862             k++;
863           }
864
865         }
866
867         i++;
868
869       }
870       
871     }
872
873   }
874
875   return distance;
876   
877 }
878
879 static char * is_stack(void *address){
880   unsigned int cursor = 0;
881   stack_region_t stack;
882
883   xbt_dynar_foreach(stacks_areas, cursor, stack){
884     if(address == stack->address)
885       return stack->process_name;
886   }
887
888   return NULL;
889 }