1 /* mm_diff - Memory snapshooting and comparison */
3 /* Copyright (c) 2008-2012. The SimGrid Team. All rights reserved. */
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. */
8 #include "xbt/ex_interface.h" /* internals of backtrace setup */
10 extern char *xbt_binary_name;
12 void mmalloc_backtrace_display(xbt_mheap_t mdp, void *ptr){
13 size_t block = BLOCK(ptr);
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");
22 type = mdp->heapinfo[block].type;
25 //fprintf(stderr,"Only full blocks are backtraced for now. Ignoring your request.\n");
28 if (mdp->heapinfo[block].busy_block.bt_size == 0) {
29 fprintf(stderr,"No backtrace available for that block, sorry.\n");
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;
36 xbt_ex_setup_backtrace(&e);
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");
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);
52 int mmalloc_compare_heap(xbt_mheap_t mdp1, xbt_mheap_t mdp2, void *std_heap_addr){
54 if(mdp1 == NULL && mdp2 == NULL){
55 XBT_DEBUG("Malloc descriptors null");
61 int errors = mmalloc_compare_mdesc(mdp1, mdp2, std_heap_addr);
67 int mmalloc_compare_mdesc(struct mdesc *mdp1, struct mdesc *mdp2, void *std_heap_addr){
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");
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");
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");
98 if(mdp1->flags != mdp2->flags){
99 if(XBT_LOG_ISENABLED(xbt_mm_legacy, xbt_log_priority_debug)){
100 XBT_DEBUG("Different flags");
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");
116 //XBT_DEBUG("Heap size : %zu", mdp1->heapsize);
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");
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);
137 //XBT_DEBUG("Heap index : %zu", mdp1->heapindex);
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");
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");
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");
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");
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");
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");
194 size_t block_free1, block_free2 , next_block_free, first_block_free, block_free ;
196 void *addr_block1, *addr_block2;
200 /* Search index of the first free block */
202 block_free1 = mdp1->heapindex;
203 block_free2 = mdp2->heapindex;
205 while(mdp1->heapinfo[block_free1].free_block.prev != 0){
206 block_free1 = mdp1->heapinfo[block_free1].free_block.prev;
209 while(mdp2->heapinfo[block_free2].free_block.prev != 0){
210 block_free2 = mdp1->heapinfo[block_free2].free_block.prev;
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");
222 first_block_free = block_free1;
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");
233 /* Check busy blocks (circular checking)*/
235 i = first_block_free + mdp1->heapinfo[first_block_free].free_block.size;
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");
246 block_free = first_block_free;
247 next_block_free = mdp1->heapinfo[first_block_free].free_block.next;
249 if(next_block_free == 0)
250 next_block_free = mdp1->heaplimit;
252 while(i != first_block_free){
254 while(i<next_block_free){
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");
265 addr_block1 = (char *)mdp1 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
266 addr_block2 = (char *)mdp2 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
268 switch(mdp1->heapinfo[i].type){ //FIXME deal with type<0 == free
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");
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);
287 i = i+mdp1->heapinfo[i].busy_block.size;
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);
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);
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);
329 if( i != first_block_free){
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");
340 block_free = mdp1->heapinfo[block_free].free_block.next;
341 next_block_free = mdp1->heapinfo[block_free].free_block.next;
343 i = block_free + mdp1->heapinfo[block_free].free_block.size;
345 if((next_block_free == 0) && (i != mdp1->heaplimit)){
347 while(i < mdp1->heaplimit){
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");
358 addr_block1 = (char *)mdp1 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
359 addr_block2 = (char *)mdp2 + sizeof(struct mdesc) + ((i-1) * BLOCKSIZE);
361 switch(mdp1->heapinfo[i].type){
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");
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);
381 i = i+mdp1->heapinfo[i].busy_block.size;
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);
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);
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);
431 void mmalloc_display_info_heap(xbt_mheap_t h){