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