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); 300 if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 301 return -1; 302 } 303 304 static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { 305 psaddr_t sym_addr; 306 int err; 307 308 err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); 309 if (err != PS_OK) goto fail; 310 *valuep = sym_addr; 311 return PS_OK; 312 313 fail: 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 | 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_heaps_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 // Code cache heaps 160 int32_t Number_of_heaps; 161 uint64_t* Heap_low; 162 uint64_t* Heap_high; 163 uint64_t* Heap_segmap_low; 164 uint64_t* Heap_segmap_high; 165 166 int32_t SIZE_CodeCache_log2_segment; 167 168 uint64_t methodPtr; 169 uint64_t bcx; 170 171 Nmethod_t *N; /*Inlined methods support */ 172 Frame_t prev_fr; 173 Frame_t curr_fr; 174 }; 175 176 static int 177 read_string(struct ps_prochandle *P, 178 char *buf, /* caller's buffer */ 179 size_t size, /* upper limit on bytes to read */ 180 uintptr_t addr) /* address in process */ 181 { 182 int err = PS_OK; 183 while (size-- > 1 && err == PS_OK) { 184 err = ps_pread(P, addr, buf, 1); 260 uint64_t gHotSpotVMStructs; 261 psaddr_t sym_addr; 262 uint64_t base; 263 int err; 264 265 err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr); 266 CHECK_FAIL(err); 267 err = read_pointer(J, sym_addr, &gHotSpotVMStructs); 268 CHECK_FAIL(err); 269 base = gHotSpotVMStructs; 270 271 err = PS_OK; 272 while (err == PS_OK) { 273 memset(vmp, 0, sizeof(VMStructEntry)); 274 err = parse_vmstruct_entry(J, base, vmp); 275 if (err != PS_OK || vmp->typeName == NULL) { 276 break; 277 } 278 279 if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { 280 /* Read _heaps field of type GrowableArray<CodeHeaps*>* */ 281 if (strcmp("_heaps", vmp->fieldName) == 0) { 282 err = read_pointer(J, vmp->address, &J->CodeCache_heaps_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); 293 294 base += SIZE_VMStructEntry; 295 if (vmp->typeName != NULL) free((void*)vmp->typeName); 296 if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 297 } 298 299 return PS_OK; 300 301 fail: 302 if (vmp->typeName != NULL) free((void*)vmp->typeName); 303 if (vmp->fieldName != NULL) free((void*)vmp->fieldName); 304 return -1; 305 } 306 307 static int find_symbol(jvm_agent_t* J, const char *name, uint64_t* valuep) { 308 psaddr_t sym_addr; 309 int err; 310 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; 315 316 fail: 317 return err; 318 } 319 320 static int read_volatiles(jvm_agent_t* J) { 321 int i; 322 uint64_t array_data; 323 uint64_t code_heap_address; 324 int err; 325 326 err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); 327 if (err == PS_OK) { 328 err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); 329 CHECK_FAIL(err); 330 } else { 331 J->Use_Compressed_Oops = 0; 332 } 333 334 err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); 335 CHECK_FAIL(err); 336 err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); 337 CHECK_FAIL(err); 338 339 /* CodeCache_heaps_address points to GrowableArray<CodeHeaps*>, read _data field 340 pointing to the first entry of type CodeCache* in the array */ 341 err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data); 342 /* Read _len field containing the number of code heaps */ 343 err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len, 344 &J->Number_of_heaps, sizeof(J->Number_of_heaps)); 345 346 /* Allocate memory for heap configurations */ 347 J->Heap_low = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 348 J->Heap_high = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 349 J->Heap_segmap_low = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 350 J->Heap_segmap_high = (jvm_agent_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); 351 352 /* Read code heap configurations */ 353 for (i = 0; i < J->Number_of_heaps; ++i) { 354 /* Read address of heap */ 355 err = read_pointer(J, array_data, &code_heap_address); 356 CHECK_FAIL(err); 357 358 err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + 359 OFFSET_VirtualSpace_low, &J->Heap_low[i]); 360 CHECK_FAIL(err); 361 err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + 362 OFFSET_VirtualSpace_high, &J->Heap_high[i]); 363 CHECK_FAIL(err); 364 err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + 365 OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]); 366 CHECK_FAIL(err); 367 err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + 368 OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]); 369 CHECK_FAIL(err); 370 371 /* Increment pointer to next entry */ 372 array_data = array_data + POINTER_SIZE; 373 } 374 375 err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size, 376 &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); 377 CHECK_FAIL(err); 378 379 return PS_OK; 380 381 fail: 382 return err; 383 } 384 385 static int codeheap_contains(int heap_num, jvm_agent_t* J, uint64_t ptr) { 386 return (J->Heap_low[heap_num] <= ptr && ptr < J->Heap_high[heap_num]); 387 } 388 389 static int codecache_contains(jvm_agent_t* J, uint64_t ptr) { 390 int i; 391 for (i = 0; i < J->Number_of_heaps; ++i) { 392 if (codeheap_contains(i, J, ptr)) { 393 return 1; 394 } 395 } 396 return 0; 397 } 398 399 static uint64_t segment_for(int heap_num, jvm_agent_t* J, uint64_t p) { 400 return (p - J->Heap_low[heap_num]) >> J->SIZE_CodeCache_log2_segment; 401 } 402 403 static uint64_t block_at(int heap_num, jvm_agent_t* J, int i) { 404 return J->Heap_low[heap_num] + (i << J->SIZE_CodeCache_log2_segment); 405 } 406 407 static int find_start(jvm_agent_t* J, uint64_t ptr, uint64_t *startp) { 408 int err; 409 int i; 410 411 for (i = 0; i < J->Number_of_heaps; ++i) { 412 *startp = 0; 413 if (codeheap_contains(i, J, ptr)) { 414 int32_t used; 415 uint64_t segment = segment_for(i, J, ptr); 416 uint64_t block = J->Heap_segmap_low[i]; 417 uint8_t tag; 418 err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); 419 CHECK_FAIL(err); 420 if (tag == 0xff) 421 return PS_OK; 422 while (tag > 0) { 423 err = ps_pread(J->P, block + segment, &tag, sizeof(tag)); 424 CHECK_FAIL(err); 425 segment -= tag; 426 } 427 block = block_at(i, J, segment); 428 err = ps_pread(J->P, block + OFFSET_HeapBlockHeader_used, &used, sizeof(used)); 429 CHECK_FAIL(err); 430 if (used) { 431 *startp = block + SIZE_HeapBlockHeader; 432 } 433 } 434 return PS_OK; 435 } 436 437 fail: 438 return -1; 439 } 440 441 static int find_jlong_constant(jvm_agent_t* J, const char *name, uint64_t* valuep) { 442 psaddr_t sym_addr; 443 int err = ps_pglobal_lookup(J->P, LIBJVM_SO, name, &sym_addr); 444 if (err == PS_OK) { 445 err = ps_pread(J->P, sym_addr, valuep, sizeof(uint64_t)); 446 return err; 447 } 448 *valuep = -1; 449 return -1; 450 } 451 452 jvm_agent_t *Jagent_create(struct ps_prochandle *P, int vers) { 453 jvm_agent_t* J; 454 int err; 455 |