src/os/solaris/dtrace/libjvm_db.c

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

mercurial