1 /* natGCInfo.cc -- Native portion of support for creating heap dumps.
2 Copyright (C) 2007 Free Software Foundation
4 This file is part of libgcj.
6 This software is copyrighted work licensed under the terms of the
7 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
15 #include <gnu/gcj/util/GCInfo.h>
17 #ifdef HAVE_PROC_SELF_MAPS
19 // If /proc/self/maps does not exist we assume we are doomed and do nothing.
39 #ifdef PACKAGE_TARNAME
40 #undef PACKAGE_TARNAME
43 #ifdef PACKAGE_VERSION
44 #undef PACKAGE_VERSION
56 #include "private/dbg_mlc.h"
57 int GC_n_set_marks(hdr
* hhdr
);
58 ptr_t
GC_clear_stack(ptr_t p
);
59 extern int GC_gcj_kind
;
60 extern int GC_gcj_debug_kind
;
65 #ifdef HAVE_PROC_SELF_MAPS
69 typedef struct gc_debug_info
79 GC_print_debug_callback(hblk
*h
, word user_data
)
82 size_t bytes
= WORDS_TO_BYTES(hhdr
-> hb_sz
);
84 gc_debug_info
*pinfo
= (gc_debug_info
*)user_data
;
86 fprintf(pinfo
->fp
, "ptr = %#lx, kind = %d, size = %zd, marks = %d\n",
87 (unsigned long)h
, hhdr
->hb_obj_kind
, bytes
, GC_n_set_marks(hhdr
));
91 this next section of definitions shouldn't really be here.
92 copied from boehmgc/allchblk.c
95 # define UNIQUE_THRESHOLD 32
96 # define HUGE_THRESHOLD 256
97 # define FL_COMPRESSION 8
98 # define N_HBLK_FLS (HUGE_THRESHOLD - UNIQUE_THRESHOLD)/FL_COMPRESSION \
102 extern word GC_free_bytes
[N_HBLK_FLS
+1];
107 # define IS_MAPPED(hhdr) (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0)
108 # else /* !USE_MMAP */
109 # define IS_MAPPED(hhdr) 1
110 # endif /* USE_MUNMAP */
113 GC_print_hblkfreelist_file(FILE *fp
)
121 fprintf(fp
, "---------- Begin free map ----------\n");
122 for (i
= 0; i
<= N_HBLK_FLS
; ++i
)
124 h
= GC_hblkfreelist
[i
];
127 fprintf (fp
, "Free list %ld:\n", (unsigned long)i
);
130 fprintf (fp
, "Free list %ld (Total size %ld):\n",
132 (unsigned long)GC_free_bytes
[i
]);
138 fprintf (fp
, "\t0x%lx size %lu ", (unsigned long)h
,
142 if (GC_is_black_listed (h
, HBLKSIZE
) != 0)
143 fprintf (fp
, "start black listed\n");
144 else if (GC_is_black_listed(h
, hhdr
-> hb_sz
) != 0)
145 fprintf (fp
, "partially black listed\n");
147 fprintf (fp
, "not black listed\n");
153 if (total_free
!= GC_large_free_bytes
)
155 fprintf (fp
, "GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
156 (unsigned long) GC_large_free_bytes
);
159 fprintf (fp
, "Total of %lu bytes on free list\n", (unsigned long)total_free
);
160 fprintf (fp
, "---------- End free map ----------\n");
163 static int GC_dump_count
= 1;
166 GC_print_debug_info_file(FILE* fp
)
170 memset(&info
, 0, sizeof info
);
175 fprintf(info
.fp
, "---------- Begin block map ----------\n");
176 GC_apply_to_all_blocks(GC_print_debug_callback
, (word
)(void*)(&info
));
177 //fprintf(fp, "#Total used %d free %d wasted %d\n", info.used, info.free, info.wasted);
178 //fprintf(fp, "#Total blocks %d; %dK bytes\n", info.blocks, info.blocks*4);
179 fprintf(info
.fp
, "---------- End block map ----------\n");
181 //fprintf(fp, "\n***Free blocks:\n");
182 //GC_print_hblkfreelist();
187 class __attribute__ ((visibility ("hidden"))) GC_enumerator
190 GC_enumerator(const char *name
);
196 void print_address_map();
197 void enumerate_callback(struct hblk
*h
);
198 static void enumerate_callback_adaptor(struct hblk
*h
, word dummy
);
202 GC_enumerator::GC_enumerator(const char *name
)
205 fp
= fopen (name
, "w");
208 printf ("GC_enumerator failed to open [%s]\n", name
);
211 printf ("GC_enumerator saving summary to [%s]\n", name
);
214 char bytes_name
[strlen(name
) + 10];
215 sprintf (bytes_name
, "%s.bytes", name
);
216 bytes_fd
= open (bytes_name
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0666);
219 printf ("GC_enumerator failed to open [%s]\n", bytes_name
);
222 printf ("GC_enumerator saving heap contents to [%s]\n", bytes_name
);
226 sample format of /proc/self/maps
228 0063b000-00686000 rw-p 001fb000 03:01 81993 /avtrex/bin/dumppropapp
229 00686000-0072e000 rwxp 00000000 00:00 0
231 These are parsed below as:
232 start -end xxxx xxxxxxxx a:b xxxxxxxxxxxxxxx
238 GC_enumerator::print_address_map()
243 fprintf(fp
, "---------- Begin address map ----------\n");
245 fm
= fopen("/proc/self/maps", "r");
248 if (0 == strerror_r (errno
, buffer
, sizeof buffer
))
253 while (fgets (buffer
, sizeof buffer
, fm
) != NULL
)
256 char *dash
= strchr(buffer
, '-');
257 char *colon
= strchr(buffer
, ':');
258 if (dash
&& colon
&& ((ptrdiff_t)strlen(buffer
) > (colon
- buffer
) + 2))
261 unsigned long start
= strtoul(buffer
, NULL
, 16);
262 unsigned long end
= strtoul(dash
+ 1, &endp
, 16);
263 unsigned long a
= strtoul(colon
- 2, NULL
, 16);
264 unsigned long b
= strtoul(colon
+ 1, NULL
, 16);
265 // If it is an anonymous mapping 00:00 and both readable
266 // and writeable then dump the contents of the mapping
267 // to the bytes file. Each block has a header of three
269 // 0 - The number sizeof(unsigned long) to detect endianness and
271 // 1 - The offset in VM.
272 // 2 - The Length in bytes.
273 // Followed by the bytes.
274 if (!a
&& !b
&& endp
< colon
&& 'r' == endp
[1] && 'w' == endp
[2])
276 unsigned long t
= sizeof(unsigned long);
277 write(bytes_fd
, (void*)&t
, sizeof(t
));
278 write(bytes_fd
, (void*)&start
, sizeof(start
));
280 write(bytes_fd
, (void*)&t
, sizeof(t
));
281 write(bytes_fd
, (void*)start
, (end
- start
));
287 fprintf(fp
, "---------- End address map ----------\n");
292 GC_enumerator::enumerate()
295 fprintf(fp
, "---------- Begin object map ----------\n");
298 GC_apply_to_all_blocks(enumerate_callback_adaptor
,
299 (word
)(void*)(this));
300 fprintf(fp
, "---------- End object map ----------\n");
303 GC_print_debug_info_file(fp
);
305 GC_print_hblkfreelist_file(fp
);
315 GC_enumerator::enumerate_callback_adaptor(struct hblk
*h
,
318 GC_enumerator
* pinfo
= (GC_enumerator
*)dummy
;
319 pinfo
->enumerate_callback(h
);
323 GC_enumerator::enumerate_callback(struct hblk
*h
)
326 size_t bytes
= WORDS_TO_BYTES(hhdr
->hb_sz
);
329 for (i
= 0; i
== 0 || (i
+ bytes
<= HBLKSIZE
); i
+= bytes
)
331 int inUse
= mark_bit_from_hdr(hhdr
,BYTES_TO_WORDS(i
)); // in use
332 char *ptr
= (char*)h
+i
; // address
333 int kind
= hhdr
->hb_obj_kind
; // kind
336 if (kind
== GC_gcj_kind
337 || kind
== GC_gcj_debug_kind
338 || kind
== GC_gcj_debug_kind
+1)
340 void* v
= *(void **)ptr
;
344 data
= *(void **)(ptr
+ sizeof(void*));
348 fprintf (fp
, "used = %d, ptr = %#lx, size = %zd, kind = %d, "
349 "klass = %#lx, data = %#lx\n",
350 inUse
, (unsigned long)ptr
, bytes
, kind
,
351 (unsigned long)klass
, (unsigned long)data
);
356 * Fill in a char[] with low bytes of the string characters. These
357 * methods may be called while an OutOfMemoryError is being thrown, so
358 * we cannot call nice java methods to get the encoding of the string.
361 J2A(::java::lang::String
* str
, char *dst
)
363 jchar
* pchars
= JvGetStringChars(str
);
364 jint len
= str
->length();
366 for (i
=0; i
<len
; i
++)
367 dst
[i
] = (char)pchars
[i
];
372 ::gnu::gcj::util::GCInfo::dump0 (::java::lang::String
* name
)
374 char n
[name
->length() + 1];
377 char temp
[name
->length() + 20];
378 sprintf(temp
, "%s%03d", n
, GC_dump_count
++);
379 FILE* fp
= fopen(temp
, "w");
381 GC_print_debug_info_file(fp
);
387 ::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String
* name
)
389 char n
[name
->length() + 1];
391 char temp
[name
->length() + 20];
392 sprintf(temp
, "%s%03d", n
, GC_dump_count
++);
394 GC_enumerator
x(temp
);
398 static char *oomDumpName
= NULL
;
401 nomem_handler(size_t size
)
405 char temp
[strlen(oomDumpName
) + 20];
406 sprintf(temp
, "%s%03d", temp
, GC_dump_count
++);
407 printf("nomem_handler(%zd) called\n", size
);
409 GC_enumerator
x(temp
);
417 ::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String
* name
)
419 char *oldName
= oomDumpName
;
426 char *n
= (char *)malloc(name
->length() + 1);
430 GC_oom_fn
= nomem_handler
;
433 #else // HAVE_PROC_SELF_MAPS
436 ::gnu::gcj::util::GCInfo::dump0 (::java::lang::String
* name
)
438 // Do nothing if dumping not supported.
442 ::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String
* name
)
444 // Do nothing if dumping not supported.
448 ::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String
* name
)
450 // Do nothing if dumping not supported.
453 #endif // HAVE_PROC_SELF_MAPS