New hotspot/src/share/vm/prims/stackwalk.cpp (original) (raw)
1 /*
2 * Copyright (c) 2015, 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 #include "precompiled.hpp"
26 #include "classfile/javaClasses.hpp"
27 #include "classfile/javaClasses.inline.hpp"
28 #include "classfile/vmSymbols.hpp"
29 #include "memory/oopFactory.hpp"
30 #include "oops/oop.inline.hpp"
31 #include "oops/objArrayOop.inline.hpp"
32 #include "prims/stackwalk.hpp"
33 #include "runtime/globals.hpp"
34 #include "runtime/handles.inline.hpp"
35 #include "runtime/javaCalls.hpp"
36 #include "runtime/vframe.hpp"
37 #include "utilities/globalDefinitions.hpp"
38
39 // setup and cleanup actions
40 void StackWalkAnchor::setup_magic_on_entry() {
41 _frames->obj_at_put(StackWalk::magic_pos, _thread->threadObj());
42 _anchor = address_value();
43 assert(check_magic(), "invalid magic");
44 }
45
46 bool StackWalkAnchor::check_magic() {
47 oop m1 = _frames->obj_at(StackWalk::magic_pos);
48 jlong m2 = _anchor;
49 if (m1 == _thread->threadObj() && m2 == address_value()) return true;
50 return false;
51 }
52
53 bool StackWalkAnchor::cleanup_magic_on_exit() {
54 bool ok = check_magic();
55 _frames->obj_at_put(StackWalk::magic_pos, NULL);
56 _anchor = 0L;
57 return ok;
58 }
59
60 /*
61 * Returns StackWalkAnchor for the current stack being traversed.
62 *
63 * @argument thread. Current Java thread.
64 * @argument magic. Magic value used for each stack walking
65 * @argument classes_array User-supplied buffers. The 0th element is reserved
66 * to this StackWalkAnchor to use
67 /
68 StackWalkAnchor StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
69 objArrayHandle classes_array)
70 {
71 assert(thread != NULL && thread->is_Java_thread(), "");
72 oop m1 = classes_array->obj_at(StackWalk::magic_pos);
73 if (m1 != thread->threadObj()) return NULL;
74 if (magic == 0L) return NULL;
75 StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic;
76 if (!anchor->is_valid_in(thread)) return NULL;
77 return anchor;
78 }
79
80 /*
81 * Unpacks one or more frames into user-supplied buffers.
82 * Updates the end index, and returns the number of unpacked frames.
83 * Always start with the existing vfst.method and bci.
84 * Do not call vfst.next to advance over the last returned value.
85 * In other words, do not leave any stale data in the vfst.
86 *
87 * @argument mode. Restrict which frames to be decoded.
88 * @argument decode_limit. Maximum of frames to be decoded.
89 * @argument start_index. Start index to the user-supplied buffers.
90 * @argument classes_array. Buffer to store classes in, starting at start_index.
91 * @argument frames_array. Buffer to store StackFrame in, starting at start_index.
92 * NULL if not used.
93 * @argument end_index. End index to the user-supplied buffers
94 * with unpacked frames.
95 *
96 * @return Number of frames whose information was transferred into the buffers.
97 /
98 int StackWalkAnchor::decode_frames(jlong mode, int decode_limit, int start_index,
99 objArrayHandle classes_array,
100 objArrayHandle frames_array,
101 int& end_index, TRAPS) {
102 if (TraceStackWalk) {
103 tty->print_cr("decode_frames limit=%d start=%d frames length=%d",
104 decode_limit, start_index, classes_array->length());
105 }
106 assert(decode_limit > 0, "invalid decode_limit");
107 assert(start_index + decode_limit <= classes_array->length(), "oob");
108
109 int frames_decoded = 0;
110 for (; !_vfst.at_end(); _vfst.next()) {
111 Method method = vfst.method();
112 int bci = vfst.bci();
113
114 if (method == NULL) continue;
115 if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) {
116 if (method->is_hidden()) {
117 if (TraceStackWalk) {
118 tty->print(" hidden method: "); method->print_short_name();
119 tty->print("\n");
120 }
121 continue;
122 }
123 }
124
125 int index = end_index++;
126 if (TraceStackWalk) {
127 tty->print(" %d: frame method: ", index); method->print_short_name();
128 tty->print_cr(" bci=%d", bci);
129 }
130
131 classes_array->obj_at_put(index, method->method_holder()->java_mirror());
132 // fill in StackFrameInfo and initialize MemberName
133 if (StackWalk::live_frame_info(mode)) {
134 Handle stackFrame(frames_array->obj_at(index));
135 StackWalk::fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0);
136 } else if (StackWalk::need_method_info(mode)) {
137 Handle stackFrame(frames_array->obj_at(index));
138 StackWalk::fill_stackframe(stackFrame, method, bci);
139 }
140 if (++frames_decoded >= decode_limit) break;
141 }
142 return frames_decoded;
143 }
144
145 static oop create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) {
146 Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL);
147 instanceKlassHandle ik (THREAD, k);
148
149 JavaValue result(T_OBJECT);
150 JavaCallArguments args;
151 Symbol* signature = NULL;
152
153 // ## TODO: type is only available in LocalVariable table, if present.
154 // ## StackValue type is T_INT or T_OBJECT.
155 switch (values->at(i)->type()) {
156 case T_INT:
157 args.push_int(values->int_at(i));
158 signature = vmSymbols::asPrimitive_int_signature();
159 break;
160
161 case T_LONG:
162 args.push_long(values->long_at(i));
163 signature = vmSymbols::asPrimitive_long_signature();
164 break;
165
166 case T_FLOAT:
167 args.push_float(values->float_at(i));
168 signature = vmSymbols::asPrimitive_float_signature();
169 break;
170
171 case T_DOUBLE:
172 args.push_double(values->double_at(i));
173 signature = vmSymbols::asPrimitive_double_signature();
174 break;
175
176 case T_BYTE:
177 args.push_int(values->int_at(i));
178 signature = vmSymbols::asPrimitive_byte_signature();
179 break;
180
181 case T_SHORT:
182 args.push_int(values->int_at(i));
183 signature = vmSymbols::asPrimitive_short_signature();
184 break;
185
186 case T_CHAR:
187 args.push_int(values->int_at(i));
188 signature = vmSymbols::asPrimitive_char_signature();
189 break;
190
191 case T_BOOLEAN:
192 args.push_int(values->int_at(i));
193 signature = vmSymbols::asPrimitive_boolean_signature();
194 break;
195
196 case T_OBJECT:
197 return values->obj_at(i)();
198
199 case T_CONFLICT:
200 // put a non-null slot
201 args.push_int(0);
202 signature = vmSymbols::asPrimitive_int_signature();
203 break;
204
205 default: ShouldNotReachHere();
206 }
207 JavaCalls::call_static(&result,
208 ik,
209 vmSymbols::asPrimitive_name(),
210 signature,
211 &args,
212 CHECK_NULL);
213 return (instanceOop) result.get_jobject();
214 }
215
216 static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS) {
217 objArrayHandle empty;
218 int length = values->size();
219 objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
220 length, CHECK(empty));
221 objArrayHandle array_h(THREAD, array_oop);
222 for (int i = 0; i < values->size(); i++) {
223 StackValue* st = values->at(i);
224 oop obj = create_primitive_value_instance(values, i, CHECK(empty));
225 if (obj != NULL)
226 array_h->obj_at_put(i, obj);
227 }
228 return array_h;
229 }
230
231 static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
232 int length = monitors->length();
233 objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
234 length, CHECK(objArrayHandle()));
235 objArrayHandle array_h(THREAD, array_oop);
236 for (int i = 0; i < length; i++) {
237 MonitorInfo* monitor = monitors->at(i);
238 array_h->obj_at_put(i, monitor->owner());
239 }
240 return array_h;
241 }
242
243 /*
244 * Fill StackFrameInfo with declaringClass and bci and initialize memberName
245 /
246 void StackWalk::fill_stackframe(Handle stackFrame, const methodHandle& method, int bci) {
247 if (TraceStackWalk) {
248 tty->print(" member name: "); method->print_short_name();
249 tty->print_cr(" bci=%d", bci);
250 }
251
252 java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror());
253 java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci);
254 }
255
256 /
257 * Fill LiveStackFrameInfo with locals, monitors, and expressions
258 /
259
260 void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& method, int bci, javaVFrame jvf, TRAPS) {
261 fill_stackframe(stackFrame, method, bci);
262
263 if (jvf != NULL) {
264 StackValueCollection* locals = jvf->locals();
265 StackValueCollection* expressions = jvf->expressions();
266 GrowableArray<MonitorInfo*>* monitors = jvf->monitors();
267
268 if (!locals->is_empty()) {
269 objArrayHandle locals_h = values_to_object_array(locals, CHECK);
270 java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h());
271 }
272 if (!expressions->is_empty()) {
273 objArrayHandle expressions_h = values_to_object_array(expressions, CHECK);
274 java_lang_LiveStackFrameInfo::set_operands(stackFrame(), expressions_h());
275 }
276 if (monitors->length() > 0) {
277 objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK);
278 java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h());
279 }
280 }
281 }
282
283 /*
284 * Begins stack walking.
285 *
286 * @argument stackStream. StackStream object
287 * @argument mode. Stack walking mode.
288 * @argument skip_frames. Number of frames to be skipped.
289 * @argument frame_count. Number of frames to be traversed.
290 * @argument start_index. Start index to the user-supplied buffers.
291 * @argument classes_array. Buffer to store classes in, starting at start_index.
292 * @argument frames_array. Buffer to store StackFrame in, starting at start_index.
293 * NULL if not used.
294 * @return Object returned from AbstractStackWalker::doStackWalk call.
295 /
296 Handle StackWalk::walk(Handle stackStream, jlong mode,
297 int skip_frames, int frame_count, int start_index,
298 objArrayHandle classes_array,
299 objArrayHandle frames_array,
300 TRAPS)
301 {
302 Handle empty;
303
304 JavaThread jt = (JavaThread*)THREAD;
305 if (TraceStackWalk) {
306 tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d", mode, skip_frames, frame_count);
307 }
308
309 if (need_method_info(mode)) {
310 if (frames_array.is_null()) {
311 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", empty);
312 }
313 }
314
315 Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
316 Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
317
318 methodHandle m_doStackWalk(THREAD, Universe::stack_walker_callback_method());
319
320 // Open up a traversable stream onto my stack.
321 // This stream will be made available by reference to the inner Java call.
322 StackWalkAnchor anchor(jt, classes_array);
323 vframeStream& vfst = anchor.vframe_stream();
324
325 {
326 // Skip all methods from AbstractStackWalker and StackWalk (enclosing method)
327 if (!fill_in_stacktrace(mode)) {
328 while (!vfst.at_end()) {
329 InstanceKlass* ik = vfst.method()->method_holder();
330 if (ik != stackWalker_klass && ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
331 break;
332 }
333
334 if (TraceStackWalk) {
335 tty->print(" skip "); vfst.method()->print_short_name(); tty->print("\n");
336 }
337 vfst.next();
338 }
339 }
340
341 // For exceptions, skip Throwable::fillInStackTrace and methods
342 // of the exception class and superclasses
343 if (fill_in_stacktrace(mode)) {
344 bool skip_to_fillInStackTrace = false;
345 bool skip_throwableInit_check = false;
346 while (!vfst.at_end() && !skip_throwableInit_check) {
347 InstanceKlass* ik = vfst.method()->method_holder();
348 Method* method = vfst.method();
349 if (!skip_to_fillInStackTrace) {
350 if (ik == SystemDictionary::Throwable_klass() &&
351 method->name() == vmSymbols::fillInStackTrace_name()) {
352 // this frame will be skipped
353 skip_to_fillInStackTrace = true;
354 }
355 } else if (!(ik->is_subclass_of(SystemDictionary::Throwable_klass()) &&
356 method->name() == vmSymbols::object_initializer_name())) {
357 // there are none or we've seen them all - either way stop checking
358 skip_throwableInit_check = true;
359 break;
360 }
361
362 if (TraceStackWalk) {
363 tty->print("stack walk: skip "); vfst.method()->print_short_name(); tty->print("\n");
364 }
365 vfst.next();
366 }
367 }
368
369 // stack frame has been traversed individually and resume stack walk
370 // from the stack frame at depth == skip_frames.
371 for (int n=0; n < skip_frames && !vfst.at_end(); vfst.next(), n++) {
372 if (TraceStackWalk) {
373 tty->print(" skip "); vfst.method()->print_short_name();
374 tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
375 p2i(vfst.frame_id()), p2i(vfst.frame_pc()));
376 }
377 }
378 }
379
380 // The Method* pointer in the vfst has a very short shelf life. Grab it now.
381 int end_index = start_index;
382 int numFrames = 0;
383 if (!vfst.at_end()) {
384 numFrames = anchor.decode_frames(mode, frame_count, start_index, classes_array,
385 frames_array, end_index, CHECK_(empty));
386 if (numFrames < 1) {
387 THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", empty);
388 }
389 }
390
391 // call StackStream::doStackWalk to do bulk traversal on the entire stack
392 JavaValue result(T_OBJECT);
393 JavaCallArguments args(stackStream);
394 args.push_long(anchor.address_value());
395 args.push_int(skip_frames);
396 args.push_int(frame_count);
397 args.push_int(start_index);
398 args.push_int(end_index);
399
400 // Link the thread and vframe stream into the callee-visible object:
401 anchor.setup_magic_on_entry();
402
403 JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
404
405 // Do this before anything else happens, to disable any lingering stream objects:
406 bool ok = anchor.cleanup_magic_on_exit();
407
408 // Throw pending exception if we must:
409 (void) (CHECK_(empty));
410
411 if (!ok) {
412 THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", empty);
413 }
414
415 Handle obj(THREAD, (oop) result.get_jobject());
416 // Return normally:
417 return obj;
418
419 }
420
421 /*
422 * Walk the next batch of stack frames
423 *
424 * @argument stackStream. StackStream object
425 * @argument mode. Stack walking mode.
426 * @argument magic. Must be valid value to continue the stack walk
427 * @argument frame_count. Number of frames to be decoded.
428 * @argument start_index. Start index to the user-supplied buffers.
429 * @argument classes_array. Buffer to store classes in, starting at start_index.
430 * @argument frames_array. Buffer to store StackFrame in, starting at start_index.
431 * NULL if not used.
432 * @return End index
433 */
434 jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
435 int frame_count, int start_index,
436 objArrayHandle classes_array,
437 objArrayHandle frames_array,
438 TRAPS)
439 {
440 JavaThread* jt = (JavaThread*)THREAD;
441 StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array);
442 if (existing_anchor == NULL) {
443 THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
444 }
445
446 if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) {
447 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
448 }
449
450 if (TraceStackWalk) {
451 tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d",
452 frame_count, p2i(existing_anchor), start_index, classes_array->length());
453 }
454 int end_index = start_index;
455 if (frame_count <= 0) {
456 return end_index; // No operation.
457 }
458
459 int count = frame_count+start_index;
460 assert (classes_array->length() >= count, "not enough space in buffers");
461
462 StackWalkAnchor& anchor = (*existing_anchor);
463 vframeStream& vfst = anchor.vframe_stream();
464 if (!vfst.at_end()) {
465 vfst.next(); // skip java.lang.StackStream::moreStackWalk
466 if (!vfst.at_end()) {
467 int n = anchor.decode_frames(mode, frame_count, start_index, classes_array,
468 frames_array, end_index, CHECK_0);
469 if (n < 1) {
470 THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
471 }
472 return end_index;
473 }
474 }
475 return end_index;
476 }