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