2
|
1 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
|
2 |
"http://www.w3.org/TR/html4/loose.dtd">
|
|
3 |
<html><head>
|
|
4 |
<title>Walking through the Call Stack</title>
|
|
5 |
<link href="sysdoc-eclipse.css" type="text/css" rel="stylesheet" >
|
|
6 |
<link href="sysdoc-eclipse.css" type="text/css" rel="stylesheet" >
|
|
7 |
<link href="../../book.css" type="text/css" rel="stylesheet" >
|
|
8 |
<div class="Head1">
|
|
9 |
<h2>Walking through the Call Stack</h2>
|
|
10 |
</div>
|
|
11 |
<div>
|
|
12 |
<p>The heuristic method is quick but produces lots of false positives.
|
|
13 |
Another option is to manually reconstitute the call stack from the memory dump.
|
|
14 |
This is relatively easy for debug builds because GCC uses R11 as a frame
|
|
15 |
pointer (FP) and generates the same prologue/epilogue for every
|
|
16 |
function.</p>
|
|
17 |
<p>For release builds, there is no generic solution. It is necessary
|
|
18 |
to check the generated assembler code as there is no standard prologue/epilogue
|
|
19 |
and R11 is not used as frame pointer.</p>
|
|
20 |
<p>A typical prologue for a debug ARM function looks like this:</p>
|
|
21 |
<p class="CodeBlock">mov ip, sp<br>stmfd sp!, {fp, ip, lr, pc}<br>sub fp, ip, #4 /* FP now points to base of stack frame */<br>sub sp, sp, #16 /* space for local variables */</p>
|
|
22 |
<p>noting that: SP = R13, FP = R11, IP
|
|
23 |
= R12, LR = R14, and PC = R15.</p>
|
|
24 |
<p>This code creates the following stack frame:</p>
|
|
25 |
<div class="Figure">
|
|
26 |
<p class="Image"><a name=""><img src="CrashDebuggerStackFrame-01.gif" alt="" border="0"></a></p>
|
|
27 |
</div>
|
|
28 |
<p>Looking at the example session listed in when
|
|
29 |
<a href="CrashDebuggerCallStack.guide.html" title="Examining the call stack / Tracing through the stack heuristically">tracing through the stack heuristically</a>. in which the crash is due to a panic, the FP value is the
|
|
30 |
R11 value; this is 0x6571de70. This gives us the innermost stack
|
|
31 |
frame:</p>
|
|
32 |
<p class="CodeBlock">6571de64: e8 de 71 65 <------------- pointer to previous stack frame <br> 74 de 71 65 <br> 74 fb 16 f8 <------------- Saved return address <br> 88 28 03 f8 <------------- FP points to this word</p>
|
|
33 |
<p>Looking up the saved return address, 0xf816fb74, in
|
|
34 |
the symbol file shows that the current function was called from
|
|
35 |
DDmaChannel::DoCreate().</p>
|
|
36 |
<p class="CodeBlock">f816fb50 0198 DDmaTestChannel::DoCreate(int, TDesC8 const *, TVersion const &)<br>f816fce8 007c DDmaTestChannel::~DDmaTestChannel(void)<br>f816fd64 0294 DDmaTestChannel::Request(int, void *, void *)</p>
|
|
37 |
<p>Using the pointer to the previous stack frame saved into the
|
|
38 |
current frame, we can decode the next frame:</p>
|
|
39 |
<p class="CodeBlock">6571ded4: 1c c4 03 64 <br> f8 02 00 64 <br> 10 df 71 65 <------------- pointer to previous stack frame <br> ec de 71 65 <br><br>6571dee4: 84 da 01 f8 <------------- saved return address <br> 5c fb 16 f8 <------------- start of second stack frame <br> 00 4e 40 00 <br> 00 00 00 00 </p>
|
|
40 |
<p>Looking up the saved return address, 0xf801da84, in
|
|
41 |
the symbol file shows that DDmaTestChannel::DoCreate() was called
|
|
42 |
from DLogicalDevice::ChannelCreate().</p>
|
|
43 |
<p class="CodeBlock">f801d9b4 00f8 DLogicalDevice::ChannelCreate(DLogicalChannelBase *&, TChannelCreateInfo &)<br>f801daac 01b8 ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo &, int)<br>f801dc64 00e4 ExecHandler::ChannelRequest(DLogicalChannelBase *, int, void *, void *)</p>
|
|
44 |
<p>And here is the third stack frame:</p>
|
|
45 |
<p class="CodeBlock">6571df04: d4 df 71 65 <------------- pointer to previous stack frame <br> 14 df 71 65 <br> e0 db 01 f8 <------------- saved return address <br> c0 d9 01 f8 <------------- start of third stack frame </p>
|
|
46 |
<p>So DLogicalDevice::ChannelCreate() was called from
|
|
47 |
ExecHandler::ChannelCreate().</p>
|
|
48 |
<p>Note that this mechanical way of walking the stack is valid only
|
|
49 |
for debug functions. For release functions, it is necessary to study the code
|
|
50 |
generated by the compiler.</p>
|
|
51 |
<p>For completness, this is a typical prologue for a debug THUMB
|
|
52 |
function:</p>
|
|
53 |
<p class="CodeBlock">push { r7, lr }<br>sub sp, #28<br>add r7, sp, #12 /* R7 is THUMB frame pointer */</p>
|
|
54 |
<p>and this creates the following stack frame:</p>
|
|
55 |
<div class="Figure">
|
|
56 |
<p class="Image"><a name=""><img src="CrashDebuggerStackFrame-02.gif" alt="" border="0"></a></p>
|
|
57 |
</div>
|
|
58 |
<p>A call stack can mix ARM and THUMB frames. Odd return addresses are
|
|
59 |
used for THUMB code and even ones for ARM code.</p>
|
|
60 |
|
|
61 |
</div>
|
|
62 |
<h5>Related tasks</h5>
|
|
63 |
<ul>
|
|
64 |
<li><a href="CrashDebuggerCallStack.guide02.html">General Points</a></li>
|
|
65 |
<li><a href="CrashDebuggerCallStack.guide03.html">Finding the Stack</a></li>
|
|
66 |
<li><a href="CrashDebuggerCallStack.guide04.html">Tracing through the Call Stack Heuristically</a></li>
|
|
67 |
</ul>
|
|
68 |
<div id="footer">Copyright © 2009 Nokia Corporation and/or its subsidiary(-ies). All rights reserved. <br>License: <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a></div>
|
|
69 |
</body>
|
|
70 |
</html>
|
|
71 |
|