(this is an update to 'story about lost %ebx (gcc bug?)' mail that seems to wait for moderato approval) My first impression was that there is a bug in gcc compiler on 7-BETA and 8-CURRENT (i386 only, and only if optimization is enabled), but it seems to be incorrect. Most probably source is stack corruption in inet_aton() How to reproduce: 1) Get i386 version of 7-BETA or 8-CURRENT (amd64 does not expose this bug) 2) make shure you build with default options (empty /etc/make.conf) 3) /sbin/route add 172.17.1.0.0/12 10.0.0.1 (yes, network address is incorrect) 4) get core dump core dump shows that in route.c q==NULL in last assignment of this code block: -------- q = strchr(s,'/'); if (q && which == RTA_DST) { *q = '\0'; if ((val = inet_network(s)) != INADDR_NONE) { inet_makenetandmask( val, &su->sin, strtoul(q+1, 0, 0)); return (0); } *q = '/'; } -------- with relevant asm output: --asm--- (-O1) movl $47, 4(%esp) #, movl 12(%ebp), %edx # s, movl %edx, (%esp) #, call strchr # movl %eax, %ebx #, q.583 ## %ebx is q.583 testl %eax, %eax # q.583 setne %al #, tmp160 cmpl $1, 8(%ebp) #, which sete -73(%ebp) #, D.6325 testb %al, -73(%ebp) # tmp160, D.6325 je .L419 #, movb $0, (%ebx) #,* q.583 movl 12(%ebp), %eax # s, movl %eax, (%esp) #, call __inet_network # ## %ebx here should be == 0, because nothing change it below movl %eax, %esi #, D.6327 cmpl $-1, %eax #, D.6327 je .L421 #, leal 1(%ebx), %eax #, D.6328 movl $0, 8(%esp) #, movl $0, 4(%esp) #, movl %eax, (%esp) # D.6328, call strtoul # movl %eax, 8(%esp) # D.6329, movl %edi, 4(%esp) # su, movl %esi, (%esp) # D.6327, call inet_makenetandmask # movl $0, %eax #, D.6280 jmp .L385 # .L421: ## null pointer reference here movb $47, (%ebx) #,* q.583 .L419: -- asm--- My findings so far: for route.c (and 'broken' libc) : 1) code generated by gcc 4.2.1 for this part of route.c is correct for -O0 and -O1. You can make it with CFLAGS=-save-temps -fverbose-asm and check yourself. 2) if route is built with -O0 it will work well in any case. (will not use %ebx) 3) if route is built with -O1 -fno-tree-lrs it will work well (it will not use %ebx to keep q) 4) if -ftree-lrs is enabled with -O1 (or -O2) it will fail (because it will use %ebx that seems to be == 0 after call to inet_network(s)). for libc: 1) if libc is built with -O0 any optimization on route.c will work well (it will not push/pop %ebx in __inet_network in libc) 2) if libc is built with -O1 -fno-tree-lrs route will coredump (-fno-tree-lrs is only a workaround for route.c) 3) -O1 and -O2 libc will give you coredump I checked inet_network.s asm output and can't find any obvious compiler errors there. The only reason for this (as I see now) is a stack corruption in inet_aton that leads to old %ebx (pushed into stack) being replaced with 0x0 and then popped on return from inet_network. Yuriy.Received on Tue Dec 18 2007 - 05:35:10 UTC
This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:24 UTC