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