libjvm_db.c revision 6765:ea86cb581cfa
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" 3260833Sjake#include "JvmOffsets.h" 3360833Sjake 341590Srgrimes#define LIBJVM_SO "libjvm.so" 351590Srgrimes 361590Srgrimes#if defined(i386) || defined(__i386) || defined(__amd64) 3778201Sdd#ifdef COMPILER2 381590Srgrimes#define X86_COMPILER2 391590Srgrimes#endif /* COMPILER2 */ 401590Srgrimes#endif /* i386 */ 411590Srgrimes 421590Srgrimestypedef struct { 4378201Sdd 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 */ 461590Srgrimes uint64_t new_fp; /* fp for the next frame */ 471590Srgrimes uint64_t new_pc; /* pc for the next frame */ 481590Srgrimes uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */ 491590Srgrimes char locinf; /* indicates there is valid location info */ 501590Srgrimes} Jframe_t; 5174588Sache 5216438Sacheint Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, 531590Srgrimes size_t size, Jframe_t *jframe); 541590Srgrimes 551590Srgrimesint main(int arg) { return arg; } 561590Srgrimes 571590Srgrimesstatic int debug = 0; 581590Srgrimes 591590Srgrimesstatic void failed(int err, const char * file, int line) { 601590Srgrimes if (debug) { 6111547Sdg fprintf(stderr, "failed %d at %s:%d\n", err, file, line); 621590Srgrimes } 631590Srgrimes} 641590Srgrimes 6577291Sddstatic void warn(const char * file, int line, const char * msg) { 661590Srgrimes if (debug) { 671590Srgrimes fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line); 681590Srgrimes } 691590Srgrimes} 701590Srgrimes 711590Srgrimesstatic void warn1(const char * file, int line, const char * msg, intptr_t arg1) { 721590Srgrimes if (debug) { 731590Srgrimes fprintf(stderr, "warning: "); 741590Srgrimes fprintf(stderr, msg, arg1); 751590Srgrimes fprintf(stderr, " at %s:%d\n", file, line); 761590Srgrimes } 771590Srgrimes} 781590Srgrimes 7960938Sjake#define CHECK_FAIL(err) \ 8011547Sdg if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; } 8111547Sdg#define WARN(msg) warn(__FILE__, __LINE__, msg) 8236062Sjb#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1) 831590Srgrimes 8460938Sjaketypedef struct VMStructEntry { 8511547Sdg const char * typeName; /* The type name containing the given field (example: "Klass") */ 861590Srgrimes const char * fieldName; /* The field name within the type (example: "_name") */ 871590Srgrimes uint64_t address; /* Address of field; only used for static fields */ 881590Srgrimes /* ("offset" can not be reused because of apparent SparcWorks compiler bug */ 8978201Sdd /* in generation of initializer data) */ 9036434Sdanny} VMStructEntry; 9136434Sdanny 9274588Sache/* Prototyping inlined methods */ 9377291Sdd 9477291Sddint sprintf(char *s, const char *format, ...); 9577291Sdd 9677291Sdd#define SZ16 sizeof(int16_t) 971590Srgrimes#define SZ32 sizeof(int32_t) 981590Srgrimes 9978201Sdd#define COMP_METHOD_SIGN '*' 1001590Srgrimes 1011590Srgrimes#define MAX_VFRAMES_CNT 256 1021590Srgrimes 10311547Sdgtypedef struct vframe { 10478201Sdd uint64_t method; 1051590Srgrimes int32_t sender_decode_offset; 1061590Srgrimes int32_t methodIdx; 10736434Sdanny int32_t bci; 10836434Sdanny int32_t line; 10936434Sdanny} Vframe_t; 11036434Sdanny 11136434Sdannytypedef struct frame { 11236434Sdanny uintptr_t fp; 11336434Sdanny uintptr_t pc; 11436434Sdanny uintptr_t sp; 1151590Srgrimes uintptr_t sender_sp; // The unextended sp of the caller 1161590Srgrimes} Frame_t; 1171590Srgrimes 1181590Srgrimestypedef struct Nmethod_t { 1191590Srgrimes struct jvm_agent* J; 1201590Srgrimes Jframe_t *jframe; 1211590Srgrimes 1221590Srgrimes uint64_t nm; /* _nmethod */ 12316438Sache uint64_t pc; 12474588Sache uint64_t pc_desc; 12516438Sache 1261590Srgrimes int32_t orig_pc_offset; /* _orig_pc_offset */ 12777291Sdd int32_t instrs_beg; /* _code_offset */ 12877291Sdd int32_t instrs_end; 1291590Srgrimes int32_t deopt_beg; /* _deoptimize_offset */ 1301590Srgrimes int32_t scopes_data_beg; /* _scopes_data_offset */ 1311590Srgrimes int32_t scopes_data_end; 1321590Srgrimes int32_t metadata_beg; /* _metadata_offset */ 1331590Srgrimes int32_t metadata_end; 1341590Srgrimes int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ 1351590Srgrimes int32_t scopes_pcs_end; 1361590Srgrimes 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; 14677291Sdd uint64_t BufferBlob_vtbl; 14777291Sdd uint64_t RuntimeStub_vtbl; 14877291Sdd 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; 1531590Srgrimes uint64_t CodeCache_heap_address; 1541590Srgrimes 1551590Srgrimes /* Volatiles */ 15636434Sdanny uint8_t Use_Compressed_Oops; 15736434Sdanny uint64_t Universe_narrow_oop_base; 15836434Sdanny uint32_t Universe_narrow_oop_shift; 1591590Srgrimes uint64_t CodeCache_low; 1601590Srgrimes uint64_t CodeCache_high; 1611590Srgrimes uint64_t CodeCache_segmap_low; 16236434Sdanny uint64_t CodeCache_segmap_high; 16336434Sdanny 16436434Sdanny int32_t SIZE_CodeCache_log2_segment; 1651590Srgrimes 1661590Srgrimes uint64_t methodPtr; 16736434Sdanny uint64_t bcp; 1681590Srgrimes 1691590Srgrimes Nmethod_t *N; /*Inlined methods support */ 17036434Sdanny Frame_t prev_fr; 17136434Sdanny Frame_t curr_fr; 1721590Srgrimes}; 1731590Srgrimes 1741590Srgrimesstatic int 1751590Srgrimesread_string(struct ps_prochandle *P, 1761590Srgrimes char *buf, /* caller's buffer */ 1771590Srgrimes size_t size, /* upper limit on bytes to read */ 1781590Srgrimes uintptr_t addr) /* address in process */ 1791590Srgrimes{ 1801590Srgrimes int err = PS_OK; 1811590Srgrimes while (size-- > 1 && err == PS_OK) { 1821590Srgrimes err = ps_pread(P, addr, buf, 1); 1831590Srgrimes if (*buf == '\0') { 1841590Srgrimes return PS_OK; 1851590Srgrimes } 1861590Srgrimes addr += 1; 1871590Srgrimes buf += 1; 1881590Srgrimes } 1891590Srgrimes return -1; 1901590Srgrimes} 1911590Srgrimes 1921590Srgrimesstatic int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) { 1931590Srgrimes int err = -1; 1941590Srgrimes uint32_t ptr32; 19519223Sjoerg err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); 1961590Srgrimes *ptr = ptr32; 19736062Sjb return err; 19836062Sjb} 1991590Srgrimes 20078201Sddstatic int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) { 20116438Sache int err = -1; 20216438Sache uint32_t ptr32; 20377291Sdd 2041590Srgrimes switch (DATA_MODEL) { 20511547Sdg case PR_MODEL_LP64: 20611547Sdg err = ps_pread(J->P, base, ptr, sizeof(uint64_t)); 2071590Srgrimes break; 2081590Srgrimes case PR_MODEL_ILP32: 2091590Srgrimes err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); 2101590Srgrimes *ptr = ptr32; 2111590Srgrimes break; 2121590Srgrimes } 2131590Srgrimes 2141590Srgrimes return err; 2151590Srgrimes} 2161590Srgrimes 2171590Srgrimesstatic int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) { 2181590Srgrimes uint64_t ptr; 2191590Srgrimes int err; 2201590Srgrimes char buffer[1024]; 2211590Srgrimes 2221590Srgrimes *stringp = NULL; 2231590Srgrimes err = read_pointer(J, base, &ptr); 2241590Srgrimes CHECK_FAIL(err); 2251590Srgrimes if (ptr != 0) { 22670467Sphk err = read_string(J->P, buffer, sizeof(buffer), ptr); 22711547Sdg CHECK_FAIL(err); 22819223Sjoerg *stringp = strdup(buffer); 22970467Sphk } 23019223Sjoerg return PS_OK; 23111547Sdg 2321590Srgrimes fail: 2331590Srgrimes return err; 2341590Srgrimes} 23577291Sdd 23677291Sddstatic int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) { 23777291Sdd uint64_t ptr; 23877291Sdd int err; 23977291Sdd 24077291Sdd err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName); 24177291Sdd CHECK_FAIL(err); 24277291Sdd err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName); 24377291Sdd CHECK_FAIL(err); 24477291Sdd err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address); 24577291Sdd CHECK_FAIL(err); 24677291Sdd 24777291Sdd return PS_OK; 24816438Sache 24974588Sache fail: 25074588Sache if (vmp->typeName != NULL) free((void*)vmp->typeName); 25174588Sache if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 25274588Sache return err; 25374588Sache} 2541590Srgrimes 2551590Srgrimesstatic int parse_vmstructs(jvm_agent_t* J) { 2561590Srgrimes VMStructEntry vmVar; 2571590Srgrimes VMStructEntry* vmp = &vmVar; 25874588Sache uint64_t gHotSpotVMStructs; 2591590Srgrimes psaddr_t sym_addr; 2601590Srgrimes uint64_t base; 2611590Srgrimes int err; 2621590Srgrimes 2631590Srgrimes /* Clear *vmp now in case we jump to fail: */ 2641590Srgrimes memset(vmp, 0, sizeof(VMStructEntry)); 2651590Srgrimes 2661590Srgrimes err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr); 2671590Srgrimes CHECK_FAIL(err); 2681590Srgrimes err = read_pointer(J, sym_addr, &gHotSpotVMStructs); 2691590Srgrimes CHECK_FAIL(err); 27077291Sdd base = gHotSpotVMStructs; 27116438Sache 27274588Sache err = PS_OK; 27374588Sache while (err == PS_OK) { 27474588Sache memset(vmp, 0, sizeof(VMStructEntry)); 27574588Sache err = parse_vmstruct_entry(J, base, vmp); 27674588Sache if (err != PS_OK || vmp->typeName == NULL) { 27711547Sdg break; 27811547Sdg } 27911547Sdg 28074588Sache if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { 2811590Srgrimes if (strcmp("_heap", vmp->fieldName) == 0) { 2821590Srgrimes err = read_pointer(J, vmp->address, &J->CodeCache_heap_address); 2831590Srgrimes } 2841590Srgrimes } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { 2851590Srgrimes if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { 28677291Sdd J->Universe_narrow_oop_base_address = vmp->address; 28777291Sdd } 28877291Sdd if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { 28977291Sdd J->Universe_narrow_oop_shift_address = vmp->address; 29077291Sdd } 29177291Sdd } 29277291Sdd CHECK_FAIL(err); 29377291Sdd 29477291Sdd base += SIZE_VMStructEntry; 29577291Sdd if (vmp->typeName != NULL) free((void*)vmp->typeName); 29677291Sdd if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 29777291Sdd } 29877291Sdd 29977291Sdd return PS_OK; 30077291Sdd 30177291Sdd fail: 30277291Sdd if (vmp->typeName != NULL) free((void*)vmp->typeName); 30377291Sdd if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 30477291Sdd return -1; 30577291Sdd} 30677291Sdd 30777291Sddstatic int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { 30877291Sdd psaddr_t sym_addr; 30977291Sdd int err; 31077291Sdd 31177291Sdd err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); 31277291Sdd if (err != PS_OK) goto fail; 31377291Sdd *valuep = sym_addr; 31477291Sdd return PS_OK; 31577291Sdd 31677291Sdd fail: 31777291Sdd return err; 31877291Sdd} 31977291Sdd 32077291Sddstatic int read_volatiles(jvm_agent_t* J) { 32177291Sdd uint64_t ptr; 32277291Sdd int err; 32377291Sdd 32477291Sdd err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); 32577291Sdd if (err == PS_OK) { 32677291Sdd err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); 32777291Sdd CHECK_FAIL(err); 32877291Sdd } else { 32977291Sdd J->Use_Compressed_Oops = 0; 33077291Sdd } 33177291Sdd 33277291Sdd err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); 33377291Sdd CHECK_FAIL(err); 33477291Sdd err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); 33511547Sdg CHECK_FAIL(err); 33677291Sdd 33777291Sdd err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + 33877291Sdd OFFSET_VirtualSpace_low, &J->CodeCache_low); 33977291Sdd CHECK_FAIL(err); 34077291Sdd err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + 34177291Sdd OFFSET_VirtualSpace_high, &J->CodeCache_high); 34278201Sdd CHECK_FAIL(err); 34378201Sdd err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap + 34477291Sdd OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low); 34577291Sdd CHECK_FAIL(err); 34677291Sdd err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap + 34777291Sdd OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high); 34877291Sdd CHECK_FAIL(err); 34977291Sdd 35074588Sache err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size, 35177291Sdd &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); 35274588Sache CHECK_FAIL(err); 35378201Sdd 35478201Sdd return PS_OK; 3551590Srgrimes 3561590Srgrimes fail: 35777291Sdd return err; 35877291Sdd} 3591590Srgrimes 36077328Sru 3611590Srgrimesstatic int codecache_contains(jvm_agent_t* J, uint64_t ptr) { 3621590Srgrimes /* make sure the code cache is up to date */ 36316438Sache return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high); 36478201Sdd} 36562871Skris 3661590Srgrimesstatic uint64_t segment_for(jvm_agent_t* J, uint64_t p) { 3671590Srgrimes return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment; 3681590Srgrimes} 3691590Srgrimes 3701590Srgrimesstatic uint64_t block_at(jvm_agent_t* J, int i) { 3711590Srgrimes return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment); 3721590Srgrimes} 37311547Sdg 3741590Srgrimesstatic int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) { 3751590Srgrimes int err; 3761590Srgrimes 3771590Srgrimes *startp = 0; 37877291Sdd if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) { 37977291Sdd int32_t used; 38077291Sdd uint64_t segment = segment_for(J, ptr); 3811590Srgrimes uint64_t block = J->CodeCache_segmap_low; 3821590Srgrimes uint8_t tag; 3831590Srgrimes err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); 3841590Srgrimes CHECK_FAIL(err); 3851590Srgrimes if (tag == 0xff) 3861590Srgrimes return PS_OK; 3871590Srgrimes while (tag > 0) { 3881590Srgrimes err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); 3891590Srgrimes CHECK_FAIL(err); 3901590Srgrimes segment -= tag; 3911590Srgrimes } 3921590Srgrimes block = block_at(J, segment); 3931590Srgrimes err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used)); 3941590Srgrimes CHECK_FAIL(err); 3951590Srgrimes if (used) { 3961590Srgrimes *startp = block + SIZE_HeapBlockHeader; 3971590Srgrimes } 3981590Srgrimes } 3991590Srgrimes return PS_OK; 4001590Srgrimes 4011590Srgrimes fail: 4021590Srgrimes return -1; 4031590Srgrimes} 4041590Srgrimes 4051590Srgrimesstatic int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) { 4061590Srgrimes psaddr_t sym_addr; 4071590Srgrimes int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); 4081590Srgrimes if (err == PS_OK) { 4091590Srgrimes err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t)); 4101590Srgrimes return err; 4111590Srgrimes } 4121590Srgrimes *valuep = -1; 4131590Srgrimes return -1; 4141590Srgrimes} 4151590Srgrimes 4161590Srgrimesjvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) { 4171590Srgrimes jvm_agent_t* J; 4181590Srgrimes int err; 4191590Srgrimes 4201590Srgrimes if (vers != JVM_DB_VERSION) { 4211590Srgrimes errno = ENOTSUP; 4221590Srgrimes return NULL; 4231590Srgrimes } 4241590Srgrimes 4251590Srgrimes J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1); 4261590Srgrimes 4271590Srgrimes debug = getenv("LIBJVMDB_DEBUG") != NULL; 4281590Srgrimes if (debug) debug = 3; 4291590Srgrimes 4301590Srgrimes if (debug) { 4311590Srgrimes fprintf(stderr, "Jagent_create: debug=%d\n", debug); 4321590Srgrimes#ifdef X86_COMPILER2 4331590Srgrimes fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE); 4341590Srgrimes#endif /* X86_COMPILER2 */ 4351590Srgrimes } 4361590Srgrimes 4371590Srgrimes J->P = P; 4381590Srgrimes 4391590Srgrimes // Initialize the initial previous frame 4401590Srgrimes 4411590Srgrimes J->prev_fr.fp = 0; 4421590Srgrimes J->prev_fr.pc = 0; 4431590Srgrimes J->prev_fr.sp = 0; 4441590Srgrimes J->prev_fr.sender_sp = 0; 4451590Srgrimes 4461590Srgrimes err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl); 4471590Srgrimes CHECK_FAIL(err); 4481590Srgrimes err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl); 4491590Srgrimes if (err != PS_OK) J->BufferBlob_vtbl = 0; 4501590Srgrimes err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl); 4511590Srgrimes CHECK_FAIL(err); 4521590Srgrimes err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl); 4531590Srgrimes CHECK_FAIL(err); 4541590Srgrimes err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl); 4551590Srgrimes CHECK_FAIL(err); 4561590Srgrimes 4571590Srgrimes err = parse_vmstructs(J); 4581590Srgrimes CHECK_FAIL(err); 4591590Srgrimes err = read_volatiles(J); 4601590Srgrimes CHECK_FAIL(err); 4611590Srgrimes 4621590Srgrimes return J; 4631590Srgrimes 4641590Srgrimes fail: 4651590Srgrimes Jagent_destroy(J); 4661590Srgrimes return NULL; 4671590Srgrimes} 4681590Srgrimes 4691590Srgrimesvoid Jagent_destroy(jvm_agent_t *J) { 4701590Srgrimes if (J != NULL) { 4711590Srgrimes free(J); 4721590Srgrimes } 4731590Srgrimes} 4741590Srgrimes 4751590Srgrimesstatic int is_method(jvm_agent_t* J, uint64_t methodPtr) { 4761590Srgrimes uint64_t klass; 4771590Srgrimes int err = read_pointer(J, methodPtr, &klass); 4781590Srgrimes if (err != PS_OK) goto fail; 47977291Sdd return klass == J->Method_vtbl; 48077291Sdd 48177291Sdd fail: 48277291Sdd return 0; 48377291Sdd} 48477291Sdd 48577291Sddstatic int 48677291Sddname_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size) 48777291Sdd{ 48877291Sdd short nameIndex; 48977291Sdd short signatureIndex; 49077291Sdd uint64_t constantPool; 49177291Sdd uint64_t constMethod; 49277291Sdd uint64_t nameSymbol; 49377291Sdd uint64_t signatureSymbol; 49477291Sdd uint64_t klassPtr; 49577291Sdd uint64_t klassSymbol; 49677291Sdd short klassSymbolLength; 49777291Sdd short nameSymbolLength; 49877291Sdd short signatureSymbolLength; 49977291Sdd char * nameString = NULL; 50077291Sdd char * klassString = NULL; 50177291Sdd char * signatureString = NULL; 50277291Sdd int err; 50377291Sdd 50477291Sdd err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod); 50577291Sdd CHECK_FAIL(err); 50677291Sdd err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool); 50777291Sdd CHECK_FAIL(err); 50877291Sdd 50977291Sdd /* To get name string */ 51077291Sdd err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2); 51177291Sdd CHECK_FAIL(err); 51277291Sdd err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol); 51377291Sdd CHECK_FAIL(err); 51477291Sdd // The symbol is a CPSlot and has lower bit set to indicate metadata 51577291Sdd nameSymbol &= (~1); // remove metadata lsb 51677291Sdd err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); 51777291Sdd CHECK_FAIL(err); 51877291Sdd nameString = (char*)calloc(nameSymbolLength + 1, 1); 51977291Sdd err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); 52077291Sdd CHECK_FAIL(err); 52177291Sdd 52277291Sdd /* To get signature string */ 52377291Sdd err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2); 52477291Sdd CHECK_FAIL(err); 52577291Sdd err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol); 52677291Sdd CHECK_FAIL(err); 52777291Sdd signatureSymbol &= (~1); // remove metadata lsb 52877291Sdd err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); 52977291Sdd CHECK_FAIL(err); 53077291Sdd signatureString = (char*)calloc(signatureSymbolLength + 1, 1); 53177291Sdd err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); 53277291Sdd CHECK_FAIL(err); 53377291Sdd 53477291Sdd /* To get klass string */ 53577291Sdd err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr); 53677291Sdd CHECK_FAIL(err); 53777291Sdd err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol); 53877291Sdd CHECK_FAIL(err); 53977291Sdd err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); 54077291Sdd CHECK_FAIL(err); 54177291Sdd klassString = (char*)calloc(klassSymbolLength + 1, 1); 54277291Sdd err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); 54377291Sdd CHECK_FAIL(err); 54477291Sdd 54577291Sdd result[0] = '\0'; 54677291Sdd strncat(result, klassString, size); 54777291Sdd size -= strlen(klassString); 54877291Sdd strncat(result, ".", size); 54977291Sdd size -= 1; 55077291Sdd strncat(result, nameString, size); 55177291Sdd size -= strlen(nameString); 55277291Sdd strncat(result, signatureString, size); 5531590Srgrimes 5541590Srgrimes if (nameString != NULL) free(nameString); 5551590Srgrimes if (klassString != NULL) free(klassString); 5561590Srgrimes if (signatureString != NULL) free(signatureString); 5571590Srgrimes 5581590Srgrimes return PS_OK; 5591590Srgrimes 56016438Sache fail: 56116438Sache if (debug) { 5621590Srgrimes fprintf(stderr, "name_for_methodPtr: FAIL \n\n"); 56316438Sache } 56474588Sache if (nameString != NULL) free(nameString); 56574588Sache if (klassString != NULL) free(klassString); 56674588Sache if (signatureString != NULL) free(signatureString); 56774588Sache return -1; 5681590Srgrimes} 5691590Srgrimes 5701590Srgrimesstatic int nmethod_info(Nmethod_t *N) 5711590Srgrimes{ 572 jvm_agent_t *J = N->J; 573 uint64_t nm = N->nm; 574 int32_t err; 575 576 if (debug > 2 ) 577 fprintf(stderr, "\t nmethod_info: BEGIN \n"); 578 579 /* Instructions */ 580 err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32); 581 CHECK_FAIL(err); 582 err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32); 583 CHECK_FAIL(err); 584 err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32); 585 CHECK_FAIL(err); 586 err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); 587 CHECK_FAIL(err); 588 589 /* Metadata */ 590 err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32); 591 CHECK_FAIL(err); 592 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32); 593 CHECK_FAIL(err); 594 595 /* scopes_pcs */ 596 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); 597 CHECK_FAIL(err); 598 err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32); 599 CHECK_FAIL(err); 600 601 /* scopes_data */ 602 err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32); 603 CHECK_FAIL(err); 604 605 if (debug > 2 ) { 606 N->scopes_data_end = N->scopes_pcs_beg; 607 608 fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n", 609 N->instrs_beg, N->instrs_end); 610 611 fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n", 612 N->deopt_beg); 613 614 fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", 615 N->orig_pc_offset); 616 617 fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n", 618 N->metadata_beg, N->metadata_end); 619 620 fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", 621 N->scopes_data_beg, N->scopes_data_end); 622 623 fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", 624 N->scopes_pcs_beg, N->scopes_pcs_end); 625 626 fprintf(stderr, "\t nmethod_info: END \n\n"); 627 } 628 return PS_OK; 629 630 fail: 631 return err; 632} 633 634static int 635raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val) 636{ 637 int shift = 0; 638 int value = 0; 639 uint8_t ch = 0; 640 int32_t err; 641 int32_t sum; 642 // Constants for UNSIGNED5 coding of Pack200 643 // see compressedStream.hpp 644 enum { 645 lg_H = 6, 646 H = 1<<lg_H, 647 BitsPerByte = 8, 648 L = (1<<BitsPerByte)-H, 649 }; 650 int i; 651 652 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); 653 CHECK_FAIL(err); 654 if (debug > 2) 655 fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch); 656 657 sum = ch; 658 if ( sum >= L ) { 659 int32_t lg_H_i = lg_H; 660 // Read maximum of 5 total bytes (we've already read 1). 661 // See CompressedReadStream::read_int_mb 662 for ( i = 0; i < 4; i++) { 663 err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); 664 CHECK_FAIL(err); 665 sum += ch << lg_H_i; 666 if (ch < L ) { 667 *val = sum; 668 return PS_OK; 669 } 670 lg_H_i += lg_H; 671 } 672 } 673 *val = sum; 674 return PS_OK; 675 676 fail: 677 return err; 678} 679 680static int 681read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line) 682{ 683 uint8_t next = 0; 684 int32_t bci_delta; 685 int32_t line_delta; 686 int32_t err; 687 688 if (debug > 2) 689 fprintf(stderr, "\t\t read_pair: BEGIN\n"); 690 691 err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t)); 692 CHECK_FAIL(err); 693 694 if (next == 0) { 695 if (debug > 2) 696 fprintf(stderr, "\t\t read_pair: END: next == 0\n"); 697 return 1; /* stream terminated */ 698 } 699 if (next == 0xFF) { 700 if (debug > 2) 701 fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n"); 702 703 /* Escape character, regular compression used */ 704 705 err = raw_read_int(J, buffer, &bci_delta); 706 CHECK_FAIL(err); 707 708 err = raw_read_int(J, buffer, &line_delta); 709 CHECK_FAIL(err); 710 711 *bci += bci_delta; 712 *line += line_delta; 713 714 if (debug > 2) { 715 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", 716 line_delta, bci_delta); 717 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", 718 *line, *bci); 719 } 720 } else { 721 /* Single byte compression used */ 722 *bci += next >> 3; 723 *line += next & 0x7; 724 if (debug > 2) { 725 fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", 726 next & 0x7, next >> 3); 727 fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", 728 *line, *bci); 729 } 730 } 731 if (debug > 2) 732 fprintf(stderr, "\t\t read_pair: END\n"); 733 return PS_OK; 734 735 fail: 736 if (debug) 737 fprintf(stderr, "\t\t read_pair: FAIL\n"); 738 return err; 739} 740 741static int 742line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) 743{ 744 uint64_t buffer; 745 uint16_t code_size; 746 uint64_t code_end_delta; 747 uint64_t constMethod; 748 int8_t access_flags; 749 int32_t best_bci = 0; 750 int32_t stream_bci = 0; 751 int32_t stream_line = 0; 752 int32_t err; 753 754 if (debug > 2) { 755 char name[256]; 756 err = name_for_methodPtr(J, vf->method, name, 256); 757 CHECK_FAIL(err); 758 fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n", 759 name, vf->bci); 760 } 761 762 err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod); 763 CHECK_FAIL(err); 764 765 vf->line = 0; 766 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t)); 767 CHECK_FAIL(err); 768 769 if (!(access_flags & ConstMethod_has_linenumber_table)) { 770 if (debug > 2) 771 fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n"); 772 return PS_OK; 773 } 774 775 /* The line numbers are a short array of 2-tuples [start_pc, line_number]. 776 * Not necessarily sorted and not necessarily one-to-one. 777 */ 778 779 err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16); 780 CHECK_FAIL(err); 781 782 /* inlined_table_start() */ 783 code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0; 784 buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta; 785 786 if (debug > 2) { 787 fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n", 788 vf->method, (access_flags & AccessFlags_NATIVE)); 789 fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n", 790 buffer, (int) code_size); 791 } 792 793 while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) { 794 if (stream_bci == vf->bci) { 795 /* perfect match */ 796 if (debug > 2) 797 fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line); 798 vf->line = stream_line; 799 return PS_OK; 800 } else { 801 /* update best_bci/line */ 802 if (stream_bci < vf->bci && stream_bci >= best_bci) { 803 best_bci = stream_bci; 804 vf->line = stream_line; 805 if (debug > 2) { 806 fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n", 807 best_bci, vf->line); 808 } 809 } 810 } 811 } 812 if (debug > 2) 813 fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line); 814 return PS_OK; 815 816 fail: 817 if (debug) 818 fprintf(stderr, "\t line_number_from_bci: FAIL\n"); 819 return err; 820} 821 822static int 823get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc) 824{ 825 int32_t pc_offset; 826 int32_t err; 827 828 err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32); 829 CHECK_FAIL(err); 830 831 *real_pc = N->nm + N->instrs_beg + pc_offset; 832 if (debug > 2) { 833 fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n", 834 pc_offset, *real_pc); 835 } 836 return PS_OK; 837 838 fail: 839 return err; 840} 841 842/* Finds a PcDesc with real-pc equal to N->pc */ 843static int pc_desc_at(Nmethod_t *N) 844{ 845 uint64_t pc_diff; 846 int32_t offs; 847 int32_t err; 848 849 if (debug > 2) 850 fprintf(stderr, "\t pc_desc_at: BEGIN\n"); 851 852 N->vf_cnt = 0; 853 N->pc_desc = 0; 854 855 for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) { 856 uint64_t pd; 857 uint64_t best_pc_diff = 16; /* some approximation */ 858 uint64_t real_pc = 0; 859 860 pd = N->nm + offs; 861 err = get_real_pc(N, pd, &real_pc); 862 CHECK_FAIL(err); 863 864 pc_diff = real_pc - N->pc; 865 866 /* In general, this fragment should work */ 867 if (pc_diff == 0) { 868 N->pc_desc = pd; 869 if (debug) { 870 fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd); 871 } 872 return PS_OK; 873 } 874 /* This fragment is to be able to find out an appropriate 875 * pc_desc entry even if pc_desc info is inaccurate. 876 */ 877 if (best_pc_diff > pc_diff && pc_diff > 0) { 878 best_pc_diff = pc_diff; 879 N->pc_desc = pd; 880 } 881 } 882 if (debug) { 883 fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND"); 884 if (pc_diff < 20) 885 fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff); 886 else 887 fprintf(stderr, "\n\n"); 888 } 889 return PS_OK; 890 891 fail: 892 return err; 893} 894 895static int 896scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf) 897{ 898 uint64_t buffer; 899 int32_t err; 900 901 if (debug > 2) { 902 fprintf(stderr, "\t\t scope_desc_at: BEGIN \n"); 903 } 904 905 buffer = N->nm + N->scopes_data_beg + decode_offset; 906 907 err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset); 908 CHECK_FAIL(err); 909 910 err = raw_read_int(N->J, &buffer, &vf->methodIdx); 911 CHECK_FAIL(err); 912 913 err = raw_read_int(N->J, &buffer, &vf->bci); 914 CHECK_FAIL(err); 915 916 if (debug > 2) { 917 fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n", 918 vf->sender_decode_offset); 919 fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx); 920 fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci); 921 922 fprintf(stderr, "\t\t scope_desc_at: END \n\n"); 923 } 924 return PS_OK; 925 926 fail: 927 return err; 928} 929 930static int scopeDesc_chain(Nmethod_t *N) { 931 int32_t decode_offset = 0; 932 int32_t err; 933 934 if (debug > 2) { 935 fprintf(stderr, "\t scopeDesc_chain: BEGIN\n"); 936 } 937 938 err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset, 939 &decode_offset, SZ32); 940 CHECK_FAIL(err); 941 942 while (decode_offset > 0) { 943 Vframe_t *vf = &N->vframes[N->vf_cnt]; 944 945 if (debug > 2) { 946 fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset); 947 } 948 949 err = scope_desc_at(N, decode_offset, vf); 950 CHECK_FAIL(err); 951 952 if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) { 953 fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n"); 954 return -1; 955 } 956 err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE, 957 &vf->method); 958 CHECK_FAIL(err); 959 960 if (vf->method) { 961 N->vf_cnt++; 962 err = line_number_from_bci(N->J, vf); 963 CHECK_FAIL(err); 964 if (debug > 2) { 965 fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n", 966 vf->method, vf->line); 967 } 968 } 969 decode_offset = vf->sender_decode_offset; 970 } 971 if (debug > 2) { 972 fprintf(stderr, "\t scopeDesc_chain: END \n\n"); 973 } 974 return PS_OK; 975 976 fail: 977 if (debug) { 978 fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n"); 979 } 980 return err; 981} 982 983 984static int 985name_for_nmethod(jvm_agent_t* J, 986 uint64_t nm, 987 uint64_t pc, 988 uint64_t method, 989 char *result, 990 size_t size, 991 Jframe_t *jframe 992) { 993 Nmethod_t *N; 994 Vframe_t *vf; 995 int32_t err; 996 int deoptimized = 0; 997 998 if (debug) { 999 fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc); 1000 } 1001 if (J->N == NULL) { 1002 J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t)); 1003 } 1004 memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */ 1005 N = J->N; 1006 N->J = J; 1007 N->nm = nm; 1008 N->pc = pc; 1009 N->jframe = jframe; 1010 1011 err = nmethod_info(N); 1012 CHECK_FAIL(err); 1013 if (debug) { 1014 fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n", 1015 pc, N->nm + N->deopt_beg); 1016 } 1017 1018 /* check for a deoptimized frame */ 1019 if ( pc == N->nm + N->deopt_beg) { 1020 uint64_t base; 1021 if (debug) { 1022 fprintf(stderr, "name_for_nmethod: found deoptimized frame\n"); 1023 } 1024 if (J->prev_fr.sender_sp != 0) { 1025 base = J->prev_fr.sender_sp + N->orig_pc_offset; 1026 } else { 1027 base = J->curr_fr.sp + N->orig_pc_offset; 1028 } 1029 err = read_pointer(J, base, &N->pc); 1030 CHECK_FAIL(err); 1031 if (debug) { 1032 fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n", 1033 pc, N->pc); 1034 } 1035 deoptimized = 1; 1036 } 1037 1038 err = pc_desc_at(N); 1039 CHECK_FAIL(err); 1040 1041 if (N->pc_desc > 0) { 1042 jframe->locinf = 1; 1043 err = scopeDesc_chain(N); 1044 CHECK_FAIL(err); 1045 } 1046 result[0] = COMP_METHOD_SIGN; 1047 vf = &N->vframes[0]; 1048 if (N->vf_cnt > 0) { 1049 jframe->vf_cnt = N->vf_cnt; 1050 jframe->bci = vf->bci; 1051 jframe->line = vf->line; 1052 err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1); 1053 CHECK_FAIL(err); 1054 } else { 1055 err = name_for_methodPtr(J, method, result+1, size-1); 1056 CHECK_FAIL(err); 1057 } 1058 if (deoptimized) { 1059 strncat(result + 1, " [deoptimized frame]; ", size-1); 1060 } else { 1061 strncat(result + 1, " [compiled] ", size-1); 1062 } 1063 if (debug) 1064 fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n", 1065 result, N->vf_cnt); 1066 return PS_OK; 1067 1068 fail: 1069 if (debug) 1070 fprintf(stderr, "name_for_nmethod: FAIL \n\n"); 1071 return err; 1072} 1073 1074static int 1075name_for_imethod(jvm_agent_t* J, 1076 uint64_t bcp, 1077 uint64_t method, 1078 char *result, 1079 size_t size, 1080 Jframe_t *jframe 1081) { 1082 uint64_t bci; 1083 uint64_t constMethod; 1084 Vframe_t vframe = {0}; 1085 Vframe_t *vf = &vframe; 1086 int32_t err; 1087 1088 err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod); 1089 CHECK_FAIL(err); 1090 1091 bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod); 1092 1093 if (debug) 1094 fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method); 1095 1096 err = name_for_methodPtr(J, method, result, size); 1097 CHECK_FAIL(err); 1098 if (debug) 1099 fprintf(stderr, "\t name_for_imethod: method name: %s\n", result); 1100 1101 if (bci > 0) { 1102 vf->method = method; 1103 vf->bci = bci; 1104 err = line_number_from_bci(J, vf); 1105 CHECK_FAIL(err); 1106 } 1107 jframe->bci = vf->bci; 1108 jframe->line = vf->line; 1109 jframe->locinf = 1; 1110 1111 if (debug) { 1112 fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n", 1113 vf->bci, vf->line); 1114 } 1115 return PS_OK; 1116 1117 fail: 1118 if (debug) 1119 fprintf(stderr, "\t name_for_imethod: FAIL\n"); 1120 return err; 1121} 1122 1123static int 1124name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result, 1125 size_t size, Jframe_t *jframe, int* is_interpreted) 1126{ 1127 uint64_t start; 1128 uint64_t vtbl; 1129 int32_t err; 1130 *is_interpreted = 0; 1131 1132 result[0] = '\0'; 1133 1134 err = find_start(J, pc, &start); 1135 CHECK_FAIL(err); 1136 1137 err = read_pointer(J, start, &vtbl); 1138 CHECK_FAIL(err); 1139 1140 if (vtbl == J->nmethod_vtbl) { 1141 uint64_t method; 1142 1143 err = read_pointer(J, start + OFFSET_nmethod_method, &method); 1144 CHECK_FAIL(err); 1145 1146 if (debug) { 1147 fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n", 1148 start, pc, method); 1149 } 1150 err = name_for_nmethod(J, start, pc, method, result, size, jframe); 1151 CHECK_FAIL(err); 1152 } else if (vtbl == J->BufferBlob_vtbl) { 1153 const char * name; 1154 1155 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); 1156 1157 /* 1158 * Temporary usage of string "Interpreter". 1159 * We need some other way to distinguish "StubRoutines" 1160 * and regular interpreted frames. 1161 */ 1162 if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) { 1163 *is_interpreted = 1; 1164 if (is_method(J, J->methodPtr)) { 1165 return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe); 1166 } 1167 } 1168 1169 if (err == PS_OK) { 1170 strncpy(result, name, size); 1171 free((void*)name); 1172 } else { 1173 strncpy(result, "<unknown BufferBlob>", size); 1174 } 1175 /* return PS_OK; */ 1176 } else { 1177 const char * name; 1178 1179 err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); 1180 if (err == PS_OK) { 1181 strncpy(result, name, size); 1182 free((void*)name); 1183 } else { 1184 strncpy(result, "<unknown CodeBlob>", size); 1185 WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl); 1186 } 1187 } 1188 result[size-1] = '\0'; 1189 1190#ifdef X86_COMPILER2 1191 if (vtbl != J->RuntimeStub_vtbl) { 1192 uint64_t trial_pc; 1193 int frame_size; 1194 err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size, 1195 &frame_size, SZ32); 1196 CHECK_FAIL(err); 1197 1198 // frame_size is in words, we want bytes. 1199 frame_size *= POINTER_SIZE; /* word => byte conversion */ 1200 1201 /* 1202 Because c2 doesn't use FP as a framepointer the value of sp/fp we receive 1203 in the initial entry to a set of stack frames containing server frames 1204 will pretty much be nonsense. We can detect that nonsense by looking to 1205 see if the PC we received is correct if we look at the expected storage 1206 location in relation to the FP (ie. POINTER_SIZE(FP) ) 1207 */ 1208 1209 err = read_pointer(J, fp + POINTER_SIZE , &trial_pc); 1210 if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) { 1211 // Either we couldn't even read at the "fp" or the pc didn't match 1212 // both are sure clues that the fp is bogus. We no search the stack 1213 // for a reasonable number of words trying to find the bogus fp 1214 // and the current pc in adjacent words. The we will be able to 1215 // deduce an approximation of the frame pointer and actually get 1216 // the correct stack pointer. Which we can then unwind for the 1217 // next frame. 1218 int i; 1219 uint64_t check; 1220 uint64_t base = J->curr_fr.sp; 1221 uint64_t prev_fp = 0; 1222 for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) { 1223 err = read_pointer(J, base , &check); 1224 CHECK_FAIL(err); 1225 if (check == fp) { 1226 base += POINTER_SIZE; 1227 err = read_pointer(J, base , &check); 1228 CHECK_FAIL(err); 1229 if (check == pc) { 1230 if (debug) { 1231 fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE); 1232 } 1233 prev_fp = base - 2 * POINTER_SIZE; 1234 break; 1235 } 1236 } 1237 } 1238 if ( prev_fp != 0 ) { 1239 // real_sp is the sp we should have received for this frame 1240 uint64_t real_sp = prev_fp + 2 * POINTER_SIZE; 1241 // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word 1242 jframe->new_sp = real_sp + frame_size + POINTER_SIZE; 1243 err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc); 1244 CHECK_FAIL(err); 1245 err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp); 1246 CHECK_FAIL(err); 1247 return PS_OK; 1248 } 1249 } 1250 1251 /* A prototype to workaround FP absence */ 1252 /* 1253 * frame_size can be 0 for StubRoutines (1) frame. 1254 * In this case it should work with fp as usual. 1255 */ 1256 if (frame_size > 0) { 1257 jframe->new_fp = J->prev_fr.fp + frame_size; 1258 jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE; 1259 } else { 1260 memset(&J->curr_fr, 0, sizeof(Frame_t)); 1261 err = read_pointer(J, fp, &jframe->new_fp); 1262 CHECK_FAIL(err); 1263 1264 err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); 1265 CHECK_FAIL(err); 1266 } 1267 if (debug) { 1268 fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n", 1269 result, frame_size); 1270 fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n", 1271 J->prev_fr.fp, jframe->new_fp); 1272 } 1273 } 1274#endif /* X86_COMPILER2 */ 1275 1276 return PS_OK; 1277 1278 fail: 1279 return err; 1280} 1281 1282int Jget_vframe(jvm_agent_t* J, int vframe_no, 1283 char *name, size_t size, Jframe_t *jframe) 1284{ 1285 Nmethod_t *N = J->N; 1286 Vframe_t *vf; 1287 int32_t err; 1288 1289 if (vframe_no >= N->vf_cnt) { 1290 (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no); 1291 return -1; 1292 } 1293 vf = N->vframes + vframe_no; 1294 name[0] = COMP_METHOD_SIGN; 1295 err = name_for_methodPtr(J, vf->method, name + 1, size); 1296 CHECK_FAIL(err); 1297 1298 jframe->bci = vf->bci; 1299 jframe->line = vf->line; 1300 if (debug) { 1301 fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n", 1302 name, vf->line); 1303 } 1304 return PS_OK; 1305 1306 fail: 1307 if (debug) { 1308 fprintf(stderr, "\t Jget_vframe: FAIL\n"); 1309 } 1310 return err; 1311} 1312 1313#define MAX_SYM_SIZE 256 1314 1315int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, 1316 size_t size, Jframe_t *jframe) { 1317 uintptr_t fp; 1318 uintptr_t pc; 1319 /* arguments given to read_pointer need to be worst case sized */ 1320 uint64_t methodPtr = 0; 1321 uint64_t sender_sp; 1322 uint64_t bcp = 0; 1323 int is_interpreted = 0; 1324 int result = PS_OK; 1325 int err = PS_OK; 1326 1327 if (J == NULL) { 1328 return -1; 1329 } 1330 1331 jframe->vf_cnt = 1; 1332 jframe->new_fp = 0; 1333 jframe->new_pc = 0; 1334 jframe->line = 0; 1335 jframe->bci = 0; 1336 jframe->locinf = 0; 1337 1338 read_volatiles(J); 1339 pc = (uintptr_t) regs[R_PC]; 1340 J->curr_fr.pc = pc; 1341 J->curr_fr.fp = regs[R_FP]; 1342 J->curr_fr.sp = regs[R_SP]; 1343 1344 if (debug) 1345 fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc); 1346 1347#if defined(sparc) || defined(__sparc) 1348 /* The following workaround is for SPARC. CALL instruction occupates 8 bytes. 1349 * In the pcDesc structure return pc offset is recorded for CALL instructions. 1350 * regs[R_PC] contains a CALL instruction pc offset. 1351 */ 1352 pc += 8; 1353 bcp = (uintptr_t) regs[R_L1]; 1354 methodPtr = (uintptr_t) regs[R_L2]; 1355 sender_sp = regs[R_I5]; 1356 if (debug > 2) { 1357 fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n", 1358 regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]); 1359 } 1360#elif defined(i386) || defined(__i386) || defined(__amd64) 1361 1362 fp = (uintptr_t) regs[R_FP]; 1363 if (J->prev_fr.fp == 0) { 1364#ifdef X86_COMPILER2 1365 /* A workaround for top java frames */ 1366 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE); 1367#else 1368 J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE); 1369#endif /* COMPILER2 */ 1370 } 1371 if (debug > 2) { 1372 printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp); 1373 } 1374 1375 if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) { 1376 methodPtr = 0; 1377 } 1378 if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) { 1379 sender_sp = 0; 1380 } 1381 if (read_pointer(J, fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) { 1382 bcp = 0; 1383 } 1384#endif /* i386 */ 1385 1386 J->methodPtr = methodPtr; 1387 J->bcp = bcp; 1388 1389 /* On x86 with C2 JVM: native frame may have wrong regs[R_FP] 1390 * For example: JVM_SuspendThread frame poins to the top interpreted frame. 1391 * If we call is_method(J, methodPtr) before codecache_contains(J, pc) 1392 * then we go over and omit both: nmethod and I2CAdapter frames. 1393 * Note, that regs[R_PC] is always correct if frame defined correctly. 1394 * So it is better to call codecache_contains(J, pc) from the beginning. 1395 */ 1396#ifndef X86_COMPILER2 1397 if (is_method(J, J->methodPtr)) { 1398 result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe); 1399 /* If the methodPtr is a method then this is highly likely to be 1400 an interpreter frame */ 1401 if (result >= 0) { 1402 is_interpreted = 1; 1403 } 1404 } else 1405#endif /* ! X86_COMPILER2 */ 1406 1407 if (codecache_contains(J, pc)) { 1408 result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted); 1409 } 1410#ifdef X86_COMPILER2 1411 else if (is_method(J, J->methodPtr)) { 1412 result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe); 1413 /* If the methodPtr is a method then this is highly likely to be 1414 an interpreter frame */ 1415 if (result >= 0) { 1416 is_interpreted = 1; 1417 } 1418 } 1419#endif /* X86_COMPILER2 */ 1420 else { 1421 if (debug) { 1422 fprintf(stderr, "Jlookup_by_regs: END with -1\n\n"); 1423 } 1424 result = -1; 1425 } 1426 if (!is_interpreted) { 1427 sender_sp = 0; 1428 } 1429 J->curr_fr.sender_sp = sender_sp; 1430 1431#ifdef X86_COMPILER2 1432 if (!J->curr_fr.fp) { 1433 J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP]; 1434 } 1435 if (!jframe->new_pc && jframe->new_fp) { 1436 // This seems dubious 1437 read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); 1438 CHECK_FAIL(err); 1439 if (debug > 2) { 1440 printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n", 1441 jframe->new_fp, jframe->new_pc); 1442 } 1443 } 1444 1445#endif /* X86_COMPILER2 */ 1446 J->prev_fr = J->curr_fr; 1447 1448 if (debug) 1449 fprintf(stderr, "Jlookup_by_regs: END\n\n"); 1450 1451 return result; 1452 1453 fail: 1454 return err; 1455} 1456 1457void update_gregs(prgregset_t gregs, Jframe_t jframe) { 1458#ifdef X86_COMPILER2 1459 if (debug > 0) { 1460 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]); 1461 } 1462 /* 1463 * A workaround for java C2 frames with unconventional FP. 1464 * may have to modify regset with new values for FP/PC/SP when needed. 1465 */ 1466 if (jframe.new_sp) { 1467 *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp; 1468 } else { 1469 // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE; 1470 } 1471 1472 if (jframe.new_fp) { 1473 *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp; 1474 } 1475 if (jframe.new_pc) { 1476 *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc; 1477 } 1478 if (debug > 0) { 1479 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]); 1480 } 1481#endif /* X86_COMPILER2 */ 1482} 1483 1484/* 1485 * Iterates over java frames at current location given by 'gregs'. 1486 * 1487 * Returns -1 if no java frames are present or if an error is encountered. 1488 * Returns the result of calling 'func' if the return value is non-zero. 1489 * Returns 0 otherwise. 1490 */ 1491int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) { 1492 char buf[MAX_SYM_SIZE + 1]; 1493 Jframe_t jframe; 1494 int i = 0, res; 1495#ifdef X86_COMPILER2 1496 if (debug > 0) { 1497 fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]); 1498 } 1499#endif /* X86_COMPILER2 */ 1500 1501 memset(&jframe, 0, sizeof(Jframe_t)); 1502 memset(buf, 0, sizeof(buf)); 1503 res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe); 1504 if (res != PS_OK) 1505 return (-1); 1506 1507 1508 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, 1509 jframe.line, NULL); 1510 if (res != 0) { 1511 update_gregs(gregs, jframe); 1512 return (res); 1513 } 1514 for (i = 1; i < jframe.vf_cnt; i++) { 1515 Jget_vframe(J, i, buf, sizeof(buf), &jframe); 1516 res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, 1517 jframe.line, NULL); 1518 if (res != 0) { 1519 update_gregs(gregs, jframe); 1520 return (res); 1521 } 1522 } 1523 update_gregs(gregs, jframe); 1524 return (0); 1525} 1526