Пример #1
0
/* Read the entire file into memory */
static void *
get_binary_file_image(char *filename, int *pnbytes)
{
    unsigned char *image;
    int            fd;
    jlong          nbytes;
    int            nread;

    *pnbytes = 0;
    fd = md_open_binary(filename);
    CHECK_FOR_ERROR(fd>=0);
    if ( (nbytes = md_seek(fd, (jlong)-1)) == (jlong)-1 ) {
        HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to end of file");
    }
    CHECK_FOR_ERROR(((jint)nbytes)>512);
    if ( md_seek(fd, (jlong)0) != (jlong)0 ) {
        HPROF_ERROR(JNI_TRUE, "Cannot md_seek() to start of file");
    }
    image = HPROF_MALLOC(((jint)nbytes)+1);
    CHECK_FOR_ERROR(image!=NULL);

    /* Read the entire file image into memory */
    nread = md_read(fd, image, (jint)nbytes);
    if ( nread <= 0 ) {
        HPROF_ERROR(JNI_TRUE, "System read failed.");
    }
    CHECK_FOR_ERROR(((jint)nbytes)==nread);
    md_close(fd);
    *pnbytes = (jint)nbytes;
    return image;
}
Пример #2
0
/* Read out a given typed element */
static jvalue
read_val(unsigned char **pp, HprofType ty)
{
    jvalue        val;
    static jvalue empty_val;

    val = empty_val;
    switch ( ty ) {
        case 0:
        case HPROF_ARRAY_OBJECT:
        case HPROF_NORMAL_OBJECT:
            val.i = read_id(pp);
            break;
        case HPROF_BYTE:
        case HPROF_BOOLEAN:
            val.b = read_u1(pp);
            break;
        case HPROF_CHAR:
        case HPROF_SHORT:
            val.s = read_u2(pp);
            break;
        case HPROF_FLOAT:
        case HPROF_INT:
            val.i = read_u4(pp);
            break;
        case HPROF_DOUBLE:
        case HPROF_LONG:
            val.j = read_u8(pp);
            break;
        default:
            HPROF_ERROR(JNI_TRUE, "bad type number");
            break;
    }
    return val;
}
/* Verify field data */
static void
verify_field(RefIndex list, FieldInfo *fields, jvalue *fvalues, int n_fields,
                jint index, jvalue value, jvmtiPrimitiveType primType)
{
    HPROF_ASSERT(fvalues != NULL);
    HPROF_ASSERT(n_fields > 0);
    HPROF_ASSERT(index < n_fields);
    HPROF_ASSERT(index >= 0 );
    if ( primType!=fields[index].primType ) {
        dump_fields(list, fields, fvalues, n_fields);
        debug_message("\nPROBLEM WITH:\n");
        dump_field(fields, fvalues, n_fields, index, value, primType);
        debug_message("\n");
        HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data");
    }
    if ( primType == JVMTI_PRIMITIVE_TYPE_BOOLEAN && 
         ( value.b != 1 && value.b != 0 ) ) {
        dump_fields(list, fields, fvalues, n_fields);
        debug_message("\nPROBLEM WITH:\n");
        dump_field(fields, fvalues, n_fields, index, value, primType);
        debug_message("\n");
        HPROF_ERROR(JNI_FALSE, "Trouble with fields and heap data");
    }
}
Пример #4
0
/* System error routine */
static void
system_error(const char *system_call, int rc, int errnum)
{
    char buf[256];
    char details[256];

    details[0] = 0;
    if ( errnum != 0 ) {
        md_system_error(details, (int)sizeof(details));
    } else if ( rc >= 0 ) {
        (void)strcpy(details,"Only part of buffer processed");
    }
    if ( details[0] == 0 ) {
        (void)strcpy(details,"Unknown system error condition");
    }
    (void)md_snprintf(buf, sizeof(buf), "System %s failed: %s\n",
                            system_call, details);
    HPROF_ERROR(JNI_TRUE, buf);
}
/* Walk all references for an ObjectIndex and construct the hprof INST dump. */
static void
dump_instance(JNIEnv *env, ObjectIndex object_index, RefIndex list)
{
    jvmtiPrimitiveType primType;
    SiteIndex    site_index;
    SerialNumber trace_serial_num;
    RefIndex     index;
    ObjectIndex  class_index;
    jlong        size;
    ClassIndex   cnum;
    char        *sig;
    void        *elements;
    jint         num_elements;
    jint         num_bytes;
    ObjectIndex *values;
    FieldInfo   *fields;
    jvalue      *fvalues;
    jint         n_fields;
    jboolean     skip_fields;
    jint         n_fields_set;
    ObjectKind   kind;
    TraceIndex   trace_index;
    jboolean     is_array;
    jboolean     is_prim_array;

    HPROF_ASSERT(object_index!=0);
    kind        = object_get_kind(object_index);
    if ( kind == OBJECT_CLASS ) {
        return;
    }
    site_index       = object_get_site(object_index);
    HPROF_ASSERT(site_index!=0);
    cnum             = site_get_class_index(site_index);
    HPROF_ASSERT(cnum!=0);
    size             = (jlong)object_get_size(object_index);
    trace_index      = site_get_trace_index(site_index);
    HPROF_ASSERT(trace_index!=0);
    trace_serial_num = trace_get_serial_number(trace_index);
    sig              = string_get(class_get_signature(cnum));
    class_index      = class_get_object_index(cnum);
        
    values       = NULL;
    elements     = NULL;
    num_elements = 0;
    num_bytes    = 0;
    
    n_fields     = 0;
    skip_fields  = JNI_FALSE;
    n_fields_set = 0;
    fields       = NULL;
    fvalues      = NULL;
    
    index      = list;
    
    is_array      = JNI_FALSE;
    is_prim_array = JNI_FALSE;
    
    if ( sig[0] != JVM_SIGNATURE_ARRAY ) {
        if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) {
	    /* Trouble getting all the fields, can't trust field index values */
	    skip_fields = JNI_TRUE;
	    /* It is assumed that the reason why we didn't get the fields
	     *     was because the class is not prepared.
	     */
	    if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) {
                if ( list != 0 ) {
		    dump_ref_list(list);
		    debug_message("Instance of unprepared class with refs: %s\n", 
				   sig);
		} else {
		    debug_message("Instance of unprepared class without refs: %s\n", 
				   sig);
		}
                HPROF_ERROR(JNI_FALSE, "Big Trouble with unprepared class instances");
	    }
	}
        if ( n_fields > 0 ) {
            fvalues = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue));
            (void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue));
        }
    } else {
        is_array = JNI_TRUE;
        if ( sig[0] != 0 && sigToPrimSize(sig+1) != 0 ) {
            is_prim_array = JNI_TRUE;
        }
    }

    while ( index != 0 ) {
        RefInfo *info;
        jvalue   ovalue;
        static jvalue empty_value;

        info = get_info(index);

        /* Process reference objects, many not used right now. */
        switch ( info->flavor ) {
            case INFO_OBJECT_REF_DATA:
                switch ( info->refKind ) {
                    case JVMTI_HEAP_REFERENCE_SIGNERS:
                    case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
                    case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
                    case JVMTI_HEAP_REFERENCE_INTERFACE:
                    case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
                    case JVMTI_HEAP_REFERENCE_CONSTANT_POOL:
                        /* Should never be seen on an instance dump */
                        HPROF_ASSERT(0);
                        break;
                    case JVMTI_HEAP_REFERENCE_FIELD:
			if ( skip_fields == JNI_TRUE ) {
			    break;
			}
                        HPROF_ASSERT(is_array!=JNI_TRUE);
                        ovalue   = empty_value;
                        ovalue.i = info->object_index;
                        fill_in_field_value(list, fields, fvalues, n_fields, 
                                        info->index, ovalue, 0);
                        n_fields_set++;
                        HPROF_ASSERT(n_fields_set <= n_fields);
                        break;
                    case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
                        /* We get each object element one at a time.  */
                        HPROF_ASSERT(is_array==JNI_TRUE);
                        HPROF_ASSERT(is_prim_array!=JNI_TRUE);
                        if ( num_elements <= info->index ) {
                            int nbytes;
                            
                            if ( values == NULL ) {
                                num_elements = info->index + 1;
                                nbytes = num_elements*(int)sizeof(ObjectIndex);
                                values = (ObjectIndex*)HPROF_MALLOC(nbytes);
                                (void)memset(values, 0, nbytes);
                            } else {
                                void *new_values;
                                int   new_size;
                                int   obytes;

                                obytes = num_elements*(int)sizeof(ObjectIndex);
                                new_size = info->index + 1;
                                nbytes = new_size*(int)sizeof(ObjectIndex);
                                new_values = (void*)HPROF_MALLOC(nbytes);
                                (void)memcpy(new_values, values, obytes);
                                (void)memset(((char*)new_values)+obytes, 0, 
                                                        nbytes-obytes);
                                HPROF_FREE(values);
                                num_elements = new_size;
                                values =  new_values;
                            }
                        }
                        HPROF_ASSERT(values[info->index]==0);
                        values[info->index] = info->object_index;
                        break;
                    default:
                        /* Ignore, not needed */
                        break;
                }
                break;
            case INFO_PRIM_FIELD_DATA:
		if ( skip_fields == JNI_TRUE ) {
		    break;
		}
                HPROF_ASSERT(info->primType!=0);
                HPROF_ASSERT(info->length==-1);
                HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_FIELD);
                HPROF_ASSERT(is_array!=JNI_TRUE);
                ovalue = get_key_value(index);
                fill_in_field_value(list, fields, fvalues, n_fields, 
                                    info->index, ovalue, info->primType);
                n_fields_set++;
                HPROF_ASSERT(n_fields_set <= n_fields);
                break;
            case INFO_PRIM_ARRAY_DATA:
                /* Should only be one, and it's handled below */
                HPROF_ASSERT(info->refKind==0);
                /* We assert that nothing else was saved with this array */
                HPROF_ASSERT(index==list&&info->next==0);
                HPROF_ASSERT(is_array==JNI_TRUE);
                HPROF_ASSERT(is_prim_array==JNI_TRUE);
                primType = info->primType;
                elements = get_key_elements(index, primType, 
                                            &num_elements, &num_bytes);
                HPROF_ASSERT(info->length==num_elements);
                size = num_bytes;
                break;
            default:
                HPROF_ASSERT(0);
                break;
        }
        index = info->next;
    }
    
    if ( is_array == JNI_TRUE ) {
        if ( is_prim_array == JNI_TRUE ) {
            HPROF_ASSERT(values==NULL);
            io_heap_prim_array(object_index, trace_serial_num, 
                    (jint)size, num_elements, sig, elements);
        } else {
            HPROF_ASSERT(elements==NULL);
            io_heap_object_array(object_index, trace_serial_num,
                    (jint)size, num_elements, sig, values, class_index);
        }
    } else { 
        io_heap_instance_dump(cnum, object_index, trace_serial_num,
                    class_index, (jint)size, sig, fields, fvalues, n_fields);
    } 
    if ( values != NULL ) {
        HPROF_FREE(values);
    }
    if ( fvalues != NULL ) {
        HPROF_FREE(fvalues);
    }
    if ( elements != NULL ) {
        /* Do NOT free elements, it's a key in the table, leave it be */
    }
}
/* Walk all references for an ObjectIndex and construct the hprof CLASS dump. */
static void
dump_class_and_supers(JNIEnv *env, ObjectIndex object_index, RefIndex list)
{
    SiteIndex    site_index;
    SerialNumber trace_serial_num;
    RefIndex     index;
    ClassIndex   super_cnum;
    ObjectIndex  super_index;
    LoaderIndex  loader_index;
    ObjectIndex  signers_index;
    ObjectIndex  domain_index;
    FieldInfo   *fields;
    jvalue      *fvalues;
    jint         n_fields;
    jboolean     skip_fields;
    jint         n_fields_set;
    jlong        size;
    ClassIndex   cnum;
    char        *sig;
    ObjectKind   kind;
    TraceIndex   trace_index;
    Stack       *cpool_values;
    ConstantPoolValue *cpool;
    jint         cpool_count;

    HPROF_ASSERT(object_index!=0);
    kind        = object_get_kind(object_index);
    if ( kind != OBJECT_CLASS ) {
        return;
    }
    site_index         = object_get_site(object_index);
    HPROF_ASSERT(site_index!=0);
    cnum        = site_get_class_index(site_index);
    HPROF_ASSERT(cnum!=0);
    if ( class_get_status(cnum) & CLASS_DUMPED ) {
        return;
    }
    class_add_status(cnum, CLASS_DUMPED);
    size        = (jlong)object_get_size(object_index);

    super_index = 0;
    super_cnum  = class_get_super(cnum);
    if ( super_cnum != 0 ) {
        super_index  = class_get_object_index(super_cnum);
        if ( super_index != 0 ) {
            dump_class_and_supers(env, super_index, 
                        object_get_references(super_index));
        }
    }

    trace_index      = site_get_trace_index(site_index);
    HPROF_ASSERT(trace_index!=0);
    trace_serial_num = trace_get_serial_number(trace_index);
    sig              = string_get(class_get_signature(cnum));
    loader_index     = class_get_loader(cnum);
    signers_index    = 0;
    domain_index     = 0;

    /* Get field information */
    n_fields     = 0;
    skip_fields  = JNI_FALSE;
    n_fields_set = 0;
    fields       = NULL;
    fvalues      = NULL;
    if ( class_get_all_fields(env, cnum, &n_fields, &fields) == 1 ) {
	/* Problems getting all the fields, can't trust field index values */
	skip_fields = JNI_TRUE;
	/* Class with no references at all? (ok to be unprepared if list==0?) */
	if ( list != 0 ) {
	    /* It is assumed that the reason why we didn't get the fields
	     *     was because the class is not prepared.
	     */
	    if ( gdata->debugflags & DEBUGFLAG_UNPREPARED_CLASSES ) {
                dump_ref_list(list);
		debug_message("Unprepared class with references: %s\n",
			       sig);
	    }
            HPROF_ERROR(JNI_FALSE, "Trouble with unprepared classes");
	}
	/* Why would an unprepared class contain references? */
    }
    if ( n_fields > 0 ) {
        fvalues      = (jvalue*)HPROF_MALLOC(n_fields*(int)sizeof(jvalue));
        (void)memset(fvalues, 0, n_fields*(int)sizeof(jvalue));
    }
    
    /* We use a Stack just because it will automatically expand as needed */
    cpool_values = stack_init(16, 16, sizeof(ConstantPoolValue));
    cpool = NULL;
    cpool_count = 0;
    
    index      = list;
    while ( index != 0 ) {
        RefInfo    *info;
        jvalue      ovalue;
        static jvalue empty_value;

        info = get_info(index);

        switch ( info->flavor ) {
            case INFO_OBJECT_REF_DATA:
                switch ( info->refKind ) {
                    case JVMTI_HEAP_REFERENCE_FIELD:
                    case JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT:
                        /* Should never be seen on a class dump */
                        HPROF_ASSERT(0);
                        break;
                    case JVMTI_HEAP_REFERENCE_STATIC_FIELD:
			if ( skip_fields == JNI_TRUE ) {
			    break;
			}
                        ovalue   = empty_value;
                        ovalue.i = info->object_index;
                        fill_in_field_value(list, fields, fvalues, n_fields, 
                                        info->index, ovalue, 0);
                        n_fields_set++;
                        HPROF_ASSERT(n_fields_set <= n_fields);
                        break;
                    case JVMTI_HEAP_REFERENCE_CONSTANT_POOL: {
                        ConstantPoolValue cpv;
                        ObjectIndex       cp_object_index;
                        SiteIndex         cp_site_index;
                        ClassIndex        cp_cnum;
                        
                        cp_object_index = info->object_index;
                        HPROF_ASSERT(cp_object_index!=0);
                        cp_site_index = object_get_site(cp_object_index);
                        HPROF_ASSERT(cp_site_index!=0);
                        cp_cnum = site_get_class_index(cp_site_index);
                        cpv.constant_pool_index = info->index;
                        cpv.sig_index = class_get_signature(cp_cnum); 
                        cpv.value.i = cp_object_index;
                        stack_push(cpool_values, (void*)&cpv);
                        cpool_count++;
                        break;
                        }
                    case JVMTI_HEAP_REFERENCE_SIGNERS:
                        signers_index = info->object_index;
                        break;
                    case JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN:
                        domain_index = info->object_index;
                        break;
                    case JVMTI_HEAP_REFERENCE_CLASS_LOADER:
                    case JVMTI_HEAP_REFERENCE_INTERFACE:
                    default:
                        /* Ignore, not needed */
                        break;
                }
                break;
            case INFO_PRIM_FIELD_DATA:
		if ( skip_fields == JNI_TRUE ) {
		    break;
		}
                HPROF_ASSERT(info->primType!=0);
                HPROF_ASSERT(info->length==-1);
                HPROF_ASSERT(info->refKind==JVMTI_HEAP_REFERENCE_STATIC_FIELD);
                ovalue = get_key_value(index);
                fill_in_field_value(list, fields, fvalues, n_fields, 
                                    info->index, ovalue, info->primType);
                n_fields_set++;
                HPROF_ASSERT(n_fields_set <= n_fields);
                break;
            case INFO_PRIM_ARRAY_DATA:
            default:
                /* Should never see these */
                HPROF_ASSERT(0);
                break;
        }

        index = info->next;
    }

    /* Get constant pool data if we have any */
    HPROF_ASSERT(cpool_count==stack_depth(cpool_values));
    if ( cpool_count > 0 ) {
        cpool = (ConstantPoolValue*)stack_element(cpool_values, 0);
    }
    io_heap_class_dump(cnum, sig, object_index, trace_serial_num,
            super_index, 
            loader_object_index(env, loader_index), 
            signers_index, domain_index,
            (jint)size, cpool_count, cpool, n_fields, fields, fvalues);

    stack_term(cpool_values);
    if ( fvalues != NULL ) {
        HPROF_FREE(fvalues);
    }
}
Пример #7
0
/* Check all the heap tags in a heap dump */
static int
check_tags(unsigned char *pstart, int nbytes)
{
    unsigned char      *p;
    int                 nrecord;
    struct LookupTable *utab;
    UmapInfo            umap;

    check_printf("\nCHECK TAGS: starting\n");

    utab    = table_initialize("temp utf8 map", 64, 64, 512, sizeof(UmapInfo));

    /* Walk the tags, assumes UTF8 tags are defined before used */
    p       = pstart;
    nrecord = 0;
    while ( p < (pstart+nbytes) ) {
        unsigned     tag;
        unsigned     size;
        int          nheap_records;
        int          npos;
        char        *label;
        HprofId      id, nm, sg, so, gr, gn;
        int          i, li, num_elements;
        HprofType    ty;
        SerialNumber trace_serial_num;
        SerialNumber thread_serial_num;
        SerialNumber class_serial_num;
        unsigned     flags;
        unsigned     depth;
        float        cutoff;
        unsigned     temp;
        jint         nblive;
        jint         nilive;
        jlong        tbytes;
        jlong        tinsts;
        jint         total_samples;
        jint         trace_count;

        nrecord++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag = read_u1(&p);
        (void)read_u4(&p); /* microsecs */
        size = read_u4(&p);
        #define CASE_TAG(name) case name: label = #name;
        switch ( tag ) {
            CASE_TAG(HPROF_UTF8)
                CHECK_FOR_ERROR(size>=(int)sizeof(HprofId));
                id = read_id(&p);
                check_printf("#%d@%d: %s, sz=%d, name_id=0x%x, \"",
                                nrecord, npos, label, size, id);
                num_elements = size-(int)sizeof(HprofId);
                check_raw(p, num_elements);
                check_printf("\"\n");
                /* Create entry in umap */
                umap.str = HPROF_MALLOC(num_elements+1);
                (void)strncpy(umap.str, (char*)p, (size_t)num_elements);
                umap.str[num_elements] = 0;
                (void)table_create_entry(utab, &id, sizeof(id), &umap);
                p += num_elements;
                break;
            CASE_TAG(HPROF_LOAD_CLASS)
                CHECK_FOR_ERROR(size==2*4+2*(int)sizeof(HprofId));
                class_serial_num = read_u4(&p);
                CHECK_CLASS_SERIAL_NO(class_serial_num);
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                nm = read_id(&p);
                check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u,"
                             " id=0x%x, trace_serial_num=%u, name_id=0x%x\n",
                                nrecord, npos, label, size, class_serial_num,
                                id, trace_serial_num, nm);
                break;
            CASE_TAG(HPROF_UNLOAD_CLASS)
                CHECK_FOR_ERROR(size==4);
                class_serial_num = read_u4(&p);
                CHECK_CLASS_SERIAL_NO(class_serial_num);
                check_printf("#%d@%d: %s, sz=%d, class_serial_num=%u\n",
                                nrecord, npos, label, size, class_serial_num);
                break;
            CASE_TAG(HPROF_FRAME)
                CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
                id = read_id(&p);
                nm = read_id(&p);
                sg = read_id(&p);
                so = read_id(&p);
                class_serial_num = read_u4(&p);
                CHECK_CLASS_SERIAL_NO(class_serial_num);
                li = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, ", nrecord, npos, label, size);
                check_print_utf8(utab, "id=", id);
                check_printf(" name_id=0x%x, sig_id=0x%x, source_id=0x%x,"
                             " class_serial_num=%u, lineno=%d\n",
                                nm, sg, so, class_serial_num, li);
                break;
            CASE_TAG(HPROF_TRACE)
                CHECK_FOR_ERROR(size>=3*4);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                thread_serial_num = read_u4(&p); /* Can be 0 */
                num_elements = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, trace_serial_num=%u,"
                             " thread_serial_num=%u, nelems=%d [",
                                nrecord, npos, label, size,
                                trace_serial_num, thread_serial_num, num_elements);
                for(i=0; i< num_elements; i++) {
                    check_printf("0x%x,", read_id(&p));
                }
                check_printf("]\n");
                break;
            CASE_TAG(HPROF_ALLOC_SITES)
                CHECK_FOR_ERROR(size>=2+4*4+2*8);
                flags = read_u2(&p);
                temp  = read_u4(&p);
                cutoff = *((float*)&temp);
                nblive = read_u4(&p);
                nilive = read_u4(&p);
                tbytes = read_u8(&p);
                tinsts = read_u8(&p);
                num_elements     = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, flags=0x%x, cutoff=%g,"
                             " nblive=%d, nilive=%d, tbytes=(%d,%d),"
                             " tinsts=(%d,%d), num_elements=%d\n",
                                nrecord, npos, label, size,
                                flags, cutoff, nblive, nilive,
                                jlong_high(tbytes), jlong_low(tbytes),
                                jlong_high(tinsts), jlong_low(tinsts),
                                num_elements);
                for(i=0; i< num_elements; i++) {
                    ty = read_u1(&p);
                    class_serial_num = read_u4(&p);
                    CHECK_CLASS_SERIAL_NO(class_serial_num);
                    trace_serial_num = read_u4(&p);
                    CHECK_TRACE_SERIAL_NO(trace_serial_num);
                    nblive = read_u4(&p);
                    nilive = read_u4(&p);
                    tbytes = read_u4(&p);
                    tinsts = read_u4(&p);
                    check_printf("\t %d: ty=%d, class_serial_num=%u,"
                                 " trace_serial_num=%u, nblive=%d, nilive=%d,"
                                 " tbytes=%d, tinsts=%d\n",
                                 i, ty, class_serial_num, trace_serial_num,
                                 nblive, nilive, (jint)tbytes, (jint)tinsts);
                }
                break;
            CASE_TAG(HPROF_HEAP_SUMMARY)
                CHECK_FOR_ERROR(size==2*4+2*8);
                nblive = read_u4(&p);
                nilive = read_u4(&p);
                tbytes = read_u8(&p);
                tinsts = read_u8(&p);
                check_printf("#%d@%d: %s, sz=%d,"
                             " nblive=%d, nilive=%d, tbytes=(%d,%d),"
                             " tinsts=(%d,%d)\n",
                                nrecord, npos, label, size,
                                nblive, nilive,
                                jlong_high(tbytes), jlong_low(tbytes),
                                jlong_high(tinsts), jlong_low(tinsts));
                break;
            CASE_TAG(HPROF_START_THREAD)
                CHECK_FOR_ERROR(size==2*4+4*(int)sizeof(HprofId));
                thread_serial_num = read_u4(&p);
                CHECK_THREAD_SERIAL_NO(thread_serial_num);
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                nm = read_id(&p);
                gr = read_id(&p);
                gn = read_id(&p);
                check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u,"
                             " id=0x%x, trace_serial_num=%u, ",
                                nrecord, npos, label, size,
                                thread_serial_num, id, trace_serial_num);
                check_print_utf8(utab, "nm=", id);
                check_printf(" trace_serial_num=%u, nm=0x%x,"
                             " gr=0x%x, gn=0x%x\n",
                                trace_serial_num, nm, gr, gn);
                break;
            CASE_TAG(HPROF_END_THREAD)
                CHECK_FOR_ERROR(size==4);
                thread_serial_num = read_u4(&p);
                CHECK_THREAD_SERIAL_NO(thread_serial_num);
                check_printf("#%d@%d: %s, sz=%d, thread_serial_num=%u\n",
                                nrecord, npos, label, size, thread_serial_num);
                break;
            CASE_TAG(HPROF_HEAP_DUMP)
                check_printf("#%d@%d: BEGIN: %s, sz=%d\n",
                                nrecord, npos, label, size);
                nheap_records = check_heap_tags(utab, p, size);
                check_printf("#%d@%d: END: %s, sz=%d, nheap_recs=%d\n",
                                nrecord, npos, label, size, nheap_records);
                p += size;
                break;
            CASE_TAG(HPROF_HEAP_DUMP_SEGMENT) /* 1.0.2 */
                check_printf("#%d@%d: BEGIN SEGMENT: %s, sz=%d\n",
                                nrecord, npos, label, size);
                nheap_records = check_heap_tags(utab, p, size);
                check_printf("#%d@%d: END SEGMENT: %s, sz=%d, nheap_recs=%d\n",
                                nrecord, npos, label, size, nheap_records);
                p += size;
                break;
            CASE_TAG(HPROF_HEAP_DUMP_END) /* 1.0.2 */
                check_printf("#%d@%d: SEGMENT END: %s, sz=%d\n",
                                nrecord, npos, label, size);
                break;
            CASE_TAG(HPROF_CPU_SAMPLES)
                CHECK_FOR_ERROR(size>=2*4);
                total_samples = read_u4(&p);
                trace_count = read_u4(&p);
                check_printf("#%d@%d: %s, sz=%d, total_samples=%d,"
                             " trace_count=%d\n",
                                nrecord, npos, label, size,
                                total_samples, trace_count);
                for(i=0; i< trace_count; i++) {
                    num_elements = read_u4(&p);
                    trace_serial_num = read_u4(&p);
                    CHECK_TRACE_SERIAL_NO(trace_serial_num);
                    check_printf("\t %d: samples=%d, trace_serial_num=%u\n",
                                 trace_serial_num, num_elements);
                }
                break;
            CASE_TAG(HPROF_CONTROL_SETTINGS)
                CHECK_FOR_ERROR(size==4+2);
                flags = read_u4(&p);
                depth = read_u2(&p);
                check_printf("#%d@%d: %s, sz=%d, flags=0x%x, depth=%d\n",
                                nrecord, npos, label, size, flags, depth);
                break;
            default:
                label = "UNKNOWN";
                check_printf("#%d@%d: %s, sz=%d\n",
                                nrecord, npos, label, size);
                HPROF_ERROR(JNI_TRUE, "unknown record type");
                p += size;
                break;
        }
        CHECK_FOR_ERROR(p<=(pstart+nbytes));
    }
    check_flush();
    CHECK_FOR_ERROR(p==(pstart+nbytes));
    table_cleanup(utab, &utab_cleanup, NULL);
    return nrecord;
}
Пример #8
0
/* Given the heap dump data and the utf8 map, check/write the heap dump. */
static int
check_heap_tags(struct LookupTable *utab, unsigned char *pstart, int nbytes)
{
    int                 nrecords;
    unsigned char      *p;
    unsigned char      *psave;
    struct LookupTable *ctab;
    CmapInfo            cmap;
    char               *label;
    unsigned            tag;
    HprofType           ty;
    HprofId             id, id2, fr, sup;
    int                 num_elements;
    int                 num_bytes;
    SerialNumber        trace_serial_num;
    SerialNumber        thread_serial_num;
    int                 npos;
    int                 i;
    int                 inst_size;

    ctab     = table_initialize("temp ctab", 64, 64, 512, sizeof(CmapInfo));

    /* First pass over heap records just fills in the CmapInfo table */
    nrecords = 0;
    p        = pstart;
    while ( p < (pstart+nbytes) ) {
        nrecords++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag  = read_u1(&p);
        switch ( tag ) {
            CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
                id  = read_id(&p);
                id2 = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
                id = read_id(&p);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                trace_serial_num = read_u4(&p);
                break;
            CASE_HEAP(HPROF_GC_CLASS_DUMP)
                (void)memset((void*)&cmap, 0, sizeof(cmap));
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                {
                    HprofId ld, si, pr, re1, re2;

                    sup      = read_id(&p);
                    ld       = read_id(&p);
                    si       = read_id(&p);
                    pr       = read_id(&p);
                    re1      = read_id(&p);
                    re2      = read_id(&p);
                    cmap.sup = sup;
                }
                inst_size = read_u4(&p);
                cmap.inst_size = inst_size;
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    (void)read_u2(&p);
                    ty = read_u1(&p);
                    (void)read_val(&p, ty);
                }
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    (void)read_id(&p);
                    ty = read_u1(&p);
                    (void)read_val(&p, ty);
                }
                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;

                    id = read_id(&p);
                    ty = read_u1(&p);
                    add_inst_field_to_cmap(&cmap, id, ty);
                }
                (void)table_create_entry(ctab, &id, sizeof(id), &cmap);
                break;
            CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                id2 = read_id(&p); /* class id */
                num_bytes = read_u4(&p);
                p += num_bytes;
                break;
            CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                num_elements = read_u4(&p);
                id2 = read_id(&p);
                p += num_elements*(int)sizeof(HprofId);
                break;
            CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                num_elements = read_u4(&p);
                ty = read_u1(&p);
                p += type_size[ty]*num_elements;
                break;
            default:
                label = "UNKNOWN";
                check_printf("H#%d@%d %s: ERROR!\n",
                                nrecords, npos, label);
                HPROF_ERROR(JNI_TRUE, "unknown heap record type");
                break;
        }
    }
    CHECK_FOR_ERROR(p==pstart+nbytes);

    /* Scan again once we have our cmap */
    nrecords = 0;
    p        = pstart;
    while ( p < (pstart+nbytes) ) {
        nrecords++;
        /*LINTED*/
        npos = (int)(p - pstart);
        tag  = read_u1(&p);
        switch ( tag ) {
            CASE_HEAP(HPROF_GC_ROOT_UNKNOWN)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_GLOBAL)
                id = read_id(&p);
                id2 = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x, id2=0x%x\n",
                        nrecords, npos, label, id, id2);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JNI_LOCAL)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
                        nrecords, npos, label, id, thread_serial_num, fr);
                break;
            CASE_HEAP(HPROF_GC_ROOT_JAVA_FRAME)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                fr = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u, fr=0x%x\n",
                        nrecords, npos, label, id, thread_serial_num, fr);
                break;
            CASE_HEAP(HPROF_GC_ROOT_NATIVE_STACK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num);
                break;
            CASE_HEAP(HPROF_GC_ROOT_STICKY_CLASS)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_BLOCK)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num);
                break;
            CASE_HEAP(HPROF_GC_ROOT_MONITOR_USED)
                id = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x\n",
                        nrecords, npos, label, id);
                break;
            CASE_HEAP(HPROF_GC_ROOT_THREAD_OBJ)
                id = read_id(&p);
                thread_serial_num = read_u4(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                check_printf("H#%d@%d %s: id=0x%x, thread_serial_num=%u,"
                             " trace_serial_num=%u\n",
                        nrecords, npos, label, id, thread_serial_num,
                        trace_serial_num);
                break;
            CASE_HEAP(HPROF_GC_CLASS_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u\n",
                        nrecords, npos, label, id, trace_serial_num);
                {
                    HprofId ld, si, pr, re1, re2;

                    sup = read_id(&p);
                    ld  = read_id(&p);
                    si  = read_id(&p);
                    pr  = read_id(&p);
                    re1 = read_id(&p);
                    re2 = read_id(&p);
                    check_printf("  su=0x%x, ld=0x%x, si=0x%x,"
                                 " pr=0x%x, re1=0x%x, re2=0x%x\n",
                        sup, ld, si, pr, re1, re2);
                }
                inst_size = read_u4(&p);
                check_printf("  instance_size=%d\n", inst_size);

                num_elements = read_u2(&p);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    unsigned  cpi;
                    jvalue    val;

                    cpi = read_u2(&p);
                    ty  = read_u1(&p);
                    val = read_val(&p, ty);
                    check_printf("  constant_pool %d: cpi=%d, ty=%d, val=",
                                i, cpi, ty);
                    check_printf_val(ty, val, 1);
                    check_printf("\n");
                }

                num_elements = read_u2(&p);
                check_printf("  static_field_count=%d\n", num_elements);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;
                    jvalue    val;

                    id  = read_id(&p);
                    ty  = read_u1(&p);
                    val = read_val(&p, ty);
                    check_printf("  static field %d: ", i);
                    check_print_utf8(utab, "id=", id);
                    check_printf(", ty=%d, val=", ty);
                    check_printf_val(ty, val, 1);
                    check_printf("\n");
                }

                num_elements = read_u2(&p);
                check_printf("  instance_field_count=%d\n", num_elements);
                for(i=0; i<num_elements; i++) {
                    HprofType ty;
                    HprofId   id;

                    id = read_id(&p);
                    ty = read_u1(&p);
                    check_printf("  instance_field %d: ", i);
                    check_print_utf8(utab, "id=", id);
                    check_printf(", ty=%d\n", ty);
                }
                break;
            CASE_HEAP(HPROF_GC_INSTANCE_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                id2 = read_id(&p); /* class id */
                num_bytes = read_u4(&p);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u,"
                             " cid=0x%x, nbytes=%d\n",
                            nrecords, npos, label, id, trace_serial_num,
                            id2, num_bytes);
                /* This is a packed set of bytes for the instance fields */
                if ( num_bytes > 0 ) {
                    TableIndex cindex;
                    int        ifield;
                    CmapInfo  *map;

                    cindex = table_find_entry(ctab, &id2, sizeof(id2));
                    HPROF_ASSERT(cindex!=0);
                    map = (CmapInfo*)table_get_info(ctab, cindex);
                    HPROF_ASSERT(map!=NULL);
                    HPROF_ASSERT(num_bytes==map->inst_size);

                    psave  = p;
                    ifield = 0;

                    do {
                        for(i=0;i<map->n_finfo;i++) {
                            HprofType ty;
                            HprofId   id;
                            jvalue    val;

                            ty = map->finfo[i].ty;
                            id = map->finfo[i].id;
                            HPROF_ASSERT(ty!=0);
                            HPROF_ASSERT(id!=0);
                            val = read_val(&p, ty);
                            check_printf("  field %d: ", ifield);
                            check_print_utf8(utab, "id=", id);
                            check_printf(", ty=%d, val=", ty);
                            check_printf_val(ty, val, 1);
                            check_printf("\n");
                            ifield++;
                        }
                        id2    = map->sup;
                        map    = NULL;
                        cindex = 0;
                        if ( id2 != 0 ) {
                            cindex = table_find_entry(ctab, &id2, sizeof(id2));
                            HPROF_ASSERT(cindex!=0);
                            map = (CmapInfo*)table_get_info(ctab, cindex);
                            HPROF_ASSERT(map!=NULL);
                        }
                    } while ( map != NULL );
                    HPROF_ASSERT(num_bytes==(p-psave));
                }
                break;
            CASE_HEAP(HPROF_GC_OBJ_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                num_elements = read_u4(&p);
                id2 = read_id(&p);
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, nelems=%d, eid=0x%x\n",
                                nrecords, npos, label, id, trace_serial_num, num_elements, id2);
                for(i=0; i<num_elements; i++) {
                    HprofId id;

                    id = read_id(&p);
                    check_printf("  [%d]: id=0x%x\n", i, id);
                }
                break;
            CASE_HEAP(HPROF_GC_PRIM_ARRAY_DUMP)
                id = read_id(&p);
                trace_serial_num = read_u4(&p);
                CHECK_TRACE_SERIAL_NO(trace_serial_num);
                num_elements = read_u4(&p);
                ty = read_u1(&p);
                psave = p;
                check_printf("H#%d@%d %s: id=0x%x, trace_serial_num=%u, "
                             "nelems=%d, ty=%d\n",
                                nrecords, npos, label, id, trace_serial_num, num_elements, ty);
                HPROF_ASSERT(HPROF_TYPE_IS_PRIMITIVE(ty));
                if ( num_elements > 0 ) {
                    int   count;
                    int   long_form;
                    int   max_count;
                    char *quote;

                    quote     = "";
                    long_form = 1;
                    max_count = 8;
                    count     = 0;
                    switch ( ty ) {
                        case HPROF_CHAR:
                            long_form = 0;
                            max_count = 72;
                            quote     = "\"";
                            /*FALLTHRU*/
                        case HPROF_INT:
                        case HPROF_DOUBLE:
                        case HPROF_LONG:
                        case HPROF_BYTE:
                        case HPROF_BOOLEAN:
                        case HPROF_SHORT:
                        case HPROF_FLOAT:
                            check_printf("  val=%s", quote);
                            for(i=0; i<num_elements; i++) {
                                jvalue val;

                                if ( i > 0 && count == 0 ) {
                                    check_printf("  %s", quote);
                                }
                                val = read_val(&p, ty);
                                check_printf_val(ty, val, long_form);
                                count += 1;
                                if ( count >= max_count ) {
                                    check_printf("\"\n");
                                    count = 0;
                                }
                            }
                            if ( count != 0 ) {
                                check_printf("%s\n", quote);
                            }
                            break;
                    }
                }
                HPROF_ASSERT(type_size[ty]*num_elements==(p-psave));
                break;
            default:
                label = "UNKNOWN";
                check_printf("H#%d@%d %s: ERROR!\n",
                                nrecords, npos, label);
                HPROF_ERROR(JNI_TRUE, "unknown heap record type");
                break;
        }
    }
    CHECK_FOR_ERROR(p==pstart+nbytes);

    table_cleanup(ctab, &cmap_cleanup, NULL);

    return nrecords;
}