Logo AND Algorithmique Numérique Distribuée

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