comparison src/os/bsd/dtrace/libjvm_db.c @ 4006:436b4a3231bf

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