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