blob: 8db4a6b7dd3f517cbb0385e7592d3f619127eb9e [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
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 */
29static 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 */
46static 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/*
Jesse Wilson8210fad2009-07-28 17:34:57 -070059 * public static Class<?> getStackClass2()
60 *
61 * Returns the class of the caller's caller's caller.
62 */
63static 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/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080074 * 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 */
80static 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 */
Barry Hayes364f9d92010-06-11 16:12:47 -0700153 unsigned int objCount = 0;
154 for (idx = kSkip; (int) idx < methodCount; idx++) {
155 if (dvmIsReflectionMethod(methods[idx])) {
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800156 continue;
Barry Hayes364f9d92010-06-11 16:12:47 -0700157 }
158 dvmSetObjectArrayElement(classes, objCount,
159 (Object *)methods[idx]->clazz);
160 objCount++;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800161 }
Barry Hayes364f9d92010-06-11 16:12:47 -0700162 assert(objCount == classes->length);
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800163
164bail:
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 */
176static 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
223const 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 },
Jesse Wilson8210fad2009-07-28 17:34:57 -0700228 { "getStackClass2", "()Ljava/lang/Class;",
229 Dalvik_dalvik_system_VMStack_getStackClass2 },
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800230 { "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};