src/os/solaris/dtrace/libjvm_db.c

Tue, 05 Apr 2011 14:12:31 -0700

author
trims
date
Tue, 05 Apr 2011 14:12:31 -0700
changeset 2708
1d1603768966
parent 2626
8a3f8defe568
child 3826
2fe087c3e814
permissions
-rw-r--r--

7010070: Update all 2010 Oracle-changed OpenJDK files to have the proper copyright dates - second pass
Summary: Update the copyright to be 2010 on all changed files in OpenJDK
Reviewed-by: ohair

     1 /*
     2  * Copyright (c) 2003, 2011, 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   // The symbol is a CPSlot and has lower bit set to indicate metadata
   528   nameSymbol &= (~1); // remove metadata lsb
   529   err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2);
   530   CHECK_FAIL(err);
   531   nameString = (char*)calloc(nameSymbolLength + 1, 1);
   532   err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength);
   533   CHECK_FAIL(err);
   535   /* To get signature string */
   536   err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_signature_index, &signatureIndex, 2);
   537   CHECK_FAIL(err);
   538   err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_constantPoolOopDesc, &signatureSymbol);
   539   CHECK_FAIL(err);
   540   signatureSymbol &= (~1);  // remove metadata lsb
   541   err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2);
   542   CHECK_FAIL(err);
   543   signatureString = (char*)calloc(signatureSymbolLength + 1, 1);
   544   err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength);
   545   CHECK_FAIL(err);
   547   /* To get klass string */
   548   err = read_pointer(J, constantPool + OFFSET_constantPoolOopDesc_pool_holder, &klassPtr);
   549   CHECK_FAIL(err);
   550   err = read_pointer(J, klassPtr + OFFSET_Klass_name + SIZE_oopDesc, &klassSymbol);
   551   CHECK_FAIL(err);
   552   err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2);
   553   CHECK_FAIL(err);
   554   klassString = (char*)calloc(klassSymbolLength + 1, 1);
   555   err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength);
   556   CHECK_FAIL(err);
   558   result[0] = '\0';
   559   strncat(result, klassString, size);
   560   size -= strlen(klassString);
   561   strncat(result, ".", size);
   562   size -= 1;
   563   strncat(result, nameString, size);
   564   size -= strlen(nameString);
   565   strncat(result, signatureString, size);
   567   if (nameString != NULL) free(nameString);
   568   if (klassString != NULL) free(klassString);
   569   if (signatureString != NULL) free(signatureString);
   571   return PS_OK;
   573  fail:
   574   if (debug) {
   575       fprintf(stderr, "name_for_methodOop: FAIL \n\n");
   576   }
   577   if (nameString != NULL) free(nameString);
   578   if (klassString != NULL) free(klassString);
   579   if (signatureString != NULL) free(signatureString);
   580   return -1;
   581 }
   583 static int nmethod_info(Nmethod_t *N)
   584 {
   585   jvm_agent_t *J = N->J;
   586   uint64_t    nm = N->nm;
   587   int32_t err;
   589   if (debug > 2 )
   590       fprintf(stderr, "\t nmethod_info: BEGIN \n");
   592   /* Instructions */
   593   err = ps_pread(J->P, nm + OFFSET_CodeBlob_code_offset, &N->instrs_beg, SZ32);
   594   CHECK_FAIL(err);
   595   err = ps_pread(J->P, nm + OFFSET_CodeBlob_data_offset, &N->instrs_end, SZ32);
   596   CHECK_FAIL(err);
   597   err = ps_pread(J->P, nm + OFFSET_nmethod_deoptimize_offset, &N->deopt_beg, SZ32);
   598   CHECK_FAIL(err);
   599   err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32);
   600   CHECK_FAIL(err);
   602   /* Oops */
   603   err = ps_pread(J->P, nm + OFFSET_nmethod_oops_offset, &N->oops_beg, SZ32);
   604   CHECK_FAIL(err);
   605   err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->oops_end, SZ32);
   606   CHECK_FAIL(err);
   608   /* scopes_pcs */
   609   err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32);
   610   CHECK_FAIL(err);
   611   err = ps_pread(J->P, nm + OFFSET_nmethod_handler_table_offset, &N->scopes_pcs_end, SZ32);
   612   CHECK_FAIL(err);
   614   /* scopes_data */
   615   err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_offset, &N->scopes_data_beg, SZ32);
   616   CHECK_FAIL(err);
   618   if (debug > 2 ) {
   619       N->scopes_data_end = N->scopes_pcs_beg;
   621       fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n",
   622                        N->instrs_beg, N->instrs_end);
   624       fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n",
   625                        N->deopt_beg);
   627       fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n",
   628                        N->orig_pc_offset);
   630       fprintf(stderr, "\t nmethod_info: oops_beg: %#x, oops_end: %#x\n",
   631                        N->oops_beg, N->oops_end);
   633       fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n",
   634                        N->scopes_data_beg, N->scopes_data_end);
   636       fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n",
   637                        N->scopes_pcs_beg, N->scopes_pcs_end);
   639       fprintf(stderr, "\t nmethod_info: END \n\n");
   640   }
   641   return PS_OK;
   643  fail:
   644   return err;
   645 }
   647 static int
   648 raw_read_int(jvm_agent_t* J, uint64_t *buffer, int32_t *val)
   649 {
   650   int shift = 0;
   651   int value = 0;
   652   uint8_t ch = 0;
   653   int32_t  err;
   654   int32_t sum;
   655   // Constants for UNSIGNED5 coding of Pack200
   656   // see compressedStream.hpp
   657   enum {
   658     lg_H = 6,
   659     H = 1<<lg_H,
   660     BitsPerByte = 8,
   661     L = (1<<BitsPerByte)-H,
   662   };
   663   int i;
   665   err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
   666   CHECK_FAIL(err);
   667   if (debug > 2)
   668       fprintf(stderr, "\t\t\t raw_read_int: *buffer: %#llx, ch: %#x\n", *buffer, ch);
   670   sum = ch;
   671   if ( sum >= L ) {
   672     int32_t lg_H_i = lg_H;
   673     // Read maximum of 5 total bytes (we've already read 1).
   674     // See CompressedReadStream::read_int_mb
   675     for ( i = 0;  i < 4; i++) {
   676       err = ps_pread(J->P, (*buffer)++, &ch, sizeof(uint8_t));
   677       CHECK_FAIL(err);
   678       sum += ch << lg_H_i;
   679       if (ch < L ) {
   680         *val = sum;
   681         return PS_OK;
   682       }
   683       lg_H_i += lg_H;
   684     }
   685   }
   686   *val = sum;
   687   return PS_OK;
   689  fail:
   690   return err;
   691 }
   693 static int
   694 read_pair(jvm_agent_t* J, uint64_t *buffer, int32_t *bci, int32_t *line)
   695 {
   696   uint8_t next = 0;
   697   int32_t bci_delta;
   698   int32_t line_delta;
   699   int32_t err;
   701   if (debug > 2)
   702       fprintf(stderr, "\t\t read_pair: BEGIN\n");
   704   err = ps_pread(J->P, (*buffer)++, &next, sizeof(uint8_t));
   705   CHECK_FAIL(err);
   707   if (next == 0) {
   708       if (debug > 2)
   709           fprintf(stderr, "\t\t read_pair: END: next == 0\n");
   710       return 1; /* stream terminated */
   711   }
   712   if (next == 0xFF) {
   713       if (debug > 2)
   714           fprintf(stderr, "\t\t read_pair: END: next == 0xFF\n");
   716       /* Escape character, regular compression used */
   718       err = raw_read_int(J, buffer, &bci_delta);
   719       CHECK_FAIL(err);
   721       err = raw_read_int(J, buffer, &line_delta);
   722       CHECK_FAIL(err);
   724       *bci  += bci_delta;
   725       *line += line_delta;
   727       if (debug > 2) {
   728           fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
   729                           line_delta, bci_delta);
   730           fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
   731                           *line, *bci);
   732       }
   733   } else {
   734       /* Single byte compression used */
   735       *bci  += next >> 3;
   736       *line += next & 0x7;
   737       if (debug > 2) {
   738           fprintf(stderr, "\t\t read_pair: delta = (line %d: %d)\n",
   739                           next & 0x7, next >> 3);
   740           fprintf(stderr, "\t\t read_pair: unpack= (line %d: %d)\n",
   741                           *line, *bci);
   742       }
   743   }
   744   if (debug > 2)
   745       fprintf(stderr, "\t\t read_pair: END\n");
   746   return PS_OK;
   748  fail:
   749   if (debug)
   750       fprintf(stderr, "\t\t read_pair: FAIL\n");
   751   return err;
   752 }
   754 static int
   755 line_number_from_bci(jvm_agent_t* J, Vframe_t *vf)
   756 {
   757   uint64_t buffer;
   758   uint16_t code_size;
   759   uint64_t code_end_delta;
   760   uint64_t constMethod;
   761   int8_t   access_flags;
   762   int32_t  best_bci    = 0;
   763   int32_t  stream_bci  = 0;
   764   int32_t  stream_line = 0;
   765   int32_t  err;
   767   if (debug > 2) {
   768       char name[256];
   769       err = name_for_methodOop(J, vf->methodOop, name, 256);
   770       CHECK_FAIL(err);
   771       fprintf(stderr, "\t line_number_from_bci: BEGIN, method name: %s, targ bci: %d\n",
   772                        name, vf->bci);
   773   }
   775   err = read_pointer(J, vf->methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
   776   CHECK_FAIL(err);
   778   vf->line = 0;
   779   err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_flags, &access_flags, sizeof(int8_t));
   780   CHECK_FAIL(err);
   782   if (!(access_flags & constMethodOopDesc_has_linenumber_table)) {
   783       if (debug > 2)
   784           fprintf(stderr, "\t line_number_from_bci: END: !HAS_LINE_NUMBER_TABLE \n\n");
   785       return PS_OK;
   786   }
   788   /*  The line numbers are a short array of 2-tuples [start_pc, line_number].
   789    *  Not necessarily sorted and not necessarily one-to-one.
   790    */
   792   err = ps_pread(J->P, constMethod + OFFSET_constMethodOopDesc_code_size, &code_size, SZ16);
   793   CHECK_FAIL(err);
   795   /* inlined_table_start() */
   796   code_end_delta = (uint64_t) (access_flags & AccessFlags_NATIVE) ? 2*POINTER_SIZE : 0;
   797   buffer = constMethod + (uint64_t) SIZE_constMethodOopDesc + (uint64_t) code_size + code_end_delta;
   799   if (debug > 2) {
   800       fprintf(stderr, "\t\t line_number_from_bci: methodOop: %#llx, native: %d\n",
   801                       vf->methodOop, (access_flags & AccessFlags_NATIVE));
   802       fprintf(stderr, "\t\t line_number_from_bci: buffer: %#llx, code_size: %d\n",
   803                       buffer, (int) code_size);
   804   }
   806   while (read_pair(J, &buffer, &stream_bci, &stream_line) == 0) {
   807       if (stream_bci == vf->bci) {
   808           /* perfect match */
   809           if (debug > 2)
   810               fprintf(stderr, "\t line_number_from_bci: END: exact line: %ld \n\n", vf->line);
   811           vf->line = stream_line;
   812           return PS_OK;
   813       } else {
   814           /* update best_bci/line */
   815           if (stream_bci < vf->bci && stream_bci >= best_bci) {
   816               best_bci = stream_bci;
   817               vf->line = stream_line;
   818               if (debug > 2) {
   819                   fprintf(stderr, "\t line_number_from_bci: best_bci: %ld, best_line: %ld\n",
   820                                    best_bci, vf->line);
   821               }
   822           }
   823       }
   824   }
   825   if (debug > 2)
   826       fprintf(stderr, "\t line_number_from_bci: END: line: %ld \n\n", vf->line);
   827   return PS_OK;
   829  fail:
   830   if (debug)
   831       fprintf(stderr, "\t line_number_from_bci: FAIL\n");
   832   return err;
   833 }
   835 static int
   836 get_real_pc(Nmethod_t *N, uint64_t pc_desc, uint64_t *real_pc)
   837 {
   838   int32_t pc_offset;
   839   int32_t err;
   841   err = ps_pread(N->J->P, pc_desc + OFFSET_PcDesc_pc_offset, &pc_offset, SZ32);
   842   CHECK_FAIL(err);
   844   *real_pc = N->nm + N->instrs_beg + pc_offset;
   845   if (debug > 2) {
   846       fprintf(stderr, "\t\t get_real_pc: pc_offset: %lx, real_pc: %llx\n",
   847                        pc_offset, *real_pc);
   848   }
   849   return PS_OK;
   851  fail:
   852   return err;
   853 }
   855 /* Finds a PcDesc with real-pc equal to N->pc */
   856 static int pc_desc_at(Nmethod_t *N)
   857 {
   858   uint64_t pc_diff;
   859   int32_t offs;
   860   int32_t err;
   862   if (debug > 2)
   863       fprintf(stderr, "\t pc_desc_at: BEGIN\n");
   865   N->vf_cnt  = 0;
   866   N->pc_desc = 0;
   868   for (offs = N->scopes_pcs_beg; offs < N->scopes_pcs_end; offs += SIZE_PcDesc) {
   869       uint64_t pd;
   870       uint64_t best_pc_diff = 16;       /* some approximation */
   871       uint64_t real_pc = 0;
   873       pd = N->nm + offs;
   874       err = get_real_pc(N, pd, &real_pc);
   875       CHECK_FAIL(err);
   877       pc_diff = real_pc - N->pc;
   879       /* In general, this fragment should work */
   880       if (pc_diff == 0) {
   881           N->pc_desc = pd;
   882           if (debug) {
   883             fprintf(stderr, "\t pc_desc_at: END: pc_desc: FOUND: %#lx \n\n", pd);
   884           }
   885           return PS_OK;
   886       }
   887       /* This fragment is to be able to find out an appropriate
   888        * pc_desc entry even if pc_desc info is inaccurate.
   889        */
   890       if (best_pc_diff > pc_diff && pc_diff > 0) {
   891           best_pc_diff = pc_diff;
   892           N->pc_desc = pd;
   893       }
   894   }
   895   if (debug) {
   896       fprintf(stderr, "\t pc_desc_at: END: pc_desc NOT FOUND");
   897       if (pc_diff < 20)
   898           fprintf(stderr, ", best pc_diff: %d\n\n", pc_diff);
   899       else
   900           fprintf(stderr, "\n\n");
   901   }
   902   return PS_OK;
   904  fail:
   905   return err;
   906 }
   908 static int
   909 scope_desc_at(Nmethod_t *N, int32_t decode_offset, Vframe_t *vf)
   910 {
   911   uint64_t buffer;
   912   int32_t  err;
   914   if (debug > 2) {
   915       fprintf(stderr, "\t\t scope_desc_at: BEGIN \n");
   916   }
   918   buffer = N->nm + N->scopes_data_beg + decode_offset;
   920   err = raw_read_int(N->J, &buffer, &vf->sender_decode_offset);
   921   CHECK_FAIL(err);
   923   err = raw_read_int(N->J, &buffer, &vf->methodIdx);
   924   CHECK_FAIL(err);
   926   err = raw_read_int(N->J, &buffer, &vf->bci);
   927   CHECK_FAIL(err);
   929   if (debug > 2) {
   930       fprintf(stderr, "\t\t scope_desc_at: sender_decode_offset: %#x\n",
   931                       vf->sender_decode_offset);
   932       fprintf(stderr, "\t\t scope_desc_at: methodIdx: %d\n", vf->methodIdx);
   933       fprintf(stderr, "\t\t scope_desc_at: bci: %d\n", vf->bci);
   935       fprintf(stderr, "\t\t scope_desc_at: END \n\n");
   936   }
   937   return PS_OK;
   939  fail:
   940   return err;
   941 }
   943 static int scopeDesc_chain(Nmethod_t *N) {
   944   int32_t decode_offset = 0;
   945   int32_t err;
   947   if (debug > 2) {
   948     fprintf(stderr, "\t scopeDesc_chain: BEGIN\n");
   949   }
   951   err = ps_pread(N->J->P, N->pc_desc + OFFSET_PcDesc_scope_decode_offset,
   952                  &decode_offset, SZ32);
   953   CHECK_FAIL(err);
   955   while (decode_offset > 0) {
   956     Vframe_t *vf = &N->vframes[N->vf_cnt];
   958     if (debug > 2) {
   959       fprintf(stderr, "\t scopeDesc_chain: decode_offset: %#x\n", decode_offset);
   960     }
   962     err = scope_desc_at(N, decode_offset, vf);
   963     CHECK_FAIL(err);
   965     if (vf->methodIdx > ((N->oops_end - N->oops_beg) / POINTER_SIZE)) {
   966       fprintf(stderr, "\t scopeDesc_chain: (methodIdx > oops length) !\n");
   967       return -1;
   968     }
   969     err = read_pointer(N->J, N->nm + N->oops_beg + (vf->methodIdx-1)*POINTER_SIZE,
   970                        &vf->methodOop);
   971     CHECK_FAIL(err);
   973     if (vf->methodOop) {
   974       N->vf_cnt++;
   975       err = line_number_from_bci(N->J, vf);
   976       CHECK_FAIL(err);
   977       if (debug > 2) {
   978         fprintf(stderr, "\t scopeDesc_chain: methodOop: %#8llx, line: %ld\n",
   979                 vf->methodOop, vf->line);
   980       }
   981     }
   982     decode_offset = vf->sender_decode_offset;
   983   }
   984   if (debug > 2) {
   985     fprintf(stderr, "\t scopeDesc_chain: END \n\n");
   986   }
   987   return PS_OK;
   989  fail:
   990   if (debug) {
   991     fprintf(stderr, "\t scopeDesc_chain: FAIL \n\n");
   992   }
   993   return err;
   994 }
   997 static int
   998 name_for_nmethod(jvm_agent_t* J,
   999                  uint64_t nm,
  1000                  uint64_t pc,
  1001                  uint64_t methodOop,
  1002                  char *result,
  1003                  size_t size,
  1004                  Jframe_t *jframe
  1005 ) {
  1006   Nmethod_t *N;
  1007   Vframe_t *vf;
  1008   int32_t err;
  1009   int deoptimized = 0;
  1011   if (debug) {
  1012       fprintf(stderr, "name_for_nmethod: BEGIN: nmethod: %#llx, pc: %#llx\n", nm, pc);
  1014   if (J->N == NULL) {
  1015     J->N = (Nmethod_t *) malloc(sizeof(Nmethod_t));
  1017   memset(J->N, 0, sizeof(Nmethod_t));   /* Initial stat: all values are zeros */
  1018   N     = J->N;
  1019   N->J  = J;
  1020   N->nm = nm;
  1021   N->pc = pc;
  1022   N->jframe = jframe;
  1024   err = nmethod_info(N);
  1025   CHECK_FAIL(err);
  1026   if (debug) {
  1027       fprintf(stderr, "name_for_nmethod: pc: %#llx, deopt_pc:  %#llx\n",
  1028               pc, N->nm + N->deopt_beg);
  1031   /* check for a deoptimized frame */
  1032   if ( pc == N->nm + N->deopt_beg) {
  1033     uint64_t base;
  1034     if (debug) {
  1035         fprintf(stderr, "name_for_nmethod: found deoptimized frame\n");
  1037     if (J->prev_fr.sender_sp != 0) {
  1038       base = J->prev_fr.sender_sp + N->orig_pc_offset;
  1039     } else {
  1040       base = J->curr_fr.sp + N->orig_pc_offset;
  1042     err = read_pointer(J, base, &N->pc);
  1043     CHECK_FAIL(err);
  1044     if (debug) {
  1045         fprintf(stderr, "name_for_nmethod: found deoptimized frame converting pc from %#8llx to %#8llx\n",
  1046         pc,  N->pc);
  1048     deoptimized = 1;
  1051   err = pc_desc_at(N);
  1052   CHECK_FAIL(err);
  1054   if (N->pc_desc > 0) {
  1055       jframe->locinf = 1;
  1056       err = scopeDesc_chain(N);
  1057       CHECK_FAIL(err);
  1059   result[0] = COMP_METHOD_SIGN;
  1060   vf = &N->vframes[0];
  1061   if (N->vf_cnt > 0) {
  1062       jframe->vf_cnt = N->vf_cnt;
  1063       jframe->bci  = vf->bci;
  1064       jframe->line = vf->line;
  1065       err = name_for_methodOop(J, N->vframes[0].methodOop, result+1, size-1);
  1066       CHECK_FAIL(err);
  1067   } else {
  1068       err = name_for_methodOop(J, methodOop, result+1, size-1);
  1069       CHECK_FAIL(err);
  1071   if (deoptimized) {
  1072     strncat(result + 1, " [deoptimized frame]; ", size-1);
  1073   } else {
  1074     strncat(result + 1, " [compiled] ", size-1);
  1076   if (debug)
  1077       fprintf(stderr, "name_for_nmethod: END: method name: %s, vf_cnt: %d\n\n",
  1078                       result, N->vf_cnt);
  1079   return PS_OK;
  1081  fail:
  1082   if (debug)
  1083       fprintf(stderr, "name_for_nmethod: FAIL \n\n");
  1084   return err;
  1087 int is_bci(intptr_t bcx) {
  1088   switch (DATA_MODEL) {
  1089   case PR_MODEL_LP64:
  1090     return ((uintptr_t) bcx) <= ((uintptr_t) MAX_METHOD_CODE_SIZE) ;
  1091   case PR_MODEL_ILP32:
  1092   default:
  1093     return 0 <= bcx && bcx <= MAX_METHOD_CODE_SIZE;
  1097 static int
  1098 name_for_imethod(jvm_agent_t* J,
  1099                  uint64_t bcx,
  1100                  uint64_t methodOop,
  1101                  char *result,
  1102                  size_t size,
  1103                  Jframe_t *jframe
  1104 ) {
  1105   uint64_t bci;
  1106   uint64_t constMethod;
  1107   Vframe_t vframe = {0};
  1108   Vframe_t *vf = &vframe;
  1109   int32_t   err;
  1111   err = read_pointer(J, methodOop + OFFSET_methodOopDesc_constMethod, &constMethod);
  1112   CHECK_FAIL(err);
  1114   bci = is_bci(bcx) ? bcx : bcx - (constMethod + (uint64_t) SIZE_constMethodOopDesc);
  1116   if (debug)
  1117       fprintf(stderr, "\t name_for_imethod: BEGIN: methodOop: %#llx\n", methodOop);
  1119   err = name_for_methodOop(J, methodOop, result, size);
  1120   CHECK_FAIL(err);
  1121   if (debug)
  1122       fprintf(stderr, "\t name_for_imethod: method name: %s\n", result);
  1124   if (bci > 0) {
  1125       vf->methodOop = methodOop;
  1126       vf->bci       = bci;
  1127       err = line_number_from_bci(J, vf);
  1128       CHECK_FAIL(err);
  1130   jframe->bci  = vf->bci;
  1131   jframe->line = vf->line;
  1132   jframe->locinf = 1;
  1134   if (debug) {
  1135       fprintf(stderr, "\t name_for_imethod: END: bci: %d, line: %d\n\n",
  1136                       vf->bci, vf->line);
  1138   return PS_OK;
  1140  fail:
  1141   if (debug)
  1142       fprintf(stderr, "\t name_for_imethod: FAIL\n");
  1143   return err;
  1146 static int
  1147 name_for_codecache(jvm_agent_t* J, uint64_t fp, uint64_t pc, char * result,
  1148                    size_t size, Jframe_t *jframe, int* is_interpreted)
  1150   uint64_t start;
  1151   uint64_t vtbl;
  1152   int32_t err;
  1153   *is_interpreted = 0;
  1155   result[0] = '\0';
  1157   err = find_start(J, pc, &start);
  1158   CHECK_FAIL(err);
  1160   err = read_pointer(J, start, &vtbl);
  1161   CHECK_FAIL(err);
  1163   if (vtbl == J->nmethod_vtbl) {
  1164     uint64_t methodOop;
  1166     err = read_pointer(J, start + OFFSET_nmethod_method, &methodOop);
  1167     CHECK_FAIL(err);
  1169     if (debug) {
  1170         fprintf(stderr, "name_for_codecache: start: %#8llx, pc: %#8llx, methodOop: %#8llx \n",
  1171                         start, pc, methodOop);
  1173     err = name_for_nmethod(J, start, pc, methodOop, result, size, jframe);
  1174     CHECK_FAIL(err);
  1175   } else if (vtbl == J->BufferBlob_vtbl) {
  1176     const char * name;
  1178     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  1180     /*
  1181      * Temporary usage of string "Interpreter".
  1182      * We need some other way to distinguish "StubRoutines"
  1183      * and regular interpreted frames.
  1184      */
  1185     if (err == PS_OK && strncmp(name, "Interpreter", 11) == 0) {
  1186       *is_interpreted = 1;
  1187       if (is_methodOop(J, J->methodOopPtr)) {
  1188         return name_for_imethod(J, J->bcx, J->methodOopPtr, result, size, jframe);
  1192     if (err == PS_OK) {
  1193       strncpy(result, name, size);
  1194       free((void*)name);
  1195     } else {
  1196       strncpy(result, "<unknown BufferBlob>", size);
  1198     /* return PS_OK; */
  1199   } else {
  1200     const char * name;
  1202     err = read_string_pointer(J, start + OFFSET_CodeBlob_name, &name);
  1203     if (err == PS_OK) {
  1204       strncpy(result, name, size);
  1205       free((void*)name);
  1206     } else {
  1207       strncpy(result, "<unknown CodeBlob>", size);
  1208       WARN1("unknown CodeBlob: vtbl = 0x%x", vtbl);
  1211   result[size-1] = '\0';
  1213 #ifdef X86_COMPILER2
  1214   if (vtbl != J->RuntimeStub_vtbl) {
  1215     uint64_t trial_pc;
  1216     int frame_size;
  1217     err = ps_pread(J->P, start + OFFSET_CodeBlob_frame_size,
  1218                          &frame_size, SZ32);
  1219     CHECK_FAIL(err);
  1221     // frame_size is in words, we want bytes.
  1222     frame_size *= POINTER_SIZE; /* word => byte conversion */
  1224     /*
  1225       Because c2 doesn't use FP as a framepointer the value of sp/fp we receive
  1226       in the initial entry to a set of stack frames containing server frames
  1227       will pretty much be nonsense. We can detect that nonsense by looking to
  1228       see if the PC we received is correct if we look at the expected storage
  1229       location in relation to the FP (ie. POINTER_SIZE(FP) )
  1230     */
  1232     err = read_pointer(J, fp + POINTER_SIZE , &trial_pc);
  1233     if ( (err != PS_OK || trial_pc != pc) && frame_size > 0 ) {
  1234       // Either we couldn't even read at the "fp" or the pc didn't match
  1235       // both are sure clues that the fp is bogus. We no search the stack
  1236       // for a reasonable number of words trying to find the bogus fp
  1237       // and the current pc in adjacent words. The we will be able to
  1238       // deduce an approximation of the frame pointer and actually get
  1239       // the correct stack pointer. Which we can then unwind for the
  1240       // next frame.
  1241       int i;
  1242       uint64_t check;
  1243       uint64_t base = J->curr_fr.sp;
  1244       uint64_t prev_fp = 0;
  1245       for ( i = 0; i < frame_size * 5 ; i++, base += POINTER_SIZE ) {
  1246         err = read_pointer(J, base , &check);
  1247         CHECK_FAIL(err);
  1248         if (check == fp) {
  1249           base += POINTER_SIZE;
  1250           err = read_pointer(J, base , &check);
  1251           CHECK_FAIL(err);
  1252           if (check == pc) {
  1253             if (debug) {
  1254               fprintf(stderr, "name_for_codecache: found matching fp/pc combo at 0x%llx\n", base - POINTER_SIZE);
  1256             prev_fp = base - 2 * POINTER_SIZE;
  1257             break;
  1261       if ( prev_fp != 0 ) {
  1262         // real_sp is the sp we should have received for this frame
  1263         uint64_t real_sp = prev_fp + 2 * POINTER_SIZE;
  1264         // +POINTER_SIZE because callee owns the return address so caller's sp is +1 word
  1265         jframe->new_sp = real_sp + frame_size + POINTER_SIZE;
  1266         err = read_pointer(J, jframe->new_sp - POINTER_SIZE , &jframe->new_pc);
  1267         CHECK_FAIL(err);
  1268         err = read_pointer(J, jframe->new_sp - 2*POINTER_SIZE, &jframe->new_fp);
  1269         CHECK_FAIL(err);
  1270         return PS_OK;
  1274     /* A prototype to workaround FP absence */
  1275     /*
  1276      * frame_size can be 0 for StubRoutines (1) frame.
  1277      * In this case it should work with fp as usual.
  1278      */
  1279     if (frame_size > 0) {
  1280       jframe->new_fp = J->prev_fr.fp + frame_size;
  1281       jframe->new_sp = jframe->new_fp + 2 * POINTER_SIZE;
  1282     } else {
  1283       memset(&J->curr_fr, 0, sizeof(Frame_t));
  1284       err = read_pointer(J,  fp, &jframe->new_fp);
  1285       CHECK_FAIL(err);
  1287       err = read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1288       CHECK_FAIL(err);
  1290     if (debug) {
  1291       fprintf(stderr, "name_for_codecache: %s, frame_size=%#lx\n",
  1292                        result, frame_size);
  1293       fprintf(stderr, "name_for_codecache: prev_fr.fp=%#lx, fp=%#lx\n",
  1294                        J->prev_fr.fp, jframe->new_fp);
  1297 #endif /* X86_COMPILER2 */
  1299   return PS_OK;
  1301  fail:
  1302   return err;
  1305 int Jget_vframe(jvm_agent_t* J, int vframe_no,
  1306                 char *name, size_t size, Jframe_t *jframe)
  1308   Nmethod_t *N = J->N;
  1309   Vframe_t  *vf;
  1310   int32_t   err;
  1312   if (vframe_no >= N->vf_cnt) {
  1313      (void) sprintf(name, "Wrong inlinedMethod%1d()", vframe_no);
  1314      return -1;
  1316   vf = N->vframes + vframe_no;
  1317   name[0] = COMP_METHOD_SIGN;
  1318   err = name_for_methodOop(J, vf->methodOop, name + 1, size);
  1319   CHECK_FAIL(err);
  1321   jframe->bci = vf->bci;
  1322   jframe->line = vf->line;
  1323   if (debug) {
  1324       fprintf(stderr, "\t Jget_vframe: method name: %s, line: %ld\n",
  1325                        name, vf->line);
  1327   return PS_OK;
  1329  fail:
  1330   if (debug) {
  1331       fprintf(stderr, "\t Jget_vframe: FAIL\n");
  1333   return err;
  1336 #define MAX_SYM_SIZE 256
  1338 int Jlookup_by_regs(jvm_agent_t* J, const prgregset_t regs, char *name,
  1339                     size_t size, Jframe_t *jframe) {
  1340   uintptr_t fp;
  1341   uintptr_t pc;
  1342   /* arguments given to read_pointer need to be worst case sized */
  1343   uint64_t methodOopPtr = 0;
  1344   uint64_t sender_sp;
  1345   uint64_t bcx = 0;
  1346   int is_interpreted = 0;
  1347   int result = PS_OK;
  1348   int err = PS_OK;
  1350   if (J == NULL) {
  1351     return -1;
  1354   jframe->vf_cnt = 1;
  1355   jframe->new_fp = 0;
  1356   jframe->new_pc = 0;
  1357   jframe->line   = 0;
  1358   jframe->bci    = 0;
  1359   jframe->locinf = 0;
  1361   read_volatiles(J);
  1362   pc = (uintptr_t) regs[R_PC];
  1363   J->curr_fr.pc = pc;
  1364   J->curr_fr.fp = regs[R_FP];
  1365   J->curr_fr.sp = regs[R_SP];
  1367   if (debug)
  1368       fprintf(stderr, "Jlookup_by_regs: BEGINs: fp=%#lx, pc=%#lx\n", regs[R_FP], pc);
  1370 #if defined(sparc) || defined(__sparc)
  1371     /* The following workaround is for SPARC. CALL instruction occupates 8 bytes.
  1372      * In the pcDesc structure return pc offset is recorded for CALL instructions.
  1373      * regs[R_PC] contains a CALL instruction pc offset.
  1374      */
  1375     pc += 8;
  1376     bcx          = (uintptr_t) regs[R_L1];
  1377     methodOopPtr = (uintptr_t) regs[R_L2];
  1378     sender_sp = regs[R_I5];
  1379     if (debug > 2) {
  1380         fprintf(stderr, "\nregs[R_I1]=%lx, regs[R_I2]=%lx, regs[R_I5]=%lx, regs[R_L1]=%lx, regs[R_L2]=%lx\n",
  1381                          regs[R_I1], regs[R_I2], regs[R_I5], regs[R_L1], regs[R_L2]);
  1383 #elif defined(i386) || defined(__i386) || defined(__amd64)
  1385     fp = (uintptr_t) regs[R_FP];
  1386     if (J->prev_fr.fp == 0) {
  1387 #ifdef X86_COMPILER2
  1388         /* A workaround for top java frames */
  1389         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - 2 * POINTER_SIZE);
  1390 #else
  1391         J->prev_fr.fp = (uintptr_t)(regs[R_SP] - POINTER_SIZE);
  1392 #endif /* COMPILER2 */
  1394     if (debug > 2) {
  1395         printf("Jlookup_by_regs: J->prev_fr.fp = %#lx\n", J->prev_fr.fp);
  1398     if (read_pointer(J,  fp + OFFSET_interpreter_frame_method, &methodOopPtr) != PS_OK) {
  1399       methodOopPtr = 0;
  1401     if (read_pointer(J,  fp + OFFSET_interpreter_frame_sender_sp, &sender_sp) != PS_OK) {
  1402       sender_sp = 0;
  1404     if (read_pointer(J,  fp + OFFSET_interpreter_frame_bcx_offset, &bcx) != PS_OK) {
  1405       bcx = 0;
  1407 #endif /* i386 */
  1409   J->methodOopPtr = methodOopPtr;
  1410   J->bcx = bcx;
  1412   /* On x86 with C2 JVM: native frame may have wrong regs[R_FP]
  1413    * For example: JVM_SuspendThread frame poins to the top interpreted frame.
  1414    * If we call is_methodOop(J, methodOopPtr) before codecache_contains(J, pc)
  1415    * then we go over and omit both: nmethod and I2CAdapter frames.
  1416    * Note, that regs[R_PC] is always correct if frame defined correctly.
  1417    * So it is better to call codecache_contains(J, pc) from the beginning.
  1418    */
  1419 #ifndef X86_COMPILER2
  1420   if (is_methodOop(J, J->methodOopPtr)) {
  1421     result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe);
  1422     /* If the methodOopPtr is a method then this is highly likely to be
  1423        an interpreter frame */
  1424     if (result >= 0) {
  1425       is_interpreted = 1;
  1427   } else
  1428 #endif /* ! X86_COMPILER2 */
  1430   if (codecache_contains(J, pc)) {
  1431     result = name_for_codecache(J, fp, pc, name, size, jframe, &is_interpreted);
  1433 #ifdef X86_COMPILER2
  1434   else if (is_methodOop(J, J->methodOopPtr)) {
  1435     result = name_for_imethod(J, bcx, J->methodOopPtr, name, size, jframe);
  1436     /* If the methodOopPtr is a method then this is highly likely to be
  1437        an interpreter frame */
  1438     if (result >= 0) {
  1439       is_interpreted = 1;
  1442 #endif /* X86_COMPILER2 */
  1443   else {
  1444     if (debug) {
  1445         fprintf(stderr, "Jlookup_by_regs: END with -1\n\n");
  1447     result = -1;
  1449   if (!is_interpreted) {
  1450     sender_sp = 0;
  1452   J->curr_fr.sender_sp = sender_sp;
  1454 #ifdef X86_COMPILER2
  1455   if (!J->curr_fr.fp) {
  1456     J->curr_fr.fp = (jframe->new_fp) ? jframe->new_fp : (uintptr_t)regs[R_FP];
  1458   if (!jframe->new_pc && jframe->new_fp) {
  1459     // This seems dubious
  1460     read_pointer(J,  jframe->new_fp + POINTER_SIZE,  &jframe->new_pc);
  1461     CHECK_FAIL(err);
  1462     if (debug > 2) {
  1463         printf("Jlookup_by_regs: (update pc) jframe->new_fp: %#llx, jframe->new_pc: %#llx\n",
  1464                jframe->new_fp, jframe->new_pc);
  1468 #endif /* X86_COMPILER2 */
  1469   J->prev_fr = J->curr_fr;
  1471   if (debug)
  1472       fprintf(stderr, "Jlookup_by_regs: END\n\n");
  1474   return result;
  1476  fail:
  1477   return err;
  1480 void update_gregs(prgregset_t gregs, Jframe_t jframe) {
  1481 #ifdef X86_COMPILER2
  1482     if (debug > 0) {
  1483       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]);
  1485     /*
  1486      * A workaround for java C2 frames with unconventional FP.
  1487      * may have to modify regset with new values for FP/PC/SP when needed.
  1488      */
  1489      if (jframe.new_sp) {
  1490          *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) jframe.new_sp;
  1491      } else {
  1492          // *((uintptr_t *) &gregs[R_SP]) = (uintptr_t) gregs[R_FP] + 2 * POINTER_SIZE;
  1495      if (jframe.new_fp) {
  1496          *((uintptr_t *) &gregs[R_FP]) = (uintptr_t) jframe.new_fp;
  1498      if (jframe.new_pc) {
  1499          *((uintptr_t *) &gregs[R_PC]) = (uintptr_t) jframe.new_pc;
  1501     if (debug > 0) {
  1502       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]);
  1504 #endif  /* X86_COMPILER2 */
  1507 /*
  1508  * Iterates over java frames at current location given by 'gregs'.
  1510  *  Returns -1 if no java frames are present or if an error is encountered.
  1511  *  Returns the result of calling 'func' if the return value is non-zero.
  1512  *  Returns 0 otherwise.
  1513  */
  1514 int Jframe_iter(jvm_agent_t *J, prgregset_t gregs, java_stack_f *func, void* cld) {
  1515     char buf[MAX_SYM_SIZE + 1];
  1516     Jframe_t jframe;
  1517     int i = 0, res;
  1518 #ifdef X86_COMPILER2
  1519     if (debug > 0) {
  1520       fprintf(stderr, "Jframe_iter: Entry sp = 0x%llx, fp = 0x%llx, pc = 0x%llx\n", gregs[R_SP], gregs[R_FP], gregs[R_PC]);
  1522 #endif  /* X86_COMPILER2 */
  1524     memset(&jframe, 0, sizeof(Jframe_t));
  1525     memset(buf, 0, sizeof(buf));
  1526     res =  Jlookup_by_regs(J, gregs, buf, sizeof(buf), &jframe);
  1527     if (res != PS_OK)
  1528         return (-1);
  1531     res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
  1532                jframe.line, NULL);
  1533     if (res != 0) {
  1534         update_gregs(gregs, jframe);
  1535         return (res);
  1537     for (i = 1; i < jframe.vf_cnt; i++) {
  1538         Jget_vframe(J, i, buf, sizeof(buf), &jframe);
  1539         res = func(cld, gregs, buf, (jframe.locinf)? jframe.bci : -1,
  1540                    jframe.line, NULL);
  1541         if (res != 0) {
  1542             update_gregs(gregs, jframe);
  1543             return (res);
  1546     update_gregs(gregs, jframe);
  1547     return (0);

mercurial