Logo AND Algorithmique Numérique Distribuée

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