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 }
547