src/os/solaris/dtrace/libjvm_db.c

Thu, 12 Mar 2009 10:37:46 -0700

author
kvn
date
Thu, 12 Mar 2009 10:37:46 -0700
changeset 1077
660978a2a31a
parent 631
d1605aabd0a1
child 1279
bd02caa94611
permissions
-rw-r--r--

6791178: Specialize for zero as the compressed oop vm heap base
Summary: Use zero based compressed oops if java heap is below 32gb and unscaled compressed oops if java heap is below 4gb.
Reviewed-by: never, twisti, jcoomes, coleenp

     1 /*
     2  * Copyright 2003-2008 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  */
    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;          /* _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;
   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_symbolOopDesc_length, &nameSymbolLength, 2);
   528   CHECK_FAIL(err);
   529   nameString = (char*)calloc(nameSymbolLength + 1, 1);
   530   err = ps_pread(J->P, nameSymbol + OFFSET_symbolOopDesc_body, nameString, nameSymbolLength);
   531   CHECK_FAIL(err);
   533   /* To get signature string */
   534   err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_signature_index, &signatureIndex, 2);
   535   CHECK_FAIL(err);
   536   err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol);
   537   CHECK_FAIL(err);
   538   err = ps_pread(J->P, signatureSymbol + OFFSET_symbolOopDesc_length, &signatureSymbolLength, 2);
   539   CHECK_FAIL(err);
   540   signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
   541   err = ps_pread(J->P, signatureSymbol + OFFSET_symbolOopDesc_body, signatureString, signatureSymbolLength);
   542   CHECK_FAIL(err);
   544   /* To get klass string */
   545   err = read_pointer(J, constantPool + OFFSET_constantPoolOopDesc_pool_holder, &klassPtr);
   546   CHECK_FAIL(err);
   547   err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol);
   548   CHECK_FAIL(err);
   549   err = ps_pread(J->P, klassSymbol + OFFSET_symbolOopDesc_length, &klassSymbolLength, 2);
   550   CHECK_FAIL(err);
   551   klassString = (char*)calloc(klassSymbolLength + 1, 1);
   552   err = ps_pread(J->P, klassSymbol + OFFSET_symbolOopDesc_body, klassString, klassSymbolLength);
   553   CHECK_FAIL(err);
   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_instructions_offset, &N->instrs_beg, SZ32);
   591   CHECK_FAIL(err);
   592   err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
   593   CHECK_FAIL(err);
   594   err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
   595   CHECK_FAIL(err);
   596   err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
   597   CHECK_FAIL(err);
   599   /* Oops */
   600   err = ps_pread(J->P, nm + OFFSET_CodeBlob_oops_offset, &N->oops_beg, SZ32);
   601   CHECK_FAIL(err);
   602   err = ps_pread(J->P, nm + OFFSET_CodeBlob_oops_length, &N->oops_len, 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_len: %#x\n",
   628                        N->oops_beg, N->oops_len);
   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
   941 scopeDesc_chain(Nmethod_t *N)
   942 {
   943   int32_t decode_offset = 0;
   944   int32_t err;
   946   if (debug > 2)
   947       fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
   949   err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
   950                  &decode_offset, SZ32);
   951   CHECK_FAIL(err);
   953   while (decode_offset > 0) {
   954       if (debug > 2)
   955           fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
   957       Vframe_t *vf = &N->vframes[N->vf_cnt];
   959       err = scope_desc_at(N, decode_offset, vf);
   960       CHECK_FAIL(err);
   962       if (vf->methodIdx > N->oops_len) {
   963           fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops_len) !\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   return PS_OK;
   985  fail:
   986   if (debug)
   987       fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
   988   return err;
   989 }
   992 static int
   993 name_for_nmethod(jvm_agent_t* J,
   994                  uint64_t nm,
   995                  uint64_t pc,
   996                  uint64_t methodOop,
   997                  char *result,
   998                  size_t size,
   999                  Jframe_t *jframe
  1000 ) {
  1001   Nmethod_t *N;
  1002   Vframe_t *vf;
  1003   int32_t err;
  1004   int deoptimized = 0;
  1006   if (debug) {
  1007       fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
  1009   if (J->N == NULL) {
  1010     J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
  1012   memset(J->N, 0, sizeof(Nmethod_t));   /* Initial stat: all values are zeros */
  1013   N     = J->N;
  1014   N->J  = J;
  1015   N->nm = nm;
  1016   N->pc = pc;
  1017   N->jframe = jframe;
  1019   err = nmethod_info(N);
  1020   CHECK_FAIL(err);
  1021   if (debug) {
  1022       fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc:  %#llx\n",
  1023               pc, N->nm + N->deopt_beg);
  1026   /* check for a deoptimized frame */
  1027   if ( pc == N->nm + N->deopt_beg) {
  1028     uint64_t base;
  1029     if (debug) {
  1030         fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
  1032     if (J->prev_fr.sender_sp != 0) {
  1033       base = J->prev_fr.sender_sp + N->orig_pc_offset;
  1034     } else {
  1035       base = J->curr_fr.sp + N->orig_pc_offset;
  1037     err = read_pointer(J, base, &N->pc);
  1038     CHECK_FAIL(err);
  1039     if (debug) {
  1040         fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
  1041         pc,  N->pc);
  1043     deoptimized = 1;
  1046   err = pc_desc_at(N);
  1047   CHECK_FAIL(err);
  1049   if (N->pc_desc > 0) {
  1050       jframe->locinf = 1;
  1051       err = scopeDesc_chain(N);
  1052       CHECK_FAIL(err);
  1054   result[0] = COMP_METHOD_SIGN;
  1055   vf = &N->vframes[0];
  1056   if (N->vf_cnt > 0) {
  1057       jframe->vf_cnt = N->vf_cnt;
  1058       jframe->bci  = vf->bci;
  1059       jframe->line = vf->line;
  1060       err = name_for_methodOop(J, N->vframes[0].methodOop, result+1, size-1);
  1061       CHECK_FAIL(err);
  1062   } else {
  1063       err = name_for_methodOop(J, methodOop, result+1, size-1);
  1064       CHECK_FAIL(err);
  1066   if (deoptimized) {
  1067     strncat(result + 1, " [deoptimized frame]; ", size-1);
  1068   } else {
  1069     strncat(result + 1, " [compiled] ", size-1);
  1071   if (debug)
  1072       fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
  1073                       result, N->vf_cnt);
  1074   return PS_OK;
  1076  fail:
  1077   if (debug)
  1078       fprintf(stderr, "name_for_nmethod: FAIL \n\n");
  1079   return err;
  1082 int is_bci(intptr_t bcx) {
  1083   switch (DATA_MODEL) {
  1084   case PR_MODEL_LP64:
  1085     return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
  1086   case PR_MODEL_ILP32:
  1087   default:
  1088     return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
  1092 static int
  1093 name_for_imethod(jvm_agent_t* J,
  1094                  uint64_t bcx,
  1095                  uint64_t methodOop,
  1096                  char *result,
  1097                  size_t size,
  1098                  Jframe_t *jframe
  1099 ) {
  1100   uint64_t bci;
  1101   uint64_t constMethod;
  1102   Vframe_t vframe = {0};
  1103   Vframe_t *vf = &vframe;
  1104   int32_t   err;
  1106   err = read_pointer(J, methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
  1107   CHECK_FAIL(err);
  1109   bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_constMethodOopDesc);
  1111   if (debug)
  1112       fprintf(stderr, "\t name_for_imethod: BEGIN: methodOop: %#llx\n", methodOop);
  1114   err = name_for_methodOop(J, methodOop, result, size);
  1115   CHECK_FAIL(err);
  1116   if (debug)
  1117       fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
  1119   if (bci > 0) {
  1120       vf->methodOop = methodOop;
  1121       vf->bci       = bci;
  1122       err = line_number_from_bci(J, vf);
  1123       CHECK_FAIL(err);
  1125   jframe->bci  = vf->bci;
  1126   jframe->line = vf->line;
  1127   jframe->locinf = 1;
  1129   if (debug) {
  1130       fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
  1131                       vf->bci, vf->line);
  1133   return PS_OK;
  1135  fail:
  1136   if (debug)
  1137       fprintf(stderr, "\t name_for_imethod: FAIL\n");
  1138   return err;
  1141 static int
  1142 name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
  1143                    size_t size, Jframe_t *jframe, int* is_interpreted)
  1145   uint64_t start;
  1146   uint64_t vtbl;
  1147   int32_t err;
  1148   *is_interpreted = 0;
  1150   result[0] = '\0';
  1152   err = find_start(J, pc, &start);
  1153   CHECK_FAIL(err);
  1155   err = read_pointer(J, start, &vtbl);
  1156   CHECK_FAIL(err);
  1158   if (vtbl == J->nmethod_vtbl) {
  1159     uint64_t methodOop;
  1161     err = read_pointer(J, start + OFFSET_nmethod_method, &methodOop);
  1162     CHECK_FAIL(err);
  1164     if (debug) {
  1165         fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, methodOop: %#8llx \n",
  1166                         start, pc, methodOop);
  1168     err = name_for_nmethod(J, start, pc, methodOop, result, size, jframe);
  1169     CHECK_FAIL(err);
  1170   } else if (vtbl == J->BufferBlob_vtbl) {
  1171     const char * name;
  1173     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  1175     /*
  1176      * Temporary usage of string "Interpreter".
  1177      * We need some other way to distinguish "StubRoutines"
  1178      * and regular interpreted frames.
  1179      */
  1180     if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
  1181       *is_interpreted = 1;
  1182       if (is_methodOop(J, J->methodOopPtr)) {
  1183         return name_for_imethod(J, J->bcx, J->methodOopPtr, result, size, jframe);
  1187     if (err == PS_OK) {
  1188       strncpy(result, name, size);
  1189       free((void*)name);
  1190     } else {
  1191       strncpy(result, "<unknown BufferBlob>", size);
  1193     /* return PS_OK; */
  1194   } else {
  1195     const char * name;
  1197     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  1198     if (err == PS_OK) {
  1199       strncpy(result, name, size);
  1200       free((void*)name);
  1201     } else {
  1202       strncpy(result, "<unknown CodeBlob>", size);
  1203       WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
  1206   result[size-1] = '\0';
  1208 #ifdef X86_COMPILER2
  1209   if (vtbl != J->RuntimeStub_vtbl) {
  1210     uint64_t trial_pc;
  1211     int frame_size;
  1212     err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
  1213                          &frame_size, SZ32);
  1214     CHECK_FAIL(err);
  1216     // frame_size is in words, we want bytes.
  1217     frame_size *= POINTER_SIZE; /* word => byte conversion */
  1219     /*
  1220       Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
  1221       in the initial entry to a set of stack frames containing server frames
  1222       will pretty much be nonsense. We can detect that nonsense by looking to
  1223       see if the PC we received is correct if we look at the expected storage
  1224       location in relation to the FP (ie. POINTER_SIZE(FP) )
  1225     */
  1227     err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
  1228     if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
  1229       // Either we couldn't even read at the "fp" or the pc didn't match
  1230       // both are sure clues that the fp is bogus. We no search the stack
  1231       // for a reasonable number of words trying to find the bogus fp
  1232       // and the current pc in adjacent words. The we will be able to
  1233       // deduce an approximation of the frame pointer and actually get
  1234       // the correct stack pointer. Which we can then unwind for the
  1235       // next frame.
  1236       int i;
  1237       uint64_t check;
  1238       uint64_t base = J->curr_fr.sp;
  1239       uint64_t prev_fp = 0;
  1240       for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
  1241         err = read_pointer(J, base , &check);
  1242         CHECK_FAIL(err);
  1243         if (check == fp) {
  1244           base += POINTER_SIZE;
  1245           err = read_pointer(J, base , &check);
  1246           CHECK_FAIL(err);
  1247           if (check == pc) {
  1248             if (debug) {
  1249               fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
  1251             prev_fp = base - 2 * POINTER_SIZE;
  1252             break;
  1256       if ( prev_fp != 0 ) {
  1257         // real_sp is the sp we should have received for this frame
  1258         uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
  1259         // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
  1260         jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
  1261         err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
  1262         CHECK_FAIL(err);
  1263         err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
  1264         CHECK_FAIL(err);
  1265         return PS_OK;
  1269     /* A prototype to workaround FP absence */
  1270     /*
  1271      * frame_size can be 0 for StubRoutines (1) frame.
  1272      * In this case it should work with fp as usual.
  1273      */
  1274     if (frame_size > 0) {
  1275       jframe->new_fp = J->prev_fr.fp + frame_size;
  1276       jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
  1277     } else {
  1278       memset(&J->curr_fr, 0, sizeof(Frame_t));
  1279       err = read_pointer(J,  fp, &jframe->new_fp);
  1280       CHECK_FAIL(err);
  1282       err = read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1283       CHECK_FAIL(err);
  1285     if (debug) {
  1286       fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
  1287                        result, frame_size);
  1288       fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
  1289                        J->prev_fr.fp, jframe->new_fp);
  1292 #endif /* X86_COMPILER2 */
  1294   return PS_OK;
  1296  fail:
  1297   return err;
  1300 int Jget_vframe(jvm_agent_t* J, int vframe_no,
  1301                 char *name, size_t size, Jframe_t *jframe)
  1303   Nmethod_t *N = J->N;
  1304   Vframe_t  *vf;
  1305   int32_t   err;
  1307   if (vframe_no >= N->vf_cnt) {
  1308      (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
  1309      return -1;
  1311   vf = N->vframes + vframe_no;
  1312   name[0] = COMP_METHOD_SIGN;
  1313   err = name_for_methodOop(J, vf->methodOop, name + 1, size);
  1314   CHECK_FAIL(err);
  1316   jframe->bci = vf->bci;
  1317   jframe->line = vf->line;
  1318   if (debug) {
  1319       fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
  1320                        name, vf->line);
  1322   return PS_OK;
  1324  fail:
  1325   if (debug) {
  1326       fprintf(stderr, "\t Jget_vframe: FAIL\n");
  1328   return err;
  1331 #define MAX_SYM_SIZE 256
  1333 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
  1334                     size_t size, Jframe_t *jframe) {
  1335   uintptr_t fp;
  1336   uintptr_t pc;
  1337   /* arguments given to read_pointer need to be worst case sized */
  1338   uint64_t methodOopPtr = 0;
  1339   uint64_t sender_sp;
  1340   uint64_t bcx = 0;
  1341   int is_interpreted = 0;
  1342   int result = PS_OK;
  1343   int err = PS_OK;
  1345   if (J == NULL) {
  1346     return -1;
  1349   jframe->vf_cnt = 1;
  1350   jframe->new_fp = 0;
  1351   jframe->new_pc = 0;
  1352   jframe->line   = 0;
  1353   jframe->bci    = 0;
  1354   jframe->locinf = 0;
  1356   read_volatiles(J);
  1357   pc = (uintptr_t) regs[R_PC];
  1358   J->curr_fr.pc = pc;
  1359   J->curr_fr.fp = regs[R_FP];
  1360   J->curr_fr.sp = regs[R_SP];
  1362   if (debug)
  1363       fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
  1365 #if defined(sparc) || defined(__sparc)
  1366     /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
  1367      * In the pcDesc structure return pc offset is recorded for CALL instructions.
  1368      * regs[R_PC] contains a CALL instruction pc offset.
  1369      */
  1370     pc += 8;
  1371     bcx          = (uintptr_t) regs[R_L1];
  1372     methodOopPtr = (uintptr_t) regs[R_L2];
  1373     sender_sp = regs[R_I5];
  1374     if (debug > 2) {
  1375         fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
  1376                          regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
  1378 #elif defined(i386) || defined(__i386) || defined(__amd64)
  1380     fp = (uintptr_t) regs[R_FP];
  1381     if (J->prev_fr.fp == 0) {
  1382 #ifdef X86_COMPILER2
  1383         /* A workaround for top java frames */
  1384         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
  1385 #else
  1386         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
  1387 #endif /* COMPILER2 */
  1389     if (debug > 2) {
  1390         printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
  1393     if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodOopPtr) != PS_OK) {
  1394       methodOopPtr = 0;
  1396     if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
  1397       sender_sp = 0;
  1399     if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
  1400       bcx = 0;
  1402 #endif /* i386 */
  1404   J->methodOopPtr = methodOopPtr;
  1405   J->bcx = bcx;
  1407   /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
  1408    * For example: JVM_SuspendThread frame poins to the top interpreted frame.
  1409    * If we call is_methodOop(J, methodOopPtr) before codecache_contains(J, pc)
  1410    * then we go over and omit both: nmethod and I2CAdapter frames.
  1411    * Note, that regs[R_PC] is always correct if frame defined correctly.
  1412    * So it is better to call codecache_contains(J, pc) from the beginning.
  1413    */
  1414 #ifndef X86_COMPILER2
  1415   if (is_methodOop(J, J->methodOopPtr)) {
  1416     result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe);
  1417     /* If the methodOopPtr is a method then this is highly likely to be
  1418        an interpreter frame */
  1419     if (result >= 0) {
  1420       is_interpreted = 1;
  1422   } else
  1423 #endif /* ! X86_COMPILER2 */
  1425   if (codecache_contains(J, pc)) {
  1426     result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
  1428 #ifdef X86_COMPILER2
  1429   else if (is_methodOop(J, J->methodOopPtr)) {
  1430     result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe);
  1431     /* If the methodOopPtr is a method then this is highly likely to be
  1432        an interpreter frame */
  1433     if (result >= 0) {
  1434       is_interpreted = 1;
  1437 #endif /* X86_COMPILER2 */
  1438   else {
  1439     if (debug) {
  1440         fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
  1442     result = -1;
  1444   if (!is_interpreted) {
  1445     sender_sp = 0;
  1447   J->curr_fr.sender_sp = sender_sp;
  1449 #ifdef X86_COMPILER2
  1450   if (!J->curr_fr.fp) {
  1451     J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
  1453   if (!jframe->new_pc && jframe->new_fp) {
  1454     // This seems dubious
  1455     read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1456     CHECK_FAIL(err);
  1457     if (debug > 2) {
  1458         printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
  1459                jframe->new_fp, jframe->new_pc);
  1463 #endif /* X86_COMPILER2 */
  1464   J->prev_fr = J->curr_fr;
  1466   if (debug)
  1467       fprintf(stderr, "Jlookup_by_regs: END\n\n");
  1469   return result;
  1471  fail:
  1472   return err;
  1475 void update_gregs(prgregset_t gregs, Jframe_t jframe) {
  1476 #ifdef X86_COMPILER2
  1477     if (debug > 0) {
  1478       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]);
  1480     /*
  1481      * A workaround for java C2 frames with unconventional FP.
  1482      * may have to modify regset with new values for FP/PC/SP when needed.
  1483      */
  1484      if (jframe.new_sp) {
  1485          *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
  1486      } else {
  1487          // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
  1490      if (jframe.new_fp) {
  1491          *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
  1493      if (jframe.new_pc) {
  1494          *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
  1496     if (debug > 0) {
  1497       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]);
  1499 #endif  /* X86_COMPILER2 */
  1502 /*
  1503  * Iterates over java frames at current location given by 'gregs'.
  1505  *  Returns -1 if no java frames are present or if an error is encountered.
  1506  *  Returns the result of calling 'func' if the return value is non-zero.
  1507  *  Returns 0 otherwise.
  1508  */
  1509 int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
  1510     char buf[MAX_SYM_SIZE + 1];
  1511     Jframe_t jframe;
  1512     int i = 0, res;
  1513 #ifdef X86_COMPILER2
  1514     if (debug > 0) {
  1515       fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
  1517 #endif  /* X86_COMPILER2 */
  1519     memset(&jframe, 0, sizeof(Jframe_t));
  1520     memset(buf, 0, sizeof(buf));
  1521     res =  Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
  1522     if (res != PS_OK)
  1523         return (-1);
  1526     res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
  1527                jframe.line, NULL);
  1528     if (res != 0) {
  1529         update_gregs(gregs, jframe);
  1530         return (res);
  1532     for (i = 1; i < jframe.vf_cnt; i++) {
  1533         Jget_vframe(J, i, buf, sizeof(buf), &jframe);
  1534         res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
  1535                    jframe.line, NULL);
  1536         if (res != 0) {
  1537             update_gregs(gregs, jframe);
  1538             return (res);
  1541     update_gregs(gregs, jframe);
  1542     return (0);

mercurial