Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Setup the framework allowing to add backtraces to the malloc meta-data
[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
10 extern char *xbt_binary_name;
11
12 void mmalloc_backtrace_display(xbt_mheap_t mdp, void *ptr){
13   size_t block = BLOCK(ptr);
14   int type;
15   xbt_ex_t e;
16
17   if ((char *) ptr < (char *) mdp->heapbase || block > mdp->heapsize) {
18     fprintf(stderr,"Ouch, this pointer is not mine. I cannot display its backtrace. I refuse it to death!!\n");
19     abort();
20   }
21
22   type = mdp->heapinfo[block].type;
23
24   if (type != 0) {
25     //fprintf(stderr,"Only full blocks are backtraced for now. Ignoring your request.\n");
26     return;
27   }
28   if (mdp->heapinfo[block].busy_block.bt_size == 0) {
29     fprintf(stderr,"No backtrace available for that block, sorry.\n");
30     return;
31   }
32
33   memcpy(&e.bt,&(mdp->heapinfo[block].busy_block.bt),sizeof(void*)*XBT_BACKTRACE_SIZE);
34   e.used = mdp->heapinfo[block].busy_block.bt_size;
35
36   xbt_ex_setup_backtrace(&e);
37   if (e.used == 0) {
38     fprintf(stderr, "(backtrace not set)\n");
39   } else if (e.bt_strings == NULL) {
40     fprintf(stderr, "(backtrace not ready to be computed. %s)\n",xbt_binary_name?"Dunno why":"xbt_binary_name not setup yet");
41   } else {
42     int i;
43
44     fprintf(stderr, "Backtrace of where the block %p where malloced (%d frames):\n",ptr,e.used);
45     for (i = 0; i < e.used; i++)       /* no need to display "xbt_backtrace_display" */{
46       fprintf(stderr,"%d",i);fflush(NULL);
47       fprintf(stderr, "---> %s\n", e.bt_strings[i] + 4);
48     }
49   }
50 }
51
52 int mmalloc_compare_heap(xbt_mheap_t mdp1, xbt_mheap_t mdp2, void *std_heap_addr){
53
54   if(mdp1 == NULL && mdp2 == NULL){
55     XBT_DEBUG("Malloc descriptors null");
56     return 0;
57   }
58
59   /* Heapstats */
60
61   int errors = mmalloc_compare_mdesc(mdp1, mdp2, std_heap_addr);
62
63   return (errors > 0);
64
65 }
66
67 int mmalloc_compare_mdesc(struct mdesc *mdp1, struct mdesc *mdp2, void *std_heap_addr){
68
69   int errors = 0;
70
71   if(mdp1->headersize != mdp2->headersize){
72     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
73       XBT_DEBUG("Different size of the file header for the mapped files");
74       errors++;
75     }else{
76       return 1;
77     }
78   }
79
80   if(mdp1->refcount != mdp2->refcount){
81     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
82       XBT_DEBUG("Different number of processes that attached the heap");
83       errors++;
84     }else{
85       return 1;
86     }
87   }
88
89   if(strcmp(mdp1->magic, mdp2->magic) != 0){
90     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
91       XBT_DEBUG("Different magic number");
92       errors++;
93     }else{
94       return 1;
95     }
96   }
97
98   if(mdp1->flags != mdp2->flags){
99     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
100       XBT_DEBUG("Different flags");
101       errors++;
102     }else{
103       return 1;
104     }
105   }
106
107   if(mdp1->heapsize != mdp2->heapsize){
108     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
109       XBT_DEBUG("Different number of info entries");
110       errors++;
111     }else{
112       return 1;
113     }
114   }
115
116   //XBT_DEBUG("Heap size : %zu", mdp1->heapsize);
117
118   if(mdp1->heapbase != mdp2->heapbase){
119     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
120       XBT_DEBUG("Different first block of the heap");
121       errors++;
122     }else{
123       return 1;
124     }
125   }
126
127
128   if(mdp1->heapindex != mdp2->heapindex){
129     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
130       XBT_DEBUG("Different index for the heap table : %zu - %zu", mdp1->heapindex, mdp2->heapindex);
131       errors++;
132     }else{
133       return 1;
134     }
135   }
136
137   //XBT_DEBUG("Heap index : %zu", mdp1->heapindex);
138
139   if(mdp1->base != mdp2->base){
140     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
141       XBT_DEBUG("Different base address of the memory region");
142       errors++;
143     }else{
144       return 1;
145     }
146   }
147
148   if(mdp1->breakval != mdp2->breakval){
149     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
150       XBT_DEBUG("Different current location in the memory region");
151       errors++;
152     }else{
153       return 1;
154     }
155   }
156
157   if(mdp1->top != mdp2->top){
158     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
159       XBT_DEBUG("Different end of the current location in the memory region");
160       errors++;
161     }else{
162       return 1;
163     }
164   }
165
166   if(mdp1->heaplimit != mdp2->heaplimit){
167     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
168       XBT_DEBUG("Different limit of valid info table indices");
169       errors++;
170     }else{
171       return 1;
172     }
173   }
174
175   if(mdp1->fd != mdp2->fd){
176     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
177       XBT_DEBUG("Different file descriptor for the file to which this malloc heap is mapped");
178       errors++;
179     }else{
180       return 1;
181     }
182   }
183
184   if(mdp1->version != mdp2->version){
185     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
186       XBT_DEBUG("Different version of the mmalloc package");
187       errors++;
188     }else{
189       return 1;
190     }
191   }
192
193
194   size_t block_free1, block_free2 , next_block_free, first_block_free, block_free ;
195   size_t i, j;
196   void *addr_block1, *addr_block2;
197   size_t frag_size;
198
199
200   /* Search index of the first free block */
201
202   block_free1 = mdp1->heapindex;
203   block_free2 = mdp2->heapindex;
204
205   while(mdp1->heapinfo[block_free1].free_block.prev != 0){
206     block_free1 = mdp1->heapinfo[block_free1].free_block.prev;
207   }
208
209   while(mdp2->heapinfo[block_free2].free_block.prev != 0){
210     block_free2 = mdp1->heapinfo[block_free2].free_block.prev;
211   }
212
213   if(block_free1 !=  block_free2){
214     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
215       XBT_DEBUG("Different first free block");
216       errors++;
217     }else{
218       return 1;
219     }
220   }
221
222   first_block_free = block_free1;
223
224   if(mdp1->heapinfo[first_block_free].free_block.size != mdp2->heapinfo[first_block_free].free_block.size){
225     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
226       XBT_DEBUG("Different size (in blocks) of the first free cluster");
227       errors++;
228     }else{
229       return 1;
230     }
231   }
232
233   /* Check busy blocks (circular checking)*/
234
235   i = first_block_free + mdp1->heapinfo[first_block_free].free_block.size;
236
237   if(mdp1->heapinfo[first_block_free].free_block.next != mdp2->heapinfo[first_block_free].free_block.next){
238     if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
239       XBT_DEBUG("Different next block free");
240       errors++;
241     }else{
242       return 1;
243     }
244   }
245
246   block_free = first_block_free;
247   next_block_free = mdp1->heapinfo[first_block_free].free_block.next;
248
249   if(next_block_free == 0)
250     next_block_free = mdp1->heaplimit;
251
252   while(i != first_block_free){
253
254     while(i<next_block_free){
255
256       if(mdp1->heapinfo[i].type != mdp2->heapinfo[i].type){
257         if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
258           XBT_DEBUG("Different type of busy block");
259           errors++;
260         }else{
261           return 1;
262         }
263       }else{
264
265         addr_block1 = (char *)mdp1 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
266         addr_block2 = (char *)mdp2 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
267
268         switch(mdp1->heapinfo[i].type){ //FIXME deal with type<0 == free
269         case 0 :
270           if(mdp1->heapinfo[i].busy_block.size != mdp2->heapinfo[i].busy_block.size){
271             if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
272               XBT_DEBUG("Different size of a large cluster");
273               errors++;
274             }else{
275               return 1;
276             }
277           }else{
278             if(memcmp(addr_block1, addr_block2, (mdp1->heapinfo[i].busy_block.size * BLOCKSIZE)) != 0){
279               if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
280                 XBT_DEBUG("Different data in block %zu (size = %zu) (addr_block1 = %p (current = %p) - addr_block2 = %p)", i, mdp1->heapinfo[i].busy_block.size, addr_block1, (char *)std_heap_addr + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE), addr_block2);
281                 errors++;
282               }else{
283                 return 1;
284               }
285             }
286           }
287           i = i+mdp1->heapinfo[i].busy_block.size;
288
289           break;
290         default :
291           if(mdp1->heapinfo[i].busy_frag.nfree != mdp2->heapinfo[i].busy_frag.nfree){
292             if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
293               XBT_DEBUG("Different free fragments in the fragmented block %zu", i);
294               errors++;
295             }else{
296               return 1;
297             }
298           }else{
299             if(mdp1->heapinfo[i].busy_frag.first != mdp2->heapinfo[i].busy_frag.first){
300               if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
301                 XBT_DEBUG("Different first free fragments in the block %zu", i);
302                 errors++;
303               }else{
304                 return 1;
305               }
306             }else{
307               frag_size = pow(2,mdp1->heapinfo[i].type);
308               for(j=0 ; j< (BLOCKSIZE/frag_size); j++){
309                 if(memcmp((char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size), frag_size) != 0){
310                   if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
311                     XBT_DEBUG("Different data in fragment %zu (addr_frag1 = %p - addr_frag2 = %p) of block %zu", j + 1, (char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size),  i);
312                     errors++;
313                   }else{
314                     return 1;
315                   }
316                 }
317               }
318             }
319           }
320
321           i++;
322
323           break;
324         }
325
326       }
327     }
328
329     if( i != first_block_free){
330
331       if(mdp1->heapinfo[block_free].free_block.next != mdp2->heapinfo[block_free].free_block.next){
332         if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
333           XBT_DEBUG("Different next block free");
334           errors++;
335         }else{
336           return 1;
337         }
338       }
339
340       block_free = mdp1->heapinfo[block_free].free_block.next;
341       next_block_free = mdp1->heapinfo[block_free].free_block.next;
342
343       i = block_free + mdp1->heapinfo[block_free].free_block.size;
344
345       if((next_block_free == 0) && (i != mdp1->heaplimit)){
346
347         while(i < mdp1->heaplimit){
348
349           if(mdp1->heapinfo[i].type != mdp2->heapinfo[i].type){
350             if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
351               XBT_DEBUG("Different type of busy block");
352               errors++;
353             }else{
354               return 1;
355             }
356           }else{
357
358             addr_block1 = (char *)mdp1 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
359             addr_block2 = (char *)mdp2 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
360
361             switch(mdp1->heapinfo[i].type){
362             case 0 :
363               if(mdp1->heapinfo[i].busy_block.size != mdp2->heapinfo[i].busy_block.size){
364                 if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
365                   XBT_DEBUG("Different size of a large cluster");
366                   errors++;
367                 }else{
368                   return 1;
369                 }
370               }else{
371                 if(memcmp(addr_block1, addr_block2, (mdp1->heapinfo[i].busy_block.size * BLOCKSIZE)) != 0){
372                   if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
373                     XBT_DEBUG("Different data in block %zu (addr_block1 = %p (current = %p) - addr_block2 = %p)", i, addr_block1, (char *)std_heap_addr + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE), addr_block2);
374                     errors++;
375                   }else{
376                     return 1;
377                   }
378                 }
379               }
380
381               i = i+mdp1->heapinfo[i].busy_block.size;
382
383               break;
384             default :
385               if(mdp1->heapinfo[i].busy_frag.nfree != mdp2->heapinfo[i].busy_frag.nfree){
386                 if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
387                   XBT_DEBUG("Different free fragments in the fragmented block %zu", i);
388                   errors++;
389                 }else{
390                   return 1;
391                 }
392               }else{
393                 if(mdp1->heapinfo[i].busy_frag.first != mdp2->heapinfo[i].busy_frag.first){
394                   if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
395                     XBT_DEBUG("Different first free fragments in the block %zu", i);
396                     errors++;
397                   }else{
398                     return 1;
399                   }
400                 }else{
401                   frag_size = pow(2,mdp1->heapinfo[i].type);
402                   for(j=0 ; j< (BLOCKSIZE/frag_size); j++){
403                     if(memcmp((char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size), frag_size) != 0){
404                       if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
405                         XBT_DEBUG("Different data in fragment %zu (addr_frag1 = %p - addr_frag2 = %p) of block %zu", j + 1, (char *)addr_block1 + (j * frag_size), (char *)addr_block2 + (j * frag_size),  i);
406                         errors++;
407                       }else{
408                         return 1;
409                       }
410                     }
411                   }
412                 }
413               }
414
415               i++;
416
417               break;
418             }
419           }
420         }
421
422       }
423
424     }
425   }
426
427   return (errors>0);
428 }
429
430
431 void mmalloc_display_info_heap(xbt_mheap_t h){
432
433 }
434
435
436