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