1 /* 2 * Copyright (c) 2003, 2018, 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 */ 24 25 /* This file is auto-generated */ 26 #include "JvmOffsetsIndex.h" 27 28 #define DEBUG 29 30 #ifdef DEBUG 31 #define MARK_LINE this->line = __LINE__ 32 #else 33 #define MARK_LINE 34 #endif 35 36 #ifdef _LP64 37 #define STACK_BIAS 0x7ff 38 #define pointer uint64_t 39 #else 40 #define STACK_BIAS 0 41 #define pointer uint32_t 42 #endif 43 44 extern pointer __JvmOffsets; 45 46 /* GrowableArray<CodeHeaps*>* */ 47 extern pointer __1cJCodeCacheG_heaps_; 48 49 extern pointer __1cIUniverseO_collectedHeap_; 50 51 extern pointer __1cHnmethodG__vtbl_; 52 extern pointer __1cGMethodG__vtbl_; 53 extern pointer __1cKBufferBlobG__vtbl_; 54 55 #define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer)) 56 #define copyin_uchar(ADDR) *(uchar_t*) copyin((pointer) (ADDR), sizeof(uchar_t)) 57 #define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t)) 58 #define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t)) 59 #define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t)) 60 #define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t)) 61 62 #define copyin_offset(JVM_CONST) JVM_CONST = \ 63 copyin_int32(JvmOffsetsPtr + IDX_##JVM_CONST * sizeof(int32_t)) 64 65 int init_done; 66 67 dtrace:helper:ustack: 68 { 69 MARK_LINE; 70 this->done = 0; 71 /* 72 * TBD: 73 * Here we initialize init_done, otherwise jhelper does not work. 74 * Therefore, copyin_offset() statements work multiple times now. 75 * There is a hope we could avoid it in the future, and so, 76 * this initialization can be removed. 77 */ 78 init_done = 0; 79 this->error = (char *) NULL; 80 this->result = (char *) NULL; 81 this->isMethod = 0; 82 this->codecache = 0; 83 this->klass = (pointer) NULL; 84 this->vtbl = (pointer) NULL; 85 this->suffix = '\0'; 86 } 87 88 dtrace:helper:ustack: 89 { 90 MARK_LINE; 91 /* Initialization of JvmOffsets constants */ 92 JvmOffsetsPtr = (pointer) &``__JvmOffsets; 93 } 94 95 dtrace:helper:ustack: 96 /!init_done && !this->done/ 97 { 98 MARK_LINE; 99 100 copyin_offset(POINTER_SIZE); 101 copyin_offset(COMPILER); 102 copyin_offset(OFFSET_CollectedHeap_reserved); 103 copyin_offset(OFFSET_MemRegion_start); 104 copyin_offset(OFFSET_MemRegion_word_size); 105 copyin_offset(SIZE_HeapWord); 106 107 copyin_offset(OFFSET_interpreter_frame_method); 108 copyin_offset(OFFSET_Klass_name); 109 copyin_offset(OFFSET_ConstantPool_pool_holder); 110 111 copyin_offset(OFFSET_HeapBlockHeader_used); 112 copyin_offset(OFFSET_oopDesc_metadata); 113 114 copyin_offset(OFFSET_Symbol_length); 115 copyin_offset(OFFSET_Symbol_body); 116 117 copyin_offset(OFFSET_Method_constMethod); 118 copyin_offset(OFFSET_ConstMethod_constants); 119 copyin_offset(OFFSET_ConstMethod_name_index); 120 copyin_offset(OFFSET_ConstMethod_signature_index); 121 122 copyin_offset(OFFSET_CodeHeap_memory); 123 copyin_offset(OFFSET_CodeHeap_segmap); 124 copyin_offset(OFFSET_CodeHeap_log2_segment_size); 125 126 copyin_offset(OFFSET_GrowableArray_CodeHeap_data); 127 copyin_offset(OFFSET_GrowableArray_CodeHeap_len); 128 129 copyin_offset(OFFSET_VirtualSpace_low); 130 copyin_offset(OFFSET_VirtualSpace_high); 131 132 copyin_offset(OFFSET_CodeBlob_name); 133 134 copyin_offset(OFFSET_nmethod_method); 135 copyin_offset(SIZE_HeapBlockHeader); 136 copyin_offset(SIZE_oopDesc); 137 copyin_offset(SIZE_ConstantPool); 138 139 copyin_offset(OFFSET_NarrowPtrStruct_base); 140 copyin_offset(OFFSET_NarrowPtrStruct_shift); 141 142 /* 143 * The PC to translate is in arg0. 144 */ 145 this->pc = arg0; 146 147 /* 148 * The methodPtr is in %l2 on SPARC. This can be found at 149 * offset 8 from the frame pointer on 32-bit processes. 150 */ 151 #if defined(__sparc) 152 this->methodPtr = copyin_ptr(arg1 + 2 * sizeof(pointer) + STACK_BIAS); 153 #elif defined(__i386) || defined(__amd64) 154 this->methodPtr = copyin_ptr(arg1 + OFFSET_interpreter_frame_method); 155 #else 156 #error "Don't know architecture" 157 #endif 158 159 /* Read address of GrowableArray<CodeHeaps*> */ 160 // this->code_heaps_address = copyin_ptr(&``__1cJCodeCacheG_heaps_); 161 this->code_heaps_address = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cJCodeCacheG_heaps_ ) , sizeof ( uint64_t ) ); 162 163 /* Read address of _data array field in GrowableArray */ 164 this->code_heaps_array_address = copyin_ptr(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_data); 165 this->number_of_heaps = copyin_uint32(this->code_heaps_address + OFFSET_GrowableArray_CodeHeap_len); 166 167 this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_; 168 169 /* 170 * Get Java heap bounds 171 */ 172 // this->Universe_collectedHeap = copyin_ptr(&``__1cIUniverseO_collectedHeap_); 173 this->Universe_collectedHeap = * ( uint64_t * ) copyin ( ( uint64_t ) ( &``__1cIUniverseO_collectedHeap_ ) , sizeof ( uint64_t ) ); 174 175 this->heap_start = copyin_ptr(this->Universe_collectedHeap + 176 OFFSET_CollectedHeap_reserved + 177 OFFSET_MemRegion_start); 178 this->heap_size = SIZE_HeapWord * 179 copyin_ptr(this->Universe_collectedHeap + 180 OFFSET_CollectedHeap_reserved + 181 OFFSET_MemRegion_word_size 182 ); 183 this->heap_end = this->heap_start + this->heap_size; 184 } 185 186 /* 187 * IMPORTANT: At the moment the ustack helper supports up to 5 code heaps in 188 * the code cache. If more code heaps are added the following probes have to 189 * be extended. This is done by simply adding a probe to get the heap bounds 190 * and another probe to set the code heap address of the newly created heap. 191 */ 192 193 /* 194 * ----- BEGIN: Get bounds of code heaps ----- 195 */ 196 dtrace:helper:ustack: 197 /init_done < 1 && this->number_of_heaps >= 1 && !this->done/ 198 { 199 MARK_LINE; 200 /* CodeHeap 1 */ 201 init_done = 1; 202 this->code_heap1_address = copyin_ptr(this->code_heaps_array_address); 203 this->code_heap1_low = copyin_ptr(this->code_heap1_address + 204 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); 205 this->code_heap1_high = copyin_ptr(this->code_heap1_address + 206 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high); 207 } 208 209 dtrace:helper:ustack: 210 /init_done < 2 && this->number_of_heaps >= 2 && !this->done/ 211 { 212 MARK_LINE; 213 /* CodeHeap 2 */ 214 init_done = 2; 215 this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE; 216 this->code_heap2_address = copyin_ptr(this->code_heaps_array_address); 217 this->code_heap2_low = copyin_ptr(this->code_heap2_address + 218 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); 219 this->code_heap2_high = copyin_ptr(this->code_heap2_address + 220 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high); 221 } 222 223 dtrace:helper:ustack: 224 /init_done < 3 && this->number_of_heaps >= 3 && !this->done/ 225 { 226 /* CodeHeap 3 */ 227 init_done = 3; 228 this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE; 229 this->code_heap3_address = copyin_ptr(this->code_heaps_array_address); 230 this->code_heap3_low = copyin_ptr(this->code_heap3_address + 231 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); 232 this->code_heap3_high = copyin_ptr(this->code_heap3_address + 233 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high); 234 } 235 236 dtrace:helper:ustack: 237 /init_done < 4 && this->number_of_heaps >= 4 && !this->done/ 238 { 239 /* CodeHeap 4 */ 240 init_done = 4; 241 this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE; 242 this->code_heap4_address = copyin_ptr(this->code_heaps_array_address); 243 this->code_heap4_low = copyin_ptr(this->code_heap4_address + 244 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); 245 this->code_heap4_high = copyin_ptr(this->code_heap4_address + 246 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high); 247 } 248 249 dtrace:helper:ustack: 250 /init_done < 5 && this->number_of_heaps >= 5 && !this->done/ 251 { 252 /* CodeHeap 5 */ 253 init_done = 5; 254 this->code_heaps_array_address = this->code_heaps_array_address + POINTER_SIZE; 255 this->code_heap5_address = copyin_ptr(this->code_heaps_array_address); 256 this->code_heap5_low = copyin_ptr(this->code_heap5_address + 257 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); 258 this->code_heap5_high = copyin_ptr(this->code_heap5_address + 259 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high); 260 } 261 /* 262 * ----- END: Get bounds of code heaps ----- 263 */ 264 265 /* 266 * ----- BEGIN: Get address of the code heap pc points to ----- 267 */ 268 dtrace:helper:ustack: 269 /!this->done && this->number_of_heaps >= 1 && this->code_heap1_low <= this->pc && this->pc < this->code_heap1_high/ 270 { 271 MARK_LINE; 272 this->codecache = 1; 273 this->code_heap_address = this->code_heap1_address; 274 } 275 276 dtrace:helper:ustack: 277 /!this->done && this->number_of_heaps >= 2 && this->code_heap2_low <= this->pc && this->pc < this->code_heap2_high/ 278 { 279 MARK_LINE; 280 this->codecache = 1; 281 this->code_heap_address = this->code_heap2_address; 282 } 283 284 dtrace:helper:ustack: 285 /!this->done && this->number_of_heaps >= 3 && this->code_heap3_low <= this->pc && this->pc < this->code_heap3_high/ 286 { 287 MARK_LINE; 288 this->codecache = 1; 289 this->code_heap_address = this->code_heap3_address; 290 } 291 292 dtrace:helper:ustack: 293 /!this->done && this->number_of_heaps >= 4 && this->code_heap4_low <= this->pc && this->pc < this->code_heap4_high/ 294 { 295 MARK_LINE; 296 this->codecache = 1; 297 this->code_heap_address = this->code_heap4_address; 298 } 299 300 dtrace:helper:ustack: 301 /!this->done && this->number_of_heaps >= 5 && this->code_heap5_low <= this->pc && this->pc < this->code_heap5_high/ 302 { 303 MARK_LINE; 304 this->codecache = 1; 305 this->code_heap_address = this->code_heap5_address; 306 } 307 /* 308 * ----- END: Get address of the code heap pc points to ----- 309 */ 310 311 dtrace:helper:ustack: 312 /!this->done && this->codecache/ 313 { 314 MARK_LINE; 315 /* 316 * Get code heap configuration 317 */ 318 this->code_heap_low = copyin_ptr(this->code_heap_address + 319 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low); 320 this->code_heap_segmap_low = copyin_ptr(this->code_heap_address + 321 OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low); 322 this->code_heap_log2_segment_size = copyin_uint32( 323 this->code_heap_address + OFFSET_CodeHeap_log2_segment_size); 324 325 /* 326 * Find start 327 */ 328 this->segment = (this->pc - this->code_heap_low) >> 329 this->code_heap_log2_segment_size; 330 this->block = this->code_heap_segmap_low; 331 this->tag = copyin_uchar(this->block + this->segment); 332 } 333 334 dtrace:helper:ustack: 335 /!this->done && this->codecache && this->tag > 0/ 336 { 337 MARK_LINE; 338 this->tag = copyin_uchar(this->block + this->segment); 339 this->segment = this->segment - this->tag; 340 } 341 342 dtrace:helper:ustack: 343 /!this->done && this->codecache && this->tag > 0/ 344 { 345 MARK_LINE; 346 this->tag = copyin_uchar(this->block + this->segment); 347 this->segment = this->segment - this->tag; 348 } 349 350 dtrace:helper:ustack: 351 /!this->done && this->codecache && this->tag > 0/ 352 { 353 MARK_LINE; 354 this->tag = copyin_uchar(this->block + this->segment); 355 this->segment = this->segment - this->tag; 356 } 357 358 dtrace:helper:ustack: 359 /!this->done && this->codecache && this->tag > 0/ 360 { 361 MARK_LINE; 362 this->tag = copyin_uchar(this->block + this->segment); 363 this->segment = this->segment - this->tag; 364 } 365 366 dtrace:helper:ustack: 367 /!this->done && this->codecache && this->tag > 0/ 368 { 369 MARK_LINE; 370 this->tag = copyin_uchar(this->block + this->segment); 371 this->segment = this->segment - this->tag; 372 } 373 374 dtrace:helper:ustack: 375 /!this->done && this->codecache && this->tag > 0/ 376 { 377 MARK_LINE; 378 this->error = "<couldn't find start>"; 379 this->done = 1; 380 } 381 382 dtrace:helper:ustack: 383 /!this->done && this->codecache/ 384 { 385 MARK_LINE; 386 this->block = this->code_heap_low + 387 (this->segment << this->code_heap_log2_segment_size); 388 this->used = copyin_uint32(this->block + OFFSET_HeapBlockHeader_used); 389 } 390 391 dtrace:helper:ustack: 392 /!this->done && this->codecache && !this->used/ 393 { 394 MARK_LINE; 395 this->error = "<block not in use>"; 396 this->done = 1; 397 } 398 399 dtrace:helper:ustack: 400 /!this->done && this->codecache/ 401 { 402 MARK_LINE; 403 this->start = this->block + SIZE_HeapBlockHeader; 404 this->vtbl = copyin_ptr(this->start); 405 406 this->nmethod_vtbl = (pointer) &``__1cHnmethodG__vtbl_; 407 this->BufferBlob_vtbl = (pointer) &``__1cKBufferBlobG__vtbl_; 408 } 409 410 dtrace:helper:ustack: 411 /!this->done && this->vtbl == this->nmethod_vtbl/ 412 { 413 MARK_LINE; 414 this->methodPtr = copyin_ptr(this->start + OFFSET_nmethod_method); 415 this->suffix = '*'; 416 this->isMethod = 1; 417 } 418 419 dtrace:helper:ustack: 420 /!this->done && this->vtbl == this->BufferBlob_vtbl/ 421 { 422 MARK_LINE; 423 this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name); 424 } 425 426 427 dtrace:helper:ustack: 428 /!this->done && this->vtbl == this->BufferBlob_vtbl && this->methodPtr != 0/ 429 { 430 MARK_LINE; 431 this->klass = copyin_ptr(this->methodPtr); 432 this->isMethod = this->klass == this->Method_vtbl; 433 this->done = !this->isMethod; 434 } 435 436 dtrace:helper:ustack: 437 /!this->done && !this->isMethod/ 438 { 439 MARK_LINE; 440 this->name = copyin_ptr(this->start + OFFSET_CodeBlob_name); 441 this->result = this->name != 0 ? copyinstr(this->name) : "<CodeBlob>"; 442 this->done = 1; 443 } 444 445 dtrace:helper:ustack: 446 /!this->done && this->isMethod/ 447 { 448 MARK_LINE; 449 this->constMethod = copyin_ptr(this->methodPtr + 450 OFFSET_Method_constMethod); 451 452 this->nameIndex = copyin_uint16(this->constMethod + 453 OFFSET_ConstMethod_name_index); 454 455 this->signatureIndex = copyin_uint16(this->constMethod + 456 OFFSET_ConstMethod_signature_index); 457 458 this->constantPool = copyin_ptr(this->constMethod + 459 OFFSET_ConstMethod_constants); 460 461 this->nameSymbol = copyin_ptr(this->constantPool + 462 this->nameIndex * sizeof (pointer) + SIZE_ConstantPool); 463 /* The symbol is a CPSlot and has lower bit set to indicate metadata */ 464 this->nameSymbol &= (~1); /* remove metadata lsb */ 465 466 this->nameSymbolLength = copyin_uint16(this->nameSymbol + 467 OFFSET_Symbol_length); 468 469 this->signatureSymbol = copyin_ptr(this->constantPool + 470 this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool); 471 this->signatureSymbol &= (~1); /* remove metadata lsb */ 472 473 this->signatureSymbolLength = copyin_uint16(this->signatureSymbol + 474 OFFSET_Symbol_length); 475 476 this->klassPtr = copyin_ptr(this->constantPool + 477 OFFSET_ConstantPool_pool_holder); 478 479 this->klassSymbol = copyin_ptr(this->klassPtr + 480 OFFSET_Klass_name); 481 482 this->klassSymbolLength = copyin_uint16(this->klassSymbol + 483 OFFSET_Symbol_length); 484 485 /* 486 * Enough for three strings, plus the '.', plus the trailing '\0'. 487 */ 488 this->result = (char *) alloca(this->klassSymbolLength + 489 this->nameSymbolLength + 490 this->signatureSymbolLength + 2 + 1); 491 492 copyinto(this->klassSymbol + OFFSET_Symbol_body, 493 this->klassSymbolLength, this->result); 494 495 /* 496 * Add the '.' between the class and the name. 497 */ 498 this->result[this->klassSymbolLength] = '.'; 499 500 copyinto(this->nameSymbol + OFFSET_Symbol_body, 501 this->nameSymbolLength, 502 this->result + this->klassSymbolLength + 1); 503 504 copyinto(this->signatureSymbol + OFFSET_Symbol_body, 505 this->signatureSymbolLength, 506 this->result + this->klassSymbolLength + 507 this->nameSymbolLength + 1); 508 509 /* 510 * Now we need to add a trailing '\0' and possibly a tag character. 511 */ 512 this->result[this->klassSymbolLength + 1 + 513 this->nameSymbolLength + 514 this->signatureSymbolLength] = this->suffix; 515 this->result[this->klassSymbolLength + 2 + 516 this->nameSymbolLength + 517 this->signatureSymbolLength] = '\0'; 518 519 this->done = 1; 520 } 521 522 dtrace:helper:ustack: 523 /this->done && this->error == (char *) NULL/ 524 { 525 this->result; 526 } 527 528 dtrace:helper:ustack: 529 /this->done && this->error != (char *) NULL/ 530 { 531 this->error; 532 } 533 534 dtrace:helper:ustack: 535 /!this->done && this->codecache/ 536 { 537 this->done = 1; 538 "error"; 539 } 540 541 542 dtrace:helper:ustack: 543 /!this->done/ 544 { 545 NULL; 546 }