blob: f944ae2458609920c67d7dd7d1c3a5c043cc519e [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * - Neither the name of Sun Microsystems nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32/* Functionality for checking hprof format=b output. */
33
34/* ONLY used with logflags=4. */
35
36/* Verifies and write a verbose textual version of a format=b file.
37 * Textual output file is gdata->checkfilename, fd is gdata->check_fd.
38 * Buffer is in gdata too, see gdata->check* variables.
39 * Could probably be isolated to a separate library or utility.
40 */
41
42#include "hprof.h"
43
44typedef TableIndex HprofId;
45
46#include "hprof_b_spec.h"
47
48static int type_size[ /*HprofType*/ ] = HPROF_TYPE_SIZES;
49
50/* For map from HPROF_UTF8 to a string */
51typedef struct UmapInfo {
52 char *str;
53} UmapInfo;
54
55/* Field information */
56typedef struct Finfo {
57 HprofId id;
58 HprofType ty;
59} Finfo;
60
61/* Class information map from class ID (ClassIndex) to class information */
62typedef struct CmapInfo {
63 int max_finfo;
64 int n_finfo;
65 Finfo *finfo;
66 int inst_size;
67 HprofId sup;
68} CmapInfo;
69
70/* Read raw bytes from the file image, update the pointer */
71static void
72read_raw(unsigned char **pp, unsigned char *buf, int len)
73{
74 while ( len > 0 ) {
75 *buf = **pp;
76 buf++;
77 (*pp)++;
78 len--;
79 }
80}
81
82/* Read various sized elements, properly converted from big to right endian.
83 * File will contain big endian format.
84 */
85static unsigned
86read_u1(unsigned char **pp)
87{
88 unsigned char b;
89
90 read_raw(pp, &b, 1);
91 return b;
92}
93static unsigned
94read_u2(unsigned char **pp)
95{
96 unsigned short s;
97
98 read_raw(pp, (void*)&s, 2);
99 return md_htons(s);
100}
101static unsigned
102read_u4(unsigned char **pp)
103{
104 unsigned int u;
105
106 read_raw(pp, (void*)&u, 4);
107 return md_htonl(u);
108}
109static jlong
110read_u8(unsigned char **pp)
111{
112 unsigned int high;
113 unsigned int low;
114 jlong x;
115
116 high = read_u4(pp);
117 low = read_u4(pp);
118 x = high;
119 x = (x << 32) | low;
120 return x;
121}
122static HprofId
123read_id(unsigned char **pp)
124{
125 return (HprofId)read_u4(pp);
126}
127
128/* System error routine */
129static void
130system_error(const char *system_call, int rc, int errnum)
131{
132 char buf[256];
133 char details[256];
134
135 details[0] = 0;
136 if ( errnum != 0 ) {
137 md_system_error(details, (int)sizeof(details));
138 } else if ( rc >= 0 ) {
139 (void)strcpy(details,"Only part of buffer processed");
140 }
141 if ( details[0] == 0 ) {
142 (void)strcpy(details,"Unknown system error condition");
143 }
144 (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
145 system_call, details);
146 HPROF_ERROR(JNI_TRUE, buf);
147}
148
149/* Write to a fd */
150static void
151system_write(int fd, void *buf, int len)
152{
153 int res;
154
155 HPROF_ASSERT(fd>=0);
156 res = md_write(fd, buf, len);
157 if (res < 0 || res!=len) {
158 system_error("write", res, errno);
159 }
160}
161
162/* Flush check buffer */
163static void
164check_flush(void)
165{
166 if ( gdata->check_fd < 0 ) {
167 return;
168 }
169 if (gdata->check_buffer_index) {
170 system_write(gdata->check_fd, gdata->check_buffer, gdata->check_buffer_index);
171 gdata->check_buffer_index = 0;
172 }
173}
174
175/* Read out a given typed element */
176static jvalue
177read_val(unsigned char **pp, HprofType ty)
178{
179 jvalue val;
180 static jvalue empty_val;
181
182 val = empty_val;
183 switch ( ty ) {
184 case 0:
185 case HPROF_ARRAY_OBJECT:
186 case HPROF_NORMAL_OBJECT:
187 val.i = read_id(pp);
188 break;
189 case HPROF_BYTE:
190 case HPROF_BOOLEAN:
191 val.b = read_u1(pp);
192 break;
193 case HPROF_CHAR:
194 case HPROF_SHORT:
195 val.s = read_u2(pp);
196 break;
197 case HPROF_FLOAT:
198 case HPROF_INT:
199 val.i = read_u4(pp);
200 break;
201 case HPROF_DOUBLE:
202 case HPROF_LONG:
203 val.j = read_u8(pp);
204 break;
205 default:
206 HPROF_ERROR(JNI_TRUE, "bad type number");
207 break;
208 }
209 return val;
210}
211
212/* Move arbitrary byte stream into gdata->check_fd */
213static void
214check_raw(void *buf, int len)
215{
216 if ( gdata->check_fd < 0 ) {
217 return;
218 }
219
220 if ( len <= 0 ) {
221 return;
222 }
223
224 if (gdata->check_buffer_index + len > gdata->check_buffer_size) {
225 check_flush();
226 if (len > gdata->check_buffer_size) {
227 system_write(gdata->check_fd, buf, len);
228 return;
229 }
230 }
231 (void)memcpy(gdata->check_buffer + gdata->check_buffer_index, buf, len);
232 gdata->check_buffer_index += len;
233}
234
235/* Printf for gdata->check_fd */
236static void
237check_printf(char *fmt, ...)
238{
239 char buf[1024];
240 va_list args;
241
242 if ( gdata->check_fd < 0 ) {
243 return;
244 }
245
246 va_start(args, fmt);
247 (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
248 buf[sizeof(buf)-1] = 0;
249 check_raw(buf, (int)strlen(buf));
250 va_end(args);
251}
252
253/* Printf of an element for gdata->check_fd */
254static void
255check_printf_val(HprofType ty, jvalue val, int long_form)
256{
257 jint low;
258 jint high;
259
260 switch ( ty ) {
261 case HPROF_ARRAY_OBJECT:
262 check_printf("0x%08x", val.i);
263 break;
264 case HPROF_NORMAL_OBJECT:
265 check_printf("0x%08x", val.i);
266 break;
267 case HPROF_BOOLEAN:
268 check_printf("0x%02x", val.b);
269 break;
270 case HPROF_CHAR:
271 if ( long_form ) {
272 if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) {
273 check_printf("0x%04x", val.s);
274 } else {
275 check_printf("0x%04x(%c)", val.s, val.s);
276 }
277 } else {
278 if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) {
279 check_printf("\\u%04x", val.s);
280 } else {
281 check_printf("%c", val.s);
282 }
283 }
284 break;
285 case HPROF_FLOAT:
286 low = jlong_low(val.j);
287 check_printf("0x%08x(%f)", low, (double)val.f);
288 break;
289 case HPROF_DOUBLE:
290 high = jlong_high(val.j);
291 low = jlong_low(val.j);
292 check_printf("0x%08x%08x(%f)", high, low, val.d);
293 break;
294 case HPROF_BYTE:
295 check_printf("0x%02x", val.b);
296 break;
297 case HPROF_SHORT:
298 check_printf("0x%04x", val.s);
299 break;
300 case HPROF_INT:
301 check_printf("0x%08x", val.i);
302 break;
303 case HPROF_LONG:
304 high = jlong_high(val.j);
305 low = jlong_low(val.j);
306 check_printf("0x%08x%08x", high, low);
307 break;
308 }
309}
310
311/* Printf of a string for gdata->check_fd */
312static void
313check_printf_str(char *str)
314{
315 int len;
316 int i;
317
318 if ( str == NULL ) {
319 check_printf("<null>");
320 }
321 check_printf("\"");
322 len = (int)strlen(str);
323 for (i = 0; i < len; i++) {
324 unsigned char c;
325 c = str[i];
326 if ( isprint(c) ) {
327 check_printf("%c", c);
328 } else {
329 check_printf("\\x%02x", c);
330 }
331 }
332 check_printf("\"");
333}
334
335/* Printf of a utf8 id for gdata->check_fd */
336static void
337check_print_utf8(struct LookupTable *utab, char *prefix, HprofId id)
338{
339 TableIndex uindex;
340
341 if ( id == 0 ) {
342 check_printf("%s0x%x", prefix, id);
343 } else {
344 uindex = table_find_entry(utab, &id, sizeof(id));
345 if ( uindex == 0 ) {
346 check_printf("%s0x%x", prefix, id);
347 } else {
348 UmapInfo *umap;
349
350 umap = (UmapInfo*)table_get_info(utab, uindex);
351 HPROF_ASSERT(umap!=NULL);
352 HPROF_ASSERT(umap->str!=NULL);
353 check_printf("%s0x%x->", prefix, id);
354 check_printf_str(umap->str);
355 }
356 }
357}
358
359/* Add a instance field information to this cmap. */
360static void
361add_inst_field_to_cmap(CmapInfo *cmap, HprofId id, HprofType ty)
362{
363 int i;
364
365 HPROF_ASSERT(cmap!=NULL);
366 i = cmap->n_finfo++;
367 if ( i+1 >= cmap->max_finfo ) {
368 int osize;
369 Finfo *new_finfo;
370
371 osize = cmap->max_finfo;
372 cmap->max_finfo += 12;
373 new_finfo = (Finfo*)HPROF_MALLOC(cmap->max_finfo*(int)sizeof(Finfo));
374 (void)memset(new_finfo,0,cmap->max_finfo*(int)sizeof(Finfo));
375 if ( i == 0 ) {
376 cmap->finfo = new_finfo;
377 } else {
378 (void)memcpy(new_finfo,cmap->finfo,osize*(int)sizeof(Finfo));
379 HPROF_FREE(cmap->finfo);
380 cmap->finfo = new_finfo;
381 }
382 }
383 cmap->finfo[i].id = id;
384 cmap->finfo[i].ty = ty;
385}
386
387/* LookupTable callback for cmap entry cleanup */
388static void
389cmap_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
390{
391 CmapInfo *cmap = info;
392
393 if ( cmap == NULL ) {
394 return;
395 }
396 if ( cmap->finfo != NULL ) {
397 HPROF_FREE(cmap->finfo);
398 cmap->finfo = NULL;
399 }
400}
401
402/* Case label for a switch on hprof heap dump elements */
403#define CASE_HEAP(name) case name: label = #name;
404
405/* Given the heap dump data and the utf8 map, check/write the heap dump. */
406static int
407check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes)
408{
409 int nrecords;
410 unsigned char *p;
411 unsigned char *psave;
412 struct LookupTable *ctab;
413 CmapInfo cmap;
414 char *label;
415 unsigned tag;
416 HprofType ty;
417 HprofId id, id2, fr, sup;
418 int num_elements;
419 int num_bytes;
420 SerialNumber trace_serial_num;
421 SerialNumber thread_serial_num;
422 int npos;
423 int i;
424 int inst_size;
425
426 ctab = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo));
427
428 /* First pass over heap records just fills in the CmapInfo table */
429 nrecords = 0;
430 p = pstart;
431 while ( p < (pstart+nbytes) ) {
432 nrecords++;
433 /*LINTED*/
434 npos = (int)(p - pstart);
435 tag = read_u1(&p);
436 switch ( tag ) {
437 CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
438 id = read_id(&p);
439 break;
440 CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
441 id = read_id(&p);
442 id2 = read_id(&p);
443 break;
444 CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
445 id = read_id(&p);
446 thread_serial_num = read_u4(&p);
447 fr = read_u4(&p);
448 break;
449 CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
450 id = read_id(&p);
451 thread_serial_num = read_u4(&p);
452 fr = read_u4(&p);
453 break;
454 CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
455 id = read_id(&p);
456 thread_serial_num = read_u4(&p);
457 break;
458 CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
459 id = read_id(&p);
460 break;
461 CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
462 id = read_id(&p);
463 thread_serial_num = read_u4(&p);
464 break;
465 CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
466 id = read_id(&p);
467 break;
468 CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
469 id = read_id(&p);
470 thread_serial_num = read_u4(&p);
471 trace_serial_num = read_u4(&p);
472 break;
473 CASE_HEAP(HPROF_GC_CLASS_DUMP)
474 (void)memset((void*)&cmap, 0, sizeof(cmap));
475 id = read_id(&p);
476 trace_serial_num = read_u4(&p);
477 {
478 HprofId ld, si, pr, re1, re2;
479
480 sup = read_id(&p);
481 ld = read_id(&p);
482 si = read_id(&p);
483 pr = read_id(&p);
484 re1 = read_id(&p);
485 re2 = read_id(&p);
486 cmap.sup = sup;
487 }
488 inst_size = read_u4(&p);
489 cmap.inst_size = inst_size;
490 num_elements = read_u2(&p);
491 for(i=0; i<num_elements; i++) {
492 (void)read_u2(&p);
493 ty = read_u1(&p);
494 (void)read_val(&p, ty);
495 }
496 num_elements = read_u2(&p);
497 for(i=0; i<num_elements; i++) {
498 (void)read_id(&p);
499 ty = read_u1(&p);
500 (void)read_val(&p, ty);
501 }
502 num_elements = read_u2(&p);
503 for(i=0; i<num_elements; i++) {
504 HprofType ty;
505 HprofId id;
506
507 id = read_id(&p);
508 ty = read_u1(&p);
509 add_inst_field_to_cmap(&cmap, id, ty);
510 }
511 (void)table_create_entry(ctab, &id, sizeof(id), &cmap);
512 break;
513 CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
514 id = read_id(&p);
515 trace_serial_num = read_u4(&p);
516 id2 = read_id(&p); /* class id */
517 num_bytes = read_u4(&p);
518 p += num_bytes;
519 break;
520 CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
521 id = read_id(&p);
522 trace_serial_num = read_u4(&p);
523 num_elements = read_u4(&p);
524 id2 = read_id(&p);
525 p += num_elements*(int)sizeof(HprofId);
526 break;
527 CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
528 id = read_id(&p);
529 trace_serial_num = read_u4(&p);
530 num_elements = read_u4(&p);
531 ty = read_u1(&p);
532 p += type_size[ty]*num_elements;
533 break;
534 default:
535 label = "UNKNOWN";
536 check_printf("H#%d@%d %s: ERROR!\n",
537 nrecords, npos, label);
538 HPROF_ERROR(JNI_TRUE, "unknown heap record type");
539 break;
540 }
541 }
542 CHECK_FOR_ERROR(p==pstart+nbytes);
543
544 /* Scan again once we have our cmap */
545 nrecords = 0;
546 p = pstart;
547 while ( p < (pstart+nbytes) ) {
548 nrecords++;
549 /*LINTED*/
550 npos = (int)(p - pstart);
551 tag = read_u1(&p);
552 switch ( tag ) {
553 CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
554 id = read_id(&p);
555 check_printf("H#%d@%d %s: id=0x%x\n",
556 nrecords, npos, label, id);
557 break;
558 CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
559 id = read_id(&p);
560 id2 = read_id(&p);
561 check_printf("H#%d@%d %s: id=0x%x, id2=0x%x\n",
562 nrecords, npos, label, id, id2);
563 break;
564 CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
565 id = read_id(&p);
566 thread_serial_num = read_u4(&p);
567 fr = read_u4(&p);
568 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
569 nrecords, npos, label, id, thread_serial_num, fr);
570 break;
571 CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
572 id = read_id(&p);
573 thread_serial_num = read_u4(&p);
574 fr = read_u4(&p);
575 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
576 nrecords, npos, label, id, thread_serial_num, fr);
577 break;
578 CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
579 id = read_id(&p);
580 thread_serial_num = read_u4(&p);
581 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
582 nrecords, npos, label, id, thread_serial_num);
583 break;
584 CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
585 id = read_id(&p);
586 check_printf("H#%d@%d %s: id=0x%x\n",
587 nrecords, npos, label, id);
588 break;
589 CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
590 id = read_id(&p);
591 thread_serial_num = read_u4(&p);
592 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
593 nrecords, npos, label, id, thread_serial_num);
594 break;
595 CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
596 id = read_id(&p);
597 check_printf("H#%d@%d %s: id=0x%x\n",
598 nrecords, npos, label, id);
599 break;
600 CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
601 id = read_id(&p);
602 thread_serial_num = read_u4(&p);
603 trace_serial_num = read_u4(&p);
604 CHECK_TRACE_SERIAL_NO(trace_serial_num);
605 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u,"
606 " trace_serial_num=%u\n",
607 nrecords, npos, label, id, thread_serial_num,
608 trace_serial_num);
609 break;
610 CASE_HEAP(HPROF_GC_CLASS_DUMP)
611 id = read_id(&p);
612 trace_serial_num = read_u4(&p);
613 CHECK_TRACE_SERIAL_NO(trace_serial_num);
614 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u\n",
615 nrecords, npos, label, id, trace_serial_num);
616 {
617 HprofId ld, si, pr, re1, re2;
618
619 sup = read_id(&p);
620 ld = read_id(&p);
621 si = read_id(&p);
622 pr = read_id(&p);
623 re1 = read_id(&p);
624 re2 = read_id(&p);
625 check_printf(" su=0x%x, ld=0x%x, si=0x%x,"
626 " pr=0x%x, re1=0x%x, re2=0x%x\n",
627 sup, ld, si, pr, re1, re2);
628 }
629 inst_size = read_u4(&p);
630 check_printf(" instance_size=%d\n", inst_size);
631
632 num_elements = read_u2(&p);
633 for(i=0; i<num_elements; i++) {
634 HprofType ty;
635 unsigned cpi;
636 jvalue val;
637
638 cpi = read_u2(&p);
639 ty = read_u1(&p);
640 val = read_val(&p, ty);
641 check_printf(" constant_pool %d: cpi=%d, ty=%d, val=",
642 i, cpi, ty);
643 check_printf_val(ty, val, 1);
644 check_printf("\n");
645 }
646
647 num_elements = read_u2(&p);
648 check_printf(" static_field_count=%d\n", num_elements);
649 for(i=0; i<num_elements; i++) {
650 HprofType ty;
651 HprofId id;
652 jvalue val;
653
654 id = read_id(&p);
655 ty = read_u1(&p);
656 val = read_val(&p, ty);
657 check_printf(" static field %d: ", i);
658 check_print_utf8(utab, "id=", id);
659 check_printf(", ty=%d, val=", ty);
660 check_printf_val(ty, val, 1);
661 check_printf("\n");
662 }
663
664 num_elements = read_u2(&p);
665 check_printf(" instance_field_count=%d\n", num_elements);
666 for(i=0; i<num_elements; i++) {
667 HprofType ty;
668 HprofId id;
669
670 id = read_id(&p);
671 ty = read_u1(&p);
672 check_printf(" instance_field %d: ", i);
673 check_print_utf8(utab, "id=", id);
674 check_printf(", ty=%d\n", ty);
675 }
676 break;
677 CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
678 id = read_id(&p);
679 trace_serial_num = read_u4(&p);
680 CHECK_TRACE_SERIAL_NO(trace_serial_num);
681 id2 = read_id(&p); /* class id */
682 num_bytes = read_u4(&p);
683 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u,"
684 " cid=0x%x, nbytes=%d\n",
685 nrecords, npos, label, id, trace_serial_num,
686 id2, num_bytes);
687 /* This is a packed set of bytes for the instance fields */
688 if ( num_bytes > 0 ) {
689 TableIndex cindex;
690 int ifield;
691 CmapInfo *map;
692
693 cindex = table_find_entry(ctab, &id2, sizeof(id2));
694 HPROF_ASSERT(cindex!=0);
695 map = (CmapInfo*)table_get_info(ctab, cindex);
696 HPROF_ASSERT(map!=NULL);
697 HPROF_ASSERT(num_bytes==map->inst_size);
698
699 psave = p;
700 ifield = 0;
701
702 do {
703 for(i=0;i<map->n_finfo;i++) {
704 HprofType ty;
705 HprofId id;
706 jvalue val;
707
708 ty = map->finfo[i].ty;
709 id = map->finfo[i].id;
710 HPROF_ASSERT(ty!=0);
711 HPROF_ASSERT(id!=0);
712 val = read_val(&p, ty);
713 check_printf(" field %d: ", ifield);
714 check_print_utf8(utab, "id=", id);
715 check_printf(", ty=%d, val=", ty);
716 check_printf_val(ty, val, 1);
717 check_printf("\n");
718 ifield++;
719 }
720 id2 = map->sup;
721 map = NULL;
722 cindex = 0;
723 if ( id2 != 0 ) {
724 cindex = table_find_entry(ctab, &id2, sizeof(id2));
725 HPROF_ASSERT(cindex!=0);
726 map = (CmapInfo*)table_get_info(ctab, cindex);
727 HPROF_ASSERT(map!=NULL);
728 }
729 } while ( map != NULL );
730 HPROF_ASSERT(num_bytes==(p-psave));
731 }
732 break;
733 CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
734 id = read_id(&p);
735 trace_serial_num = read_u4(&p);
736 CHECK_TRACE_SERIAL_NO(trace_serial_num);
737 num_elements = read_u4(&p);
738 id2 = read_id(&p);
739 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n",
740 nrecords, npos, label, id, trace_serial_num, num_elements, id2);
741 for(i=0; i<num_elements; i++) {
742 HprofId id;
743
744 id = read_id(&p);
745 check_printf(" [%d]: id=0x%x\n", i, id);
746 }
747 break;
748 CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
749 id = read_id(&p);
750 trace_serial_num = read_u4(&p);
751 CHECK_TRACE_SERIAL_NO(trace_serial_num);
752 num_elements = read_u4(&p);
753 ty = read_u1(&p);
754 psave = p;
755 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, "
756 "nelems=%d, ty=%d\n",
757 nrecords, npos, label, id, trace_serial_num, num_elements, ty);
758 HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(ty));
759 if ( num_elements > 0 ) {
760 int count;
761 int long_form;
762 int max_count;
763 char *quote;
764
765 quote = "";
766 long_form = 1;
767 max_count = 8;
768 count = 0;
769 switch ( ty ) {
770 case HPROF_CHAR:
771 long_form = 0;
772 max_count = 72;
773 quote = "\"";
774 /*FALLTHRU*/
775 case HPROF_INT:
776 case HPROF_DOUBLE:
777 case HPROF_LONG:
778 case HPROF_BYTE:
779 case HPROF_BOOLEAN:
780 case HPROF_SHORT:
781 case HPROF_FLOAT:
782 check_printf(" val=%s", quote);
783 for(i=0; i<num_elements; i++) {
784 jvalue val;
785
786 if ( i > 0 && count == 0 ) {
787 check_printf(" %s", quote);
788 }
789 val = read_val(&p, ty);
790 check_printf_val(ty, val, long_form);
791 count += 1;
792 if ( count >= max_count ) {
793 check_printf("\"\n");
794 count = 0;
795 }
796 }
797 if ( count != 0 ) {
798 check_printf("%s\n", quote);
799 }
800 break;
801 }
802 }
803 HPROF_ASSERT(type_size[ty]*num_elements==(p-psave));
804 break;
805 default:
806 label = "UNKNOWN";
807 check_printf("H#%d@%d %s: ERROR!\n",
808 nrecords, npos, label);
809 HPROF_ERROR(JNI_TRUE, "unknown heap record type");
810 break;
811 }
812 }
813 CHECK_FOR_ERROR(p==pstart+nbytes);
814
815 table_cleanup(ctab, &cmap_cleanup, NULL);
816
817 return nrecords;
818}
819
820/* LookupTable cleanup callback for utab */
821static void
822utab_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
823{
824 UmapInfo *umap = info;
825
826 if ( umap == NULL ) {
827 return;
828 }
829 if ( umap->str != NULL ) {
830 HPROF_FREE(umap->str);
831 umap->str = NULL;
832 }
833}
834
835/* Check all the heap tags in a heap dump */
836static int
837check_tags(unsigned char *pstart, int nbytes)
838{
839 unsigned char *p;
840 int nrecord;
841 struct LookupTable *utab;
842 UmapInfo umap;
843
844 check_printf("\nCHECK TAGS: starting\n");
845
846 utab = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo));
847
848 /* Walk the tags, assumes UTF8 tags are defined before used */
849 p = pstart;
850 nrecord = 0;
851 while ( p < (pstart+nbytes) ) {
852 unsigned tag;
853 unsigned size;
854 int nheap_records;
855 int npos;
856 char *label;
857 HprofId id, nm, sg, so, gr, gn;
858 int i, li, num_elements;
859 HprofType ty;
860 SerialNumber trace_serial_num;
861 SerialNumber thread_serial_num;
862 SerialNumber class_serial_num;
863 unsigned flags;
864 unsigned depth;
865 float cutoff;
866 unsigned temp;
867 jint nblive;
868 jint nilive;
869 jlong tbytes;
870 jlong tinsts;
871 jint total_samples;
872 jint trace_count;
873
874 nrecord++;
875 /*LINTED*/
876 npos = (int)(p - pstart);
877 tag = read_u1(&p);
878 (void)read_u4(&p); /* microsecs */
879 size = read_u4(&p);
880 #define CASE_TAG(name) case name: label = #name;
881 switch ( tag ) {
882 CASE_TAG(HPROF_UTF8)
883 CHECK_FOR_ERROR(size>=(int)sizeof(HprofId));
884 id = read_id(&p);
885 check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"",
886 nrecord, npos, label, size, id);
887 num_elements = size-(int)sizeof(HprofId);
888 check_raw(p, num_elements);
889 check_printf("\"\n");
890 /* Create entry in umap */
891 umap.str = HPROF_MALLOC(num_elements+1);
892 (void)strncpy(umap.str, (char*)p, (size_t)num_elements);
893 umap.str[num_elements] = 0;
894 (void)table_create_entry(utab, &id, sizeof(id), &umap);
895 p += num_elements;
896 break;
897 CASE_TAG(HPROF_LOAD_CLASS)
898 CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId));
899 class_serial_num = read_u4(&p);
900 CHECK_CLASS_SERIAL_NO(class_serial_num);
901 id = read_id(&p);
902 trace_serial_num = read_u4(&p);
903 CHECK_TRACE_SERIAL_NO(trace_serial_num);
904 nm = read_id(&p);
905 check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u,"
906 " id=0x%x, trace_serial_num=%u, name_id=0x%x\n",
907 nrecord, npos, label, size, class_serial_num,
908 id, trace_serial_num, nm);
909 break;
910 CASE_TAG(HPROF_UNLOAD_CLASS)
911 CHECK_FOR_ERROR(size==4);
912 class_serial_num = read_u4(&p);
913 CHECK_CLASS_SERIAL_NO(class_serial_num);
914 check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n",
915 nrecord, npos, label, size, class_serial_num);
916 break;
917 CASE_TAG(HPROF_FRAME)
918 CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
919 id = read_id(&p);
920 nm = read_id(&p);
921 sg = read_id(&p);
922 so = read_id(&p);
923 class_serial_num = read_u4(&p);
924 CHECK_CLASS_SERIAL_NO(class_serial_num);
925 li = read_u4(&p);
926 check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size);
927 check_print_utf8(utab, "id=", id);
928 check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x,"
929 " class_serial_num=%u, lineno=%d\n",
930 nm, sg, so, class_serial_num, li);
931 break;
932 CASE_TAG(HPROF_TRACE)
933 CHECK_FOR_ERROR(size>=3*4);
934 trace_serial_num = read_u4(&p);
935 CHECK_TRACE_SERIAL_NO(trace_serial_num);
936 thread_serial_num = read_u4(&p); /* Can be 0 */
937 num_elements = read_u4(&p);
938 check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u,"
939 " thread_serial_num=%u, nelems=%d [",
940 nrecord, npos, label, size,
941 trace_serial_num, thread_serial_num, num_elements);
942 for(i=0; i< num_elements; i++) {
943 check_printf("0x%x,", read_id(&p));
944 }
945 check_printf("]\n");
946 break;
947 CASE_TAG(HPROF_ALLOC_SITES)
948 CHECK_FOR_ERROR(size>=2+4*4+2*8);
949 flags = read_u2(&p);
950 temp = read_u4(&p);
951 cutoff = *((float*)&temp);
952 nblive = read_u4(&p);
953 nilive = read_u4(&p);
954 tbytes = read_u8(&p);
955 tinsts = read_u8(&p);
956 num_elements = read_u4(&p);
957 check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g,"
958 " nblive=%d, nilive=%d, tbytes=(%d,%d),"
959 " tinsts=(%d,%d), num_elements=%d\n",
960 nrecord, npos, label, size,
961 flags, cutoff, nblive, nilive,
962 jlong_high(tbytes), jlong_low(tbytes),
963 jlong_high(tinsts), jlong_low(tinsts),
964 num_elements);
965 for(i=0; i< num_elements; i++) {
966 ty = read_u1(&p);
967 class_serial_num = read_u4(&p);
968 CHECK_CLASS_SERIAL_NO(class_serial_num);
969 trace_serial_num = read_u4(&p);
970 CHECK_TRACE_SERIAL_NO(trace_serial_num);
971 nblive = read_u4(&p);
972 nilive = read_u4(&p);
973 tbytes = read_u4(&p);
974 tinsts = read_u4(&p);
975 check_printf("\t %d: ty=%d, class_serial_num=%u,"
976 " trace_serial_num=%u, nblive=%d, nilive=%d,"
977 " tbytes=%d, tinsts=%d\n",
978 i, ty, class_serial_num, trace_serial_num,
979 nblive, nilive, (jint)tbytes, (jint)tinsts);
980 }
981 break;
982 CASE_TAG(HPROF_HEAP_SUMMARY)
983 CHECK_FOR_ERROR(size==2*4+2*8);
984 nblive = read_u4(&p);
985 nilive = read_u4(&p);
986 tbytes = read_u8(&p);
987 tinsts = read_u8(&p);
988 check_printf("#%d@%d: %s, sz=%d,"
989 " nblive=%d, nilive=%d, tbytes=(%d,%d),"
990 " tinsts=(%d,%d)\n",
991 nrecord, npos, label, size,
992 nblive, nilive,
993 jlong_high(tbytes), jlong_low(tbytes),
994 jlong_high(tinsts), jlong_low(tinsts));
995 break;
996 CASE_TAG(HPROF_START_THREAD)
997 CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
998 thread_serial_num = read_u4(&p);
999 CHECK_THREAD_SERIAL_NO(thread_serial_num);
1000 id = read_id(&p);
1001 trace_serial_num = read_u4(&p);
1002 CHECK_TRACE_SERIAL_NO(trace_serial_num);
1003 nm = read_id(&p);
1004 gr = read_id(&p);
1005 gn = read_id(&p);
1006 check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u,"
1007 " id=0x%x, trace_serial_num=%u, ",
1008 nrecord, npos, label, size,
1009 thread_serial_num, id, trace_serial_num);
1010 check_print_utf8(utab, "nm=", id);
1011 check_printf(" trace_serial_num=%u, nm=0x%x,"
1012 " gr=0x%x, gn=0x%x\n",
1013 trace_serial_num, nm, gr, gn);
1014 break;
1015 CASE_TAG(HPROF_END_THREAD)
1016 CHECK_FOR_ERROR(size==4);
1017 thread_serial_num = read_u4(&p);
1018 CHECK_THREAD_SERIAL_NO(thread_serial_num);
1019 check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n",
1020 nrecord, npos, label, size, thread_serial_num);
1021 break;
1022 CASE_TAG(HPROF_HEAP_DUMP)
1023 check_printf("#%d@%d: BEGIN: %s, sz=%d\n",
1024 nrecord, npos, label, size);
1025 nheap_records = check_heap_tags(utab, p, size);
1026 check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n",
1027 nrecord, npos, label, size, nheap_records);
1028 p += size;
1029 break;
1030 CASE_TAG(HPROF_HEAP_DUMP_SEGMENT) /* 1.0.2 */
1031 check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n",
1032 nrecord, npos, label, size);
1033 nheap_records = check_heap_tags(utab, p, size);
1034 check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n",
1035 nrecord, npos, label, size, nheap_records);
1036 p += size;
1037 break;
1038 CASE_TAG(HPROF_HEAP_DUMP_END) /* 1.0.2 */
1039 check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n",
1040 nrecord, npos, label, size);
1041 break;
1042 CASE_TAG(HPROF_CPU_SAMPLES)
1043 CHECK_FOR_ERROR(size>=2*4);
1044 total_samples = read_u4(&p);
1045 trace_count = read_u4(&p);
1046 check_printf("#%d@%d: %s, sz=%d, total_samples=%d,"
1047 " trace_count=%d\n",
1048 nrecord, npos, label, size,
1049 total_samples, trace_count);
1050 for(i=0; i< trace_count; i++) {
1051 num_elements = read_u4(&p);
1052 trace_serial_num = read_u4(&p);
1053 CHECK_TRACE_SERIAL_NO(trace_serial_num);
1054 check_printf("\t %d: samples=%d, trace_serial_num=%u\n",
1055 trace_serial_num, num_elements);
1056 }
1057 break;
1058 CASE_TAG(HPROF_CONTROL_SETTINGS)
1059 CHECK_FOR_ERROR(size==4+2);
1060 flags = read_u4(&p);
1061 depth = read_u2(&p);
1062 check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n",
1063 nrecord, npos, label, size, flags, depth);
1064 break;
1065 default:
1066 label = "UNKNOWN";
1067 check_printf("#%d@%d: %s, sz=%d\n",
1068 nrecord, npos, label, size);
1069 HPROF_ERROR(JNI_TRUE, "unknown record type");
1070 p += size;
1071 break;
1072 }
1073 CHECK_FOR_ERROR(p<=(pstart+nbytes));
1074 }
1075 check_flush();
1076 CHECK_FOR_ERROR(p==(pstart+nbytes));
1077 table_cleanup(utab, &utab_cleanup, NULL);
1078 return nrecord;
1079}
1080
1081/* Read the entire file into memory */
1082static void *
1083get_binary_file_image(char *filename, int *pnbytes)
1084{
1085 unsigned char *image;
1086 int fd;
1087 jlong nbytes;
1088 int nread;
1089
1090 *pnbytes = 0;
1091 fd = md_open_binary(filename);
1092 CHECK_FOR_ERROR(fd>=0);
1093 if ( (nbytes = md_seek(fd, (jlong)-1)) == (jlong)-1 ) {
1094 HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to end of file");
1095 }
1096 CHECK_FOR_ERROR(((jint)nbytes)>512);
1097 if ( md_seek(fd, (jlong)0) != (jlong)0 ) {
1098 HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to start of file");
1099 }
1100 image = HPROF_MALLOC(((jint)nbytes)+1);
1101 CHECK_FOR_ERROR(image!=NULL);
1102
1103 /* Read the entire file image into memory */
1104 nread = md_read(fd, image, (jint)nbytes);
1105 if ( nread <= 0 ) {
1106 HPROF_ERROR(JNI_TRUE, "System read failed.");
1107 }
1108 CHECK_FOR_ERROR(((jint)nbytes)==nread);
1109 md_close(fd);
1110 *pnbytes = (jint)nbytes;
1111 return image;
1112}
1113
1114/* ------------------------------------------------------------------ */
1115
1116void
1117check_binary_file(char *filename)
1118{
1119 unsigned char *image;
1120 unsigned char *p;
1121 unsigned idsize;
1122 int nbytes;
1123 int nrecords;
1124
1125 image = get_binary_file_image(filename, &nbytes);
1126 if ( image == NULL ) {
1127 check_printf("No file image: %s\n", filename);
1128 return;
1129 }
1130 p = image;
1131 CHECK_FOR_ERROR(strcmp((char*)p, gdata->header)==0);
1132 check_printf("Filename=%s, nbytes=%d, header=\"%s\"\n",
1133 filename, nbytes, p);
1134 p+=((int)strlen((char*)p)+1);
1135 idsize = read_u4(&p);
1136 CHECK_FOR_ERROR(idsize==sizeof(HprofId));
1137 (void)read_u4(&p);
1138 (void)read_u4(&p);
1139 /* LINTED */
1140 nrecords = check_tags(p, nbytes - (int)( p - image ) );
1141 check_printf("#%d total records found in %d bytes\n", nrecords, nbytes);
1142 HPROF_FREE(image);
1143}