Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jvmti/hprof/hprof_check.c
38829 views
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
}
1153
1154