avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[avr-libc-dev] [bug #29774] prologue/epilogue stack pointer manipulation


From: Matthew Vernon
Subject: [avr-libc-dev] [bug #29774] prologue/epilogue stack pointer manipulation not interrupt safe in XMega
Date: Tue, 04 May 2010 16:05:22 +0000
User-agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6

URL:
  <http://savannah.nongnu.org/bugs/?29774>

                 Summary: prologue/epilogue stack pointer manipulation not
interrupt safe in XMega
                 Project: AVR C Runtime Library
            Submitted by: sunergos
            Submitted on: Tue 04 May 2010 04:05:21 PM GMT
                Category: Library
                Severity: 3 - Normal
                Priority: 5 - Normal
              Item Group: Unknown
                  Status: None
        Percent Complete: 0%
             Assigned to: None
             Open/Closed: Open
         Discussion Lock: Any
                 Release: 1.6.8
           Fixed Release: None

    _______________________________________________________

Details:

The function prologue and epilogue code (in list files __prologue_saves__ and
__epilogue_restores__) finish by clearing interrupts, changing the stack
pointer, then restoring the status register (potentially enabling
interrupts).

The actual code from the list file for my XMega project is shown below. Note
that 0x3F is the status register (including interrupt enable), and 0x3D with
0x3E are the stack pointer.

The status register is preserved, then interrupts are cleared. Half of the
stack is written, the status register is restored, then the other half of the
stack is written. On most architectures this is correct as one instruction can
safely execute after enabling interrupts (restore SREG) before an interrupt
can occur.


0001b082 <__epilogue_restores__>:
   ...
   1b0aa:       0f b6           in      r0, 0x3f        ; 63
   1b0ac:       f8 94           cli
   1b0ae:       de bf           out     0x3e, r29       ; 62
   1b0b0:       0f be           out     0x3f, r0        ; 63
   1b0b2:       cd bf           out     0x3d, r28       ; 61
   1b0b4:       ed 01           movw    r28, r26
   1b0b6:       08 95           ret


The XMega, however, can jump to an interrupt immediately after the status
register is restored and before the second half of the stack is written.
Therefore any interrupt code that uses the stack will potentially write to an
arbitrary memory location. In my application this results in stack corruption
and a function return to an arbitrary address. 

The solution is to restore the status register on line later ("out      0x3f, 
r0"
after "out      0x3d, r28"). Since this code appears to be external to the 
avr-libc
project I am not sure how to implement the fix beyond my own version of the
library. 

This behavior can be tested by setting an interrupt to be always active such
as a very fast timer interrupt. The code will execute one instruction between
interrupts and therefore an interrupt will occur at the point indicated
above.






    _______________________________________________________

Reply to this item at:

  <http://savannah.nongnu.org/bugs/?29774>

_______________________________________________
  Message sent via/by Savannah
  http://savannah.nongnu.org/





reply via email to

[Prev in Thread] Current Thread [Next in Thread]