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