jhelper.d revision 7081:39231c6e51fe
131921Sbrian/*
231921Sbrian * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
331921Sbrian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
431921Sbrian *
531921Sbrian * This code is free software; you can redistribute it and/or modify it
631921Sbrian * under the terms of the GNU General Public License version 2 only, as
731921Sbrian * published by the Free Software Foundation.
831921Sbrian *
931921Sbrian * This code is distributed in the hope that it will be useful, but WITHOUT
1031921Sbrian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1131921Sbrian * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1231921Sbrian * version 2 for more details (a copy is included in the LICENSE file that
1331921Sbrian * accompanied this code).
1431921Sbrian *
1531921Sbrian * You should have received a copy of the GNU General Public License version
1631921Sbrian * 2 along with this work; if not, write to the Free Software Foundation,
1731921Sbrian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1831921Sbrian *
1931921Sbrian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2031921Sbrian * or visit www.oracle.com if you need additional information or have any
2131921Sbrian * questions.
2231921Sbrian *
2331921Sbrian */
2431921Sbrian
2531921Sbrian/* This file is auto-generated */
2650479Speter#include "JvmOffsetsIndex.h"
2730715Sbrian
2830715Sbrian#define DEBUG
2936285Sbrian
3026940Sbrian#ifdef DEBUG
3136285Sbrian#define MARK_LINE this->line = __LINE__
3258028Sbrian#else
3336285Sbrian#define MARK_LINE
3436285Sbrian#endif
3571657Sbrian
3671657Sbrian#ifdef _LP64
3736285Sbrian#define STACK_BIAS 0x7ff
3874001Sbrian#define pointer uint64_t
3971657Sbrian#else
4071657Sbrian#define STACK_BIAS 0
4171657Sbrian#define pointer uint32_t
4271657Sbrian#endif
4336285Sbrian
4436285Sbrianextern pointer __JvmOffsets;
4571657Sbrian
4671657Sbrian/* GrowableArray<CodeHeaps*>* */
4771657Sbrianextern pointer __1cJCodeCacheG_heaps_;
4871657Sbrian
4971657Sbrianextern pointer __1cIUniverseO_collectedHeap_;
5071657Sbrian
5171657Sbrianextern pointer __1cHnmethodG__vtbl_;
5236285Sbrianextern pointer __1cNMethodG__vtbl_;
5336285Sbrianextern pointer __1cKBufferBlobG__vtbl_;
5436285Sbrian
5536285Sbrian#define copyin_ptr(ADDR)    *(pointer*)  copyin((pointer) (ADDR), sizeof(pointer))
5636285Sbrian#define copyin_uchar(ADDR)  *(uchar_t*)  copyin((pointer) (ADDR), sizeof(uchar_t))
5771657Sbrian#define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t))
5871657Sbrian#define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t))
5971657Sbrian#define copyin_int32(ADDR)  *(int32_t*)  copyin((pointer) (ADDR), sizeof(int32_t))
6036285Sbrian#define copyin_uint8(ADDR)  *(uint8_t*)  copyin((pointer) (ADDR), sizeof(uint8_t))
6171657Sbrian
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
66int init_done;
67
68dtrace: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
89dtrace:helper:ustack:
90{
91  MARK_LINE;
92  /* Initialization of JvmOffsets constants */
93  JvmOffsetsPtr = (pointer) &``__JvmOffsets;
94}
95
96dtrace: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 */
193dtrace: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
206dtrace: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
220dtrace: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
233dtrace: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
246dtrace: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 */
265dtrace: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
273dtrace: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
281dtrace: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
289dtrace: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
297dtrace: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
308dtrace: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
331dtrace: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
339dtrace: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
347dtrace: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
355dtrace: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
363dtrace: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
371dtrace: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
379dtrace: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
388dtrace: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
396dtrace: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
407dtrace: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
416dtrace: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
424dtrace: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
433dtrace: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
442dtrace: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
461  this->nameSymbolLength = copyin_uint16(this->nameSymbol +
462      OFFSET_Symbol_length);
463
464  this->signatureSymbol = copyin_ptr(this->constantPool +
465      this->signatureIndex * sizeof (pointer) + SIZE_ConstantPool);
466
467  this->signatureSymbolLength = copyin_uint16(this->signatureSymbol +
468      OFFSET_Symbol_length);
469
470  this->klassPtr = copyin_ptr(this->constantPool +
471      OFFSET_ConstantPool_pool_holder);
472
473  this->klassSymbol = copyin_ptr(this->klassPtr +
474      OFFSET_Klass_name);
475
476  this->klassSymbolLength = copyin_uint16(this->klassSymbol +
477      OFFSET_Symbol_length);
478
479  /*
480   * Enough for three strings, plus the '.', plus the trailing '\0'.
481   */
482  this->result = (char *) alloca(this->klassSymbolLength +
483      this->nameSymbolLength +
484      this->signatureSymbolLength + 2 + 1);
485
486  copyinto(this->klassSymbol + OFFSET_Symbol_body,
487      this->klassSymbolLength, this->result);
488
489  /*
490   * Add the '.' between the class and the name.
491   */
492  this->result[this->klassSymbolLength] = '.';
493
494  copyinto(this->nameSymbol + OFFSET_Symbol_body,
495      this->nameSymbolLength,
496      this->result + this->klassSymbolLength + 1);
497
498  copyinto(this->signatureSymbol + OFFSET_Symbol_body,
499      this->signatureSymbolLength,
500      this->result + this->klassSymbolLength +
501      this->nameSymbolLength + 1);
502
503  /*
504   * Now we need to add a trailing '\0' and possibly a tag character.
505   */
506  this->result[this->klassSymbolLength + 1 +
507      this->nameSymbolLength +
508      this->signatureSymbolLength] = this->suffix;
509  this->result[this->klassSymbolLength + 2 +
510      this->nameSymbolLength +
511      this->signatureSymbolLength] = '\0';
512
513  this->done = 1;
514}
515
516dtrace:helper:ustack:
517/this->done && this->error == (char *) NULL/
518{
519  this->result;
520}
521
522dtrace:helper:ustack:
523/this->done && this->error != (char *) NULL/
524{
525  this->error;
526}
527
528dtrace:helper:ustack:
529/!this->done && this->codecache/
530{
531  this->done = 1;
532  "error";
533}
534
535
536dtrace:helper:ustack:
537/!this->done/
538{
539  NULL;
540}
541