Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/os/solaris/dtrace/libjvm_db.c
32284 views
1
/*
2
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*
23
*/
24
25
#include <stdio.h>
26
#include <stdlib.h>
27
#include <string.h>
28
#include <errno.h>
29
#include <gelf.h>
30
31
#include "libjvm_db.h"
32
#include "JvmOffsets.h"
33
34
#define LIBJVM_SO "libjvm.so"
35
36
#if defined(i386) || defined(__i386) || defined(__amd64)
37
#ifdef COMPILER2
38
#define X86_COMPILER2
39
#endif /* COMPILER2 */
40
#endif /* i386 */
41
42
typedef struct {
43
short vf_cnt; /* number of recognized java vframes */
44
short bci; /* current frame method byte code index */
45
int line; /* current frame method source line */
46
uint64_t new_fp; /* fp for the next frame */
47
uint64_t new_pc; /* pc for the next frame */
48
uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
49
char locinf; /* indicates there is valid location info */
50
} Jframe_t;
51
52
int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
53
size_t size, Jframe_t *jframe);
54
55
int main(int arg) { return arg; }
56
57
static int debug = 0;
58
59
static void failed(int err, const char * file, int line) {
60
if (debug) {
61
fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
62
}
63
}
64
65
static void warn(const char * file, int line, const char * msg) {
66
if (debug) {
67
fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
68
}
69
}
70
71
static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
72
if (debug) {
73
fprintf(stderr, "warning: ");
74
fprintf(stderr, msg, arg1);
75
fprintf(stderr, " at %s:%d\n", file, line);
76
}
77
}
78
79
#define CHECK_FAIL(err) \
80
if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
81
#define WARN(msg) warn(__FILE__, __LINE__, msg)
82
#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1)
83
84
typedef struct VMStructEntry {
85
const char * typeName; /* The type name containing the given field (example: "Klass") */
86
const char * fieldName; /* The field name within the type (example: "_name") */
87
uint64_t address; /* Address of field; only used for static fields */
88
/* ("offset" can not be reused because of apparent SparcWorks compiler bug */
89
/* in generation of initializer data) */
90
} VMStructEntry;
91
92
/* Prototyping inlined methods */
93
94
int sprintf(char *s, const char *format, ...);
95
96
#define SZ16 sizeof(int16_t)
97
#define SZ32 sizeof(int32_t)
98
99
#define COMP_METHOD_SIGN '*'
100
101
#define MAX_VFRAMES_CNT 256
102
103
typedef struct vframe {
104
uint64_t method;
105
int32_t sender_decode_offset;
106
int32_t methodIdx;
107
int32_t bci;
108
int32_t line;
109
} Vframe_t;
110
111
typedef struct frame {
112
uintptr_t fp;
113
uintptr_t pc;
114
uintptr_t sp;
115
uintptr_t sender_sp; // The unextended sp of the caller
116
} Frame_t;
117
118
typedef struct Nmethod_t {
119
struct jvm_agent* J;
120
Jframe_t *jframe;
121
122
uint64_t nm; /* _nmethod */
123
uint64_t pc;
124
uint64_t pc_desc;
125
126
int32_t orig_pc_offset; /* _orig_pc_offset */
127
int32_t instrs_beg; /* _code_offset */
128
int32_t instrs_end;
129
int32_t deopt_beg; /* _deoptimize_offset */
130
int32_t scopes_data_beg; /* _scopes_data_offset */
131
int32_t scopes_data_end;
132
int32_t metadata_beg; /* _metadata_offset */
133
int32_t metadata_end;
134
int32_t scopes_pcs_beg; /* _scopes_pcs_offset */
135
int32_t scopes_pcs_end;
136
137
int vf_cnt;
138
Vframe_t vframes[MAX_VFRAMES_CNT];
139
} Nmethod_t;
140
141
struct jvm_agent {
142
struct ps_prochandle* P;
143
144
uint64_t nmethod_vtbl;
145
uint64_t CodeBlob_vtbl;
146
uint64_t BufferBlob_vtbl;
147
uint64_t RuntimeStub_vtbl;
148
uint64_t Method_vtbl;
149
150
uint64_t Use_Compressed_Oops_address;
151
uint64_t Universe_narrow_oop_base_address;
152
uint64_t Universe_narrow_oop_shift_address;
153
uint64_t CodeCache_heap_address;
154
155
/* Volatiles */
156
uint8_t Use_Compressed_Oops;
157
uint64_t Universe_narrow_oop_base;
158
uint32_t Universe_narrow_oop_shift;
159
uint64_t CodeCache_low;
160
uint64_t CodeCache_high;
161
uint64_t CodeCache_segmap_low;
162
uint64_t CodeCache_segmap_high;
163
164
int32_t SIZE_CodeCache_log2_segment;
165
166
uint64_t methodPtr;
167
uint64_t bcx;
168
169
Nmethod_t *N; /*Inlined methods support */
170
Frame_t prev_fr;
171
Frame_t curr_fr;
172
};
173
174
static int
175
read_string(struct ps_prochandle *P,
176
char *buf, /* caller's buffer */
177
size_t size, /* upper limit on bytes to read */
178
uintptr_t addr) /* address in process */
179
{
180
int err = PS_OK;
181
while (size-- > 1 && err == PS_OK) {
182
err = ps_pread(P, addr, buf, 1);
183
if (*buf == '\0') {
184
return PS_OK;
185
}
186
addr += 1;
187
buf += 1;
188
}
189
return -1;
190
}
191
192
static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
193
int err = -1;
194
uint32_t ptr32;
195
err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
196
*ptr = ptr32;
197
return err;
198
}
199
200
static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
201
int err = -1;
202
uint32_t ptr32;
203
204
switch (DATA_MODEL) {
205
case PR_MODEL_LP64:
206
err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
207
break;
208
case PR_MODEL_ILP32:
209
err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
210
*ptr = ptr32;
211
break;
212
}
213
214
return err;
215
}
216
217
static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
218
uint64_t ptr;
219
int err;
220
char buffer[1024];
221
222
*stringp = NULL;
223
err = read_pointer(J, base, &ptr);
224
CHECK_FAIL(err);
225
if (ptr != 0) {
226
err = read_string(J->P, buffer, sizeof(buffer), ptr);
227
CHECK_FAIL(err);
228
*stringp = strdup(buffer);
229
}
230
return PS_OK;
231
232
fail:
233
return err;
234
}
235
236
static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
237
uint64_t ptr;
238
int err;
239
240
err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
241
CHECK_FAIL(err);
242
err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
243
CHECK_FAIL(err);
244
err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
245
CHECK_FAIL(err);
246
247
return PS_OK;
248
249
fail:
250
if (vmp->typeName != NULL) free((void*)vmp->typeName);
251
if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
252
return err;
253
}
254
255
static int parse_vmstructs(jvm_agent_t* J) {
256
VMStructEntry vmVar;
257
VMStructEntry* vmp = &vmVar;
258
uint64_t gHotSpotVMStructs;
259
psaddr_t sym_addr;
260
uint64_t base;
261
int err;
262
263
/* Clear *vmp now in case we jump to fail: */
264
memset(vmp, 0, sizeof(VMStructEntry));
265
266
err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
267
CHECK_FAIL(err);
268
err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
269
CHECK_FAIL(err);
270
base = gHotSpotVMStructs;
271
272
err = PS_OK;
273
while (err == PS_OK) {
274
memset(vmp, 0, sizeof(VMStructEntry));
275
err = parse_vmstruct_entry(J, base, vmp);
276
if (err != PS_OK || vmp->typeName == NULL) {
277
break;
278
}
279
280
if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
281
if (strcmp("_heap", vmp->fieldName) == 0) {
282
err = read_pointer(J, vmp->address, &J->CodeCache_heap_address);
283
}
284
} else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
285
if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
286
J->Universe_narrow_oop_base_address = vmp->address;
287
}
288
if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
289
J->Universe_narrow_oop_shift_address = vmp->address;
290
}
291
}
292
CHECK_FAIL(err);
293
294
base += SIZE_VMStructEntry;
295
if (vmp->typeName != NULL) free((void*)vmp->typeName);
296
if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
297
}
298
299
return PS_OK;
300
301
fail:
302
if (vmp->typeName != NULL) free((void*)vmp->typeName);
303
if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
304
return -1;
305
}
306
307
static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
308
psaddr_t sym_addr;
309
int err;
310
311
err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
312
if (err != PS_OK) goto fail;
313
*valuep = sym_addr;
314
return PS_OK;
315
316
fail:
317
return err;
318
}
319
320
static int read_volatiles(jvm_agent_t* J) {
321
uint64_t ptr;
322
int err;
323
324
err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
325
if (err == PS_OK) {
326
err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
327
CHECK_FAIL(err);
328
} else {
329
J->Use_Compressed_Oops = 0;
330
}
331
332
err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
333
CHECK_FAIL(err);
334
err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
335
CHECK_FAIL(err);
336
337
err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
338
OFFSET_VirtualSpace_low, &J->CodeCache_low);
339
CHECK_FAIL(err);
340
err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
341
OFFSET_VirtualSpace_high, &J->CodeCache_high);
342
CHECK_FAIL(err);
343
err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
344
OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low);
345
CHECK_FAIL(err);
346
err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
347
OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high);
348
CHECK_FAIL(err);
349
350
err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size,
351
&J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
352
CHECK_FAIL(err);
353
354
return PS_OK;
355
356
fail:
357
return err;
358
}
359
360
361
static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
362
/* make sure the code cache is up to date */
363
return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high);
364
}
365
366
static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
367
return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
368
}
369
370
static uint64_t block_at(jvm_agent_t* J, int i) {
371
return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
372
}
373
374
static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
375
int err;
376
377
*startp = 0;
378
if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) {
379
int32_t used;
380
uint64_t segment = segment_for(J, ptr);
381
uint64_t block = J->CodeCache_segmap_low;
382
uint8_t tag;
383
err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
384
CHECK_FAIL(err);
385
if (tag == 0xff)
386
return PS_OK;
387
while (tag > 0) {
388
err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
389
CHECK_FAIL(err);
390
segment -= tag;
391
}
392
block = block_at(J, segment);
393
err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
394
CHECK_FAIL(err);
395
if (used) {
396
*startp = block + SIZE_HeapBlockHeader;
397
}
398
}
399
return PS_OK;
400
401
fail:
402
return -1;
403
}
404
405
static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
406
psaddr_t sym_addr;
407
int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
408
if (err == PS_OK) {
409
err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
410
return err;
411
}
412
*valuep = -1;
413
return -1;
414
}
415
416
jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
417
jvm_agent_t* J;
418
int err;
419
420
if (vers != JVM_DB_VERSION) {
421
errno = ENOTSUP;
422
return NULL;
423
}
424
425
J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
426
427
debug = getenv("LIBJVMDB_DEBUG") != NULL;
428
if (debug) debug = 3;
429
430
if (debug) {
431
fprintf(stderr, "Jagent_create: debug=%d\n", debug);
432
#ifdef X86_COMPILER2
433
fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
434
#endif /* X86_COMPILER2 */
435
}
436
437
J->P = P;
438
439
// Initialize the initial previous frame
440
441
J->prev_fr.fp = 0;
442
J->prev_fr.pc = 0;
443
J->prev_fr.sp = 0;
444
J->prev_fr.sender_sp = 0;
445
446
err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
447
CHECK_FAIL(err);
448
err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
449
if (err != PS_OK) J->BufferBlob_vtbl = 0;
450
err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
451
CHECK_FAIL(err);
452
err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
453
CHECK_FAIL(err);
454
err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
455
CHECK_FAIL(err);
456
457
err = parse_vmstructs(J);
458
CHECK_FAIL(err);
459
err = read_volatiles(J);
460
CHECK_FAIL(err);
461
462
return J;
463
464
fail:
465
Jagent_destroy(J);
466
return NULL;
467
}
468
469
void Jagent_destroy(jvm_agent_t *J) {
470
if (J != NULL) {
471
free(J);
472
}
473
}
474
475
static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
476
uint64_t klass;
477
int err = read_pointer(J, methodPtr, &klass);
478
if (err != PS_OK) goto fail;
479
return klass == J->Method_vtbl;
480
481
fail:
482
return 0;
483
}
484
485
static int
486
name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
487
{
488
short nameIndex;
489
short signatureIndex;
490
uint64_t constantPool;
491
uint64_t constMethod;
492
uint64_t nameSymbol;
493
uint64_t signatureSymbol;
494
uint64_t klassPtr;
495
uint64_t klassSymbol;
496
short klassSymbolLength;
497
short nameSymbolLength;
498
short signatureSymbolLength;
499
char * nameString = NULL;
500
char * klassString = NULL;
501
char * signatureString = NULL;
502
int err;
503
504
err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
505
CHECK_FAIL(err);
506
err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
507
CHECK_FAIL(err);
508
509
/* To get name string */
510
err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
511
CHECK_FAIL(err);
512
err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
513
CHECK_FAIL(err);
514
// The symbol is a CPSlot and has lower bit set to indicate metadata
515
nameSymbol &= (~1); // remove metadata lsb
516
err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
517
CHECK_FAIL(err);
518
nameString = (char*)calloc(nameSymbolLength + 1, 1);
519
err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
520
CHECK_FAIL(err);
521
522
/* To get signature string */
523
err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
524
CHECK_FAIL(err);
525
err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
526
CHECK_FAIL(err);
527
signatureSymbol &= (~1); // remove metadata lsb
528
err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
529
CHECK_FAIL(err);
530
signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
531
err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
532
CHECK_FAIL(err);
533
534
/* To get klass string */
535
err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
536
CHECK_FAIL(err);
537
err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
538
CHECK_FAIL(err);
539
err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
540
CHECK_FAIL(err);
541
klassString = (char*)calloc(klassSymbolLength + 1, 1);
542
err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
543
CHECK_FAIL(err);
544
545
result[0] = '\0';
546
if (snprintf(result, size,
547
"%s.%s%s",
548
klassString,
549
nameString,
550
signatureString) >= size) {
551
// truncation
552
goto fail;
553
}
554
555
if (nameString != NULL) free(nameString);
556
if (klassString != NULL) free(klassString);
557
if (signatureString != NULL) free(signatureString);
558
559
return PS_OK;
560
561
fail:
562
if (debug) {
563
fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
564
}
565
if (nameString != NULL) free(nameString);
566
if (klassString != NULL) free(klassString);
567
if (signatureString != NULL) free(signatureString);
568
return -1;
569
}
570
571
static int nmethod_info(Nmethod_t *N)
572
{
573
jvm_agent_t *J = N->J;
574
uint64_t nm = N->nm;
575
int32_t err;
576
577
if (debug > 2 )
578
fprintf(stderr, "\t nmethod_info: BEGIN \n");
579
580
/* Instructions */
581
err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32);
582
CHECK_FAIL(err);
583
err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
584
CHECK_FAIL(err);
585
err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
586
CHECK_FAIL(err);
587
err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
588
CHECK_FAIL(err);
589
590
/* Metadata */
591
err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
592
CHECK_FAIL(err);
593
err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32);
594
CHECK_FAIL(err);
595
596
/* scopes_pcs */
597
err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
598
CHECK_FAIL(err);
599
err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32);
600
CHECK_FAIL(err);
601
602
/* scopes_data */
603
err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
604
CHECK_FAIL(err);
605
606
if (debug > 2 ) {
607
N->scopes_data_end = N->scopes_pcs_beg;
608
609
fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
610
N->instrs_beg, N->instrs_end);
611
612
fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
613
N->deopt_beg);
614
615
fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
616
N->orig_pc_offset);
617
618
fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
619
N->metadata_beg, N->metadata_end);
620
621
fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
622
N->scopes_data_beg, N->scopes_data_end);
623
624
fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
625
N->scopes_pcs_beg, N->scopes_pcs_end);
626
627
fprintf(stderr, "\t nmethod_info: END \n\n");
628
}
629
return PS_OK;
630
631
fail:
632
return err;
633
}
634
635
static int
636
raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
637
{
638
int shift = 0;
639
int value = 0;
640
uint8_t ch = 0;
641
int32_t err;
642
int32_t sum;
643
// Constants for UNSIGNED5 coding of Pack200
644
// see compressedStream.hpp
645
enum {
646
lg_H = 6,
647
H = 1<<lg_H,
648
BitsPerByte = 8,
649
L = (1<<BitsPerByte)-H,
650
};
651
int i;
652
653
err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
654
CHECK_FAIL(err);
655
if (debug > 2)
656
fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
657
658
sum = ch;
659
if ( sum >= L ) {
660
int32_t lg_H_i = lg_H;
661
// Read maximum of 5 total bytes (we've already read 1).
662
// See CompressedReadStream::read_int_mb
663
for ( i = 0; i < 4; i++) {
664
err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
665
CHECK_FAIL(err);
666
sum += ch << lg_H_i;
667
if (ch < L ) {
668
*val = sum;
669
return PS_OK;
670
}
671
lg_H_i += lg_H;
672
}
673
}
674
*val = sum;
675
return PS_OK;
676
677
fail:
678
return err;
679
}
680
681
static int
682
read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
683
{
684
uint8_t next = 0;
685
int32_t bci_delta;
686
int32_t line_delta;
687
int32_t err;
688
689
if (debug > 2)
690
fprintf(stderr, "\t\t read_pair: BEGIN\n");
691
692
err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
693
CHECK_FAIL(err);
694
695
if (next == 0) {
696
if (debug > 2)
697
fprintf(stderr, "\t\t read_pair: END: next == 0\n");
698
return 1; /* stream terminated */
699
}
700
if (next == 0xFF) {
701
if (debug > 2)
702
fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
703
704
/* Escape character, regular compression used */
705
706
err = raw_read_int(J, buffer, &bci_delta);
707
CHECK_FAIL(err);
708
709
err = raw_read_int(J, buffer, &line_delta);
710
CHECK_FAIL(err);
711
712
*bci += bci_delta;
713
*line += line_delta;
714
715
if (debug > 2) {
716
fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
717
line_delta, bci_delta);
718
fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
719
*line, *bci);
720
}
721
} else {
722
/* Single byte compression used */
723
*bci += next >> 3;
724
*line += next & 0x7;
725
if (debug > 2) {
726
fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
727
next & 0x7, next >> 3);
728
fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
729
*line, *bci);
730
}
731
}
732
if (debug > 2)
733
fprintf(stderr, "\t\t read_pair: END\n");
734
return PS_OK;
735
736
fail:
737
if (debug)
738
fprintf(stderr, "\t\t read_pair: FAIL\n");
739
return err;
740
}
741
742
static int
743
line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
744
{
745
uint64_t buffer;
746
uint16_t code_size;
747
uint64_t code_end_delta;
748
uint64_t constMethod;
749
int8_t access_flags;
750
int32_t best_bci = 0;
751
int32_t stream_bci = 0;
752
int32_t stream_line = 0;
753
int32_t err;
754
755
if (debug > 2) {
756
char name[256];
757
err = name_for_methodPtr(J, vf->method, name, 256);
758
CHECK_FAIL(err);
759
fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
760
name, vf->bci);
761
}
762
763
err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
764
CHECK_FAIL(err);
765
766
vf->line = 0;
767
err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
768
CHECK_FAIL(err);
769
770
if (!(access_flags & ConstMethod_has_linenumber_table)) {
771
if (debug > 2)
772
fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
773
return PS_OK;
774
}
775
776
/* The line numbers are a short array of 2-tuples [start_pc, line_number].
777
* Not necessarily sorted and not necessarily one-to-one.
778
*/
779
780
err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
781
CHECK_FAIL(err);
782
783
/* inlined_table_start() */
784
code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
785
buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
786
787
if (debug > 2) {
788
fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
789
vf->method, (access_flags & AccessFlags_NATIVE));
790
fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
791
buffer, (int) code_size);
792
}
793
794
while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
795
if (stream_bci == vf->bci) {
796
/* perfect match */
797
if (debug > 2)
798
fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
799
vf->line = stream_line;
800
return PS_OK;
801
} else {
802
/* update best_bci/line */
803
if (stream_bci < vf->bci && stream_bci >= best_bci) {
804
best_bci = stream_bci;
805
vf->line = stream_line;
806
if (debug > 2) {
807
fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
808
best_bci, vf->line);
809
}
810
}
811
}
812
}
813
if (debug > 2)
814
fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
815
return PS_OK;
816
817
fail:
818
if (debug)
819
fprintf(stderr, "\t line_number_from_bci: FAIL\n");
820
return err;
821
}
822
823
static int
824
get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
825
{
826
int32_t pc_offset;
827
int32_t err;
828
829
err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
830
CHECK_FAIL(err);
831
832
*real_pc = N->nm + N->instrs_beg + pc_offset;
833
if (debug > 2) {
834
fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
835
pc_offset, *real_pc);
836
}
837
return PS_OK;
838
839
fail:
840
return err;
841
}
842
843
/* Finds a PcDesc with real-pc equal to N->pc */
844
static int pc_desc_at(Nmethod_t *N)
845
{
846
uint64_t pc_diff;
847
int32_t offs;
848
int32_t err;
849
850
if (debug > 2)
851
fprintf(stderr, "\t pc_desc_at: BEGIN\n");
852
853
N->vf_cnt = 0;
854
N->pc_desc = 0;
855
856
for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
857
uint64_t pd;
858
uint64_t best_pc_diff = 16; /* some approximation */
859
uint64_t real_pc = 0;
860
861
pd = N->nm + offs;
862
err = get_real_pc(N, pd, &real_pc);
863
CHECK_FAIL(err);
864
865
pc_diff = real_pc - N->pc;
866
867
/* In general, this fragment should work */
868
if (pc_diff == 0) {
869
N->pc_desc = pd;
870
if (debug) {
871
fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
872
}
873
return PS_OK;
874
}
875
/* This fragment is to be able to find out an appropriate
876
* pc_desc entry even if pc_desc info is inaccurate.
877
*/
878
if (best_pc_diff > pc_diff && pc_diff > 0) {
879
best_pc_diff = pc_diff;
880
N->pc_desc = pd;
881
}
882
}
883
if (debug) {
884
fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
885
if (pc_diff < 20)
886
fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
887
else
888
fprintf(stderr, "\n\n");
889
}
890
return PS_OK;
891
892
fail:
893
return err;
894
}
895
896
static int
897
scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
898
{
899
uint64_t buffer;
900
int32_t err;
901
902
if (debug > 2) {
903
fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
904
}
905
906
buffer = N->nm + N->scopes_data_beg + decode_offset;
907
908
err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
909
CHECK_FAIL(err);
910
911
err = raw_read_int(N->J, &buffer, &vf->methodIdx);
912
CHECK_FAIL(err);
913
914
err = raw_read_int(N->J, &buffer, &vf->bci);
915
CHECK_FAIL(err);
916
917
if (debug > 2) {
918
fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
919
vf->sender_decode_offset);
920
fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
921
fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
922
923
fprintf(stderr, "\t\t scope_desc_at: END \n\n");
924
}
925
return PS_OK;
926
927
fail:
928
return err;
929
}
930
931
static int scopeDesc_chain(Nmethod_t *N) {
932
int32_t decode_offset = 0;
933
int32_t err;
934
935
if (debug > 2) {
936
fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
937
}
938
939
err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
940
&decode_offset, SZ32);
941
CHECK_FAIL(err);
942
943
while (decode_offset > 0) {
944
Vframe_t *vf = &N->vframes[N->vf_cnt];
945
946
if (debug > 2) {
947
fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
948
}
949
950
err = scope_desc_at(N, decode_offset, vf);
951
CHECK_FAIL(err);
952
953
if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
954
fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
955
return -1;
956
}
957
err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
958
&vf->method);
959
CHECK_FAIL(err);
960
961
if (vf->method) {
962
N->vf_cnt++;
963
err = line_number_from_bci(N->J, vf);
964
CHECK_FAIL(err);
965
if (debug > 2) {
966
fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n",
967
vf->method, vf->line);
968
}
969
}
970
decode_offset = vf->sender_decode_offset;
971
}
972
if (debug > 2) {
973
fprintf(stderr, "\t scopeDesc_chain: END \n\n");
974
}
975
return PS_OK;
976
977
fail:
978
if (debug) {
979
fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
980
}
981
return err;
982
}
983
984
985
static int
986
name_for_nmethod(jvm_agent_t* J,
987
uint64_t nm,
988
uint64_t pc,
989
uint64_t method,
990
char *result,
991
size_t size,
992
Jframe_t *jframe
993
) {
994
Nmethod_t *N;
995
Vframe_t *vf;
996
int32_t err;
997
int deoptimized = 0;
998
999
if (debug) {
1000
fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
1001
}
1002
if (J->N == NULL) {
1003
J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
1004
}
1005
memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */
1006
N = J->N;
1007
N->J = J;
1008
N->nm = nm;
1009
N->pc = pc;
1010
N->jframe = jframe;
1011
1012
err = nmethod_info(N);
1013
CHECK_FAIL(err);
1014
if (debug) {
1015
fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n",
1016
pc, N->nm + N->deopt_beg);
1017
}
1018
1019
/* check for a deoptimized frame */
1020
if ( pc == N->nm + N->deopt_beg) {
1021
uint64_t base;
1022
if (debug) {
1023
fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
1024
}
1025
if (J->prev_fr.sender_sp != 0) {
1026
base = J->prev_fr.sender_sp + N->orig_pc_offset;
1027
} else {
1028
base = J->curr_fr.sp + N->orig_pc_offset;
1029
}
1030
err = read_pointer(J, base, &N->pc);
1031
CHECK_FAIL(err);
1032
if (debug) {
1033
fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
1034
pc, N->pc);
1035
}
1036
deoptimized = 1;
1037
}
1038
1039
err = pc_desc_at(N);
1040
CHECK_FAIL(err);
1041
1042
if (N->pc_desc > 0) {
1043
jframe->locinf = 1;
1044
err = scopeDesc_chain(N);
1045
CHECK_FAIL(err);
1046
}
1047
result[0] = COMP_METHOD_SIGN;
1048
vf = &N->vframes[0];
1049
if (N->vf_cnt > 0) {
1050
jframe->vf_cnt = N->vf_cnt;
1051
jframe->bci = vf->bci;
1052
jframe->line = vf->line;
1053
err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
1054
CHECK_FAIL(err);
1055
} else {
1056
err = name_for_methodPtr(J, method, result+1, size-1);
1057
CHECK_FAIL(err);
1058
}
1059
if (deoptimized) {
1060
strncat(result, " [deoptimized frame]; ", size - strlen(result) - 1);
1061
} else {
1062
strncat(result, " [compiled] ", size - strlen(result) - 1);
1063
}
1064
if (debug)
1065
fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
1066
result, N->vf_cnt);
1067
return PS_OK;
1068
1069
fail:
1070
if (debug)
1071
fprintf(stderr, "name_for_nmethod: FAIL \n\n");
1072
return err;
1073
}
1074
1075
int is_bci(intptr_t bcx) {
1076
switch (DATA_MODEL) {
1077
case PR_MODEL_LP64:
1078
return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
1079
case PR_MODEL_ILP32:
1080
default:
1081
return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
1082
}
1083
}
1084
1085
static int
1086
name_for_imethod(jvm_agent_t* J,
1087
uint64_t bcx,
1088
uint64_t method,
1089
char *result,
1090
size_t size,
1091
Jframe_t *jframe
1092
) {
1093
uint64_t bci;
1094
uint64_t constMethod;
1095
Vframe_t vframe = {0};
1096
Vframe_t *vf = &vframe;
1097
int32_t err;
1098
1099
err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
1100
CHECK_FAIL(err);
1101
1102
bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_ConstMethod);
1103
1104
if (debug)
1105
fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
1106
1107
err = name_for_methodPtr(J, method, result, size);
1108
CHECK_FAIL(err);
1109
if (debug)
1110
fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
1111
1112
if (bci > 0) {
1113
vf->method = method;
1114
vf->bci = bci;
1115
err = line_number_from_bci(J, vf);
1116
CHECK_FAIL(err);
1117
}
1118
jframe->bci = vf->bci;
1119
jframe->line = vf->line;
1120
jframe->locinf = 1;
1121
1122
if (debug) {
1123
fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
1124
vf->bci, vf->line);
1125
}
1126
return PS_OK;
1127
1128
fail:
1129
if (debug)
1130
fprintf(stderr, "\t name_for_imethod: FAIL\n");
1131
return err;
1132
}
1133
1134
static int
1135
name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
1136
size_t size, Jframe_t *jframe, int* is_interpreted)
1137
{
1138
uint64_t start;
1139
uint64_t vtbl;
1140
int32_t err;
1141
*is_interpreted = 0;
1142
1143
result[0] = '\0';
1144
1145
err = find_start(J, pc, &start);
1146
CHECK_FAIL(err);
1147
1148
err = read_pointer(J, start, &vtbl);
1149
CHECK_FAIL(err);
1150
1151
if (vtbl == J->nmethod_vtbl) {
1152
uint64_t method;
1153
1154
err = read_pointer(J, start + OFFSET_nmethod_method, &method);
1155
CHECK_FAIL(err);
1156
1157
if (debug) {
1158
fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
1159
start, pc, method);
1160
}
1161
err = name_for_nmethod(J, start, pc, method, result, size, jframe);
1162
CHECK_FAIL(err);
1163
} else if (vtbl == J->BufferBlob_vtbl) {
1164
const char * name;
1165
1166
err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1167
1168
/*
1169
* Temporary usage of string "Interpreter".
1170
* We need some other way to distinguish "StubRoutines"
1171
* and regular interpreted frames.
1172
*/
1173
if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
1174
*is_interpreted = 1;
1175
if (is_method(J, J->methodPtr)) {
1176
return name_for_imethod(J, J->bcx, J->methodPtr, result, size, jframe);
1177
}
1178
}
1179
1180
if (err == PS_OK) {
1181
strncpy(result, name, size);
1182
free((void*)name);
1183
} else {
1184
strncpy(result, "<unknown BufferBlob>", size);
1185
}
1186
/* return PS_OK; */
1187
} else {
1188
const char * name;
1189
1190
err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1191
if (err == PS_OK) {
1192
strncpy(result, name, size);
1193
free((void*)name);
1194
} else {
1195
strncpy(result, "<unknown CodeBlob>", size);
1196
WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
1197
}
1198
}
1199
result[size-1] = '\0';
1200
1201
#ifdef X86_COMPILER2
1202
if (vtbl != J->RuntimeStub_vtbl) {
1203
uint64_t trial_pc;
1204
int frame_size;
1205
err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
1206
&frame_size, SZ32);
1207
CHECK_FAIL(err);
1208
1209
// frame_size is in words, we want bytes.
1210
frame_size *= POINTER_SIZE; /* word => byte conversion */
1211
1212
/*
1213
Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
1214
in the initial entry to a set of stack frames containing server frames
1215
will pretty much be nonsense. We can detect that nonsense by looking to
1216
see if the PC we received is correct if we look at the expected storage
1217
location in relation to the FP (ie. POINTER_SIZE(FP) )
1218
*/
1219
1220
err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
1221
if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
1222
// Either we couldn't even read at the "fp" or the pc didn't match
1223
// both are sure clues that the fp is bogus. We no search the stack
1224
// for a reasonable number of words trying to find the bogus fp
1225
// and the current pc in adjacent words. The we will be able to
1226
// deduce an approximation of the frame pointer and actually get
1227
// the correct stack pointer. Which we can then unwind for the
1228
// next frame.
1229
int i;
1230
uint64_t check;
1231
uint64_t base = J->curr_fr.sp;
1232
uint64_t prev_fp = 0;
1233
for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
1234
err = read_pointer(J, base , &check);
1235
CHECK_FAIL(err);
1236
if (check == fp) {
1237
base += POINTER_SIZE;
1238
err = read_pointer(J, base , &check);
1239
CHECK_FAIL(err);
1240
if (check == pc) {
1241
if (debug) {
1242
fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
1243
}
1244
prev_fp = base - 2 * POINTER_SIZE;
1245
break;
1246
}
1247
}
1248
}
1249
if ( prev_fp != 0 ) {
1250
// real_sp is the sp we should have received for this frame
1251
uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
1252
// +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
1253
jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
1254
err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
1255
CHECK_FAIL(err);
1256
err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
1257
CHECK_FAIL(err);
1258
return PS_OK;
1259
}
1260
}
1261
1262
/* A prototype to workaround FP absence */
1263
/*
1264
* frame_size can be 0 for StubRoutines (1) frame.
1265
* In this case it should work with fp as usual.
1266
*/
1267
if (frame_size > 0) {
1268
jframe->new_fp = J->prev_fr.fp + frame_size;
1269
jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
1270
} else {
1271
memset(&J->curr_fr, 0, sizeof(Frame_t));
1272
err = read_pointer(J, fp, &jframe->new_fp);
1273
CHECK_FAIL(err);
1274
1275
err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
1276
CHECK_FAIL(err);
1277
}
1278
if (debug) {
1279
fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
1280
result, frame_size);
1281
fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
1282
J->prev_fr.fp, jframe->new_fp);
1283
}
1284
}
1285
#endif /* X86_COMPILER2 */
1286
1287
return PS_OK;
1288
1289
fail:
1290
return err;
1291
}
1292
1293
int Jget_vframe(jvm_agent_t* J, int vframe_no,
1294
char *name, size_t size, Jframe_t *jframe)
1295
{
1296
Nmethod_t *N = J->N;
1297
Vframe_t *vf;
1298
int32_t err;
1299
1300
if (vframe_no >= N->vf_cnt) {
1301
(void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
1302
return -1;
1303
}
1304
vf = N->vframes + vframe_no;
1305
name[0] = COMP_METHOD_SIGN;
1306
err = name_for_methodPtr(J, vf->method, name + 1, size);
1307
CHECK_FAIL(err);
1308
1309
jframe->bci = vf->bci;
1310
jframe->line = vf->line;
1311
if (debug) {
1312
fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
1313
name, vf->line);
1314
}
1315
return PS_OK;
1316
1317
fail:
1318
if (debug) {
1319
fprintf(stderr, "\t Jget_vframe: FAIL\n");
1320
}
1321
return err;
1322
}
1323
1324
#define MAX_SYM_SIZE 256
1325
1326
int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
1327
size_t size, Jframe_t *jframe) {
1328
uintptr_t fp;
1329
uintptr_t pc;
1330
/* arguments given to read_pointer need to be worst case sized */
1331
uint64_t methodPtr = 0;
1332
uint64_t sender_sp;
1333
uint64_t bcx = 0;
1334
int is_interpreted = 0;
1335
int result = PS_OK;
1336
int err = PS_OK;
1337
1338
if (J == NULL) {
1339
return -1;
1340
}
1341
1342
jframe->vf_cnt = 1;
1343
jframe->new_fp = 0;
1344
jframe->new_pc = 0;
1345
jframe->line = 0;
1346
jframe->bci = 0;
1347
jframe->locinf = 0;
1348
1349
read_volatiles(J);
1350
pc = (uintptr_t) regs[R_PC];
1351
J->curr_fr.pc = pc;
1352
J->curr_fr.fp = regs[R_FP];
1353
J->curr_fr.sp = regs[R_SP];
1354
1355
if (debug)
1356
fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
1357
1358
#if defined(sparc) || defined(__sparc)
1359
/* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
1360
* In the pcDesc structure return pc offset is recorded for CALL instructions.
1361
* regs[R_PC] contains a CALL instruction pc offset.
1362
*/
1363
pc += 8;
1364
bcx = (uintptr_t) regs[R_L1];
1365
methodPtr = (uintptr_t) regs[R_L2];
1366
sender_sp = regs[R_I5];
1367
if (debug > 2) {
1368
fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
1369
regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
1370
}
1371
#elif defined(i386) || defined(__i386) || defined(__amd64)
1372
1373
fp = (uintptr_t) regs[R_FP];
1374
if (J->prev_fr.fp == 0) {
1375
#ifdef X86_COMPILER2
1376
/* A workaround for top java frames */
1377
J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
1378
#else
1379
J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
1380
#endif /* COMPILER2 */
1381
}
1382
if (debug > 2) {
1383
printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
1384
}
1385
1386
if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
1387
methodPtr = 0;
1388
}
1389
if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
1390
sender_sp = 0;
1391
}
1392
if (read_pointer(J, fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
1393
bcx = 0;
1394
}
1395
#endif /* i386 */
1396
1397
J->methodPtr = methodPtr;
1398
J->bcx = bcx;
1399
1400
/* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
1401
* For example: JVM_SuspendThread frame poins to the top interpreted frame.
1402
* If we call is_method(J, methodPtr) before codecache_contains(J, pc)
1403
* then we go over and omit both: nmethod and I2CAdapter frames.
1404
* Note, that regs[R_PC] is always correct if frame defined correctly.
1405
* So it is better to call codecache_contains(J, pc) from the beginning.
1406
*/
1407
#ifndef X86_COMPILER2
1408
if (is_method(J, J->methodPtr)) {
1409
result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
1410
/* If the methodPtr is a method then this is highly likely to be
1411
an interpreter frame */
1412
if (result >= 0) {
1413
is_interpreted = 1;
1414
}
1415
} else
1416
#endif /* ! X86_COMPILER2 */
1417
1418
if (codecache_contains(J, pc)) {
1419
result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
1420
}
1421
#ifdef X86_COMPILER2
1422
else if (is_method(J, J->methodPtr)) {
1423
result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
1424
/* If the methodPtr is a method then this is highly likely to be
1425
an interpreter frame */
1426
if (result >= 0) {
1427
is_interpreted = 1;
1428
}
1429
}
1430
#endif /* X86_COMPILER2 */
1431
else {
1432
if (debug) {
1433
fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
1434
}
1435
result = -1;
1436
}
1437
if (!is_interpreted) {
1438
sender_sp = 0;
1439
}
1440
J->curr_fr.sender_sp = sender_sp;
1441
1442
#ifdef X86_COMPILER2
1443
if (!J->curr_fr.fp) {
1444
J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
1445
}
1446
if (!jframe->new_pc && jframe->new_fp) {
1447
// This seems dubious
1448
read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
1449
CHECK_FAIL(err);
1450
if (debug > 2) {
1451
printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
1452
jframe->new_fp, jframe->new_pc);
1453
}
1454
}
1455
1456
#endif /* X86_COMPILER2 */
1457
J->prev_fr = J->curr_fr;
1458
1459
if (debug)
1460
fprintf(stderr, "Jlookup_by_regs: END\n\n");
1461
1462
return result;
1463
1464
fail:
1465
return err;
1466
}
1467
1468
void update_gregs(prgregset_t gregs, Jframe_t jframe) {
1469
#ifdef X86_COMPILER2
1470
if (debug > 0) {
1471
fprintf(stderr, "update_gregs: before update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
1472
}
1473
/*
1474
* A workaround for java C2 frames with unconventional FP.
1475
* may have to modify regset with new values for FP/PC/SP when needed.
1476
*/
1477
if (jframe.new_sp) {
1478
*((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
1479
} else {
1480
// *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
1481
}
1482
1483
if (jframe.new_fp) {
1484
*((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
1485
}
1486
if (jframe.new_pc) {
1487
*((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
1488
}
1489
if (debug > 0) {
1490
fprintf(stderr, "update_gregs: after update sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
1491
}
1492
#endif /* X86_COMPILER2 */
1493
}
1494
1495
/*
1496
* Iterates over java frames at current location given by 'gregs'.
1497
*
1498
* Returns -1 if no java frames are present or if an error is encountered.
1499
* Returns the result of calling 'func' if the return value is non-zero.
1500
* Returns 0 otherwise.
1501
*/
1502
int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
1503
char buf[MAX_SYM_SIZE + 1];
1504
Jframe_t jframe;
1505
int i = 0, res;
1506
#ifdef X86_COMPILER2
1507
if (debug > 0) {
1508
fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
1509
}
1510
#endif /* X86_COMPILER2 */
1511
1512
memset(&jframe, 0, sizeof(Jframe_t));
1513
memset(buf, 0, sizeof(buf));
1514
res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
1515
if (res != PS_OK)
1516
return (-1);
1517
1518
1519
res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
1520
jframe.line, NULL);
1521
if (res != 0) {
1522
update_gregs(gregs, jframe);
1523
return (res);
1524
}
1525
for (i = 1; i < jframe.vf_cnt; i++) {
1526
Jget_vframe(J, i, buf, sizeof(buf), &jframe);
1527
res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
1528
jframe.line, NULL);
1529
if (res != 0) {
1530
update_gregs(gregs, jframe);
1531
return (res);
1532
}
1533
}
1534
update_gregs(gregs, jframe);
1535
return (0);
1536
}
1537
1538