How to generate meaningfull stacktraces with RTEMS on the Leon3

Jan Sommer soja-lists at aries.uberspace.de
Mon Dec 12 13:44:23 UTC 2016


Hello,

thank you for all your help.
It took some time to read into the sparc specifics, but I think I 
understand enough of the deatils know.
So far I managed to flush the register windows by creating a trap 0x83 
and could properly walk the
callstack upwards from within a function.

I will have to check if I can initiate the trap from within a trap 
handler too and how to get the correct frame pointer at the beginning.

I was wondering if there is a proper way to determine when I have 
reached the beginning of the stack and stop the unwinding. So far I just 
unwind 10 times and afterwards ignore the bogus addresses which may 
appear at some point.

And is there an easy way to replace the bsp_spurious_handler with an own 
implementation without recompiling the BSP?
It doesn't seem to be marked weakly linked.

One last question: What does tpc stand for in the 
CPU_Minimum_stack_frame-struct which is used by the handler-function? I 
first thought it's the trap program counter, but this register seems to 
be new in sparcV9 whereas the leon is sparcV8 (The documentation only 
says "This is the offset of the tpc register on an ISF.").

Best regards,

    Jan



Am 2016-12-08 08:39, schrieb Jiri Gaisler:
> Remember that on SPARC (leon3), parts of the stack will be cached in 
> the
> register file windows. Printing the backtrace by following the
> stack/frame pointers will then not work unless all windows are first
> flushed to memory. This is done automatically on high-level O/S (Linux 
> &
> Solaris), but not on embedded systems like RTEMS.
> 
> Jiri.
> 
> On 07/12/16 13:30, Matthew J Fletcher wrote:
>> Hi,
>> 
>> The gcc builtin functions (and libunwind) and only work if the stack
>> frame information is not optimised away, this is controlled by gcc
>> compiler flags,
>> see; https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html 
>> -fomit-frame-pointer
>> 
>> Without that you have to do your own unwinding, for example on x86 you
>> could do the following, but its pretty crude. Linux/FreeBSD do much
>> more fancy unwinders, it depends on what you want.
>> 
>> #define get_ebp()       \
>> ({ unsigned long  __value;   \
>>    asm volatile (" mov %%ebp,%0": "=a"(__value));  \
>>    __value; })
>> 
>> void error_dump_callstack(int fd)
>> {
>> unsigned longebp=0,arg0,arg4,arg8,arg12,arg16;
>> int i;
>> 
>> arg0 = get_ebp(); // base pointer, start of current stack frame
>> 
>> assert_out(fd,"\r\nCall Stack Information:\r\n\r\n");
>> for (i=0; i<15; i++)
>> {
>> // attempt get backtrace (with arguments) from stored EPB
>> arg0 = *(unsigned long*)(arg0);
>> 
>> if (arg0 == 0)
>> break;
>> 
>> // print stackframe back past inturrupt
>> arg0 = *(unsigned long*)(arg0);
>> arg4 = *(unsigned long*)(arg0+4);
>> arg8 = *(unsigned long*)(arg0+8);
>> arg12 = *(unsigned long*)(arg0+12);
>> arg16 = *(unsigned long*)(arg0+16);
>> sprintf(assertbuffer,"ebp:     %p\r\nframe%d:  %p\r\narg1:
>>  %p\r\narg2:    %p\r\narg3:    %p\r\n",arg0,i,arg4,arg8,arg12,arg16);
>> assert_out(fd,assertbuffer);
>> }
>> assert_out(fd,"use 'addr2line -C -e abc.elf -f address' to get symbol
>> names\r\n");
>> }
>> 
>> 
>> 
>> 
>> 
>> On 6 December 2016 at 22:36, Chris Johns <chrisj at rtems.org
>> <mailto:chrisj at rtems.org>> wrote:
>> 
>>     On 06/12/2016 01:46, Jan Sommer wrote:
>> 
>>         Is there a common way how to create stacktraces in RTEMS?
>> 
>> 
>>     Not that I know of.
>> 
>>         I tried to use the _Unwind_Backtrace_-function from gcc, but
>>         so far it
>>         only returns _URC_END_OF_STACK if I call it from a leaf 
>> function
>>         (haven't tried a trap handler yet).
>> 
>> 
>>     The end of stack code means the unwinder could not find any data
>>     about the frames in the stack. The default DWARF unwinder, which
>>     SPARC uses, searches for a valid Frame Description Entry (FDE) and
>>     if not found reports the end of stack code. If an FDE is found the
>>     Common Information Entry (CIE) is extracted from that data and the
>>     frame info decoded.
>> 
>>     C++ uses the same process for exceptions. A .eh_frame plus some
>>     other sections are created and the frames effected by the
>>     exceptions added to these sections. These sections are registered
>>     at start up. For a DWARF unwinder, which includes the SPARC, the
>>     DWARF standard is used for the format of these sections.
>> 
>>         I am not sure if that is the way to go.
>> 
>> 
>>     I am not 100% sure myself. I think you would need to include some
>>     level of DWARF related information in the executable to do this.
>>     This information would need to be registered with the DWARF
>>     unwinder code via something like 'void __register_frame (void
>>     *begin)'.
>> 
>>     I would also take a look at FreeBSD and see how they implement the
>>     unwinder. I do not know if the FreeBSD kernel has one.
>> 
>>         Are there any recommendations or examples for this topic?
>> 
>> 
>>     The DWARF standard website is the best source of info:
>> 
>>     http://dwarfstd.org/
>> 
>>     Chris
>> 
>>     _______________________________________________
>>     users mailing list
>>     users at rtems.org <mailto:users at rtems.org>
>>     http://lists.rtems.org/mailman/listinfo/users
>>     <http://lists.rtems.org/mailman/listinfo/users>
>> 
>> 
>> 
>> 
>> --
>> 
>> regards
>> ---
>> Matthew J Fletcher
>> 
>> 
>> 
>> _______________________________________________
>> users mailing list
>> users at rtems.org
>> http://lists.rtems.org/mailman/listinfo/users
> 
> 
> _______________________________________________
> users mailing list
> users at rtems.org
> http://lists.rtems.org/mailman/listinfo/users


More information about the users mailing list