• 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     unsigned int objCount = 0;
154     for (idx = kSkip; (int) idx < methodCount; idx++) {
155         if (dvmIsReflectionMethod(methods[idx])) {
156             continue;
157         }
158         dvmSetObjectArrayElement(classes, objCount,
159                                  (Object *)methods[idx]->clazz);
160         objCount++;
161     }
162     assert(objCount == classes->length);
163 
164 bail:
165     free(methods);
166     dvmReleaseTrackedAlloc((Object*) classes, NULL);
167     RETURN_PTR(classes);
168 }
169 
170 /*
171  * public static StackTraceElement[] getThreadStackTrace(Thread t)
172  *
173  * Retrieve the stack trace of the specified thread and return it as an
174  * array of StackTraceElement.  Returns NULL on failure.
175  */
Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4 * args,JValue * pResult)176 static void Dalvik_dalvik_system_VMStack_getThreadStackTrace(const u4* args,
177     JValue* pResult)
178 {
179     Object* targetThreadObj = (Object*) args[0];
180     Thread* self = dvmThreadSelf();
181     Thread* thread;
182     int* traceBuf;
183 
184     assert(targetThreadObj != NULL);
185 
186     dvmLockThreadList(self);
187 
188     /*
189      * Make sure the thread is still alive and in the list.
190      */
191     for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
192         if (thread->threadObj == targetThreadObj)
193             break;
194     }
195     if (thread == NULL) {
196         LOGI("VMStack.getThreadStackTrace: threadObj %p not active\n",
197             targetThreadObj);
198         dvmUnlockThreadList();
199         RETURN_PTR(NULL);
200     }
201 
202     /*
203      * Suspend the thread, pull out the stack trace, then resume the thread
204      * and release the thread list lock.  If we're being asked to examine
205      * our own stack trace, skip the suspend/resume.
206      */
207     int stackDepth = -1;
208     if (thread != self)
209         dvmSuspendThread(thread);
210     traceBuf = dvmFillInStackTraceRaw(thread, &stackDepth);
211     if (thread != self)
212         dvmResumeThread(thread);
213     dvmUnlockThreadList();
214 
215     /*
216      * Convert the raw buffer into an array of StackTraceElement.
217      */
218     ArrayObject* trace = dvmGetStackTraceRaw(traceBuf, stackDepth);
219     free(traceBuf);
220     RETURN_PTR(trace);
221 }
222 
223 const DalvikNativeMethod dvm_dalvik_system_VMStack[] = {
224     { "getCallingClassLoader",  "()Ljava/lang/ClassLoader;",
225         Dalvik_dalvik_system_VMStack_getCallingClassLoader },
226     { "getCallingClassLoader2", "()Ljava/lang/ClassLoader;",
227         Dalvik_dalvik_system_VMStack_getCallingClassLoader2 },
228     { "getStackClass2", "()Ljava/lang/Class;",
229         Dalvik_dalvik_system_VMStack_getStackClass2 },
230     { "getClasses",             "(IZ)[Ljava/lang/Class;",
231         Dalvik_dalvik_system_VMStack_getClasses },
232     { "getThreadStackTrace",    "(Ljava/lang/Thread;)[Ljava/lang/StackTraceElement;",
233         Dalvik_dalvik_system_VMStack_getThreadStackTrace },
234     { NULL, NULL, NULL },
235 };
236