public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Linux kernel miscompile due to clobbered MEM_SIZE
@ 2002-06-07 13:45 Ulrich Weigand
  0 siblings, 0 replies; only message in thread
From: Ulrich Weigand @ 2002-06-07 13:45 UTC (permalink / raw)
  To: gcc

Hello,

we've found incorrect code being generated for the routine
inode_init_once of the Linux kernel 2.5.20 by both gcc 3.1
and CVS head on s390x.  This is a regression over gcc 2.95.3.

The following reduced code snippet shows the bug:

struct rwlock {
  unsigned long lock;
  unsigned long owner_pc;
};

struct list_head {
  struct list_head *next;
  struct list_head *prev;
};

struct wait_queue_head {
  unsigned int lock;
  struct list_head task_list;
};

struct semaphore {
  unsigned int count;
  struct wait_queue_head wait;
};

void inode_init_once (struct semaphore *sem, struct rwlock *lock)
{
  *sem = (struct semaphore) { 1,
                              { lock: 0,
                                task_list: { &sem->wait.task_list,
                                             &sem->wait.task_list } } };
  *lock = (struct rwlock) { 0, 0 };
}

What happens is that *sem is only partially initialized
(on gcc 3.1, only sem->wait.task_list.prev is not initialized, on
gcc 3.2, both sem->wait.task_list.prev and sem->wait.task_list.next
are not initialized).

The initialization is done by preparing a struct semaphore on the
stack, and copying that into *sem.  In this preparation code, the
insns supposed to initialize ...prev (and ...next on gcc 3.2) are
deleted as dead code by the life analysis pass.

If we look at the relevant insns before life:

(insn 23 21 27 (set (mem/s:DI (plus:DI (reg/f:DI 34 %fp)
                (const_int 176 [0xb0])) [0 <anonymous>+16 S8 A64])
        (reg/f:DI 42)) 51 {*movdi_64} (nil)
    (nil))

(insn 27 23 29 (set (mem/s:DI (plus:DI (reg/f:DI 34 %fp)
                (const_int 184 [0xb8])) [0 <anonymous>+24 S8 A64])
        (reg/f:DI 42)) 51 {*movdi_64} (nil)
    (nil))

(insn 29 27 31 (parallel[
            (set (mem/s:BLK (reg/v/f:DI 40) [0 A8])
                (mem/s:BLK (plus:DI (reg/f:DI 34 %fp)
                        (const_int 160 [0xa0])) [0 <anonymous>+0 S16 A64]))
            (use (const_int 31 [0x1f]))
            (clobber (scratch:DI))
        ] ) 72 {movstrdi_short} (nil)
    (nil))

we see that the problem is that in the movstrdi insn, the source
MEM has an incorrect MEM_SIZE of 16 (instead of 32).  This causes
life analysis to think the stores into <anonymous>+16 and +24 dead.
(For some reason, gcc 3.1 doesn't eliminate the store into +16,
only the one into +24.)


The reason for the incorrect MEM_SIZE, in turn, is that this MEM
pointing to the temp stack slot is *reused* as shared rtl for the
*two* compound initializers; first a struct semaphore with 32 bytes,
and later on a struct rwlock with 16 bytes.

Code in expand_expr, however, simply overwrites the mem_attributes
of the MEM returned by assign_temp.  If that temp happens to be
already used, all occurrences in the already emitted RTL will
have their attributes changed as well ...

(Note that this only happens with -fno-strict-aliasing, because
with -fstrict-aliasing, two separate stack slots are allocated.
However, we need -fno-strict-aliasing for the Linux kernel ...)

Any suggestions how this could be fixed?


Mit freundlichen Gruessen / Best Regards

Ulrich Weigand

--
  Dr. Ulrich Weigand
  Linux for S/390 Design & Development
  IBM Deutschland Entwicklung GmbH, Schoenaicher Str. 220, 71032 Boeblingen
  Phone: +49-7031/16-3727   ---   Email: Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2002-06-07 20:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-06-07 13:45 Linux kernel miscompile due to clobbered MEM_SIZE Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).