|
1 <?xml version="1.0" encoding="utf-8"?> |
|
2 <!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. --> |
|
3 <!-- This component and the accompanying materials are made available under the terms of the License |
|
4 "Eclipse Public License v1.0" which accompanies this distribution, |
|
5 and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". --> |
|
6 <!-- Initial Contributors: |
|
7 Nokia Corporation - initial contribution. |
|
8 Contributors: |
|
9 --> |
|
10 <!DOCTYPE concept |
|
11 PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd"> |
|
12 <concept id="GUID-1E43E258-A926-5D24-B0A5-8756491C687F" xml:lang="en"><title>Call |
|
13 Stack Information Commands</title><prolog><metadata><keywords/></metadata></prolog><conbody> |
|
14 <p>Describes how to use the debug monitor commands to get information about |
|
15 the call stack. </p> |
|
16 <ul> |
|
17 <li id="GUID-9D1E42B6-658E-59DF-AC7D-0551B8EF6B61"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-D8F141D7-3BE2-5ADB-8A55-CFFE85E89804">General points</xref> </p> </li> |
|
18 <li id="GUID-92B8F3E9-11C1-5260-A862-6CE017984DB0"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-1EC3F2E7-6BFF-56BE-B042-DA6940CC909E">Finding the stack</xref> </p> </li> |
|
19 <li id="GUID-CEFC5F08-C19E-53DD-A0E2-C9C4FFFF3490"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-877742A5-F07F-54B6-B871-255FAAE790EB">Tracing through the call stack heuristically</xref> </p> </li> |
|
20 <li id="GUID-8D00F8C3-B367-5C75-89E4-B712002E942D"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-7F160B0F-9921-578B-B9B0-7CC4CA3B24C3">Walking through the call stack</xref> </p> </li> |
|
21 </ul> |
|
22 <section id="GUID-D8F141D7-3BE2-5ADB-8A55-CFFE85E89804"><title>General points</title> <p>Tracing |
|
23 the call stack is an advanced use of the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-2A0D5950-F1A5-5EE1-87A3-840B1EAD6AAD">m</xref> command that allows you to <xref href="GUID-DC2CF276-95E2-5810-9B8D-EB8B72E04FEC.dita">examine |
|
24 memory</xref>. </p> <p>Every time a function is called, the return address |
|
25 is automatically saved into register <codeph>R14</codeph> (Link Register). |
|
26 In addition to this the return address is generally pushed onto the call stack; |
|
27 it is always pushed in debug builds but the push operation is sometimes optimized |
|
28 out in release builds. This allows you to trace back through the value of <codeph>R14</codeph> and |
|
29 these saved addresses to see the sequence of function calls. Unfortunately |
|
30 this is quite tedious to do because the stack is also used for automatic variables |
|
31 and other data. You need to work out which values on the stack refer to return |
|
32 addresses. </p> <p>When you are debugging only ROM-based code, it is relatively |
|
33 easy to identify the pushed return addresses because all code addresses will |
|
34 be in the ROM range: <codeph>0xF800000</codeph> to <codeph>0xFFEFFFFF</codeph> for |
|
35 the <xref href="GUID-D520CBC3-FCAC-5A53-AE1A-E5254ABBC6A2.dita#GUID-D520CBC3-FCAC-5A53-AE1A-E5254ABBC6A2/GUID-A5845A0C-2C88-52BB-B7DE-210C2DE481B9">moving |
|
36 model</xref>. However, there is also data in the ROM, which means that an |
|
37 address on the stack which is in the ROM range could point to data instead |
|
38 of code. If you want to trace applications loaded into RAM, i.e. anything |
|
39 not run from drive Z:, then stack tracing is more difficult because the code |
|
40 can move about and RAM-loaded code is given an address assigned at load time. </p> <p>Note |
|
41 that <xref href="GUID-DA62FD4F-2E74-5B2F-B703-4A40DF5F01CA.dita">using the MAKSYM |
|
42 tool</xref> is essential for tracing back through the stack. </p> </section> |
|
43 <section id="GUID-1EC3F2E7-6BFF-56BE-B042-DA6940CC909E"><title>Finding the |
|
44 stack</title> <p>To trace back through a thread’s kernel or user stack, you |
|
45 first need to find the stack pointer value. On the ARM, <codeph>R13</codeph> always |
|
46 points to the stack, but there are different <codeph>R13</codeph> registers |
|
47 for each processor mode: </p> <ul> |
|
48 <li id="GUID-756C8CDD-AF47-561B-BAA7-EA8FBDEE5245"><p>In thread context: </p> <ul> |
|
49 <li id="GUID-81BC92C2-6022-5EBF-BF60-C4D69131C720"><p> <codeph>R13usr</codeph> points |
|
50 to the thread’s user stack, </p> </li> |
|
51 <li id="GUID-CA6CF8C9-0BA3-5BD4-AECE-80AB3DFCFAD1"><p> <codeph>R13svc</codeph> points |
|
52 to the thread’s kernel stack. </p> </li> |
|
53 </ul> </li> |
|
54 <li id="GUID-C4A1AD73-64E8-56F7-A7DF-129B2A35FC9D"><p>When handling interrupts, |
|
55 dedicated stacks are used: </p> <ul> |
|
56 <li id="GUID-7D27A691-1479-578B-9B05-7946C8D84010"><p> <codeph>R13Fiq</codeph> points |
|
57 to the stack used when processing fast interrupts (FIQ). </p> </li> |
|
58 <li id="GUID-CE76BE0F-A6BA-55A6-8CDD-B1E40D97A42D"><p> <codeph>R13Irq</codeph> points |
|
59 to the stack used when processing general purpose interrupts (IRQ). </p> </li> |
|
60 </ul> </li> |
|
61 </ul> <p>To find out which stack to inspect, you need to know what mode the |
|
62 CPU was in when the fault occurred. The <xref href="GUID-7ECDCF7B-3B2A-561F-9136-04BC4DAE46E4.dita#GUID-7ECDCF7B-3B2A-561F-9136-04BC4DAE46E4/GUID-BFA2235C-1598-59E6-9F1F-A8281F13A957">processor |
|
63 mode</xref> is identified by the five least-significant bits of the CPSR register. |
|
64 To get the value of the CPSR register: </p> <ul> |
|
65 <li id="GUID-2FAF9E34-CCF0-5C6E-AA6A-9D274433FC49"><p>use the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-D5F2E0AF-EF03-5150-813B-DF989F12C47B">f</xref> command when the debug monitor is triggered by a hardware exception. </p> </li> |
|
66 <li id="GUID-EECA647F-38C8-5B57-80EA-B4D9EBA1928B"><p>use the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-0CDF0190-A445-526B-AC1F-D9D58095B18B">r</xref> command when the debug monitor is triggered by a panic. </p> </li> |
|
67 </ul> <p>The following examples show how to find the stack(s): </p> <ul> |
|
68 <li id="GUID-A5533A14-EEF7-5A9F-B93B-E6E41ECF3928"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-4E735CB7-3171-58FB-9D93-EE86702952F6">Kernel & user stacks of the current thread after a hardware exception</xref> </p> </li> |
|
69 <li id="GUID-750F8489-5918-5062-9ABC-C8951E50716A"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-FB9D2307-01D9-562A-A46F-AAD91D61C32E">Kernel & user stacks of the current thread after a panic</xref> </p> </li> |
|
70 <li id="GUID-0ADBB680-827C-5AEF-96F9-B5684B146097"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-C265F9C5-3280-5A4F-B023-56E33D52DDE0">Interrupt stacks</xref> </p> </li> |
|
71 <li id="GUID-B7CA8584-317C-5ECB-9D4D-2EEFED3F51EA"><p> <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-9637574E-A9A0-509D-B9B1-C672E2B13431">Kernel & user stacks of a non-current thread</xref> </p> </li> |
|
72 </ul> <p id="GUID-4E735CB7-3171-58FB-9D93-EE86702952F6"><b>Kernel & user stacks |
|
73 of the current thread after a hardware exception</b> </p> <p>Use the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-D5F2E0AF-EF03-5150-813B-DF989F12C47B">f</xref> command. </p> <codeblock id="GUID-A92D63C6-1594-5C95-AAC2-42D2FDE5160F" xml:space="preserve">Fault Category: Exception Fault Reason: 10000000 |
|
74 ExcId 00000001 CodeAddr f816c908 DataAddr 80000001 Extra c0007003 |
|
75 Exc 1 Cpsr=60000010 FAR=80000001 FSR=c0007003 |
|
76 R0=00000000 R1=00000000 R2=30000000 R3=80000001 |
|
77 R4=00000001 R5=00403d88 R6=00002000 R7=f816c768 |
|
78 R8=00000012 R9=00000040 R10=00000000 R11=00403fa4 |
|
79 R12=00403d5c R13=00403d70 R14=f80906f8 R15=f816c908 |
|
80 R13Svc=6571e000 R14Svc=f80074bc SpsrSvc=80000010 |
|
81 </codeblock> <p>In this example: </p> <ul> |
|
82 <li id="GUID-7C35AE63-13E9-5D8D-A77F-CD1A0B9A5EF4"><p>the kernel stack is |
|
83 the value of <codeph>R13Svc</codeph>, i.e. <codeph>0x6571e00</codeph>. </p> </li> |
|
84 <li id="GUID-D70628B9-A750-5557-BACF-471D2D75A2E4"><p>the user stack is the |
|
85 value of <codeph>R13</codeph>, i.e. <codeph>0x00403d70</codeph>. </p> </li> |
|
86 </ul> <p id="GUID-FB9D2307-01D9-562A-A46F-AAD91D61C32E"><b>Kernel & user stacks |
|
87 of the current thread after a panic</b> </p> <p>Use the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-0CDF0190-A445-526B-AC1F-D9D58095B18B">r</xref> command. </p> <codeblock id="GUID-705AF9EC-4513-5C3C-BD28-A91992D73296" xml:space="preserve">MODE_USR: |
|
88 R0=6571de54 R1=0000002a R2=00000002 R3=ffffffff |
|
89 R4=0000002a R5=f8170414 R6=6571df14 R7=6403cc50 |
|
90 R8=00000001 R9=6403c44c R10=640002f8 R11=6571de70 |
|
91 R12=00000020 R13=00404e00 R14=f80818c0 R15=f800bfa8 |
|
92 CPSR=60000013 |
|
93 MODE_FIQ: |
|
94 R8=00000000 R9=ffffffff R10=ffffffff R11=00000000 |
|
95 R12=00000000 R13=64000d0c R14=c080079c SPSR=e00000dc |
|
96 MODE_IRQ: |
|
97 R13=6400110c R14=00000013 SPSR=20000013 |
|
98 MODE_SVC: |
|
99 R13=6571de54 R14=f80328bc SPSR=60000010 |
|
100 MODE_ABT: |
|
101 R13=6400090c R14=ccbfd0e0 SPSR=b00000d9 |
|
102 MODE_UND: |
|
103 R13=6400090c R14=b5a39950 SPSR=f000009d |
|
104 </codeblock> <p>In this example: </p> <ul> |
|
105 <li id="GUID-C23A3F68-FAEB-596A-AF51-810E7429D17B"><p>the kernel stack is |
|
106 the value of <codeph>R13</codeph> under <codeph>MODE_SVC:</codeph>, i.e. <codeph>0x6571de54</codeph>. </p> </li> |
|
107 <li id="GUID-98FD71CA-BD17-5CB3-B0A8-0FBECFBF3ECF"><p>the user stack is the |
|
108 value of <codeph>R13</codeph> under <codeph>MODE_USR:</codeph>, i.e. <codeph>0x00404e00</codeph>. </p> </li> |
|
109 </ul> <p id="GUID-C265F9C5-3280-5A4F-B023-56E33D52DDE0"><b>Interrupt stacks</b> </p> <p>Use |
|
110 the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-0CDF0190-A445-526B-AC1F-D9D58095B18B">r</xref> command. </p> <codeblock id="GUID-28065EA2-194E-5D8D-8C1B-D85299B91431" xml:space="preserve">MODE_USR: |
|
111 R0=6571de54 R1=0000002a R2=00000002 R3=ffffffff |
|
112 R4=0000002a R5=f8170414 R6=6571df14 R7=6403cc50 |
|
113 R8=00000001 R9=6403c44c R10=640002f8 R11=6571de70 |
|
114 R12=00000020 R13=00404e00 R14=f80818c0 R15=f800bfa8 |
|
115 CPSR=60000013 |
|
116 MODE_FIQ: |
|
117 R8=00000000 R9=ffffffff R10=ffffffff R11=00000000 |
|
118 R12=00000000 R13=64000d0c R14=c080079c SPSR=e00000dc |
|
119 MODE_IRQ: |
|
120 R13=6400110c R14=00000013 SPSR=20000013 |
|
121 MODE_SVC: |
|
122 R13=6571de54 R14=f80328bc SPSR=60000010 |
|
123 MODE_ABT: |
|
124 R13=6400090c R14=ccbfd0e0 SPSR=b00000d9 |
|
125 MODE_UND: |
|
126 R13=6400090c R14=b5a39950 SPSR=f000009d |
|
127 </codeblock> <p>In this example: </p> <ul> |
|
128 <li id="GUID-6A48007B-973A-50F1-BCF5-31A72EC68D57"><p>the IRQ stack is the |
|
129 value of <codeph>R13</codeph> under <codeph>MODE_IRQ:</codeph>, i.e. <codeph>0x6400110c</codeph>. </p> </li> |
|
130 <li id="GUID-65CD3376-7D50-548F-A473-04B049034D0D"><p>the FRQ stack is the |
|
131 value of <codeph>R13</codeph> under <codeph>MODE_FIQ:</codeph>, i.e. <codeph>0x64000d0c</codeph>. </p> </li> |
|
132 </ul> <p id="GUID-9637574E-A9A0-509D-B9B1-C672E2B13431"><b>Kernel & user stacks |
|
133 of a non-current thread</b> </p> <p>Use the output of the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-D0175D78-6F84-5F4F-BA90-2C591B473C69">i</xref>, <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-1DED2B2F-E780-50A0-8325-5DA22BC7D3E0">q</xref> and <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-FB2E24A6-9744-5169-BA90-DDF84DF1D3E5">c0</xref> commands. </p> <codeblock id="GUID-F45908AC-ADF8-5B92-AA8C-4C33D77D24B8" xml:space="preserve">THREAD at 6403c194 VPTR=f8046c18 AccessCount=5 Owner=6403bb4c |
|
134 Full name t_dmasim::Main |
|
135 Thread MState READY |
|
136 Default priority 12 WaitLink Priority 12 |
|
137 ExitInfo 3,0, |
|
138 Flags 00000002, Handles 6403b418 |
|
139 Supervisor stack base 6571d000 size 1000 |
|
140 User stack base 00403000 size 2000 |
|
141 Id=25, Alctr=00700000, Created alctr=00700000, Frame=00000000 |
|
142 Trap handler=00000000, ActiveScheduler=007000c8, Exception handler=00000000 |
|
143 TempObj=00000000 TempAlloc=00000000 |
|
144 NThread @ 6403c44c Pri 12 NState READY |
|
145 Next=6403c44c Prev=6403c44c Att=03 iUserContextType=02 |
|
146 HeldFM=00000000 WaitFM=00000000 AddrSp=6403bb4c |
|
147 Time=0 Timeslice=20 ReqCount=0 |
|
148 SuspendCount=0 CsCount=1 CsFunction=00000000 |
|
149 SavedSP=6571df98 |
|
150 DACR f800bd2c |
|
151 R13_USR 0d404c38 R14_USR 00000001 SPSR_SVC 00000000 |
|
152 R4 f8022d84 R5 6571dfd4 R6 6571dfbc R7 f8022db8 |
|
153 R8 f800bddc R9 f800a454 R10 00000000 R11 f801daac |
|
154 PC 60000010 |
|
155 </codeblock> <p>In this example: </p> <ul> |
|
156 <li id="GUID-A4217DD4-A46C-5EAE-85D3-2EEAD763B726"><p>the kernel stack is |
|
157 the value of <codeph>SavedSP</codeph>, i.e. <codeph>0x6571df98</codeph>. </p> </li> |
|
158 <li id="GUID-8220888D-7411-5AC5-AD20-89E892301188"><p>the user stack is the |
|
159 value of <codeph>R13_USR</codeph>, i.e. <codeph>0x0d404c38</codeph>. </p> </li> |
|
160 </ul> </section> |
|
161 <section id="GUID-877742A5-F07F-54B6-B871-255FAAE790EB"><title>Tracing through |
|
162 the stack heuristically</title> <p>One way of tracing through the call stack |
|
163 is to assume that every word on the stack which looks like a ROM code address |
|
164 is a saved return address. We say that this heuristic because: </p> <ul> |
|
165 <li id="GUID-B5BF6BD6-0163-55F9-A34D-EB78982848B0"><p>some data words may |
|
166 look like code addresses in ROM. </p> </li> |
|
167 <li id="GUID-0A978212-73B6-5C89-B805-84327B9CF733"><p>there may be saved return |
|
168 addresses left over from previous function calls. For example, suppose that <codeph>F()</codeph> calls <codeph>A()</codeph> and |
|
169 then <codeph>B()</codeph> in sequence. <codeph>A()</codeph> itself calls <codeph>X()</codeph>, |
|
170 which calls <codeph>Y()</codeph>. If a crash occurs in <codeph>B()</codeph>, |
|
171 the saved return addresses from the calls to <codeph>X()</codeph> and <codeph>Y()</codeph> are |
|
172 still present on the stack and may be mistaken for function calls occuring |
|
173 while <codeph>B()</codeph> is active. </p> <p>This scenario happens frequently |
|
174 when <codeph>B()</codeph> allocates a buffer (e.g. <xref href="GUID-0B9C8884-6BFF-35E2-AA6F-E4057B85AFCF.dita"><apiname>TBuf</apiname></xref>) |
|
175 on the stack which overlaps old stack frames. </p> <fig id="GUID-FED8CC0F-F1A0-59C9-B082-2D3B499D00D5"> |
|
176 <image href="GUID-A328F9E3-7D91-594A-A589-E8CE5FA9227A_d0e300312_href.png" placement="inline"/> |
|
177 </fig> </li> |
|
178 </ul> <p>If you want to trace applications loaded into RAM, then stack tracing |
|
179 is more difficult because RAM-loaded DLLs are given addresses assigned at |
|
180 load time. </p> <p>On ARM, the stack pointer starts at the higher address |
|
181 end and moves 'down' towards the lower address end. This means that values |
|
182 at the top of the memory dump are more recent. You need to look back through |
|
183 this for code addresses. For ROM code this will be words with most significant |
|
184 byte in the range <codeph>0xF8</codeph> to <codeph>0xFF</codeph>, remembering |
|
185 that they are little-endian. This can either be done manually, or automatically |
|
186 using the <filepath>printsym.pl</filepath> perl script, which can be found |
|
187 in <codeph>...\epoc32\tools</codeph>. </p> <p>Let's follow this in an example |
|
188 session: </p> <ul> |
|
189 <li id="GUID-D761405E-86BD-55ED-ACC6-C6D2125FDCE7"><p>Decide whether the crash |
|
190 has been caused by a panic or an exception using the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-D5F2E0AF-EF03-5150-813B-DF989F12C47B">f</xref> command: </p> <codeblock id="GUID-480D9B52-C556-5733-91E2-87D7F12651FC" xml:space="preserve">.f |
|
191 Fault Category: EXAMPLE Fault Reason: 0000002a |
|
192 ExcId 00000000 CodeAddr 00000000 DataAddr 00000000 Extra 00000000 |
|
193 </codeblock> </li> |
|
194 <li id="GUID-73690262-2895-51ED-9532-E76638B0EC1E"><p>This shows that the |
|
195 crash was caused by a panic, so now use the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-0CDF0190-A445-526B-AC1F-D9D58095B18B">r</xref> command to find the CPU mode and the stack pointer: </p> <codeblock id="GUID-1FB9E3E1-54FF-5109-804D-2D6109626A66" xml:space="preserve">.r |
|
196 MODE_USR: |
|
197 R0=6571de54 R1=0000002a R2=00000002 R3=ffffffff |
|
198 R4=0000002a R5=f8170414 R6=6571df14 R7=6403cba8 |
|
199 R8=00000001 R9=6403c41c R10=640002f8 R11=6571de70 |
|
200 R12=00000020 R13=00404e00 R14=f80818c0 R15=f800bfa8 |
|
201 CPSR=60000013 |
|
202 MODE_FIQ: |
|
203 R8=00000000 R9=ffffffff R10=ffffffff R11=00000000 |
|
204 R12=00000000 R13=64000d0c R14=c080079c SPSR=e00000dc |
|
205 MODE_IRQ: |
|
206 R13=6400110c R14=00000013 SPSR=20000013 |
|
207 MODE_SVC: |
|
208 R13=6571de54 R14=f80328bc SPSR=60000010 |
|
209 MODE_ABT: |
|
210 R13=6400090c R14=ffff0010 SPSR=400000d7 |
|
211 MODE_UND: |
|
212 R13=6400090c R14=95221110 SPSR=f000009d |
|
213 </codeblock> <p>The panic happened in supervisor mode, because <codeph>CPSR |
|
214 & 0x1F == 0x13</codeph>, so <codeph>R13Svc</codeph>, i.e. |
|
215 the value of <codeph>R13</codeph> shown under <codeph>MODE_SVC:</codeph> in |
|
216 the above display, is the stack pointer to look at; this has the value <codeph>0x6571DE54</codeph>. </p> </li> |
|
217 <li id="GUID-CE74A8F7-97EF-5ACD-BA16-A35CDA293B3D"><p>Using the <xref href="GUID-08E14B34-5144-5AA8-AA55-7AF03671676C.dita#GUID-08E14B34-5144-5AA8-AA55-7AF03671676C/GUID-2A0D5950-F1A5-5EE1-87A3-840B1EAD6AAD">m</xref> command to look at memory starting at location <codeph>0x6571DE54</codeph> gives: </p> <codeblock id="GUID-BF6D6BD9-ADDE-587F-85B6-39140620B9AC" xml:space="preserve">.m6571de54+200 |
|
218 6571de54: 07 00 00 10 14 04 17 f8 00 00 00 00 d4 4e 40 00 .............N@. |
|
219 6571de64: e8 de 71 65 74 de 71 65 74 fb 16 f8 88 28 03 f8 ..qet.qet....(.. |
|
220 6571de74: 0c d4 03 f8 64 35 03 f8 00 00 00 00 00 00 00 00 ....d5.......... |
|
221 6571de84: d0 00 00 00 14 df 71 65 a8 cb 03 64 a8 cb 03 64 ......qe...d...d |
|
222 6571de94: d0 00 00 00 14 df 71 65 1c df 71 65 ec 4e 40 00 ......qe..qe.N@. |
|
223 6571dea4: 1c c4 03 64 b4 2a 03 f8 00 00 00 00 14 df 71 65 ...d.*........qe |
|
224 6571deb4: d0 de 71 65 c4 de 71 65 b0 ab 03 f8 00 00 00 00 ..qe..qe........ |
|
225 6571dec4: e0 ba 03 64 14 df 71 65 1c df 71 65 01 00 00 00 ...d..qe..qe.... |
|
226 6571ded4: 1c c4 03 64 f8 02 00 64 10 df 71 65 ec de 71 65 ...d...d..qe..qe |
|
227 6571dee4: 84 da 01 f8 5c fb 16 f8 00 4e 40 00 00 00 00 00 ....\....N@..... |
|
228 6571def4: 00 4e 40 00 00 00 00 00 d3 00 00 00 ec 4e 40 00 .N@..........N@. |
|
229 6571df04: d4 df 71 65 14 df 71 65 e0 db 01 f8 c0 d9 01 f8 ..qe..qe........ |
|
230 6571df14: a8 cb 03 64 e0 ba 03 64 01 00 01 00 00 00 00 00 ...d...d........ |
|
231 6571df24: 00 00 00 00 d4 4e 40 00 00 00 00 30 40 00 00 00 .....N@....0@... |
|
232 6571df34: 13 00 00 60 98 df 71 65 48 df 71 65 f4 81 00 f8 ...`..qeH.qe.... |
|
233 6571df44: 8c 7a 00 f8 68 df 71 65 58 df 71 65 6c df 71 65 .z..h.qeX.qel.qe |
|
234 6571df54: 60 df 71 65 0c 2b 00 f8 bc 2a 00 f8 84 df 71 65 `.qe.+...*....qe |
|
235 6571df64: 70 df 71 65 e4 7d 04 f8 08 2b 00 f8 0d 00 00 00 p.qe.}...+...... |
|
236 6571df74: 0a 00 00 30 40 00 00 00 54 65 73 74 44 6d 61 53 ...0@...TestDmaS |
|
237 6571df84: 69 6d 04 f8 a9 4b 40 00 b8 df 71 65 9c df 71 65 im...K@...qe..qe |
|
238 6571df94: 2c be 00 f8 2c bd 00 f8 38 4c 40 0d 01 00 00 00 ,...,...8L@..... |
|
239 6571dfa4: 00 00 00 00 84 2d 02 f8 d4 df 71 65 bc df 71 65 .....-....qe..qe |
|
240 6571dfb4: b8 2d 02 f8 dc bd 00 f8 54 a4 00 f8 00 00 00 00 .-......T....... |
|
241 6571dfc4: ac da 01 f8 10 00 00 60 d8 df 71 65 70 74 00 f8 .......`..qept.. |
|
242 6571dfd4: b8 da 01 f8 d4 4e 40 00 20 f7 16 f8 d0 4e 40 00 .....N@. ....N@. |
|
243 6571dfe4: 00 00 00 00 00 00 00 00 ec 4e 40 00 40 00 00 00 .........N@.@... |
|
244 </codeblock> <p>We can look for potential ROM addresses by scanning the log |
|
245 and look up the corresponding function name in the symbol file generated <xref href="GUID-DA62FD4F-2E74-5B2F-B703-4A40DF5F01CA.dita">using the MAKSYM tool</xref> . |
|
246 The first one is <codeph>0xF8170414</codeph> at offset <codeph>4</codeph> in |
|
247 the memory dump. </p> </li> |
|
248 <li id="GUID-3197B03A-FD94-5D78-B699-22BDCE71DD1D"><p>Alternatively, we can |
|
249 use the <filepath>printsym.pl</filepath> perl script, passing it the dump |
|
250 output. The following is part of the output: </p> <codeblock id="GUID-B4289E03-6E98-591D-9E26-CEEDC3CD9437" xml:space="preserve">R:\base\e32\rombuild>perl -S printsym.pl ASSABETARM4D.symbol |
|
251 ROM Symbols from ASSABETARM4D.symbol |
|
252 Please enter data to be decoded |
|
253 6571de54: 07 00 00 10 14 04 17 f8 00 00 00 00 d4 4e 40 00 .............N@. |
|
254 = 10000007 .... |
|
255 = f8170414 .... etext=. + 0x0 |
|
256 = 00000000 .... |
|
257 = 00404ed4 .N@. |
|
258 6571de64: e8 de 71 65 74 de 71 65 74 fb 16 f8 88 28 03 f8 ..qet.qet....(.. |
|
259 = 6571dee8 ..qe |
|
260 = 6571de74 t.qe |
|
261 = f816fb74 t... DDmaTestChannel::DoCreate(int, TDesC8 const *, TVersion const & |
|
262 ) + 0x24 |
|
263 = f8032888 .(.. Kern::Fault(char const *, int) + 0xc |
|
264 6571de74: 0c d4 03 f8 64 35 03 f8 00 00 00 00 00 00 00 00 ....d5.......... |
|
265 = f803d40c .... RHeap::Alloc(int) + 0xf4 |
|
266 = f8033564 d5.. Kern::MutexSignal(DMutex &) + 0xc |
|
267 = 00000000 .... |
|
268 = 00000000 .... |
|
269 |
|
270 [............ truncated ...............] |
|
271 |
|
272 = f801da84 .... DLogicalDevice::ChannelCreate(DLogicalChannelBase *&, TChannelC |
|
273 reateInfo &) + 0xd0 |
|
274 = f816fb5c \... DDmaTestChannel::DoCreate(int, TDesC8 const *, TVersion const & |
|
275 ) + 0xc |
|
276 = 00404e00 .N@. |
|
277 = 00000000 .... |
|
278 6571def4: 00 4e 40 00 00 00 00 00 d3 00 00 00 ec 4e 40 00 .N@..........N@. |
|
279 = 00404e00 .N@. |
|
280 = 00000000 .... |
|
281 = 000000d3 .... |
|
282 = 00404eec .N@. |
|
283 6571df04: d4 df 71 65 14 df 71 65 e0 db 01 f8 c0 d9 01 f8 ..qe..qe........ |
|
284 = 6571dfd4 ..qe |
|
285 = 6571df14 ..qe |
|
286 = f801dbe0 .... ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo & |
|
287 , int) + 0x134 |
|
288 = f801d9c0 .... DLogicalDevice::ChannelCreate(DLogicalChannelBase *&, TChannelC |
|
289 reateInfo &) + 0xc |
|
290 |
|
291 [.......................... truncated .........................] |
|
292 |
|
293 = f8022db8 .-.. ExecHandler::DebugPrint(void *, int) + 0x34 |
|
294 = f800bddc .... A::UserDebugPrint(unsigned char const *, int, int) + 0xc |
|
295 = f800a454 T... EpocSlowExecTable + 0xc |
|
296 = 00000000 .... |
|
297 6571dfc4: ac da 01 f8 10 00 00 60 d8 df 71 65 70 74 00 f8 .......`..qept.. |
|
298 = f801daac .... ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo & |
|
299 , int) + 0x0 |
|
300 = 60000010 ...` |
|
301 = 6571dfd8 ..qe |
|
302 = f8007470 pt.. __ArmVectorSwi + 0xd8 |
|
303 6571dfd4: b8 da 01 f8 d4 4e 40 00 20 f7 16 f8 d0 4e 40 00 .....N@. ....N@. |
|
304 = f801dab8 .... ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo & |
|
305 , int) + 0xc |
|
306 = 00404ed4 .N@. |
|
307 = f816f720 ... etext=. + 0x560 |
|
308 = 00404ed0 .N@. |
|
309 6571dfe4: 00 00 00 00 00 00 00 00 ec 4e 40 00 40 00 00 00 .........N@.@... |
|
310 = 00000000 .... |
|
311 = 00000000 .... |
|
312 = 00404eec .N@. |
|
313 = 00000040 @... |
|
314 ^C |
|
315 R:\base\e32\rombuild> |
|
316 </codeblock> <p>There are several false positives in this output (and even |
|
317 more in the truncated parts). So some study of the source code is needed to |
|
318 discard the noise and find the actual call stack. Here it is (innermost frame |
|
319 first): </p> <ul> |
|
320 <li id="GUID-C83CA525-1731-56BC-8C98-4AEEB5809780"><p> <codeph>Kern::Fault</codeph> </p> </li> |
|
321 <li id="GUID-40B7B48A-F6A0-5CD6-9C0C-2E432FF760BA"><p> <codeph>DDmaTestChannel::DoCreate</codeph> </p> </li> |
|
322 <li id="GUID-E9327B91-F69C-5BC1-B964-FE1B90CA314C"><p> <codeph>ExecHandler::ChannelCreate</codeph> </p> </li> |
|
323 <li id="GUID-0391ADD8-EF56-51F9-987F-B9111903EAC7"><p> <codeph> __ArmVectorSwi</codeph> </p> </li> |
|
324 </ul> <p>Note that for the sake of the example, a call to <xref href="GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D.dita#GUID-C6946ECB-775F-3EC2-A56F-78F25B9FBE3D/GUID-45337A03-5893-3D0D-948C-23BDCF8AECBD"><apiname>Kern::Fault()</apiname></xref> was |
|
325 deliberately inserted into <xref href="GUID-63F99C5E-55C4-305B-BA86-CF73B0CF1520.dita#GUID-63F99C5E-55C4-305B-BA86-CF73B0CF1520/GUID-F0A1E76C-A0E1-39C9-845C-BE19FE2EB415"><apiname>DDmaTestChannel::DoCreate()</apiname></xref>. </p> <p>All |
|
326 other function names are false positives and should be ignored. </p> </li> |
|
327 </ul> </section> |
|
328 <section id="GUID-7F160B0F-9921-578B-B9B0-7CC4CA3B24C3"><title>Walking through |
|
329 the call stack</title> <p>The heuristic method is quick but produces lots |
|
330 of false positives. Another option is to manually reconstitute the call stack |
|
331 from the memory dump. This is relatively easy for debug builds because GCC |
|
332 uses R11 as a frame pointer (FP) and generates the same prologue/epilogue |
|
333 for every function. </p> <p>For release builds, there is no generic solution. |
|
334 It is necessary to check the generated assembler code as there is no standard |
|
335 prologue/epilogue and R11 is not used as frame pointer. </p> <p>A typical |
|
336 prologue for a debug ARM function looks like this: </p> <codeblock id="GUID-9C1F71E0-5F2A-50FF-ABD2-035EB9B5B4D9" xml:space="preserve">mov ip, sp |
|
337 stmfd sp!, {fp, ip, lr, pc} |
|
338 sub fp, ip, #4 /* FP now points to base of stack frame */ |
|
339 sub sp, sp, #16 /* space for local variables */ |
|
340 </codeblock> <p>noting that: <codeph>SP = R13</codeph>, <codeph>FP = R11</codeph>, <codeph>IP |
|
341 = R12</codeph>, <codeph>LR = R14</codeph>, and <codeph>PC = R15</codeph>. </p> <p>This |
|
342 code creates the following stack frame: </p> <fig id="GUID-5CE044A2-CDD0-5A09-B824-BAF46324AB27"> |
|
343 <image href="GUID-F12437C5-BD96-5B43-AD76-614CFAB104D2_d0e300510_href.png" placement="inline"/> |
|
344 </fig> <p>Looking at the example session listed in when <xref href="GUID-1E43E258-A926-5D24-B0A5-8756491C687F.dita#GUID-1E43E258-A926-5D24-B0A5-8756491C687F/GUID-877742A5-F07F-54B6-B871-255FAAE790EB">tracing through the stack heuristically</xref>. in which the crash is due |
|
345 to a panic, the FP value is the R11 value; this is <codeph>0x6571de70</codeph>. |
|
346 This gives us the innermost stack frame: </p> <codeblock id="GUID-DE5FFB23-A85D-562F-858B-CFF407448E36" xml:space="preserve">6571de64: e8 de 71 65 <------------- pointer to previous stack frame |
|
347 74 de 71 65 |
|
348 74 fb 16 f8 <------------- Saved return address |
|
349 88 28 03 f8 <------------- FP points to this word |
|
350 </codeblock> <p>Looking up the saved return address, <codeph>0xf816fb74</codeph>, |
|
351 in the symbol file shows that the current function was called from <codeph>DDmaChannel::DoCreate()</codeph>. </p> <codeblock id="GUID-576615AE-2253-595C-97F5-1DC05F79B750" xml:space="preserve">f816fb50 0198 DDmaTestChannel::DoCreate(int, TDesC8 const *, TVersion const &) |
|
352 f816fce8 007c DDmaTestChannel::~DDmaTestChannel(void) |
|
353 f816fd64 0294 DDmaTestChannel::Request(int, void *, void *) |
|
354 </codeblock> <p>Using the pointer to the previous stack frame saved into the |
|
355 current frame, we can decode the next frame: </p> <codeblock id="GUID-570DB2F6-A76F-5858-816F-7A0E8562B35A" xml:space="preserve">6571ded4: 1c c4 03 64 |
|
356 f8 02 00 64 |
|
357 10 df 71 65 <------------- pointer to previous stack frame |
|
358 ec de 71 65 |
|
359 |
|
360 6571dee4: 84 da 01 f8 <------------- saved return address |
|
361 5c fb 16 f8 <------------- start of second stack frame |
|
362 00 4e 40 00 |
|
363 00 00 00 00 |
|
364 </codeblock> <p>Looking up the saved return address, <codeph>0xf801da84</codeph>, |
|
365 in the symbol file shows that <codeph>DDmaTestChannel::DoCreate()</codeph> was |
|
366 called from <codeph>DLogicalDevice::ChannelCreate()</codeph>. </p> <codeblock id="GUID-B36A9D49-5414-5CC3-8CBF-A2A0EE332B3C" xml:space="preserve">f801d9b4 00f8 DLogicalDevice::ChannelCreate(DLogicalChannelBase *&, TChannelCreateInfo &) |
|
367 f801daac 01b8 ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo &, int) |
|
368 f801dc64 00e4 ExecHandler::ChannelRequest(DLogicalChannelBase *, int, void *, void *) |
|
369 </codeblock> <p>And here is the third stack frame: </p> <codeblock id="GUID-B07DEA17-BA2F-5FEA-8781-E44682BE2D1D" xml:space="preserve">6571df04: d4 df 71 65 <------------- pointer to previous stack frame |
|
370 14 df 71 65 |
|
371 e0 db 01 f8 <------------- saved return address |
|
372 c0 d9 01 f8 <------------- start of third stack frame |
|
373 </codeblock> <p>So <codeph>DLogicalDevice::ChannelCreate()</codeph> was called |
|
374 from <codeph>ExecHandler::ChannelCreate()</codeph>. </p> <p>Note that this |
|
375 mechanical way of walking the stack is valid only for debug functions. For |
|
376 release functions, it is necessary to study the code generated by the compiler. </p> <p>For |
|
377 completness, this is a typical prologue for a debug THUMB function: </p> <codeblock id="GUID-2DC6601E-6304-5638-A1F6-F44F1AB26288" xml:space="preserve">push { r7, lr } |
|
378 sub sp, #28 |
|
379 add r7, sp, #12 /* R7 is THUMB frame pointer */ |
|
380 </codeblock> <p>and this creates the following stack frame: </p> <fig id="GUID-85FAEE94-6D61-5D6B-84CB-6A9491927077"> |
|
381 <image href="GUID-5CF162CA-4395-58AC-A318-2BF178276A57_d0e300587_href.png" placement="inline"/> |
|
382 </fig> <p>A call stack can mix ARM and THUMB frames. Odd return addresses |
|
383 are used for THUMB code and even ones for ARM code. </p> </section> |
|
384 </conbody></concept> |