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