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