ARM runtime Stack Unwind
Hi,
I have a question about unwinding the stack. I'm using CrossWorks for ARM 3.6 in conjunction with an ARM Cortex M7 processor (STM32F746) powering FreeRTOS v9.0.
I have successfully implemented "pseudo" unwinding in some way - I get to the point where I can get the address of the current r0-r3, r12, LR, PC and PSR registers (HardFault_Handler and MemManage_Handler calls C function from assembler with the frame pointer and control register). However, I'm out of any luck when it comes to real unwinding.
I'm using the following to compile the code:
Compiler options (C and C++):
- -ggdb
- -fexceptions
- -funwind-tables
Code Generation Options:
- Debugging Level: 3
- DWARF version: 4
- Emit Assembler CFI: Yes
- Enable Exception Support: Yes
- Enable RTTI support: Yes
- Instrument Functions: No
- Omit frame pointer: No
- Optimization Level: None
The file /usr/share/crossworks_for_arm_3.6/source/libxceptrtti/gcc-4.x.x/gcc/unwind.h does exist, however I cannot #include it.
Both #include <unwind.h> and #include <gcc/unwind.h> result in a 'no such file' error. Thus, I have added the path /usr/share/crossworks_for_arm_3.6/source/libxceptrtti/gcc-4.x.x as an include path and now GCC can resolve the #include <gcc/unwind.h> include. But I'm not too sure if that is the way it's supposed to look like. Maybe I am missing something.
When I nm my .elf file (grepping for "unwind" and "Unwind"), I get the following output:
08025740 T __aeabi_unwind_cpp_pr0
0802574c W __aeabi_unwind_cpp_pr1
08025758 W __aeabi_unwind_cpp_pr2
08025a18 T __gnu_Unwind_Backtrace
08024cd0 T __gnu_unwind_execute
w __gnu_Unwind_Find_exidx
08025998 T __gnu_Unwind_ForcedUnwind
080251b8 T __gnu_unwind_frame
080254bc t __gnu_unwind_pr_common
08025930 T __gnu_Unwind_RaiseException
08024b3c T __gnu_Unwind_Restore_VFP
08024b4c T __gnu_Unwind_Restore_VFP_D
08024b5c T __gnu_Unwind_Restore_VFP_D_16_to_31
08024bf4 T __gnu_Unwind_Restore_WMMXC
08024b6c T __gnu_Unwind_Restore_WMMXD
080259ac T __gnu_Unwind_Resume
080259ec T __gnu_Unwind_Resume_or_Rethrow
08024b44 T __gnu_Unwind_Save_VFP
08024b54 T __gnu_Unwind_Save_VFP_D
08024b64 T __gnu_Unwind_Save_VFP_D_16_to_31
08024c08 T __gnu_Unwind_Save_WMMXC
08024bb0 T __gnu_Unwind_Save_WMMXD
08024cac T ___Unwind_Backtrace
08024cac T _Unwind_Backtrace
08025a04 T _Unwind_Complete
08025a08 T _Unwind_DeleteException
08024c88 T ___Unwind_ForcedUnwind
08024c88 T _Unwind_ForcedUnwind
08025224 T _Unwind_GetDataRelBase
0800e048 t _Unwind_GetGR
08025200 T _Unwind_GetLanguageSpecificData
080251e4 T _Unwind_GetRegionStart
0802522c T _Unwind_GetTextRelBase
080253b4 t unwind_phase2
080253ec t unwind_phase2_forced
08024c1c T ___Unwind_RaiseException
08024c1c T _Unwind_RaiseException
08024c40 T ___Unwind_Resume
08024c40 T _Unwind_Resume
08024c64 T ___Unwind_Resume_or_Rethrow
08024c64 T _Unwind_Resume_or_Rethrow
08025764 T _Unwind_VRS_Get
080257c4 T _Unwind_VRS_Pop
08025794 T _Unwind_VRS_Set
08023d6c t _ZL17parse_lsda_headerP15_Unwind_ContextPKhP16lsda_header_info
08023d14 t _ZL21base_of_encoded_valuehP15_Unwind_Context
080242c0 t _ZL23__gxx_exception_cleanup19_Unwind_Reason_CodeP21_Unwind_Control_Block
08027c0c R _ZTIN10__cxxabiv115__forced_unwindE
08027bec R _ZTSN10__cxxabiv115__forced_unwindE
So I have the symbols and I can use them after adding the include path. But even then, I still don't know how to do the unwinding itself. My trace function is the following:
_Unwind_Reason_Code trace_func(struct _Unwind_Context * context, void* arg) {
void *ip = (void *)_Unwind_GetIP(context);
printf("Address: %p\n", ip);
return _URC_NO_REASON;
}
I call it via:
_Unwind_Reason_Code code = _Unwind_Backtrace(&trace_func, (void*)(2));
printf("%x\n", code);
within the C function the assembler calls. This does print:
Address: 0800053e
9
The 9 indicates failure "of some kind", as defined in ../gcc/config/arm/unwind-arm.h. The address 0800053e is the return address to the C function that calls _Unwind_Backtrace above.
The Call Stack within the CorssWorks IDE tells me that the last 3 addresses (of my interest) are:
0x08000560 (C handler function)
0x0800056C (assembler HardFault_Handler and MemManage_Handler)
0x080108EE (C++ method where the fault occurs: passing a NULL pointer which is expected to be an array)
I need to get at least to printing out 0x080108EE. As soon as I'm there, I can work my way up. How do I do that?
Thanks a bunch!
Please sign in to leave a comment.
Comments
1 comment