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