GCC generates an invalid stack frame usage sequence in a function epilogue. Function prologue with comments: .align 2 .global rtems_bdbuf_read .code 16 .thumb_func .type rtems_bdbuf_read, %function rtems_bdbuf_read: push {r4, r5, r6, r7, lr} sub sp, sp, #60 add r7, sp, #8 /* * We have now reserved a stack frame in a two step process. The * non-volatile register r7 will be use as an local variable anchor. */ str r3, [r7, #4] mov r3, #0 str r3, [r7, #48] str r3, [r7, #44] str r3, [r7, #40] mov r3, r7 add r3, r3, #44 str r3, [sp] sub r3, r3, #4 str r3, [sp, #4] add r3, r3, #8 bl rtems_bdbuf_obtain_disk str r0, [r7, #12] cmp r0, #0 beq .LCB3661 b .L520 @long jump .LCB3661: Function epilogue with comments: .L520: mov sp, r7 add sp, sp, #52 /* * Here we released the second part of our stack frame which contains * local variables. */ ldr r0, [r7, #12] /* * Here we used the second part of our stack frame which contains local * variables. We read a status variable from the stack frame that will * be returned now. That means we use a part of the frame that we * already released. In case an interrupt happens between these two * instructions (add and ldr) we may have a big problem. These two * instructions are in the wrong order, the reverse order is correct. */ @ sp needed for prologue pop {r4, r5, r6, r7, pc} Attached files follow.
Created attachment 20641 [details] Log.
Created attachment 20642 [details] Preprocessed source file.
Created attachment 20643 [details] Generated assembler file.
GCC 4.5.0 20100414 has this problem too.
GCC 4.2.4 does not have this problem. Function epilogue: .L672: ldr r0, [r7, #4] mov sp, r7 add sp, sp, #52 @ sp needed for prologue pop {r4, r5, r6, r7, pc} You can see here that the mov/add and ldr instructions are in the right order.
If you use GCC 4.5.0 20100414 with '-march=armv7' '-mthumb' '-Os' the function epilogue is also correct. It seems that this is a Thumb 1 problem.
GCC 4.3.2 20080827 has this problem too.
A summary follows. Broken means bdbuf.i generates an invalid stack frame usage sequence in a function epilogue. Works means that the corresponding area is valid. Flags: -march=armv5t -mthumb -Os Broken: GCC 4.3.2 20080827 GCC 4.4.4 20100429 GCC 4.5.0 20100414 Works: GCC 4.2.4 Flags: -march=armv7 -mthumb -Os Works: GCC 4.5.0 20100414 Flags: -march=armv5t -mthumb -O2 Suspicious: GCC 4.5.0 20100414 Suspicious means that the epilogue sequence is this: .L577: mov sp, r7 add sp, sp, #36 mov r0, r4 /* * Here we don't have a problem since r0 comes from r4 * and not from the stack frame. Is this always the case? */ @ sp needed for prologue pop {r2, r3, r4, r5} mov r8, r2 mov r9, r3 mov sl, r4 mov fp, r5 pop {r4, r5, r6, r7, pc}
Confirmed with cross to armv5tel-unknown-linux-gnueabi. 4.3/4.4/4.5/4.6 all generate the signal-unsafe epilogue.
Binary search through trunk revisions yield: r159321 BROKEN r150000 BROKEN r140000 BROKEN r135000 BROKEN r132500 BROKEN r131024 BROKEN r130512 BROKEN r130256 BROKEN r130128 BROKEN r130064 BROKEN r130056 BROKEN r130052 BROKEN r130051 OK r130050 OK r130048 OK r130032 OK r130000 OK
Created attachment 20654 [details] Difference between bdbuf.s in revsions 130051 and 130052 This clearly shows how the frame usage sequence changed.
r130052 is a generic scheduling tweak originally described here: http://gcc.gnu.org/ml/gcc-patches/2007-10/msg01814.html
*** This bug has been marked as a duplicate of 38644 ***