• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 /*
18  * dalvik.system.VMStack
19  */
20 #include "Dalvik.h"
21 #include "native/InternalNativePriv.h"
22 
23 
24 /*
25  * public static ClassLoader getCallingClassLoader()
26  *
27  * Return the defining class loader of the caller's caller.
28  */
Dalvik_dalvik_system_VMStack_getCallingClassLoader(const u4 * args,JValue * pResult)29 static void Dalvik_dalvik_system_VMStack_getCallingClassLoader(const u4* args,
30     JValue* pResult)
31 {
32     ClassObject* clazz = dvmGetCaller2Class(dvmThreadSelf()->curFrame);
33 
34     UNUSED_PARAMETER(args);
35 
36     if (clazz == NULL)
37         RETURN_PTR(NULL);
38     RETURN_PTR(clazz->classLoader);
39 }
40 
41 /*
42  * public static ClassLoader getCallingClassLoader2()
43  *
44  * Return the defining class loader of the caller's caller's caller.
45  */
Dalvik_dalvik_system_VMStack_getCallingClassLoader2(const u4 * args,JValue * pResult)46 static void Dalvik_dalvik_system_VMStack_getCallingClassLoader2(const u4* args,
47     JValue* pResult)
48 {
49     ClassObject* clazz = dvmGetCaller3Class(dvmThreadSelf()->curFrame);
50 
51     UNUSED_PARAMETER(args);
52 
53     if (clazz == NULL)
54         RETURN_PTR(NULL);
55     RETURN_PTR(clazz->classLoader);
56 }
57 
58 /*
59  * public static Class<?> getStackClass2()
60  *
61  * Returns the class of the caller's caller's caller.
62  */
Dalvik_dalvik_system_VMStack_getStackClass2(const u4 * args,JValue * pResult)63 static void Dalvik_dalvik_system_VMStack_getStackClass2(const u4* args,
64     JValue* pResult)
65 {
66     ClassObject* clazz = dvmGetCaller3Class(dvmThreadSelf()->curFrame);
67 
68     UNUSED_PARAMETER(args);
69 
70     RETURN_PTR(clazz);
71 }
72 
73 /*
74  * public static Class<?>[] getClasses(int maxDepth, boolean stopAtPrivileged)
75  *
76  * Create an array of classes for the methods on the stack, skipping the
77  * first two and all reflection methods.  If "stopAtPrivileged" is set,
78  * stop shortly after we encounter a privileged class.
79  */
Dalvik_dalvik_system_VMStack_getClasses(const u4 * args,JValue * pResult)80 static void Dalvik_dalvik_system_VMStack_getClasses(const u4* args,
81     JValue* pResult)
82 {
83     /* note "maxSize" is unsigned, so -1 turns into a very large value */
84     unsigned int maxSize = args[0];
85     bool stopAtPrivileged = args[1];
86     unsigned int size = 0;
87     const unsigned int kSkip = 2;
88     const Method** methods = NULL;
89     int methodCount;
90 
91     /*
92      * Get an array with the stack trace in it.
93      */
94     if (!dvmCreateStackTraceArray(dvmThreadSelf()->curFrame, &methods,
95             &methodCount))
96     {
97         LOGE("Failed to create stack trace array\n");
98         dvmThrowException("Ljava/lang/InternalError;", NULL);
99         RETURN_VOID();
100     }
101 
102     //int i;
103     //LOGI("dvmCreateStackTraceArray results:\n");
104     //for (i = 0; i < methodCount; i++) {
105     //    LOGI(" %2d: %s.%s\n",
106     //        i, methods[i]->clazz->descriptor, methods[i]->name);
107     //}
108 
109     /*
110      * Run through the array and count up how many elements there are.
111      */
112     unsigned int idx;
113     for (idx = kSkip; (int) idx < methodCount && size < maxSize; idx++) {
114         const Method* meth = methods[idx];
115 
116         if (dvmIsReflectionMethod(meth))
117             continue;
118 
119         if (stopAtPrivileged && dvmIsPrivilegedMethod(meth)) {
120             /*
121              * We want the last element of the array to be the caller of
122              * the privileged method, so we want to include the privileged
123              * method and the next one.
124              */
125             if (maxSize > size + 2)
126                 maxSize = size + 2;
127         }
128 
129         size++;
130     }
131 
132     /*
133      * Create an array object to hold the classes.
134      * TODO: can use gDvm.classJavaLangClassArray here?
135      */
136     ClassObject* classArrayClass = NULL;
137     ArrayObject* classes = NULL;
138     classArrayClass = dvmFindArrayClass("[Ljava/lang/Class;", NULL);
139     if (classArrayClass == NULL) {
140         LOGW("Unable to find java.lang.Class array class\n");
141         goto bail;
142     }
143     classes = dvmAllocArray(classArrayClass, size, kObjectArrayRefWidth,
144                 ALLOC_DEFAULT);
145     if (classes == NULL) {
146         LOGW("Unable to allocate class array (%d elems)\n", size);
147         goto bail;
148     }
149 
150     /*
151      * Fill in the array.
152      */
153     ClassObject** objects = (ClassObject**) classes->contents;
154 
155     unsigned int sidx = 0;
156     for (idx = kSkip; (int) idx < methodCount && sidx < size; idx++) {
157         const Method* meth = methods[idx];
158 
159         if (dvmIsReflectionMethod(meth))
160             continue;
161 
162         *objects++ = meth->clazz;
163         sidx++;
164     }
165 
166 bail:
167     free(methods);
168     dvmReleaseTrackedAlloc((Object*) classes, NULL);
169     RETURN_PTR(classes);
170 }
171 
172 /*
173  * public static StackTraceElement[] getThreadStackTrace(Thread t)
174  *
175  * Retrieve the stack trace of the specified thread and return it as an
176  * array of StackTraceElement.  Returns NULL on failure.
177  */
Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4 * args,JValue * pResult)178 static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
179     JValue* pResult)
180 {
181     Object* targetThreadObj = (Object*) args[0];
182     Thread* self = dvmThreadSelf();
183     Thread* thread;
184     int* traceBuf;
185 
186     assert(targetThreadObj != NULL);
187 
188     dvmLockThreadList(self);
189 
190     /*
191      * Make sure the thread is still alive and in the list.
192      */
193     for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
194         if (thread->threadObj == targetThreadObj)
195             break;
196     }
197     if (thread == NULL) {
198         LOGI("VMStack.getThreadStackTrace: threadObj %p not active\n",
199             targetThreadObj);
200         dvmUnlockThreadList();
201         RETURN_PTR(NULL);
202     }
203 
204     /*
205      * Suspend the thread, pull out the stack trace, then resume the thread
206      * and release the thread list lock.  If we're being asked to examine
207      * our own stack trace, skip the suspend/resume.
208      */
209     int stackDepth = -1;
210     if (thread != self)
211         dvmSuspendThread(thread);
212     traceBuf = dvmFillInStackTraceRaw(thread, &stackDepth);
213     if (thread != self)
214         dvmResumeThread(thread);
215     dvmUnlockThreadList();
216 
217     /*
218      * Convert the raw buffer into an array of StackTraceElement.
219      */
220     ArrayObject* trace = dvmGetStackTraceRaw(traceBuf, stackDepth);
221     free(traceBuf);
222     RETURN_PTR(trace);
223 }
224 
225 const DalvikNativeMethod dvm_dalvik_system_VMStack[] = {
226     { "getCallingClassLoader",  "()Ljava/lang/ClassLoader;",
227         Dalvik_dalvik_system_VMStack_getCallingClassLoader },
228     { "getCallingClassLoader2", "()Ljava/lang/ClassLoader;",
229         Dalvik_dalvik_system_VMStack_getCallingClassLoader2 },
230     { "getStackClass2", "()Ljava/lang/Class;",
231         Dalvik_dalvik_system_VMStack_getStackClass2 },
232     { "getClasses",             "(IZ)[Ljava/lang/Class;",
233         Dalvik_dalvik_system_VMStack_getClasses },
234     { "getThreadStackTrace",    "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;",
235         Dalvik_dalvik_system_VMStack_getThreadStackTrace },
236     { NULL, NULL, NULL },
237 };
238 
239