--- old/src/java.base/solaris/native/libjvm_db/libjvm_db.c 2020-05-20 18:10:25.750088494 -0700 +++ /dev/null 2020-03-09 18:57:19.455001459 -0700 @@ -1,1566 +0,0 @@ -/* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include -#include -#include -#include -#include - -#include "libjvm_db.h" -#include "JvmOffsets.h" - -#define LIBJVM_SO "libjvm.so" - -#if defined(i386) || defined(__i386) || defined(__amd64) -#ifdef COMPILER2 -#define X86_COMPILER2 -#endif /* COMPILER2 */ -#endif /* i386 */ - -typedef struct { - short vf_cnt; /* number of recognized java vframes */ - short bci; /* current frame method byte code index */ - int line; /* current frame method source line */ - uint64_t new_fp; /* fp for the next frame */ - uint64_t new_pc; /* pc for the next frame */ - uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */ - char locinf; /* indicates there is valid location info */ -} Jframe_t; - -int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, - size_t size, Jframe_t *jframe); - -int main(int arg) { return arg; } - -static int debug = 0; - -static void failed(int err, const char * file, int line) { - if (debug) { - fprintf(stderr, "failed %d at %s:%d\n", err, file, line); - } -} - -static void warn(const char * file, int line, const char * msg) { - if (debug) { - fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line); - } -} - -static void warn1(const char * file, int line, const char * msg, intptr_t arg1) { - if (debug) { - fprintf(stderr, "warning: "); - fprintf(stderr, msg, arg1); - fprintf(stderr, " at %s:%d\n", file, line); - } -} - -#define CHECK_FAIL(err) \ - if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; } -#define WARN(msg) warn(__FILE__, __LINE__, msg) -#define WARN1(msg, arg1) warn1(__FILE__, __LINE__, msg, arg1) - -typedef struct VMStructEntry { - const char * typeName; /* The type name containing the given field (example: "Klass") */ - const char * fieldName; /* The field name within the type (example: "_name") */ - uint64_t address; /* Address of field; only used for static fields */ - /* ("offset" can not be reused because of apparent solstudio compiler bug */ - /* in generation of initializer data) */ -} VMStructEntry; - -/* Prototyping inlined methods */ - -int sprintf(char *s, const char *format, ...); - -#define SZ16 sizeof(int16_t) -#define SZ32 sizeof(int32_t) - -#define COMP_METHOD_SIGN '*' - -#define MAX_VFRAMES_CNT 256 - -typedef struct vframe { - uint64_t method; - int32_t sender_decode_offset; - int32_t methodIdx; - int32_t bci; - int32_t line; -} Vframe_t; - -typedef struct frame { - uintptr_t fp; - uintptr_t pc; - uintptr_t sp; - uintptr_t sender_sp; // The unextended sp of the caller -} Frame_t; - -typedef struct Nmethod_t { - struct jvm_agent* J; - Jframe_t *jframe; - - uint64_t nm; /* _nmethod */ - uint64_t pc; - uint64_t pc_desc; - - int32_t orig_pc_offset; /* _orig_pc_offset */ - uint64_t instrs_beg; /* _code_offset */ - uint64_t instrs_end; - uint64_t deopt_beg; /* _deoptimize_offset */ - uint64_t scopes_data_beg; /* _scopes_data_begin */ - int32_t scopes_data_end; - int32_t metadata_beg; /* _metadata_offset */ - int32_t metadata_end; - int32_t scopes_pcs_beg; /* _scopes_pcs_offset */ - int32_t scopes_pcs_end; - - int vf_cnt; - Vframe_t vframes[MAX_VFRAMES_CNT]; -} Nmethod_t; - -struct jvm_agent { - struct ps_prochandle* P; - - uint64_t nmethod_vtbl; - uint64_t CodeBlob_vtbl; - uint64_t BufferBlob_vtbl; - uint64_t RuntimeStub_vtbl; - uint64_t Method_vtbl; - - uint64_t Use_Compressed_Oops_address; - uint64_t Universe_narrow_oop_base_address; - uint64_t Universe_narrow_oop_shift_address; - uint64_t CodeCache_heaps_address; - - /* Volatiles */ - uint8_t Use_Compressed_Oops; - uint64_t Universe_narrow_oop_base; - uint32_t Universe_narrow_oop_shift; - // Code cache heaps - int32_t Number_of_heaps; - uint64_t* Heap_low; - uint64_t* Heap_high; - uint64_t* Heap_segmap_low; - uint64_t* Heap_segmap_high; - - int32_t SIZE_CodeCache_log2_segment; - - uint64_t methodPtr; - uint64_t bcp; - - Nmethod_t *N; /*Inlined methods support */ - Frame_t prev_fr; - Frame_t curr_fr; -}; - -static int -read_string(struct ps_prochandle *P, - char *buf, /* caller's buffer */ - size_t size, /* upper limit on bytes to read */ - uintptr_t addr) /* address in process */ -{ - int err = PS_OK; - while (size-- > 1 && err == PS_OK) { - err = ps_pread(P, addr, buf, 1); - if (*buf == '\0') { - return PS_OK; - } - addr += 1; - buf += 1; - } - return -1; -} - -static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) { - int err = -1; - uint32_t ptr32; - err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); - *ptr = ptr32; - return err; -} - -static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) { - int err = -1; - uint32_t ptr32; - - switch (DATA_MODEL) { - case PR_MODEL_LP64: - err = ps_pread(J->P, base, ptr, sizeof(uint64_t)); - break; - case PR_MODEL_ILP32: - err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t)); - *ptr = ptr32; - break; - } - - return err; -} - -static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) { - uint64_t ptr; - int err; - char buffer[1024]; - - *stringp = NULL; - err = read_pointer(J, base, &ptr); - CHECK_FAIL(err); - if (ptr != 0) { - err = read_string(J->P, buffer, sizeof(buffer), ptr); - CHECK_FAIL(err); - *stringp = strdup(buffer); - } - return PS_OK; - - fail: - return err; -} - -static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) { - uint64_t ptr; - int err; - - err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName); - CHECK_FAIL(err); - err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName); - CHECK_FAIL(err); - err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address); - CHECK_FAIL(err); - - return PS_OK; - - fail: - if (vmp->typeName != NULL) free((void*)vmp->typeName); - if (vmp->fieldName != NULL) free((void*)vmp->fieldName); - return err; -} - -static int parse_vmstructs(jvm_agent_t* J) { - VMStructEntry vmVar; - VMStructEntry* vmp = &vmVar; - uint64_t gHotSpotVMStructs; - psaddr_t sym_addr; - uint64_t base; - int err; - - /* Clear *vmp now in case we jump to fail: */ - memset(vmp, 0, sizeof(VMStructEntry)); - - err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr); - CHECK_FAIL(err); - err = read_pointer(J, sym_addr, &gHotSpotVMStructs); - CHECK_FAIL(err); - base = gHotSpotVMStructs; - - err = PS_OK; - while (err == PS_OK) { - memset(vmp, 0, sizeof(VMStructEntry)); - err = parse_vmstruct_entry(J, base, vmp); - if (err != PS_OK || vmp->typeName == NULL) { - break; - } - - if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { - /* Read _heaps field of type GrowableArray* */ - if (strcmp("_heaps", vmp->fieldName) == 0) { - err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address); - } - } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { - if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { - J->Universe_narrow_oop_base_address = vmp->address; - } - if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { - J->Universe_narrow_oop_shift_address = vmp->address; - } - } - CHECK_FAIL(err); - - base += SIZE_VMStructEntry; - if (vmp->typeName != NULL) free((void*)vmp->typeName); - if (vmp->fieldName != NULL) free((void*)vmp->fieldName); - } - - return PS_OK; - - fail: - if (vmp->typeName != NULL) free((void*)vmp->typeName); - if (vmp->fieldName != NULL) free((void*)vmp->fieldName); - return -1; -} - -static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { - psaddr_t sym_addr; - int err; - - err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); - if (err != PS_OK) goto fail; - *valuep = sym_addr; - return PS_OK; - - fail: - return err; -} - -static int read_volatiles(jvm_agent_t* J) { - int i; - uint64_t array_data; - uint64_t code_heap_address; - int err; - - err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); - if (err == PS_OK) { - err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); - CHECK_FAIL(err); - } else { - J->Use_Compressed_Oops = 0; - } - - err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); - CHECK_FAIL(err); - err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); - CHECK_FAIL(err); - - /* CodeCache_heaps_address points to GrowableArray, read _data field - pointing to the first entry of type CodeCache* in the array */ - err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data); - /* Read _len field containing the number of code heaps */ - err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len, - &J->Number_of_heaps, sizeof(J->Number_of_heaps)); - - /* Allocate memory for heap configurations */ - J->Heap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); - J->Heap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); - J->Heap_segmap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); - J->Heap_segmap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); - - /* Read code heap configurations */ - for (i = 0; i < J->Number_of_heaps; ++i) { - /* Read address of heap */ - err = read_pointer(J, array_data, &code_heap_address); - CHECK_FAIL(err); - - err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + - OFFSET_VirtualSpace_low, &J->Heap_low[i]); - CHECK_FAIL(err); - err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + - OFFSET_VirtualSpace_high, &J->Heap_high[i]); - CHECK_FAIL(err); - err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + - OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]); - CHECK_FAIL(err); - err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + - OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]); - CHECK_FAIL(err); - - /* Increment pointer to next entry */ - array_data = array_data + POINTER_SIZE; - } - - err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size, - &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); - CHECK_FAIL(err); - - return PS_OK; - - fail: - return err; -} - -static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) { - return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]); -} - -static int codecache_contains(jvm_agent_t* J, uint64_t ptr) { - int i; - for (i = 0; i < J->Number_of_heaps; ++i) { - if (codeheap_contains(i, J, ptr)) { - return 1; - } - } - return 0; -} - -static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) { - return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment; -} - -static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) { - return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment); -} - -static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) { - int err; - int i; - - for (i = 0; i < J->Number_of_heaps; ++i) { - *startp = 0; - if (codeheap_contains(i, J, ptr)) { - int32_t used; - uint64_t segment = segment_for(i, J, ptr); - uint64_t block = J->Heap_segmap_low[i]; - uint8_t tag; - err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); - CHECK_FAIL(err); - if (tag == 0xff) - return PS_OK; - while (tag > 0) { - err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); - CHECK_FAIL(err); - segment -= tag; - } - block = block_at(i, J, segment); - err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used)); - CHECK_FAIL(err); - if (used) { - *startp = block + SIZE_HeapBlockHeader; - } - } - return PS_OK; - } - - fail: - return -1; -} - -static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) { - psaddr_t sym_addr; - int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); - if (err == PS_OK) { - err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t)); - return err; - } - *valuep = -1; - return -1; -} - -jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) { - jvm_agent_t* J; - int err; - - if (vers != JVM_DB_VERSION) { - errno = ENOTSUP; - return NULL; - } - - J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1); - - debug = getenv("LIBJVMDB_DEBUG") != NULL; - if (debug) debug = 3; - - if (debug) { - fprintf(stderr, "Jagent_create: debug=%d\n", debug); -#ifdef X86_COMPILER2 - fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE); -#endif /* X86_COMPILER2 */ - } - - J->P = P; - - // Initialize the initial previous frame - - J->prev_fr.fp = 0; - J->prev_fr.pc = 0; - J->prev_fr.sp = 0; - J->prev_fr.sender_sp = 0; - - err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl); - CHECK_FAIL(err); - err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl); - if (err != PS_OK) J->BufferBlob_vtbl = 0; - err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl); - CHECK_FAIL(err); - err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl); - CHECK_FAIL(err); - err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl); - CHECK_FAIL(err); - - err = parse_vmstructs(J); - CHECK_FAIL(err); - err = read_volatiles(J); - CHECK_FAIL(err); - - return J; - - fail: - Jagent_destroy(J); - return NULL; -} - -void Jagent_destroy(jvm_agent_t *J) { - if (J != NULL) { - free(J); - } -} - -static int is_method(jvm_agent_t* J, uint64_t methodPtr) { - uint64_t klass; - int err = read_pointer(J, methodPtr, &klass); - if (err != PS_OK) goto fail; - return klass == J->Method_vtbl; - - fail: - return 0; -} - -static int -name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size) -{ - short nameIndex; - short signatureIndex; - uint64_t constantPool; - uint64_t constMethod; - uint64_t nameSymbol; - uint64_t signatureSymbol; - uint64_t klassPtr; - uint64_t klassSymbol; - short klassSymbolLength; - short nameSymbolLength; - short signatureSymbolLength; - char * nameString = NULL; - char * klassString = NULL; - char * signatureString = NULL; - int err; - - err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod); - CHECK_FAIL(err); - err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool); - CHECK_FAIL(err); - - /* To get name string */ - err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2); - CHECK_FAIL(err); - err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol); - CHECK_FAIL(err); - // The symbol is a CPSlot and has lower bit set to indicate metadata - nameSymbol &= (~1); // remove metadata lsb - err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); - CHECK_FAIL(err); - nameString = (char*)calloc(nameSymbolLength + 1, 1); - err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); - CHECK_FAIL(err); - - /* To get signature string */ - err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2); - CHECK_FAIL(err); - err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol); - CHECK_FAIL(err); - signatureSymbol &= (~1); // remove metadata lsb - err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); - CHECK_FAIL(err); - signatureString = (char*)calloc(signatureSymbolLength + 1, 1); - err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); - CHECK_FAIL(err); - - /* To get klass string */ - err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr); - CHECK_FAIL(err); - err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol); - CHECK_FAIL(err); - err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); - CHECK_FAIL(err); - klassString = (char*)calloc(klassSymbolLength + 1, 1); - err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); - CHECK_FAIL(err); - - result[0] = '\0'; - if (snprintf(result, size, - "%s.%s%s", - klassString, - nameString, - signatureString) >= size) { - // truncation - goto fail; - } - - if (nameString != NULL) free(nameString); - if (klassString != NULL) free(klassString); - if (signatureString != NULL) free(signatureString); - - return PS_OK; - - fail: - if (debug) { - fprintf(stderr, "name_for_methodPtr: FAIL \n\n"); - } - if (nameString != NULL) free(nameString); - if (klassString != NULL) free(klassString); - if (signatureString != NULL) free(signatureString); - return -1; -} - -static int nmethod_info(Nmethod_t *N) -{ - jvm_agent_t *J = N->J; - uint64_t nm = N->nm; - int32_t err; - - if (debug > 2 ) - fprintf(stderr, "\t nmethod_info: BEGIN \n"); - - /* Instructions */ - err = read_pointer(J, nm + OFFSET_CodeBlob_code_begin, &N->instrs_beg); - CHECK_FAIL(err); - err = read_pointer(J, nm + OFFSET_CodeBlob_code_end, &N->instrs_end); - CHECK_FAIL(err); - err = read_pointer(J, nm + OFFSET_nmethod_deopt_handler_begin, &N->deopt_beg); - CHECK_FAIL(err); - err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); - CHECK_FAIL(err); - - /* Metadata */ - err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32); - CHECK_FAIL(err); - err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->metadata_end, SZ32); - CHECK_FAIL(err); - - /* scopes_pcs */ - err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); - CHECK_FAIL(err); - err = ps_pread(J->P, nm + OFFSET_nmethod_dependencies_offset, &N->scopes_pcs_end, SZ32); - CHECK_FAIL(err); - - /* scopes_data */ - err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->scopes_data_beg, POINTER_SIZE); - CHECK_FAIL(err); - - if (debug > 2 ) { - N->scopes_data_end = N->scopes_pcs_beg; - - fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n", - N->instrs_beg, N->instrs_end); - - fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n", - N->deopt_beg); - - fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", - N->orig_pc_offset); - - fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n", - N->metadata_beg, N->metadata_end); - - fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", - N->scopes_data_beg, N->scopes_data_end); - - fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", - N->scopes_pcs_beg, N->scopes_pcs_end); - - fprintf(stderr, "\t nmethod_info: END \n\n"); - } - return PS_OK; - - fail: - return err; -} - -static int -raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val) -{ - int shift = 0; - int value = 0; - uint8_t ch = 0; - int32_t err; - int32_t sum; - // Constants for UNSIGNED5 coding of Pack200 - // see compressedStream.hpp - enum { - lg_H = 6, - H = 1<P, (*buffer)++, &ch, sizeof(uint8_t)); - CHECK_FAIL(err); - if (debug > 2) - fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch); - - sum = ch; - if ( sum >= L ) { - int32_t lg_H_i = lg_H; - // Read maximum of 5 total bytes (we've already read 1). - // See CompressedReadStream::read_int_mb - for ( i = 0; i < 4; i++) { - err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t)); - CHECK_FAIL(err); - sum += ch << lg_H_i; - if (ch < L ) { - *val = sum; - return PS_OK; - } - lg_H_i += lg_H; - } - } - *val = sum; - return PS_OK; - - fail: - return err; -} - -static int -read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line) -{ - uint8_t next = 0; - int32_t bci_delta; - int32_t line_delta; - int32_t err; - - if (debug > 2) - fprintf(stderr, "\t\t read_pair: BEGIN\n"); - - err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t)); - CHECK_FAIL(err); - - if (next == 0) { - if (debug > 2) - fprintf(stderr, "\t\t read_pair: END: next == 0\n"); - return 1; /* stream terminated */ - } - if (next == 0xFF) { - if (debug > 2) - fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n"); - - /* Escape character, regular compression used */ - - err = raw_read_int(J, buffer, &bci_delta); - CHECK_FAIL(err); - - err = raw_read_int(J, buffer, &line_delta); - CHECK_FAIL(err); - - *bci += bci_delta; - *line += line_delta; - - if (debug > 2) { - fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", - line_delta, bci_delta); - fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", - *line, *bci); - } - } else { - /* Single byte compression used */ - *bci += next >> 3; - *line += next & 0x7; - if (debug > 2) { - fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n", - next & 0x7, next >> 3); - fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n", - *line, *bci); - } - } - if (debug > 2) - fprintf(stderr, "\t\t read_pair: END\n"); - return PS_OK; - - fail: - if (debug) - fprintf(stderr, "\t\t read_pair: FAIL\n"); - return err; -} - -static int -line_number_from_bci(jvm_agent_t* J, Vframe_t *vf) -{ - uint64_t buffer; - uint16_t code_size; - uint64_t code_end_delta; - uint64_t constMethod; - int8_t access_flags; - int32_t best_bci = 0; - int32_t stream_bci = 0; - int32_t stream_line = 0; - int32_t err; - - if (debug > 2) { - char name[256]; - err = name_for_methodPtr(J, vf->method, name, 256); - CHECK_FAIL(err); - fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n", - name, vf->bci); - } - - err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod); - CHECK_FAIL(err); - - vf->line = 0; - err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t)); - CHECK_FAIL(err); - - if (!(access_flags & ConstMethod_has_linenumber_table)) { - if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n"); - return PS_OK; - } - - /* The line numbers are a short array of 2-tuples [start_pc, line_number]. - * Not necessarily sorted and not necessarily one-to-one. - */ - - err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16); - CHECK_FAIL(err); - - /* inlined_table_start() */ - code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0; - buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta; - - if (debug > 2) { - fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n", - vf->method, (access_flags & AccessFlags_NATIVE)); - fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n", - buffer, (int) code_size); - } - - while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) { - if (stream_bci == vf->bci) { - /* perfect match */ - if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: exact line: %d \n\n", vf->line); - vf->line = stream_line; - return PS_OK; - } else { - /* update best_bci/line */ - if (stream_bci < vf->bci && stream_bci >= best_bci) { - best_bci = stream_bci; - vf->line = stream_line; - if (debug > 2) { - fprintf(stderr, "\t line_number_from_bci: best_bci: %d, best_line: %d\n", - best_bci, vf->line); - } - } - } - } - if (debug > 2) - fprintf(stderr, "\t line_number_from_bci: END: line: %d \n\n", vf->line); - return PS_OK; - - fail: - if (debug) - fprintf(stderr, "\t line_number_from_bci: FAIL\n"); - return err; -} - -static int -get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc) -{ - int32_t pc_offset; - int32_t err; - - err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32); - CHECK_FAIL(err); - - *real_pc = N->instrs_beg + pc_offset; - if (debug > 2) { - fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n", - pc_offset, *real_pc); - } - return PS_OK; - - fail: - return err; -} - -/* Finds a PcDesc with real-pc equal to N->pc */ -static int pc_desc_at(Nmethod_t *N) -{ - uint64_t pc_diff = 999; - int32_t offs; - int32_t err; - - if (debug > 2) - fprintf(stderr, "\t pc_desc_at: BEGIN\n"); - - N->vf_cnt = 0; - N->pc_desc = 0; - - for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) { - uint64_t pd; - uint64_t best_pc_diff = 16; /* some approximation */ - uint64_t real_pc = 0; - - pd = N->nm + offs; - err = get_real_pc(N, pd, &real_pc); - CHECK_FAIL(err); - - pc_diff = real_pc - N->pc; - - /* In general, this fragment should work */ - if (pc_diff == 0) { - N->pc_desc = pd; - if (debug) { - fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd); - } - return PS_OK; - } - /* This fragment is to be able to find out an appropriate - * pc_desc entry even if pc_desc info is inaccurate. - */ - if (best_pc_diff > pc_diff && pc_diff > 0) { - best_pc_diff = pc_diff; - N->pc_desc = pd; - } - } - if (debug) { - fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND"); - if (pc_diff < 20) - fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff); - else - fprintf(stderr, "\n\n"); - } - return PS_OK; - - fail: - return err; -} - -static int -scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf) -{ - uint64_t buffer; - int32_t err; - - if (debug > 2) { - fprintf(stderr, "\t\t scope_desc_at: BEGIN \n"); - } - - buffer = N->scopes_data_beg + decode_offset; - - err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset); - CHECK_FAIL(err); - - err = raw_read_int(N->J, &buffer, &vf->methodIdx); - CHECK_FAIL(err); - - err = raw_read_int(N->J, &buffer, &vf->bci); - CHECK_FAIL(err); - - if (debug > 2) { - fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n", - vf->sender_decode_offset); - fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx); - fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci); - - fprintf(stderr, "\t\t scope_desc_at: END \n\n"); - } - return PS_OK; - - fail: - return err; -} - -static int scopeDesc_chain(Nmethod_t *N) { - int32_t decode_offset = 0; - int32_t err; - - if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: BEGIN\n"); - } - - err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset, - &decode_offset, SZ32); - CHECK_FAIL(err); - - while (decode_offset > 0) { - Vframe_t *vf = &N->vframes[N->vf_cnt]; - - if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset); - } - - err = scope_desc_at(N, decode_offset, vf); - CHECK_FAIL(err); - - if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) { - fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n"); - return -1; - } - err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE, - &vf->method); - CHECK_FAIL(err); - - if (vf->method) { - N->vf_cnt++; - err = line_number_from_bci(N->J, vf); - CHECK_FAIL(err); - if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %d\n", - vf->method, vf->line); - } - } - decode_offset = vf->sender_decode_offset; - } - if (debug > 2) { - fprintf(stderr, "\t scopeDesc_chain: END \n\n"); - } - return PS_OK; - - fail: - if (debug) { - fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n"); - } - return err; -} - - -static int -name_for_nmethod(jvm_agent_t* J, - uint64_t nm, - uint64_t pc, - uint64_t method, - char *result, - size_t size, - Jframe_t *jframe -) { - Nmethod_t *N; - Vframe_t *vf; - int32_t err; - int deoptimized = 0; - - if (debug) { - fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc); - } - if (J->N == NULL) { - J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t)); - } - memset(J->N, 0, sizeof(Nmethod_t)); /* Initial stat: all values are zeros */ - N = J->N; - N->J = J; - N->nm = nm; - N->pc = pc; - N->jframe = jframe; - - err = nmethod_info(N); - CHECK_FAIL(err); - if (debug) { - fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc: %#llx\n", - pc, N->deopt_beg); - } - - /* check for a deoptimized frame */ - if ( pc == N->deopt_beg) { - uint64_t base; - if (debug) { - fprintf(stderr, "name_for_nmethod: found deoptimized frame\n"); - } - if (J->prev_fr.sender_sp != 0) { - base = J->prev_fr.sender_sp + N->orig_pc_offset; - } else { - base = J->curr_fr.sp + N->orig_pc_offset; - } - err = read_pointer(J, base, &N->pc); - CHECK_FAIL(err); - if (debug) { - fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n", - pc, N->pc); - } - deoptimized = 1; - } - - err = pc_desc_at(N); - CHECK_FAIL(err); - - if (N->pc_desc > 0) { - jframe->locinf = 1; - err = scopeDesc_chain(N); - CHECK_FAIL(err); - } - result[0] = COMP_METHOD_SIGN; - vf = &N->vframes[0]; - if (N->vf_cnt > 0) { - jframe->vf_cnt = N->vf_cnt; - jframe->bci = vf->bci; - jframe->line = vf->line; - err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1); - CHECK_FAIL(err); - } else { - err = name_for_methodPtr(J, method, result+1, size-1); - CHECK_FAIL(err); - } - if (deoptimized) { - strncat(result, " [deoptimized frame]; ", size - strlen(result) - 1); - } else { - strncat(result, " [compiled] ", size - strlen(result) - 1); - } - if (debug) - fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n", - result, N->vf_cnt); - return PS_OK; - - fail: - if (debug) - fprintf(stderr, "name_for_nmethod: FAIL \n\n"); - return err; -} - -static int -name_for_imethod(jvm_agent_t* J, - uint64_t bcp, - uint64_t method, - char *result, - size_t size, - Jframe_t *jframe -) { - uint64_t bci; - uint64_t constMethod; - Vframe_t vframe = {0}; - Vframe_t *vf = &vframe; - int32_t err; - - err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod); - CHECK_FAIL(err); - - bci = bcp - (constMethod + (uint64_t) SIZE_ConstMethod); - - if (debug) - fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method); - - err = name_for_methodPtr(J, method, result, size); - CHECK_FAIL(err); - if (debug) - fprintf(stderr, "\t name_for_imethod: method name: %s\n", result); - - if (bci > 0) { - vf->method = method; - vf->bci = bci; - err = line_number_from_bci(J, vf); - CHECK_FAIL(err); - } - jframe->bci = vf->bci; - jframe->line = vf->line; - jframe->locinf = 1; - - if (debug) { - fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n", - vf->bci, vf->line); - } - return PS_OK; - - fail: - if (debug) - fprintf(stderr, "\t name_for_imethod: FAIL\n"); - return err; -} - -static int -name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result, - size_t size, Jframe_t *jframe, int* is_interpreted) -{ - uint64_t start; - uint64_t vtbl; - int32_t err; - *is_interpreted = 0; - - result[0] = '\0'; - - err = find_start(J, pc, &start); - CHECK_FAIL(err); - - err = read_pointer(J, start, &vtbl); - CHECK_FAIL(err); - - if (vtbl == J->nmethod_vtbl) { - uint64_t method; - - err = read_pointer(J, start + OFFSET_nmethod_method, &method); - CHECK_FAIL(err); - - if (debug) { - fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n", - start, pc, method); - } - err = name_for_nmethod(J, start, pc, method, result, size, jframe); - CHECK_FAIL(err); - } else if (vtbl == J->BufferBlob_vtbl) { - const char * name; - - err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); - - /* - * Temporary usage of string "Interpreter". - * We need some other way to distinguish "StubRoutines" - * and regular interpreted frames. - */ - if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) { - *is_interpreted = 1; - if (is_method(J, J->methodPtr)) { - return name_for_imethod(J, J->bcp, J->methodPtr, result, size, jframe); - } - } - - if (err == PS_OK) { - strncpy(result, name, size); - free((void*)name); - } else { - strncpy(result, "", size); - } - /* return PS_OK; */ - } else { - const char * name; - - err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name); - if (err == PS_OK) { - strncpy(result, name, size); - free((void*)name); - } else { - strncpy(result, "", size); - WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl); - } - } - result[size-1] = '\0'; - -#ifdef X86_COMPILER2 - if (vtbl != J->RuntimeStub_vtbl) { - uint64_t trial_pc; - int frame_size; - err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size, - &frame_size, SZ32); - CHECK_FAIL(err); - - // frame_size is in words, we want bytes. - frame_size *= POINTER_SIZE; /* word => byte conversion */ - - /* - Because c2 doesn't use FP as a framepointer the value of sp/fp we receive - in the initial entry to a set of stack frames containing server frames - will pretty much be nonsense. We can detect that nonsense by looking to - see if the PC we received is correct if we look at the expected storage - location in relation to the FP (ie. POINTER_SIZE(FP) ) - */ - - err = read_pointer(J, fp + POINTER_SIZE , &trial_pc); - if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) { - // Either we couldn't even read at the "fp" or the pc didn't match - // both are sure clues that the fp is bogus. We no search the stack - // for a reasonable number of words trying to find the bogus fp - // and the current pc in adjacent words. The we will be able to - // deduce an approximation of the frame pointer and actually get - // the correct stack pointer. Which we can then unwind for the - // next frame. - int i; - uint64_t check; - uint64_t base = J->curr_fr.sp; - uint64_t prev_fp = 0; - for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) { - err = read_pointer(J, base , &check); - CHECK_FAIL(err); - if (check == fp) { - base += POINTER_SIZE; - err = read_pointer(J, base , &check); - CHECK_FAIL(err); - if (check == pc) { - if (debug) { - fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE); - } - prev_fp = base - 2 * POINTER_SIZE; - break; - } - } - } - if ( prev_fp != 0 ) { - // real_sp is the sp we should have received for this frame - uint64_t real_sp = prev_fp + 2 * POINTER_SIZE; - // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word - jframe->new_sp = real_sp + frame_size + POINTER_SIZE; - err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc); - CHECK_FAIL(err); - err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp); - CHECK_FAIL(err); - return PS_OK; - } - } - - /* A prototype to workaround FP absence */ - /* - * frame_size can be 0 for StubRoutines (1) frame. - * In this case it should work with fp as usual. - */ - if (frame_size > 0) { - jframe->new_fp = J->prev_fr.fp + frame_size; - jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE; - } else { - memset(&J->curr_fr, 0, sizeof(Frame_t)); - err = read_pointer(J, fp, &jframe->new_fp); - CHECK_FAIL(err); - - err = read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); - CHECK_FAIL(err); - } - if (debug) { - fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n", - result, frame_size); - fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n", - J->prev_fr.fp, jframe->new_fp); - } - } -#endif /* X86_COMPILER2 */ - - return PS_OK; - - fail: - return err; -} - -int Jget_vframe(jvm_agent_t* J, int vframe_no, - char *name, size_t size, Jframe_t *jframe) -{ - Nmethod_t *N = J->N; - Vframe_t *vf; - int32_t err; - - if (vframe_no >= N->vf_cnt) { - (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no); - return -1; - } - vf = N->vframes + vframe_no; - name[0] = COMP_METHOD_SIGN; - err = name_for_methodPtr(J, vf->method, name + 1, size); - CHECK_FAIL(err); - - jframe->bci = vf->bci; - jframe->line = vf->line; - if (debug) { - fprintf(stderr, "\t Jget_vframe: method name: %s, line: %d\n", - name, vf->line); - } - return PS_OK; - - fail: - if (debug) { - fprintf(stderr, "\t Jget_vframe: FAIL\n"); - } - return err; -} - -#define MAX_SYM_SIZE 256 - -int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name, - size_t size, Jframe_t *jframe) { - uintptr_t fp; - uintptr_t pc; - /* arguments given to read_pointer need to be worst case sized */ - uint64_t methodPtr = 0; - uint64_t sender_sp; - uint64_t bcp = 0; - int is_interpreted = 0; - int result = PS_OK; - int err = PS_OK; - - if (J == NULL) { - return -1; - } - - jframe->vf_cnt = 1; - jframe->new_fp = 0; - jframe->new_pc = 0; - jframe->line = 0; - jframe->bci = 0; - jframe->locinf = 0; - - read_volatiles(J); - pc = (uintptr_t) regs[R_PC]; - J->curr_fr.pc = pc; - J->curr_fr.fp = regs[R_FP]; - J->curr_fr.sp = regs[R_SP]; - - if (debug) - fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc); - -#if defined(sparc) || defined(__sparc) - /* The following workaround is for SPARC. CALL instruction occupates 8 bytes. - * In the pcDesc structure return pc offset is recorded for CALL instructions. - * regs[R_PC] contains a CALL instruction pc offset. - */ - pc += 8; - bcp = (uintptr_t) regs[R_L1]; - methodPtr = (uintptr_t) regs[R_L2]; - sender_sp = regs[R_I5]; - fp = (uintptr_t) regs[R_FP]; - if (debug > 2) { - fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n", - regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]); - } -#elif defined(i386) || defined(__i386) || defined(__amd64) - - fp = (uintptr_t) regs[R_FP]; - if (J->prev_fr.fp == 0) { -#ifdef X86_COMPILER2 - /* A workaround for top java frames */ - J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE); -#else - J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE); -#endif /* COMPILER2 */ - } - if (debug > 2) { - printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp); - } - - if (read_pointer(J, fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) { - methodPtr = 0; - } - if (read_pointer(J, fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) { - sender_sp = 0; - } - if (read_pointer(J, fp + OFFSET_interpreter_frame_bcp_offset, &bcp) != PS_OK) { - bcp = 0; - } -#endif /* i386 */ - - J->methodPtr = methodPtr; - J->bcp = bcp; - - /* On x86 with C2 JVM: native frame may have wrong regs[R_FP] - * For example: JVM_SuspendThread frame poins to the top interpreted frame. - * If we call is_method(J, methodPtr) before codecache_contains(J, pc) - * then we go over and omit both: nmethod and I2CAdapter frames. - * Note, that regs[R_PC] is always correct if frame defined correctly. - * So it is better to call codecache_contains(J, pc) from the beginning. - */ -#ifndef X86_COMPILER2 - if (is_method(J, J->methodPtr)) { - result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe); - /* If the methodPtr is a method then this is highly likely to be - an interpreter frame */ - if (result >= 0) { - is_interpreted = 1; - } - } else -#endif /* ! X86_COMPILER2 */ - - if (codecache_contains(J, pc)) { - result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted); - } -#ifdef X86_COMPILER2 - else if (is_method(J, J->methodPtr)) { - result = name_for_imethod(J, bcp, J->methodPtr, name, size, jframe); - /* If the methodPtr is a method then this is highly likely to be - an interpreter frame */ - if (result >= 0) { - is_interpreted = 1; - } - } -#endif /* X86_COMPILER2 */ - else { - if (debug) { - fprintf(stderr, "Jlookup_by_regs: END with -1\n\n"); - } - result = -1; - } - if (!is_interpreted) { - sender_sp = 0; - } - J->curr_fr.sender_sp = sender_sp; - -#ifdef X86_COMPILER2 - if (!J->curr_fr.fp) { - J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP]; - } - if (!jframe->new_pc && jframe->new_fp) { - // This seems dubious - read_pointer(J, jframe->new_fp + POINTER_SIZE, &jframe->new_pc); - CHECK_FAIL(err); - if (debug > 2) { - printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n", - jframe->new_fp, jframe->new_pc); - } - } - -#endif /* X86_COMPILER2 */ - J->prev_fr = J->curr_fr; - - if (debug) - fprintf(stderr, "Jlookup_by_regs: END\n\n"); - - return result; - - fail: - return err; -} - -void update_gregs(prgregset_t gregs, Jframe_t jframe) { -#ifdef X86_COMPILER2 - if (debug > 0) { - 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]); - } - /* - * A workaround for java C2 frames with unconventional FP. - * may have to modify regset with new values for FP/PC/SP when needed. - */ - if (jframe.new_sp) { - *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp; - } else { - // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE; - } - - if (jframe.new_fp) { - *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp; - } - if (jframe.new_pc) { - *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc; - } - if (debug > 0) { - 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]); - } -#endif /* X86_COMPILER2 */ -} - -/* - * Iterates over java frames at current location given by 'gregs'. - * - * Returns -1 if no java frames are present or if an error is encountered. - * Returns the result of calling 'func' if the return value is non-zero. - * Returns 0 otherwise. - */ -int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) { - char buf[MAX_SYM_SIZE + 1]; - Jframe_t jframe; - int i = 0, res; -#ifdef X86_COMPILER2 - if (debug > 0) { - fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]); - } -#endif /* X86_COMPILER2 */ - - memset(&jframe, 0, sizeof(Jframe_t)); - memset(buf, 0, sizeof(buf)); - res = Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe); - if (res != PS_OK) - return (-1); - - - res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, - jframe.line, NULL); - if (res != 0) { - update_gregs(gregs, jframe); - return (res); - } - for (i = 1; i < jframe.vf_cnt; i++) { - Jget_vframe(J, i, buf, sizeof(buf), &jframe); - res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1, - jframe.line, NULL); - if (res != 0) { - update_gregs(gregs, jframe); - return (res); - } - } - update_gregs(gregs, jframe); - return (0); -}