libjvm_db.c revision 7081:39231c6e51fe
11590Srgrimes/* 21590Srgrimes * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. 31590Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41590Srgrimes * 51590Srgrimes * This code is free software; you can redistribute it and/or modify it 61590Srgrimes * under the terms of the GNU General Public License version 2 only, as 71590Srgrimes * published by the Free Software Foundation. 81590Srgrimes * 91590Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 101590Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 111590Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 121590Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 131590Srgrimes * accompanied this code). 141590Srgrimes * 151590Srgrimes * You should have received a copy of the GNU General Public License version 161590Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 171590Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 181590Srgrimes * 191590Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 201590Srgrimes * or visit www.oracle.com if you need additional information or have any 211590Srgrimes * questions. 221590Srgrimes * 231590Srgrimes */ 241590Srgrimes 251590Srgrimes#include <stdio.h> 261590Srgrimes#include <stdlib.h> 271590Srgrimes#include <string.h> 281590Srgrimes#include <errno.h> 291590Srgrimes#include <gelf.h> 301590Srgrimes 311590Srgrimes#include "libjvm_db.h" 321590Srgrimes#include "JvmOffsets.h" 331590Srgrimes 3427888Scharnier#define LIBJVM_SO "libjvm.so" 351590Srgrimes 361590Srgrimes#if defined(i386) || defined(__i386) || defined(__amd64) 3795624Smarkm#ifdef COMPILER2 381590Srgrimes#define X86_COMPILER2 391590Srgrimes#endif /* COMPILER2 */ 4095624Smarkm#endif /* i386 */ 411590Srgrimes 421590Srgrimestypedef struct { 431590Srgrimes short vf_cnt; /* number of recognized java vframes */ 441590Srgrimes short bci; /* current frame method byte code index */ 451590Srgrimes int line; /* current frame method source line */ 4695624Smarkm uint64_t new_fp; /* fp for the next frame */ 4795624Smarkm uint64_t new_pc; /* pc for the next frame */ 4895624Smarkm uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */ 491590Srgrimes char locinf; /* indicates there is valid location info */ 5013236Sgraichen} Jframe_t; 511590Srgrimes 521590Srgrimesint Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, 5313236Sgraichen size_t size, Jframe_t *jframe); 5413236Sgraichen 5595624Smarkmint main(int arg) { return arg; } 5695624Smarkm 5795624Smarkmstatic int debug = 0; 5895624Smarkm 5995624Smarkmstatic void failed(int err, const char * file, int line) { 601590Srgrimes if (debug) { 6195624Smarkm fprintf(stderr, "failed %d at %s:%d\n", err, file, line); 6227888Scharnier } 6327888Scharnier} 6427888Scharnier 6527888Scharnierstatic void warn(const char * file, int line, const char * msg) { 66163599Sru if (debug) { 6795624Smarkm fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line); 6827888Scharnier } 691590Srgrimes} 70169345Sdwmalone 7113236Sgraichenstatic void warn1(const char * file, int line, const char * msg, intptr_t arg1) { 7213236Sgraichen if (debug) { 73166646Smpp fprintf(stderr, "warning: "); 7416379Salex fprintf(stderr, msg, arg1); 751590Srgrimes fprintf(stderr, " at %s:%d\n", file, line); 76227176Sed } 7713236Sgraichen} 781590Srgrimes 791590Srgrimes#define CHECK_FAIL(err) \ 801590Srgrimes if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; } 811590Srgrimes#define WARN(msg) warn(__FILE__, __LINE__, msg) 821590Srgrimes#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1) 8313236Sgraichen 841590Srgrimestypedef struct VMStructEntry { 85207736Smckusick const char * typeName; /* The type name containing the given field (example: "Klass") */ 8692921Simp const char * fieldName; /* The field name within the type (example: "_name") */ 8795624Smarkm uint64_t address; /* Address of field; only used for static fields */ 88166388Smpp /* ("offset" can not be reused because of apparent SparcWorks compiler bug */ 89166388Smpp /* in generation of initializer data) */ 90166388Smpp} VMStructEntry; 91166388Smpp 92166388Smpp/* Prototyping inlined methods */ 93166646Smpp 9495624Smarkmint sprintf(char *s, const char *format, ...); 9595624Smarkm 9695624Smarkm#define SZ16 sizeof(int16_t) 9795624Smarkm#define SZ32 sizeof(int32_t) 9895624Smarkm 9916379Salex#define COMP_METHOD_SIGN '*' 10095624Smarkm 10116379Salex#define MAX_VFRAMES_CNT 256 10213236Sgraichen 103227176Sedtypedef struct vframe { 104227176Sed uint64_t method; 105227176Sed int32_t sender_decode_offset; 106227176Sed int32_t methodIdx; 107227176Sed int32_t bci; 108227176Sed int32_t line; 1091590Srgrimes} Vframe_t; 11016379Salex 11195624Smarkmtypedef struct frame { 1121590Srgrimes uintptr_t fp; 11313236Sgraichen uintptr_t pc; 114207736Smckusick uintptr_t sp; 115166388Smpp uintptr_t sender_sp; // The unextended sp of the caller 1161590Srgrimes} Frame_t; 117166646Smpp 1181590Srgrimestypedef struct Nmethod_t { 119166646Smpp struct jvm_agent* J; 120166646Smpp Jframe_t *jframe; 121166646Smpp 1221590Srgrimes uint64_t nm; /* _nmethod */ 1231590Srgrimes uint64_t pc; 1241590Srgrimes uint64_t pc_desc; 125163599Sru 126163599Sru int32_t orig_pc_offset; /* _orig_pc_offset */ 127163599Sru int32_t instrs_beg; /* _code_offset */ 128101545Siedowse int32_t instrs_end; 129101545Siedowse int32_t deopt_beg; /* _deoptimize_offset */ 130101545Siedowse int32_t scopes_data_beg; /* _scopes_data_offset */ 131101544Siedowse int32_t scopes_data_end; 132101544Siedowse int32_t metadata_beg; /* _metadata_offset */ 133101544Siedowse int32_t metadata_end; 134166646Smpp int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ 135166646Smpp int32_t scopes_pcs_end; 136166646Smpp 1371590Srgrimes int vf_cnt; 1381590Srgrimes Vframe_t vframes[MAX_VFRAMES_CNT]; 1391590Srgrimes} Nmethod_t; 1401590Srgrimes 1411590Srgrimesstruct jvm_agent { 1421590Srgrimes struct ps_prochandle* P; 1431590Srgrimes 1441590Srgrimes uint64_t nmethod_vtbl; 1451590Srgrimes uint64_t CodeBlob_vtbl; 1461590Srgrimes uint64_t BufferBlob_vtbl; 1471590Srgrimes uint64_t RuntimeStub_vtbl; 1481590Srgrimes uint64_t Method_vtbl; 1491590Srgrimes 1501590Srgrimes uint64_t Use_Compressed_Oops_address; 1511590Srgrimes uint64_t Universe_narrow_oop_base_address; 1521590Srgrimes uint64_t Universe_narrow_oop_shift_address; 153166388Smpp uint64_t CodeCache_heaps_address; 1541590Srgrimes 15513236Sgraichen /* Volatiles */ 156207736Smckusick uint8_t Use_Compressed_Oops; 15727888Scharnier uint64_t Universe_narrow_oop_base; 15827888Scharnier uint32_t Universe_narrow_oop_shift; 159166388Smpp // Code cache heaps 16013236Sgraichen int32_t Number_of_heaps; 16113236Sgraichen uint64_t* Heap_low; 162166388Smpp uint64_t* Heap_high; 1631590Srgrimes uint64_t* Heap_segmap_low; 164166388Smpp uint64_t* Heap_segmap_high; 1651590Srgrimes 1661590Srgrimes int32_t SIZE_CodeCache_log2_segment; 1671590Srgrimes 1681590Srgrimes uint64_t methodPtr; 1691590Srgrimes uint64_t bcp; 1701590Srgrimes 171166388Smpp Nmethod_t *N; /*Inlined methods support */ 1721590Srgrimes Frame_t prev_fr; 173166388Smpp Frame_t curr_fr; 1741590Srgrimes}; 175166388Smpp 1761590Srgrimesstatic int 1771590Srgrimesread_string(struct ps_prochandle *P, 1781590Srgrimes char *buf, /* caller's buffer */ 1791590Srgrimes size_t size, /* upper limit on bytes to read */ 180166388Smpp uintptr_t addr) /* address in process */ 1811590Srgrimes{ 182166388Smpp int err = PS_OK; 1831590Srgrimes while (size-- > 1 && err == PS_OK) { 1841590Srgrimes err = ps_pread(P, addr, buf, 1); 185166388Smpp if (*buf == '\0') { 1861590Srgrimes return PS_OK; 1871590Srgrimes } 18816379Salex addr += 1; 18995624Smarkm buf += 1; 1901590Srgrimes } 1911590Srgrimes return -1; 1921590Srgrimes} 193166646Smpp 194166646Smppstatic int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) { 195166646Smpp int err = -1; 1961590Srgrimes uint32_t ptr32; 1971590Srgrimes err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); 1981590Srgrimes *ptr = ptr32; 1991590Srgrimes return err; 2001590Srgrimes} 2011590Srgrimes 202166388Smppstatic int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) { 20395624Smarkm int err = -1; 2041590Srgrimes uint32_t ptr32; 2051590Srgrimes 20695624Smarkm switch (DATA_MODEL) { 2071590Srgrimes case PR_MODEL_LP64: 2081590Srgrimes err = ps_pread(J->P, base, ptr, sizeof(uint64_t)); 2091590Srgrimes break; 2101590Srgrimes case PR_MODEL_ILP32: 2111590Srgrimes err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); 212166388Smpp *ptr = ptr32; 2131590Srgrimes break; 2141590Srgrimes } 2151590Srgrimes 2161590Srgrimes return err; 2171590Srgrimes} 218166388Smpp 21995624Smarkmstatic int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) { 2201590Srgrimes uint64_t ptr; 2211590Srgrimes int err; 2221590Srgrimes char buffer[1024]; 2231590Srgrimes 22427888Scharnier *stringp = NULL; 225166388Smpp err = read_pointer(J, base, &ptr); 2261590Srgrimes CHECK_FAIL(err); 227166388Smpp if (ptr != 0) { 2281590Srgrimes err = read_string(J->P, buffer, sizeof(buffer), ptr); 2291590Srgrimes CHECK_FAIL(err); 2301590Srgrimes *stringp = strdup(buffer); 2311590Srgrimes } 2321590Srgrimes return PS_OK; 233166388Smpp 23495624Smarkm fail: 2351590Srgrimes return err; 2361590Srgrimes} 23795624Smarkm 2381590Srgrimesstatic int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) { 2391590Srgrimes uint64_t ptr; 2401590Srgrimes int err; 2411590Srgrimes 2421590Srgrimes err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName); 243166388Smpp CHECK_FAIL(err); 2441590Srgrimes err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName); 2451590Srgrimes CHECK_FAIL(err); 2461590Srgrimes err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address); 2471590Srgrimes CHECK_FAIL(err); 2481590Srgrimes 249166388Smpp return PS_OK; 25095624Smarkm 2511590Srgrimes fail: 2521590Srgrimes if (vmp->typeName != NULL) free((void*)vmp->typeName); 2531590Srgrimes if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 2541590Srgrimes return err; 25527888Scharnier} 256166388Smpp 2571590Srgrimesstatic int parse_vmstructs(jvm_agent_t* J) { 258166388Smpp VMStructEntry vmVar; 2591590Srgrimes VMStructEntry* vmp = &vmVar; 2601590Srgrimes uint64_t gHotSpotVMStructs; 26116379Salex psaddr_t sym_addr; 262207736Smckusick uint64_t base; 263163599Sru int err; 264163599Sru 265163599Sru /* Clear *vmp now in case we jump to fail: */ 266223690Spluknet memset(vmp, 0, sizeof(VMStructEntry)); 267223690Spluknet 268223690Spluknet err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr); 269223690Spluknet CHECK_FAIL(err); 270223690Spluknet err = read_pointer(J, sym_addr, &gHotSpotVMStructs); 271163599Sru CHECK_FAIL(err); 272163599Sru base = gHotSpotVMStructs; 273163599Sru 274163599Sru err = PS_OK; 275166388Smpp while (err == PS_OK) { 27695624Smarkm memset(vmp, 0, sizeof(VMStructEntry)); 2771590Srgrimes err = parse_vmstruct_entry(J, base, vmp); 27895624Smarkm if (err != PS_OK || vmp->typeName == NULL) { 27913236Sgraichen break; 28095624Smarkm } 28195624Smarkm 282181267Sdelphij if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { 283166388Smpp /* Read _heaps field of type GrowableArray<CodeHeaps*>* */ 2841590Srgrimes if (strcmp("_heaps", vmp->fieldName) == 0) { 2851590Srgrimes err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address); 2861590Srgrimes } 2871590Srgrimes } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { 2881590Srgrimes if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { 2891590Srgrimes J->Universe_narrow_oop_base_address = vmp->address; 290207736Smckusick } 2911590Srgrimes if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { 292166388Smpp J->Universe_narrow_oop_shift_address = vmp->address; 293166388Smpp } 2941590Srgrimes } 295166388Smpp CHECK_FAIL(err); 2961590Srgrimes 29795624Smarkm base += SIZE_VMStructEntry; 298166388Smpp if (vmp->typeName != NULL) free((void*)vmp->typeName); 2991590Srgrimes if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 3001590Srgrimes } 3011590Srgrimes 3021590Srgrimes return PS_OK; 30395624Smarkm 304207736Smckusick fail: 3051590Srgrimes if (vmp->typeName != NULL) free((void*)vmp->typeName); 306166388Smpp if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 307166388Smpp return -1; 3081590Srgrimes} 309166388Smpp 3101590Srgrimesstatic int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { 31195624Smarkm psaddr_t sym_addr; 312166388Smpp int err; 3131590Srgrimes 3141590Srgrimes err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); 3151590Srgrimes if (err != PS_OK) goto fail; 3161590Srgrimes *valuep = sym_addr; 31795624Smarkm return PS_OK; 318166646Smpp 319166646Smpp fail: 320166646Smpp return err; 321166646Smpp} 322166646Smpp 323166646Smppstatic int read_volatiles(jvm_agent_t* J) { 324166646Smpp int i; 325166646Smpp uint64_t array_data; 326166646Smpp uint64_t code_heap_address; 327166646Smpp int err; 3281590Srgrimes 329207736Smckusick err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); 3301590Srgrimes if (err == PS_OK) { 3311590Srgrimes err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); 332207736Smckusick CHECK_FAIL(err); 3331590Srgrimes } else { 334207736Smckusick J->Use_Compressed_Oops = 0; 3351590Srgrimes } 3361590Srgrimes 3371590Srgrimes err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); 338207736Smckusick CHECK_FAIL(err); 339207736Smckusick err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); 340207736Smckusick CHECK_FAIL(err); 3411590Srgrimes 342207736Smckusick /* CodeCache_heaps_address points to GrowableArray<CodeHeaps*>, read _data field 343207736Smckusick pointing to the first entry of type CodeCache* in the array */ 344207736Smckusick err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data); 345207736Smckusick /* Read _len field containing the number of code heaps */ 346207736Smckusick err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len, 347207736Smckusick &J->Number_of_heaps, sizeof(J->Number_of_heaps)); 348207736Smckusick 349207736Smckusick /* Allocate memory for heap configurations */ 350207736Smckusick J->Heap_low = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 351207736Smckusick J->Heap_high = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 352207736Smckusick J->Heap_segmap_low = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 353207736Smckusick J->Heap_segmap_high = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 354207736Smckusick 355207736Smckusick /* Read code heap configurations */ 356207736Smckusick for (i = 0; i < J->Number_of_heaps; ++i) { 357223690Spluknet /* Read address of heap */ 358223690Spluknet err = read_pointer(J, array_data, &code_heap_address); 359207736Smckusick CHECK_FAIL(err); 360223690Spluknet 361223690Spluknet err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + 362223690Spluknet OFFSET_VirtualSpace_low, &J->Heap_low[i]); 363223690Spluknet CHECK_FAIL(err); 3641590Srgrimes err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + 365207736Smckusick OFFSET_VirtualSpace_high, &J->Heap_high[i]); 366207736Smckusick CHECK_FAIL(err); 367207736Smckusick err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + 368207736Smckusick OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]); 369207736Smckusick CHECK_FAIL(err); 370207736Smckusick err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + 371207736Smckusick OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]); 372207736Smckusick CHECK_FAIL(err); 373207736Smckusick 374207736Smckusick /* Increment pointer to next entry */ 375207736Smckusick array_data = array_data + POINTER_SIZE; 376207736Smckusick } 377207736Smckusick 378207736Smckusick err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size, 379207736Smckusick &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); 380207736Smckusick CHECK_FAIL(err); 3811590Srgrimes 382166646Smpp return PS_OK; 3831590Srgrimes 384207736Smckusick fail: 3851590Srgrimes return err; 3861590Srgrimes} 38716379Salex 388181267Sdelphijstatic int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) { 389166646Smpp return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]); 390207736Smckusick} 391207736Smckusick 392166646Smppstatic int codecache_contains(jvm_agent_t* J, uint64_t ptr) { 393166646Smpp int i; 394207736Smckusick for (i = 0; i < J->Number_of_heaps; ++i) { 395207736Smckusick if (codeheap_contains(i, J, ptr)) { 396207736Smckusick return 1; 397207736Smckusick } 398207736Smckusick } 399207736Smckusick return 0; 400207736Smckusick} 401207736Smckusick 402207736Smckusickstatic uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) { 403207736Smckusick return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment; 404207736Smckusick} 405207736Smckusick 406207736Smckusickstatic uint64_t block_at(int heap_num, jvm_agent_t* J, int i) { 407207736Smckusick return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment); 408181262Scognet} 409207736Smckusick 410207736Smckusickstatic int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) { 411207736Smckusick int err; 412166646Smpp int i; 413207736Smckusick 414169345Sdwmalone for (i = 0; i < J->Number_of_heaps; ++i) { 415181262Scognet *startp = 0; 416207736Smckusick if (codeheap_contains(i, J, ptr)) { 417207736Smckusick int32_t used; 418207736Smckusick uint64_t segment = segment_for(i, J, ptr); 419166646Smpp uint64_t block = J->Heap_segmap_low[i]; 420207736Smckusick uint8_t tag; 421166646Smpp err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); 422166646Smpp CHECK_FAIL(err); 423166646Smpp if (tag == 0xff) 424166646Smpp return PS_OK; 42595624Smarkm while (tag > 0) { 4261590Srgrimes err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); 4271590Srgrimes CHECK_FAIL(err); 42813365Sgraichen segment -= tag; 4291590Srgrimes } 4301590Srgrimes block = block_at(i, J, segment); 431207736Smckusick err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used)); 4321590Srgrimes CHECK_FAIL(err); 43377047Spirzyk if (used) { 4341590Srgrimes *startp = block + SIZE_HeapBlockHeader; 4351590Srgrimes } 4361590Srgrimes } 4371590Srgrimes return PS_OK; 4381590Srgrimes } 4391590Srgrimes 4401590Srgrimes fail: 4411590Srgrimes return -1; 4421590Srgrimes} 4431590Srgrimes 4441590Srgrimesstatic int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) { 4451590Srgrimes psaddr_t sym_addr; 4461590Srgrimes int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); 4471590Srgrimes if (err == PS_OK) { 448166495Smpp err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t)); 449207736Smckusick return err; 4501590Srgrimes } 4511590Srgrimes *valuep = -1; 452207736Smckusick return -1; 4531590Srgrimes} 4541590Srgrimes 4551590Srgrimesjvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) { 4561590Srgrimes jvm_agent_t* J; 457166495Smpp int err; 458207736Smckusick 459207736Smckusick if (vers != JVM_DB_VERSION) { 460207736Smckusick errno = ENOTSUP; 461166495Smpp return NULL; 4621590Srgrimes } 4631590Srgrimes 4641590Srgrimes J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1); 4651590Srgrimes 466166495Smpp debug = getenv("LIBJVMDB_DEBUG") != NULL; 467207736Smckusick if (debug) debug = 3; 4681590Srgrimes 4691590Srgrimes if (debug) { 4701590Srgrimes fprintf(stderr, "Jagent_create: debug=%d\n", debug); 471166495Smpp#ifdef X86_COMPILER2 472166495Smpp fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE); 473207736Smckusick#endif /* X86_COMPILER2 */ 4741590Srgrimes } 4751590Srgrimes 476166495Smpp J->P = P; 477207736Smckusick 4781590Srgrimes // Initialize the initial previous frame 4791590Srgrimes 4801590Srgrimes J->prev_fr.fp = 0; 4811590Srgrimes J->prev_fr.pc = 0; 4821590Srgrimes J->prev_fr.sp = 0; 4831590Srgrimes J->prev_fr.sender_sp = 0; 48416379Salex 48595624Smarkm err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl); 4861590Srgrimes CHECK_FAIL(err); 487101544Siedowse err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl); 48895624Smarkm if (err != PS_OK) J->BufferBlob_vtbl = 0; 4891590Srgrimes err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl); 49013236Sgraichen CHECK_FAIL(err); 49113236Sgraichen err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl); 492166646Smpp CHECK_FAIL(err); 4931590Srgrimes err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl); 49413236Sgraichen CHECK_FAIL(err); 49513236Sgraichen 496166646Smpp err = parse_vmstructs(J); 497166646Smpp CHECK_FAIL(err); 49897764Siedowse err = read_volatiles(J); 49927888Scharnier CHECK_FAIL(err); 50027888Scharnier 5011590Srgrimes return J; 502207736Smckusick 50313236Sgraichen fail: 50413365Sgraichen Jagent_destroy(J); 50527888Scharnier return NULL; 50627888Scharnier} 5071590Srgrimes 508166646Smppvoid Jagent_destroy(jvm_agent_t *J) { 509166646Smpp if (J != NULL) { 510166646Smpp free(J); 511166646Smpp } 512166646Smpp} 513166646Smpp 514166646Smppstatic int is_method(jvm_agent_t* J, uint64_t methodPtr) { 51532651Sbde uint64_t klass; 516101545Siedowse int err = read_pointer(J, methodPtr, &klass); 517101545Siedowse if (err != PS_OK) goto fail; 518166646Smpp return klass == J->Method_vtbl; 5191590Srgrimes 52036880Sache fail: 52113236Sgraichen return 0; 52213236Sgraichen} 52313236Sgraichen 52413236Sgraichenstatic int 52513236Sgraichenname_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size) 52613236Sgraichen{ 52713236Sgraichen short nameIndex; 52813236Sgraichen short signatureIndex; 52913236Sgraichen uint64_t constantPool; 5301590Srgrimes uint64_t constMethod; 53195624Smarkm uint64_t nameSymbol; 53213236Sgraichen uint64_t signatureSymbol; 53313236Sgraichen uint64_t klassPtr; 53413236Sgraichen uint64_t klassSymbol; 53513236Sgraichen short klassSymbolLength; 5361590Srgrimes short nameSymbolLength; 5371590Srgrimes short signatureSymbolLength; 5381590Srgrimes char * nameString = NULL; 5391590Srgrimes char * klassString = NULL; 5401590Srgrimes char * signatureString = NULL; 54113236Sgraichen int err; 54213236Sgraichen 5431590Srgrimes err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod); 54413236Sgraichen CHECK_FAIL(err); 54513236Sgraichen err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool); 5461590Srgrimes CHECK_FAIL(err); 5471590Srgrimes 5481590Srgrimes /* To get name string */ 5491590Srgrimes err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2); 5501590Srgrimes CHECK_FAIL(err); 551207736Smckusick err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol); 5521590Srgrimes CHECK_FAIL(err); 55316379Salex // The symbol is a CPSlot and has lower bit set to indicate metadata 554207736Smckusick nameSymbol &= (~1); // remove metadata lsb 5551590Srgrimes err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); 556207736Smckusick CHECK_FAIL(err); 5571590Srgrimes nameString = (char*)calloc(nameSymbolLength + 1, 1); 558207736Smckusick err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); 5591590Srgrimes CHECK_FAIL(err); 560207736Smckusick 561166485Smpp /* To get signature string */ 562207736Smckusick err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2); 5631590Srgrimes CHECK_FAIL(err); 5641590Srgrimes err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol); 5651590Srgrimes CHECK_FAIL(err); 56616379Salex signatureSymbol &= (~1); // remove metadata lsb 56795624Smarkm err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); 56813236Sgraichen CHECK_FAIL(err); 56913236Sgraichen signatureString = (char*)calloc(signatureSymbolLength + 1, 1); 57013236Sgraichen err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); 57113236Sgraichen CHECK_FAIL(err); 57213236Sgraichen 57313236Sgraichen /* To get klass string */ 57413236Sgraichen err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr); 57513236Sgraichen CHECK_FAIL(err); 57613236Sgraichen err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol); 57713236Sgraichen CHECK_FAIL(err); 57813236Sgraichen err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); 57913236Sgraichen CHECK_FAIL(err); 58013236Sgraichen klassString = (char*)calloc(klassSymbolLength + 1, 1); 58113236Sgraichen err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); 58213236Sgraichen CHECK_FAIL(err); 58313236Sgraichen 58413236Sgraichen result[0] = '\0'; 58513236Sgraichen strncat(result, klassString, size); 58613236Sgraichen size -= strlen(klassString); 58713236Sgraichen strncat(result, ".", size); 58813236Sgraichen size -= 1; 58958618Scharnier strncat(result, nameString, size); 59013236Sgraichen size -= strlen(nameString); 59113236Sgraichen strncat(result, signatureString, size); 59213236Sgraichen 59313236Sgraichen if (nameString != NULL) free(nameString); 59413236Sgraichen if (klassString != NULL) free(klassString); 59513236Sgraichen if (signatureString != NULL) free(signatureString); 59613236Sgraichen 59713236Sgraichen return PS_OK; 59813236Sgraichen 59997764Siedowse fail: 60097764Siedowse if (debug) { 60197764Siedowse fprintf(stderr, "name_for_methodPtr: FAIL \n\n"); 60297764Siedowse } 60397764Siedowse if (nameString != NULL) free(nameString); 60497764Siedowse if (klassString != NULL) free(klassString); 60597764Siedowse if (signatureString != NULL) free(signatureString); 60613236Sgraichen return -1; 60713236Sgraichen} 60813236Sgraichen 609101544Siedowsestatic int nmethod_info(Nmethod_t *N) 610101544Siedowse{ 61113236Sgraichen jvm_agent_t *J = N->J; 61213236Sgraichen uint64_t nm = N->nm; 61313236Sgraichen int32_t err; 61413236Sgraichen 61513236Sgraichen if (debug > 2 ) 61613236Sgraichen fprintf(stderr, "\t nmethod_info: BEGIN \n"); 61713236Sgraichen 61813236Sgraichen /* Instructions */ 61927888Scharnier err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32); 62013236Sgraichen CHECK_FAIL(err); 62113236Sgraichen err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32); 62213236Sgraichen CHECK_FAIL(err); 62313236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32); 62413236Sgraichen CHECK_FAIL(err); 62513236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); 62613236Sgraichen CHECK_FAIL(err); 627118464Sdas 62813236Sgraichen /* Metadata */ 62913236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32); 630118464Sdas CHECK_FAIL(err); 63113236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32); 63213236Sgraichen CHECK_FAIL(err); 633118464Sdas 63413236Sgraichen /* scopes_pcs */ 63513236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); 63613236Sgraichen CHECK_FAIL(err); 63713236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32); 63813236Sgraichen CHECK_FAIL(err); 63913236Sgraichen 64013236Sgraichen /* scopes_data */ 64113236Sgraichen err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32); 64213236Sgraichen CHECK_FAIL(err); 64313236Sgraichen 64413236Sgraichen if (debug > 2 ) { 64513236Sgraichen N->scopes_data_end = N->scopes_pcs_beg; 64613236Sgraichen 64713236Sgraichen fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n", 64813236Sgraichen N->instrs_beg, N->instrs_end); 64958618Scharnier 65013236Sgraichen fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n", 65113236Sgraichen N->deopt_beg); 65213236Sgraichen 65313236Sgraichen fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", 65413236Sgraichen N->orig_pc_offset); 65513236Sgraichen 65616379Salex fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n", 65795624Smarkm N->metadata_beg, N->metadata_end); 65895624Smarkm 65913236Sgraichen fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", 66013236Sgraichen N->scopes_data_beg, N->scopes_data_end); 66113236Sgraichen 66213236Sgraichen fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", 66313236Sgraichen N->scopes_pcs_beg, N->scopes_pcs_end); 66413236Sgraichen 66513236Sgraichen fprintf(stderr, "\t nmethod_info: END \n\n"); 66695624Smarkm } 66713236Sgraichen return PS_OK; 66813236Sgraichen 66913236Sgraichen fail: 67013236Sgraichen return err; 67113236Sgraichen} 67258618Scharnier 67395624Smarkmstatic int 67413236Sgraichenraw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val) 67513236Sgraichen{ 67613236Sgraichen int shift = 0; 67713236Sgraichen int value = 0; 67895624Smarkm uint8_t ch = 0; 67913236Sgraichen int32_t err; 68013236Sgraichen int32_t sum; 68113236Sgraichen // Constants for UNSIGNED5 coding of Pack200 68213236Sgraichen // see compressedStream.hpp 68313236Sgraichen enum { 68413236Sgraichen lg_H = 6, 68513236Sgraichen H = 1<<lg_H, 68613236Sgraichen BitsPerByte = 8, 68713236Sgraichen L = (1<<BitsPerByte)-H, 68813236Sgraichen }; 68913236Sgraichen int i; 69016379Salex 69195624Smarkm err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); 6921590Srgrimes CHECK_FAIL(err); 69395624Smarkm if (debug > 2) 6941590Srgrimes fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch); 6951590Srgrimes 6961590Srgrimes sum = ch; 6971590Srgrimes if ( sum >= L ) { 6981590Srgrimes int32_t lg_H_i = lg_H; 69916379Salex // Read maximum of 5 total bytes (we've already read 1). 7001590Srgrimes // See CompressedReadStream::read_int_mb 7011590Srgrimes for ( i = 0; i < 4; i++) { 702 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); 703 CHECK_FAIL(err); 704 sum += ch << lg_H_i; 705 if (ch < L ) { 706 *val = sum; 707 return PS_OK; 708 } 709 lg_H_i += lg_H; 710 } 711 } 712 *val = sum; 713 return PS_OK; 714 715 fail: 716 return err; 717} 718 719static int 720read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line) 721{ 722 uint8_t next = 0; 723 int32_t bci_delta; 724 int32_t line_delta; 725 int32_t err; 726 727 if (debug > 2) 728 fprintf(stderr, "\t\t read_pair: BEGIN\n"); 729 730 err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t)); 731 CHECK_FAIL(err); 732 733 if (next == 0) { 734 if (debug > 2) 735 fprintf(stderr, "\t\t read_pair: END: next == 0\n"); 736 return 1; /* stream terminated */ 737 } 738 if (next == 0xFF) { 739 if (debug > 2) 740 fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n"); 741 742 /* Escape character, regular compression used */ 743 744 err = raw_read_int(J, buffer, &bci_delta); 745 CHECK_FAIL(err); 746 747 err = raw_read_int(J, buffer, &line_delta); 748 CHECK_FAIL(err); 749 750 *bci += bci_delta; 751 *line += line_delta; 752 753 if (debug > 2) { 754 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", 755 line_delta, bci_delta); 756 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", 757 *line, *bci); 758 } 759 } else { 760 /* Single byte compression used */ 761 *bci += next >> 3; 762 *line += next & 0x7; 763 if (debug > 2) { 764 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", 765 next & 0x7, next >> 3); 766 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", 767 *line, *bci); 768 } 769 } 770 if (debug > 2) 771 fprintf(stderr, "\t\t read_pair: END\n"); 772 return PS_OK; 773 774 fail: 775 if (debug) 776 fprintf(stderr, "\t\t read_pair: FAIL\n"); 777 return err; 778} 779 780static int 781line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) 782{ 783 uint64_t buffer; 784 uint16_t code_size; 785 uint64_t code_end_delta; 786 uint64_t constMethod; 787 int8_t access_flags; 788 int32_t best_bci = 0; 789 int32_t stream_bci = 0; 790 int32_t stream_line = 0; 791 int32_t err; 792 793 if (debug > 2) { 794 char name[256]; 795 err = name_for_methodPtr(J, vf->method, name, 256); 796 CHECK_FAIL(err); 797 fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n", 798 name, vf->bci); 799 } 800 801 err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod); 802 CHECK_FAIL(err); 803 804 vf->line = 0; 805 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t)); 806 CHECK_FAIL(err); 807 808 if (!(access_flags & ConstMethod_has_linenumber_table)) { 809 if (debug > 2) 810 fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n"); 811 return PS_OK; 812 } 813 814 /* The line numbers are a short array of 2-tuples [start_pc, line_number]. 815 * Not necessarily sorted and not necessarily one-to-one. 816 */ 817 818 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16); 819 CHECK_FAIL(err); 820 821 /* inlined_table_start() */ 822 code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0; 823 buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta; 824 825 if (debug > 2) { 826 fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n", 827 vf->method, (access_flags & AccessFlags_NATIVE)); 828 fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n", 829 buffer, (int) code_size); 830 } 831 832 while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) { 833 if (stream_bci == vf->bci) { 834 /* perfect match */ 835 if (debug > 2) 836 fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line); 837 vf->line = stream_line; 838 return PS_OK; 839 } else { 840 /* update best_bci/line */ 841 if (stream_bci < vf->bci && stream_bci >= best_bci) { 842 best_bci = stream_bci; 843 vf->line = stream_line; 844 if (debug > 2) { 845 fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n", 846 best_bci, vf->line); 847 } 848 } 849 } 850 } 851 if (debug > 2) 852 fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line); 853 return PS_OK; 854 855 fail: 856 if (debug) 857 fprintf(stderr, "\t line_number_from_bci: FAIL\n"); 858 return err; 859} 860 861static int 862get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc) 863{ 864 int32_t pc_offset; 865 int32_t err; 866 867 err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32); 868 CHECK_FAIL(err); 869 870 *real_pc = N->nm + N->instrs_beg + pc_offset; 871 if (debug > 2) { 872 fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n", 873 pc_offset, *real_pc); 874 } 875 return PS_OK; 876 877 fail: 878 return err; 879} 880 881/* Finds a PcDesc with real-pc equal to N->pc */ 882static int pc_desc_at(Nmethod_t *N) 883{ 884 uint64_t pc_diff; 885 int32_t offs; 886 int32_t err; 887 888 if (debug > 2) 889 fprintf(stderr, "\t pc_desc_at: BEGIN\n"); 890 891 N->vf_cnt = 0; 892 N->pc_desc = 0; 893 894 for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) { 895 uint64_t pd; 896 uint64_t best_pc_diff = 16; /* some approximation */ 897 uint64_t real_pc = 0; 898 899 pd = N->nm + offs; 900 err = get_real_pc(N, pd, &real_pc); 901 CHECK_FAIL(err); 902 903 pc_diff = real_pc - N->pc; 904 905 /* In general, this fragment should work */ 906 if (pc_diff == 0) { 907 N->pc_desc = pd; 908 if (debug) { 909 fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd); 910 } 911 return PS_OK; 912 } 913 /* This fragment is to be able to find out an appropriate 914 * pc_desc entry even if pc_desc info is inaccurate. 915 */ 916 if (best_pc_diff > pc_diff && pc_diff > 0) { 917 best_pc_diff = pc_diff; 918 N->pc_desc = pd; 919 } 920 } 921 if (debug) { 922 fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND"); 923 if (pc_diff < 20) 924 fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff); 925 else 926 fprintf(stderr, "\n\n"); 927 } 928 return PS_OK; 929 930 fail: 931 return err; 932} 933 934static int 935scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf) 936{ 937 uint64_t buffer; 938 int32_t err; 939 940 if (debug > 2) { 941 fprintf(stderr, "\t\t scope_desc_at: BEGIN \n"); 942 } 943 944 buffer = N->nm + N->scopes_data_beg + decode_offset; 945 946 err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset); 947 CHECK_FAIL(err); 948 949 err = raw_read_int(N->J, &buffer, &vf->methodIdx); 950 CHECK_FAIL(err); 951 952 err = raw_read_int(N->J, &buffer, &vf->bci); 953 CHECK_FAIL(err); 954 955 if (debug > 2) { 956 fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n", 957 vf->sender_decode_offset); 958 fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx); 959 fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci); 960 961 fprintf(stderr, "\t\t scope_desc_at: END \n\n"); 962 } 963 return PS_OK; 964 965 fail: 966 return err; 967} 968 969static int scopeDesc_chain(Nmethod_t *N) { 970 int32_t decode_offset = 0; 971 int32_t err; 972 973 if (debug > 2) { 974 fprintf(stderr, "\t scopeDesc_chain: BEGIN\n"); 975 } 976 977 err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset, 978 &decode_offset, SZ32); 979 CHECK_FAIL(err); 980 981 while (decode_offset > 0) { 982 Vframe_t *vf = &N->vframes[N->vf_cnt]; 983 984 if (debug > 2) { 985 fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset); 986 } 987 988 err = scope_desc_at(N, decode_offset, vf); 989 CHECK_FAIL(err); 990 991 if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) { 992 fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n"); 993 return -1; 994 } 995 err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE, 996 &vf->method); 997 CHECK_FAIL(err); 998 999 if (vf->method) { 1000 N->vf_cnt++; 1001 err = line_number_from_bci(N->J, vf); 1002 CHECK_FAIL(err); 1003 if (debug > 2) { 1004 fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n", 1005 vf->method, vf->line); 1006 } 1007 } 1008 decode_offset = vf->sender_decode_offset; 1009 } 1010 if (debug > 2) { 1011 fprintf(stderr, "\t scopeDesc_chain: END \n\n"); 1012 } 1013 return PS_OK; 1014 1015 fail: 1016 if (debug) { 1017 fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n"); 1018 } 1019 return err; 1020} 1021 1022 1023static int 1024name_for_nmethod(jvm_agent_t* J, 1025 uint64_t nm, 1026 uint64_t pc, 1027 uint64_t method, 1028 char *result, 1029 size_t size, 1030 Jframe_t *jframe 1031) { 1032 Nmethod_t *N; 1033 Vframe_t *vf; 1034 int32_t err; 1035 int deoptimized = 0; 1036 1037 if (debug) { 1038 fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc); 1039 } 1040 if (J->N == NULL) { 1041 J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t)); 1042 } 1043 memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */ 1044 N = J->N; 1045 N->J = J; 1046 N->nm = nm; 1047 N->pc = pc; 1048 N->jframe = jframe; 1049 1050 err = nmethod_info(N); 1051 CHECK_FAIL(err); 1052 if (debug) { 1053 fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n", 1054 pc, N->nm + N->deopt_beg); 1055 } 1056 1057 /* check for a deoptimized frame */ 1058 if ( pc == N->nm + N->deopt_beg) { 1059 uint64_t base; 1060 if (debug) { 1061 fprintf(stderr, "name_for_nmethod: found deoptimized frame\n"); 1062 } 1063 if (J->prev_fr.sender_sp != 0) { 1064 base = J->prev_fr.sender_sp + N->orig_pc_offset; 1065 } else { 1066 base = J->curr_fr.sp + N->orig_pc_offset; 1067 } 1068 err = read_pointer(J, base, &N->pc); 1069 CHECK_FAIL(err); 1070 if (debug) { 1071 fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n", 1072 pc, N->pc); 1073 } 1074 deoptimized = 1; 1075 } 1076 1077 err = pc_desc_at(N); 1078 CHECK_FAIL(err); 1079 1080 if (N->pc_desc > 0) { 1081 jframe->locinf = 1; 1082 err = scopeDesc_chain(N); 1083 CHECK_FAIL(err); 1084 } 1085 result[0] = COMP_METHOD_SIGN; 1086 vf = &N->vframes[0]; 1087 if (N->vf_cnt > 0) { 1088 jframe->vf_cnt = N->vf_cnt; 1089 jframe->bci = vf->bci; 1090 jframe->line = vf->line; 1091 err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1); 1092 CHECK_FAIL(err); 1093 } else { 1094 err = name_for_methodPtr(J, method, result+1, size-1); 1095 CHECK_FAIL(err); 1096 } 1097 if (deoptimized) { 1098 strncat(result + 1, " [deoptimized frame]; ", size-1); 1099 } else { 1100 strncat(result + 1, " [compiled] ", size-1); 1101 } 1102 if (debug) 1103 fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n", 1104 result, N->vf_cnt); 1105 return PS_OK; 1106 1107 fail: 1108 if (debug) 1109 fprintf(stderr, "name_for_nmethod: FAIL \n\n"); 1110 return err; 1111} 1112 1113static int 1114name_for_imethod(jvm_agent_t* J, 1115 uint64_t bcp, 1116 uint64_t method, 1117 char *result, 1118 size_t size, 1119 Jframe_t *jframe 1120) { 1121 uint64_t bci; 1122 uint64_t constMethod; 1123 Vframe_t vframe = {0}; 1124 Vframe_t *vf = &vframe; 1125 int32_t err; 1126 1127 err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod); 1128 CHECK_FAIL(err); 1129 1130 bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod); 1131 1132 if (debug) 1133 fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method); 1134 1135 err = name_for_methodPtr(J, method, result, size); 1136 CHECK_FAIL(err); 1137 if (debug) 1138 fprintf(stderr, "\t name_for_imethod: method name: %s\n", result); 1139 1140 if (bci > 0) { 1141 vf->method = method; 1142 vf->bci = bci; 1143 err = line_number_from_bci(J, vf); 1144 CHECK_FAIL(err); 1145 } 1146 jframe->bci = vf->bci; 1147 jframe->line = vf->line; 1148 jframe->locinf = 1; 1149 1150 if (debug) { 1151 fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n", 1152 vf->bci, vf->line); 1153 } 1154 return PS_OK; 1155 1156 fail: 1157 if (debug) 1158 fprintf(stderr, "\t name_for_imethod: FAIL\n"); 1159 return err; 1160} 1161 1162static int 1163name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result, 1164 size_t size, Jframe_t *jframe, int* is_interpreted) 1165{ 1166 uint64_t start; 1167 uint64_t vtbl; 1168 int32_t err; 1169 *is_interpreted = 0; 1170 1171 result[0] = '\0'; 1172 1173 err = find_start(J, pc, &start); 1174 CHECK_FAIL(err); 1175 1176 err = read_pointer(J, start, &vtbl); 1177 CHECK_FAIL(err); 1178 1179 if (vtbl == J->nmethod_vtbl) { 1180 uint64_t method; 1181 1182 err = read_pointer(J, start + OFFSET_nmethod_method, &method); 1183 CHECK_FAIL(err); 1184 1185 if (debug) { 1186 fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n", 1187 start, pc, method); 1188 } 1189 err = name_for_nmethod(J, start, pc, method, result, size, jframe); 1190 CHECK_FAIL(err); 1191 } else if (vtbl == J->BufferBlob_vtbl) { 1192 const char * name; 1193 1194 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); 1195 1196 /* 1197 * Temporary usage of string "Interpreter". 1198 * We need some other way to distinguish "StubRoutines" 1199 * and regular interpreted frames. 1200 */ 1201 if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) { 1202 *is_interpreted = 1; 1203 if (is_method(J, J->methodPtr)) { 1204 return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe); 1205 } 1206 } 1207 1208 if (err == PS_OK) { 1209 strncpy(result, name, size); 1210 free((void*)name); 1211 } else { 1212 strncpy(result, "<unknown BufferBlob>", size); 1213 } 1214 /* return PS_OK; */ 1215 } else { 1216 const char * name; 1217 1218 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); 1219 if (err == PS_OK) { 1220 strncpy(result, name, size); 1221 free((void*)name); 1222 } else { 1223 strncpy(result, "<unknown CodeBlob>", size); 1224 WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl); 1225 } 1226 } 1227 result[size-1] = '\0'; 1228 1229#ifdef X86_COMPILER2 1230 if (vtbl != J->RuntimeStub_vtbl) { 1231 uint64_t trial_pc; 1232 int frame_size; 1233 err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size, 1234 &frame_size, SZ32); 1235 CHECK_FAIL(err); 1236 1237 // frame_size is in words, we want bytes. 1238 frame_size *= POINTER_SIZE; /* word => byte conversion */ 1239 1240 /* 1241 Because c2 doesn't use FP as a framepointer the value of sp/fp we receive 1242 in the initial entry to a set of stack frames containing server frames 1243 will pretty much be nonsense. We can detect that nonsense by looking to 1244 see if the PC we received is correct if we look at the expected storage 1245 location in relation to the FP (ie. POINTER_SIZE(FP) ) 1246 */ 1247 1248 err = read_pointer(J, fp + POINTER_SIZE , &trial_pc); 1249 if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) { 1250 // Either we couldn't even read at the "fp" or the pc didn't match 1251 // both are sure clues that the fp is bogus. We no search the stack 1252 // for a reasonable number of words trying to find the bogus fp 1253 // and the current pc in adjacent words. The we will be able to 1254 // deduce an approximation of the frame pointer and actually get 1255 // the correct stack pointer. Which we can then unwind for the 1256 // next frame. 1257 int i; 1258 uint64_t check; 1259 uint64_t base = J->curr_fr.sp; 1260 uint64_t prev_fp = 0; 1261 for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) { 1262 err = read_pointer(J, base , &check); 1263 CHECK_FAIL(err); 1264 if (check == fp) { 1265 base += POINTER_SIZE; 1266 err = read_pointer(J, base , &check); 1267 CHECK_FAIL(err); 1268 if (check == pc) { 1269 if (debug) { 1270 fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE); 1271 } 1272 prev_fp = base - 2 * POINTER_SIZE; 1273 break; 1274 } 1275 } 1276 } 1277 if ( prev_fp != 0 ) { 1278 // real_sp is the sp we should have received for this frame 1279 uint64_t real_sp = prev_fp + 2 * POINTER_SIZE; 1280 // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word 1281 jframe->new_sp = real_sp + frame_size + POINTER_SIZE; 1282 err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc); 1283 CHECK_FAIL(err); 1284 err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp); 1285 CHECK_FAIL(err); 1286 return PS_OK; 1287 } 1288 } 1289 1290 /* A prototype to workaround FP absence */ 1291 /* 1292 * frame_size can be 0 for StubRoutines (1) frame. 1293 * In this case it should work with fp as usual. 1294 */ 1295 if (frame_size > 0) { 1296 jframe->new_fp = J->prev_fr.fp + frame_size; 1297 jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE; 1298 } else { 1299 memset(&J->curr_fr, 0, sizeof(Frame_t)); 1300 err = read_pointer(J, fp, &jframe->new_fp); 1301 CHECK_FAIL(err); 1302 1303 err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); 1304 CHECK_FAIL(err); 1305 } 1306 if (debug) { 1307 fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n", 1308 result, frame_size); 1309 fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n", 1310 J->prev_fr.fp, jframe->new_fp); 1311 } 1312 } 1313#endif /* X86_COMPILER2 */ 1314 1315 return PS_OK; 1316 1317 fail: 1318 return err; 1319} 1320 1321int Jget_vframe(jvm_agent_t* J, int vframe_no, 1322 char *name, size_t size, Jframe_t *jframe) 1323{ 1324 Nmethod_t *N = J->N; 1325 Vframe_t *vf; 1326 int32_t err; 1327 1328 if (vframe_no >= N->vf_cnt) { 1329 (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no); 1330 return -1; 1331 } 1332 vf = N->vframes + vframe_no; 1333 name[0] = COMP_METHOD_SIGN; 1334 err = name_for_methodPtr(J, vf->method, name + 1, size); 1335 CHECK_FAIL(err); 1336 1337 jframe->bci = vf->bci; 1338 jframe->line = vf->line; 1339 if (debug) { 1340 fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n", 1341 name, vf->line); 1342 } 1343 return PS_OK; 1344 1345 fail: 1346 if (debug) { 1347 fprintf(stderr, "\t Jget_vframe: FAIL\n"); 1348 } 1349 return err; 1350} 1351 1352#define MAX_SYM_SIZE 256 1353 1354int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, 1355 size_t size, Jframe_t *jframe) { 1356 uintptr_t fp; 1357 uintptr_t pc; 1358 /* arguments given to read_pointer need to be worst case sized */ 1359 uint64_t methodPtr = 0; 1360 uint64_t sender_sp; 1361 uint64_t bcp = 0; 1362 int is_interpreted = 0; 1363 int result = PS_OK; 1364 int err = PS_OK; 1365 1366 if (J == NULL) { 1367 return -1; 1368 } 1369 1370 jframe->vf_cnt = 1; 1371 jframe->new_fp = 0; 1372 jframe->new_pc = 0; 1373 jframe->line = 0; 1374 jframe->bci = 0; 1375 jframe->locinf = 0; 1376 1377 read_volatiles(J); 1378 pc = (uintptr_t) regs[R_PC]; 1379 J->curr_fr.pc = pc; 1380 J->curr_fr.fp = regs[R_FP]; 1381 J->curr_fr.sp = regs[R_SP]; 1382 1383 if (debug) 1384 fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc); 1385 1386#if defined(sparc) || defined(__sparc) 1387 /* The following workaround is for SPARC. CALL instruction occupates 8 bytes. 1388 * In the pcDesc structure return pc offset is recorded for CALL instructions. 1389 * regs[R_PC] contains a CALL instruction pc offset. 1390 */ 1391 pc += 8; 1392 bcp = (uintptr_t) regs[R_L1]; 1393 methodPtr = (uintptr_t) regs[R_L2]; 1394 sender_sp = regs[R_I5]; 1395 if (debug > 2) { 1396 fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n", 1397 regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]); 1398 } 1399#elif defined(i386) || defined(__i386) || defined(__amd64) 1400 1401 fp = (uintptr_t) regs[R_FP]; 1402 if (J->prev_fr.fp == 0) { 1403#ifdef X86_COMPILER2 1404 /* A workaround for top java frames */ 1405 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE); 1406#else 1407 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE); 1408#endif /* COMPILER2 */ 1409 } 1410 if (debug > 2) { 1411 printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp); 1412 } 1413 1414 if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) { 1415 methodPtr = 0; 1416 } 1417 if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) { 1418 sender_sp = 0; 1419 } 1420 if (read_pointer(J, fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) { 1421 bcp = 0; 1422 } 1423#endif /* i386 */ 1424 1425 J->methodPtr = methodPtr; 1426 J->bcp = bcp; 1427 1428 /* On x86 with C2 JVM: native frame may have wrong regs[R_FP] 1429 * For example: JVM_SuspendThread frame poins to the top interpreted frame. 1430 * If we call is_method(J, methodPtr) before codecache_contains(J, pc) 1431 * then we go over and omit both: nmethod and I2CAdapter frames. 1432 * Note, that regs[R_PC] is always correct if frame defined correctly. 1433 * So it is better to call codecache_contains(J, pc) from the beginning. 1434 */ 1435#ifndef X86_COMPILER2 1436 if (is_method(J, J->methodPtr)) { 1437 result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe); 1438 /* If the methodPtr is a method then this is highly likely to be 1439 an interpreter frame */ 1440 if (result >= 0) { 1441 is_interpreted = 1; 1442 } 1443 } else 1444#endif /* ! X86_COMPILER2 */ 1445 1446 if (codecache_contains(J, pc)) { 1447 result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted); 1448 } 1449#ifdef X86_COMPILER2 1450 else if (is_method(J, J->methodPtr)) { 1451 result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe); 1452 /* If the methodPtr is a method then this is highly likely to be 1453 an interpreter frame */ 1454 if (result >= 0) { 1455 is_interpreted = 1; 1456 } 1457 } 1458#endif /* X86_COMPILER2 */ 1459 else { 1460 if (debug) { 1461 fprintf(stderr, "Jlookup_by_regs: END with -1\n\n"); 1462 } 1463 result = -1; 1464 } 1465 if (!is_interpreted) { 1466 sender_sp = 0; 1467 } 1468 J->curr_fr.sender_sp = sender_sp; 1469 1470#ifdef X86_COMPILER2 1471 if (!J->curr_fr.fp) { 1472 J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP]; 1473 } 1474 if (!jframe->new_pc && jframe->new_fp) { 1475 // This seems dubious 1476 read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); 1477 CHECK_FAIL(err); 1478 if (debug > 2) { 1479 printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n", 1480 jframe->new_fp, jframe->new_pc); 1481 } 1482 } 1483 1484#endif /* X86_COMPILER2 */ 1485 J->prev_fr = J->curr_fr; 1486 1487 if (debug) 1488 fprintf(stderr, "Jlookup_by_regs: END\n\n"); 1489 1490 return result; 1491 1492 fail: 1493 return err; 1494} 1495 1496void update_gregs(prgregset_t gregs, Jframe_t jframe) { 1497#ifdef X86_COMPILER2 1498 if (debug > 0) { 1499 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]); 1500 } 1501 /* 1502 * A workaround for java C2 frames with unconventional FP. 1503 * may have to modify regset with new values for FP/PC/SP when needed. 1504 */ 1505 if (jframe.new_sp) { 1506 *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp; 1507 } else { 1508 // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE; 1509 } 1510 1511 if (jframe.new_fp) { 1512 *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp; 1513 } 1514 if (jframe.new_pc) { 1515 *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc; 1516 } 1517 if (debug > 0) { 1518 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]); 1519 } 1520#endif /* X86_COMPILER2 */ 1521} 1522 1523/* 1524 * Iterates over java frames at current location given by 'gregs'. 1525 * 1526 * Returns -1 if no java frames are present or if an error is encountered. 1527 * Returns the result of calling 'func' if the return value is non-zero. 1528 * Returns 0 otherwise. 1529 */ 1530int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) { 1531 char buf[MAX_SYM_SIZE + 1]; 1532 Jframe_t jframe; 1533 int i = 0, res; 1534#ifdef X86_COMPILER2 1535 if (debug > 0) { 1536 fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]); 1537 } 1538#endif /* X86_COMPILER2 */ 1539 1540 memset(&jframe, 0, sizeof(Jframe_t)); 1541 memset(buf, 0, sizeof(buf)); 1542 res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe); 1543 if (res != PS_OK) 1544 return (-1); 1545 1546 1547 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, 1548 jframe.line, NULL); 1549 if (res != 0) { 1550 update_gregs(gregs, jframe); 1551 return (res); 1552 } 1553 for (i = 1; i < jframe.vf_cnt; i++) { 1554 Jget_vframe(J, i, buf, sizeof(buf), &jframe); 1555 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, 1556 jframe.line, NULL); 1557 if (res != 0) { 1558 update_gregs(gregs, jframe); 1559 return (res); 1560 } 1561 } 1562 update_gregs(gregs, jframe); 1563 return (0); 1564} 1565