Hi,
I'm trying to add backtrace functionallity to the exceptional handler as an offline debugging method where it's not possible to connct a debugger at a customer enviromnet, so it would print in a file the calling stack untill it reachs the exceptional handler.
I followed this thread but I didn't get how to do so through the QSPY or the build flag -mapcs-frame, so I tried this thread by adding a call to the below code from the exception handler and trying these flags to the build flags of the Makefile -mapcs-frame -funwind-tables or -fasynchronous-unwind-tables
#include<unwind.h>//GCC's internal unwinder, part of libgcc_Unwind_Reason_Codetrace_fcn(_Unwind_Context*ctx, void*d)
{
int*depth=(int*)d;printf("\t#%d: program counter at %08x\n", *depth, _Unwind_GetIP(ctx));(*depth)++;return_URC_NO_REASON;
}
voidprint_backtrace_here()
{
intdepth=0;_Unwind_Backtrace(&trace_fcn, &depth);
}
When I tried to build, it throwed the follwoing error
/media/sec_hdd/ahendawy/sedona_workspace/SM-Tools-OS/bin/../lib/gcc/arm-eabi/4.7.3/libgcc.a(unwind-arm.o):Infunction`__aeabi_unwind_cpp_pr0':/home_local/msokolov/tc-build/gcc-build/arm-eabi/libgcc/../../../gcc-4.7.3/libgcc/config/arm/unwind-arm.c:510: multiple definition of `__aeabi_unwind_cpp_pr0'/media/sec_hdd/ahendawy/sedona_workspace/MACSW/qxkinit/aeabi_stubs.o:/media/sec_hdd/ahendawy/sedona_workspace/MACSW/qxkinit/aeabi_stubs.c:8:firstdefinedhere/media/sec_hdd/ahendawy/sedona_workspace/SM-Tools-OS/bin/../lib/gcc/arm-eabi/4.7.3/libgcc.a(unwind-arm.o):Infunction`get_eit_entry':unwind-arm.c:(.text+0x28c): undefined reference to `__exidx_start'unwind-arm.c:(.text+0x290):undefinedreferenceto`__exidx_end'/media/sec_hdd/ahendawy/sedona_workspace/SM-Tools-OS/bin/../lib/gcc/arm-eabi/4.7.3/libgcc.a(unwind-arm.o): In function `unwind_phase2':unwind-arm.c:(.text+0x458):undefinedreferenceto`abort'/media/sec_hdd/ahendawy/sedona_workspace/SM-Tools-OS/bin/../lib/gcc/arm-eabi/4.7.3/libgcc.a(unwind-arm.o): In function `__gnu_Unwind_Resume':unwind-arm.c:(.text+0x568):undefinedreferenceto`abort'unwind-arm.c:(.text+0x590): undefined reference to `abort'/media/sec_hdd/ahendawy/sedona_workspace/SM-Tools-OS/bin/../lib/gcc/arm-eabi/4.7.3/libgcc.a(pr-support.o):Infunction`_Unwind_GetDataRelBase':/home_local/msokolov/tc-build/gcc-build/arm-eabi/libgcc/../../../gcc-4.7.3/libgcc/config/arm/pr-support.c:394: undefined reference to `abort'/media/sec_hdd/ahendawy/sedona_workspace/SM-Tools-OS/bin/../lib/gcc/arm-eabi/4.7.3/libgcc.a(pr-support.o):Infunction`_Unwind_GetTextRelBase':/home_local/msokolov/tc-build/gcc-build/arm-eabi/libgcc/../../../gcc-4.7.3/libgcc/config/arm/pr-support.c:400: undefined reference to `abort'
So kindly, any clues how to fix such error, or in general how to add a backtrace for QXK exceptional handler.
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As you notice, GCC's internal unwinder is part of libgcc, while your build errors are comming from the linker that is unable to find exactly parts of libgcc. This is most likely due to the fact that the program is built without the standard library (see linker options -specs=nosys.specs -specs=nano.specs). The ommision of the standard library in the QP examples for GCC is intentional, because it saves you several KB of code space and allows you to use your own startup code and exception handlers.
But I'm not sure what you're getting from "unwind.h". I mean, there are easier ways to just dump several words from the current stack. I would just take an address of an automatic variable and take this as a good approximation of the current top of stack. From there, you can keep incrementing the pointer. (On ARM the stack grows towards lower addresses, so going from the top of stack down corresponds to incrementing a pointer). A pseudocode for this could look something like this:
I added these flags for the compiler -Wl,-specs=nosys.specs,-specs=nano.specs,-funwind-tables,-fno-exceptions, but it didn't solve the above problems, the flag -fno-exceptions just fix __exidx_start __exidx_end errors.
I see we have here two different errors,
1- multiple definition of __aeabi_unwind_cpp_pr0 which seems conflict with qxk stub at this file qxkinit/aeabi_stubs.c
2- undefined reference to abort function I don't have any idea what's the missing library here, I tried differet options but get nothing.
I'm not close to "unwind.h", but my point behind unwind.h is to print the call stack or the stack trace till the exception handler, the purpose is to print the function addresses ,calling sequence, that leads to that exception handler, I don't know how I could doing so by dumping the current stack in the way you have mentioned above, it may print the return function address 'LR register', but could it print the list of calling functions?
I understand -corect me if I'm wrong- that QP/SPY has the utility to print the call stack or the stack trace but I don't know it could do so?
Thanks
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As I wrote in my previous post, the Makefiles for the QP/C++ examples have been carefully optimized to avoid as much C++ overhead as possible. But to achieve this, the Makefiles don't use the standard library, because that's where the most "fat" could be cut down.
In your case, you apparently use some parts of the GCC library, so you would need to experiment and figure out compiler options and libraries are needed. This might include the "abort()" function and other facilities.
But I would perhaps step back and look at the bigger picture of what you are trying to achieve here. If your application crashes by calling an exception handler, then I would highly recommend that you focus on designing the exception handler to provide some additional information. For example, the return address from the exception is located at the specified offset from the top of stack (the exact offset depends on the use of FPU etc.). Also, if you are using the startup code provided with the QP examples, your exception handler should end up calling the assertion handler (Q_onAssert()). Therefore, you could also think of instrumenting the assertion handler to provide some information.
But stepping back even further, the fact that your application ends up crashing means that you very likely might be using too few assertions in your code. With the right assertion density all errors end up tripping an assertion, which is much better than "crash and burn". You could read more about assertions in the code here:
Hi,
I'm trying to add backtrace functionallity to the exceptional handler as an offline debugging method where it's not possible to connct a debugger at a customer enviromnet, so it would print in a file the calling stack untill it reachs the exceptional handler.
I followed this thread but I didn't get how to do so through the QSPY or the build flag
-mapcs-frame
, so I tried this thread by adding a call to the below code from the exception handler and trying these flags to the build flags of the Makefile-mapcs-frame -funwind-tables or -fasynchronous-unwind-tables
When I tried to build, it throwed the follwoing error
So kindly, any clues how to fix such error, or in general how to add a backtrace for QXK exceptional handler.
Thanks
As you notice, GCC's internal unwinder is part of libgcc, while your build errors are comming from the linker that is unable to find exactly parts of libgcc. This is most likely due to the fact that the program is built without the standard library (see linker options
-specs=nosys.specs -specs=nano.specs
). The ommision of the standard library in the QP examples for GCC is intentional, because it saves you several KB of code space and allows you to use your own startup code and exception handlers.But I'm not sure what you're getting from "unwind.h". I mean, there are easier ways to just dump several words from the current stack. I would just take an address of an automatic variable and take this as a good approximation of the current top of stack. From there, you can keep incrementing the pointer. (On ARM the stack grows towards lower addresses, so going from the top of stack down corresponds to incrementing a pointer). A pseudocode for this could look something like this:
Also, I would probably use QP/Spy to dump the stack instead of
printf()
.--MMS
Last edit: Quantum Leaps 2019-11-07
I added these flags for the compiler
-Wl,-specs=nosys.specs,-specs=nano.specs,-funwind-tables,-fno-exceptions
, but it didn't solve the above problems, the flag-fno-exceptions
just fix__exidx_start __exidx_end
errors.I see we have here two different errors,
1-
multiple definition of __aeabi_unwind_cpp_pr0
which seems conflict with qxk stub at this fileqxkinit/aeabi_stubs.c
2-
undefined reference to abort function
I don't have any idea what's the missing library here, I tried differet options but get nothing.I'm not close to "unwind.h", but my point behind
unwind.h
is to print the call stack or the stack trace till the exception handler, the purpose is to print the function addresses ,calling sequence, that leads to that exception handler, I don't know how I could doing so by dumping the current stack in the way you have mentioned above, it may print the return function address 'LR register', but could it print the list of calling functions?I understand -corect me if I'm wrong- that QP/SPY has the utility to print the call stack or the stack trace but I don't know it could do so?
Thanks
As I wrote in my previous post, the Makefiles for the QP/C++ examples have been carefully optimized to avoid as much C++ overhead as possible. But to achieve this, the Makefiles don't use the standard library, because that's where the most "fat" could be cut down.
In your case, you apparently use some parts of the GCC library, so you would need to experiment and figure out compiler options and libraries are needed. This might include the "abort()" function and other facilities.
But I would perhaps step back and look at the bigger picture of what you are trying to achieve here. If your application crashes by calling an exception handler, then I would highly recommend that you focus on designing the exception handler to provide some additional information. For example, the return address from the exception is located at the specified offset from the top of stack (the exact offset depends on the use of FPU etc.). Also, if you are using the startup code provided with the QP examples, your exception handler should end up calling the assertion handler (Q_onAssert()). Therefore, you could also think of instrumenting the assertion handler to provide some information.
But stepping back even further, the fact that your application ends up crashing means that you very likely might be using too few assertions in your code. With the right assertion density all errors end up tripping an assertion, which is much better than "crash and burn". You could read more about assertions in the code here:
https://embeddedgurus.com/state-space/2009/11/a-nail-for-a-fuse/
https://www.state-machine.com/doc/Samek0308.pdf
https://jaxenter.com/power-ten-nasas-coding-commandments-114124.html
--MMS