I have extracted the following section of code from some boot code that
tests DRAM. As a result this code cannot be run without causing a
segmentation fault, but the problem it illustrates occurs in the real
DRAM test and can be seen it the code disassembly.
This bug has been seen in gcc 4.1.2 and gcc 4.2.1
The code has two loops, which compile correctly when no optimization, or
-O1 are used, but the second loop becomes infinite if -Os or -O2 is used.
The code is:
#include <stdio.h>
int main()
{
volatile unsigned int *addr;
unsigned int readback;
int i;
addr = 0;
for (i = 0; i < 16; i++) *(addr++) = 0;
for (i = 0; i < 16; i++) {
printf("\n reads %d, 0x%08X", i, addr);
readback = *(--addr);
}
return 0;
}
The object dump produced by 'gcc test.c' looks correct:
08048384 <main>:
8048384: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048388: 83 e4 f0 and $0xfffffff0,%esp
804838b: ff 71 fc pushl 0xfffffffc(%ecx)
804838e: 55 push %ebp
804838f: 89 e5 mov %esp,%ebp
8048391: 51 push %ecx
8048392: 83 ec 24 sub $0x24,%esp
8048395: c7 45 f0 00 00 00 00 movl $0x0,0xfffffff0(%ebp)
804839c: c7 45 f8 00 00 00 00 movl $0x0,0xfffffff8(%ebp)
80483a3: eb 11 jmp 80483b6 <main+0x32>
80483a5: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80483a8: c7 00 00 00 00 00 movl $0x0,(%eax)
80483ae: 83 45 f0 04 addl $0x4,0xfffffff0(%ebp)
80483b2: 83 45 f8 01 addl $0x1,0xfffffff8(%ebp)
80483b6: 83 7d f8 0f cmpl $0xf,0xfffffff8(%ebp)
80483ba: 7e e9 jle 80483a5 <main+0x21>
80483bc: c7 45 f8 00 00 00 00 movl $0x0,0xfffffff8(%ebp)
80483c3: eb 2a jmp 80483ef <main+0x6b>
80483c5: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80483c8: 89 44 24 08 mov %eax,0x8(%esp)
80483cc: 8b 45 f8 mov 0xfffffff8(%ebp),%eax
80483cf: 89 44 24 04 mov %eax,0x4(%esp)
80483d3: c7 04 24 e0 84 04 08 movl $0x80484e0,(%esp)
80483da: e8 b9 fe ff ff call 8048298 <printf@plt>
80483df: 83 6d f0 04 subl $0x4,0xfffffff0(%ebp)
80483e3: 8b 45 f0 mov 0xfffffff0(%ebp),%eax
80483e6: 8b 00 mov (%eax),%eax
80483e8: 89 45 f4 mov %eax,0xfffffff4(%ebp)
80483eb: 83 45 f8 01 addl $0x1,0xfffffff8(%ebp)
80483ef: 83 7d f8 0f cmpl $0xf,0xfffffff8(%ebp)
80483f3: 7e d0 jle 80483c5 <main+0x41>
80483f5: b8 00 00 00 00 mov $0x0,%eax
80483fa: 83 c4 24 add $0x24,%esp
80483fd: 59 pop %ecx
80483fe: 5d pop %ebp
80483ff: 8d 61 fc lea 0xfffffffc(%ecx),%esp
8048402: c3 ret
8048403: 90 nop
The object dump produced by 'gcc -Os test.c' seems to have lost the
condition on the second loop so continues indefinitely :
08048384 <main>:
8048384: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048388: 83 e4 f0 and $0xfffffff0,%esp
804838b: ff 71 fc pushl 0xfffffffc(%ecx)
804838e: 55 push %ebp
804838f: 89 e5 mov %esp,%ebp
8048391: 56 push %esi
8048392: 53 push %ebx
8048393: 31 db xor %ebx,%ebx
8048395: 51 push %ecx
8048396: 83 ec 0c sub $0xc,%esp
8048399: c7 03 00 00 00 00 movl $0x0,(%ebx)
804839f: 83 c3 04 add $0x4,%ebx
80483a2: 83 fb 40 cmp $0x40,%ebx
80483a5: 75 f2 jne 8048399 <main+0x15>
80483a7: 31 f6 xor %esi,%esi
80483a9: 50 push %eax
80483aa: 53 push %ebx
80483ab: 83 eb 04 sub $0x4,%ebx
80483ae: 56 push %esi
80483af: 46 inc %esi
80483b0: 68 a0 84 04 08 push $0x80484a0
80483b5: e8 de fe ff ff call 8048298 <printf@plt>
80483ba: 8b 03 mov (%ebx),%eax
80483bc: 83 c4 10 add $0x10,%esp
80483bf: eb e8 jmp 80483a9 <main+0x25>
80483c1: 90 nop
80483c2: 90 nop
80483c3: 90 nop
In this case the second loop no longer has a condition so repeats
indefinitely.