src/os/solaris/dtrace/libjvm_db.c

Fri, 03 Apr 2020 14:14:26 +0100

author
aph
date
Fri, 03 Apr 2020 14:14:26 +0100
changeset 9920
3a3803a0c789
parent 6948
fd94cbe7c5da
child 9931
fd44df5e3bc3
permissions
-rw-r--r--

8076475: Misuses of strncpy/strncat
Summary: Various small fixes around strncpy and strncat
Reviewed-by: andrew

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

mercurial