src/os/solaris/dtrace/libjvm_db.c

Wed, 16 Mar 2011 14:57:49 -0400

author
coleenp
date
Wed, 16 Mar 2011 14:57:49 -0400
changeset 2626
8a3f8defe568
parent 2497
3582bf76420e
child 2708
1d1603768966
permissions
-rw-r--r--

7019165: Incorrect symbols in pstack output after SymbolTable changes
Summary: And out lsb which is set for symbols in constant pool slots to distinguish them from strings
Reviewed-by: phh, dholmes, never, dcubed

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 */
twisti@2103 127 int32_t instrs_beg; /* _code_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);
coleenp@2626 527 // The symbol is a CPSlot and has lower bit set to indicate metadata
coleenp@2626 528 nameSymbol &= (~1); // remove metadata lsb
coleenp@2497 529 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
duke@435 530 CHECK_FAIL(err);
duke@435 531 nameString = (char*)calloc(nameSymbolLength + 1, 1);
coleenp@2497 532 err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
duke@435 533 CHECK_FAIL(err);
duke@435 534
duke@435 535 /* To get signature string */
duke@435 536 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_signature_index, &signatureIndex, 2);
duke@435 537 CHECK_FAIL(err);
duke@435 538 err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol);
duke@435 539 CHECK_FAIL(err);
coleenp@2626 540 signatureSymbol &= (~1); // remove metadata lsb
coleenp@2497 541 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
duke@435 542 CHECK_FAIL(err);
duke@435 543 signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
coleenp@2497 544 err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
duke@435 545 CHECK_FAIL(err);
duke@435 546
duke@435 547 /* To get klass string */
duke@435 548 err = read_pointer(J, constantPool + OFFSET_constantPoolOopDesc_pool_holder, &klassPtr);
duke@435 549 CHECK_FAIL(err);
duke@435 550 err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol);
duke@435 551 CHECK_FAIL(err);
coleenp@2497 552 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
duke@435 553 CHECK_FAIL(err);
duke@435 554 klassString = (char*)calloc(klassSymbolLength + 1, 1);
coleenp@2497 555 err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
duke@435 556 CHECK_FAIL(err);
duke@435 557
duke@435 558 result[0] = '\0';
duke@435 559 strncat(result, klassString, size);
duke@435 560 size -= strlen(klassString);
duke@435 561 strncat(result, ".", size);
duke@435 562 size -= 1;
duke@435 563 strncat(result, nameString, size);
duke@435 564 size -= strlen(nameString);
duke@435 565 strncat(result, signatureString, size);
duke@435 566
duke@435 567 if (nameString != NULL) free(nameString);
duke@435 568 if (klassString != NULL) free(klassString);
duke@435 569 if (signatureString != NULL) free(signatureString);
duke@435 570
duke@435 571 return PS_OK;
duke@435 572
duke@435 573 fail:
duke@435 574 if (debug) {
duke@435 575 fprintf(stderr, "name_for_methodOop: FAIL \n\n");
duke@435 576 }
duke@435 577 if (nameString != NULL) free(nameString);
duke@435 578 if (klassString != NULL) free(klassString);
duke@435 579 if (signatureString != NULL) free(signatureString);
duke@435 580 return -1;
duke@435 581 }
duke@435 582
duke@435 583 static int nmethod_info(Nmethod_t *N)
duke@435 584 {
duke@435 585 jvm_agent_t *J = N->J;
duke@435 586 uint64_t nm = N->nm;
duke@435 587 int32_t err;
duke@435 588
duke@435 589 if (debug > 2 )
duke@435 590 fprintf(stderr, "\t nmethod_info: BEGIN \n");
duke@435 591
duke@435 592 /* Instructions */
twisti@2103 593 err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32);
duke@435 594 CHECK_FAIL(err);
duke@435 595 err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
duke@435 596 CHECK_FAIL(err);
duke@435 597 err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
duke@435 598 CHECK_FAIL(err);
duke@435 599 err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
duke@435 600 CHECK_FAIL(err);
duke@435 601
duke@435 602 /* Oops */
twisti@1918 603 err = ps_pread(J->P, nm + OFFSET_nmethod_oops_offset, &N->oops_beg, SZ32);
duke@435 604 CHECK_FAIL(err);
twisti@1918 605 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->oops_end, SZ32);
duke@435 606 CHECK_FAIL(err);
duke@435 607
duke@435 608 /* scopes_pcs */
duke@435 609 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
duke@435 610 CHECK_FAIL(err);
duke@435 611 err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32);
duke@435 612 CHECK_FAIL(err);
duke@435 613
duke@435 614 /* scopes_data */
duke@435 615 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
duke@435 616 CHECK_FAIL(err);
duke@435 617
duke@435 618 if (debug > 2 ) {
duke@435 619 N->scopes_data_end = N->scopes_pcs_beg;
duke@435 620
duke@435 621 fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
duke@435 622 N->instrs_beg, N->instrs_end);
duke@435 623
duke@435 624 fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
duke@435 625 N->deopt_beg);
duke@435 626
duke@435 627 fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
duke@435 628 N->orig_pc_offset);
duke@435 629
twisti@1918 630 fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n",
twisti@1918 631 N->oops_beg, N->oops_end);
duke@435 632
duke@435 633 fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
duke@435 634 N->scopes_data_beg, N->scopes_data_end);
duke@435 635
duke@435 636 fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
duke@435 637 N->scopes_pcs_beg, N->scopes_pcs_end);
duke@435 638
duke@435 639 fprintf(stderr, "\t nmethod_info: END \n\n");
duke@435 640 }
duke@435 641 return PS_OK;
duke@435 642
duke@435 643 fail:
duke@435 644 return err;
duke@435 645 }
duke@435 646
duke@435 647 static int
duke@435 648 raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
duke@435 649 {
duke@435 650 int shift = 0;
duke@435 651 int value = 0;
duke@435 652 uint8_t ch = 0;
duke@435 653 int32_t err;
duke@435 654 int32_t sum;
duke@435 655 // Constants for UNSIGNED5 coding of Pack200
duke@435 656 // see compressedStream.hpp
duke@435 657 enum {
duke@435 658 lg_H = 6,
duke@435 659 H = 1<<lg_H,
duke@435 660 BitsPerByte = 8,
duke@435 661 L = (1<<BitsPerByte)-H,
duke@435 662 };
duke@435 663 int i;
duke@435 664
duke@435 665 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
duke@435 666 CHECK_FAIL(err);
duke@435 667 if (debug > 2)
duke@435 668 fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
duke@435 669
duke@435 670 sum = ch;
duke@435 671 if ( sum >= L ) {
duke@435 672 int32_t lg_H_i = lg_H;
duke@435 673 // Read maximum of 5 total bytes (we've already read 1).
duke@435 674 // See CompressedReadStream::read_int_mb
duke@435 675 for ( i = 0; i < 4; i++) {
duke@435 676 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
duke@435 677 CHECK_FAIL(err);
duke@435 678 sum += ch << lg_H_i;
duke@435 679 if (ch < L ) {
duke@435 680 *val = sum;
duke@435 681 return PS_OK;
duke@435 682 }
duke@435 683 lg_H_i += lg_H;
duke@435 684 }
duke@435 685 }
duke@435 686 *val = sum;
duke@435 687 return PS_OK;
duke@435 688
duke@435 689 fail:
duke@435 690 return err;
duke@435 691 }
duke@435 692
duke@435 693 static int
duke@435 694 read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
duke@435 695 {
duke@435 696 uint8_t next = 0;
duke@435 697 int32_t bci_delta;
duke@435 698 int32_t line_delta;
duke@435 699 int32_t err;
duke@435 700
duke@435 701 if (debug > 2)
duke@435 702 fprintf(stderr, "\t\t read_pair: BEGIN\n");
duke@435 703
duke@435 704 err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
duke@435 705 CHECK_FAIL(err);
duke@435 706
duke@435 707 if (next == 0) {
duke@435 708 if (debug > 2)
duke@435 709 fprintf(stderr, "\t\t read_pair: END: next == 0\n");
duke@435 710 return 1; /* stream terminated */
duke@435 711 }
duke@435 712 if (next == 0xFF) {
duke@435 713 if (debug > 2)
duke@435 714 fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
duke@435 715
duke@435 716 /* Escape character, regular compression used */
duke@435 717
duke@435 718 err = raw_read_int(J, buffer, &bci_delta);
duke@435 719 CHECK_FAIL(err);
duke@435 720
duke@435 721 err = raw_read_int(J, buffer, &line_delta);
duke@435 722 CHECK_FAIL(err);
duke@435 723
duke@435 724 *bci += bci_delta;
duke@435 725 *line += line_delta;
duke@435 726
duke@435 727 if (debug > 2) {
duke@435 728 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
duke@435 729 line_delta, bci_delta);
duke@435 730 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
duke@435 731 *line, *bci);
duke@435 732 }
duke@435 733 } else {
duke@435 734 /* Single byte compression used */
duke@435 735 *bci += next >> 3;
duke@435 736 *line += next & 0x7;
duke@435 737 if (debug > 2) {
duke@435 738 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
duke@435 739 next & 0x7, next >> 3);
duke@435 740 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
duke@435 741 *line, *bci);
duke@435 742 }
duke@435 743 }
duke@435 744 if (debug > 2)
duke@435 745 fprintf(stderr, "\t\t read_pair: END\n");
duke@435 746 return PS_OK;
duke@435 747
duke@435 748 fail:
duke@435 749 if (debug)
duke@435 750 fprintf(stderr, "\t\t read_pair: FAIL\n");
duke@435 751 return err;
duke@435 752 }
duke@435 753
duke@435 754 static int
duke@435 755 line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
duke@435 756 {
duke@435 757 uint64_t buffer;
duke@435 758 uint16_t code_size;
duke@435 759 uint64_t code_end_delta;
duke@435 760 uint64_t constMethod;
duke@435 761 int8_t access_flags;
duke@435 762 int32_t best_bci = 0;
duke@435 763 int32_t stream_bci = 0;
duke@435 764 int32_t stream_line = 0;
duke@435 765 int32_t err;
duke@435 766
duke@435 767 if (debug > 2) {
duke@435 768 char name[256];
duke@435 769 err = name_for_methodOop(J, vf->methodOop, name, 256);
duke@435 770 CHECK_FAIL(err);
duke@435 771 fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
duke@435 772 name, vf->bci);
duke@435 773 }
duke@435 774
duke@435 775 err = read_pointer(J, vf->methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
duke@435 776 CHECK_FAIL(err);
duke@435 777
duke@435 778 vf->line = 0;
duke@435 779 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_flags, &access_flags, sizeof(int8_t));
duke@435 780 CHECK_FAIL(err);
duke@435 781
duke@435 782 if (!(access_flags & constMethodOopDesc_has_linenumber_table)) {
duke@435 783 if (debug > 2)
duke@435 784 fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
duke@435 785 return PS_OK;
duke@435 786 }
duke@435 787
duke@435 788 /* The line numbers are a short array of 2-tuples [start_pc, line_number].
duke@435 789 * Not necessarily sorted and not necessarily one-to-one.
duke@435 790 */
duke@435 791
duke@435 792 err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_code_size, &code_size, SZ16);
duke@435 793 CHECK_FAIL(err);
duke@435 794
duke@435 795 /* inlined_table_start() */
duke@435 796 code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
duke@435 797 buffer = constMethod + (uint64_t) SIZE_constMethodOopDesc + (uint64_t) code_size + code_end_delta;
duke@435 798
duke@435 799 if (debug > 2) {
duke@435 800 fprintf(stderr, "\t\t line_number_from_bci: methodOop: %#llx, native: %d\n",
duke@435 801 vf->methodOop, (access_flags & AccessFlags_NATIVE));
duke@435 802 fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
duke@435 803 buffer, (int) code_size);
duke@435 804 }
duke@435 805
duke@435 806 while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
duke@435 807 if (stream_bci == vf->bci) {
duke@435 808 /* perfect match */
duke@435 809 if (debug > 2)
duke@435 810 fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
duke@435 811 vf->line = stream_line;
duke@435 812 return PS_OK;
duke@435 813 } else {
duke@435 814 /* update best_bci/line */
duke@435 815 if (stream_bci < vf->bci && stream_bci >= best_bci) {
duke@435 816 best_bci = stream_bci;
duke@435 817 vf->line = stream_line;
duke@435 818 if (debug > 2) {
duke@435 819 fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
duke@435 820 best_bci, vf->line);
duke@435 821 }
duke@435 822 }
duke@435 823 }
duke@435 824 }
duke@435 825 if (debug > 2)
duke@435 826 fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
duke@435 827 return PS_OK;
duke@435 828
duke@435 829 fail:
duke@435 830 if (debug)
duke@435 831 fprintf(stderr, "\t line_number_from_bci: FAIL\n");
duke@435 832 return err;
duke@435 833 }
duke@435 834
duke@435 835 static int
duke@435 836 get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
duke@435 837 {
duke@435 838 int32_t pc_offset;
duke@435 839 int32_t err;
duke@435 840
duke@435 841 err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
duke@435 842 CHECK_FAIL(err);
duke@435 843
duke@435 844 *real_pc = N->nm + N->instrs_beg + pc_offset;
duke@435 845 if (debug > 2) {
duke@435 846 fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
duke@435 847 pc_offset, *real_pc);
duke@435 848 }
duke@435 849 return PS_OK;
duke@435 850
duke@435 851 fail:
duke@435 852 return err;
duke@435 853 }
duke@435 854
duke@435 855 /* Finds a PcDesc with real-pc equal to N->pc */
duke@435 856 static int pc_desc_at(Nmethod_t *N)
duke@435 857 {
duke@435 858 uint64_t pc_diff;
duke@435 859 int32_t offs;
duke@435 860 int32_t err;
duke@435 861
duke@435 862 if (debug > 2)
duke@435 863 fprintf(stderr, "\t pc_desc_at: BEGIN\n");
duke@435 864
duke@435 865 N->vf_cnt = 0;
duke@435 866 N->pc_desc = 0;
duke@435 867
duke@435 868 for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
duke@435 869 uint64_t pd;
duke@435 870 uint64_t best_pc_diff = 16; /* some approximation */
duke@435 871 uint64_t real_pc = 0;
duke@435 872
duke@435 873 pd = N->nm + offs;
duke@435 874 err = get_real_pc(N, pd, &real_pc);
duke@435 875 CHECK_FAIL(err);
duke@435 876
duke@435 877 pc_diff = real_pc - N->pc;
duke@435 878
duke@435 879 /* In general, this fragment should work */
duke@435 880 if (pc_diff == 0) {
duke@435 881 N->pc_desc = pd;
duke@435 882 if (debug) {
duke@435 883 fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
duke@435 884 }
duke@435 885 return PS_OK;
duke@435 886 }
duke@435 887 /* This fragment is to be able to find out an appropriate
duke@435 888 * pc_desc entry even if pc_desc info is inaccurate.
duke@435 889 */
duke@435 890 if (best_pc_diff > pc_diff && pc_diff > 0) {
duke@435 891 best_pc_diff = pc_diff;
duke@435 892 N->pc_desc = pd;
duke@435 893 }
duke@435 894 }
duke@435 895 if (debug) {
duke@435 896 fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
duke@435 897 if (pc_diff < 20)
duke@435 898 fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
duke@435 899 else
duke@435 900 fprintf(stderr, "\n\n");
duke@435 901 }
duke@435 902 return PS_OK;
duke@435 903
duke@435 904 fail:
duke@435 905 return err;
duke@435 906 }
duke@435 907
duke@435 908 static int
duke@435 909 scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
duke@435 910 {
duke@435 911 uint64_t buffer;
duke@435 912 int32_t err;
duke@435 913
duke@435 914 if (debug > 2) {
duke@435 915 fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
duke@435 916 }
duke@435 917
duke@435 918 buffer = N->nm + N->scopes_data_beg + decode_offset;
duke@435 919
duke@435 920 err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
duke@435 921 CHECK_FAIL(err);
duke@435 922
duke@435 923 err = raw_read_int(N->J, &buffer, &vf->methodIdx);
duke@435 924 CHECK_FAIL(err);
duke@435 925
duke@435 926 err = raw_read_int(N->J, &buffer, &vf->bci);
duke@435 927 CHECK_FAIL(err);
duke@435 928
duke@435 929 if (debug > 2) {
duke@435 930 fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
duke@435 931 vf->sender_decode_offset);
duke@435 932 fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
duke@435 933 fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
duke@435 934
duke@435 935 fprintf(stderr, "\t\t scope_desc_at: END \n\n");
duke@435 936 }
duke@435 937 return PS_OK;
duke@435 938
duke@435 939 fail:
duke@435 940 return err;
duke@435 941 }
duke@435 942
phh@1558 943 static int scopeDesc_chain(Nmethod_t *N) {
duke@435 944 int32_t decode_offset = 0;
duke@435 945 int32_t err;
duke@435 946
phh@1558 947 if (debug > 2) {
phh@1558 948 fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
phh@1558 949 }
duke@435 950
duke@435 951 err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
duke@435 952 &decode_offset, SZ32);
duke@435 953 CHECK_FAIL(err);
duke@435 954
duke@435 955 while (decode_offset > 0) {
phh@1558 956 Vframe_t *vf = &N->vframes[N->vf_cnt];
duke@435 957
phh@1558 958 if (debug > 2) {
phh@1558 959 fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
phh@1558 960 }
duke@435 961
phh@1558 962 err = scope_desc_at(N, decode_offset, vf);
phh@1558 963 CHECK_FAIL(err);
phh@1558 964
twisti@1918 965 if (vf->methodIdx > ((N->oops_end - N->oops_beg) / POINTER_SIZE)) {
twisti@1918 966 fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops length) !\n");
phh@1558 967 return -1;
phh@1558 968 }
phh@1558 969 err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE,
phh@1558 970 &vf->methodOop);
phh@1558 971 CHECK_FAIL(err);
phh@1558 972
phh@1558 973 if (vf->methodOop) {
phh@1558 974 N->vf_cnt++;
phh@1558 975 err = line_number_from_bci(N->J, vf);
duke@435 976 CHECK_FAIL(err);
phh@1558 977 if (debug > 2) {
phh@1558 978 fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n",
phh@1558 979 vf->methodOop, vf->line);
duke@435 980 }
phh@1558 981 }
phh@1558 982 decode_offset = vf->sender_decode_offset;
duke@435 983 }
phh@1558 984 if (debug > 2) {
phh@1558 985 fprintf(stderr, "\t scopeDesc_chain: END \n\n");
phh@1558 986 }
duke@435 987 return PS_OK;
duke@435 988
duke@435 989 fail:
phh@1558 990 if (debug) {
phh@1558 991 fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
phh@1558 992 }
duke@435 993 return err;
duke@435 994 }
duke@435 995
duke@435 996
duke@435 997 static int
duke@435 998 name_for_nmethod(jvm_agent_t* J,
duke@435 999 uint64_t nm,
duke@435 1000 uint64_t pc,
duke@435 1001 uint64_t methodOop,
duke@435 1002 char *result,
duke@435 1003 size_t size,
duke@435 1004 Jframe_t *jframe
duke@435 1005 ) {
duke@435 1006 Nmethod_t *N;
duke@435 1007 Vframe_t *vf;
duke@435 1008 int32_t err;
duke@435 1009 int deoptimized = 0;
duke@435 1010
duke@435 1011 if (debug) {
duke@435 1012 fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
duke@435 1013 }
duke@435 1014 if (J->N == NULL) {
duke@435 1015 J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
duke@435 1016 }
duke@435 1017 memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */
duke@435 1018 N = J->N;
duke@435 1019 N->J = J;
duke@435 1020 N->nm = nm;
duke@435 1021 N->pc = pc;
duke@435 1022 N->jframe = jframe;
duke@435 1023
duke@435 1024 err = nmethod_info(N);
duke@435 1025 CHECK_FAIL(err);
duke@435 1026 if (debug) {
duke@435 1027 fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n",
duke@435 1028 pc, N->nm + N->deopt_beg);
duke@435 1029 }
duke@435 1030
duke@435 1031 /* check for a deoptimized frame */
duke@435 1032 if ( pc == N->nm + N->deopt_beg) {
duke@435 1033 uint64_t base;
duke@435 1034 if (debug) {
duke@435 1035 fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
duke@435 1036 }
duke@435 1037 if (J->prev_fr.sender_sp != 0) {
duke@435 1038 base = J->prev_fr.sender_sp + N->orig_pc_offset;
duke@435 1039 } else {
duke@435 1040 base = J->curr_fr.sp + N->orig_pc_offset;
duke@435 1041 }
duke@435 1042 err = read_pointer(J, base, &N->pc);
duke@435 1043 CHECK_FAIL(err);
duke@435 1044 if (debug) {
duke@435 1045 fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
duke@435 1046 pc, N->pc);
duke@435 1047 }
duke@435 1048 deoptimized = 1;
duke@435 1049 }
duke@435 1050
duke@435 1051 err = pc_desc_at(N);
duke@435 1052 CHECK_FAIL(err);
duke@435 1053
duke@435 1054 if (N->pc_desc > 0) {
duke@435 1055 jframe->locinf = 1;
duke@435 1056 err = scopeDesc_chain(N);
duke@435 1057 CHECK_FAIL(err);
duke@435 1058 }
duke@435 1059 result[0] = COMP_METHOD_SIGN;
duke@435 1060 vf = &N->vframes[0];
duke@435 1061 if (N->vf_cnt > 0) {
duke@435 1062 jframe->vf_cnt = N->vf_cnt;
duke@435 1063 jframe->bci = vf->bci;
duke@435 1064 jframe->line = vf->line;
duke@435 1065 err = name_for_methodOop(J, N->vframes[0].methodOop, result+1, size-1);
duke@435 1066 CHECK_FAIL(err);
duke@435 1067 } else {
duke@435 1068 err = name_for_methodOop(J, methodOop, result+1, size-1);
duke@435 1069 CHECK_FAIL(err);
duke@435 1070 }
duke@435 1071 if (deoptimized) {
duke@435 1072 strncat(result + 1, " [deoptimized frame]; ", size-1);
duke@435 1073 } else {
duke@435 1074 strncat(result + 1, " [compiled] ", size-1);
duke@435 1075 }
duke@435 1076 if (debug)
duke@435 1077 fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
duke@435 1078 result, N->vf_cnt);
duke@435 1079 return PS_OK;
duke@435 1080
duke@435 1081 fail:
duke@435 1082 if (debug)
duke@435 1083 fprintf(stderr, "name_for_nmethod: FAIL \n\n");
duke@435 1084 return err;
duke@435 1085 }
duke@435 1086
duke@435 1087 int is_bci(intptr_t bcx) {
duke@435 1088 switch (DATA_MODEL) {
duke@435 1089 case PR_MODEL_LP64:
duke@435 1090 return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
duke@435 1091 case PR_MODEL_ILP32:
duke@435 1092 default:
duke@435 1093 return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
duke@435 1094 }
duke@435 1095 }
duke@435 1096
duke@435 1097 static int
duke@435 1098 name_for_imethod(jvm_agent_t* J,
duke@435 1099 uint64_t bcx,
duke@435 1100 uint64_t methodOop,
duke@435 1101 char *result,
duke@435 1102 size_t size,
duke@435 1103 Jframe_t *jframe
duke@435 1104 ) {
duke@435 1105 uint64_t bci;
duke@435 1106 uint64_t constMethod;
duke@435 1107 Vframe_t vframe = {0};
duke@435 1108 Vframe_t *vf = &vframe;
duke@435 1109 int32_t err;
duke@435 1110
duke@435 1111 err = read_pointer(J, methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
duke@435 1112 CHECK_FAIL(err);
duke@435 1113
duke@435 1114 bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_constMethodOopDesc);
duke@435 1115
duke@435 1116 if (debug)
duke@435 1117 fprintf(stderr, "\t name_for_imethod: BEGIN: methodOop: %#llx\n", methodOop);
duke@435 1118
duke@435 1119 err = name_for_methodOop(J, methodOop, result, size);
duke@435 1120 CHECK_FAIL(err);
duke@435 1121 if (debug)
duke@435 1122 fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
duke@435 1123
duke@435 1124 if (bci > 0) {
duke@435 1125 vf->methodOop = methodOop;
duke@435 1126 vf->bci = bci;
duke@435 1127 err = line_number_from_bci(J, vf);
duke@435 1128 CHECK_FAIL(err);
duke@435 1129 }
duke@435 1130 jframe->bci = vf->bci;
duke@435 1131 jframe->line = vf->line;
duke@435 1132 jframe->locinf = 1;
duke@435 1133
duke@435 1134 if (debug) {
duke@435 1135 fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
duke@435 1136 vf->bci, vf->line);
duke@435 1137 }
duke@435 1138 return PS_OK;
duke@435 1139
duke@435 1140 fail:
duke@435 1141 if (debug)
duke@435 1142 fprintf(stderr, "\t name_for_imethod: FAIL\n");
duke@435 1143 return err;
duke@435 1144 }
duke@435 1145
duke@435 1146 static int
duke@435 1147 name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
duke@435 1148 size_t size, Jframe_t *jframe, int* is_interpreted)
duke@435 1149 {
duke@435 1150 uint64_t start;
duke@435 1151 uint64_t vtbl;
duke@435 1152 int32_t err;
duke@435 1153 *is_interpreted = 0;
duke@435 1154
duke@435 1155 result[0] = '\0';
duke@435 1156
duke@435 1157 err = find_start(J, pc, &start);
duke@435 1158 CHECK_FAIL(err);
duke@435 1159
duke@435 1160 err = read_pointer(J, start, &vtbl);
duke@435 1161 CHECK_FAIL(err);
duke@435 1162
duke@435 1163 if (vtbl == J->nmethod_vtbl) {
duke@435 1164 uint64_t methodOop;
duke@435 1165
duke@435 1166 err = read_pointer(J, start + OFFSET_nmethod_method, &methodOop);
duke@435 1167 CHECK_FAIL(err);
duke@435 1168
duke@435 1169 if (debug) {
duke@435 1170 fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, methodOop: %#8llx \n",
duke@435 1171 start, pc, methodOop);
duke@435 1172 }
duke@435 1173 err = name_for_nmethod(J, start, pc, methodOop, result, size, jframe);
duke@435 1174 CHECK_FAIL(err);
duke@435 1175 } else if (vtbl == J->BufferBlob_vtbl) {
duke@435 1176 const char * name;
duke@435 1177
duke@435 1178 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
duke@435 1179
duke@435 1180 /*
duke@435 1181 * Temporary usage of string "Interpreter".
duke@435 1182 * We need some other way to distinguish "StubRoutines"
duke@435 1183 * and regular interpreted frames.
duke@435 1184 */
duke@435 1185 if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
duke@435 1186 *is_interpreted = 1;
duke@435 1187 if (is_methodOop(J, J->methodOopPtr)) {
duke@435 1188 return name_for_imethod(J, J->bcx, J->methodOopPtr, result, size, jframe);
duke@435 1189 }
duke@435 1190 }
duke@435 1191
duke@435 1192 if (err == PS_OK) {
duke@435 1193 strncpy(result, name, size);
duke@435 1194 free((void*)name);
duke@435 1195 } else {
duke@435 1196 strncpy(result, "<unknown BufferBlob>", size);
duke@435 1197 }
duke@435 1198 /* return PS_OK; */
duke@435 1199 } else {
duke@435 1200 const char * name;
duke@435 1201
duke@435 1202 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
duke@435 1203 if (err == PS_OK) {
duke@435 1204 strncpy(result, name, size);
duke@435 1205 free((void*)name);
duke@435 1206 } else {
duke@435 1207 strncpy(result, "<unknown CodeBlob>", size);
duke@435 1208 WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
duke@435 1209 }
duke@435 1210 }
duke@435 1211 result[size-1] = '\0';
duke@435 1212
duke@435 1213 #ifdef X86_COMPILER2
duke@435 1214 if (vtbl != J->RuntimeStub_vtbl) {
duke@435 1215 uint64_t trial_pc;
duke@435 1216 int frame_size;
duke@435 1217 err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
duke@435 1218 &frame_size, SZ32);
duke@435 1219 CHECK_FAIL(err);
duke@435 1220
duke@435 1221 // frame_size is in words, we want bytes.
duke@435 1222 frame_size *= POINTER_SIZE; /* word => byte conversion */
duke@435 1223
duke@435 1224 /*
duke@435 1225 Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
duke@435 1226 in the initial entry to a set of stack frames containing server frames
duke@435 1227 will pretty much be nonsense. We can detect that nonsense by looking to
duke@435 1228 see if the PC we received is correct if we look at the expected storage
duke@435 1229 location in relation to the FP (ie. POINTER_SIZE(FP) )
duke@435 1230 */
duke@435 1231
duke@435 1232 err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
duke@435 1233 if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
duke@435 1234 // Either we couldn't even read at the "fp" or the pc didn't match
duke@435 1235 // both are sure clues that the fp is bogus. We no search the stack
duke@435 1236 // for a reasonable number of words trying to find the bogus fp
duke@435 1237 // and the current pc in adjacent words. The we will be able to
duke@435 1238 // deduce an approximation of the frame pointer and actually get
duke@435 1239 // the correct stack pointer. Which we can then unwind for the
duke@435 1240 // next frame.
duke@435 1241 int i;
duke@435 1242 uint64_t check;
duke@435 1243 uint64_t base = J->curr_fr.sp;
duke@435 1244 uint64_t prev_fp = 0;
duke@435 1245 for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
duke@435 1246 err = read_pointer(J, base , &check);
duke@435 1247 CHECK_FAIL(err);
duke@435 1248 if (check == fp) {
duke@435 1249 base += POINTER_SIZE;
duke@435 1250 err = read_pointer(J, base , &check);
duke@435 1251 CHECK_FAIL(err);
duke@435 1252 if (check == pc) {
duke@435 1253 if (debug) {
duke@435 1254 fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
duke@435 1255 }
duke@435 1256 prev_fp = base - 2 * POINTER_SIZE;
duke@435 1257 break;
duke@435 1258 }
duke@435 1259 }
duke@435 1260 }
duke@435 1261 if ( prev_fp != 0 ) {
duke@435 1262 // real_sp is the sp we should have received for this frame
duke@435 1263 uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
duke@435 1264 // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
duke@435 1265 jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
duke@435 1266 err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
duke@435 1267 CHECK_FAIL(err);
duke@435 1268 err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
duke@435 1269 CHECK_FAIL(err);
duke@435 1270 return PS_OK;
duke@435 1271 }
duke@435 1272 }
duke@435 1273
duke@435 1274 /* A prototype to workaround FP absence */
duke@435 1275 /*
duke@435 1276 * frame_size can be 0 for StubRoutines (1) frame.
duke@435 1277 * In this case it should work with fp as usual.
duke@435 1278 */
duke@435 1279 if (frame_size > 0) {
duke@435 1280 jframe->new_fp = J->prev_fr.fp + frame_size;
duke@435 1281 jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
duke@435 1282 } else {
duke@435 1283 memset(&J->curr_fr, 0, sizeof(Frame_t));
duke@435 1284 err = read_pointer(J, fp, &jframe->new_fp);
duke@435 1285 CHECK_FAIL(err);
duke@435 1286
duke@435 1287 err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
duke@435 1288 CHECK_FAIL(err);
duke@435 1289 }
duke@435 1290 if (debug) {
duke@435 1291 fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
duke@435 1292 result, frame_size);
duke@435 1293 fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
duke@435 1294 J->prev_fr.fp, jframe->new_fp);
duke@435 1295 }
duke@435 1296 }
duke@435 1297 #endif /* X86_COMPILER2 */
duke@435 1298
duke@435 1299 return PS_OK;
duke@435 1300
duke@435 1301 fail:
duke@435 1302 return err;
duke@435 1303 }
duke@435 1304
duke@435 1305 int Jget_vframe(jvm_agent_t* J, int vframe_no,
duke@435 1306 char *name, size_t size, Jframe_t *jframe)
duke@435 1307 {
duke@435 1308 Nmethod_t *N = J->N;
duke@435 1309 Vframe_t *vf;
duke@435 1310 int32_t err;
duke@435 1311
duke@435 1312 if (vframe_no >= N->vf_cnt) {
duke@435 1313 (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
duke@435 1314 return -1;
duke@435 1315 }
duke@435 1316 vf = N->vframes + vframe_no;
duke@435 1317 name[0] = COMP_METHOD_SIGN;
duke@435 1318 err = name_for_methodOop(J, vf->methodOop, name + 1, size);
duke@435 1319 CHECK_FAIL(err);
duke@435 1320
duke@435 1321 jframe->bci = vf->bci;
duke@435 1322 jframe->line = vf->line;
duke@435 1323 if (debug) {
duke@435 1324 fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
duke@435 1325 name, vf->line);
duke@435 1326 }
duke@435 1327 return PS_OK;
duke@435 1328
duke@435 1329 fail:
duke@435 1330 if (debug) {
duke@435 1331 fprintf(stderr, "\t Jget_vframe: FAIL\n");
duke@435 1332 }
duke@435 1333 return err;
duke@435 1334 }
duke@435 1335
duke@435 1336 #define MAX_SYM_SIZE 256
duke@435 1337
duke@435 1338 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
duke@435 1339 size_t size, Jframe_t *jframe) {
duke@435 1340 uintptr_t fp;
duke@435 1341 uintptr_t pc;
duke@435 1342 /* arguments given to read_pointer need to be worst case sized */
duke@435 1343 uint64_t methodOopPtr = 0;
duke@435 1344 uint64_t sender_sp;
duke@435 1345 uint64_t bcx = 0;
duke@435 1346 int is_interpreted = 0;
duke@435 1347 int result = PS_OK;
duke@435 1348 int err = PS_OK;
duke@435 1349
duke@435 1350 if (J == NULL) {
duke@435 1351 return -1;
duke@435 1352 }
duke@435 1353
duke@435 1354 jframe->vf_cnt = 1;
duke@435 1355 jframe->new_fp = 0;
duke@435 1356 jframe->new_pc = 0;
duke@435 1357 jframe->line = 0;
duke@435 1358 jframe->bci = 0;
duke@435 1359 jframe->locinf = 0;
duke@435 1360
duke@435 1361 read_volatiles(J);
duke@435 1362 pc = (uintptr_t) regs[R_PC];
duke@435 1363 J->curr_fr.pc = pc;
duke@435 1364 J->curr_fr.fp = regs[R_FP];
duke@435 1365 J->curr_fr.sp = regs[R_SP];
duke@435 1366
duke@435 1367 if (debug)
duke@435 1368 fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
duke@435 1369
duke@435 1370 #if defined(sparc) || defined(__sparc)
duke@435 1371 /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
duke@435 1372 * In the pcDesc structure return pc offset is recorded for CALL instructions.
duke@435 1373 * regs[R_PC] contains a CALL instruction pc offset.
duke@435 1374 */
duke@435 1375 pc += 8;
duke@435 1376 bcx = (uintptr_t) regs[R_L1];
duke@435 1377 methodOopPtr = (uintptr_t) regs[R_L2];
duke@435 1378 sender_sp = regs[R_I5];
duke@435 1379 if (debug > 2) {
duke@435 1380 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 1381 regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
duke@435 1382 }
duke@435 1383 #elif defined(i386) || defined(__i386) || defined(__amd64)
duke@435 1384
duke@435 1385 fp = (uintptr_t) regs[R_FP];
duke@435 1386 if (J->prev_fr.fp == 0) {
duke@435 1387 #ifdef X86_COMPILER2
duke@435 1388 /* A workaround for top java frames */
duke@435 1389 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
duke@435 1390 #else
duke@435 1391 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
duke@435 1392 #endif /* COMPILER2 */
duke@435 1393 }
duke@435 1394 if (debug > 2) {
duke@435 1395 printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
duke@435 1396 }
duke@435 1397
duke@435 1398 if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodOopPtr) != PS_OK) {
duke@435 1399 methodOopPtr = 0;
duke@435 1400 }
duke@435 1401 if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
duke@435 1402 sender_sp = 0;
duke@435 1403 }
duke@435 1404 if (read_pointer(J, fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
duke@435 1405 bcx = 0;
duke@435 1406 }
duke@435 1407 #endif /* i386 */
duke@435 1408
duke@435 1409 J->methodOopPtr = methodOopPtr;
duke@435 1410 J->bcx = bcx;
duke@435 1411
duke@435 1412 /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
duke@435 1413 * For example: JVM_SuspendThread frame poins to the top interpreted frame.
duke@435 1414 * If we call is_methodOop(J, methodOopPtr) before codecache_contains(J, pc)
duke@435 1415 * then we go over and omit both: nmethod and I2CAdapter frames.
duke@435 1416 * Note, that regs[R_PC] is always correct if frame defined correctly.
duke@435 1417 * So it is better to call codecache_contains(J, pc) from the beginning.
duke@435 1418 */
duke@435 1419 #ifndef X86_COMPILER2
duke@435 1420 if (is_methodOop(J, J->methodOopPtr)) {
duke@435 1421 result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe);
duke@435 1422 /* If the methodOopPtr is a method then this is highly likely to be
duke@435 1423 an interpreter frame */
duke@435 1424 if (result >= 0) {
duke@435 1425 is_interpreted = 1;
duke@435 1426 }
duke@435 1427 } else
duke@435 1428 #endif /* ! X86_COMPILER2 */
duke@435 1429
duke@435 1430 if (codecache_contains(J, pc)) {
duke@435 1431 result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
duke@435 1432 }
duke@435 1433 #ifdef X86_COMPILER2
duke@435 1434 else if (is_methodOop(J, J->methodOopPtr)) {
duke@435 1435 result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe);
duke@435 1436 /* If the methodOopPtr is a method then this is highly likely to be
duke@435 1437 an interpreter frame */
duke@435 1438 if (result >= 0) {
duke@435 1439 is_interpreted = 1;
duke@435 1440 }
duke@435 1441 }
duke@435 1442 #endif /* X86_COMPILER2 */
duke@435 1443 else {
duke@435 1444 if (debug) {
duke@435 1445 fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
duke@435 1446 }
duke@435 1447 result = -1;
duke@435 1448 }
duke@435 1449 if (!is_interpreted) {
duke@435 1450 sender_sp = 0;
duke@435 1451 }
duke@435 1452 J->curr_fr.sender_sp = sender_sp;
duke@435 1453
duke@435 1454 #ifdef X86_COMPILER2
duke@435 1455 if (!J->curr_fr.fp) {
duke@435 1456 J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
duke@435 1457 }
duke@435 1458 if (!jframe->new_pc && jframe->new_fp) {
duke@435 1459 // This seems dubious
duke@435 1460 read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc);
duke@435 1461 CHECK_FAIL(err);
duke@435 1462 if (debug > 2) {
duke@435 1463 printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
duke@435 1464 jframe->new_fp, jframe->new_pc);
duke@435 1465 }
duke@435 1466 }
duke@435 1467
duke@435 1468 #endif /* X86_COMPILER2 */
duke@435 1469 J->prev_fr = J->curr_fr;
duke@435 1470
duke@435 1471 if (debug)
duke@435 1472 fprintf(stderr, "Jlookup_by_regs: END\n\n");
duke@435 1473
duke@435 1474 return result;
duke@435 1475
duke@435 1476 fail:
duke@435 1477 return err;
duke@435 1478 }
duke@435 1479
duke@435 1480 void update_gregs(prgregset_t gregs, Jframe_t jframe) {
duke@435 1481 #ifdef X86_COMPILER2
duke@435 1482 if (debug > 0) {
duke@435 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]);
duke@435 1484 }
duke@435 1485 /*
duke@435 1486 * A workaround for java C2 frames with unconventional FP.
duke@435 1487 * may have to modify regset with new values for FP/PC/SP when needed.
duke@435 1488 */
duke@435 1489 if (jframe.new_sp) {
duke@435 1490 *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
duke@435 1491 } else {
duke@435 1492 // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
duke@435 1493 }
duke@435 1494
duke@435 1495 if (jframe.new_fp) {
duke@435 1496 *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
duke@435 1497 }
duke@435 1498 if (jframe.new_pc) {
duke@435 1499 *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
duke@435 1500 }
duke@435 1501 if (debug > 0) {
duke@435 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]);
duke@435 1503 }
duke@435 1504 #endif /* X86_COMPILER2 */
duke@435 1505 }
duke@435 1506
duke@435 1507 /*
duke@435 1508 * Iterates over java frames at current location given by 'gregs'.
duke@435 1509 *
duke@435 1510 * Returns -1 if no java frames are present or if an error is encountered.
duke@435 1511 * Returns the result of calling 'func' if the return value is non-zero.
duke@435 1512 * Returns 0 otherwise.
duke@435 1513 */
duke@435 1514 int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
duke@435 1515 char buf[MAX_SYM_SIZE + 1];
duke@435 1516 Jframe_t jframe;
duke@435 1517 int i = 0, res;
duke@435 1518 #ifdef X86_COMPILER2
duke@435 1519 if (debug > 0) {
duke@435 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]);
duke@435 1521 }
duke@435 1522 #endif /* X86_COMPILER2 */
duke@435 1523
duke@435 1524 memset(&jframe, 0, sizeof(Jframe_t));
duke@435 1525 memset(buf, 0, sizeof(buf));
duke@435 1526 res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
duke@435 1527 if (res != PS_OK)
duke@435 1528 return (-1);
duke@435 1529
duke@435 1530
duke@435 1531 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
duke@435 1532 jframe.line, NULL);
duke@435 1533 if (res != 0) {
duke@435 1534 update_gregs(gregs, jframe);
duke@435 1535 return (res);
duke@435 1536 }
duke@435 1537 for (i = 1; i < jframe.vf_cnt; i++) {
duke@435 1538 Jget_vframe(J, i, buf, sizeof(buf), &jframe);
duke@435 1539 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
duke@435 1540 jframe.line, NULL);
duke@435 1541 if (res != 0) {
duke@435 1542 update_gregs(gregs, jframe);
duke@435 1543 return (res);
duke@435 1544 }
duke@435 1545 }
duke@435 1546 update_gregs(gregs, jframe);
duke@435 1547 return (0);
duke@435 1548 }

mercurial