18daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes/* 28daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Copyright (C) 2008 The Android Open Source Project 38daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * 48daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 58daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * you may not use this file except in compliance with the License. 68daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * You may obtain a copy of the License at 78daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * 88daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 98daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * 108daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * Unless required by applicable law or agreed to in writing, software 118daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 128daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * See the License for the specific language governing permissions and 148daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes * limitations under the License. 158daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes */ 168daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "dalvik_system_VMStack.h" 18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 19e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier#include "art_method-inl.h" 20eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes#include "jni_internal.h" 216a144338023bdc0ca6954fc71a1f9b4d94088ee4Elliott Hughes#include "nth_caller_visitor.h" 224f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/class-inl.h" 232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 244f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 251eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers#include "scoped_fast_native_object_access.h" 2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h" 2701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes#include "thread_list.h" 288daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesnamespace art { 308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 3153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogersstatic jobject GetThreadStack(const ScopedFastNativeObjectAccess& soa, jobject peer) 3290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier SHARED_REQUIRES(Locks::mutator_lock_) { 3353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers jobject trace = nullptr; 3453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers if (soa.Decode<mirror::Object*>(peer) == soa.Self()->GetPeer()) { 35ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz trace = soa.Self()->CreateInternalStackTrace<false>(soa); 3600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } else { 3753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers // Suspend thread to build stack trace. 384f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier ScopedThreadSuspension sts(soa.Self(), kNative); 39ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom ThreadList* thread_list = Runtime::Current()->GetThreadList(); 4053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers bool timed_out; 414ad5cd3e7d519484559ef778d96fb3f0be8919faIan Rogers Thread* thread = thread_list->SuspendThreadByPeer(peer, true, false, &timed_out); 4253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers if (thread != nullptr) { 4353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers // Must be runnable to create returned array. 44f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier { 45f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier ScopedObjectAccess soa2(soa.Self()); 46f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier trace = thread->CreateInternalStackTrace<false>(soa); 47f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier } 4853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers // Restart suspended thread. 49ba32de47e32f436d7c11cb4a2e78bdd4ad4dc5d2Brian Carlstrom thread_list->Resume(thread, false); 504f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier } else if (timed_out) { 514f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier LOG(ERROR) << "Trying to get thread's stack failed as the thread failed to suspend within a " 524f55e22630d99ca0edd9e951e5ee96b57bb9b980Mathieu Chartier "generous timeout."; 5315bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers } 5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 5553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers return trace; 5601158d7a57c8321370667a6045220237d16e0da8Elliott Hughes} 5701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes 58306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogersstatic jint VMStack_fillStackTraceElements(JNIEnv* env, jclass, jobject javaThread, 59306057fd278d75bf3794bd5243a3b6652c487d18Ian Rogers jobjectArray javaSteArray) { 6053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers ScopedFastNativeObjectAccess soa(env); 6153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers jobject trace = GetThreadStack(soa, javaThread); 6253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers if (trace == nullptr) { 6301158d7a57c8321370667a6045220237d16e0da8Elliott Hughes return 0; 6401158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 6501158d7a57c8321370667a6045220237d16e0da8Elliott Hughes int32_t depth; 6653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers Thread::InternalStackTraceToStackTraceElementArray(soa, trace, javaSteArray, &depth); 6701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes return depth; 688daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} 698daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 706a144338023bdc0ca6954fc71a1f9b4d94088ee4Elliott Hughes// Returns the defining class loader of the caller's caller. 710512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jobject VMStack_getCallingClassLoader(JNIEnv* env, jclass) { 721eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers ScopedFastNativeObjectAccess soa(env); 737a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers NthCallerVisitor visitor(soa.Self(), 2); 740399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 75718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe if (UNLIKELY(visitor.caller == nullptr)) { 76718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe // The caller is an attached native thread. 77718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe return nullptr; 78718ac65aa78403124c2269f0dcadd341a18b8efeAndreas Gampe } 7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return soa.AddLocalReference<jobject>(visitor.caller->GetDeclaringClass()->GetClassLoader()); 808daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} 818daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 82598854726a5d50c18fa720af6b097279e5e01584Brian Carlstromstatic jobject VMStack_getClosestUserClassLoader(JNIEnv* env, jclass) { 830399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers struct ClosestUserClassLoaderVisitor : public StackVisitor { 84598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom explicit ClosestUserClassLoaderVisitor(Thread* thread) 858e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray : StackVisitor(thread, nullptr, StackVisitor::StackWalkKind::kIncludeInlinedFrames), 868e5bd18fc665d7ec5461ea068e98740a65da754cNicolas Geoffray class_loader(nullptr) {} 8708fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes 8890443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier bool VisitFrame() SHARED_REQUIRES(Locks::mutator_lock_) { 89598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom DCHECK(class_loader == nullptr); 902dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Class* c = GetMethod()->GetDeclaringClass(); 91e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier // c is null for runtime methods. 92e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (c != nullptr) { 93e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier mirror::Object* cl = c->GetClassLoader(); 94e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier if (cl != nullptr) { 95e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier class_loader = cl; 96e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier return false; 97e401d146407d61eeb99f8d6176b2ac13c4df1e33Mathieu Chartier } 985cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom } 99530fa005e2944d3b12712f80d974f0e753f568efElliott Hughes return true; 1005cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom } 10108fc03ae5dded4adc9b45b7014a4b9dfedbe95a6Elliott Hughes 1022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mirror::Object* class_loader; 1035cb71bb4437db51f415e57e6002ba1ef023e7de1Brian Carlstrom }; 1041eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers ScopedFastNativeObjectAccess soa(env); 105598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom ClosestUserClassLoaderVisitor visitor(soa.Self()); 1060399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 10700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return soa.AddLocalReference<jobject>(visitor.class_loader); 1088daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} 1098daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 1106a144338023bdc0ca6954fc71a1f9b4d94088ee4Elliott Hughes// Returns the class of the caller's caller's caller. 1110512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jclass VMStack_getStackClass2(JNIEnv* env, jclass) { 1121eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers ScopedFastNativeObjectAccess soa(env); 1137a22fa657b972e8323692368975bc5a7be1cc0f5Ian Rogers NthCallerVisitor visitor(soa.Self(), 3); 1140399dde18753aa9bd2bd0d7cf60beef154d164a4Ian Rogers visitor.WalkStack(); 1150d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe if (UNLIKELY(visitor.caller == nullptr)) { 1160d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe // The caller is an attached native thread. 1170d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe return nullptr; 1180d334ce54efd791da14536b6a16f61d9085b8785Andreas Gampe } 11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return soa.AddLocalReference<jclass>(visitor.caller->GetDeclaringClass()); 1208daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} 1218daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 1220512f02dd6623c0870c11fbf3274d7462f732136Elliott Hughesstatic jobjectArray VMStack_getThreadStackTrace(JNIEnv* env, jclass, jobject javaThread) { 12353b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers ScopedFastNativeObjectAccess soa(env); 12453b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers jobject trace = GetThreadStack(soa, javaThread); 12553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers if (trace == nullptr) { 12653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers return nullptr; 12701158d7a57c8321370667a6045220237d16e0da8Elliott Hughes } 12853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers return Thread::InternalStackTraceToStackTraceElementArray(soa, trace); 1298daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} 1308daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 1318daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesstatic JNINativeMethod gMethods[] = { 13253b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers NATIVE_METHOD(VMStack, fillStackTraceElements, "!(Ljava/lang/Thread;[Ljava/lang/StackTraceElement;)I"), 1331eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers NATIVE_METHOD(VMStack, getCallingClassLoader, "!()Ljava/lang/ClassLoader;"), 134598854726a5d50c18fa720af6b097279e5e01584Brian Carlstrom NATIVE_METHOD(VMStack, getClosestUserClassLoader, "!()Ljava/lang/ClassLoader;"), 1351eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers NATIVE_METHOD(VMStack, getStackClass2, "!()Ljava/lang/Class;"), 13653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers NATIVE_METHOD(VMStack, getThreadStackTrace, "!(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;"), 1378daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes}; 1388daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 1398daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughesvoid register_dalvik_system_VMStack(JNIEnv* env) { 140eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes REGISTER_NATIVE_METHODS("dalvik/system/VMStack"); 1418daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} 1428daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes 1438daa0929f08a3080ea64dbd4e997e72f411e6fc9Elliott Hughes} // namespace art 144