src/os/solaris/dtrace/libjvm_db.c

Wed, 02 Jun 2010 22:45:42 -0700

author
jrose
date
Wed, 02 Jun 2010 22:45:42 -0700
changeset 1934
e9ff18c4ace7
parent 1907
c18cbe5936b8
parent 1918
1a5913bf5e19
child 2103
3e8fbc61cee8
permissions
-rw-r--r--

Merge

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

mercurial