diff -r bf9a2104bee6 -r 5d016a880824 debuggercdi/com.nokia.carbide.cpp.debug.crashdebugger/html/DebuggingInformation/CrashDebuggerCallStack.guide05.html --- a/debuggercdi/com.nokia.carbide.cpp.debug.crashdebugger/html/DebuggingInformation/CrashDebuggerCallStack.guide05.html Thu Feb 18 14:39:30 2010 -0600 +++ b/debuggercdi/com.nokia.carbide.cpp.debug.crashdebugger/html/DebuggingInformation/CrashDebuggerCallStack.guide05.html Thu Feb 18 15:11:20 2010 -0600 @@ -1,71 +1,71 @@ - -
-The heuristic method is quick but produces lots of false positives. -Another option is to manually reconstitute the call stack from the memory dump. -This is relatively easy for debug builds because GCC uses R11 as a frame -pointer (FP) and generates the same prologue/epilogue for every -function.
-For release builds, there is no generic solution. It is necessary -to check the generated assembler code as there is no standard prologue/epilogue -and R11 is not used as frame pointer.
-A typical prologue for a debug ARM function looks like this:
-mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4 /* FP now points to base of stack frame */
sub sp, sp, #16 /* space for local variables */
noting that: SP = R13, FP = R11, IP -= R12, LR = R14, and PC = R15.
-This code creates the following stack frame:
- -Looking at the example session listed in when -tracing through the stack heuristically. in which the crash is due to a panic, the FP value is the -R11 value; this is 0x6571de70. This gives us the innermost stack -frame:
-6571de64: e8 de 71 65 <------------- pointer to previous stack frame
74 de 71 65
74 fb 16 f8 <------------- Saved return address
88 28 03 f8 <------------- FP points to this word
Looking up the saved return address, 0xf816fb74, in -the symbol file shows that the current function was called from -DDmaChannel::DoCreate().
-f816fb50 0198 DDmaTestChannel::DoCreate(int, TDesC8 const *, TVersion const &)
f816fce8 007c DDmaTestChannel::~DDmaTestChannel(void)
f816fd64 0294 DDmaTestChannel::Request(int, void *, void *)
Using the pointer to the previous stack frame saved into the -current frame, we can decode the next frame:
-6571ded4: 1c c4 03 64
f8 02 00 64
10 df 71 65 <------------- pointer to previous stack frame
ec de 71 65
6571dee4: 84 da 01 f8 <------------- saved return address
5c fb 16 f8 <------------- start of second stack frame
00 4e 40 00
00 00 00 00
Looking up the saved return address, 0xf801da84, in -the symbol file shows that DDmaTestChannel::DoCreate() was called -from DLogicalDevice::ChannelCreate().
-f801d9b4 00f8 DLogicalDevice::ChannelCreate(DLogicalChannelBase *&, TChannelCreateInfo &)
f801daac 01b8 ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo &, int)
f801dc64 00e4 ExecHandler::ChannelRequest(DLogicalChannelBase *, int, void *, void *)
And here is the third stack frame:
-6571df04: d4 df 71 65 <------------- pointer to previous stack frame
14 df 71 65
e0 db 01 f8 <------------- saved return address
c0 d9 01 f8 <------------- start of third stack frame
So DLogicalDevice::ChannelCreate() was called from -ExecHandler::ChannelCreate().
-Note that this mechanical way of walking the stack is valid only -for debug functions. For release functions, it is necessary to study the code -generated by the compiler.
-For completness, this is a typical prologue for a debug THUMB -function:
-push { r7, lr }
sub sp, #28
add r7, sp, #12 /* R7 is THUMB frame pointer */
and this creates the following stack frame:
- -A call stack can mix ARM and THUMB frames. Odd return addresses are -used for THUMB code and even ones for ARM code.
- -The heuristic method is quick but produces lots of false positives. +Another option is to manually reconstitute the call stack from the memory dump. +This is relatively easy for debug builds because GCC uses R11 as a frame +pointer (FP) and generates the same prologue/epilogue for every +function.
+For release builds, there is no generic solution. It is necessary +to check the generated assembler code as there is no standard prologue/epilogue +and R11 is not used as frame pointer.
+A typical prologue for a debug ARM function looks like this:
+mov ip, sp
stmfd sp!, {fp, ip, lr, pc}
sub fp, ip, #4 /* FP now points to base of stack frame */
sub sp, sp, #16 /* space for local variables */
noting that: SP = R13, FP = R11, IP += R12, LR = R14, and PC = R15.
+This code creates the following stack frame:
+ +Looking at the example session listed in when +tracing through the stack heuristically. in which the crash is due to a panic, the FP value is the +R11 value; this is 0x6571de70. This gives us the innermost stack +frame:
+6571de64: e8 de 71 65 <------------- pointer to previous stack frame
74 de 71 65
74 fb 16 f8 <------------- Saved return address
88 28 03 f8 <------------- FP points to this word
Looking up the saved return address, 0xf816fb74, in +the symbol file shows that the current function was called from +DDmaChannel::DoCreate().
+f816fb50 0198 DDmaTestChannel::DoCreate(int, TDesC8 const *, TVersion const &)
f816fce8 007c DDmaTestChannel::~DDmaTestChannel(void)
f816fd64 0294 DDmaTestChannel::Request(int, void *, void *)
Using the pointer to the previous stack frame saved into the +current frame, we can decode the next frame:
+6571ded4: 1c c4 03 64
f8 02 00 64
10 df 71 65 <------------- pointer to previous stack frame
ec de 71 65
6571dee4: 84 da 01 f8 <------------- saved return address
5c fb 16 f8 <------------- start of second stack frame
00 4e 40 00
00 00 00 00
Looking up the saved return address, 0xf801da84, in +the symbol file shows that DDmaTestChannel::DoCreate() was called +from DLogicalDevice::ChannelCreate().
+f801d9b4 00f8 DLogicalDevice::ChannelCreate(DLogicalChannelBase *&, TChannelCreateInfo &)
f801daac 01b8 ExecHandler::ChannelCreate(TDesC8 const &, TChannelCreateInfo &, int)
f801dc64 00e4 ExecHandler::ChannelRequest(DLogicalChannelBase *, int, void *, void *)
And here is the third stack frame:
+6571df04: d4 df 71 65 <------------- pointer to previous stack frame
14 df 71 65
e0 db 01 f8 <------------- saved return address
c0 d9 01 f8 <------------- start of third stack frame
So DLogicalDevice::ChannelCreate() was called from +ExecHandler::ChannelCreate().
+Note that this mechanical way of walking the stack is valid only +for debug functions. For release functions, it is necessary to study the code +generated by the compiler.
+For completness, this is a typical prologue for a debug THUMB +function:
+push { r7, lr }
sub sp, #28
add r7, sp, #12 /* R7 is THUMB frame pointer */
and this creates the following stack frame:
+ +A call stack can mix ARM and THUMB frames. Odd return addresses are +used for THUMB code and even ones for ARM code.
+ +