src/os/solaris/dtrace/libjvm_db.c

Thu, 27 Jan 2011 16:11:27 -0800

author
coleenp
date
Thu, 27 Jan 2011 16:11:27 -0800
changeset 2497
3582bf76420e
parent 2103
3e8fbc61cee8
child 2626
8a3f8defe568
permissions
-rw-r--r--

6990754: Use native memory and reference counting to implement SymbolTable
Summary: move symbols from permgen into C heap and reference count them
Reviewed-by: never, acorn, jmasa, stefank

     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  */
    25 #include <stdio.h>
    26 #include <stdlib.h>
    27 #include <string.h>
    28 #include <errno.h>
    29 #include <gelf.h>
    31 #include "libjvm_db.h"
    32 #include "JvmOffsets.h"
    34 #define LIBJVM_SO "libjvm.so"
    36 #if defined(i386) || defined(__i386) || defined(__amd64)
    37 #ifdef COMPILER2
    38 #define X86_COMPILER2
    39 #endif /* COMPILER2 */
    40 #endif /* i386 */
    42 typedef 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;
    52 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
    53                     size_t size, Jframe_t *jframe);
    55 int main(int arg) { return arg; }
    57 static int debug = 0;
    59 static 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 }
    65 static 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 }
    71 static 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 }
    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)
    84 typedef 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;
    92 /* Prototyping inlined methods */
    94 int sprintf(char *s, const char *format, ...);
    96 #define SZ16  sizeof(int16_t)
    97 #define SZ32  sizeof(int32_t)
    99 #define COMP_METHOD_SIGN '*'
   101 #define MAX_VFRAMES_CNT 256
   103 typedef 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;
   111 typedef 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;
   118 typedef struct Nmethod_t {
   119   struct jvm_agent* J;
   120   Jframe_t *jframe;
   122   uint64_t nm;                  /* _nmethod */
   123   uint64_t pc;
   124   uint64_t pc_desc;
   126   int32_t  orig_pc_offset;      /* _orig_pc_offset */
   127   int32_t  instrs_beg;          /* _code_offset */
   128   int32_t  instrs_end;
   129   int32_t  deopt_beg;           /* _deoptimize_offset */
   130   int32_t  scopes_data_beg;     /* _scopes_data_offset */
   131   int32_t  scopes_data_end;
   132   int32_t  oops_beg;            /* _oops_offset */
   133   int32_t  oops_end;
   134   int32_t  scopes_pcs_beg;      /* _scopes_pcs_offset */
   135   int32_t  scopes_pcs_end;
   137   int      vf_cnt;
   138   Vframe_t vframes[MAX_VFRAMES_CNT];
   139 } Nmethod_t;
   141 struct jvm_agent {
   142   struct ps_prochandle* P;
   144   uint64_t nmethod_vtbl;
   145   uint64_t CodeBlob_vtbl;
   146   uint64_t BufferBlob_vtbl;
   147   uint64_t RuntimeStub_vtbl;
   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;
   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;
   165   int32_t  SIZE_CodeCache_log2_segment;
   167   uint64_t methodOopPtr;
   168   uint64_t bcx;
   170   Nmethod_t *N;                 /*Inlined methods support */
   171   Frame_t   prev_fr;
   172   Frame_t   curr_fr;
   173 };
   175 static int
   176 read_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 }
   193 static 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 }
   201 static int read_pointer(jvm_agent_t* J, uint64_t base, uint64_t* ptr) {
   202   int err = -1;
   203   uint32_t ptr32;
   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   }
   215   return err;
   216 }
   218 static 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];
   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;
   233  fail:
   234   return err;
   235 }
   237 static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) {
   238   uint64_t ptr;
   239   int err;
   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);
   248   return PS_OK;
   250  fail:
   251   if (vmp->typeName != NULL) free((void*)vmp->typeName);
   252   if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
   253   return err;
   254 }
   256 static 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;
   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;
   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     }
   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);
   295     base += SIZE_VMStructEntry;
   296     if (vmp->typeName != NULL) free((void*)vmp->typeName);
   297     if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
   298   }
   300   return PS_OK;
   302  fail:
   303   if (vmp->typeName != NULL) free((void*)vmp->typeName);
   304   if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
   305   return -1;
   306 }
   308 static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) {
   309   psaddr_t sym_addr;
   310   int err;
   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;
   317  fail:
   318   return err;
   319 }
   321 static int read_volatiles(jvm_agent_t* J) {
   322   uint64_t ptr;
   323   int err;
   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   }
   333   err = read_pointer(J, J->Universe_methodKlassObj_address, &J->Universe_methodKlassObj);
   334   CHECK_FAIL(err);
   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);
   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);
   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);
   358   return PS_OK;
   360  fail:
   361   return err;
   362 }
   365 static 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 }
   370 static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
   371   return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
   372 }
   374 static uint64_t block_at(jvm_agent_t* J, int i) {
   375   return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
   376 }
   378 static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
   379   int err;
   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;
   405  fail:
   406   return -1;
   407 }
   409 static 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 }
   420 jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
   421   jvm_agent_t* J;
   422   int err;
   424   if (vers != JVM_DB_VERSION) {
   425     errno = ENOTSUP;
   426     return NULL;
   427   }
   429   J = (jvm_agent_t*)calloc(sizeof(struct jvm_agent), 1);
   431   debug = getenv("LIBJVMDB_DEBUG") != NULL;
   432   if (debug) debug = 3;
   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   }
   441   J->P = P;
   443   // Initialize the initial previous frame
   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;
   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);
   459   err = parse_vmstructs(J);
   460   CHECK_FAIL(err);
   461   err = read_volatiles(J);
   462   CHECK_FAIL(err);
   464   return J;
   466  fail:
   467   Jagent_destroy(J);
   468   return NULL;
   469 }
   471 void Jagent_destroy(jvm_agent_t *J) {
   472   if (J != NULL) {
   473     free(J);
   474   }
   475 }
   477 static 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;
   494  fail:
   495   return 0;
   496 }
   498 static int
   499 name_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;
   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);
   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_Symbol_length, &nameSymbolLength, 2);
   528   CHECK_FAIL(err);
   529   nameString = (char*)calloc(nameSymbolLength + 1, 1);
   530   err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
   531   CHECK_FAIL(err);
   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_Symbol_length, &signatureSymbolLength, 2);
   539   CHECK_FAIL(err);
   540   signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
   541   err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
   542   CHECK_FAIL(err);
   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_Symbol_length, &klassSymbolLength, 2);
   550   CHECK_FAIL(err);
   551   klassString = (char*)calloc(klassSymbolLength + 1, 1);
   552   err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
   553   CHECK_FAIL(err);
   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);
   564   if (nameString != NULL) free(nameString);
   565   if (klassString != NULL) free(klassString);
   566   if (signatureString != NULL) free(signatureString);
   568   return PS_OK;
   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 }
   580 static int nmethod_info(Nmethod_t *N)
   581 {
   582   jvm_agent_t *J = N->J;
   583   uint64_t    nm = N->nm;
   584   int32_t err;
   586   if (debug > 2 )
   587       fprintf(stderr, "\t nmethod_info: BEGIN \n");
   589   /* Instructions */
   590   err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_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);
   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);
   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);
   611   /* scopes_data */
   612   err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
   613   CHECK_FAIL(err);
   615   if (debug > 2 ) {
   616       N->scopes_data_end = N->scopes_pcs_beg;
   618       fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
   619                        N->instrs_beg, N->instrs_end);
   621       fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
   622                        N->deopt_beg);
   624       fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
   625                        N->orig_pc_offset);
   627       fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n",
   628                        N->oops_beg, N->oops_end);
   630       fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
   631                        N->scopes_data_beg, N->scopes_data_end);
   633       fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
   634                        N->scopes_pcs_beg, N->scopes_pcs_end);
   636       fprintf(stderr, "\t nmethod_info: END \n\n");
   637   }
   638   return PS_OK;
   640  fail:
   641   return err;
   642 }
   644 static int
   645 raw_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;
   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);
   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;
   686  fail:
   687   return err;
   688 }
   690 static int
   691 read_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;
   698   if (debug > 2)
   699       fprintf(stderr, "\t\t read_pair: BEGIN\n");
   701   err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
   702   CHECK_FAIL(err);
   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");
   713       /* Escape character, regular compression used */
   715       err = raw_read_int(J, buffer, &bci_delta);
   716       CHECK_FAIL(err);
   718       err = raw_read_int(J, buffer, &line_delta);
   719       CHECK_FAIL(err);
   721       *bci  += bci_delta;
   722       *line += line_delta;
   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;
   745  fail:
   746   if (debug)
   747       fprintf(stderr, "\t\t read_pair: FAIL\n");
   748   return err;
   749 }
   751 static int
   752 line_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;
   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   }
   772   err = read_pointer(J, vf->methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
   773   CHECK_FAIL(err);
   775   vf->line = 0;
   776   err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_flags, &access_flags, sizeof(int8_t));
   777   CHECK_FAIL(err);
   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   }
   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    */
   789   err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_code_size, &code_size, SZ16);
   790   CHECK_FAIL(err);
   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;
   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   }
   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;
   826  fail:
   827   if (debug)
   828       fprintf(stderr, "\t line_number_from_bci: FAIL\n");
   829   return err;
   830 }
   832 static int
   833 get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
   834 {
   835   int32_t pc_offset;
   836   int32_t err;
   838   err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
   839   CHECK_FAIL(err);
   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;
   848  fail:
   849   return err;
   850 }
   852 /* Finds a PcDesc with real-pc equal to N->pc */
   853 static int pc_desc_at(Nmethod_t *N)
   854 {
   855   uint64_t pc_diff;
   856   int32_t offs;
   857   int32_t err;
   859   if (debug > 2)
   860       fprintf(stderr, "\t pc_desc_at: BEGIN\n");
   862   N->vf_cnt  = 0;
   863   N->pc_desc = 0;
   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;
   870       pd = N->nm + offs;
   871       err = get_real_pc(N, pd, &real_pc);
   872       CHECK_FAIL(err);
   874       pc_diff = real_pc - N->pc;
   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;
   901  fail:
   902   return err;
   903 }
   905 static int
   906 scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
   907 {
   908   uint64_t buffer;
   909   int32_t  err;
   911   if (debug > 2) {
   912       fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
   913   }
   915   buffer = N->nm + N->scopes_data_beg + decode_offset;
   917   err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
   918   CHECK_FAIL(err);
   920   err = raw_read_int(N->J, &buffer, &vf->methodIdx);
   921   CHECK_FAIL(err);
   923   err = raw_read_int(N->J, &buffer, &vf->bci);
   924   CHECK_FAIL(err);
   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);
   932       fprintf(stderr, "\t\t scope_desc_at: END \n\n");
   933   }
   934   return PS_OK;
   936  fail:
   937   return err;
   938 }
   940 static int scopeDesc_chain(Nmethod_t *N) {
   941   int32_t decode_offset = 0;
   942   int32_t err;
   944   if (debug > 2) {
   945     fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
   946   }
   948   err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
   949                  &decode_offset, SZ32);
   950   CHECK_FAIL(err);
   952   while (decode_offset > 0) {
   953     Vframe_t *vf = &N->vframes[N->vf_cnt];
   955     if (debug > 2) {
   956       fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
   957     }
   959     err = scope_desc_at(N, decode_offset, vf);
   960     CHECK_FAIL(err);
   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);
   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;
   986  fail:
   987   if (debug) {
   988     fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
   989   }
   990   return err;
   991 }
   994 static int
   995 name_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;
  1008   if (debug) {
  1009       fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
  1011   if (J->N == NULL) {
  1012     J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
  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;
  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);
  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");
  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;
  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);
  1045     deoptimized = 1;
  1048   err = pc_desc_at(N);
  1049   CHECK_FAIL(err);
  1051   if (N->pc_desc > 0) {
  1052       jframe->locinf = 1;
  1053       err = scopeDesc_chain(N);
  1054       CHECK_FAIL(err);
  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);
  1068   if (deoptimized) {
  1069     strncat(result + 1, " [deoptimized frame]; ", size-1);
  1070   } else {
  1071     strncat(result + 1, " [compiled] ", size-1);
  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;
  1078  fail:
  1079   if (debug)
  1080       fprintf(stderr, "name_for_nmethod: FAIL \n\n");
  1081   return err;
  1084 int 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;
  1094 static int
  1095 name_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;
  1108   err = read_pointer(J, methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
  1109   CHECK_FAIL(err);
  1111   bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_constMethodOopDesc);
  1113   if (debug)
  1114       fprintf(stderr, "\t name_for_imethod: BEGIN: methodOop: %#llx\n", methodOop);
  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);
  1121   if (bci > 0) {
  1122       vf->methodOop = methodOop;
  1123       vf->bci       = bci;
  1124       err = line_number_from_bci(J, vf);
  1125       CHECK_FAIL(err);
  1127   jframe->bci  = vf->bci;
  1128   jframe->line = vf->line;
  1129   jframe->locinf = 1;
  1131   if (debug) {
  1132       fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
  1133                       vf->bci, vf->line);
  1135   return PS_OK;
  1137  fail:
  1138   if (debug)
  1139       fprintf(stderr, "\t name_for_imethod: FAIL\n");
  1140   return err;
  1143 static int
  1144 name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
  1145                    size_t size, Jframe_t *jframe, int* is_interpreted)
  1147   uint64_t start;
  1148   uint64_t vtbl;
  1149   int32_t err;
  1150   *is_interpreted = 0;
  1152   result[0] = '\0';
  1154   err = find_start(J, pc, &start);
  1155   CHECK_FAIL(err);
  1157   err = read_pointer(J, start, &vtbl);
  1158   CHECK_FAIL(err);
  1160   if (vtbl == J->nmethod_vtbl) {
  1161     uint64_t methodOop;
  1163     err = read_pointer(J, start + OFFSET_nmethod_method, &methodOop);
  1164     CHECK_FAIL(err);
  1166     if (debug) {
  1167         fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, methodOop: %#8llx \n",
  1168                         start, pc, methodOop);
  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;
  1175     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  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);
  1189     if (err == PS_OK) {
  1190       strncpy(result, name, size);
  1191       free((void*)name);
  1192     } else {
  1193       strncpy(result, "<unknown BufferBlob>", size);
  1195     /* return PS_OK; */
  1196   } else {
  1197     const char * name;
  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);
  1208   result[size-1] = '\0';
  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);
  1218     // frame_size is in words, we want bytes.
  1219     frame_size *= POINTER_SIZE; /* word => byte conversion */
  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     */
  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);
  1253             prev_fp = base - 2 * POINTER_SIZE;
  1254             break;
  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;
  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);
  1284       err = read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1285       CHECK_FAIL(err);
  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);
  1294 #endif /* X86_COMPILER2 */
  1296   return PS_OK;
  1298  fail:
  1299   return err;
  1302 int Jget_vframe(jvm_agent_t* J, int vframe_no,
  1303                 char *name, size_t size, Jframe_t *jframe)
  1305   Nmethod_t *N = J->N;
  1306   Vframe_t  *vf;
  1307   int32_t   err;
  1309   if (vframe_no >= N->vf_cnt) {
  1310      (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
  1311      return -1;
  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);
  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);
  1324   return PS_OK;
  1326  fail:
  1327   if (debug) {
  1328       fprintf(stderr, "\t Jget_vframe: FAIL\n");
  1330   return err;
  1333 #define MAX_SYM_SIZE 256
  1335 int 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;
  1347   if (J == NULL) {
  1348     return -1;
  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;
  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];
  1364   if (debug)
  1365       fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
  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]);
  1380 #elif defined(i386) || defined(__i386) || defined(__amd64)
  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 */
  1391     if (debug > 2) {
  1392         printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
  1395     if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodOopPtr) != PS_OK) {
  1396       methodOopPtr = 0;
  1398     if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
  1399       sender_sp = 0;
  1401     if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
  1402       bcx = 0;
  1404 #endif /* i386 */
  1406   J->methodOopPtr = methodOopPtr;
  1407   J->bcx = bcx;
  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;
  1424   } else
  1425 #endif /* ! X86_COMPILER2 */
  1427   if (codecache_contains(J, pc)) {
  1428     result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
  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;
  1439 #endif /* X86_COMPILER2 */
  1440   else {
  1441     if (debug) {
  1442         fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
  1444     result = -1;
  1446   if (!is_interpreted) {
  1447     sender_sp = 0;
  1449   J->curr_fr.sender_sp = sender_sp;
  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];
  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);
  1465 #endif /* X86_COMPILER2 */
  1466   J->prev_fr = J->curr_fr;
  1468   if (debug)
  1469       fprintf(stderr, "Jlookup_by_regs: END\n\n");
  1471   return result;
  1473  fail:
  1474   return err;
  1477 void 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]);
  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;
  1492      if (jframe.new_fp) {
  1493          *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
  1495      if (jframe.new_pc) {
  1496          *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
  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]);
  1501 #endif  /* X86_COMPILER2 */
  1504 /*
  1505  * Iterates over java frames at current location given by 'gregs'.
  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  */
  1511 int 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]);
  1519 #endif  /* X86_COMPILER2 */
  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);
  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);
  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);
  1543     update_gregs(gregs, jframe);
  1544     return (0);

mercurial