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 "logging/log.hpp"
30 #include "memory/oopFactory.hpp"
31 #include "oops/oop.inline.hpp"
32 #include "oops/objArrayOop.inline.hpp"
33 #include "prims/stackwalk.hpp"
34 #include "runtime/globals.hpp"
35 #include "runtime/handles.inline.hpp"
36 #include "runtime/javaCalls.hpp"
37 #include "runtime/vframe.hpp"
38 #include "utilities/globalDefinitions.hpp"
39
40 // setup and cleanup actions
41 void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
42 frames_array->obj_at_put(magic_pos, _thread->threadObj());
43 _anchor = address_value();
44 assert(check_magic(frames_array), "invalid magic");
45 }
46
47 bool BaseFrameStream::check_magic(objArrayHandle frames_array) {
48 oop m1 = frames_array->obj_at(magic_pos);
49 jlong m2 = _anchor;
104 //
105 int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream,
106 int max_nframes, int start_index,
107 objArrayHandle frames_array,
108 int& end_index, TRAPS) {
109 log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d",
110 max_nframes, start_index, frames_array->length());
111 assert(max_nframes > 0, "invalid max_nframes");
112 assert(start_index + max_nframes <= frames_array->length(), "oob");
113
114 int frames_decoded = 0;
115 for (; !stream.at_end(); stream.next()) {
116 Method* method = stream.method();
117
118 if (method == NULL) continue;
119
120 // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES
121 // not set) and when StackWalker::getCallerClass is called
122 if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) {
123 if (method->is_hidden()) {
124 if (log_is_enabled(Debug, stackwalk)) {
125 ResourceMark rm(THREAD);
126 outputStream* st = Log(stackwalk)::debug_stream();
127 st->print(" hidden method: ");
128 method->print_short_name(st);
129 st->cr();
130 }
131 continue;
132 }
133 }
134
135 int index = end_index++;
136 if (log_is_enabled(Debug, stackwalk)) {
137 ResourceMark rm(THREAD);
138 outputStream* st = Log(stackwalk)::debug_stream();
139 st->print(" %d: frame method: ", index);
140 method->print_short_name(st);
141 st->print_cr(" bci=%d", stream.bci());
142 }
143
144 if (!need_method_info(mode) && get_caller_class(mode) &&
145 index == start_index && method->caller_sensitive()) {
146 ResourceMark rm(THREAD);
147 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
148 err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
149 method->name_and_sig_as_C_string()));
150 }
151 // fill in StackFrameInfo and initialize MemberName
152 stream.fill_frame(index, frames_array, method, CHECK_0);
153 if (++frames_decoded >= max_nframes) break;
154 }
155 return frames_decoded;
156 }
157
158 // Fill in the LiveStackFrameInfo at the given index in frames_array
159 void LiveFrameStream::fill_frame(int index, objArrayHandle frames_array,
160 const methodHandle& method, TRAPS) {
161 Handle stackFrame(THREAD, frames_array->obj_at(index));
347 return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
348 start_index, frames_array, THREAD);
349 }
350 }
351
352 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
353 jlong mode, int skip_frames, int frame_count,
354 int start_index, objArrayHandle frames_array, TRAPS) {
355 methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
356
357 {
358 Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
359 Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
360 while (!stream.at_end()) {
361 InstanceKlass* ik = stream.method()->method_holder();
362 if (ik != stackWalker_klass &&
363 ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
364 break;
365 }
366
367 if (log_is_enabled(Debug, stackwalk)) {
368 ResourceMark rm(THREAD);
369 outputStream* st = Log(stackwalk)::debug_stream();
370 st->print(" skip ");
371 stream.method()->print_short_name(st);
372 st->cr();
373 }
374 stream.next();
375 }
376
377 // stack frame has been traversed individually and resume stack walk
378 // from the stack frame at depth == skip_frames.
379 for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
380 if (log_is_enabled(Debug, stackwalk)) {
381 ResourceMark rm(THREAD);
382 outputStream* st = Log(stackwalk)::debug_stream();
383 st->print(" skip ");
384 stream.method()->print_short_name(st);
385 st->cr();
386 }
387 }
388 }
389
390 int end_index = start_index;
391 int numFrames = 0;
392 if (!stream.at_end()) {
393 numFrames = fill_in_frames(mode, stream, frame_count, start_index,
394 frames_array, end_index, CHECK_NULL);
395 if (numFrames < 1) {
396 THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
397 }
398 }
399
400 // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to
401 // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
402 // which calls the implementation to consume the stack frames.
403 // When JVM_CallStackWalk returns, it invalidates the stack stream.
404 JavaValue result(T_OBJECT);
405 JavaCallArguments args(stackStream);
|
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 "logging/log.hpp"
30 #include "logging/logStream.hpp"
31 #include "memory/oopFactory.hpp"
32 #include "oops/oop.inline.hpp"
33 #include "oops/objArrayOop.inline.hpp"
34 #include "prims/stackwalk.hpp"
35 #include "runtime/globals.hpp"
36 #include "runtime/handles.inline.hpp"
37 #include "runtime/javaCalls.hpp"
38 #include "runtime/vframe.hpp"
39 #include "utilities/globalDefinitions.hpp"
40
41 // setup and cleanup actions
42 void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
43 frames_array->obj_at_put(magic_pos, _thread->threadObj());
44 _anchor = address_value();
45 assert(check_magic(frames_array), "invalid magic");
46 }
47
48 bool BaseFrameStream::check_magic(objArrayHandle frames_array) {
49 oop m1 = frames_array->obj_at(magic_pos);
50 jlong m2 = _anchor;
105 //
106 int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream,
107 int max_nframes, int start_index,
108 objArrayHandle frames_array,
109 int& end_index, TRAPS) {
110 log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d",
111 max_nframes, start_index, frames_array->length());
112 assert(max_nframes > 0, "invalid max_nframes");
113 assert(start_index + max_nframes <= frames_array->length(), "oob");
114
115 int frames_decoded = 0;
116 for (; !stream.at_end(); stream.next()) {
117 Method* method = stream.method();
118
119 if (method == NULL) continue;
120
121 // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES
122 // not set) and when StackWalker::getCallerClass is called
123 if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) {
124 if (method->is_hidden()) {
125 LogTarget(Debug, stackwalk) lt;
126 if (lt.is_enabled()) {
127 ResourceMark rm(THREAD);
128 LogStream ls(lt);
129 ls.print(" hidden method: ");
130 method->print_short_name(&ls);
131 ls.cr();
132 }
133 continue;
134 }
135 }
136
137 int index = end_index++;
138 LogTarget(Debug, stackwalk) lt;
139 if (lt.is_enabled()) {
140 ResourceMark rm(THREAD);
141 LogStream ls(lt);
142 ls.print(" %d: frame method: ", index);
143 method->print_short_name(&ls);
144 ls.print_cr(" bci=%d", stream.bci());
145 }
146
147 if (!need_method_info(mode) && get_caller_class(mode) &&
148 index == start_index && method->caller_sensitive()) {
149 ResourceMark rm(THREAD);
150 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
151 err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
152 method->name_and_sig_as_C_string()));
153 }
154 // fill in StackFrameInfo and initialize MemberName
155 stream.fill_frame(index, frames_array, method, CHECK_0);
156 if (++frames_decoded >= max_nframes) break;
157 }
158 return frames_decoded;
159 }
160
161 // Fill in the LiveStackFrameInfo at the given index in frames_array
162 void LiveFrameStream::fill_frame(int index, objArrayHandle frames_array,
163 const methodHandle& method, TRAPS) {
164 Handle stackFrame(THREAD, frames_array->obj_at(index));
350 return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
351 start_index, frames_array, THREAD);
352 }
353 }
354
355 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
356 jlong mode, int skip_frames, int frame_count,
357 int start_index, objArrayHandle frames_array, TRAPS) {
358 methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
359
360 {
361 Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
362 Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
363 while (!stream.at_end()) {
364 InstanceKlass* ik = stream.method()->method_holder();
365 if (ik != stackWalker_klass &&
366 ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) {
367 break;
368 }
369
370 LogTarget(Debug, stackwalk) lt;
371 if (lt.is_enabled()) {
372 ResourceMark rm(THREAD);
373 LogStream ls(lt);
374 ls.print(" skip ");
375 stream.method()->print_short_name(&ls);
376 ls.cr();
377 }
378 stream.next();
379 }
380
381 // stack frame has been traversed individually and resume stack walk
382 // from the stack frame at depth == skip_frames.
383 for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
384 LogTarget(Debug, stackwalk) lt;
385 if (lt.is_enabled()) {
386 ResourceMark rm(THREAD);
387 LogStream ls(lt);
388 ls.print(" skip ");
389 stream.method()->print_short_name(&ls);
390 ls.cr();
391 }
392 }
393 }
394
395 int end_index = start_index;
396 int numFrames = 0;
397 if (!stream.at_end()) {
398 numFrames = fill_in_frames(mode, stream, frame_count, start_index,
399 frames_array, end_index, CHECK_NULL);
400 if (numFrames < 1) {
401 THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
402 }
403 }
404
405 // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to
406 // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
407 // which calls the implementation to consume the stack frames.
408 // When JVM_CallStackWalk returns, it invalidates the stack stream.
409 JavaValue result(T_OBJECT);
410 JavaCallArguments args(stackStream);
|