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