Logo AND Algorithmique Numérique Distribuée

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