src/os/bsd/dtrace/libjvm_db.c

Print this page




  83 
  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;
  91 
  92 /* Prototyping inlined methods */
  93 
  94 int sprintf(char *s, const char *format, ...);
  95 
  96 #define SZ16  sizeof(int16_t)
  97 #define SZ32  sizeof(int32_t)
  98 
  99 #define COMP_METHOD_SIGN '*'
 100 
 101 #define MAX_VFRAMES_CNT 256
 102 



 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;
 110 
 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;
 117 
 118 typedef struct Nmethod_t {
 119   struct jvm_agent* J;
 120   Jframe_t *jframe;
 121 
 122   uint64_t nm;                  /* _nmethod */


 133   int32_t  metadata_end;
 134   int32_t  scopes_pcs_beg;      /* _scopes_pcs_offset */
 135   int32_t  scopes_pcs_end;
 136 
 137   int      vf_cnt;
 138   Vframe_t vframes[MAX_VFRAMES_CNT];
 139 } Nmethod_t;
 140 
 141 struct jvm_agent {
 142   struct ps_prochandle* P;
 143 
 144   uint64_t nmethod_vtbl;
 145   uint64_t CodeBlob_vtbl;
 146   uint64_t BufferBlob_vtbl;
 147   uint64_t RuntimeStub_vtbl;
 148   uint64_t Method_vtbl;
 149 
 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;
 154 
 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;

 163 
 164   int32_t  SIZE_CodeCache_log2_segment;
 165 
 166   uint64_t methodPtr;
 167   uint64_t bcx;
 168 
 169   Nmethod_t *N;                 /*Inlined methods support */
 170   Frame_t   prev_fr;
 171   Frame_t   curr_fr;
 172 };
 173 
 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);


 258   uint64_t gHotSpotVMStructs;
 259   psaddr_t sym_addr;
 260   uint64_t base;
 261   int err;
 262 
 263   err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
 264   CHECK_FAIL(err);
 265   err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
 266   CHECK_FAIL(err);
 267   base = gHotSpotVMStructs;
 268 
 269   err = PS_OK;
 270   while (err == PS_OK) {
 271     memset(vmp, 0, sizeof(VMStructEntry));
 272     err = parse_vmstruct_entry(J, base, vmp);
 273     if (err != PS_OK || vmp->typeName == NULL) {
 274       break;
 275     }
 276 
 277     if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
 278       if (strcmp("_heap", vmp->fieldName) == 0) {
 279         err = read_pointer(J, vmp->address, &J->CodeCache_heap_address);





 280       }
 281     } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
 282       if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
 283         J->Universe_narrow_oop_base_address = vmp->address;
 284       }
 285       if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
 286         J->Universe_narrow_oop_shift_address = vmp->address;
 287       }
 288     }
 289     CHECK_FAIL(err);
 290 
 291     base += SIZE_VMStructEntry;
 292     if (vmp->typeName != NULL) free((void*)vmp->typeName);
 293     if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
 294   }
 295 
 296   return PS_OK;
 297 
 298  fail:
 299   if (vmp->typeName != NULL) free((void*)vmp->typeName);


 314   return err;
 315 }
 316 
 317 static int read_volatiles(jvm_agent_t* J) {
 318   uint64_t ptr;
 319   int err;
 320 
 321   err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
 322   if (err == PS_OK) {
 323     err = ps_pread(J->P,  J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
 324     CHECK_FAIL(err);
 325   } else {
 326     J->Use_Compressed_Oops = 0;
 327   }
 328 
 329   err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
 330   CHECK_FAIL(err);
 331   err = ps_pread(J->P,  J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
 332   CHECK_FAIL(err);
 333 
 334   err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
 335                      OFFSET_VirtualSpace_low, &J->CodeCache_low);



 336   CHECK_FAIL(err);
 337   err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory +
 338                      OFFSET_VirtualSpace_high, &J->CodeCache_high);
 339   CHECK_FAIL(err);
 340   err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
 341                      OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low);
 342   CHECK_FAIL(err);
 343   err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap +
 344                      OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high);
 345   CHECK_FAIL(err);

 346 
 347   err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size,
 348                  &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
 349   CHECK_FAIL(err);
 350 
 351   return PS_OK;
 352 
 353  fail:
 354   return err;
 355 }
 356 



 357 
 358 static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
 359   /* make sure the code cache is up to date */
 360   return (J->CodeCache_low <= ptr && ptr < J->CodeCache_high);





 361 }
 362 
 363 static uint64_t segment_for(jvm_agent_t* J, uint64_t p) {
 364   return (p - J->CodeCache_low) >> J->SIZE_CodeCache_log2_segment;
 365 }
 366 
 367 static uint64_t block_at(jvm_agent_t* J, int i) {
 368   return J->CodeCache_low + (i << J->SIZE_CodeCache_log2_segment);
 369 }
 370 
 371 static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
 372   int err;
 373 

 374   *startp = 0;
 375   if (J->CodeCache_low <= ptr && ptr < J->CodeCache_high) {
 376     int32_t used;
 377     uint64_t segment = segment_for(J, ptr);
 378     uint64_t block = J->CodeCache_segmap_low;
 379     uint8_t tag;
 380     err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
 381     CHECK_FAIL(err);
 382     if (tag == 0xff)
 383       return PS_OK;
 384     while (tag > 0) {
 385       err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
 386       CHECK_FAIL(err);
 387       segment -= tag;
 388     }
 389     block = block_at(J, segment);
 390     err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
 391     CHECK_FAIL(err);
 392     if (used) {
 393       *startp = block + SIZE_HeapBlockHeader;
 394     }
 395   }
 396   return PS_OK;

 397 
 398  fail:
 399   return -1;
 400 }
 401 
 402 static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
 403   psaddr_t sym_addr;
 404   int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
 405   if (err == PS_OK) {
 406     err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
 407     return err;
 408   }
 409   *valuep = -1;
 410   return -1;
 411 }
 412 
 413 jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
 414   jvm_agent_t* J;
 415   int err;
 416 




  83 
  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;
  91 
  92 /* Prototyping inlined methods */
  93 
  94 int sprintf(char *s, const char *format, ...);
  95 
  96 #define SZ16  sizeof(int16_t)
  97 #define SZ32  sizeof(int32_t)
  98 
  99 #define COMP_METHOD_SIGN '*'
 100 
 101 #define MAX_VFRAMES_CNT 256
 102 
 103 // Number of code heaps in the code cache
 104 #define HEAP_CNT 3
 105 
 106 typedef struct vframe {
 107   uint64_t method;
 108   int32_t  sender_decode_offset;
 109   int32_t  methodIdx;
 110   int32_t  bci;
 111   int32_t  line;
 112 } Vframe_t;
 113 
 114 typedef struct frame {
 115   uintptr_t fp;
 116   uintptr_t pc;
 117   uintptr_t sp;
 118   uintptr_t sender_sp; // The unextended sp of the caller
 119 } Frame_t;
 120 
 121 typedef struct Nmethod_t {
 122   struct jvm_agent* J;
 123   Jframe_t *jframe;
 124 
 125   uint64_t nm;                  /* _nmethod */


 136   int32_t  metadata_end;
 137   int32_t  scopes_pcs_beg;      /* _scopes_pcs_offset */
 138   int32_t  scopes_pcs_end;
 139 
 140   int      vf_cnt;
 141   Vframe_t vframes[MAX_VFRAMES_CNT];
 142 } Nmethod_t;
 143 
 144 struct jvm_agent {
 145   struct ps_prochandle* P;
 146 
 147   uint64_t nmethod_vtbl;
 148   uint64_t CodeBlob_vtbl;
 149   uint64_t BufferBlob_vtbl;
 150   uint64_t RuntimeStub_vtbl;
 151   uint64_t Method_vtbl;
 152 
 153   uint64_t Use_Compressed_Oops_address;
 154   uint64_t Universe_narrow_oop_base_address;
 155   uint64_t Universe_narrow_oop_shift_address;
 156   uint64_t CodeCache_heap_address[HEAP_CNT];
 157 
 158   /* Volatiles */
 159   uint8_t  Use_Compressed_Oops;
 160   uint64_t Universe_narrow_oop_base;
 161   uint32_t Universe_narrow_oop_shift;
 162   // Code cache heaps
 163   uint64_t Heap_low[HEAP_CNT];
 164   uint64_t Heap_high[HEAP_CNT];
 165   uint64_t Heap_segmap_low[HEAP_CNT];
 166   uint64_t Heap_segmap_high[HEAP_CNT];
 167 
 168   int32_t  SIZE_CodeCache_log2_segment;
 169 
 170   uint64_t methodPtr;
 171   uint64_t bcx;
 172 
 173   Nmethod_t *N;                 /*Inlined methods support */
 174   Frame_t   prev_fr;
 175   Frame_t   curr_fr;
 176 };
 177 
 178 static int
 179 read_string(struct ps_prochandle *P,
 180         char *buf,              /* caller's buffer */
 181         size_t size,            /* upper limit on bytes to read */
 182         uintptr_t addr)         /* address in process */
 183 {
 184   int err = PS_OK;
 185   while (size-- > 1 && err == PS_OK) {
 186     err = ps_pread(P, addr, buf, 1);


 262   uint64_t gHotSpotVMStructs;
 263   psaddr_t sym_addr;
 264   uint64_t base;
 265   int err;
 266 
 267   err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
 268   CHECK_FAIL(err);
 269   err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
 270   CHECK_FAIL(err);
 271   base = gHotSpotVMStructs;
 272 
 273   err = PS_OK;
 274   while (err == PS_OK) {
 275     memset(vmp, 0, sizeof(VMStructEntry));
 276     err = parse_vmstruct_entry(J, base, vmp);
 277     if (err != PS_OK || vmp->typeName == NULL) {
 278       break;
 279     }
 280 
 281     if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) {
 282       // Read addresses of code cache heaps
 283       if (strcmp("_heap_non_method", vmp->fieldName) == 0) {
 284         err = read_pointer(J, vmp->address, &J->CodeCache_heap_address[0]);
 285       } else if (strcmp("_heap_non_profiled", vmp->fieldName) == 0) {
 286         err = read_pointer(J, vmp->address, &J->CodeCache_heap_address[1]);
 287       } else if (strcmp("_heap_profiled", vmp->fieldName) == 0) {
 288         err = read_pointer(J, vmp->address, &J->CodeCache_heap_address[2]);
 289       }
 290     } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) {
 291       if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) {
 292         J->Universe_narrow_oop_base_address = vmp->address;
 293       }
 294       if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) {
 295         J->Universe_narrow_oop_shift_address = vmp->address;
 296       }
 297     }
 298     CHECK_FAIL(err);
 299 
 300     base += SIZE_VMStructEntry;
 301     if (vmp->typeName != NULL) free((void*)vmp->typeName);
 302     if (vmp->fieldName != NULL) free((void*)vmp->fieldName);
 303   }
 304 
 305   return PS_OK;
 306 
 307  fail:
 308   if (vmp->typeName != NULL) free((void*)vmp->typeName);


 323   return err;
 324 }
 325 
 326 static int read_volatiles(jvm_agent_t* J) {
 327   uint64_t ptr;
 328   int err;
 329 
 330   err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address);
 331   if (err == PS_OK) {
 332     err = ps_pread(J->P,  J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t));
 333     CHECK_FAIL(err);
 334   } else {
 335     J->Use_Compressed_Oops = 0;
 336   }
 337 
 338   err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base);
 339   CHECK_FAIL(err);
 340   err = ps_pread(J->P,  J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t));
 341   CHECK_FAIL(err);
 342 
 343   /* Read code heap information */
 344   int i;
 345   for (i = 0; i < HEAP_CNT; ++i) {
 346     err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_memory +
 347                        OFFSET_VirtualSpace_low, &J->Heap_low[i]);
 348     CHECK_FAIL(err);
 349     err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_memory +
 350                        OFFSET_VirtualSpace_high, &J->Heap_low[i]);
 351     CHECK_FAIL(err);
 352     err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_segmap +
 353                        OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]);
 354     CHECK_FAIL(err);
 355     err = read_pointer(J, J->CodeCache_heap_address[i] + OFFSET_CodeHeap_segmap +
 356                        OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]);
 357     CHECK_FAIL(err);
 358   }
 359 
 360   err = ps_pread(J->P, J->CodeCache_heap_address[0] + OFFSET_CodeHeap_log2_segment_size,
 361                  &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment));
 362   CHECK_FAIL(err);
 363 
 364   return PS_OK;
 365 
 366  fail:
 367   return err;
 368 }
 369 
 370 static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) {
 371   return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]);
 372 }
 373 
 374 static int codecache_contains(jvm_agent_t* J, uint64_t ptr) {
 375   int i;
 376   for (i = 0; i < HEAP_CNT; ++i) {
 377     if (codeheap_contains(i, J, ptr)) {
 378       return 1;
 379     }
 380   }
 381   return 0;
 382 }
 383 
 384 static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) {
 385   return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment;
 386 }
 387 
 388 static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) {
 389   return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment);
 390 }
 391 
 392 static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) {
 393   int err;
 394 
 395   for (int i = 0; i < HEAP_CNT; ++i) {
 396     *startp = 0;
 397     if (codeheap_contains(i, J, ptr)) {
 398       int32_t used;
 399       uint64_t segment = segment_for(i, J, ptr);
 400       uint64_t block = J->Heap_segmap_low[i];
 401       uint8_t tag;
 402       err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
 403       CHECK_FAIL(err);
 404       if (tag == 0xff)
 405         return PS_OK;
 406       while (tag > 0) {
 407         err = ps_pread(J->P, block + segment, &tag, sizeof(tag));
 408         CHECK_FAIL(err);
 409         segment -= tag;
 410       }
 411       block = block_at(i, J, segment);
 412       err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used));
 413       CHECK_FAIL(err);
 414       if (used) {
 415         *startp = block + SIZE_HeapBlockHeader;
 416       }
 417     }
 418     return PS_OK;
 419   }
 420 
 421  fail:
 422   return -1;
 423 }
 424 
 425 static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) {
 426   psaddr_t sym_addr;
 427   int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr);
 428   if (err == PS_OK) {
 429     err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t));
 430     return err;
 431   }
 432   *valuep = -1;
 433   return -1;
 434 }
 435 
 436 jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) {
 437   jvm_agent_t* J;
 438   int err;
 439