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