src/os/solaris/dtrace/libjvm_db.c

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/os/solaris/dtrace/libjvm_db.c	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,1532 @@
     1.4 +/*
     1.5 + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include <stdio.h>
    1.29 +#include <stdlib.h>
    1.30 +#include <string.h>
    1.31 +#include <errno.h>
    1.32 +#include <gelf.h>
    1.33 +
    1.34 +#include "libjvm_db.h"
    1.35 +#include "JvmOffsets.h"
    1.36 +
    1.37 +#define LIBJVM_SO "libjvm.so"
    1.38 +
    1.39 +#if defined(i386) || defined(__i386) || defined(__amd64)
    1.40 +#ifdef COMPILER2
    1.41 +#define X86_COMPILER2
    1.42 +#endif /* COMPILER2 */
    1.43 +#endif /* i386 */
    1.44 +
    1.45 +typedef struct {
    1.46 +    short     vf_cnt; /* number of recognized java vframes */
    1.47 +    short     bci;    /* current frame method byte code index */
    1.48 +    int       line;   /* current frame method source line */
    1.49 +    uint64_t new_fp; /* fp for the next frame */
    1.50 +    uint64_t new_pc; /* pc for the next frame */
    1.51 +    uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
    1.52 +    char      locinf; /* indicates there is valid location info */
    1.53 +} Jframe_t;
    1.54 +
    1.55 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
    1.56 +                    size_t size, Jframe_t *jframe);
    1.57 +
    1.58 +int main(int arg) { return arg; }
    1.59 +
    1.60 +static int debug = 0;
    1.61 +
    1.62 +static void failed(int err, const char * file, int line) {
    1.63 +  if (debug) {
    1.64 +    fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
    1.65 +  }
    1.66 +}
    1.67 +
    1.68 +static void warn(const char * file, int line, const char * msg) {
    1.69 +  if (debug) {
    1.70 +    fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
    1.71 +  }
    1.72 +}
    1.73 +
    1.74 +static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
    1.75 +  if (debug) {
    1.76 +    fprintf(stderr, "warning: ");
    1.77 +    fprintf(stderr, msg, arg1);
    1.78 +    fprintf(stderr, " at %s:%d\n", file, line);
    1.79 +  }
    1.80 +}
    1.81 +
    1.82 +#define CHECK_FAIL(err) \
    1.83 +        if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
    1.84 +#define WARN(msg)  warn(__FILE__, __LINE__, msg)
    1.85 +#define WARN1(msg, arg1)  warn1(__FILE__, __LINE__, msg, arg1)
    1.86 +
    1.87 +typedef struct VMStructEntry {
    1.88 +  const char * typeName;           /* The type name containing the given field (example: "Klass") */
    1.89 +  const char * fieldName;          /* The field name within the type           (example: "_name") */
    1.90 +  uint64_t address;                /* Address of field; only used for static fields */
    1.91 +                                   /* ("offset" can not be reused because of apparent SparcWorks compiler bug */
    1.92 +                                   /* in generation of initializer data) */
    1.93 +} VMStructEntry;
    1.94 +
    1.95 +/* Prototyping inlined methods */
    1.96 +
    1.97 +int sprintf(char *s, const char *format, ...);
    1.98 +
    1.99 +#define SZ16  sizeof(int16_t)
   1.100 +#define SZ32  sizeof(int32_t)
   1.101 +
   1.102 +#define COMP_METHOD_SIGN '*'
   1.103 +
   1.104 +#define MAX_VFRAMES_CNT 256
   1.105 +
   1.106 +typedef struct vframe {
   1.107 +  uint64_t method;
   1.108 +  int32_t  sender_decode_offset;
   1.109 +  int32_t  methodIdx;
   1.110 +  int32_t  bci;
   1.111 +  int32_t  line;
   1.112 +} Vframe_t;
   1.113 +
   1.114 +typedef struct frame {
   1.115 +  uintptr_t fp;
   1.116 +  uintptr_t pc;
   1.117 +  uintptr_t sp;
   1.118 +  uintptr_t sender_sp; // The unextended sp of the caller
   1.119 +} Frame_t;
   1.120 +
   1.121 +typedef struct Nmethod_t {
   1.122 +  struct jvm_agent* J;
   1.123 +  Jframe_t *jframe;
   1.124 +
   1.125 +  uint64_t nm;                  /* _nmethod */
   1.126 +  uint64_t pc;
   1.127 +  uint64_t pc_desc;
   1.128 +
   1.129 +  int32_t  orig_pc_offset;      /* _orig_pc_offset */
   1.130 +  int32_t  instrs_beg;          /* _code_offset */
   1.131 +  int32_t  instrs_end;
   1.132 +  int32_t  deopt_beg;           /* _deoptimize_offset */
   1.133 +  int32_t  scopes_data_beg;     /* _scopes_data_offset */
   1.134 +  int32_t  scopes_data_end;
   1.135 +  int32_t  metadata_beg;        /* _metadata_offset */
   1.136 +  int32_t  metadata_end;
   1.137 +  int32_t  scopes_pcs_beg;      /* _scopes_pcs_offset */
   1.138 +  int32_t  scopes_pcs_end;
   1.139 +
   1.140 +  int      vf_cnt;
   1.141 +  Vframe_t vframes[MAX_VFRAMES_CNT];
   1.142 +} Nmethod_t;
   1.143 +
   1.144 +struct jvm_agent {
   1.145 +  struct ps_prochandle* P;
   1.146 +
   1.147 +  uint64_t nmethod_vtbl;
   1.148 +  uint64_t CodeBlob_vtbl;
   1.149 +  uint64_t BufferBlob_vtbl;
   1.150 +  uint64_t RuntimeStub_vtbl;
   1.151 +  uint64_t Method_vtbl;
   1.152 +
   1.153 +  uint64_t Use_Compressed_Oops_address;
   1.154 +  uint64_t Universe_narrow_oop_base_address;
   1.155 +  uint64_t Universe_narrow_oop_shift_address;
   1.156 +  uint64_t CodeCache_heap_address;
   1.157 +
   1.158 +  /* Volatiles */
   1.159 +  uint8_t  Use_Compressed_Oops;
   1.160 +  uint64_t Universe_narrow_oop_base;
   1.161 +  uint32_t Universe_narrow_oop_shift;
   1.162 +  uint64_t CodeCache_low;
   1.163 +  uint64_t CodeCache_high;
   1.164 +  uint64_t CodeCache_segmap_low;
   1.165 +  uint64_t CodeCache_segmap_high;
   1.166 +
   1.167 +  int32_t  SIZE_CodeCache_log2_segment;
   1.168 +
   1.169 +  uint64_t methodPtr;
   1.170 +  uint64_t bcx;
   1.171 +
   1.172 +  Nmethod_t *N;                 /*Inlined methods support */
   1.173 +  Frame_t   prev_fr;
   1.174 +  Frame_t   curr_fr;
   1.175 +};
   1.176 +
   1.177 +static int
   1.178 +read_string(struct ps_prochandle *P,
   1.179 +        char *buf,              /* caller's buffer */
   1.180 +        size_t size,            /* upper limit on bytes to read */
   1.181 +        uintptr_t addr)         /* address in process */
   1.182 +{
   1.183 +  int err = PS_OK;
   1.184 +  while (size-- > 1 && err == PS_OK) {
   1.185 +    err = ps_pread(P, addr, buf, 1);
   1.186 +    if (*buf == '\0') {
   1.187 +      return PS_OK;
   1.188 +    }
   1.189 +    addr += 1;
   1.190 +    buf += 1;
   1.191 +  }
   1.192 +  return -1;
   1.193 +}
   1.194 +
   1.195 +static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
   1.196 +  int err = -1;
   1.197 +  uint32_t ptr32;
   1.198 +  err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
   1.199 +  *ptr = ptr32;
   1.200 +  return err;
   1.201 +}
   1.202 +
   1.203 +static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
   1.204 +  int err = -1;
   1.205 +  uint32_t ptr32;
   1.206 +
   1.207 +  switch (DATA_MODEL) {
   1.208 +  case PR_MODEL_LP64:
   1.209 +    err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
   1.210 +    break;
   1.211 +  case PR_MODEL_ILP32:
   1.212 +    err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
   1.213 +    *ptr = ptr32;
   1.214 +    break;
   1.215 +  }
   1.216 +
   1.217 +  return err;
   1.218 +}
   1.219 +
   1.220 +static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
   1.221 +  uint64_t ptr;
   1.222 +  int err;
   1.223 +  char buffer[1024];
   1.224 +
   1.225 +  *stringp = NULL;
   1.226 +  err = read_pointer(J, base, &ptr);
   1.227 +  CHECK_FAIL(err);
   1.228 +  if (ptr != 0) {
   1.229 +    err = read_string(J->P, buffer, sizeof(buffer), ptr);
   1.230 +    CHECK_FAIL(err);
   1.231 +    *stringp = strdup(buffer);
   1.232 +  }
   1.233 +  return PS_OK;
   1.234 +
   1.235 + fail:
   1.236 +  return err;
   1.237 +}
   1.238 +
   1.239 +static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
   1.240 +  uint64_t ptr;
   1.241 +  int err;
   1.242 +
   1.243 +  err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
   1.244 +  CHECK_FAIL(err);
   1.245 +  err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
   1.246 +  CHECK_FAIL(err);
   1.247 +  err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
   1.248 +  CHECK_FAIL(err);
   1.249 +
   1.250 +  return PS_OK;
   1.251 +
   1.252 + fail:
   1.253 +  if (vmp->typeName != NULL) free((void*)vmp->typeName);
   1.254 +  if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
   1.255 +  return err;
   1.256 +}
   1.257 +
   1.258 +static int parse_vmstructs(jvm_agent_t* J) {
   1.259 +  VMStructEntry  vmVar;
   1.260 +  VMStructEntry* vmp = &vmVar;
   1.261 +  uint64_t gHotSpotVMStructs;
   1.262 +  psaddr_t sym_addr;
   1.263 +  uint64_t base;
   1.264 +  int err;
   1.265 +
   1.266 +  err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
   1.267 +  CHECK_FAIL(err);
   1.268 +  err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
   1.269 +  CHECK_FAIL(err);
   1.270 +  base = gHotSpotVMStructs;
   1.271 +
   1.272 +  err = PS_OK;
   1.273 +  while (err == PS_OK) {
   1.274 +    memset(vmp, 0, sizeof(VMStructEntry));
   1.275 +    err = parse_vmstruct_entry(J, base, vmp);
   1.276 +    if (err != PS_OK || vmp->typeName == NULL) {
   1.277 +      break;
   1.278 +    }
   1.279 +
   1.280 +    if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
   1.281 +      if (strcmp("_heap", vmp->fieldName) == 0) {
   1.282 +        err = read_pointer(J, vmp->address, &J->CodeCache_heap_address);
   1.283 +      }
   1.284 +    } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
   1.285 +      if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
   1.286 +        J->Universe_narrow_oop_base_address = vmp->address;
   1.287 +      }
   1.288 +      if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
   1.289 +        J->Universe_narrow_oop_shift_address = vmp->address;
   1.290 +      }
   1.291 +    }
   1.292 +    CHECK_FAIL(err);
   1.293 +
   1.294 +    base += SIZE_VMStructEntry;
   1.295 +    if (vmp->typeName != NULL) free((void*)vmp->typeName);
   1.296 +    if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
   1.297 +  }
   1.298 +
   1.299 +  return PS_OK;
   1.300 +
   1.301 + fail:
   1.302 +  if (vmp->typeName != NULL) free((void*)vmp->typeName);
   1.303 +  if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
   1.304 +  return -1;
   1.305 +}
   1.306 +
   1.307 +static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
   1.308 +  psaddr_t sym_addr;
   1.309 +  int err;
   1.310 +
   1.311 +  err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
   1.312 +  if (err != PS_OK) goto fail;
   1.313 +  *valuep = sym_addr;
   1.314 +  return PS_OK;
   1.315 +
   1.316 + fail:
   1.317 +  return err;
   1.318 +}
   1.319 +
   1.320 +static int read_volatiles(jvm_agent_t* J) {
   1.321 +  uint64_t ptr;
   1.322 +  int err;
   1.323 +
   1.324 +  err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
   1.325 +  if (err == PS_OK) {
   1.326 +    err = ps_pread(J->P,  J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
   1.327 +    CHECK_FAIL(err);
   1.328 +  } else {
   1.329 +    J->Use_Compressed_Oops = 0;
   1.330 +  }
   1.331 +
   1.332 +  err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
   1.333 +  CHECK_FAIL(err);
   1.334 +  err = ps_pread(J->P,  J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
   1.335 +  CHECK_FAIL(err);
   1.336 +
   1.337 +  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
   1.338 +                     OFFSET_VirtualSpace_low, &J->CodeCache_low);
   1.339 +  CHECK_FAIL(err);
   1.340 +  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
   1.341 +                     OFFSET_VirtualSpace_high, &J->CodeCache_high);
   1.342 +  CHECK_FAIL(err);
   1.343 +  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
   1.344 +                     OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low);
   1.345 +  CHECK_FAIL(err);
   1.346 +  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
   1.347 +                     OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high);
   1.348 +  CHECK_FAIL(err);
   1.349 +
   1.350 +  err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size,
   1.351 +                 &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
   1.352 +  CHECK_FAIL(err);
   1.353 +
   1.354 +  return PS_OK;
   1.355 +
   1.356 + fail:
   1.357 +  return err;
   1.358 +}
   1.359 +
   1.360 +
   1.361 +static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
   1.362 +  /* make sure the code cache is up to date */
   1.363 +  return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high);
   1.364 +}
   1.365 +
   1.366 +static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
   1.367 +  return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
   1.368 +}
   1.369 +
   1.370 +static uint64_t block_at(jvm_agent_t* J, int i) {
   1.371 +  return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
   1.372 +}
   1.373 +
   1.374 +static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
   1.375 +  int err;
   1.376 +
   1.377 +  *startp = 0;
   1.378 +  if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) {
   1.379 +    int32_t used;
   1.380 +    uint64_t segment = segment_for(J, ptr);
   1.381 +    uint64_t block = J->CodeCache_segmap_low;
   1.382 +    uint8_t tag;
   1.383 +    err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
   1.384 +    CHECK_FAIL(err);
   1.385 +    if (tag == 0xff)
   1.386 +      return PS_OK;
   1.387 +    while (tag > 0) {
   1.388 +      err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
   1.389 +      CHECK_FAIL(err);
   1.390 +      segment -= tag;
   1.391 +    }
   1.392 +    block = block_at(J, segment);
   1.393 +    err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
   1.394 +    CHECK_FAIL(err);
   1.395 +    if (used) {
   1.396 +      *startp = block + SIZE_HeapBlockHeader;
   1.397 +    }
   1.398 +  }
   1.399 +  return PS_OK;
   1.400 +
   1.401 + fail:
   1.402 +  return -1;
   1.403 +}
   1.404 +
   1.405 +static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
   1.406 +  psaddr_t sym_addr;
   1.407 +  int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
   1.408 +  if (err == PS_OK) {
   1.409 +    err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
   1.410 +    return err;
   1.411 +  }
   1.412 +  *valuep = -1;
   1.413 +  return -1;
   1.414 +}
   1.415 +
   1.416 +jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
   1.417 +  jvm_agent_t* J;
   1.418 +  int err;
   1.419 +
   1.420 +  if (vers != JVM_DB_VERSION) {
   1.421 +    errno = ENOTSUP;
   1.422 +    return NULL;
   1.423 +  }
   1.424 +
   1.425 +  J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
   1.426 +
   1.427 +  debug = getenv("LIBJVMDB_DEBUG") != NULL;
   1.428 +  if (debug) debug = 3;
   1.429 +
   1.430 +  if (debug) {
   1.431 +      fprintf(stderr, "Jagent_create: debug=%d\n", debug);
   1.432 +#ifdef X86_COMPILER2
   1.433 +      fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
   1.434 +#endif  /* X86_COMPILER2 */
   1.435 +  }
   1.436 +
   1.437 +  J->P = P;
   1.438 +
   1.439 +  // Initialize the initial previous frame
   1.440 +
   1.441 +  J->prev_fr.fp = 0;
   1.442 +  J->prev_fr.pc = 0;
   1.443 +  J->prev_fr.sp = 0;
   1.444 +  J->prev_fr.sender_sp = 0;
   1.445 +
   1.446 +  err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
   1.447 +  CHECK_FAIL(err);
   1.448 +  err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
   1.449 +  if (err != PS_OK) J->BufferBlob_vtbl = 0;
   1.450 +  err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
   1.451 +  CHECK_FAIL(err);
   1.452 +  err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
   1.453 +  CHECK_FAIL(err);
   1.454 +  err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
   1.455 +  CHECK_FAIL(err);
   1.456 +
   1.457 +  err = parse_vmstructs(J);
   1.458 +  CHECK_FAIL(err);
   1.459 +  err = read_volatiles(J);
   1.460 +  CHECK_FAIL(err);
   1.461 +
   1.462 +  return J;
   1.463 +
   1.464 + fail:
   1.465 +  Jagent_destroy(J);
   1.466 +  return NULL;
   1.467 +}
   1.468 +
   1.469 +void Jagent_destroy(jvm_agent_t *J) {
   1.470 +  if (J != NULL) {
   1.471 +    free(J);
   1.472 +  }
   1.473 +}
   1.474 +
   1.475 +static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
   1.476 +  uint64_t klass;
   1.477 +  int err = read_pointer(J, methodPtr, &klass);
   1.478 +  if (err != PS_OK) goto fail;
   1.479 +  return klass == J->Method_vtbl;
   1.480 +
   1.481 + fail:
   1.482 +  return 0;
   1.483 +}
   1.484 +
   1.485 +static int
   1.486 +name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
   1.487 +{
   1.488 +  short nameIndex;
   1.489 +  short signatureIndex;
   1.490 +  uint64_t constantPool;
   1.491 +  uint64_t constMethod;
   1.492 +  uint64_t nameSymbol;
   1.493 +  uint64_t signatureSymbol;
   1.494 +  uint64_t klassPtr;
   1.495 +  uint64_t klassSymbol;
   1.496 +  short klassSymbolLength;
   1.497 +  short nameSymbolLength;
   1.498 +  short signatureSymbolLength;
   1.499 +  char * nameString = NULL;
   1.500 +  char * klassString = NULL;
   1.501 +  char * signatureString = NULL;
   1.502 +  int err;
   1.503 +
   1.504 +  err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
   1.505 +  CHECK_FAIL(err);
   1.506 +  err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
   1.507 +  CHECK_FAIL(err);
   1.508 +
   1.509 +  /* To get name string */
   1.510 +  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
   1.511 +  CHECK_FAIL(err);
   1.512 +  err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
   1.513 +  CHECK_FAIL(err);
   1.514 +  // The symbol is a CPSlot and has lower bit set to indicate metadata
   1.515 +  nameSymbol &= (~1); // remove metadata lsb
   1.516 +  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
   1.517 +  CHECK_FAIL(err);
   1.518 +  nameString = (char*)calloc(nameSymbolLength + 1, 1);
   1.519 +  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
   1.520 +  CHECK_FAIL(err);
   1.521 +
   1.522 +  /* To get signature string */
   1.523 +  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
   1.524 +  CHECK_FAIL(err);
   1.525 +  err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
   1.526 +  CHECK_FAIL(err);
   1.527 +  signatureSymbol &= (~1);  // remove metadata lsb
   1.528 +  err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
   1.529 +  CHECK_FAIL(err);
   1.530 +  signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
   1.531 +  err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
   1.532 +  CHECK_FAIL(err);
   1.533 +
   1.534 +  /* To get klass string */
   1.535 +  err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
   1.536 +  CHECK_FAIL(err);
   1.537 +  err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
   1.538 +  CHECK_FAIL(err);
   1.539 +  err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
   1.540 +  CHECK_FAIL(err);
   1.541 +  klassString = (char*)calloc(klassSymbolLength + 1, 1);
   1.542 +  err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
   1.543 +  CHECK_FAIL(err);
   1.544 +
   1.545 +  result[0] = '\0';
   1.546 +  strncat(result, klassString, size);
   1.547 +  size -= strlen(klassString);
   1.548 +  strncat(result, ".", size);
   1.549 +  size -= 1;
   1.550 +  strncat(result, nameString, size);
   1.551 +  size -= strlen(nameString);
   1.552 +  strncat(result, signatureString, size);
   1.553 +
   1.554 +  if (nameString != NULL) free(nameString);
   1.555 +  if (klassString != NULL) free(klassString);
   1.556 +  if (signatureString != NULL) free(signatureString);
   1.557 +
   1.558 +  return PS_OK;
   1.559 +
   1.560 + fail:
   1.561 +  if (debug) {
   1.562 +      fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
   1.563 +  }
   1.564 +  if (nameString != NULL) free(nameString);
   1.565 +  if (klassString != NULL) free(klassString);
   1.566 +  if (signatureString != NULL) free(signatureString);
   1.567 +  return -1;
   1.568 +}
   1.569 +
   1.570 +static int nmethod_info(Nmethod_t *N)
   1.571 +{
   1.572 +  jvm_agent_t *J = N->J;
   1.573 +  uint64_t    nm = N->nm;
   1.574 +  int32_t err;
   1.575 +
   1.576 +  if (debug > 2 )
   1.577 +      fprintf(stderr, "\t nmethod_info: BEGIN \n");
   1.578 +
   1.579 +  /* Instructions */
   1.580 +  err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32);
   1.581 +  CHECK_FAIL(err);
   1.582 +  err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
   1.583 +  CHECK_FAIL(err);
   1.584 +  err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
   1.585 +  CHECK_FAIL(err);
   1.586 +  err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
   1.587 +  CHECK_FAIL(err);
   1.588 +
   1.589 +  /* Metadata */
   1.590 +  err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
   1.591 +  CHECK_FAIL(err);
   1.592 +  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32);
   1.593 +  CHECK_FAIL(err);
   1.594 +
   1.595 +  /* scopes_pcs */
   1.596 +  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
   1.597 +  CHECK_FAIL(err);
   1.598 +  err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32);
   1.599 +  CHECK_FAIL(err);
   1.600 +
   1.601 +  /* scopes_data */
   1.602 +  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
   1.603 +  CHECK_FAIL(err);
   1.604 +
   1.605 +  if (debug > 2 ) {
   1.606 +      N->scopes_data_end = N->scopes_pcs_beg;
   1.607 +
   1.608 +      fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
   1.609 +                       N->instrs_beg, N->instrs_end);
   1.610 +
   1.611 +      fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
   1.612 +                       N->deopt_beg);
   1.613 +
   1.614 +      fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
   1.615 +                       N->orig_pc_offset);
   1.616 +
   1.617 +      fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
   1.618 +                       N->metadata_beg, N->metadata_end);
   1.619 +
   1.620 +      fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
   1.621 +                       N->scopes_data_beg, N->scopes_data_end);
   1.622 +
   1.623 +      fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
   1.624 +                       N->scopes_pcs_beg, N->scopes_pcs_end);
   1.625 +
   1.626 +      fprintf(stderr, "\t nmethod_info: END \n\n");
   1.627 +  }
   1.628 +  return PS_OK;
   1.629 +
   1.630 + fail:
   1.631 +  return err;
   1.632 +}
   1.633 +
   1.634 +static int
   1.635 +raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
   1.636 +{
   1.637 +  int shift = 0;
   1.638 +  int value = 0;
   1.639 +  uint8_t ch = 0;
   1.640 +  int32_t  err;
   1.641 +  int32_t sum;
   1.642 +  // Constants for UNSIGNED5 coding of Pack200
   1.643 +  // see compressedStream.hpp
   1.644 +  enum {
   1.645 +    lg_H = 6,
   1.646 +    H = 1<<lg_H,
   1.647 +    BitsPerByte = 8,
   1.648 +    L = (1<<BitsPerByte)-H,
   1.649 +  };
   1.650 +  int i;
   1.651 +
   1.652 +  err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
   1.653 +  CHECK_FAIL(err);
   1.654 +  if (debug > 2)
   1.655 +      fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
   1.656 +
   1.657 +  sum = ch;
   1.658 +  if ( sum >= L ) {
   1.659 +    int32_t lg_H_i = lg_H;
   1.660 +    // Read maximum of 5 total bytes (we've already read 1).
   1.661 +    // See CompressedReadStream::read_int_mb
   1.662 +    for ( i = 0;  i < 4; i++) {
   1.663 +      err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
   1.664 +      CHECK_FAIL(err);
   1.665 +      sum += ch << lg_H_i;
   1.666 +      if (ch < L ) {
   1.667 +        *val = sum;
   1.668 +        return PS_OK;
   1.669 +      }
   1.670 +      lg_H_i += lg_H;
   1.671 +    }
   1.672 +  }
   1.673 +  *val = sum;
   1.674 +  return PS_OK;
   1.675 +
   1.676 + fail:
   1.677 +  return err;
   1.678 +}
   1.679 +
   1.680 +static int
   1.681 +read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
   1.682 +{
   1.683 +  uint8_t next = 0;
   1.684 +  int32_t bci_delta;
   1.685 +  int32_t line_delta;
   1.686 +  int32_t err;
   1.687 +
   1.688 +  if (debug > 2)
   1.689 +      fprintf(stderr, "\t\t read_pair: BEGIN\n");
   1.690 +
   1.691 +  err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
   1.692 +  CHECK_FAIL(err);
   1.693 +
   1.694 +  if (next == 0) {
   1.695 +      if (debug > 2)
   1.696 +          fprintf(stderr, "\t\t read_pair: END: next == 0\n");
   1.697 +      return 1; /* stream terminated */
   1.698 +  }
   1.699 +  if (next == 0xFF) {
   1.700 +      if (debug > 2)
   1.701 +          fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
   1.702 +
   1.703 +      /* Escape character, regular compression used */
   1.704 +
   1.705 +      err = raw_read_int(J, buffer, &bci_delta);
   1.706 +      CHECK_FAIL(err);
   1.707 +
   1.708 +      err = raw_read_int(J, buffer, &line_delta);
   1.709 +      CHECK_FAIL(err);
   1.710 +
   1.711 +      *bci  += bci_delta;
   1.712 +      *line += line_delta;
   1.713 +
   1.714 +      if (debug > 2) {
   1.715 +          fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
   1.716 +                          line_delta, bci_delta);
   1.717 +          fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
   1.718 +                          *line, *bci);
   1.719 +      }
   1.720 +  } else {
   1.721 +      /* Single byte compression used */
   1.722 +      *bci  += next >> 3;
   1.723 +      *line += next & 0x7;
   1.724 +      if (debug > 2) {
   1.725 +          fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
   1.726 +                          next & 0x7, next >> 3);
   1.727 +          fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
   1.728 +                          *line, *bci);
   1.729 +      }
   1.730 +  }
   1.731 +  if (debug > 2)
   1.732 +      fprintf(stderr, "\t\t read_pair: END\n");
   1.733 +  return PS_OK;
   1.734 +
   1.735 + fail:
   1.736 +  if (debug)
   1.737 +      fprintf(stderr, "\t\t read_pair: FAIL\n");
   1.738 +  return err;
   1.739 +}
   1.740 +
   1.741 +static int
   1.742 +line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
   1.743 +{
   1.744 +  uint64_t buffer;
   1.745 +  uint16_t code_size;
   1.746 +  uint64_t code_end_delta;
   1.747 +  uint64_t constMethod;
   1.748 +  int8_t   access_flags;
   1.749 +  int32_t  best_bci    = 0;
   1.750 +  int32_t  stream_bci  = 0;
   1.751 +  int32_t  stream_line = 0;
   1.752 +  int32_t  err;
   1.753 +
   1.754 +  if (debug > 2) {
   1.755 +      char name[256];
   1.756 +      err = name_for_methodPtr(J, vf->method, name, 256);
   1.757 +      CHECK_FAIL(err);
   1.758 +      fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
   1.759 +                       name, vf->bci);
   1.760 +  }
   1.761 +
   1.762 +  err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
   1.763 +  CHECK_FAIL(err);
   1.764 +
   1.765 +  vf->line = 0;
   1.766 +  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
   1.767 +  CHECK_FAIL(err);
   1.768 +
   1.769 +  if (!(access_flags & ConstMethod_has_linenumber_table)) {
   1.770 +      if (debug > 2)
   1.771 +          fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
   1.772 +      return PS_OK;
   1.773 +  }
   1.774 +
   1.775 +  /*  The line numbers are a short array of 2-tuples [start_pc, line_number].
   1.776 +   *  Not necessarily sorted and not necessarily one-to-one.
   1.777 +   */
   1.778 +
   1.779 +  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
   1.780 +  CHECK_FAIL(err);
   1.781 +
   1.782 +  /* inlined_table_start() */
   1.783 +  code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
   1.784 +  buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
   1.785 +
   1.786 +  if (debug > 2) {
   1.787 +      fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
   1.788 +                      vf->method, (access_flags & AccessFlags_NATIVE));
   1.789 +      fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
   1.790 +                      buffer, (int) code_size);
   1.791 +  }
   1.792 +
   1.793 +  while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
   1.794 +      if (stream_bci == vf->bci) {
   1.795 +          /* perfect match */
   1.796 +          if (debug > 2)
   1.797 +              fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
   1.798 +          vf->line = stream_line;
   1.799 +          return PS_OK;
   1.800 +      } else {
   1.801 +          /* update best_bci/line */
   1.802 +          if (stream_bci < vf->bci && stream_bci >= best_bci) {
   1.803 +              best_bci = stream_bci;
   1.804 +              vf->line = stream_line;
   1.805 +              if (debug > 2) {
   1.806 +                  fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
   1.807 +                                   best_bci, vf->line);
   1.808 +              }
   1.809 +          }
   1.810 +      }
   1.811 +  }
   1.812 +  if (debug > 2)
   1.813 +      fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
   1.814 +  return PS_OK;
   1.815 +
   1.816 + fail:
   1.817 +  if (debug)
   1.818 +      fprintf(stderr, "\t line_number_from_bci: FAIL\n");
   1.819 +  return err;
   1.820 +}
   1.821 +
   1.822 +static int
   1.823 +get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
   1.824 +{
   1.825 +  int32_t pc_offset;
   1.826 +  int32_t err;
   1.827 +
   1.828 +  err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
   1.829 +  CHECK_FAIL(err);
   1.830 +
   1.831 +  *real_pc = N->nm + N->instrs_beg + pc_offset;
   1.832 +  if (debug > 2) {
   1.833 +      fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
   1.834 +                       pc_offset, *real_pc);
   1.835 +  }
   1.836 +  return PS_OK;
   1.837 +
   1.838 + fail:
   1.839 +  return err;
   1.840 +}
   1.841 +
   1.842 +/* Finds a PcDesc with real-pc equal to N->pc */
   1.843 +static int pc_desc_at(Nmethod_t *N)
   1.844 +{
   1.845 +  uint64_t pc_diff;
   1.846 +  int32_t offs;
   1.847 +  int32_t err;
   1.848 +
   1.849 +  if (debug > 2)
   1.850 +      fprintf(stderr, "\t pc_desc_at: BEGIN\n");
   1.851 +
   1.852 +  N->vf_cnt  = 0;
   1.853 +  N->pc_desc = 0;
   1.854 +
   1.855 +  for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
   1.856 +      uint64_t pd;
   1.857 +      uint64_t best_pc_diff = 16;       /* some approximation */
   1.858 +      uint64_t real_pc = 0;
   1.859 +
   1.860 +      pd = N->nm + offs;
   1.861 +      err = get_real_pc(N, pd, &real_pc);
   1.862 +      CHECK_FAIL(err);
   1.863 +
   1.864 +      pc_diff = real_pc - N->pc;
   1.865 +
   1.866 +      /* In general, this fragment should work */
   1.867 +      if (pc_diff == 0) {
   1.868 +          N->pc_desc = pd;
   1.869 +          if (debug) {
   1.870 +            fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
   1.871 +          }
   1.872 +          return PS_OK;
   1.873 +      }
   1.874 +      /* This fragment is to be able to find out an appropriate
   1.875 +       * pc_desc entry even if pc_desc info is inaccurate.
   1.876 +       */
   1.877 +      if (best_pc_diff > pc_diff && pc_diff > 0) {
   1.878 +          best_pc_diff = pc_diff;
   1.879 +          N->pc_desc = pd;
   1.880 +      }
   1.881 +  }
   1.882 +  if (debug) {
   1.883 +      fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
   1.884 +      if (pc_diff < 20)
   1.885 +          fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
   1.886 +      else
   1.887 +          fprintf(stderr, "\n\n");
   1.888 +  }
   1.889 +  return PS_OK;
   1.890 +
   1.891 + fail:
   1.892 +  return err;
   1.893 +}
   1.894 +
   1.895 +static int
   1.896 +scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
   1.897 +{
   1.898 +  uint64_t buffer;
   1.899 +  int32_t  err;
   1.900 +
   1.901 +  if (debug > 2) {
   1.902 +      fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
   1.903 +  }
   1.904 +
   1.905 +  buffer = N->nm + N->scopes_data_beg + decode_offset;
   1.906 +
   1.907 +  err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
   1.908 +  CHECK_FAIL(err);
   1.909 +
   1.910 +  err = raw_read_int(N->J, &buffer, &vf->methodIdx);
   1.911 +  CHECK_FAIL(err);
   1.912 +
   1.913 +  err = raw_read_int(N->J, &buffer, &vf->bci);
   1.914 +  CHECK_FAIL(err);
   1.915 +
   1.916 +  if (debug > 2) {
   1.917 +      fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
   1.918 +                      vf->sender_decode_offset);
   1.919 +      fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
   1.920 +      fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
   1.921 +
   1.922 +      fprintf(stderr, "\t\t scope_desc_at: END \n\n");
   1.923 +  }
   1.924 +  return PS_OK;
   1.925 +
   1.926 + fail:
   1.927 +  return err;
   1.928 +}
   1.929 +
   1.930 +static int scopeDesc_chain(Nmethod_t *N) {
   1.931 +  int32_t decode_offset = 0;
   1.932 +  int32_t err;
   1.933 +
   1.934 +  if (debug > 2) {
   1.935 +    fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
   1.936 +  }
   1.937 +
   1.938 +  err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
   1.939 +                 &decode_offset, SZ32);
   1.940 +  CHECK_FAIL(err);
   1.941 +
   1.942 +  while (decode_offset > 0) {
   1.943 +    Vframe_t *vf = &N->vframes[N->vf_cnt];
   1.944 +
   1.945 +    if (debug > 2) {
   1.946 +      fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
   1.947 +    }
   1.948 +
   1.949 +    err = scope_desc_at(N, decode_offset, vf);
   1.950 +    CHECK_FAIL(err);
   1.951 +
   1.952 +    if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
   1.953 +      fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
   1.954 +      return -1;
   1.955 +    }
   1.956 +    err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
   1.957 +                       &vf->method);
   1.958 +    CHECK_FAIL(err);
   1.959 +
   1.960 +    if (vf->method) {
   1.961 +      N->vf_cnt++;
   1.962 +      err = line_number_from_bci(N->J, vf);
   1.963 +      CHECK_FAIL(err);
   1.964 +      if (debug > 2) {
   1.965 +        fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n",
   1.966 +                vf->method, vf->line);
   1.967 +      }
   1.968 +    }
   1.969 +    decode_offset = vf->sender_decode_offset;
   1.970 +  }
   1.971 +  if (debug > 2) {
   1.972 +    fprintf(stderr, "\t scopeDesc_chain: END \n\n");
   1.973 +  }
   1.974 +  return PS_OK;
   1.975 +
   1.976 + fail:
   1.977 +  if (debug) {
   1.978 +    fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
   1.979 +  }
   1.980 +  return err;
   1.981 +}
   1.982 +
   1.983 +
   1.984 +static int
   1.985 +name_for_nmethod(jvm_agent_t* J,
   1.986 +                 uint64_t nm,
   1.987 +                 uint64_t pc,
   1.988 +                 uint64_t method,
   1.989 +                 char *result,
   1.990 +                 size_t size,
   1.991 +                 Jframe_t *jframe
   1.992 +) {
   1.993 +  Nmethod_t *N;
   1.994 +  Vframe_t *vf;
   1.995 +  int32_t err;
   1.996 +  int deoptimized = 0;
   1.997 +
   1.998 +  if (debug) {
   1.999 +      fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
  1.1000 +  }
  1.1001 +  if (J->N == NULL) {
  1.1002 +    J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
  1.1003 +  }
  1.1004 +  memset(J->N, 0, sizeof(Nmethod_t));   /* Initial stat: all values are zeros */
  1.1005 +  N     = J->N;
  1.1006 +  N->J  = J;
  1.1007 +  N->nm = nm;
  1.1008 +  N->pc = pc;
  1.1009 +  N->jframe = jframe;
  1.1010 +
  1.1011 +  err = nmethod_info(N);
  1.1012 +  CHECK_FAIL(err);
  1.1013 +  if (debug) {
  1.1014 +      fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc:  %#llx\n",
  1.1015 +              pc, N->nm + N->deopt_beg);
  1.1016 +  }
  1.1017 +
  1.1018 +  /* check for a deoptimized frame */
  1.1019 +  if ( pc == N->nm + N->deopt_beg) {
  1.1020 +    uint64_t base;
  1.1021 +    if (debug) {
  1.1022 +        fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
  1.1023 +    }
  1.1024 +    if (J->prev_fr.sender_sp != 0) {
  1.1025 +      base = J->prev_fr.sender_sp + N->orig_pc_offset;
  1.1026 +    } else {
  1.1027 +      base = J->curr_fr.sp + N->orig_pc_offset;
  1.1028 +    }
  1.1029 +    err = read_pointer(J, base, &N->pc);
  1.1030 +    CHECK_FAIL(err);
  1.1031 +    if (debug) {
  1.1032 +        fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
  1.1033 +        pc,  N->pc);
  1.1034 +    }
  1.1035 +    deoptimized = 1;
  1.1036 +  }
  1.1037 +
  1.1038 +  err = pc_desc_at(N);
  1.1039 +  CHECK_FAIL(err);
  1.1040 +
  1.1041 +  if (N->pc_desc > 0) {
  1.1042 +      jframe->locinf = 1;
  1.1043 +      err = scopeDesc_chain(N);
  1.1044 +      CHECK_FAIL(err);
  1.1045 +  }
  1.1046 +  result[0] = COMP_METHOD_SIGN;
  1.1047 +  vf = &N->vframes[0];
  1.1048 +  if (N->vf_cnt > 0) {
  1.1049 +      jframe->vf_cnt = N->vf_cnt;
  1.1050 +      jframe->bci  = vf->bci;
  1.1051 +      jframe->line = vf->line;
  1.1052 +      err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
  1.1053 +      CHECK_FAIL(err);
  1.1054 +  } else {
  1.1055 +      err = name_for_methodPtr(J, method, result+1, size-1);
  1.1056 +      CHECK_FAIL(err);
  1.1057 +  }
  1.1058 +  if (deoptimized) {
  1.1059 +    strncat(result + 1, " [deoptimized frame]; ", size-1);
  1.1060 +  } else {
  1.1061 +    strncat(result + 1, " [compiled] ", size-1);
  1.1062 +  }
  1.1063 +  if (debug)
  1.1064 +      fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
  1.1065 +                      result, N->vf_cnt);
  1.1066 +  return PS_OK;
  1.1067 +
  1.1068 + fail:
  1.1069 +  if (debug)
  1.1070 +      fprintf(stderr, "name_for_nmethod: FAIL \n\n");
  1.1071 +  return err;
  1.1072 +}
  1.1073 +
  1.1074 +int is_bci(intptr_t bcx) {
  1.1075 +  switch (DATA_MODEL) {
  1.1076 +  case PR_MODEL_LP64:
  1.1077 +    return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
  1.1078 +  case PR_MODEL_ILP32:
  1.1079 +  default:
  1.1080 +    return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
  1.1081 +  }
  1.1082 +}
  1.1083 +
  1.1084 +static int
  1.1085 +name_for_imethod(jvm_agent_t* J,
  1.1086 +                 uint64_t bcx,
  1.1087 +                 uint64_t method,
  1.1088 +                 char *result,
  1.1089 +                 size_t size,
  1.1090 +                 Jframe_t *jframe
  1.1091 +) {
  1.1092 +  uint64_t bci;
  1.1093 +  uint64_t constMethod;
  1.1094 +  Vframe_t vframe = {0};
  1.1095 +  Vframe_t *vf = &vframe;
  1.1096 +  int32_t   err;
  1.1097 +
  1.1098 +  err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
  1.1099 +  CHECK_FAIL(err);
  1.1100 +
  1.1101 +  bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_ConstMethod);
  1.1102 +
  1.1103 +  if (debug)
  1.1104 +      fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
  1.1105 +
  1.1106 +  err = name_for_methodPtr(J, method, result, size);
  1.1107 +  CHECK_FAIL(err);
  1.1108 +  if (debug)
  1.1109 +      fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
  1.1110 +
  1.1111 +  if (bci > 0) {
  1.1112 +      vf->method = method;
  1.1113 +      vf->bci       = bci;
  1.1114 +      err = line_number_from_bci(J, vf);
  1.1115 +      CHECK_FAIL(err);
  1.1116 +  }
  1.1117 +  jframe->bci  = vf->bci;
  1.1118 +  jframe->line = vf->line;
  1.1119 +  jframe->locinf = 1;
  1.1120 +
  1.1121 +  if (debug) {
  1.1122 +      fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
  1.1123 +                      vf->bci, vf->line);
  1.1124 +  }
  1.1125 +  return PS_OK;
  1.1126 +
  1.1127 + fail:
  1.1128 +  if (debug)
  1.1129 +      fprintf(stderr, "\t name_for_imethod: FAIL\n");
  1.1130 +  return err;
  1.1131 +}
  1.1132 +
  1.1133 +static int
  1.1134 +name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
  1.1135 +                   size_t size, Jframe_t *jframe, int* is_interpreted)
  1.1136 +{
  1.1137 +  uint64_t start;
  1.1138 +  uint64_t vtbl;
  1.1139 +  int32_t err;
  1.1140 +  *is_interpreted = 0;
  1.1141 +
  1.1142 +  result[0] = '\0';
  1.1143 +
  1.1144 +  err = find_start(J, pc, &start);
  1.1145 +  CHECK_FAIL(err);
  1.1146 +
  1.1147 +  err = read_pointer(J, start, &vtbl);
  1.1148 +  CHECK_FAIL(err);
  1.1149 +
  1.1150 +  if (vtbl == J->nmethod_vtbl) {
  1.1151 +    uint64_t method;
  1.1152 +
  1.1153 +    err = read_pointer(J, start + OFFSET_nmethod_method, &method);
  1.1154 +    CHECK_FAIL(err);
  1.1155 +
  1.1156 +    if (debug) {
  1.1157 +        fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
  1.1158 +                        start, pc, method);
  1.1159 +    }
  1.1160 +    err = name_for_nmethod(J, start, pc, method, result, size, jframe);
  1.1161 +    CHECK_FAIL(err);
  1.1162 +  } else if (vtbl == J->BufferBlob_vtbl) {
  1.1163 +    const char * name;
  1.1164 +
  1.1165 +    err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  1.1166 +
  1.1167 +    /*
  1.1168 +     * Temporary usage of string "Interpreter".
  1.1169 +     * We need some other way to distinguish "StubRoutines"
  1.1170 +     * and regular interpreted frames.
  1.1171 +     */
  1.1172 +    if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
  1.1173 +      *is_interpreted = 1;
  1.1174 +      if (is_method(J, J->methodPtr)) {
  1.1175 +        return name_for_imethod(J, J->bcx, J->methodPtr, result, size, jframe);
  1.1176 +      }
  1.1177 +    }
  1.1178 +
  1.1179 +    if (err == PS_OK) {
  1.1180 +      strncpy(result, name, size);
  1.1181 +      free((void*)name);
  1.1182 +    } else {
  1.1183 +      strncpy(result, "<unknown BufferBlob>", size);
  1.1184 +    }
  1.1185 +    /* return PS_OK; */
  1.1186 +  } else {
  1.1187 +    const char * name;
  1.1188 +
  1.1189 +    err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  1.1190 +    if (err == PS_OK) {
  1.1191 +      strncpy(result, name, size);
  1.1192 +      free((void*)name);
  1.1193 +    } else {
  1.1194 +      strncpy(result, "<unknown CodeBlob>", size);
  1.1195 +      WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
  1.1196 +    }
  1.1197 +  }
  1.1198 +  result[size-1] = '\0';
  1.1199 +
  1.1200 +#ifdef X86_COMPILER2
  1.1201 +  if (vtbl != J->RuntimeStub_vtbl) {
  1.1202 +    uint64_t trial_pc;
  1.1203 +    int frame_size;
  1.1204 +    err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
  1.1205 +                         &frame_size, SZ32);
  1.1206 +    CHECK_FAIL(err);
  1.1207 +
  1.1208 +    // frame_size is in words, we want bytes.
  1.1209 +    frame_size *= POINTER_SIZE; /* word => byte conversion */
  1.1210 +
  1.1211 +    /*
  1.1212 +      Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
  1.1213 +      in the initial entry to a set of stack frames containing server frames
  1.1214 +      will pretty much be nonsense. We can detect that nonsense by looking to
  1.1215 +      see if the PC we received is correct if we look at the expected storage
  1.1216 +      location in relation to the FP (ie. POINTER_SIZE(FP) )
  1.1217 +    */
  1.1218 +
  1.1219 +    err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
  1.1220 +    if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
  1.1221 +      // Either we couldn't even read at the "fp" or the pc didn't match
  1.1222 +      // both are sure clues that the fp is bogus. We no search the stack
  1.1223 +      // for a reasonable number of words trying to find the bogus fp
  1.1224 +      // and the current pc in adjacent words. The we will be able to
  1.1225 +      // deduce an approximation of the frame pointer and actually get
  1.1226 +      // the correct stack pointer. Which we can then unwind for the
  1.1227 +      // next frame.
  1.1228 +      int i;
  1.1229 +      uint64_t check;
  1.1230 +      uint64_t base = J->curr_fr.sp;
  1.1231 +      uint64_t prev_fp = 0;
  1.1232 +      for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
  1.1233 +        err = read_pointer(J, base , &check);
  1.1234 +        CHECK_FAIL(err);
  1.1235 +        if (check == fp) {
  1.1236 +          base += POINTER_SIZE;
  1.1237 +          err = read_pointer(J, base , &check);
  1.1238 +          CHECK_FAIL(err);
  1.1239 +          if (check == pc) {
  1.1240 +            if (debug) {
  1.1241 +              fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
  1.1242 +            }
  1.1243 +            prev_fp = base - 2 * POINTER_SIZE;
  1.1244 +            break;
  1.1245 +          }
  1.1246 +        }
  1.1247 +      }
  1.1248 +      if ( prev_fp != 0 ) {
  1.1249 +        // real_sp is the sp we should have received for this frame
  1.1250 +        uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
  1.1251 +        // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
  1.1252 +        jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
  1.1253 +        err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
  1.1254 +        CHECK_FAIL(err);
  1.1255 +        err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
  1.1256 +        CHECK_FAIL(err);
  1.1257 +        return PS_OK;
  1.1258 +      }
  1.1259 +    }
  1.1260 +
  1.1261 +    /* A prototype to workaround FP absence */
  1.1262 +    /*
  1.1263 +     * frame_size can be 0 for StubRoutines (1) frame.
  1.1264 +     * In this case it should work with fp as usual.
  1.1265 +     */
  1.1266 +    if (frame_size > 0) {
  1.1267 +      jframe->new_fp = J->prev_fr.fp + frame_size;
  1.1268 +      jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
  1.1269 +    } else {
  1.1270 +      memset(&J->curr_fr, 0, sizeof(Frame_t));
  1.1271 +      err = read_pointer(J,  fp, &jframe->new_fp);
  1.1272 +      CHECK_FAIL(err);
  1.1273 +
  1.1274 +      err = read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1.1275 +      CHECK_FAIL(err);
  1.1276 +    }
  1.1277 +    if (debug) {
  1.1278 +      fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
  1.1279 +                       result, frame_size);
  1.1280 +      fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
  1.1281 +                       J->prev_fr.fp, jframe->new_fp);
  1.1282 +    }
  1.1283 +  }
  1.1284 +#endif /* X86_COMPILER2 */
  1.1285 +
  1.1286 +  return PS_OK;
  1.1287 +
  1.1288 + fail:
  1.1289 +  return err;
  1.1290 +}
  1.1291 +
  1.1292 +int Jget_vframe(jvm_agent_t* J, int vframe_no,
  1.1293 +                char *name, size_t size, Jframe_t *jframe)
  1.1294 +{
  1.1295 +  Nmethod_t *N = J->N;
  1.1296 +  Vframe_t  *vf;
  1.1297 +  int32_t   err;
  1.1298 +
  1.1299 +  if (vframe_no >= N->vf_cnt) {
  1.1300 +     (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
  1.1301 +     return -1;
  1.1302 +  }
  1.1303 +  vf = N->vframes + vframe_no;
  1.1304 +  name[0] = COMP_METHOD_SIGN;
  1.1305 +  err = name_for_methodPtr(J, vf->method, name + 1, size);
  1.1306 +  CHECK_FAIL(err);
  1.1307 +
  1.1308 +  jframe->bci = vf->bci;
  1.1309 +  jframe->line = vf->line;
  1.1310 +  if (debug) {
  1.1311 +      fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
  1.1312 +                       name, vf->line);
  1.1313 +  }
  1.1314 +  return PS_OK;
  1.1315 +
  1.1316 + fail:
  1.1317 +  if (debug) {
  1.1318 +      fprintf(stderr, "\t Jget_vframe: FAIL\n");
  1.1319 +  }
  1.1320 +  return err;
  1.1321 +}
  1.1322 +
  1.1323 +#define MAX_SYM_SIZE 256
  1.1324 +
  1.1325 +int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
  1.1326 +                    size_t size, Jframe_t *jframe) {
  1.1327 +  uintptr_t fp;
  1.1328 +  uintptr_t pc;
  1.1329 +  /* arguments given to read_pointer need to be worst case sized */
  1.1330 +  uint64_t methodPtr = 0;
  1.1331 +  uint64_t sender_sp;
  1.1332 +  uint64_t bcx = 0;
  1.1333 +  int is_interpreted = 0;
  1.1334 +  int result = PS_OK;
  1.1335 +  int err = PS_OK;
  1.1336 +
  1.1337 +  if (J == NULL) {
  1.1338 +    return -1;
  1.1339 +  }
  1.1340 +
  1.1341 +  jframe->vf_cnt = 1;
  1.1342 +  jframe->new_fp = 0;
  1.1343 +  jframe->new_pc = 0;
  1.1344 +  jframe->line   = 0;
  1.1345 +  jframe->bci    = 0;
  1.1346 +  jframe->locinf = 0;
  1.1347 +
  1.1348 +  read_volatiles(J);
  1.1349 +  pc = (uintptr_t) regs[R_PC];
  1.1350 +  J->curr_fr.pc = pc;
  1.1351 +  J->curr_fr.fp = regs[R_FP];
  1.1352 +  J->curr_fr.sp = regs[R_SP];
  1.1353 +
  1.1354 +  if (debug)
  1.1355 +      fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
  1.1356 +
  1.1357 +#if defined(sparc) || defined(__sparc)
  1.1358 +    /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
  1.1359 +     * In the pcDesc structure return pc offset is recorded for CALL instructions.
  1.1360 +     * regs[R_PC] contains a CALL instruction pc offset.
  1.1361 +     */
  1.1362 +    pc += 8;
  1.1363 +    bcx          = (uintptr_t) regs[R_L1];
  1.1364 +    methodPtr = (uintptr_t) regs[R_L2];
  1.1365 +    sender_sp = regs[R_I5];
  1.1366 +    if (debug > 2) {
  1.1367 +        fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
  1.1368 +                         regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
  1.1369 +    }
  1.1370 +#elif defined(i386) || defined(__i386) || defined(__amd64)
  1.1371 +
  1.1372 +    fp = (uintptr_t) regs[R_FP];
  1.1373 +    if (J->prev_fr.fp == 0) {
  1.1374 +#ifdef X86_COMPILER2
  1.1375 +        /* A workaround for top java frames */
  1.1376 +        J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
  1.1377 +#else
  1.1378 +        J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
  1.1379 +#endif /* COMPILER2 */
  1.1380 +    }
  1.1381 +    if (debug > 2) {
  1.1382 +        printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
  1.1383 +    }
  1.1384 +
  1.1385 +    if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
  1.1386 +      methodPtr = 0;
  1.1387 +    }
  1.1388 +    if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
  1.1389 +      sender_sp = 0;
  1.1390 +    }
  1.1391 +    if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
  1.1392 +      bcx = 0;
  1.1393 +    }
  1.1394 +#endif /* i386 */
  1.1395 +
  1.1396 +  J->methodPtr = methodPtr;
  1.1397 +  J->bcx = bcx;
  1.1398 +
  1.1399 +  /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
  1.1400 +   * For example: JVM_SuspendThread frame poins to the top interpreted frame.
  1.1401 +   * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
  1.1402 +   * then we go over and omit both: nmethod and I2CAdapter frames.
  1.1403 +   * Note, that regs[R_PC] is always correct if frame defined correctly.
  1.1404 +   * So it is better to call codecache_contains(J, pc) from the beginning.
  1.1405 +   */
  1.1406 +#ifndef X86_COMPILER2
  1.1407 +  if (is_method(J, J->methodPtr)) {
  1.1408 +    result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
  1.1409 +    /* If the methodPtr is a method then this is highly likely to be
  1.1410 +       an interpreter frame */
  1.1411 +    if (result >= 0) {
  1.1412 +      is_interpreted = 1;
  1.1413 +    }
  1.1414 +  } else
  1.1415 +#endif /* ! X86_COMPILER2 */
  1.1416 +
  1.1417 +  if (codecache_contains(J, pc)) {
  1.1418 +    result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
  1.1419 +  }
  1.1420 +#ifdef X86_COMPILER2
  1.1421 +  else if (is_method(J, J->methodPtr)) {
  1.1422 +    result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
  1.1423 +    /* If the methodPtr is a method then this is highly likely to be
  1.1424 +       an interpreter frame */
  1.1425 +    if (result >= 0) {
  1.1426 +      is_interpreted = 1;
  1.1427 +    }
  1.1428 +  }
  1.1429 +#endif /* X86_COMPILER2 */
  1.1430 +  else {
  1.1431 +    if (debug) {
  1.1432 +        fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
  1.1433 +    }
  1.1434 +    result = -1;
  1.1435 +  }
  1.1436 +  if (!is_interpreted) {
  1.1437 +    sender_sp = 0;
  1.1438 +  }
  1.1439 +  J->curr_fr.sender_sp = sender_sp;
  1.1440 +
  1.1441 +#ifdef X86_COMPILER2
  1.1442 +  if (!J->curr_fr.fp) {
  1.1443 +    J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
  1.1444 +  }
  1.1445 +  if (!jframe->new_pc && jframe->new_fp) {
  1.1446 +    // This seems dubious
  1.1447 +    read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1.1448 +    CHECK_FAIL(err);
  1.1449 +    if (debug > 2) {
  1.1450 +        printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
  1.1451 +               jframe->new_fp, jframe->new_pc);
  1.1452 +    }
  1.1453 +  }
  1.1454 +
  1.1455 +#endif /* X86_COMPILER2 */
  1.1456 +  J->prev_fr = J->curr_fr;
  1.1457 +
  1.1458 +  if (debug)
  1.1459 +      fprintf(stderr, "Jlookup_by_regs: END\n\n");
  1.1460 +
  1.1461 +  return result;
  1.1462 +
  1.1463 + fail:
  1.1464 +  return err;
  1.1465 +}
  1.1466 +
  1.1467 +void update_gregs(prgregset_t gregs, Jframe_t jframe) {
  1.1468 +#ifdef X86_COMPILER2
  1.1469 +    if (debug > 0) {
  1.1470 +      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]);
  1.1471 +    }
  1.1472 +    /*
  1.1473 +     * A workaround for java C2 frames with unconventional FP.
  1.1474 +     * may have to modify regset with new values for FP/PC/SP when needed.
  1.1475 +     */
  1.1476 +     if (jframe.new_sp) {
  1.1477 +         *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
  1.1478 +     } else {
  1.1479 +         // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
  1.1480 +     }
  1.1481 +
  1.1482 +     if (jframe.new_fp) {
  1.1483 +         *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
  1.1484 +     }
  1.1485 +     if (jframe.new_pc) {
  1.1486 +         *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
  1.1487 +     }
  1.1488 +    if (debug > 0) {
  1.1489 +      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]);
  1.1490 +    }
  1.1491 +#endif  /* X86_COMPILER2 */
  1.1492 +}
  1.1493 +
  1.1494 +/*
  1.1495 + * Iterates over java frames at current location given by 'gregs'.
  1.1496 + *
  1.1497 + *  Returns -1 if no java frames are present or if an error is encountered.
  1.1498 + *  Returns the result of calling 'func' if the return value is non-zero.
  1.1499 + *  Returns 0 otherwise.
  1.1500 + */
  1.1501 +int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
  1.1502 +    char buf[MAX_SYM_SIZE + 1];
  1.1503 +    Jframe_t jframe;
  1.1504 +    int i = 0, res;
  1.1505 +#ifdef X86_COMPILER2
  1.1506 +    if (debug > 0) {
  1.1507 +      fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
  1.1508 +    }
  1.1509 +#endif  /* X86_COMPILER2 */
  1.1510 +
  1.1511 +    memset(&jframe, 0, sizeof(Jframe_t));
  1.1512 +    memset(buf, 0, sizeof(buf));
  1.1513 +    res =  Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
  1.1514 +    if (res != PS_OK)
  1.1515 +        return (-1);
  1.1516 +
  1.1517 +
  1.1518 +    res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
  1.1519 +               jframe.line, NULL);
  1.1520 +    if (res != 0) {
  1.1521 +        update_gregs(gregs, jframe);
  1.1522 +        return (res);
  1.1523 +    }
  1.1524 +    for (i = 1; i < jframe.vf_cnt; i++) {
  1.1525 +        Jget_vframe(J, i, buf, sizeof(buf), &jframe);
  1.1526 +        res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
  1.1527 +                   jframe.line, NULL);
  1.1528 +        if (res != 0) {
  1.1529 +            update_gregs(gregs, jframe);
  1.1530 +            return (res);
  1.1531 +        }
  1.1532 +    }
  1.1533 +    update_gregs(gregs, jframe);
  1.1534 +    return (0);
  1.1535 +}

mercurial