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