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