My recent 2.6.21.6-rt21 kernel build for ARM dumps a NULL pointer dereference exception due to a missing loop termination condition that was omitted by the gcc 4.3.1 optimizer.
This happens in net/ipv4/inet_hashtables.c, in function inet_lookup_listener_slow which is inlined by the optimizer (-Os, -O2, -O3) into function inet_lookup_listener: ===== C-Code: sk_for_each(sk, node, head) { const struct inet_sock *inet = inet_sk(sk); if (inet->num == hnum && !ipv6_only_sock(sk)) { ... } } ===== Generated assembler code with my comments: .L57: mov r4, r0 ldr r1, [r4], #-8 @ node = node->next; THIS FAILS !!! #APP @ 108 "include/asm/processor.h" 1 pld [r1, #0] @ preload node @ 0 "" 2 ldrh r3, [r4, ip] @ load 'inet->num' ... mov r0, r1 cmp r3, r5 @ ... and compare this with 'hnum' bne .L57 @ if 'inet->num != hnum' continue loop b .L58 @ do the work inside the loop ===== why this code fails: If you look at sk_for_each macro it is replaced with something like: for (node=head; node && ...; node=node->next) Unfortunately the condition for node being non zero is not evaluated every loop. It seems to me that this important condition is replaces with the inner if-condition inet->num == hnum whereas node!=0 is evaluated later on. ===== possible workarounds: Do not use -Os, -O2, -O3. -O1 and -O0 works. E.g. this is the code for the -O1 case: .L47: mov r3, r0 mov r4, ip .L50: cmp r2, #0 @ CHECKS node != 0 !!!!!!! beq .L49 @ terminates loop mov r0, r3 mov ip, r4 b .L51 @ next loop .L43: mvn r0, #0 mov ip, #0 mov r3, #516 add lr, r3, #2 .L51: mov r4, r2 ldr r2, [r4], #-8 #APP @ 108 "include/asm/processor.h" 1 pld [r2, #0] @ 0 "" 2 mov r1, r4 ldrh r3, [r4, lr] cmp r3, r5 bne .L47 b .L54 .L49: ===== Compiler version: 4.3.1 (release version) ===== System type: ARM Linux, XScale-PXA255 (ARMv5-TE) ===== Compiler configure command line: $ ../gcc-4.3.1/configure --prefix=/tmp/tc3/sysroot/cross --target=arm-linux --host=i686-pc-linux-gnu --disable-multilib --with-sysroot=/tmp/tc3/sysroot --disable-nls --enable-shared --enable-languages=c,c++ --enable-__cxa_atexit --enable-c99 --enable-threads=posix --with-float=soft ===== Commandline: (generated by kernel makefile hierarchy) arm-linux-gcc -Wp,-MD,net/ipv4/.inet_hashtables.o.d -nostdinc -isystem tmp/tc3/sysroot/cross/lib/gcc/arm-linux/4.3.1/include -D__KERNEL__ -Iinclude in clude include/linux/autoconf.h -mlittle-endian -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Os -marm fno-omit-frame-pointer -mapcs -mno-sched-prolog -mabi=apcs-gnu -mno-thumb-interwork -D__LINUX_ARM_ARCH__=5 -march=armv5te -mtune=xscale -Wa,-mcpu=xscale -msoft-float -Uarm -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-stack-protector -Wdeclaration-after-statement -Wno-pointer-sign -DFW_VERSION=\"1.1.1-cec0\" -D"KBUILD_STR(s)=\#s" -D"KBUILD_BASENAME=KBUILD_STR(inet_hashtables)" -D"KBUILD_MODNAME=KBUILD_STR (inet_hashtables)" -c -o net/ipv4/inet_hashtables.o net/ipv4/inet_hashtables.c ===== Compiler outputs/warnings: none ===== Attachments: .c, .i and .s files -- Summary: [arm] Optimizer omits loop condition leading to failing code Product: gcc Version: 4.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: berndorfer at festo dot at GCC host triplet: i686-pc-linux-gnu GCC target triplet: arm-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37176