00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "hprof.h"
00048
00049 typedef TableIndex HprofId;
00050
00051 #include "hprof_b_spec.h"
00052
00053 static int type_size[ ] = HPROF_TYPE_SIZES;
00054
00055
00056 typedef struct UmapInfo {
00057 char *str;
00058 } UmapInfo;
00059
00060
00061 typedef struct Finfo {
00062 HprofId id;
00063 HprofType ty;
00064 } Finfo;
00065
00066
00067 typedef struct CmapInfo {
00068 int max_finfo;
00069 int n_finfo;
00070 Finfo *finfo;
00071 int inst_size;
00072 HprofId sup;
00073 } CmapInfo;
00074
00075
00076 static void
00077 read_raw(unsigned char **pp, unsigned char *buf, int len)
00078 {
00079 while ( len > 0 ) {
00080 *buf = **pp;
00081 buf++;
00082 (*pp)++;
00083 len--;
00084 }
00085 }
00086
00087
00088
00089
00090 static unsigned
00091 read_u1(unsigned char **pp)
00092 {
00093 unsigned char b;
00094
00095 read_raw(pp, &b, 1);
00096 return b;
00097 }
00098 static unsigned
00099 read_u2(unsigned char **pp)
00100 {
00101 unsigned short s;
00102
00103 read_raw(pp, (void*)&s, 2);
00104 return md_htons(s);
00105 }
00106 static unsigned
00107 read_u4(unsigned char **pp)
00108 {
00109 unsigned int u;
00110
00111 read_raw(pp, (void*)&u, 4);
00112 return md_htonl(u);
00113 }
00114 static jlong
00115 read_u8(unsigned char **pp)
00116 {
00117 unsigned int high;
00118 unsigned int low;
00119 jlong x;
00120
00121 high = read_u4(pp);
00122 low = read_u4(pp);
00123 x = high;
00124 x = (x << 32) | low;
00125 return x;
00126 }
00127 static HprofId
00128 read_id(unsigned char **pp)
00129 {
00130 return (HprofId)read_u4(pp);
00131 }
00132
00133
00134 static void
00135 system_error(const char *system_call, int rc, int errnum)
00136 {
00137 char buf[256];
00138 char details[256];
00139
00140 details[0] = 0;
00141 if ( errnum != 0 ) {
00142 md_system_error(details, (int)sizeof(details));
00143 } else if ( rc >= 0 ) {
00144 (void)strcpy(details,"Only part of buffer processed");
00145 }
00146 if ( details[0] == 0 ) {
00147 (void)strcpy(details,"Unknown system error condition");
00148 }
00149 (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
00150 system_call, details);
00151 HPROF_ERROR(JNI_TRUE, buf);
00152 }
00153
00154
00155 static void
00156 system_write(int fd, void *buf, int len)
00157 {
00158 int res;
00159
00160 HPROF_ASSERT(fd>=0);
00161 res = md_write(fd, buf, len);
00162 if (res < 0 || res!=len) {
00163 system_error("write", res, errno);
00164 }
00165 }
00166
00167
00168 static void
00169 check_flush(void)
00170 {
00171 if ( gdata->check_fd < 0 ) {
00172 return;
00173 }
00174 if (gdata->check_buffer_index) {
00175 system_write(gdata->check_fd, gdata->check_buffer, gdata->check_buffer_index);
00176 gdata->check_buffer_index = 0;
00177 }
00178 }
00179
00180
00181 static jvalue
00182 read_val(unsigned char **pp, HprofType ty)
00183 {
00184 jvalue val;
00185 static jvalue empty_val;
00186
00187 val = empty_val;
00188 switch ( ty ) {
00189 case 0:
00190 case HPROF_ARRAY_OBJECT:
00191 case HPROF_NORMAL_OBJECT:
00192 val.i = read_id(pp);
00193 break;
00194 case HPROF_BYTE:
00195 case HPROF_BOOLEAN:
00196 val.b = read_u1(pp);
00197 break;
00198 case HPROF_CHAR:
00199 case HPROF_SHORT:
00200 val.s = read_u2(pp);
00201 break;
00202 case HPROF_FLOAT:
00203 case HPROF_INT:
00204 val.i = read_u4(pp);
00205 break;
00206 case HPROF_DOUBLE:
00207 case HPROF_LONG:
00208 val.j = read_u8(pp);
00209 break;
00210 default:
00211 HPROF_ERROR(JNI_TRUE, "bad type number");
00212 break;
00213 }
00214 return val;
00215 }
00216
00217
00218 static void
00219 check_raw(void *buf, int len)
00220 {
00221 if ( gdata->check_fd < 0 ) {
00222 return;
00223 }
00224
00225 if ( len <= 0 ) {
00226 return;
00227 }
00228
00229 if (gdata->check_buffer_index + len > gdata->check_buffer_size) {
00230 check_flush();
00231 if (len > gdata->check_buffer_size) {
00232 system_write(gdata->check_fd, buf, len);
00233 return;
00234 }
00235 }
00236 (void)memcpy(gdata->check_buffer + gdata->check_buffer_index, buf, len);
00237 gdata->check_buffer_index += len;
00238 }
00239
00240
00241 static void
00242 check_printf(char *fmt, ...)
00243 {
00244 char buf[1024];
00245 va_list args;
00246
00247 if ( gdata->check_fd < 0 ) {
00248 return;
00249 }
00250
00251 va_start(args, fmt);
00252 (void)md_vsnprintf(buf, sizeof(buf), fmt, args);
00253 buf[sizeof(buf)-1] = 0;
00254 check_raw(buf, (int)strlen(buf));
00255 va_end(args);
00256 }
00257
00258
00259 static void
00260 check_printf_val(HprofType ty, jvalue val, int long_form)
00261 {
00262 jint low;
00263 jint high;
00264
00265 switch ( ty ) {
00266 case HPROF_ARRAY_OBJECT:
00267 check_printf("0x%08x", val.i);
00268 break;
00269 case HPROF_NORMAL_OBJECT:
00270 check_printf("0x%08x", val.i);
00271 break;
00272 case HPROF_BOOLEAN:
00273 check_printf("0x%02x", val.b);
00274 break;
00275 case HPROF_CHAR:
00276 if ( long_form ) {
00277 if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) {
00278 check_printf("0x%04x", val.s);
00279 } else {
00280 check_printf("0x%04x(%c)", val.s, val.s);
00281 }
00282 } else {
00283 if ( val.s < 0 || val.s > 0x7f || !isprint(val.s) ) {
00284 check_printf("\\u%04x", val.s);
00285 } else {
00286 check_printf("%c", val.s);
00287 }
00288 }
00289 break;
00290 case HPROF_FLOAT:
00291 low = jlong_low(val.j);
00292 check_printf("0x%08x(%f)", low, (double)val.f);
00293 break;
00294 case HPROF_DOUBLE:
00295 high = jlong_high(val.j);
00296 low = jlong_low(val.j);
00297 check_printf("0x%08x%08x(%f)", high, low, val.d);
00298 break;
00299 case HPROF_BYTE:
00300 check_printf("0x%02x", val.b);
00301 break;
00302 case HPROF_SHORT:
00303 check_printf("0x%04x", val.s);
00304 break;
00305 case HPROF_INT:
00306 check_printf("0x%08x", val.i);
00307 break;
00308 case HPROF_LONG:
00309 high = jlong_high(val.j);
00310 low = jlong_low(val.j);
00311 check_printf("0x%08x%08x", high, low);
00312 break;
00313 }
00314 }
00315
00316
00317 static void
00318 check_printf_str(char *str)
00319 {
00320 int len;
00321 int i;
00322
00323 if ( str == NULL ) {
00324 check_printf("<null>");
00325 }
00326 check_printf("\"");
00327 len = (int)strlen(str);
00328 for (i = 0; i < len; i++) {
00329 unsigned char c;
00330 c = str[i];
00331 if ( isprint(c) ) {
00332 check_printf("%c", c);
00333 } else {
00334 check_printf("\\x%02x", c);
00335 }
00336 }
00337 check_printf("\"");
00338 }
00339
00340
00341 static void
00342 check_print_utf8(struct LookupTable *utab, char *prefix, HprofId id)
00343 {
00344 TableIndex uindex;
00345
00346 if ( id == 0 ) {
00347 check_printf("%s0x%x", prefix, id);
00348 } else {
00349 uindex = table_find_entry(utab, &id, sizeof(id));
00350 if ( uindex == 0 ) {
00351 check_printf("%s0x%x", prefix, id);
00352 } else {
00353 UmapInfo *umap;
00354
00355 umap = (UmapInfo*)table_get_info(utab, uindex);
00356 HPROF_ASSERT(umap!=NULL);
00357 HPROF_ASSERT(umap->str!=NULL);
00358 check_printf("%s0x%x->", prefix, id);
00359 check_printf_str(umap->str);
00360 }
00361 }
00362 }
00363
00364
00365 static void
00366 add_inst_field_to_cmap(CmapInfo *cmap, HprofId id, HprofType ty)
00367 {
00368 int i;
00369
00370 HPROF_ASSERT(cmap!=NULL);
00371 i = cmap->n_finfo++;
00372 if ( i+1 >= cmap->max_finfo ) {
00373 int osize;
00374 Finfo *new_finfo;
00375
00376 osize = cmap->max_finfo;
00377 cmap->max_finfo += 12;
00378 new_finfo = (Finfo*)HPROF_MALLOC(cmap->max_finfo*(int)sizeof(Finfo));
00379 (void)memset(new_finfo,0,cmap->max_finfo*(int)sizeof(Finfo));
00380 if ( i == 0 ) {
00381 cmap->finfo = new_finfo;
00382 } else {
00383 (void)memcpy(new_finfo,cmap->finfo,osize*(int)sizeof(Finfo));
00384 HPROF_FREE(cmap->finfo);
00385 cmap->finfo = new_finfo;
00386 }
00387 }
00388 cmap->finfo[i].id = id;
00389 cmap->finfo[i].ty = ty;
00390 }
00391
00392
00393 static void
00394 cmap_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
00395 {
00396 CmapInfo *cmap = info;
00397
00398 if ( cmap == NULL ) {
00399 return;
00400 }
00401 if ( cmap->finfo != NULL ) {
00402 HPROF_FREE(cmap->finfo);
00403 cmap->finfo = NULL;
00404 }
00405 }
00406
00407
00408 #define CASE_HEAP(name) case name: label = #name;
00409
00410
00411 static int
00412 check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes)
00413 {
00414 int nrecords;
00415 unsigned char *p;
00416 unsigned char *psave;
00417 struct LookupTable *ctab;
00418 CmapInfo cmap;
00419 char *label;
00420 unsigned tag;
00421 HprofType ty;
00422 HprofId id, id2, fr, sup;
00423 int num_elements;
00424 int num_bytes;
00425 SerialNumber trace_serial_num;
00426 SerialNumber thread_serial_num;
00427 int npos;
00428 int i;
00429 int inst_size;
00430
00431 ctab = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo));
00432
00433
00434 nrecords = 0;
00435 p = pstart;
00436 while ( p < (pstart+nbytes) ) {
00437 nrecords++;
00438
00439 npos = (int)(p - pstart);
00440 tag = read_u1(&p);
00441 switch ( tag ) {
00442 CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
00443 id = read_id(&p);
00444 break;
00445 CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
00446 id = read_id(&p);
00447 id2 = read_id(&p);
00448 break;
00449 CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
00450 id = read_id(&p);
00451 thread_serial_num = read_u4(&p);
00452 fr = read_u4(&p);
00453 break;
00454 CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
00455 id = read_id(&p);
00456 thread_serial_num = read_u4(&p);
00457 fr = read_u4(&p);
00458 break;
00459 CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
00460 id = read_id(&p);
00461 thread_serial_num = read_u4(&p);
00462 break;
00463 CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
00464 id = read_id(&p);
00465 break;
00466 CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
00467 id = read_id(&p);
00468 thread_serial_num = read_u4(&p);
00469 break;
00470 CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
00471 id = read_id(&p);
00472 break;
00473 CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
00474 id = read_id(&p);
00475 thread_serial_num = read_u4(&p);
00476 trace_serial_num = read_u4(&p);
00477 break;
00478 CASE_HEAP(HPROF_GC_CLASS_DUMP)
00479 (void)memset((void*)&cmap, 0, sizeof(cmap));
00480 id = read_id(&p);
00481 trace_serial_num = read_u4(&p);
00482 {
00483 HprofId ld, si, pr, re1, re2;
00484
00485 sup = read_id(&p);
00486 ld = read_id(&p);
00487 si = read_id(&p);
00488 pr = read_id(&p);
00489 re1 = read_id(&p);
00490 re2 = read_id(&p);
00491 cmap.sup = sup;
00492 }
00493 inst_size = read_u4(&p);
00494 cmap.inst_size = inst_size;
00495 num_elements = read_u2(&p);
00496 for(i=0; i<num_elements; i++) {
00497 (void)read_u2(&p);
00498 ty = read_u1(&p);
00499 (void)read_val(&p, ty);
00500 }
00501 num_elements = read_u2(&p);
00502 for(i=0; i<num_elements; i++) {
00503 (void)read_id(&p);
00504 ty = read_u1(&p);
00505 (void)read_val(&p, ty);
00506 }
00507 num_elements = read_u2(&p);
00508 for(i=0; i<num_elements; i++) {
00509 HprofType ty;
00510 HprofId id;
00511
00512 id = read_id(&p);
00513 ty = read_u1(&p);
00514 add_inst_field_to_cmap(&cmap, id, ty);
00515 }
00516 (void)table_create_entry(ctab, &id, sizeof(id), &cmap);
00517 break;
00518 CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
00519 id = read_id(&p);
00520 trace_serial_num = read_u4(&p);
00521 id2 = read_id(&p);
00522 num_bytes = read_u4(&p);
00523 p += num_bytes;
00524 break;
00525 CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
00526 id = read_id(&p);
00527 trace_serial_num = read_u4(&p);
00528 num_elements = read_u4(&p);
00529 id2 = read_id(&p);
00530 p += num_elements*(int)sizeof(HprofId);
00531 break;
00532 CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
00533 id = read_id(&p);
00534 trace_serial_num = read_u4(&p);
00535 num_elements = read_u4(&p);
00536 ty = read_u1(&p);
00537 p += type_size[ty]*num_elements;
00538 break;
00539 default:
00540 label = "UNKNOWN";
00541 check_printf("H#%d@%d %s: ERROR!\n",
00542 nrecords, npos, label);
00543 HPROF_ERROR(JNI_TRUE, "unknown heap record type");
00544 break;
00545 }
00546 }
00547 CHECK_FOR_ERROR(p==pstart+nbytes);
00548
00549
00550 nrecords = 0;
00551 p = pstart;
00552 while ( p < (pstart+nbytes) ) {
00553 nrecords++;
00554
00555 npos = (int)(p - pstart);
00556 tag = read_u1(&p);
00557 switch ( tag ) {
00558 CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
00559 id = read_id(&p);
00560 check_printf("H#%d@%d %s: id=0x%x\n",
00561 nrecords, npos, label, id);
00562 break;
00563 CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
00564 id = read_id(&p);
00565 id2 = read_id(&p);
00566 check_printf("H#%d@%d %s: id=0x%x, id2=0x%x\n",
00567 nrecords, npos, label, id, id2);
00568 break;
00569 CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
00570 id = read_id(&p);
00571 thread_serial_num = read_u4(&p);
00572 fr = read_u4(&p);
00573 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
00574 nrecords, npos, label, id, thread_serial_num, fr);
00575 break;
00576 CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
00577 id = read_id(&p);
00578 thread_serial_num = read_u4(&p);
00579 fr = read_u4(&p);
00580 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
00581 nrecords, npos, label, id, thread_serial_num, fr);
00582 break;
00583 CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
00584 id = read_id(&p);
00585 thread_serial_num = read_u4(&p);
00586 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
00587 nrecords, npos, label, id, thread_serial_num);
00588 break;
00589 CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
00590 id = read_id(&p);
00591 check_printf("H#%d@%d %s: id=0x%x\n",
00592 nrecords, npos, label, id);
00593 break;
00594 CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
00595 id = read_id(&p);
00596 thread_serial_num = read_u4(&p);
00597 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
00598 nrecords, npos, label, id, thread_serial_num);
00599 break;
00600 CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
00601 id = read_id(&p);
00602 check_printf("H#%d@%d %s: id=0x%x\n",
00603 nrecords, npos, label, id);
00604 break;
00605 CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
00606 id = read_id(&p);
00607 thread_serial_num = read_u4(&p);
00608 trace_serial_num = read_u4(&p);
00609 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00610 check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u,"
00611 " trace_serial_num=%u\n",
00612 nrecords, npos, label, id, thread_serial_num,
00613 trace_serial_num);
00614 break;
00615 CASE_HEAP(HPROF_GC_CLASS_DUMP)
00616 id = read_id(&p);
00617 trace_serial_num = read_u4(&p);
00618 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00619 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u\n",
00620 nrecords, npos, label, id, trace_serial_num);
00621 {
00622 HprofId ld, si, pr, re1, re2;
00623
00624 sup = read_id(&p);
00625 ld = read_id(&p);
00626 si = read_id(&p);
00627 pr = read_id(&p);
00628 re1 = read_id(&p);
00629 re2 = read_id(&p);
00630 check_printf(" su=0x%x, ld=0x%x, si=0x%x,"
00631 " pr=0x%x, re1=0x%x, re2=0x%x\n",
00632 sup, ld, si, pr, re1, re2);
00633 }
00634 inst_size = read_u4(&p);
00635 check_printf(" instance_size=%d\n", inst_size);
00636
00637 num_elements = read_u2(&p);
00638 for(i=0; i<num_elements; i++) {
00639 HprofType ty;
00640 unsigned cpi;
00641 jvalue val;
00642
00643 cpi = read_u2(&p);
00644 ty = read_u1(&p);
00645 val = read_val(&p, ty);
00646 check_printf(" constant_pool %d: cpi=%d, ty=%d, val=",
00647 i, cpi, ty);
00648 check_printf_val(ty, val, 1);
00649 check_printf("\n");
00650 }
00651
00652 num_elements = read_u2(&p);
00653 check_printf(" static_field_count=%d\n", num_elements);
00654 for(i=0; i<num_elements; i++) {
00655 HprofType ty;
00656 HprofId id;
00657 jvalue val;
00658
00659 id = read_id(&p);
00660 ty = read_u1(&p);
00661 val = read_val(&p, ty);
00662 check_printf(" static field %d: ", i);
00663 check_print_utf8(utab, "id=", id);
00664 check_printf(", ty=%d, val=", ty);
00665 check_printf_val(ty, val, 1);
00666 check_printf("\n");
00667 }
00668
00669 num_elements = read_u2(&p);
00670 check_printf(" instance_field_count=%d\n", num_elements);
00671 for(i=0; i<num_elements; i++) {
00672 HprofType ty;
00673 HprofId id;
00674
00675 id = read_id(&p);
00676 ty = read_u1(&p);
00677 check_printf(" instance_field %d: ", i);
00678 check_print_utf8(utab, "id=", id);
00679 check_printf(", ty=%d\n", ty);
00680 }
00681 break;
00682 CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
00683 id = read_id(&p);
00684 trace_serial_num = read_u4(&p);
00685 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00686 id2 = read_id(&p);
00687 num_bytes = read_u4(&p);
00688 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u,"
00689 " cid=0x%x, nbytes=%d\n",
00690 nrecords, npos, label, id, trace_serial_num,
00691 id2, num_bytes);
00692
00693 if ( num_bytes > 0 ) {
00694 TableIndex cindex;
00695 int ifield;
00696 CmapInfo *map;
00697
00698 cindex = table_find_entry(ctab, &id2, sizeof(id2));
00699 HPROF_ASSERT(cindex!=0);
00700 map = (CmapInfo*)table_get_info(ctab, cindex);
00701 HPROF_ASSERT(map!=NULL);
00702 HPROF_ASSERT(num_bytes==map->inst_size);
00703
00704 psave = p;
00705 ifield = 0;
00706
00707 do {
00708 for(i=0;i<map->n_finfo;i++) {
00709 HprofType ty;
00710 HprofId id;
00711 jvalue val;
00712
00713 ty = map->finfo[i].ty;
00714 id = map->finfo[i].id;
00715 HPROF_ASSERT(ty!=0);
00716 HPROF_ASSERT(id!=0);
00717 val = read_val(&p, ty);
00718 check_printf(" field %d: ", ifield);
00719 check_print_utf8(utab, "id=", id);
00720 check_printf(", ty=%d, val=", ty);
00721 check_printf_val(ty, val, 1);
00722 check_printf("\n");
00723 ifield++;
00724 }
00725 id2 = map->sup;
00726 map = NULL;
00727 cindex = 0;
00728 if ( id2 != 0 ) {
00729 cindex = table_find_entry(ctab, &id2, sizeof(id2));
00730 HPROF_ASSERT(cindex!=0);
00731 map = (CmapInfo*)table_get_info(ctab, cindex);
00732 HPROF_ASSERT(map!=NULL);
00733 }
00734 } while ( map != NULL );
00735 HPROF_ASSERT(num_bytes==(p-psave));
00736 }
00737 break;
00738 CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
00739 id = read_id(&p);
00740 trace_serial_num = read_u4(&p);
00741 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00742 num_elements = read_u4(&p);
00743 id2 = read_id(&p);
00744 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n",
00745 nrecords, npos, label, id, trace_serial_num, num_elements, id2);
00746 for(i=0; i<num_elements; i++) {
00747 HprofId id;
00748
00749 id = read_id(&p);
00750 check_printf(" [%d]: id=0x%x\n", i, id);
00751 }
00752 break;
00753 CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
00754 id = read_id(&p);
00755 trace_serial_num = read_u4(&p);
00756 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00757 num_elements = read_u4(&p);
00758 ty = read_u1(&p);
00759 psave = p;
00760 check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, "
00761 "nelems=%d, ty=%d\n",
00762 nrecords, npos, label, id, trace_serial_num, num_elements, ty);
00763 HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(ty));
00764 if ( num_elements > 0 ) {
00765 int count;
00766 int long_form;
00767 int max_count;
00768 char *quote;
00769
00770 quote = "";
00771 long_form = 1;
00772 max_count = 8;
00773 count = 0;
00774 switch ( ty ) {
00775 case HPROF_CHAR:
00776 long_form = 0;
00777 max_count = 72;
00778 quote = "\"";
00779
00780 case HPROF_INT:
00781 case HPROF_DOUBLE:
00782 case HPROF_LONG:
00783 case HPROF_BYTE:
00784 case HPROF_BOOLEAN:
00785 case HPROF_SHORT:
00786 case HPROF_FLOAT:
00787 check_printf(" val=%s", quote);
00788 for(i=0; i<num_elements; i++) {
00789 jvalue val;
00790
00791 if ( i > 0 && count == 0 ) {
00792 check_printf(" %s", quote);
00793 }
00794 val = read_val(&p, ty);
00795 check_printf_val(ty, val, long_form);
00796 count += 1;
00797 if ( count >= max_count ) {
00798 check_printf("\"\n");
00799 count = 0;
00800 }
00801 }
00802 if ( count != 0 ) {
00803 check_printf("%s\n", quote);
00804 }
00805 break;
00806 }
00807 }
00808 HPROF_ASSERT(type_size[ty]*num_elements==(p-psave));
00809 break;
00810 default:
00811 label = "UNKNOWN";
00812 check_printf("H#%d@%d %s: ERROR!\n",
00813 nrecords, npos, label);
00814 HPROF_ERROR(JNI_TRUE, "unknown heap record type");
00815 break;
00816 }
00817 }
00818 CHECK_FOR_ERROR(p==pstart+nbytes);
00819
00820 table_cleanup(ctab, &cmap_cleanup, NULL);
00821
00822 return nrecords;
00823 }
00824
00825
00826 static void
00827 utab_cleanup(TableIndex i, void *key_ptr, int key_len, void*info, void*data)
00828 {
00829 UmapInfo *umap = info;
00830
00831 if ( umap == NULL ) {
00832 return;
00833 }
00834 if ( umap->str != NULL ) {
00835 HPROF_FREE(umap->str);
00836 umap->str = NULL;
00837 }
00838 }
00839
00840
00841 static int
00842 check_tags(unsigned char *pstart, int nbytes)
00843 {
00844 unsigned char *p;
00845 int nrecord;
00846 struct LookupTable *utab;
00847 UmapInfo umap;
00848
00849 check_printf("\nCHECK TAGS: starting\n");
00850
00851 utab = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo));
00852
00853
00854 p = pstart;
00855 nrecord = 0;
00856 while ( p < (pstart+nbytes) ) {
00857 unsigned tag;
00858 unsigned size;
00859 int nheap_records;
00860 int npos;
00861 char *label;
00862 HprofId id, nm, sg, so, gr, gn;
00863 int i, li, num_elements;
00864 HprofType ty;
00865 SerialNumber trace_serial_num;
00866 SerialNumber thread_serial_num;
00867 SerialNumber class_serial_num;
00868 unsigned flags;
00869 unsigned depth;
00870 float cutoff;
00871 unsigned temp;
00872 jint nblive;
00873 jint nilive;
00874 jlong tbytes;
00875 jlong tinsts;
00876 jint total_samples;
00877 jint trace_count;
00878
00879 nrecord++;
00880
00881 npos = (int)(p - pstart);
00882 tag = read_u1(&p);
00883 (void)read_u4(&p);
00884 size = read_u4(&p);
00885 #define CASE_TAG(name) case name: label = #name;
00886 switch ( tag ) {
00887 CASE_TAG(HPROF_UTF8)
00888 CHECK_FOR_ERROR(size>=(int)sizeof(HprofId));
00889 id = read_id(&p);
00890 check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"",
00891 nrecord, npos, label, size, id);
00892 num_elements = size-(int)sizeof(HprofId);
00893 check_raw(p, num_elements);
00894 check_printf("\"\n");
00895
00896 umap.str = HPROF_MALLOC(num_elements+1);
00897 (void)strncpy(umap.str, (char*)p, (size_t)num_elements);
00898 umap.str[num_elements] = 0;
00899 (void)table_create_entry(utab, &id, sizeof(id), &umap);
00900 p += num_elements;
00901 break;
00902 CASE_TAG(HPROF_LOAD_CLASS)
00903 CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId));
00904 class_serial_num = read_u4(&p);
00905 CHECK_CLASS_SERIAL_NO(class_serial_num);
00906 id = read_id(&p);
00907 trace_serial_num = read_u4(&p);
00908 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00909 nm = read_id(&p);
00910 check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u,"
00911 " id=0x%x, trace_serial_num=%u, name_id=0x%x\n",
00912 nrecord, npos, label, size, class_serial_num,
00913 id, trace_serial_num, nm);
00914 break;
00915 CASE_TAG(HPROF_UNLOAD_CLASS)
00916 CHECK_FOR_ERROR(size==4);
00917 class_serial_num = read_u4(&p);
00918 CHECK_CLASS_SERIAL_NO(class_serial_num);
00919 check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n",
00920 nrecord, npos, label, size, class_serial_num);
00921 break;
00922 CASE_TAG(HPROF_FRAME)
00923 CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
00924 id = read_id(&p);
00925 nm = read_id(&p);
00926 sg = read_id(&p);
00927 so = read_id(&p);
00928 class_serial_num = read_u4(&p);
00929 CHECK_CLASS_SERIAL_NO(class_serial_num);
00930 li = read_u4(&p);
00931 check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size);
00932 check_print_utf8(utab, "id=", id);
00933 check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x,"
00934 " class_serial_num=%u, lineno=%d\n",
00935 nm, sg, so, class_serial_num, li);
00936 break;
00937 CASE_TAG(HPROF_TRACE)
00938 CHECK_FOR_ERROR(size>=3*4);
00939 trace_serial_num = read_u4(&p);
00940 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00941 thread_serial_num = read_u4(&p);
00942 num_elements = read_u4(&p);
00943 check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u,"
00944 " thread_serial_num=%u, nelems=%d [",
00945 nrecord, npos, label, size,
00946 trace_serial_num, thread_serial_num, num_elements);
00947 for(i=0; i< num_elements; i++) {
00948 check_printf("0x%x,", read_id(&p));
00949 }
00950 check_printf("]\n");
00951 break;
00952 CASE_TAG(HPROF_ALLOC_SITES)
00953 CHECK_FOR_ERROR(size>=2+4*4+2*8);
00954 flags = read_u2(&p);
00955 temp = read_u4(&p);
00956 cutoff = *((float*)&temp);
00957 nblive = read_u4(&p);
00958 nilive = read_u4(&p);
00959 tbytes = read_u8(&p);
00960 tinsts = read_u8(&p);
00961 num_elements = read_u4(&p);
00962 check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g,"
00963 " nblive=%d, nilive=%d, tbytes=(%d,%d),"
00964 " tinsts=(%d,%d), num_elements=%d\n",
00965 nrecord, npos, label, size,
00966 flags, cutoff, nblive, nilive,
00967 jlong_high(tbytes), jlong_low(tbytes),
00968 jlong_high(tinsts), jlong_low(tinsts),
00969 num_elements);
00970 for(i=0; i< num_elements; i++) {
00971 ty = read_u1(&p);
00972 class_serial_num = read_u4(&p);
00973 CHECK_CLASS_SERIAL_NO(class_serial_num);
00974 trace_serial_num = read_u4(&p);
00975 CHECK_TRACE_SERIAL_NO(trace_serial_num);
00976 nblive = read_u4(&p);
00977 nilive = read_u4(&p);
00978 tbytes = read_u4(&p);
00979 tinsts = read_u4(&p);
00980 check_printf("\t %d: ty=%d, class_serial_num=%u,"
00981 " trace_serial_num=%u, nblive=%d, nilive=%d,"
00982 " tbytes=%d, tinsts=%d\n",
00983 i, ty, class_serial_num, trace_serial_num,
00984 nblive, nilive, (jint)tbytes, (jint)tinsts);
00985 }
00986 break;
00987 CASE_TAG(HPROF_HEAP_SUMMARY)
00988 CHECK_FOR_ERROR(size==2*4+2*8);
00989 nblive = read_u4(&p);
00990 nilive = read_u4(&p);
00991 tbytes = read_u8(&p);
00992 tinsts = read_u8(&p);
00993 check_printf("#%d@%d: %s, sz=%d,"
00994 " nblive=%d, nilive=%d, tbytes=(%d,%d),"
00995 " tinsts=(%d,%d)\n",
00996 nrecord, npos, label, size,
00997 nblive, nilive,
00998 jlong_high(tbytes), jlong_low(tbytes),
00999 jlong_high(tinsts), jlong_low(tinsts));
01000 break;
01001 CASE_TAG(HPROF_START_THREAD)
01002 CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
01003 thread_serial_num = read_u4(&p);
01004 CHECK_THREAD_SERIAL_NO(thread_serial_num);
01005 id = read_id(&p);
01006 trace_serial_num = read_u4(&p);
01007 CHECK_TRACE_SERIAL_NO(trace_serial_num);
01008 nm = read_id(&p);
01009 gr = read_id(&p);
01010 gn = read_id(&p);
01011 check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u,"
01012 " id=0x%x, trace_serial_num=%u, ",
01013 nrecord, npos, label, size,
01014 thread_serial_num, id, trace_serial_num);
01015 check_print_utf8(utab, "nm=", id);
01016 check_printf(" trace_serial_num=%u, nm=0x%x,"
01017 " gr=0x%x, gn=0x%x\n",
01018 trace_serial_num, nm, gr, gn);
01019 break;
01020 CASE_TAG(HPROF_END_THREAD)
01021 CHECK_FOR_ERROR(size==4);
01022 thread_serial_num = read_u4(&p);
01023 CHECK_THREAD_SERIAL_NO(thread_serial_num);
01024 check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n",
01025 nrecord, npos, label, size, thread_serial_num);
01026 break;
01027 CASE_TAG(HPROF_HEAP_DUMP)
01028 check_printf("#%d@%d: BEGIN: %s, sz=%d\n",
01029 nrecord, npos, label, size);
01030 nheap_records = check_heap_tags(utab, p, size);
01031 check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n",
01032 nrecord, npos, label, size, nheap_records);
01033 p += size;
01034 break;
01035 CASE_TAG(HPROF_HEAP_DUMP_SEGMENT)
01036 check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n",
01037 nrecord, npos, label, size);
01038 nheap_records = check_heap_tags(utab, p, size);
01039 check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n",
01040 nrecord, npos, label, size, nheap_records);
01041 p += size;
01042 break;
01043 CASE_TAG(HPROF_HEAP_DUMP_END)
01044 check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n",
01045 nrecord, npos, label, size);
01046 break;
01047 CASE_TAG(HPROF_CPU_SAMPLES)
01048 CHECK_FOR_ERROR(size>=2*4);
01049 total_samples = read_u4(&p);
01050 trace_count = read_u4(&p);
01051 check_printf("#%d@%d: %s, sz=%d, total_samples=%d,"
01052 " trace_count=%d\n",
01053 nrecord, npos, label, size,
01054 total_samples, trace_count);
01055 for(i=0; i< trace_count; i++) {
01056 num_elements = read_u4(&p);
01057 trace_serial_num = read_u4(&p);
01058 CHECK_TRACE_SERIAL_NO(trace_serial_num);
01059 check_printf("\t %d: samples=%d, trace_serial_num=%u\n",
01060 trace_serial_num, num_elements);
01061 }
01062 break;
01063 CASE_TAG(HPROF_CONTROL_SETTINGS)
01064 CHECK_FOR_ERROR(size==4+2);
01065 flags = read_u4(&p);
01066 depth = read_u2(&p);
01067 check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n",
01068 nrecord, npos, label, size, flags, depth);
01069 break;
01070 default:
01071 label = "UNKNOWN";
01072 check_printf("#%d@%d: %s, sz=%d\n",
01073 nrecord, npos, label, size);
01074 HPROF_ERROR(JNI_TRUE, "unknown record type");
01075 p += size;
01076 break;
01077 }
01078 CHECK_FOR_ERROR(p<=(pstart+nbytes));
01079 }
01080 check_flush();
01081 CHECK_FOR_ERROR(p==(pstart+nbytes));
01082 table_cleanup(utab, &utab_cleanup, NULL);
01083 return nrecord;
01084 }
01085
01086
01087 static void *
01088 get_binary_file_image(char *filename, int *pnbytes)
01089 {
01090 unsigned char *image;
01091 int fd;
01092 jlong nbytes;
01093 int nread;
01094
01095 *pnbytes = 0;
01096 fd = md_open_binary(filename);
01097 CHECK_FOR_ERROR(fd>=0);
01098 if ( (nbytes = md_seek(fd, (jlong)-1)) == (jlong)-1 ) {
01099 HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to end of file");
01100 }
01101 CHECK_FOR_ERROR(((jint)nbytes)>512);
01102 if ( md_seek(fd, (jlong)0) != (jlong)0 ) {
01103 HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to start of file");
01104 }
01105 image = HPROF_MALLOC(((jint)nbytes)+1);
01106 CHECK_FOR_ERROR(image!=NULL);
01107
01108
01109 nread = md_read(fd, image, (jint)nbytes);
01110 if ( nread <= 0 ) {
01111 HPROF_ERROR(JNI_TRUE, "System read failed.");
01112 }
01113 CHECK_FOR_ERROR(((jint)nbytes)==nread);
01114 md_close(fd);
01115 *pnbytes = (jint)nbytes;
01116 return image;
01117 }
01118
01119
01120
01121 void
01122 check_binary_file(char *filename)
01123 {
01124 unsigned char *image;
01125 unsigned char *p;
01126 unsigned idsize;
01127 int nbytes;
01128 int nrecords;
01129
01130 image = get_binary_file_image(filename, &nbytes);
01131 if ( image == NULL ) {
01132 check_printf("No file image: %s\n", filename);
01133 return;
01134 }
01135 p = image;
01136 CHECK_FOR_ERROR(strcmp((char*)p, gdata->header)==0);
01137 check_printf("Filename=%s, nbytes=%d, header=\"%s\"\n",
01138 filename, nbytes, p);
01139 p+=((int)strlen((char*)p)+1);
01140 idsize = read_u4(&p);
01141 CHECK_FOR_ERROR(idsize==sizeof(HprofId));
01142 (void)read_u4(&p);
01143 (void)read_u4(&p);
01144
01145 nrecords = check_tags(p, nbytes - (int)( p - image ) );
01146 check_printf("#%d total records found in %d bytes\n", nrecords, nbytes);
01147 HPROF_FREE(image);
01148 }
01149