libjvm_db.c revision 3602:da91efe96a93
1/*
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <errno.h>
29#include <gelf.h>
30
31#include "libjvm_db.h"
32#include "JvmOffsets.h"
33
34#define LIBJVM_SO "libjvm.so"
35
36#if defined(i386) || defined(__i386) || defined(__amd64)
37#ifdef COMPILER2
38#define X86_COMPILER2
39#endif /* COMPILER2 */
40#endif /* i386 */
41
42typedef struct {
43    short     vf_cnt; /* number of recognized java vframes */
44    short     bci;    /* current frame method byte code index */
45    int       line;   /* current frame method source line */
46    uint64_t new_fp; /* fp for the next frame */
47    uint64_t new_pc; /* pc for the next frame */
48    uint64_t new_sp; /* "raw" sp for the next frame (includes extension by interpreter/adapter */
49    char      locinf; /* indicates there is valid location info */
50} Jframe_t;
51
52int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
53                    size_t size, Jframe_t *jframe);
54
55int main(int arg) { return arg; }
56
57static int debug = 0;
58
59static void failed(int err, const char * file, int line) {
60  if (debug) {
61    fprintf(stderr, "failed %d at %s:%d\n", err, file, line);
62  }
63}
64
65static void warn(const char * file, int line, const char * msg) {
66  if (debug) {
67    fprintf(stderr, "warning: %s at %s:%d\n", msg, file, line);
68  }
69}
70
71static void warn1(const char * file, int line, const char * msg, intptr_t arg1) {
72  if (debug) {
73    fprintf(stderr, "warning: ");
74    fprintf(stderr, msg, arg1);
75    fprintf(stderr, " at %s:%d\n", file, line);
76  }
77}
78
79#define CHECK_FAIL(err) \
80        if (err != PS_OK) { failed(err, __FILE__, __LINE__); goto fail; }
81#define WARN(msg)  warn(__FILE__, __LINE__, msg)
82#define WARN1(msg, arg1)  warn1(__FILE__, __LINE__, msg, arg1)
83
84typedef struct VMStructEntry {
85  const char * typeName;           /* The type name containing the given field (example: "Klass") */
86  const char * fieldName;          /* The field name within the type           (example: "_name") */
87  uint64_t address;                /* Address of field; only used for static fields */
88                                   /* ("offset" can not be reused because of apparent SparcWorks compiler bug */
89                                   /* in generation of initializer data) */
90} VMStructEntry;
91
92/* Prototyping inlined methods */
93
94int sprintf(char *s, const char *format, ...);
95
96#define SZ16  sizeof(int16_t)
97#define SZ32  sizeof(int32_t)
98
99#define COMP_METHOD_SIGN '*'
100
101#define MAX_VFRAMES_CNT 256
102
103typedef struct vframe {
104  uint64_t method;
105  int32_t  sender_decode_offset;
106  int32_t  methodIdx;
107  int32_t  bci;
108  int32_t  line;
109} Vframe_t;
110
111typedef struct frame {
112  uintptr_t fp;
113  uintptr_t pc;
114  uintptr_t sp;
115  uintptr_t sender_sp; // The unextended sp of the caller
116} Frame_t;
117
118typedef struct Nmethod_t {
119  struct jvm_agent* J;
120  Jframe_t *jframe;
121
122  uint64_t nm;                  /* _nmethod */
123  uint64_t pc;
124  uint64_t pc_desc;
125
126  int32_t  orig_pc_offset;      /* _orig_pc_offset */
127  int32_t  instrs_beg;          /* _code_offset */
128  int32_t  instrs_end;
129  int32_t  deopt_beg;           /* _deoptimize_offset */
130  int32_t  scopes_data_beg;     /* _scopes_data_offset */
131  int32_t  scopes_data_end;
132  int32_t  metadata_beg;        /* _metadata_offset */
133  int32_t  metadata_end;
134  int32_t  scopes_pcs_beg;      /* _scopes_pcs_offset */
135  int32_t  scopes_pcs_end;
136
137  int      vf_cnt;
138  Vframe_t vframes[MAX_VFRAMES_CNT];
139} Nmethod_t;
140
141struct jvm_agent {
142  struct ps_prochandle* P;
143
144  uint64_t nmethod_vtbl;
145  uint64_t CodeBlob_vtbl;
146  uint64_t BufferBlob_vtbl;
147  uint64_t RuntimeStub_vtbl;
148  uint64_t Method_vtbl;
149
150  uint64_t Use_Compressed_Oops_address;
151  uint64_t Universe_narrow_oop_base_address;
152  uint64_t Universe_narrow_oop_shift_address;
153  uint64_t CodeCache_heap_address;
154
155  /* Volatiles */
156  uint8_t  Use_Compressed_Oops;
157  uint64_t Universe_narrow_oop_base;
158  uint32_t Universe_narrow_oop_shift;
159  uint64_t CodeCache_low;
160  uint64_t CodeCache_high;
161  uint64_t CodeCache_segmap_low;
162  uint64_t CodeCache_segmap_high;
163
164  int32_t  SIZE_CodeCache_log2_segment;
165
166  uint64_t methodPtr;
167  uint64_t bcx;
168
169  Nmethod_t *N;                 /*Inlined methods support */
170  Frame_t   prev_fr;
171  Frame_t   curr_fr;
172};
173
174static int
175read_string(struct ps_prochandle *P,
176        char *buf,              /* caller's buffer */
177        size_t size,            /* upper limit on bytes to read */
178        uintptr_t addr)         /* address in process */
179{
180  int err = PS_OK;
181  while (size-- > 1 && err == PS_OK) {
182    err = ps_pread(P, addr, buf, 1);
183    if (*buf == '\0') {
184      return PS_OK;
185    }
186    addr += 1;
187    buf += 1;
188  }
189  return -1;
190}
191
192static int read_compressed_pointer(jvm_agent_t* J, uint64_t base, uint32_t *ptr) {
193  int err = -1;
194  uint32_t ptr32;
195  err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
196  *ptr = ptr32;
197  return err;
198}
199
200static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
201  int err = -1;
202  uint32_t ptr32;
203
204  switch (DATA_MODEL) {
205  case PR_MODEL_LP64:
206    err = ps_pread(J->P, base, ptr, sizeof(uint64_t));
207    break;
208  case PR_MODEL_ILP32:
209    err = ps_pread(J->P, base, &ptr32, sizeof(uint32_t));
210    *ptr = ptr32;
211    break;
212  }
213
214  return err;
215}
216
217static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) {
218  uint64_t ptr;
219  int err;
220  char buffer[1024];
221
222  *stringp = NULL;
223  err = read_pointer(J, base, &ptr);
224  CHECK_FAIL(err);
225  if (ptr != 0) {
226    err = read_string(J->P, buffer, sizeof(buffer), ptr);
227    CHECK_FAIL(err);
228    *stringp = strdup(buffer);
229  }
230  return PS_OK;
231
232 fail:
233  return err;
234}
235
236static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
237  uint64_t ptr;
238  int err;
239
240  err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName);
241  CHECK_FAIL(err);
242  err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName);
243  CHECK_FAIL(err);
244  err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address);
245  CHECK_FAIL(err);
246
247  return PS_OK;
248
249 fail:
250  if (vmp->typeName != NULL) free((void*)vmp->typeName);
251  if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
252  return err;
253}
254
255static int parse_vmstructs(jvm_agent_t* J) {
256  VMStructEntry  vmVar;
257  VMStructEntry* vmp = &vmVar;
258  uint64_t gHotSpotVMStructs;
259  psaddr_t sym_addr;
260  uint64_t base;
261  int err;
262
263  err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
264  CHECK_FAIL(err);
265  err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
266  CHECK_FAIL(err);
267  base = gHotSpotVMStructs;
268
269  err = PS_OK;
270  while (err == PS_OK) {
271    memset(vmp, 0, sizeof(VMStructEntry));
272    err = parse_vmstruct_entry(J, base, vmp);
273    if (err != PS_OK || vmp->typeName == NULL) {
274      break;
275    }
276
277    if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
278      if (strcmp("_heap", vmp->fieldName) == 0) {
279        err = read_pointer(J, vmp->address, &J->CodeCache_heap_address);
280      }
281    } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
282      if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
283        J->Universe_narrow_oop_base_address = vmp->address;
284      }
285      if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
286        J->Universe_narrow_oop_shift_address = vmp->address;
287      }
288    }
289    CHECK_FAIL(err);
290
291    base += SIZE_VMStructEntry;
292    if (vmp->typeName != NULL) free((void*)vmp->typeName);
293    if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
294  }
295
296  return PS_OK;
297
298 fail:
299  if (vmp->typeName != NULL) free((void*)vmp->typeName);
300  if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
301  return -1;
302}
303
304static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
305  psaddr_t sym_addr;
306  int err;
307
308  err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
309  if (err != PS_OK) goto fail;
310  *valuep = sym_addr;
311  return PS_OK;
312
313 fail:
314  return err;
315}
316
317static int read_volatiles(jvm_agent_t* J) {
318  uint64_t ptr;
319  int err;
320
321  err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
322  if (err == PS_OK) {
323    err = ps_pread(J->P,  J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
324    CHECK_FAIL(err);
325  } else {
326    J->Use_Compressed_Oops = 0;
327  }
328
329  err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
330  CHECK_FAIL(err);
331  err = ps_pread(J->P,  J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
332  CHECK_FAIL(err);
333
334  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
335                     OFFSET_VirtualSpace_low, &J->CodeCache_low);
336  CHECK_FAIL(err);
337  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
338                     OFFSET_VirtualSpace_high, &J->CodeCache_high);
339  CHECK_FAIL(err);
340  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
341                     OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low);
342  CHECK_FAIL(err);
343  err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
344                     OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high);
345  CHECK_FAIL(err);
346
347  err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size,
348                 &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
349  CHECK_FAIL(err);
350
351  return PS_OK;
352
353 fail:
354  return err;
355}
356
357
358static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
359  /* make sure the code cache is up to date */
360  return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high);
361}
362
363static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
364  return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
365}
366
367static uint64_t block_at(jvm_agent_t* J, int i) {
368  return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
369}
370
371static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
372  int err;
373
374  *startp = 0;
375  if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) {
376    int32_t used;
377    uint64_t segment = segment_for(J, ptr);
378    uint64_t block = J->CodeCache_segmap_low;
379    uint8_t tag;
380    err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
381    CHECK_FAIL(err);
382    if (tag == 0xff)
383      return PS_OK;
384    while (tag > 0) {
385      err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
386      CHECK_FAIL(err);
387      segment -= tag;
388    }
389    block = block_at(J, segment);
390    err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
391    CHECK_FAIL(err);
392    if (used) {
393      *startp = block + SIZE_HeapBlockHeader;
394    }
395  }
396  return PS_OK;
397
398 fail:
399  return -1;
400}
401
402static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
403  psaddr_t sym_addr;
404  int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
405  if (err == PS_OK) {
406    err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
407    return err;
408  }
409  *valuep = -1;
410  return -1;
411}
412
413jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
414  jvm_agent_t* J;
415  int err;
416
417  if (vers != JVM_DB_VERSION) {
418    errno = ENOTSUP;
419    return NULL;
420  }
421
422  J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
423
424  debug = getenv("LIBJVMDB_DEBUG") != NULL;
425  if (debug) debug = 3;
426
427  if (debug) {
428      fprintf(stderr, "Jagent_create: debug=%d\n", debug);
429#ifdef X86_COMPILER2
430      fprintf(stderr, "Jagent_create: R_SP=%d, R_FP=%d, POINTER_SIZE=%d\n", R_SP, R_FP, POINTER_SIZE);
431#endif  /* X86_COMPILER2 */
432  }
433
434  J->P = P;
435
436  // Initialize the initial previous frame
437
438  J->prev_fr.fp = 0;
439  J->prev_fr.pc = 0;
440  J->prev_fr.sp = 0;
441  J->prev_fr.sender_sp = 0;
442
443  err = find_symbol(J, "__1cHnmethodG__vtbl_", &J->nmethod_vtbl);
444  CHECK_FAIL(err);
445  err = find_symbol(J, "__1cKBufferBlobG__vtbl_", &J->BufferBlob_vtbl);
446  if (err != PS_OK) J->BufferBlob_vtbl = 0;
447  err = find_symbol(J, "__1cICodeBlobG__vtbl_", &J->CodeBlob_vtbl);
448  CHECK_FAIL(err);
449  err = find_symbol(J, "__1cLRuntimeStubG__vtbl_", &J->RuntimeStub_vtbl);
450  CHECK_FAIL(err);
451  err = find_symbol(J, "__1cGMethodG__vtbl_", &J->Method_vtbl);
452  CHECK_FAIL(err);
453
454  err = parse_vmstructs(J);
455  CHECK_FAIL(err);
456  err = read_volatiles(J);
457  CHECK_FAIL(err);
458
459  return J;
460
461 fail:
462  Jagent_destroy(J);
463  return NULL;
464}
465
466void Jagent_destroy(jvm_agent_t *J) {
467  if (J != NULL) {
468    free(J);
469  }
470}
471
472static int is_method(jvm_agent_t* J, uint64_t methodPtr) {
473  uint64_t klass;
474  int err = read_pointer(J, methodPtr, &klass);
475  if (err != PS_OK) goto fail;
476  return klass == J->Method_vtbl;
477
478 fail:
479  return 0;
480}
481
482static int
483name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size)
484{
485  short nameIndex;
486  short signatureIndex;
487  uint64_t constantPool;
488  uint64_t constMethod;
489  uint64_t nameSymbol;
490  uint64_t signatureSymbol;
491  uint64_t klassPtr;
492  uint64_t klassSymbol;
493  short klassSymbolLength;
494  short nameSymbolLength;
495  short signatureSymbolLength;
496  char * nameString = NULL;
497  char * klassString = NULL;
498  char * signatureString = NULL;
499  int err;
500
501  err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod);
502  CHECK_FAIL(err);
503  err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool);
504  CHECK_FAIL(err);
505
506  /* To get name string */
507  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2);
508  CHECK_FAIL(err);
509  err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol);
510  CHECK_FAIL(err);
511  // The symbol is a CPSlot and has lower bit set to indicate metadata
512  nameSymbol &= (~1); // remove metadata lsb
513  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
514  CHECK_FAIL(err);
515  nameString = (char*)calloc(nameSymbolLength + 1, 1);
516  err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
517  CHECK_FAIL(err);
518
519  /* To get signature string */
520  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2);
521  CHECK_FAIL(err);
522  err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol);
523  CHECK_FAIL(err);
524  signatureSymbol &= (~1);  // remove metadata lsb
525  err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
526  CHECK_FAIL(err);
527  signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
528  err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
529  CHECK_FAIL(err);
530
531  /* To get klass string */
532  err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr);
533  CHECK_FAIL(err);
534  err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol);
535  CHECK_FAIL(err);
536  err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
537  CHECK_FAIL(err);
538  klassString = (char*)calloc(klassSymbolLength + 1, 1);
539  err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
540  CHECK_FAIL(err);
541
542  result[0] = '\0';
543  strncat(result, klassString, size);
544  size -= strlen(klassString);
545  strncat(result, ".", size);
546  size -= 1;
547  strncat(result, nameString, size);
548  size -= strlen(nameString);
549  strncat(result, signatureString, size);
550
551  if (nameString != NULL) free(nameString);
552  if (klassString != NULL) free(klassString);
553  if (signatureString != NULL) free(signatureString);
554
555  return PS_OK;
556
557 fail:
558  if (debug) {
559      fprintf(stderr, "name_for_methodPtr: FAIL \n\n");
560  }
561  if (nameString != NULL) free(nameString);
562  if (klassString != NULL) free(klassString);
563  if (signatureString != NULL) free(signatureString);
564  return -1;
565}
566
567static int nmethod_info(Nmethod_t *N)
568{
569  jvm_agent_t *J = N->J;
570  uint64_t    nm = N->nm;
571  int32_t err;
572
573  if (debug > 2 )
574      fprintf(stderr, "\t nmethod_info: BEGIN \n");
575
576  /* Instructions */
577  err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32);
578  CHECK_FAIL(err);
579  err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
580  CHECK_FAIL(err);
581  err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
582  CHECK_FAIL(err);
583  err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
584  CHECK_FAIL(err);
585
586  /* Metadata */
587  err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32);
588  CHECK_FAIL(err);
589  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->metadata_end, SZ32);
590  CHECK_FAIL(err);
591
592  /* scopes_pcs */
593  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
594  CHECK_FAIL(err);
595  err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32);
596  CHECK_FAIL(err);
597
598  /* scopes_data */
599  err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
600  CHECK_FAIL(err);
601
602  if (debug > 2 ) {
603      N->scopes_data_end = N->scopes_pcs_beg;
604
605      fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
606                       N->instrs_beg, N->instrs_end);
607
608      fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
609                       N->deopt_beg);
610
611      fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
612                       N->orig_pc_offset);
613
614      fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n",
615                       N->metadata_beg, N->metadata_end);
616
617      fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
618                       N->scopes_data_beg, N->scopes_data_end);
619
620      fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
621                       N->scopes_pcs_beg, N->scopes_pcs_end);
622
623      fprintf(stderr, "\t nmethod_info: END \n\n");
624  }
625  return PS_OK;
626
627 fail:
628  return err;
629}
630
631static int
632raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
633{
634  int shift = 0;
635  int value = 0;
636  uint8_t ch = 0;
637  int32_t  err;
638  int32_t sum;
639  // Constants for UNSIGNED5 coding of Pack200
640  // see compressedStream.hpp
641  enum {
642    lg_H = 6,
643    H = 1<<lg_H,
644    BitsPerByte = 8,
645    L = (1<<BitsPerByte)-H,
646  };
647  int i;
648
649  err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
650  CHECK_FAIL(err);
651  if (debug > 2)
652      fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
653
654  sum = ch;
655  if ( sum >= L ) {
656    int32_t lg_H_i = lg_H;
657    // Read maximum of 5 total bytes (we've already read 1).
658    // See CompressedReadStream::read_int_mb
659    for ( i = 0;  i < 4; i++) {
660      err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
661      CHECK_FAIL(err);
662      sum += ch << lg_H_i;
663      if (ch < L ) {
664        *val = sum;
665        return PS_OK;
666      }
667      lg_H_i += lg_H;
668    }
669  }
670  *val = sum;
671  return PS_OK;
672
673 fail:
674  return err;
675}
676
677static int
678read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
679{
680  uint8_t next = 0;
681  int32_t bci_delta;
682  int32_t line_delta;
683  int32_t err;
684
685  if (debug > 2)
686      fprintf(stderr, "\t\t read_pair: BEGIN\n");
687
688  err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
689  CHECK_FAIL(err);
690
691  if (next == 0) {
692      if (debug > 2)
693          fprintf(stderr, "\t\t read_pair: END: next == 0\n");
694      return 1; /* stream terminated */
695  }
696  if (next == 0xFF) {
697      if (debug > 2)
698          fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
699
700      /* Escape character, regular compression used */
701
702      err = raw_read_int(J, buffer, &bci_delta);
703      CHECK_FAIL(err);
704
705      err = raw_read_int(J, buffer, &line_delta);
706      CHECK_FAIL(err);
707
708      *bci  += bci_delta;
709      *line += line_delta;
710
711      if (debug > 2) {
712          fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
713                          line_delta, bci_delta);
714          fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
715                          *line, *bci);
716      }
717  } else {
718      /* Single byte compression used */
719      *bci  += next >> 3;
720      *line += next & 0x7;
721      if (debug > 2) {
722          fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
723                          next & 0x7, next >> 3);
724          fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
725                          *line, *bci);
726      }
727  }
728  if (debug > 2)
729      fprintf(stderr, "\t\t read_pair: END\n");
730  return PS_OK;
731
732 fail:
733  if (debug)
734      fprintf(stderr, "\t\t read_pair: FAIL\n");
735  return err;
736}
737
738static int
739line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
740{
741  uint64_t buffer;
742  uint16_t code_size;
743  uint64_t code_end_delta;
744  uint64_t constMethod;
745  int8_t   access_flags;
746  int32_t  best_bci    = 0;
747  int32_t  stream_bci  = 0;
748  int32_t  stream_line = 0;
749  int32_t  err;
750
751  if (debug > 2) {
752      char name[256];
753      err = name_for_methodPtr(J, vf->method, name, 256);
754      CHECK_FAIL(err);
755      fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
756                       name, vf->bci);
757  }
758
759  err = read_pointer(J, vf->method + OFFSET_Method_constMethod, &constMethod);
760  CHECK_FAIL(err);
761
762  vf->line = 0;
763  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_flags, &access_flags, sizeof(int8_t));
764  CHECK_FAIL(err);
765
766  if (!(access_flags & ConstMethod_has_linenumber_table)) {
767      if (debug > 2)
768          fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
769      return PS_OK;
770  }
771
772  /*  The line numbers are a short array of 2-tuples [start_pc, line_number].
773   *  Not necessarily sorted and not necessarily one-to-one.
774   */
775
776  err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_code_size, &code_size, SZ16);
777  CHECK_FAIL(err);
778
779  /* inlined_table_start() */
780  code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
781  buffer = constMethod + (uint64_t) SIZE_ConstMethod + (uint64_t) code_size + code_end_delta;
782
783  if (debug > 2) {
784      fprintf(stderr, "\t\t line_number_from_bci: method: %#llx, native: %d\n",
785                      vf->method, (access_flags & AccessFlags_NATIVE));
786      fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
787                      buffer, (int) code_size);
788  }
789
790  while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
791      if (stream_bci == vf->bci) {
792          /* perfect match */
793          if (debug > 2)
794              fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
795          vf->line = stream_line;
796          return PS_OK;
797      } else {
798          /* update best_bci/line */
799          if (stream_bci < vf->bci && stream_bci >= best_bci) {
800              best_bci = stream_bci;
801              vf->line = stream_line;
802              if (debug > 2) {
803                  fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
804                                   best_bci, vf->line);
805              }
806          }
807      }
808  }
809  if (debug > 2)
810      fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
811  return PS_OK;
812
813 fail:
814  if (debug)
815      fprintf(stderr, "\t line_number_from_bci: FAIL\n");
816  return err;
817}
818
819static int
820get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
821{
822  int32_t pc_offset;
823  int32_t err;
824
825  err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
826  CHECK_FAIL(err);
827
828  *real_pc = N->nm + N->instrs_beg + pc_offset;
829  if (debug > 2) {
830      fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
831                       pc_offset, *real_pc);
832  }
833  return PS_OK;
834
835 fail:
836  return err;
837}
838
839/* Finds a PcDesc with real-pc equal to N->pc */
840static int pc_desc_at(Nmethod_t *N)
841{
842  uint64_t pc_diff;
843  int32_t offs;
844  int32_t err;
845
846  if (debug > 2)
847      fprintf(stderr, "\t pc_desc_at: BEGIN\n");
848
849  N->vf_cnt  = 0;
850  N->pc_desc = 0;
851
852  for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
853      uint64_t pd;
854      uint64_t best_pc_diff = 16;       /* some approximation */
855      uint64_t real_pc = 0;
856
857      pd = N->nm + offs;
858      err = get_real_pc(N, pd, &real_pc);
859      CHECK_FAIL(err);
860
861      pc_diff = real_pc - N->pc;
862
863      /* In general, this fragment should work */
864      if (pc_diff == 0) {
865          N->pc_desc = pd;
866          if (debug) {
867            fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
868          }
869          return PS_OK;
870      }
871      /* This fragment is to be able to find out an appropriate
872       * pc_desc entry even if pc_desc info is inaccurate.
873       */
874      if (best_pc_diff > pc_diff && pc_diff > 0) {
875          best_pc_diff = pc_diff;
876          N->pc_desc = pd;
877      }
878  }
879  if (debug) {
880      fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
881      if (pc_diff < 20)
882          fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
883      else
884          fprintf(stderr, "\n\n");
885  }
886  return PS_OK;
887
888 fail:
889  return err;
890}
891
892static int
893scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
894{
895  uint64_t buffer;
896  int32_t  err;
897
898  if (debug > 2) {
899      fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
900  }
901
902  buffer = N->nm + N->scopes_data_beg + decode_offset;
903
904  err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
905  CHECK_FAIL(err);
906
907  err = raw_read_int(N->J, &buffer, &vf->methodIdx);
908  CHECK_FAIL(err);
909
910  err = raw_read_int(N->J, &buffer, &vf->bci);
911  CHECK_FAIL(err);
912
913  if (debug > 2) {
914      fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
915                      vf->sender_decode_offset);
916      fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
917      fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
918
919      fprintf(stderr, "\t\t scope_desc_at: END \n\n");
920  }
921  return PS_OK;
922
923 fail:
924  return err;
925}
926
927static int scopeDesc_chain(Nmethod_t *N) {
928  int32_t decode_offset = 0;
929  int32_t err;
930
931  if (debug > 2) {
932    fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
933  }
934
935  err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
936                 &decode_offset, SZ32);
937  CHECK_FAIL(err);
938
939  while (decode_offset > 0) {
940    Vframe_t *vf = &N->vframes[N->vf_cnt];
941
942    if (debug > 2) {
943      fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
944    }
945
946    err = scope_desc_at(N, decode_offset, vf);
947    CHECK_FAIL(err);
948
949    if (vf->methodIdx > ((N->metadata_end - N->metadata_beg) / POINTER_SIZE)) {
950      fprintf(stderr, "\t scopeDesc_chain: (methodIdx > metadata length) !\n");
951      return -1;
952    }
953    err = read_pointer(N->J, N->nm + N->metadata_beg + (vf->methodIdx-1)*POINTER_SIZE,
954                       &vf->method);
955    CHECK_FAIL(err);
956
957    if (vf->method) {
958      N->vf_cnt++;
959      err = line_number_from_bci(N->J, vf);
960      CHECK_FAIL(err);
961      if (debug > 2) {
962        fprintf(stderr, "\t scopeDesc_chain: method: %#8llx, line: %ld\n",
963                vf->method, vf->line);
964      }
965    }
966    decode_offset = vf->sender_decode_offset;
967  }
968  if (debug > 2) {
969    fprintf(stderr, "\t scopeDesc_chain: END \n\n");
970  }
971  return PS_OK;
972
973 fail:
974  if (debug) {
975    fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
976  }
977  return err;
978}
979
980
981static int
982name_for_nmethod(jvm_agent_t* J,
983                 uint64_t nm,
984                 uint64_t pc,
985                 uint64_t method,
986                 char *result,
987                 size_t size,
988                 Jframe_t *jframe
989) {
990  Nmethod_t *N;
991  Vframe_t *vf;
992  int32_t err;
993  int deoptimized = 0;
994
995  if (debug) {
996      fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
997  }
998  if (J->N == NULL) {
999    J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
1000  }
1001  memset(J->N, 0, sizeof(Nmethod_t));   /* Initial stat: all values are zeros */
1002  N     = J->N;
1003  N->J  = J;
1004  N->nm = nm;
1005  N->pc = pc;
1006  N->jframe = jframe;
1007
1008  err = nmethod_info(N);
1009  CHECK_FAIL(err);
1010  if (debug) {
1011      fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc:  %#llx\n",
1012              pc, N->nm + N->deopt_beg);
1013  }
1014
1015  /* check for a deoptimized frame */
1016  if ( pc == N->nm + N->deopt_beg) {
1017    uint64_t base;
1018    if (debug) {
1019        fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
1020    }
1021    if (J->prev_fr.sender_sp != 0) {
1022      base = J->prev_fr.sender_sp + N->orig_pc_offset;
1023    } else {
1024      base = J->curr_fr.sp + N->orig_pc_offset;
1025    }
1026    err = read_pointer(J, base, &N->pc);
1027    CHECK_FAIL(err);
1028    if (debug) {
1029        fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
1030        pc,  N->pc);
1031    }
1032    deoptimized = 1;
1033  }
1034
1035  err = pc_desc_at(N);
1036  CHECK_FAIL(err);
1037
1038  if (N->pc_desc > 0) {
1039      jframe->locinf = 1;
1040      err = scopeDesc_chain(N);
1041      CHECK_FAIL(err);
1042  }
1043  result[0] = COMP_METHOD_SIGN;
1044  vf = &N->vframes[0];
1045  if (N->vf_cnt > 0) {
1046      jframe->vf_cnt = N->vf_cnt;
1047      jframe->bci  = vf->bci;
1048      jframe->line = vf->line;
1049      err = name_for_methodPtr(J, N->vframes[0].method, result+1, size-1);
1050      CHECK_FAIL(err);
1051  } else {
1052      err = name_for_methodPtr(J, method, result+1, size-1);
1053      CHECK_FAIL(err);
1054  }
1055  if (deoptimized) {
1056    strncat(result + 1, " [deoptimized frame]; ", size-1);
1057  } else {
1058    strncat(result + 1, " [compiled] ", size-1);
1059  }
1060  if (debug)
1061      fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
1062                      result, N->vf_cnt);
1063  return PS_OK;
1064
1065 fail:
1066  if (debug)
1067      fprintf(stderr, "name_for_nmethod: FAIL \n\n");
1068  return err;
1069}
1070
1071int is_bci(intptr_t bcx) {
1072  switch (DATA_MODEL) {
1073  case PR_MODEL_LP64:
1074    return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
1075  case PR_MODEL_ILP32:
1076  default:
1077    return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
1078  }
1079}
1080
1081static int
1082name_for_imethod(jvm_agent_t* J,
1083                 uint64_t bcx,
1084                 uint64_t method,
1085                 char *result,
1086                 size_t size,
1087                 Jframe_t *jframe
1088) {
1089  uint64_t bci;
1090  uint64_t constMethod;
1091  Vframe_t vframe = {0};
1092  Vframe_t *vf = &vframe;
1093  int32_t   err;
1094
1095  err = read_pointer(J, method + OFFSET_Method_constMethod, &constMethod);
1096  CHECK_FAIL(err);
1097
1098  bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_ConstMethod);
1099
1100  if (debug)
1101      fprintf(stderr, "\t name_for_imethod: BEGIN: method: %#llx\n", method);
1102
1103  err = name_for_methodPtr(J, method, result, size);
1104  CHECK_FAIL(err);
1105  if (debug)
1106      fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
1107
1108  if (bci > 0) {
1109      vf->method = method;
1110      vf->bci       = bci;
1111      err = line_number_from_bci(J, vf);
1112      CHECK_FAIL(err);
1113  }
1114  jframe->bci  = vf->bci;
1115  jframe->line = vf->line;
1116  jframe->locinf = 1;
1117
1118  if (debug) {
1119      fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
1120                      vf->bci, vf->line);
1121  }
1122  return PS_OK;
1123
1124 fail:
1125  if (debug)
1126      fprintf(stderr, "\t name_for_imethod: FAIL\n");
1127  return err;
1128}
1129
1130static int
1131name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
1132                   size_t size, Jframe_t *jframe, int* is_interpreted)
1133{
1134  uint64_t start;
1135  uint64_t vtbl;
1136  int32_t err;
1137  *is_interpreted = 0;
1138
1139  result[0] = '\0';
1140
1141  err = find_start(J, pc, &start);
1142  CHECK_FAIL(err);
1143
1144  err = read_pointer(J, start, &vtbl);
1145  CHECK_FAIL(err);
1146
1147  if (vtbl == J->nmethod_vtbl) {
1148    uint64_t method;
1149
1150    err = read_pointer(J, start + OFFSET_nmethod_method, &method);
1151    CHECK_FAIL(err);
1152
1153    if (debug) {
1154        fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, method: %#8llx \n",
1155                        start, pc, method);
1156    }
1157    err = name_for_nmethod(J, start, pc, method, result, size, jframe);
1158    CHECK_FAIL(err);
1159  } else if (vtbl == J->BufferBlob_vtbl) {
1160    const char * name;
1161
1162    err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1163
1164    /*
1165     * Temporary usage of string "Interpreter".
1166     * We need some other way to distinguish "StubRoutines"
1167     * and regular interpreted frames.
1168     */
1169    if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
1170      *is_interpreted = 1;
1171      if (is_method(J, J->methodPtr)) {
1172        return name_for_imethod(J, J->bcx, J->methodPtr, result, size, jframe);
1173      }
1174    }
1175
1176    if (err == PS_OK) {
1177      strncpy(result, name, size);
1178      free((void*)name);
1179    } else {
1180      strncpy(result, "<unknown BufferBlob>", size);
1181    }
1182    /* return PS_OK; */
1183  } else {
1184    const char * name;
1185
1186    err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
1187    if (err == PS_OK) {
1188      strncpy(result, name, size);
1189      free((void*)name);
1190    } else {
1191      strncpy(result, "<unknown CodeBlob>", size);
1192      WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
1193    }
1194  }
1195  result[size-1] = '\0';
1196
1197#ifdef X86_COMPILER2
1198  if (vtbl != J->RuntimeStub_vtbl) {
1199    uint64_t trial_pc;
1200    int frame_size;
1201    err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
1202                         &frame_size, SZ32);
1203    CHECK_FAIL(err);
1204
1205    // frame_size is in words, we want bytes.
1206    frame_size *= POINTER_SIZE; /* word => byte conversion */
1207
1208    /*
1209      Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
1210      in the initial entry to a set of stack frames containing server frames
1211      will pretty much be nonsense. We can detect that nonsense by looking to
1212      see if the PC we received is correct if we look at the expected storage
1213      location in relation to the FP (ie. POINTER_SIZE(FP) )
1214    */
1215
1216    err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
1217    if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
1218      // Either we couldn't even read at the "fp" or the pc didn't match
1219      // both are sure clues that the fp is bogus. We no search the stack
1220      // for a reasonable number of words trying to find the bogus fp
1221      // and the current pc in adjacent words. The we will be able to
1222      // deduce an approximation of the frame pointer and actually get
1223      // the correct stack pointer. Which we can then unwind for the
1224      // next frame.
1225      int i;
1226      uint64_t check;
1227      uint64_t base = J->curr_fr.sp;
1228      uint64_t prev_fp = 0;
1229      for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
1230        err = read_pointer(J, base , &check);
1231        CHECK_FAIL(err);
1232        if (check == fp) {
1233          base += POINTER_SIZE;
1234          err = read_pointer(J, base , &check);
1235          CHECK_FAIL(err);
1236          if (check == pc) {
1237            if (debug) {
1238              fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
1239            }
1240            prev_fp = base - 2 * POINTER_SIZE;
1241            break;
1242          }
1243        }
1244      }
1245      if ( prev_fp != 0 ) {
1246        // real_sp is the sp we should have received for this frame
1247        uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
1248        // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
1249        jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
1250        err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
1251        CHECK_FAIL(err);
1252        err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
1253        CHECK_FAIL(err);
1254        return PS_OK;
1255      }
1256    }
1257
1258    /* A prototype to workaround FP absence */
1259    /*
1260     * frame_size can be 0 for StubRoutines (1) frame.
1261     * In this case it should work with fp as usual.
1262     */
1263    if (frame_size > 0) {
1264      jframe->new_fp = J->prev_fr.fp + frame_size;
1265      jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
1266    } else {
1267      memset(&J->curr_fr, 0, sizeof(Frame_t));
1268      err = read_pointer(J,  fp, &jframe->new_fp);
1269      CHECK_FAIL(err);
1270
1271      err = read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
1272      CHECK_FAIL(err);
1273    }
1274    if (debug) {
1275      fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
1276                       result, frame_size);
1277      fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
1278                       J->prev_fr.fp, jframe->new_fp);
1279    }
1280  }
1281#endif /* X86_COMPILER2 */
1282
1283  return PS_OK;
1284
1285 fail:
1286  return err;
1287}
1288
1289int Jget_vframe(jvm_agent_t* J, int vframe_no,
1290                char *name, size_t size, Jframe_t *jframe)
1291{
1292  Nmethod_t *N = J->N;
1293  Vframe_t  *vf;
1294  int32_t   err;
1295
1296  if (vframe_no >= N->vf_cnt) {
1297     (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
1298     return -1;
1299  }
1300  vf = N->vframes + vframe_no;
1301  name[0] = COMP_METHOD_SIGN;
1302  err = name_for_methodPtr(J, vf->method, name + 1, size);
1303  CHECK_FAIL(err);
1304
1305  jframe->bci = vf->bci;
1306  jframe->line = vf->line;
1307  if (debug) {
1308      fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
1309                       name, vf->line);
1310  }
1311  return PS_OK;
1312
1313 fail:
1314  if (debug) {
1315      fprintf(stderr, "\t Jget_vframe: FAIL\n");
1316  }
1317  return err;
1318}
1319
1320#define MAX_SYM_SIZE 256
1321
1322int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
1323                    size_t size, Jframe_t *jframe) {
1324  uintptr_t fp;
1325  uintptr_t pc;
1326  /* arguments given to read_pointer need to be worst case sized */
1327  uint64_t methodPtr = 0;
1328  uint64_t sender_sp;
1329  uint64_t bcx = 0;
1330  int is_interpreted = 0;
1331  int result = PS_OK;
1332  int err = PS_OK;
1333
1334  if (J == NULL) {
1335    return -1;
1336  }
1337
1338  jframe->vf_cnt = 1;
1339  jframe->new_fp = 0;
1340  jframe->new_pc = 0;
1341  jframe->line   = 0;
1342  jframe->bci    = 0;
1343  jframe->locinf = 0;
1344
1345  read_volatiles(J);
1346  pc = (uintptr_t) regs[R_PC];
1347  J->curr_fr.pc = pc;
1348  J->curr_fr.fp = regs[R_FP];
1349  J->curr_fr.sp = regs[R_SP];
1350
1351  if (debug)
1352      fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
1353
1354#if defined(sparc) || defined(__sparc)
1355    /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
1356     * In the pcDesc structure return pc offset is recorded for CALL instructions.
1357     * regs[R_PC] contains a CALL instruction pc offset.
1358     */
1359    pc += 8;
1360    bcx          = (uintptr_t) regs[R_L1];
1361    methodPtr = (uintptr_t) regs[R_L2];
1362    sender_sp = regs[R_I5];
1363    if (debug > 2) {
1364        fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
1365                         regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
1366    }
1367#elif defined(i386) || defined(__i386) || defined(__amd64)
1368
1369    fp = (uintptr_t) regs[R_FP];
1370    if (J->prev_fr.fp == 0) {
1371#ifdef X86_COMPILER2
1372        /* A workaround for top java frames */
1373        J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
1374#else
1375        J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
1376#endif /* COMPILER2 */
1377    }
1378    if (debug > 2) {
1379        printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
1380    }
1381
1382    if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodPtr) != PS_OK) {
1383      methodPtr = 0;
1384    }
1385    if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
1386      sender_sp = 0;
1387    }
1388    if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
1389      bcx = 0;
1390    }
1391#endif /* i386 */
1392
1393  J->methodPtr = methodPtr;
1394  J->bcx = bcx;
1395
1396  /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
1397   * For example: JVM_SuspendThread frame poins to the top interpreted frame.
1398   * If we call is_method(J, methodPtr) before codecache_contains(J, pc)
1399   * then we go over and omit both: nmethod and I2CAdapter frames.
1400   * Note, that regs[R_PC] is always correct if frame defined correctly.
1401   * So it is better to call codecache_contains(J, pc) from the beginning.
1402   */
1403#ifndef X86_COMPILER2
1404  if (is_method(J, J->methodPtr)) {
1405    result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
1406    /* If the methodPtr is a method then this is highly likely to be
1407       an interpreter frame */
1408    if (result >= 0) {
1409      is_interpreted = 1;
1410    }
1411  } else
1412#endif /* ! X86_COMPILER2 */
1413
1414  if (codecache_contains(J, pc)) {
1415    result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
1416  }
1417#ifdef X86_COMPILER2
1418  else if (is_method(J, J->methodPtr)) {
1419    result = name_for_imethod(J, bcx, J->methodPtr, name, size, jframe);
1420    /* If the methodPtr is a method then this is highly likely to be
1421       an interpreter frame */
1422    if (result >= 0) {
1423      is_interpreted = 1;
1424    }
1425  }
1426#endif /* X86_COMPILER2 */
1427  else {
1428    if (debug) {
1429        fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
1430    }
1431    result = -1;
1432  }
1433  if (!is_interpreted) {
1434    sender_sp = 0;
1435  }
1436  J->curr_fr.sender_sp = sender_sp;
1437
1438#ifdef X86_COMPILER2
1439  if (!J->curr_fr.fp) {
1440    J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
1441  }
1442  if (!jframe->new_pc && jframe->new_fp) {
1443    // This seems dubious
1444    read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
1445    CHECK_FAIL(err);
1446    if (debug > 2) {
1447        printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
1448               jframe->new_fp, jframe->new_pc);
1449    }
1450  }
1451
1452#endif /* X86_COMPILER2 */
1453  J->prev_fr = J->curr_fr;
1454
1455  if (debug)
1456      fprintf(stderr, "Jlookup_by_regs: END\n\n");
1457
1458  return result;
1459
1460 fail:
1461  return err;
1462}
1463
1464void update_gregs(prgregset_t gregs, Jframe_t jframe) {
1465#ifdef X86_COMPILER2
1466    if (debug > 0) {
1467      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]);
1468    }
1469    /*
1470     * A workaround for java C2 frames with unconventional FP.
1471     * may have to modify regset with new values for FP/PC/SP when needed.
1472     */
1473     if (jframe.new_sp) {
1474         *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
1475     } else {
1476         // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
1477     }
1478
1479     if (jframe.new_fp) {
1480         *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
1481     }
1482     if (jframe.new_pc) {
1483         *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
1484     }
1485    if (debug > 0) {
1486      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]);
1487    }
1488#endif  /* X86_COMPILER2 */
1489}
1490
1491/*
1492 * Iterates over java frames at current location given by 'gregs'.
1493 *
1494 *  Returns -1 if no java frames are present or if an error is encountered.
1495 *  Returns the result of calling 'func' if the return value is non-zero.
1496 *  Returns 0 otherwise.
1497 */
1498int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
1499    char buf[MAX_SYM_SIZE + 1];
1500    Jframe_t jframe;
1501    int i = 0, res;
1502#ifdef X86_COMPILER2
1503    if (debug > 0) {
1504      fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
1505    }
1506#endif  /* X86_COMPILER2 */
1507
1508    memset(&jframe, 0, sizeof(Jframe_t));
1509    memset(buf, 0, sizeof(buf));
1510    res =  Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
1511    if (res != PS_OK)
1512        return (-1);
1513
1514
1515    res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
1516               jframe.line, NULL);
1517    if (res != 0) {
1518        update_gregs(gregs, jframe);
1519        return (res);
1520    }
1521    for (i = 1; i < jframe.vf_cnt; i++) {
1522        Jget_vframe(J, i, buf, sizeof(buf), &jframe);
1523        res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
1524                   jframe.line, NULL);
1525        if (res != 0) {
1526            update_gregs(gregs, jframe);
1527            return (res);
1528        }
1529    }
1530    update_gregs(gregs, jframe);
1531    return (0);
1532}
1533