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