function with stack arrays corrupts saved registers on stack

Bug #1243022 reported by Victor Kamensky on 2013-10-22
12
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Linaro GCC
Fix Released
Undecided
Zhenqiang Chen
Linaro Toolchain Binaries
Fix Released
Undecided
Unassigned
linaro-networking
Medium
Unassigned
gcc-4.8 (Ubuntu)
Undecided
Unassigned

Bug Description

Problem high level description
------------------------------

Crash in xhci_mem_init function was observed on Arndale eval
board, when code was compiled by 4.8-2013.09 Linaro compiler.

Upon investigation it was found that compiler generates code
in xhci_check_trb_in_td_math function that corrupts $r8 register
value saved on stack, when code returns and restore bad value
of $r8 xhci_mem_init crashes. xhci_check_trb_in_td_math function
has complicated arrays create on the stack, most likely size
of those arrays was miscalculated.

Reproduce the issue
-------------------

Here is two ways to reproduce the issue. All test cases are in attached tarball.

1) Full post processed xhci-mem.c is attached as full/xhci-mem.i. Compile line
used by kernel build is attached as full/xhci-mem.sh

2) Smaller test case after running xhci-mem.i through delta script attached
as minimal/test.c and script compile script minimal/test.sh

Disassemble of xhci_check_trb_in_td_math function
-------------------------------------------------

Here is annotated disassemble of problematic function. It
shows that code corrups location where r8 registers is
stored. Real value cited are from below debug session
log.

