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