This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/12637] New: GCC 3.3.1 ARM. Using "interrupt" keyword causes local variables to be corrupted when calling a function from an interrupt handler.


PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12637

           Summary: GCC 3.3.1 ARM. Using "interrupt" keyword causes local
                    variables to be corrupted when calling a function from
                    an interrupt handler.
           Product: gcc
           Version: 3.3.1
            Status: UNCONFIRMED
          Severity: critical
          Priority: P1
         Component: target
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: hugh dot okeeffe at ashling dot com
                CC: gcc-bugs at gcc dot gnu dot org
 GCC build triplet: arm-elf-gcc
  GCC host triplet: arm-elf-gcc
GCC target triplet: arm-elf-gcc

As an example to highlight this problem, I have the following two functions 
within an application.

void ExternalInterrupt1(void) __attribute__ ((interrupt ("IRQ"))) ;
void ExternalInterrupt2(void);

void ExternalInterrupt1(void)
{
   unsigned long ulValue;

   ulValue = 0x11223344;

   MyFunction(1,2,3,4,5,6);
}

void ExternalInterrupt2(void)
{
   unsigned long ulValue;

   ulValue = 0x11223344;

   MyFunction(1,2,3,4,5,6);
}


These are compiled with "arm-elf-gcc -c  -O0 -g -mlittle-endian" and 
linked "arm-elf-ld -O0 -g -L /cygdrive/C/PFARM/gnuarm/

arm-elf/lib/ -L /cygdrive/C/PFARM/gnuarm/lib/gcc-lib/arm-elf/3.3.1/ -lc -lgcc -
T ./arm.ln --cref" using GNU v3.3.1





The assembler listing for these functions are as follows....



void ExternalInterrupt1(void)
{
40000444:	e52dc004 	str	ip, [sp, -#4]!
40000448:	e1a0c00d 	mov	ip, sp
4000044c:	e92dd80f 	stmdb	sp!, {r0, r1, r2, r3, fp, ip, lr, pc}
40000450:	e24cb004 	sub	fp, ip, #4	; 0x4
40000454:	e24dd00c 	sub	sp, sp, #12	; 0xc
   unsigned long ulValue;

   ulValue = 0x11223344;
40000458:	e59f3030 	ldr	r3, [pc, #48]	; 40000490 
<ExternalInterrupt1+0x4c>
4000045c:	e50b3028 	str	r3, [fp, -#40]

   MyFunction(1,2,3,4,5,6);
40000460:	e3a03005 	mov	r3, #5	; 0x5
40000464:	e58d3000 	str	r3, [sp]
40000468:	e3a03006 	mov	r3, #6	; 0x6
4000046c:	e58d3004 	str	r3, [sp, #4]
40000470:	e3a00001 	mov	r0, #1	; 0x1
40000474:	e3a01002 	mov	r1, #2	; 0x2
40000478:	e3a02003 	mov	r2, #3	; 0x3
4000047c:	e3a03004 	mov	r3, #4	; 0x4
40000480:	ebffffe6 	bl	40000420 <MyFunction>
}
40000484:	e91b680f 	ldmdb	fp, {r0, r1, r2, r3, fp, sp, lr}
40000488:	e8bd1000 	ldmia	sp!, {ip}
4000048c:	e25ef004 	subs	pc, lr, #4	; 0x4
40000490:	11223344 	teqne	r2, r4, asr #6

40000494 <ExternalInterrupt2>:

void ExternalInterrupt2(void)
{
40000494:	e1a0c00d 	mov	ip, sp
40000498:	e92dd800 	stmdb	sp!, {fp, ip, lr, pc}
4000049c:	e24cb004 	sub	fp, ip, #4	; 0x4
400004a0:	e24dd00c 	sub	sp, sp, #12	; 0xc
   unsigned long ulValue;

   ulValue = 0x11223344;
400004a4:	e59f3028 	ldr	r3, [pc, #40]	; 400004d4 
<ExternalInterrupt2+0x40>
400004a8:	e50b3010 	str	r3, [fp, -#16]

   MyFunction(1,2,3,4,5,6);
400004ac:	e3a03005 	mov	r3, #5	; 0x5
400004b0:	e58d3000 	str	r3, [sp]
400004b4:	e3a03006 	mov	r3, #6	; 0x6
400004b8:	e58d3004 	str	r3, [sp, #4]
400004bc:	e3a00001 	mov	r0, #1	; 0x1
400004c0:	e3a01002 	mov	r1, #2	; 0x2
400004c4:	e3a02003 	mov	r2, #3	; 0x3
400004c8:	e3a03004 	mov	r3, #4	; 0x4
400004cc:	ebffffd3 	bl	40000420 <MyFunction>
}
400004d0:	e91ba800 	ldmdb	fp, {fp, sp, pc}
400004d4:	11223344 	teqne	r2, r4, asr #6



When using the "interrupt" keyword, the problem occurs on the call 
to "MyFunction". When the parameters are being pushed onto 

the stack, the "ulValue" local variable gets corrupted. In the function where 
the "interrupt" keyword is not used, this 

corruption does not happen.


The assembler code analysis has shown the following.

Without using the interrupt keyword (and with the stack pointer at 0x4000F000 
on entry to the function):
===============================================================================
=========================


1. Backup the SP into IP
2. Store 0x4 registers on to the stack. SP is now at 0x4000EFF0
3. Subtract 0x4 from the IP value and store the result into FP. FP is now 
0x4000EFFC
4. Subtract 0xC from the SP value and store the result into SP. SP is now 
0x4000EFE4.
5. Load the value 0x11223344 into r3.
6. Store the value in r3 into the location 0x4000EFEC


Note that with the above, the registers (in step 2) are stored from 0x4000EFF0 
to 0x4000EFFC. The ulLocalValue is stored at 

0x4000EFEC. The addresses 0x4000EFE4 & 0x4000EFE8 are unused on the stack. And 
finally the SP is now pointing to 0x4000EFE4.


Using the interrupt keyword (and with the stack pointer at 0x4000F000 after 
the first instruction in the function):
===============================================================================
====================================


1. Backup the SP into IP
2. Store 0x8 registers on to the stack. SP is now at 0x4000EFE0
3. Subtract 0x4 from the IP value and store the result into FP. FP is now 
0x4000EFFC
4. Subtract 0xC from the SP value and store the result into SP. SP is now 
0x4000EFD4.
5. Load the value 0x11223344 into r3.
6. Store the value in r3 into the location 0x4000EFD4


Note that with the above, the registers (in step 2) are stored from 0x4000EFE0 
to 0x4000EFFC. The ulLocalValue is stored at 

0x4000EFD4. The addresses 0x4000EFDC & 0x4000EFD8 are unused on the stack. And 
finally the SP is now pointing to 0x4000EFD4. 

However the ulLocalValue is now at the same location as the stack pointer and 
is primed for destruction.

Following the previous non-interrupt example, it would have been expected that 
the compiler would have put the ulLocalValue 

into 0x4000EFDC. Therefore, intead of the "str	r3, [fp, -#40]", it should 
have been a "str	r3, [fp, -#32]"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]