How to generate meaningfull stacktraces with RTEMS on the Leon3

Jan Sommer soja-lists at aries.uberspace.de
Tue Dec 13 07:26:13 UTC 2016


Ok, 
in the end it was easier than expected.
Writing a new bsp_spurious_initialize function will override the default one, so that I can register my custom spurious handler. 
Sometimes the trap handler will cause a new trap if it dereferences addresses after reaching the end of the callstack, but that is not a real problem.

In case it might help someone else at some point, here is my custom trap handler:

rtems_isr bsp_spurious_handler(
   rtems_vector_number trap,
   CPU_Interrupt_frame *isf
)
{
    // Flush register windows (in RTEMS this is handled by user trap 0x83)
    asm volatile ("ta 0x3");

    // Save the current stackpointer
    uint32_t* sp;
    asm volatile ("\t mov %%sp, %0" : "=r"(sp));

    uint32_t real_trap;

    real_trap = SPARC_REAL_TRAP_NUMBER(trap);


    printk("====== Unexpected trap (0x%02x) at address 0x%08x" , real_trap, isf->tpc);
    switch (real_trap)
    {
      /*
       *  First the ones defined by the basic architecture
       */
      case 0x00:
        printk( "(reset) ======\n" );
        break;
      case 0x01:
        printk( "(instruction access exception) ======\n" );
        break;
      case 0x02:
        printk( "(illegal instruction) ======\n" );
        break;
      case 0x03:
        printk( "(privileged instruction) ======\n" );
        break;
      case 0x04:
        printk( "(fp disabled) ======\n" );
        break;
      case 0x07:
        printk( "(memory address not aligned) ======\n" );
        break;
      case 0x08:
        printk( "(fp exception) ======\n" );
        break;
      case 0x09:
        printk( "(data access exception) ======\n");
        break;
      case 0x0A:
        printk( "(tag overflow) ======\n" );
        break;
      default:
        printk(" ======\n");
        break;
    }

    printk("#0: Trap address: 0x%08x\n", isf->tpc);
    for (int i=1; i<10; ++i)
    {
        printk("#%d: return: 0x%08x, arg1: 0x%08x, arg2: 0x%08x, arg3: 0x%08x\n",
               i,
               sp[15],       // Return address
               sp[ 8],       // i0
               sp[ 9],       // i1
               sp[10]        // i2
               );

        sp = (uint32_t*) (*(sp+14));
    }
    printk("====== End of backtrace ======\n");
    printk("Use \"cut -d: -f3 <<trace.txt>>  | addr2line -C -f -e <<elf>>\" to get symbol names.\n");

    asm volatile( "mov 1, %g1; ta 0x0" );
}

Best regards,

   Jan


On Montag, 12. Dezember 2016 14:44:23 CET Jan Sommer wrote:
> 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
> _______________________________________________
> users mailing list
> users at rtems.org
> http://lists.rtems.org/mailman/listinfo/users
> 





More information about the users mailing list