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_and_refcount);
 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   /* Because sparc is big endian, the top half length is at the correct offset. */
 467   this->nameSymbolLength = copyin_uint16(this->nameSymbol +
 468       OFFSET_Symbol_length_and_refcount);
 469 
 470   this->signatureSymbol = copyin_ptr(this->constantPool +
 471       this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
 472   this->signatureSymbol &= (~1); /* remove metadata lsb */
 473 
 474   this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
 475       OFFSET_Symbol_length_and_refcount);
 476 
 477   this->klassPtr = copyin_ptr(this->constantPool +
 478       OFFSET_ConstantPool_pool_holder);
 479 
 480   this->klassSymbol = copyin_ptr(this->klassPtr +
 481       OFFSET_Klass_name);
 482 
 483   this->klassSymbolLength = copyin_uint16(this->klassSymbol +
 484       OFFSET_Symbol_length_and_refcount);
 485 
 486   /*
 487    * Enough for three strings, plus the '.', plus the trailing '\0'.
 488    */
 489   this->result = (char *) alloca(this->klassSymbolLength +
 490       this->nameSymbolLength +
 491       this->signatureSymbolLength + 2 + 1);
 492 
 493   copyinto(this->klassSymbol + OFFSET_Symbol_body,
 494       this->klassSymbolLength, this->result);
 495 
 496   /*
 497    * Add the '.' between the class and the name.
 498    */
 499   this->result[this->klassSymbolLength] = '.';
 500 
 501   copyinto(this->nameSymbol + OFFSET_Symbol_body,
 502       this->nameSymbolLength,
 503       this->result + this->klassSymbolLength + 1);
 504 
 505   copyinto(this->signatureSymbol + OFFSET_Symbol_body,
 506       this->signatureSymbolLength,
 507       this->result + this->klassSymbolLength +
 508       this->nameSymbolLength + 1);
 509 
 510   /*
 511    * Now we need to add a trailing '\0' and possibly a tag character.
 512    */
 513   this->result[this->klassSymbolLength + 1 +
 514       this->nameSymbolLength +
 515       this->signatureSymbolLength] = this->suffix;
 516   this->result[this->klassSymbolLength + 2 +
 517       this->nameSymbolLength +
 518       this->signatureSymbolLength] = '\0';
 519 
 520   this->done = 1;
 521 }
 522 
 523 dtrace:helper:ustack:
 524 /this->done && this->error == (char *) NULL/
 525 {
 526   this->result;
 527 }
 528 
 529 dtrace:helper:ustack:
 530 /this->done && this->error != (char *) NULL/
 531 {
 532   this->error;
 533 }
 534 
 535 dtrace:helper:ustack:
 536 /!this->done && this->codecache/
 537 {
 538   this->done = 1;
 539   "error";
 540 }
 541 
 542 
 543 dtrace:helper:ustack:
 544 /!this->done/
 545 {
 546   NULL;
 547 }