(gdb) disassemble xhci_check_trb_in_td_math
Dump of assembler code for function xhci_check_trb_in_td_math: <---- sp = sp0 = 0xEF17BC68
   0x803194e4 <+0>: stmdb sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} <-------- sp = sp0 - 36 = 0xEF17BC44 (9 registers)
                                                                            r8 stored at sp0 - 20 = 0xEF17BC54 location (5th register)
   0x803194e8 <+4>: sub sp, #444 ; 0x1bc <---- sp = sp - 444 = sp0 - 36 - 444 = sp0 - 480 = 0xEF17BA88
   0x803194ea <+6>: push {lr} <---- sp = sp - 4 = sp0 - 480 - 4 = sp0 - 484 = 0xEF17BA84
   0x803194ec <+8>: bl 0x8000cc8c <__gnu_mcount_nc> <---- in __gnu_mcount_nc sp = sp + 4 = sp0 - 480 = 0xEF17BA88
   0x803194f0 <+12>: mov r9, r0
   0x803194f2 <+14>: movs r5, #0
   0x803194f4 <+16>: ldr r0, [r0, #116] ; 0x74
   0x803194f6 <+18>: mov r11, r5
   0x803194f8 <+20>: ldr.w r1, [r9, #96] ; 0x60
   0x803194fc <+24>: add.w lr, sp, #184 ; 0xb8
   0x80319500 <+28>: str r5, [sp, #32]
   0x80319502 <+30>: add r7, sp, #440 ; 0x1b8 <---- r7 = sp + 440 = sp0 - 480 + 440 = sp0 - 40 = 0xef17bc40
   0x80319504 <+32>: ldr.w r8, [r0]
   0x80319508 <+36>: ldr r0, [r1, #0]
   0x8031950a <+38>: str r5, [sp, #36] ; 0x24
   0x8031950c <+40>: str r5, [sp, #52] ; 0x34
   0x8031950e <+42>: ldrd r4, r5, [r8, #8]
   0x80319512 <+46>: ldr r2, [r0, #0]
   0x80319514 <+48>: ldr.w r10, [r8]
   0x80319518 <+52>: adds.w r3, r5, #64 ; 0x40
   0x8031951c <+56>: str.w r8, [lr]
   0x80319520 <+60>: str.w r2, [lr, #68] ; 0x44
   0x80319524 <+64>: adc.w r2, r4, #0
   0x80319528 <+68>: strd r2, r3, [lr, #112] ; 0x70
   0x8031952c <+72>: subs.w r3, r5, #16
   0x80319530 <+76>: adc.w r2, r4, #4294967295
   0x80319534 <+80>: add.w r6, r10, #1008 ; 0x3f0
   0x80319538 <+84>: strd r2, r3, [r7, #16] <----- r7 + 16 = sp0 - 40 + 16 = sp0 - 24 = 0xef17bc50
                                                                        (bcz strd sp0 - 20 = 0xef17bc54 updated with r3
                                                                        value, which is stored r8 location)
   0x8031953c <+88>: ldrd r2, r3, [sp, #32]
   0x80319540 <+92>: str r6, [sp, #48] ; 0x30

Full DS-5 debug log
-------------------

Complete debugging session details

Execution stopped at breakpoint 2: N:0x803194E4
On core Cortex-A15_0 (ID 0)
N:0x803194E4 PUSH {r4-r11,lr}
x /40i 0x803194E4
N:0x803194E4 : PUSH {r4-r11,lr}
N:0x803194E8 : SUB sp,sp,#0x1bc
N:0x803194EA : PUSH {lr}
N:0x803194EC : BL {pc}-0x30c860 ; 0x8000cc8c
N:0x803194F0 : MOV r9,r0
N:0x803194F2 : MOVS r5,#0
N:0x803194F4 : LDR r0,[r0,#0x74]
N:0x803194F6 : MOV r11,r5
N:0x803194F8 : LDR r1,[r9,#0x60]
N:0x803194FC : ADD lr,sp,#0xb8
N:0x80319500 : STR r5,[sp,#0x20]
N:0x80319502 : ADD r7,sp,#0x1b8
N:0x80319504 : LDR r8,[r0,#0]
N:0x80319508 : LDR r0,[r1,#0]
N:0x8031950A : STR r5,[sp,#0x24]
N:0x8031950C : STR r5,[sp,#0x34]
N:0x8031950E : LDRD r4,r5,[r8,#8]
N:0x80319512 : LDR r2,[r0,#0]
N:0x80319514 : LDR r10,[r8,#0]
N:0x80319518 : ADDS r3,r5,#0x40
N:0x8031951C : STR r8,[lr,#0]
N:0x80319520 : STR r2,[lr,#0x44]
N:0x80319524 : ADC r2,r4,#0
N:0x80319528 : STRD r2,r3,[lr,#0x70]
N:0x8031952C : SUBS r3,r5,#0x10
N:0x80319530 : ADC r2,r4,#0xffffffff
N:0x80319534 : ADD r6,r10,#0x3f0
N:0x80319538 : STRD r2,r3,[r7,#0x10] <-------
N:0x8031953C : LDRD r2,r3,[sp,#0x20]
N:0x80319540 : STR r6,[sp,#0x30]
N:0x80319542 : STR r6,[lr,#8]
N:0x80319546 : MOV r6,r11
N:0x80319548 : STRD r2,r3,[r7,#-0x180]!
<snip>
p /x $sp
$4 = 0xEF17BC68
si
Execution stopped at: N:0x803194E8
On core Cortex-A15_0 (ID 0)
N:0x803194E8 SUB sp,sp,#0x1bc
p /x $sp
$5 = 0xEF17BC44
info reg
R0 0xEEB30000 0xEEB30000
R1 0xF014E400 0xF014E400
R2 0x00000000 0x00000000
R3 0xEEB1E6C0 0xEEB1E6C0
R4 0xF0160460 0xF0160460
R5 0xAEB36001 0xAEB36001
R6 0xEF268E10 0xEF268E10
R7 0xF0160020 0xF0160020
R8 0xEEB30000 0xEEB30000
R9 0x00000080 0x00000080
R10 0x00000000 0x00000000
R11 0x806924D4 0x806924D4
R12 0x80319335 0x80319335
SP 0xEF17BC44 0xEF17BC44
LR 0x8031AE61 0x8031AE61
PC 0x803194E8 0x803194E8
CPSR 0xA0000333 NzCvq_ge3ge2ge1ge0_inactive_EAifTj_SVC

x /10w $sp
N:0xEF17BC44: 0xF0160460 0xAEB36001 0xEF268E10 0xF0160020
N:0xEF17BC54: 0xEEB30000 0x00000080 0x00000000 0x806924D4
N:0xEF17BC64: 0x8031AE61 0x00000000
si
Execution stopped at: N:0x803194EA
On core Cortex-A15_0 (ID 0)
N:0x803194EA PUSH {lr}
p /x $sp
$6 = 0xEF17BA88
si
Execution stopped at: N:0x803194EC
On core Cortex-A15_0 (ID 0)
N:0x803194EC BL {pc}-0x30c860 ; 0x8000cc8c
p /x $sp
$7 = 0xEF17BA84
si
Execution stopped at: N:0x8000CC8C
On core Cortex-A15_0 (ID 0)
N:0x8000CC8C MOV r12,lr
si
Execution stopped at: N:0x8000CC8E
On core Cortex-A15_0 (ID 0)
N:0x8000CC8E POP {lr}
p /x $sp
$8 = 0xEF17BA84
si
Execution stopped at: N:0x8000CC92
On core Cortex-A15_0 (ID 0)
N:0x8000CC92 MOV pc,r12
p /x $sp
$9 = 0xEF17BA88
si
Execution stopped at breakpoint 3: N:0x803194F0
On core Cortex-A15_0 (ID 0)
N:0x803194F0 MOV r9,r0
p /x $sp
$10 = 0xEF17BA88
si
Execution stopped at: N:0x803194F2
On core Cortex-A15_0 (ID 0)
N:0x803194F2 MOVS r5,#0
si
Execution stopped at: N:0x803194F2
On core Cortex-A15_0 (ID 0)
N:0x803194F2 MOVS r5,#0
dis 3
Breakpoint 3 disabled
si
Execution stopped at: N:0x803194F4
On core Cortex-A15_0 (ID 0)
N:0x803194F4 LDR r0,[r0,#0x74]
si
Execution stopped at: N:0x803194F6
On core Cortex-A15_0 (ID 0)
N:0x803194F6 MOV r11,r5
si
Execution stopped at: N:0x803194F8
On core Cortex-A15_0 (ID 0)
N:0x803194F8 LDR r1,[r9,#0x60]
si
Execution stopped at: N:0x803194FC
On core Cortex-A15_0 (ID 0)
N:0x803194FC ADD lr,sp,#0xb8
si
Execution stopped at: N:0x80319500
On core Cortex-A15_0 (ID 0)
N:0x80319500 STR r5,[sp,#0x20]
p /x $sp
$11 = 0xEF17BA88
si
Execution stopped at: N:0x80319502
On core Cortex-A15_0 (ID 0)
N:0x80319502 ADD r7,sp,#0x1b8
si
Execution stopped at: N:0x80319504
On core Cortex-A15_0 (ID 0)
N:0x80319504 LDR r8,[r0,#0]
p /x $r7
$12 = 0xEF17BC40
p /x $sp
$13 = 0xEF17BA88
si
Execution stopped at: N:0x80319508
On core Cortex-A15_0 (ID 0)
N:0x80319508 LDR r0,[r1,#0]
si
Execution stopped at: N:0x8031950A
On core Cortex-A15_0 (ID 0)
N:0x8031950A STR r5,[sp,#0x24]
si
Execution stopped at: N:0x8031950C
On core Cortex-A15_0 (ID 0)
N:0x8031950C STR r5,[sp,#0x34]
si
Execution stopped at: N:0x8031950E
On core Cortex-A15_0 (ID 0)
N:0x8031950E LDRD r4,r5,[r8,#8]
si
Execution stopped at: N:0x80319512
On core Cortex-A15_0 (ID 0)
N:0x80319512 LDR r2,[r0,#0]
si
Execution stopped at: N:0x80319514
On core Cortex-A15_0 (ID 0)
N:0x80319514 LDR r10,[r8,#0]
si
Execution stopped at: N:0x80319518
On core Cortex-A15_0 (ID 0)
N:0x80319518 ADDS r3,r5,#0x40
si
Execution stopped at: N:0x8031951C
On core Cortex-A15_0 (ID 0)
N:0x8031951C STR r8,[lr,#0]
si
Execution stopped at: N:0x80319520
On core Cortex-A15_0 (ID 0)
N:0x80319520 STR r2,[lr,#0x44]
si
Execution stopped at: N:0x80319524
On core Cortex-A15_0 (ID 0)
N:0x80319524 ADC r2,r4,#0
si
Execution stopped at: N:0x80319528
On core Cortex-A15_0 (ID 0)
N:0x80319528 STRD r2,r3,[lr,#0x70]
si
Execution stopped at: N:0x8031952C
On core Cortex-A15_0 (ID 0)
N:0x8031952C SUBS r3,r5,#0x10
si
Execution stopped at: N:0x80319530
On core Cortex-A15_0 (ID 0)
N:0x80319530 ADC r2,r4,#0xffffffff
si
Execution stopped at: N:0x80319534
On core Cortex-A15_0 (ID 0)
N:0x80319534 ADD r6,r10,#0x3f0
si
Execution stopped at: N:0x80319538
On core Cortex-A15_0 (ID 0)
N:0x80319538 STRD r2,r3,[r7,#0x10]
x /1wx 0xEF17BC54
N:0xEF17BC54: 0xEEB30000
p /x $r3
$14 = 0xAEB363F0
si
Execution stopped at: N:0x8031953C
On core Cortex-A15_0 (ID 0)
N:0x8031953C LDRD r2,r3,[sp,#0x20]
x /1wx 0xEF17BC54
N:0xEF17BC54: 0xAEB363F0

Victor Kamensky (vkamensky) wrote :
Victor Kamensky (vkamensky) wrote :
Download full text (3.8 KiB)

4.7 vs 4.8
----------

Checked the same code under 4.7. linaro 4.7-2013.04-20130415 does not have
this problem. Note instruction at 0x8030602c that does store relative $r7
and it updates $r7. Whereas in 4.8 similar instruction comes at address
0x80319548 which is after instruction that corrupts saved on stack register.

4.7
---

(gdb) disassemble xhci_check_trb_in_td_math
Dump of assembler code for function xhci_check_trb_in_td_math:
   0x8030600c <+0>: stmdb sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} <---
   0x80306010 <+4>: sub sp, #436 ; 0x1b4 <----------------------
   0x80306012 <+6>: push {lr} <----------------------
   0x80306014 <+8>: bl 0x8000cdcc <__gnu_mcount_nc> <------------------
   0x80306018 <+12>: add r7, sp, #432 ; 0x1b0 <----------------------
   0x8030601a <+14>: mov r9, r0
   0x8030601c <+16>: ldr r1, [r0, #116] ; 0x74
   0x8030601e <+18>: add r3, sp, #176 ; 0xb0
   0x80306020 <+20>: ldr r2, [r0, #96] ; 0x60
   0x80306022 <+22>: movs r0, #0
   0x80306024 <+24>: movs r4, #0
   0x80306026 <+26>: ldr.w r8, [r1]
   0x8030602a <+30>: movs r1, #0
   0x8030602c <+32>: strd r0, r1, [r7, #-384]! ; 0x180 <--------------
   0x80306030 <+36>: mov r6, r4
   0x80306032 <+38>: ldr r2, [r2, #0]
   0x80306034 <+40>: ldr.w r1, [r8]
   0x80306038 <+44>: str r4, [sp, #40] ; 0x28
   0x8030603a <+46>: ldrd r10, r11, [r2, #8]
   0x8030603e <+50>: add.w r0, r1, #1008 ; 0x3f0
   0x80306042 <+54>: str r1, [sp, #28]
   0x80306044 <+56>: str r0, [sp, #44] ; 0x2c
   0x80306046 <+58>: ldrd r0, r1, [r8, #8]
   0x8030604a <+62>: strd r10, r11, [sp, #32]
   0x8030604e <+66>: ldrd r10, r11, [r8, #8]
   0x80306052 <+70>: adds r1, #64 ; 0x40
   0x80306054 <+72>: ldr r5, [r2, #0]
   0x80306056 <+74>: adc.w r0, r0, #0
   0x8030605a <+78>: str.w r8, [r3]
   0x8030605e <+82>: subs.w r11, r11, #16
   0x80306062 <+86>: strd r0, r1, [r3, #112] ; 0x70
   0x80306066 <+90>: ldrd r0, r1, [r8, #8]
   0x8030606a <+94>: adc.w r10, r10, #4294967295
   0x8030606e <+98>: strd r10, r11, [r7, #16] <-------------------------

4.8
---

(gdb) disassemble xhci_check_trb_in_td_math
Dump of assembler code for function xhci_check_trb_in_td_math:
   0x803194e4 <+0>: stmdb sp!, {r4, r5, r6, r7, r8, r9, r10, r11, lr} <---
   0x803194e8 <+4>: sub sp, #444 ; 0x1bc <----------------------
   0x803194ea <+6>: push {lr} <----------------------
   0x803194ec <+8>: bl 0x8000cc8c <__gnu_mcount_nc> <------------------
   0x803194f0 <+12>: mov r9, r0
   0x803194f2 <+14>: movs r5, #0
   0x803194f4 <+16>: ldr r0, [r0, #116] ; 0x74
   0x803194f6 <+18>: mov r11, r5
   0x803194f8 <+20>: ldr.w r1, [r9, #96] ; 0x60
   0x803194fc <+24>: add.w lr, sp, #184 ; 0xb8
   0x80319500 <+28>: str r5, [sp, #32]
   0x80319502 <+30>: add r7, sp, #440 ; 0x1b8 <----------------------
   0x80319504 <+32>: ldr.w r8, [r0]
   0x80319508 <+36>: ldr r0, [r1, #0]
   0x8031950a <+38>: str r5, [sp, #36] ; 0x24
   0x8031950c <+40>: str r5, [sp, #52] ; 0x34
   0x8031950e <+42>: ldrd r4, r5, [r8, #8]
   0x80319512 <+46>: ldr r2, [r0, #0]
   0x80319514 <+48>: ldr.w r10, [r8]
   0x80319518 <+52>: adds.w r3, r5, #64 ; 0x40
   0x8031951c <+56>: str.w r8, [lr]
   0x80319520 <+60>: str.w ...

Read more...

Changed in gcc-linaro:
assignee: nobody → Zhenqiang Chen (zhenqiang-chen)
Zhenqiang Chen (zhenqiang-chen) wrote :

Which toolchain do you use for 4.8? Big-endian or little-endian?

As I know, we did not release 4.7 big-endian toolchain.

If the 4.8 is Big-endian toolchain, can you try 4.8 little-endian toolchain? I want to check it is a general 4.8 issue or just Big-endian toolchain issue.

Thanks!
-Zhenqiang

Download full text (12.3 KiB)

Hi Zhenqiang,
I've spent noticeable time creating test cases for this bug.
Please look at attached xhci-mem-crash.tar.gz and bug
description for two possible ways to reproduce the issue.
Do you have trouble running them? Please let me know.
By compiler name (arm-linux-gnueabihf-gcc) used inside
of test scripts you can tell that LE compiler have being
used although with -mbig-endian option. I've tried test cases
with -mlittle-endian - the same problem is present, and actually
LE kernel image from the same source base crashes with
the same symptom. So I don't believe the problem has
anything to do with endianity.
Also FYI: kernel build does not care what ARM V7
toolchain defaults are BE or LE - kernel makefile will set all
explicit correct compiler and linker option. One can use
V7 toolchain with LE default to build BE kernel. ARM
toolchain is always capable of building LE or BE code, the
only difference between arm and armeb targets are assigned
defaults.

Thanks,
Victor

On 22 October 2013 01:48, Zhenqiang Chen <email address hidden> wrote:
> Which toolchain do you use for 4.8? Big-endian or little-endian?
>
> As I know, we did not release 4.7 big-endian toolchain.
>
> If the 4.8 is Big-endian toolchain, can you try 4.8 little-endian
> toolchain? I want to check it is a general 4.8 issue or just Big-endian
> toolchain issue.
>
> Thanks!
> -Zhenqiang
>
> --
> You received this bug notification because you are a member of Linaro
> Networking Group, which is subscribed to linaro-networking.
> Matching subscriptions: LNG all
> https://bugs.launchpad.net/bugs/1243022
>
> Title:
> function with stack arrays corrupts saved registers on stack
>
> Status in Linaro GCC:
> New
> Status in Linaro networking Group:
> New
> Status in Linaro Toolchain Binaries:
> New
>
> Bug description:
> Problem high level description
> ------------------------------
>
> Crash in xhci_mem_init function was observed on Arndale eval
> board, when code was compiled by 4.8-2013.09 Linaro compiler.
>
> Upon investigation it was found that compiler generates code
> in xhci_check_trb_in_td_math function that corrupts $r8 register
> value saved on stack, when code returns and restore bad value
> of $r8 xhci_mem_init crashes. xhci_check_trb_in_td_math function
> has complicated arrays create on the stack, most likely size
> of those arrays was miscalculated.
>
>
> Reproduce the issue
> -------------------
>
> Here is two ways to reproduce the issue. All test cases are in
> attached tarball.
>
> 1) Full post processed xhci-mem.c is attached as full/xhci-mem.i. Compile line
> used by kernel build is attached as full/xhci-mem.sh
>
> 2) Smaller test case after running xhci-mem.i through delta script attached
> as minimal/test.c and script compile script minimal/test.sh
>
>
> Disassemble of xhci_check_trb_in_td_math function
> -------------------------------------------------
>
> Here is annotated disassemble of problematic function. It
> shows that code corrups location where r8 registers is
> stored. Real value cited are from below debug session
> log.
>
> (gdb) disassemble xhci_check_trb_in_td_math
> Dump of assembler...

Zhenqiang Chen (zhenqiang-chen) wrote :

Thanks. I can reproduce it now.

Changed in linaro-toolchain-binaries:
status: New → Confirmed
Zhenqiang Chen (zhenqiang-chen) wrote :

Root cause:
REG_INC note is lost in subreg2 pass, which leads to wrong dependence and instruction.

Will work out a patch to fix it.

Zhenqiang Chen (zhenqiang-chen) wrote :

Patch is sent out for review.

Changed in gcc-linaro:
status: New → In Progress
Changed in linaro-networking:
importance: Undecided → Medium
Zhenqiang Chen (zhenqiang-chen) wrote :

Patch is committed in trunk. Will backport the Linaro gcc.

Backport to gcc-linaro-4.8 as rev SVN 240570 (bzr mirror 122136).
Part of gcc-linaro-4.8-2013.11 release.

Changed in gcc-linaro:
status: In Progress → Fix Released
Changed in linaro-toolchain-binaries:
status: Confirmed → Fix Released
Changed in linaro-networking:
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers