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 extern pointer __1cJCodeCacheF_heap_;
47 extern pointer __1cIUniverseO_collectedHeap_;
48
49 extern pointer __1cHnmethodG__vtbl_;
50 extern pointer __1cGMethodG__vtbl_;
51 extern pointer __1cKBufferBlobG__vtbl_;
52
53 #define copyin_ptr(ADDR) *(pointer*) copyin((pointer) (ADDR), sizeof(pointer))
54 #define copyin_uchar(ADDR) *(uchar_t*) copyin((pointer) (ADDR), sizeof(uchar_t))
55 #define copyin_uint16(ADDR) *(uint16_t*) copyin((pointer) (ADDR), sizeof(uint16_t))
56 #define copyin_uint32(ADDR) *(uint32_t*) copyin((pointer) (ADDR), sizeof(uint32_t))
57 #define copyin_int32(ADDR) *(int32_t*) copyin((pointer) (ADDR), sizeof(int32_t))
58 #define copyin_uint8(ADDR) *(uint8_t*) copyin((pointer) (ADDR), sizeof(uint8_t))
59
60 #define SAME(x) x
61 #define copyin_offset(JVM_CONST) JVM_CONST = \
62 copyin_int32(JvmOffsetsPtr + SAME(IDX_)JVM_CONST * sizeof(int32_t))
63
64 int init_done;
65
66 dtrace:helper:ustack:
78 this->error = (char *) NULL;
79 this->result = (char *) NULL;
80 this->isMethod = 0;
81 this->codecache = 0;
82 this->klass = (pointer) NULL;
83 this->vtbl = (pointer) NULL;
84 this->suffix = '\0';
85 }
86
87 dtrace:helper:ustack:
88 {
89 MARK_LINE;
90 /* Initialization of JvmOffsets constants */
91 JvmOffsetsPtr = (pointer) &``__JvmOffsets;
92 }
93
94 dtrace:helper:ustack:
95 /!init_done && !this->done/
96 {
97 MARK_LINE;
98 init_done = 1;
99
100 copyin_offset(COMPILER);
101 copyin_offset(OFFSET_CollectedHeap_reserved);
102 copyin_offset(OFFSET_MemRegion_start);
103 copyin_offset(OFFSET_MemRegion_word_size);
104 copyin_offset(SIZE_HeapWord);
105
106 copyin_offset(OFFSET_interpreter_frame_method);
107 copyin_offset(OFFSET_Klass_name);
108 copyin_offset(OFFSET_ConstantPool_pool_holder);
109
110 copyin_offset(OFFSET_HeapBlockHeader_used);
111 copyin_offset(OFFSET_oopDesc_metadata);
112
113 copyin_offset(OFFSET_Symbol_length);
114 copyin_offset(OFFSET_Symbol_body);
115
116 copyin_offset(OFFSET_Method_constMethod);
117 copyin_offset(OFFSET_ConstMethod_constants);
118 copyin_offset(OFFSET_ConstMethod_name_index);
119 copyin_offset(OFFSET_ConstMethod_signature_index);
120
121 copyin_offset(OFFSET_CodeHeap_memory);
122 copyin_offset(OFFSET_CodeHeap_segmap);
123 copyin_offset(OFFSET_CodeHeap_log2_segment_size);
124
125 copyin_offset(OFFSET_VirtualSpace_low);
126 copyin_offset(OFFSET_VirtualSpace_high);
127
128 copyin_offset(OFFSET_CodeBlob_name);
129
130 copyin_offset(OFFSET_nmethod_method);
131 copyin_offset(SIZE_HeapBlockHeader);
132 copyin_offset(SIZE_oopDesc);
133 copyin_offset(SIZE_ConstantPool);
134
135 copyin_offset(OFFSET_NarrowPtrStruct_base);
136 copyin_offset(OFFSET_NarrowPtrStruct_shift);
137
138 /*
139 * The PC to translate is in arg0.
140 */
141 this->pc = arg0;
142
143 /*
144 * The methodPtr is in %l2 on SPARC. This can be found at
145 * offset 8 from the frame pointer on 32-bit processes.
146 */
147 #if defined(__sparc)
148 this->methodPtr = copyin_ptr(arg1 + 2 * sizeof(pointer) + STACK_BIAS);
149 #elif defined(__i386) || defined(__amd64)
150 this->methodPtr = copyin_ptr(arg1 + OFFSET_interpreter_frame_method);
151 #else
152 #error "Don't know architecture"
153 #endif
154
155 this->CodeCache_heap_address = copyin_ptr(&``__1cJCodeCacheF_heap_);
156
157 this->CodeCache_low = copyin_ptr(this->CodeCache_heap_address +
158 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low);
159
160 this->CodeCache_high = copyin_ptr(this->CodeCache_heap_address +
161 OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high);
162
163 this->CodeCache_segmap_low = copyin_ptr(this->CodeCache_heap_address +
164 OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low);
165
166 this->CodeCache_segmap_high = copyin_ptr(this->CodeCache_heap_address +
167 OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_high);
168
169 this->CodeHeap_log2_segment_size = copyin_uint32(
170 this->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size);
171
172 this->Method_vtbl = (pointer) &``__1cGMethodG__vtbl_;
173
174 /*
175 * Get Java heap bounds
176 */
177 this->Universe_collectedHeap = copyin_ptr(&``__1cIUniverseO_collectedHeap_);
178 this->heap_start = copyin_ptr(this->Universe_collectedHeap +
179 OFFSET_CollectedHeap_reserved +
180 OFFSET_MemRegion_start);
181 this->heap_size = SIZE_HeapWord *
182 copyin_ptr(this->Universe_collectedHeap +
183 OFFSET_CollectedHeap_reserved +
184 OFFSET_MemRegion_word_size
185 );
186 this->heap_end = this->heap_start + this->heap_size;
187 }
188
189 dtrace:helper:ustack:
190 /!this->done &&
191 this->CodeCache_low <= this->pc && this->pc < this->CodeCache_high/
192 {
193 MARK_LINE;
194 this->codecache = 1;
195
196 /*
197 * Find start.
198 */
199 this->segment = (this->pc - this->CodeCache_low) >>
200 this->CodeHeap_log2_segment_size;
201 this->block = this->CodeCache_segmap_low;
202 this->tag = copyin_uchar(this->block + this->segment);
203 "second";
204 }
205
206 dtrace:helper:ustack:
207 /!this->done && this->codecache && this->tag > 0/
208 {
209 MARK_LINE;
210 this->tag = copyin_uchar(this->block + this->segment);
211 this->segment = this->segment - this->tag;
212 }
213
214 dtrace:helper:ustack:
215 /!this->done && this->codecache && this->tag > 0/
216 {
217 MARK_LINE;
218 this->tag = copyin_uchar(this->block + this->segment);
219 this->segment = this->segment - this->tag;
220 }
221
222 dtrace:helper:ustack:
223 /!this->done && this->codecache && this->tag > 0/
238 dtrace:helper:ustack:
239 /!this->done && this->codecache && this->tag > 0/
240 {
241 MARK_LINE;
242 this->tag = copyin_uchar(this->block + this->segment);
243 this->segment = this->segment - this->tag;
244 }
245
246 dtrace:helper:ustack:
247 /!this->done && this->codecache && this->tag > 0/
248 {
249 MARK_LINE;
250 this->error = "<couldn't find start>";
251 this->done = 1;
252 }
253
254 dtrace:helper:ustack:
255 /!this->done && this->codecache/
256 {
257 MARK_LINE;
258 this->block = this->CodeCache_low +
259 (this->segment << this->CodeHeap_log2_segment_size);
260 this->used = copyin_uint32(this->block + OFFSET_HeapBlockHeader_used);
261 }
262
263 dtrace:helper:ustack:
264 /!this->done && this->codecache && !this->used/
265 {
266 MARK_LINE;
267 this->error = "<block not in use>";
268 this->done = 1;
269 }
270
271 dtrace:helper:ustack:
272 /!this->done && this->codecache/
273 {
274 MARK_LINE;
275 this->start = this->block + SIZE_HeapBlockHeader;
276 this->vtbl = copyin_ptr(this->start);
277
278 this->nmethod_vtbl = (pointer) &``__1cHnmethodG__vtbl_;
279 this->BufferBlob_vtbl = (pointer) &``__1cKBufferBlobG__vtbl_;
|
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:
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/
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_;
|