Messages in this thread | | | Date | Sun, 18 Jan 1998 17:36:09 +0100 (MET) | From | "Michael L. Galbraith" <> | Subject | Re: gcc-2.8.0 miscompiles kernel (Was: gcc-2.8 out...) |
| |
On Fri, 16 Jan 1998, Christopher Seawood wrote:
> On Fri, 16 Jan 1998, Jesse Thilo wrote: > > > > They're not. > > > gcc 2.8 is aimed at being 100% reliable, > > > > For what it's worth, it doesn't seem to have quite reached that aim > > yet. When I compile kernel 2.0.33 with gcc 2.7.2.3, it works fine. > > When I compile the same kernel (same configuration, after executing > > "make mrproper") with gcc 2.8.0, my X servers and certain other > > programs dump core. I don't have detailed information yet, but it > > appears that the programs are dumping core in routines that perform > > I/O port access. > > Last I heard, this was a known problem as some kernel code relied upon a > gcc hack that got fixed. It is fixed in the lastest development kernels. > Anyone know when/if these fixes will be backported to 2.0.x ? > > Regards > Christopher
Hello Christopher,
I compiled ./arch/i386/kernel/ioport.c (sys_iopl) with both 2.7.2.3 and 2.8.0 to find out just why this should be considered a kernel code bug and not a compiler bug. Here's what I came up with.
The output of objdump -d -S seems to indicate that the line.. *(&eflags) = (eflags & 0xffffcfff) | (level << 12); .. was simply optimized away by 2.8.0.
Since the manipulation in question is to a local variable, and there are no references past this line, it's OK for gcc to throw it away as it is not valid after the function returns.
It looks like the compiler is now smart enough to take advantage of the opportunity. If I'm wrong about this, I'll surely hear :)
Cheers,
-Mike --------------------------------------------------------------------- asmlinkage int sys_iopl(long ebx,long ecx,long edx, long esi, long edi, long ebp, long eax, long ds, long es, long fs, long gs, long orig_eax, long eip,long cs,long eflags,long esp,long ss) { 120: 55 pushl %ebp 121: 89 e5 movl %esp,%ebp unsigned int level = ebx;
if (level > 3) 123: 83 7d 08 03 cmpl $0x3,0x8(%ebp) 127: 76 07 jbe 130 <sys_iopl+0x10> return -EINVAL; 129: b8 ea ff ff ff movl $0xffffffea,%eax 12e: eb 1e jmp 14e <sys_iopl+0x2e> * normal permissions checks first, and check suser() last. */ extern inline int suser(void) { if (current->euid == 0) { 130: a1 00 00 00 00 movl 0x0,%eax 135: 66 83 b8 1a 01 cmpw $0x0,0x11a(%eax) 13a: 00 00 00 13d: 74 09 je 148 <sys_iopl+0x28> if (!suser()) return -EPERM; 13f: b8 ff ff ff ff movl $0xffffffff,%eax 144: eb 08 jmp 14e <sys_iopl+0x2e> 146: 89 f6 movl %esi,%esi */ extern inline int suser(void) { if (current->euid == 0) { current->flags |= PF_SUPERPRIV; 148: 80 48 15 01 orb $0x1,0x15(%eax) *(&eflags) = (eflags & 0xffffcfff) | (level << 12); return 0; <=== insert missing assembler here :) 14c: 31 c0 xorl %eax,%eax } 14e: 89 ec movl %ebp,%esp 150: 5d popl %ebp 151: c3 ret
| |