Logo AND Algorithmique Numérique Distribuée

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