Stack.cpp revision 8e5c78470229fd2f5474574081eaa4a2286aafea
1743968520a8a6c1e23212d4ed155d053891f630aLogan Chien/*
21c30cee77f9a148215a0dacee2d922d1ec1b3baeZonr Chang * Copyright (C) 2008 The Android Open Source Project
3743968520a8a6c1e23212d4ed155d053891f630aLogan Chien *
4743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * Licensed under the Apache License, Version 2.0 (the "License");
5743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * you may not use this file except in compliance with the License.
6743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * You may obtain a copy of the License at
7743968520a8a6c1e23212d4ed155d053891f630aLogan Chien *
8743968520a8a6c1e23212d4ed155d053891f630aLogan Chien *      http://www.apache.org/licenses/LICENSE-2.0
9743968520a8a6c1e23212d4ed155d053891f630aLogan Chien *
10743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * Unless required by applicable law or agreed to in writing, software
11743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * distributed under the License is distributed on an "AS IS" BASIS,
12743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * See the License for the specific language governing permissions and
14743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * limitations under the License.
15743968520a8a6c1e23212d4ed155d053891f630aLogan Chien */
16743968520a8a6c1e23212d4ed155d053891f630aLogan Chien/*
17743968520a8a6c1e23212d4ed155d053891f630aLogan Chien * Stacks and their uses (e.g. native --> interpreted method calls).
18743968520a8a6c1e23212d4ed155d053891f630aLogan Chien *
19b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines * See the majestic ASCII art in Stack.h.
20743968520a8a6c1e23212d4ed155d053891f630aLogan Chien */
21743968520a8a6c1e23212d4ed155d053891f630aLogan Chien#include "Dalvik.h"
22743968520a8a6c1e23212d4ed155d053891f630aLogan Chien#include "jni.h"
23743968520a8a6c1e23212d4ed155d053891f630aLogan Chien
24743968520a8a6c1e23212d4ed155d053891f630aLogan Chien#include <stdlib.h>
25743968520a8a6c1e23212d4ed155d053891f630aLogan Chien#include <stdarg.h>
261c30cee77f9a148215a0dacee2d922d1ec1b3baeZonr Chang
27d2a5a0eab7a1273797029702652e50b2ed9e6a6dShih-wei Liao/*
28862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * Initialize the interpreter stack in a new thread.
292f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines *
30f74ee1940ac8e01c862e90de49eb10982648f6a1Zonr Chang * Currently this doesn't do much, since we don't need to zero out the
310f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * stack (and we really don't want to if it was created with mmap).
324f94c520f8d699a5973956a1716272146be17128Zonr Chang */
33094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Maleabool dvmInitInterpStack(Thread* thread, int stackSize)
34094881f513ab366f7ffd0b2c7778ab50281ca59eDaniel Malea{
35f74ee1940ac8e01c862e90de49eb10982648f6a1Zonr Chang    assert(thread->interpStackStart != NULL);
364f94c520f8d699a5973956a1716272146be17128Zonr Chang
374a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines    assert(thread->curFrame == NULL);
384a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines
390f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    return true;
404f94c520f8d699a5973956a1716272146be17128Zonr Chang}
410f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang
427a66e6cbb1ae32cd56b19822c4e66560deb857dbShih-wei Liao/*
431e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * We're calling an interpreted method from an internal VM function or
441e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * via reflection.
451e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang *
461e2adce6df4414d827149ec563c9c89f21ea7426Zonr Chang * Push a frame for an interpreted method onto the stack.  This is only
47ccc39a8f412edaec2d231ed1ec70ff25fa83af37Zonr Chang * used when calling into interpreted code from native code.  (The
48862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * interpreter does its own stack frame manipulation for interp-->interp
492f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines * calls.)
504a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines *
514a68b1cb89df9507584a51c3444aff99347afb74Stephen Hines * The size we need to reserve is the sum of parameters, local variables,
522f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines * saved goodies, and outbound parameters.
53862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang *
54862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * We start by inserting a "break" frame, which ensures that the interpreter
55f74ee1940ac8e01c862e90de49eb10982648f6a1Zonr Chang * hands control back to us after the function we call returns or an
56f74ee1940ac8e01c862e90de49eb10982648f6a1Zonr Chang * uncaught exception is thrown.
57b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines */
58743968520a8a6c1e23212d4ed155d053891f630aLogan Chienstatic bool dvmPushInterpFrame(Thread* self, const Method* method)
59743968520a8a6c1e23212d4ed155d053891f630aLogan Chien{
60743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    StackSaveArea* saveBlock;
61743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    StackSaveArea* breakSaveBlock;
62743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    int stackReq;
63743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    u1* stackPtr;
64743968520a8a6c1e23212d4ed155d053891f630aLogan Chien
65743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    assert(!dvmIsNativeMethod(method));
66743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    assert(!dvmIsAbstractMethod(method));
67743968520a8a6c1e23212d4ed155d053891f630aLogan Chien
6867005271fbab5e4919cc2119f6e234642ec409bdLogan Chien    stackReq = method->registersSize * 4        // params + locals
69b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines                + sizeof(StackSaveArea) * 2     // break frame + regular frame
70b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines                + method->outsSize * 4;         // args to other methods
71b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines
720f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    if (self->curFrame != NULL)
730f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
740f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    else
750f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang        stackPtr = self->interpStackStart;
76743968520a8a6c1e23212d4ed155d053891f630aLogan Chien
772f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines    if (stackPtr - stackReq < self->interpStackEnd) {
78743968520a8a6c1e23212d4ed155d053891f630aLogan Chien        /* not enough space */
79b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines        LOGW("Stack overflow on call to interp (top=%p cur=%p size=%d %s.%s)\n",
80b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines            self->interpStackStart, self->curFrame, self->interpStackSize,
81b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines            method->clazz->descriptor, method->name);
82743968520a8a6c1e23212d4ed155d053891f630aLogan Chien        dvmHandleStackOverflow(self);
83743968520a8a6c1e23212d4ed155d053891f630aLogan Chien        assert(dvmCheckException(self));
84743968520a8a6c1e23212d4ed155d053891f630aLogan Chien        return false;
85743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    }
86743968520a8a6c1e23212d4ed155d053891f630aLogan Chien
87743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    /*
88743968520a8a6c1e23212d4ed155d053891f630aLogan Chien     * Shift the stack pointer down, leaving space for the function's
89743968520a8a6c1e23212d4ed155d053891f630aLogan Chien     * args/registers and save area.
90743968520a8a6c1e23212d4ed155d053891f630aLogan Chien     */
91743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    stackPtr -= sizeof(StackSaveArea);
92743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    breakSaveBlock = (StackSaveArea*)stackPtr;
93743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
94b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines    saveBlock = (StackSaveArea*) stackPtr;
9567005271fbab5e4919cc2119f6e234642ec409bdLogan Chien
96b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
97b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines    /* debug -- memset the new stack, unless we want valgrind's help */
980f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    memset(stackPtr - (method->outsSize*4), 0xaf, stackReq);
990f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#endif
1000f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#ifdef EASY_GDB
1010f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang    breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
10267005271fbab5e4919cc2119f6e234642ec409bdLogan Chien    saveBlock->prevSave = breakSaveBlock;
103743968520a8a6c1e23212d4ed155d053891f630aLogan Chien#endif
1042f6a493aea1b6e5ad318a759fedb58713a5a374cStephen Hines
105743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    breakSaveBlock->prevFrame = self->curFrame;
106b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines    breakSaveBlock->savedPc = NULL;             // not required
107b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines    breakSaveBlock->xtra.localRefTop = NULL;    // not required
108b8ef690813bf3b32f996afb0ddc048c5bb23c8f5Stephen Hines    breakSaveBlock->method = NULL;
109743968520a8a6c1e23212d4ed155d053891f630aLogan Chien    saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
110    saveBlock->savedPc = NULL;                  // not required
111    saveBlock->xtra.currentPc = NULL;           // not required?
112    saveBlock->method = method;
113
114    LOGVV("PUSH frame: old=%p new=%p (size=%d)\n",
115        self->curFrame, FP_FROM_SAVEAREA(saveBlock),
116        (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
117
118    self->curFrame = FP_FROM_SAVEAREA(saveBlock);
119
120    return true;
121}
122
123/*
124 * We're calling a JNI native method from an internal VM fuction or
125 * via reflection.  This is also used to create the "fake" native-method
126 * frames at the top of the interpreted stack.
127 *
128 * This actually pushes two frames; the first is a "break" frame.
129 *
130 * The top frame has additional space for JNI local reference tracking.
131 */
132bool dvmPushJNIFrame(Thread* self, const Method* method)
133{
134    StackSaveArea* saveBlock;
135    StackSaveArea* breakSaveBlock;
136    int stackReq;
137    u1* stackPtr;
138
139    assert(dvmIsNativeMethod(method));
140
141    stackReq = method->registersSize * 4        // params only
142                + sizeof(StackSaveArea) * 2;    // break frame + regular frame
143
144    if (self->curFrame != NULL)
145        stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
146    else
147        stackPtr = self->interpStackStart;
148
149    if (stackPtr - stackReq < self->interpStackEnd) {
150        /* not enough space */
151        LOGW("Stack overflow on call to native (top=%p cur=%p size=%d '%s')\n",
152            self->interpStackStart, self->curFrame, self->interpStackSize,
153            method->name);
154        dvmHandleStackOverflow(self);
155        assert(dvmCheckException(self));
156        return false;
157    }
158
159    /*
160     * Shift the stack pointer down, leaving space for just the stack save
161     * area for the break frame, then shift down farther for the full frame.
162     * We leave space for the method args, which are copied in later.
163     */
164    stackPtr -= sizeof(StackSaveArea);
165    breakSaveBlock = (StackSaveArea*)stackPtr;
166    stackPtr -= method->registersSize * 4 + sizeof(StackSaveArea);
167    saveBlock = (StackSaveArea*) stackPtr;
168
169#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
170    /* debug -- memset the new stack */
171    memset(stackPtr, 0xaf, stackReq);
172#endif
173#ifdef EASY_GDB
174    if (self->curFrame == NULL)
175        breakSaveBlock->prevSave = NULL;
176    else
177        breakSaveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
178    saveBlock->prevSave = breakSaveBlock;
179#endif
180
181    breakSaveBlock->prevFrame = self->curFrame;
182    breakSaveBlock->savedPc = NULL;             // not required
183    breakSaveBlock->xtra.localRefTop = NULL;    // not required
184    breakSaveBlock->method = NULL;
185    saveBlock->prevFrame = FP_FROM_SAVEAREA(breakSaveBlock);
186    saveBlock->savedPc = NULL;                  // not required
187    saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
188    saveBlock->method = method;
189
190    LOGVV("PUSH JNI frame: old=%p new=%p (size=%d)\n",
191        self->curFrame, FP_FROM_SAVEAREA(saveBlock),
192        (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
193
194    self->curFrame = FP_FROM_SAVEAREA(saveBlock);
195
196    return true;
197}
198
199/*
200 * This is used by the JNI PushLocalFrame call.  We push a new frame onto
201 * the stack that has no ins, outs, or locals, and no break frame above it.
202 * It's strictly used for tracking JNI local refs, and will be popped off
203 * by dvmPopFrame if it's not removed explicitly.
204 */
205bool dvmPushLocalFrame(Thread* self, const Method* method)
206{
207    StackSaveArea* saveBlock;
208    int stackReq;
209    u1* stackPtr;
210
211    assert(dvmIsNativeMethod(method));
212
213    stackReq = sizeof(StackSaveArea);       // regular frame
214
215    assert(self->curFrame != NULL);
216    stackPtr = (u1*) SAVEAREA_FROM_FP(self->curFrame);
217
218    if (stackPtr - stackReq < self->interpStackEnd) {
219        /* not enough space; let JNI throw the exception */
220        LOGW("Stack overflow on PushLocal (top=%p cur=%p size=%d '%s')\n",
221            self->interpStackStart, self->curFrame, self->interpStackSize,
222            method->name);
223        dvmHandleStackOverflow(self);
224        assert(dvmCheckException(self));
225        return false;
226    }
227
228    /*
229     * Shift the stack pointer down, leaving space for just the stack save
230     * area for the break frame, then shift down farther for the full frame.
231     */
232    stackPtr -= sizeof(StackSaveArea);
233    saveBlock = (StackSaveArea*) stackPtr;
234
235#if !defined(NDEBUG) && !defined(PAD_SAVE_AREA)
236    /* debug -- memset the new stack */
237    memset(stackPtr, 0xaf, stackReq);
238#endif
239#ifdef EASY_GDB
240    saveBlock->prevSave = FP_FROM_SAVEAREA(self->curFrame);
241#endif
242
243    saveBlock->prevFrame = self->curFrame;
244    saveBlock->savedPc = NULL;                  // not required
245    saveBlock->xtra.localRefTop = self->jniLocalRefTable.nextEntry;
246    saveBlock->method = method;
247
248    LOGVV("PUSH JNI local frame: old=%p new=%p (size=%d)\n",
249        self->curFrame, FP_FROM_SAVEAREA(saveBlock),
250        (u1*)self->curFrame - (u1*)FP_FROM_SAVEAREA(saveBlock));
251
252    self->curFrame = FP_FROM_SAVEAREA(saveBlock);
253
254    return true;
255}
256
257/*
258 * Pop one frame pushed on by JNI PushLocalFrame.
259 *
260 * If we've gone too far, the previous frame is either a break frame or
261 * an interpreted frame.  Either way, the method pointer won't match.
262 */
263bool dvmPopLocalFrame(Thread* self)
264{
265    StackSaveArea* saveBlock = SAVEAREA_FROM_FP(self->curFrame);
266
267    assert(!dvmIsBreakFrame(self->curFrame));
268    if (saveBlock->method != SAVEAREA_FROM_FP(saveBlock->prevFrame)->method) {
269        /*
270         * The previous frame doesn't have the same method pointer -- we've
271         * been asked to pop too much.
272         */
273        assert(dvmIsBreakFrame(saveBlock->prevFrame) ||
274               !dvmIsNativeMethod(
275                       SAVEAREA_FROM_FP(saveBlock->prevFrame)->method));
276        return false;
277    }
278
279    LOGVV("POP JNI local frame: removing %s, now %s\n",
280        saveBlock->method->name,
281        SAVEAREA_FROM_FP(saveBlock->prevFrame)->method->name);
282    dvmPopJniLocals(self, saveBlock);
283    self->curFrame = saveBlock->prevFrame;
284
285    return true;
286}
287
288/*
289 * Pop a frame we added.  There should be one method frame and one break
290 * frame.
291 *
292 * If JNI Push/PopLocalFrame calls were mismatched, we might end up
293 * popping multiple method frames before we find the break.
294 *
295 * Returns "false" if there was no frame to pop.
296 */
297static bool dvmPopFrame(Thread* self)
298{
299    StackSaveArea* saveBlock;
300
301    if (self->curFrame == NULL)
302        return false;
303
304    saveBlock = SAVEAREA_FROM_FP(self->curFrame);
305    assert(!dvmIsBreakFrame(self->curFrame));
306
307    /*
308     * Remove everything up to the break frame.  If this was a call into
309     * native code, pop the JNI local references table.
310     */
311    while (saveBlock->prevFrame != NULL && saveBlock->method != NULL) {
312        /* probably a native->native JNI call */
313
314        if (dvmIsNativeMethod(saveBlock->method)) {
315            LOGVV("Popping JNI stack frame for %s.%s%s\n",
316                saveBlock->method->clazz->descriptor,
317                saveBlock->method->name,
318                (SAVEAREA_FROM_FP(saveBlock->prevFrame)->method == NULL) ?
319                "" : " (JNI local)");
320            assert(saveBlock->xtra.localRefTop != NULL);
321            assert(saveBlock->xtra.localRefTop >=self->jniLocalRefTable.table &&
322                saveBlock->xtra.localRefTop <=self->jniLocalRefTable.nextEntry);
323
324            dvmPopJniLocals(self, saveBlock);
325        }
326
327        saveBlock = SAVEAREA_FROM_FP(saveBlock->prevFrame);
328    }
329    if (saveBlock->method != NULL) {
330        LOGE("PopFrame missed the break\n");
331        assert(false);
332        dvmAbort();     // stack trashed -- nowhere to go in this thread
333    }
334
335    LOGVV("POP frame: cur=%p new=%p\n",
336        self->curFrame, saveBlock->prevFrame);
337
338    self->curFrame = saveBlock->prevFrame;
339    return true;
340}
341
342/*
343 * Common code for dvmCallMethodV/A and dvmInvokeMethod.
344 *
345 * Pushes a call frame on, advancing self->curFrame.
346 */
347static ClassObject* callPrep(Thread* self, const Method* method, Object* obj,
348    bool checkAccess)
349{
350    ClassObject* clazz;
351
352#ifndef NDEBUG
353    if (self->status != THREAD_RUNNING) {
354        LOGW("threadid=%d: status=%d on call to %s.%s -\n",
355            self->threadId, self->status,
356            method->clazz->descriptor, method->name);
357    }
358#endif
359
360    assert(self != NULL);
361    assert(method != NULL);
362
363    if (obj != NULL)
364        clazz = obj->clazz;
365    else
366        clazz = method->clazz;
367
368    IF_LOGVV() {
369        char* desc = dexProtoCopyMethodDescriptor(&method->prototype);
370        LOGVV("thread=%d native code calling %s.%s %s\n", self->threadId,
371            clazz->descriptor, method->name, desc);
372        free(desc);
373    }
374
375    if (checkAccess) {
376        /* needed for java.lang.reflect.Method.invoke */
377        if (!dvmCheckMethodAccess(dvmGetCaller2Class(self->curFrame),
378                method))
379        {
380            /* note this throws IAException, not IAError */
381            dvmThrowException("Ljava/lang/IllegalAccessException;",
382                "access to method denied");
383            return NULL;
384        }
385    }
386
387    /*
388     * Push a call frame on.  If there isn't enough room for ins, locals,
389     * outs, and the saved state, it will throw an exception.
390     *
391     * This updates self->curFrame.
392     */
393    if (dvmIsNativeMethod(method)) {
394        /* native code calling native code the hard way */
395        if (!dvmPushJNIFrame(self, method)) {
396            assert(dvmCheckException(self));
397            return NULL;
398        }
399    } else {
400        /* native code calling interpreted code */
401        if (!dvmPushInterpFrame(self, method)) {
402            assert(dvmCheckException(self));
403            return NULL;
404        }
405    }
406
407    return clazz;
408}
409
410/*
411 * Issue a method call.
412 *
413 * Pass in NULL for "obj" on calls to static methods.
414 *
415 * (Note this can't be inlined because it takes a variable number of args.)
416 */
417void dvmCallMethod(Thread* self, const Method* method, Object* obj,
418    JValue* pResult, ...)
419{
420    JValue result;
421
422    va_list args;
423    va_start(args, pResult);
424    dvmCallMethodV(self, method, obj, pResult, args);
425    va_end(args);
426}
427
428/*
429 * Issue a method call with a variable number of arguments.  We process
430 * the contents of "args" by scanning the method signature.
431 *
432 * Pass in NULL for "obj" on calls to static methods.
433 *
434 * We don't need to take the class as an argument because, in Dalvik,
435 * we don't need to worry about static synchronized methods.
436 */
437void dvmCallMethodV(Thread* self, const Method* method, Object* obj,
438    JValue* pResult, va_list args)
439{
440    const char* desc = &(method->shorty[1]); // [0] is the return type.
441    int verifyCount = 0;
442    ClassObject* clazz;
443    u4* ins;
444
445    clazz = callPrep(self, method, obj, false);
446    if (clazz == NULL)
447        return;
448
449    /* "ins" for new frame start at frame pointer plus locals */
450    ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
451
452    //LOGD("  FP is %p, INs live at >= %p\n", self->curFrame, ins);
453
454    /* put "this" pointer into in0 if appropriate */
455    if (!dvmIsStaticMethod(method)) {
456#ifdef WITH_EXTRA_OBJECT_VALIDATION
457        assert(obj != NULL && dvmIsValidObject(obj));
458#endif
459        *ins++ = (u4) obj;
460        verifyCount++;
461    }
462
463    while (*desc != '\0') {
464        switch (*(desc++)) {
465            case 'D': case 'J': {
466                u8 val = va_arg(args, u8);
467                memcpy(ins, &val, 8);       // EABI prevents direct store
468                ins += 2;
469                verifyCount += 2;
470                break;
471            }
472            case 'F': {
473                /* floats were normalized to doubles; convert back */
474                float f = (float) va_arg(args, double);
475                *ins++ = dvmFloatToU4(f);
476                verifyCount++;
477                break;
478            }
479#ifdef WITH_EXTRA_OBJECT_VALIDATION
480            case 'L': {     /* 'shorty' descr uses L for all refs, incl array */
481                Object* argObj = (Object*) va_arg(args, u4);
482                assert(obj == NULL || dvmIsValidObject(obj));
483                *ins++ = (u4) argObj;
484                verifyCount++;
485                break;
486            }
487#endif
488            default: {
489                *ins++ = va_arg(args, u4);
490                verifyCount++;
491                break;
492            }
493        }
494    }
495
496#ifndef NDEBUG
497    if (verifyCount != method->insSize) {
498        LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
499            method->insSize, clazz->descriptor, method->name);
500        assert(false);
501        goto bail;
502    }
503#endif
504
505    //dvmDumpThreadStack(dvmThreadSelf());
506
507    if (dvmIsNativeMethod(method)) {
508        /*
509         * Because we leave no space for local variables, "curFrame" points
510         * directly at the method arguments.
511         */
512        (*method->nativeFunc)(self->curFrame, pResult, method, self);
513    } else {
514        dvmInterpret(self, method, pResult);
515    }
516
517bail:
518    dvmPopFrame(self);
519}
520
521/*
522 * Issue a method call with arguments provided in an array.  We process
523 * the contents of "args" by scanning the method signature.
524 *
525 * The values were likely placed into an uninitialized jvalue array using
526 * the field specifiers, which means that sub-32-bit fields (e.g. short,
527 * boolean) may not have 32 or 64 bits of valid data.  This is different
528 * from the varargs invocation where the C compiler does a widening
529 * conversion when calling a function.  As a result, we have to be a
530 * little more precise when pulling stuff out.
531 *
532 * "args" may be NULL if the method has no arguments.
533 */
534void dvmCallMethodA(Thread* self, const Method* method, Object* obj,
535    JValue* pResult, const jvalue* args)
536{
537    const char* desc = &(method->shorty[1]); // [0] is the return type.
538    int verifyCount = 0;
539    ClassObject* clazz;
540    u4* ins;
541
542    clazz = callPrep(self, method, obj, false);
543    if (clazz == NULL)
544        return;
545
546    /* "ins" for new frame start at frame pointer plus locals */
547    ins = ((u4*)self->curFrame) + (method->registersSize - method->insSize);
548
549    /* put "this" pointer into in0 if appropriate */
550    if (!dvmIsStaticMethod(method)) {
551        assert(obj != NULL);
552        *ins++ = (u4) obj;
553        verifyCount++;
554    }
555
556    while (*desc != '\0') {
557        switch (*(desc++)) {
558            case 'D': case 'J': {
559                memcpy(ins, &args->j, 8);   /* EABI prevents direct store */
560                ins += 2;
561                verifyCount += 2;
562                args++;
563                break;
564            }
565            case 'F': case 'I': case 'L': { /* (no '[' in short signatures) */
566                *ins++ = args->i;           /* get all 32 bits */
567                verifyCount++;
568                args++;
569                break;
570            }
571            case 'S': {
572                *ins++ = args->s;           /* 16 bits, sign-extended */
573                verifyCount++;
574                args++;
575                break;
576            }
577            case 'C': {
578                *ins++ = args->c;           /* 16 bits, unsigned */
579                verifyCount++;
580                args++;
581                break;
582            }
583            case 'B': {
584                *ins++ = args->b;           /* 8 bits, sign-extended */
585                verifyCount++;
586                args++;
587                break;
588            }
589            case 'Z': {
590                *ins++ = args->z;           /* 8 bits, zero or non-zero */
591                verifyCount++;
592                args++;
593                break;
594            }
595            default: {
596                LOGE("Invalid char %c in short signature of %s.%s\n",
597                    *(desc-1), clazz->descriptor, method->name);
598                assert(false);
599                goto bail;
600            }
601        }
602    }
603
604#ifndef NDEBUG
605    if (verifyCount != method->insSize) {
606        LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
607            method->insSize, clazz->descriptor, method->name);
608        assert(false);
609        goto bail;
610    }
611#endif
612
613    if (dvmIsNativeMethod(method)) {
614        /*
615         * Because we leave no space for local variables, "curFrame" points
616         * directly at the method arguments.
617         */
618        (*method->nativeFunc)(self->curFrame, pResult, method, self);
619    } else {
620        dvmInterpret(self, method, pResult);
621    }
622
623bail:
624    dvmPopFrame(self);
625}
626
627/*
628 * Invoke a method, using the specified arguments and return type, through
629 * one of the reflection interfaces.  Could be a virtual or direct method
630 * (including constructors).  Used for reflection.
631 *
632 * Deals with boxing/unboxing primitives and performs widening conversions.
633 *
634 * "invokeObj" will be null for a static method.
635 *
636 * If the invocation returns with an exception raised, we have to wrap it.
637 */
638Object* dvmInvokeMethod(Object* obj, const Method* method,
639    ArrayObject* argList, ArrayObject* params, ClassObject* returnType,
640    bool noAccessCheck)
641{
642    ClassObject* clazz;
643    Object* retObj = NULL;
644    Thread* self = dvmThreadSelf();
645    s4* ins;
646    int verifyCount, argListLength;
647    JValue retval;
648
649    /* verify arg count */
650    if (argList != NULL)
651        argListLength = argList->length;
652    else
653        argListLength = 0;
654    if (argListLength != (int) params->length) {
655        LOGI("invoke: expected %d args, received %d args\n",
656            params->length, argListLength);
657        dvmThrowException("Ljava/lang/IllegalArgumentException;",
658            "wrong number of arguments");
659        return NULL;
660    }
661
662    clazz = callPrep(self, method, obj, !noAccessCheck);
663    if (clazz == NULL)
664        return NULL;
665
666    /* "ins" for new frame start at frame pointer plus locals */
667    ins = ((s4*)self->curFrame) + (method->registersSize - method->insSize);
668    verifyCount = 0;
669
670    //LOGD("  FP is %p, INs live at >= %p\n", self->curFrame, ins);
671
672    /* put "this" pointer into in0 if appropriate */
673    if (!dvmIsStaticMethod(method)) {
674        assert(obj != NULL);
675        *ins++ = (s4) obj;
676        verifyCount++;
677    }
678
679    /*
680     * Copy the args onto the stack.  Primitive types are converted when
681     * necessary, and object types are verified.
682     */
683    DataObject** args;
684    ClassObject** types;
685    int i;
686
687    args = (DataObject**) argList->contents;
688    types = (ClassObject**) params->contents;
689    for (i = 0; i < argListLength; i++) {
690        int width;
691
692        width = dvmConvertArgument(*args++, *types++, ins);
693        if (width < 0) {
694            if (*(args-1) != NULL) {
695                LOGV("invoke: type mismatch on arg %d ('%s' '%s')\n",
696                    i, (*(args-1))->obj.clazz->descriptor,
697                    (*(types-1))->descriptor);
698            }
699            dvmPopFrame(self);      // throw wants to pull PC out of stack
700            dvmThrowException("Ljava/lang/IllegalArgumentException;",
701                "argument type mismatch");
702            goto bail_popped;
703        }
704
705        ins += width;
706        verifyCount += width;
707    }
708
709    if (verifyCount != method->insSize) {
710        LOGE("Got vfycount=%d insSize=%d for %s.%s\n", verifyCount,
711            method->insSize, clazz->descriptor, method->name);
712        assert(false);
713        goto bail;
714    }
715    //dvmDumpThreadStack(dvmThreadSelf());
716
717    if (dvmIsNativeMethod(method)) {
718        /*
719         * Because we leave no space for local variables, "curFrame" points
720         * directly at the method arguments.
721         */
722        (*method->nativeFunc)(self->curFrame, &retval, method, self);
723    } else {
724        dvmInterpret(self, method, &retval);
725    }
726
727    /*
728     * If an exception is raised, wrap and replace.  This is necessary
729     * because the invoked method could have thrown a checked exception
730     * that the caller wasn't prepared for.
731     *
732     * We might be able to do this up in the interpreted code, but that will
733     * leave us with a shortened stack trace in the top-level exception.
734     */
735    if (dvmCheckException(self)) {
736        dvmWrapException("Ljava/lang/reflect/InvocationTargetException;");
737    } else {
738        /*
739         * If this isn't a void method or constructor, convert the return type
740         * to an appropriate object.
741         *
742         * We don't do this when an exception is raised because the value
743         * in "retval" is undefined.
744         */
745        if (returnType != NULL) {
746            retObj = (Object*)dvmWrapPrimitive(retval, returnType);
747            dvmReleaseTrackedAlloc(retObj, NULL);
748        }
749    }
750
751bail:
752    dvmPopFrame(self);
753bail_popped:
754    return retObj;
755}
756
757typedef struct LineNumFromPcContext {
758    u4 address;
759    u4 lineNum;
760} LineNumFromPcContext;
761
762static int lineNumForPcCb(void *cnxt, u4 address, u4 lineNum)
763{
764    LineNumFromPcContext *pContext = (LineNumFromPcContext *)cnxt;
765
766    // We know that this callback will be called in
767    // ascending address order, so keep going until we find
768    // a match or we've just gone past it.
769
770    if (address > pContext->address) {
771        // The line number from the previous positions callback
772        // wil be the final result.
773        return 1;
774    }
775
776    pContext->lineNum = lineNum;
777
778    return (address == pContext->address) ? 1 : 0;
779}
780
781/*
782 * Determine the source file line number based on the program counter.
783 * "pc" is an offset, in 16-bit units, from the start of the method's code.
784 *
785 * Returns -1 if no match was found (possibly because the source files were
786 * compiled without "-g", so no line number information is present).
787 * Returns -2 for native methods (as expected in exception traces).
788 */
789int dvmLineNumFromPC(const Method* method, u4 relPc)
790{
791    const DexCode* pDexCode = dvmGetMethodCode(method);
792
793    if (pDexCode == NULL) {
794        if (dvmIsNativeMethod(method) && !dvmIsAbstractMethod(method))
795            return -2;
796        return -1;      /* can happen for abstract method stub */
797    }
798
799    LineNumFromPcContext context;
800    memset(&context, 0, sizeof(context));
801    context.address = relPc;
802    // A method with no line number info should return -1
803    context.lineNum = -1;
804
805    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile, pDexCode,
806            method->clazz->descriptor,
807            method->prototype.protoIdx,
808            method->accessFlags,
809            lineNumForPcCb, NULL, &context);
810
811    return context.lineNum;
812}
813
814/*
815 * Compute the frame depth.
816 *
817 * Excludes "break" frames.
818 */
819int dvmComputeExactFrameDepth(const void* fp)
820{
821    int count = 0;
822
823    for ( ; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
824        if (!dvmIsBreakFrame(fp))
825            count++;
826    }
827
828    return count;
829}
830
831/*
832 * Compute the "vague" frame depth, which is just a pointer subtraction.
833 * The result is NOT an overly generous assessment of the number of
834 * frames; the only meaningful use is to compare against the result of
835 * an earlier invocation.
836 *
837 * Useful for implementing single-step debugger modes, which may need to
838 * call this for every instruction.
839 */
840int dvmComputeVagueFrameDepth(Thread* thread, const void* fp)
841{
842    const u1* interpStackStart = thread->interpStackStart;
843    const u1* interpStackBottom = interpStackStart - thread->interpStackSize;
844
845    assert((u1*) fp >= interpStackBottom && (u1*) fp < interpStackStart);
846    return interpStackStart - (u1*) fp;
847}
848
849/*
850 * Get the calling frame.  Pass in the current fp.
851 *
852 * Skip "break" frames and reflection invoke frames.
853 */
854void* dvmGetCallerFP(const void* curFrame)
855{
856    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
857    StackSaveArea* saveArea;
858
859retry:
860    if (dvmIsBreakFrame(caller)) {
861        /* pop up one more */
862        caller = SAVEAREA_FROM_FP(caller)->prevFrame;
863        if (caller == NULL)
864            return NULL;        /* hit the top */
865
866        /*
867         * If we got here by java.lang.reflect.Method.invoke(), we don't
868         * want to return Method's class loader.  Shift up one and try
869         * again.
870         */
871        saveArea = SAVEAREA_FROM_FP(caller);
872        if (dvmIsReflectionMethod(saveArea->method)) {
873            caller = saveArea->prevFrame;
874            assert(caller != NULL);
875            goto retry;
876        }
877    }
878
879    return caller;
880}
881
882/*
883 * Get the caller's class.  Pass in the current fp.
884 *
885 * This is used by e.g. java.lang.Class.
886 */
887ClassObject* dvmGetCallerClass(const void* curFrame)
888{
889    void* caller;
890
891    caller = dvmGetCallerFP(curFrame);
892    if (caller == NULL)
893        return NULL;
894
895    return SAVEAREA_FROM_FP(caller)->method->clazz;
896}
897
898/*
899 * Get the caller's caller's class.  Pass in the current fp.
900 *
901 * This is used by e.g. java.lang.Class, which wants to know about the
902 * class loader of the method that called it.
903 */
904ClassObject* dvmGetCaller2Class(const void* curFrame)
905{
906    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
907    void* callerCaller;
908
909    /* at the top? */
910    if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
911        return NULL;
912
913    /* go one more */
914    callerCaller = dvmGetCallerFP(caller);
915    if (callerCaller == NULL)
916        return NULL;
917
918    return SAVEAREA_FROM_FP(callerCaller)->method->clazz;
919}
920
921/*
922 * Get the caller's caller's caller's class.  Pass in the current fp.
923 *
924 * This is used by e.g. java.lang.Class, which wants to know about the
925 * class loader of the method that called it.
926 */
927ClassObject* dvmGetCaller3Class(const void* curFrame)
928{
929    void* caller = SAVEAREA_FROM_FP(curFrame)->prevFrame;
930    int i;
931
932    /* at the top? */
933    if (dvmIsBreakFrame(caller) && SAVEAREA_FROM_FP(caller)->prevFrame == NULL)
934        return NULL;
935
936    /* Walk up two frames if possible. */
937    for (i = 0; i < 2; i++) {
938        caller = dvmGetCallerFP(caller);
939        if (caller == NULL)
940            return NULL;
941    }
942
943    return SAVEAREA_FROM_FP(caller)->method->clazz;
944}
945
946/*
947 * Create a flat array of methods that comprise the current interpreter
948 * stack trace.  Pass in the current frame ptr.
949 *
950 * Allocates a new array and fills it with method pointers.  Break frames
951 * are skipped, but reflection invocations are not.  The caller must free
952 * "*pArray".
953 *
954 * The current frame will be in element 0.
955 *
956 * Returns "true" on success, "false" on failure (e.g. malloc failed).
957 */
958bool dvmCreateStackTraceArray(const void* fp, const Method*** pArray,
959    int* pLength)
960{
961    const Method** array;
962    int idx, depth;
963
964    depth = dvmComputeExactFrameDepth(fp);
965    array = (const Method**) malloc(depth * sizeof(Method*));
966    if (array == NULL)
967        return false;
968
969    for (idx = 0; fp != NULL; fp = SAVEAREA_FROM_FP(fp)->prevFrame) {
970        if (!dvmIsBreakFrame(fp))
971            array[idx++] = SAVEAREA_FROM_FP(fp)->method;
972    }
973    assert(idx == depth);
974
975    *pArray = array;
976    *pLength = depth;
977    return true;
978}
979
980/*
981 * Open up the reserved area and throw an exception.  The reserved area
982 * should only be needed to create and initialize the exception itself.
983 *
984 * If we already opened it and we're continuing to overflow, abort the VM.
985 *
986 * We have to leave the "reserved" area open until the "catch" handler has
987 * finished doing its processing.  This is because the catch handler may
988 * need to resolve classes, which requires calling into the class loader if
989 * the classes aren't already in the "initiating loader" list.
990 */
991void dvmHandleStackOverflow(Thread* self)
992{
993    /*
994     * Can we make the reserved area available?
995     */
996    if (self->stackOverflowed) {
997        /*
998         * Already did, nothing to do but bail.
999         */
1000        LOGE("DalvikVM: double-overflow of stack in threadid=%d; aborting\n",
1001            self->threadId);
1002        dvmDumpThread(self, false);
1003        dvmAbort();
1004    }
1005
1006    /* open it up to the full range */
1007    LOGI("Stack overflow, expanding (%p to %p)\n", self->interpStackEnd,
1008        self->interpStackStart - self->interpStackSize);
1009    //dvmDumpThread(self, false);
1010    self->interpStackEnd = self->interpStackStart - self->interpStackSize;
1011    self->stackOverflowed = true;
1012
1013    /*
1014     * If we were trying to throw an exception when the stack overflowed,
1015     * we will blow up when doing the class lookup on StackOverflowError
1016     * because of the pending exception.  So, we clear it and make it
1017     * the cause of the SOE.
1018     */
1019    Object* excep = dvmGetException(self);
1020    if (excep != NULL) {
1021        LOGW("Stack overflow while throwing exception\n");
1022        dvmClearException(self);
1023    }
1024    dvmThrowChainedException("Ljava/lang/StackOverflowError;", NULL, excep);
1025}
1026
1027/*
1028 * Reduce the available stack size.  By this point we should have finished
1029 * our overflow processing.
1030 */
1031void dvmCleanupStackOverflow(Thread* self)
1032{
1033    const u1* newStackEnd;
1034
1035    assert(self->stackOverflowed);
1036
1037    newStackEnd = (self->interpStackStart - self->interpStackSize)
1038        + STACK_OVERFLOW_RESERVE;
1039    if ((u1*)self->curFrame <= newStackEnd) {
1040        LOGE("Can't shrink stack: curFrame is in reserved area (%p %p)\n",
1041            self->interpStackEnd, self->curFrame);
1042        dvmDumpThread(self, false);
1043        dvmAbort();
1044    }
1045
1046    self->interpStackEnd = newStackEnd;
1047    self->stackOverflowed = false;
1048
1049    LOGI("Shrank stack (to %p, curFrame is %p)\n", self->interpStackEnd,
1050        self->curFrame);
1051}
1052
1053
1054/*
1055 * Dump stack frames, starting from the specified frame and moving down.
1056 *
1057 * Each frame holds a pointer to the currently executing method, and the
1058 * saved program counter from the caller ("previous" frame).  This means
1059 * we don't have the PC for the current method on the stack, which is
1060 * pretty reasonable since it's in the "PC register" for the VM.  Because
1061 * exceptions need to show the correct line number we actually *do* have
1062 * an updated version in the fame's "xtra.currentPc", but it's unreliable.
1063 *
1064 * Note "framePtr" could be NULL in rare circumstances.
1065 */
1066static void dumpFrames(const DebugOutputTarget* target, void* framePtr,
1067    Thread* thread)
1068{
1069    const StackSaveArea* saveArea;
1070    const Method* method;
1071    int checkCount = 0;
1072    const u2* currentPc = NULL;
1073    bool first = true;
1074
1075    /*
1076     * The "currentPc" is updated whenever we execute an instruction that
1077     * might throw an exception.  Show it here.
1078     */
1079    if (framePtr != NULL && !dvmIsBreakFrame(framePtr)) {
1080        saveArea = SAVEAREA_FROM_FP(framePtr);
1081
1082        if (saveArea->xtra.currentPc != NULL)
1083            currentPc = saveArea->xtra.currentPc;
1084    }
1085
1086    while (framePtr != NULL) {
1087        saveArea = SAVEAREA_FROM_FP(framePtr);
1088        method = saveArea->method;
1089
1090        if (dvmIsBreakFrame(framePtr)) {
1091            //dvmPrintDebugMessage(target, "  (break frame)\n");
1092        } else {
1093            int relPc;
1094
1095            if (currentPc != NULL)
1096                relPc = currentPc - saveArea->method->insns;
1097            else
1098                relPc = -1;
1099
1100            char* className = dvmDescriptorToDot(method->clazz->descriptor);
1101            if (dvmIsNativeMethod(method))
1102                dvmPrintDebugMessage(target,
1103                    "  at %s.%s(Native Method)\n", className, method->name);
1104            else {
1105                dvmPrintDebugMessage(target,
1106                    "  at %s.%s(%s:%s%d)\n",
1107                    className, method->name, dvmGetMethodSourceFile(method),
1108                    (relPc >= 0 && first) ? "~" : "",
1109                    relPc < 0 ? -1 : dvmLineNumFromPC(method, relPc));
1110            }
1111            free(className);
1112
1113            if (first &&
1114                (thread->status == THREAD_WAIT ||
1115                 thread->status == THREAD_TIMED_WAIT))
1116            {
1117                /* warning: wait status not stable, even in suspend */
1118                Monitor* mon = thread->waitMonitor;
1119                Object* obj = dvmGetMonitorObject(mon);
1120                if (obj != NULL) {
1121                    className = dvmDescriptorToDot(obj->clazz->descriptor);
1122                    dvmPrintDebugMessage(target,
1123                        "  - waiting on <%p> (a %s)\n", mon, className);
1124                    free(className);
1125                }
1126            }
1127
1128        }
1129
1130        /*
1131         * Get saved PC for previous frame.  There's no savedPc in a "break"
1132         * frame, because that represents native or interpreted code
1133         * invoked by the VM.  The saved PC is sitting in the "PC register",
1134         * a local variable on the native stack.
1135         */
1136        currentPc = saveArea->savedPc;
1137
1138        first = false;
1139
1140        assert(framePtr != saveArea->prevFrame);
1141        framePtr = saveArea->prevFrame;
1142
1143        checkCount++;
1144        if (checkCount > 200) {
1145            dvmPrintDebugMessage(target,
1146                "  ***** printed %d frames, not showing any more\n",
1147                checkCount);
1148            break;
1149        }
1150    }
1151    dvmPrintDebugMessage(target, "\n");
1152}
1153
1154
1155/*
1156 * Dump the stack for the specified thread.
1157 */
1158void dvmDumpThreadStack(const DebugOutputTarget* target, Thread* thread)
1159{
1160    dumpFrames(target, thread->curFrame, thread);
1161}
1162
1163/*
1164 * Dump the stack for the specified thread, which is still running.
1165 *
1166 * This is very dangerous, because stack frames are being pushed on and
1167 * popped off, and if the thread exits we'll be looking at freed memory.
1168 * The plan here is to take a snapshot of the stack and then dump that
1169 * to try to minimize the chances of catching it mid-update.  This should
1170 * work reasonably well on a single-CPU system.
1171 *
1172 * There is a small chance that calling here will crash the VM.
1173 */
1174void dvmDumpRunningThreadStack(const DebugOutputTarget* target, Thread* thread)
1175{
1176    StackSaveArea* saveArea;
1177    const u1* origStack;
1178    u1* stackCopy = NULL;
1179    int origSize, fpOffset;
1180    void* fp;
1181    int depthLimit = 200;
1182
1183    if (thread == NULL || thread->curFrame == NULL) {
1184        dvmPrintDebugMessage(target,
1185            "DumpRunning: Thread at %p has no curFrame (threadid=%d)\n",
1186            thread, (thread != NULL) ? thread->threadId : 0);
1187        return;
1188    }
1189
1190    /* wait for a full quantum */
1191    sched_yield();
1192
1193    /* copy the info we need, then the stack itself */
1194    origSize = thread->interpStackSize;
1195    origStack = (const u1*) thread->interpStackStart - origSize;
1196    stackCopy = (u1*) malloc(origSize);
1197    fpOffset = (u1*) thread->curFrame - origStack;
1198    memcpy(stackCopy, origStack, origSize);
1199
1200    /*
1201     * Run through the stack and rewrite the "prev" pointers.
1202     */
1203    //LOGI("DR: fpOff=%d (from %p %p)\n",fpOffset, origStack, thread->curFrame);
1204    fp = stackCopy + fpOffset;
1205    while (true) {
1206        int prevOffset;
1207
1208        if (depthLimit-- < 0) {
1209            /* we're probably screwed */
1210            dvmPrintDebugMessage(target, "DumpRunning: depth limit hit\n");
1211            dvmAbort();
1212        }
1213        saveArea = SAVEAREA_FROM_FP(fp);
1214        if (saveArea->prevFrame == NULL)
1215            break;
1216
1217        prevOffset = (u1*) saveArea->prevFrame - origStack;
1218        if (prevOffset < 0 || prevOffset > origSize) {
1219            dvmPrintDebugMessage(target,
1220                "DumpRunning: bad offset found: %d (from %p %p)\n",
1221                prevOffset, origStack, saveArea->prevFrame);
1222            saveArea->prevFrame = NULL;
1223            break;
1224        }
1225
1226        saveArea->prevFrame = stackCopy + prevOffset;
1227        fp = saveArea->prevFrame;
1228    }
1229
1230    /*
1231     * We still need to pass the Thread for some monitor wait stuff.
1232     */
1233    dumpFrames(target, stackCopy + fpOffset, thread);
1234    free(stackCopy);
1235}
1236
1237