2009-12-07 17:50:49

by Thomas Gleixner

[permalink] [raw]
Subject: GCC 4.x random code generator for x86_64 ?

Can anyone shed some light on the following:

Applying a patch which adds a yet unused "extern int bla(void);" line
to a header file results in something which is beyond me.

The .i files differ as expected in exaclty _one_ line.

--- 1.i 2009-12-07 16:23:35.000000000 +0100
+++ 2.i 2009-12-07 16:23:19.000000000 +0100
@@ -6566,6 +6566,8 @@
extern int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock);
# 252 "/home/tglx/work/kernel/rt-new/linux-2.6-tip/include/linux/spinlock.h"
# 1 "/home/tglx/work/kernel/rt-new/linux-2.6-tip/include/linux/rwlock.h" 1
+# 17 "/home/tglx/work/kernel/rt-new/linux-2.6-tip/include/linux/rwlock.h"
+extern int bla(void);
# 253 "/home/tglx/work/kernel/rt-new/linux-2.6-tip/include/linux/spinlock.h" 2

One would expect that the generated code would be the same, but the
resulting code has following surprising deltas (removed the "offset:"
prefix to see the meat of the changes):

41 57 push %r15
41 56 push %r14
41 55 push %r13
+ 4c 8d ad 30 ff ff ff lea -0xd0(%rbp),%r13
41 54 push %r12
49 89 fc mov %rdi,%r12
53 push %rbx
....
48 85 c0 test %rax,%rax
49 89 c5 mov %rax,%r13
- 75 0c jne 85 <timecompare_offset+0x52>
- bb 0a 00 00 00 mov $0xa,%ebx
+ 75 0c jne 8c <timecompare_offset+0x59>
4c 8d ad 30 ff ff ff lea -0xd0(%rbp),%r13
+ bb 0a 00 00 00 mov $0xa,%ebx
45 31 ff xor %r15d,%r15d
45 31 f6 xor %r14d,%r14d
....
44 89 f3 mov %r14d,%ebx
4c 89 e9 mov %r13,%rcx
- 31 d2 xor %edx,%edx
31 c0 xor %eax,%eax
- eb 09 jmp 18f <timecompare_offset+0x15c>
+ 31 d2 xor %edx,%edx
+ eb 09 jmp 196 <timecompare_offset+0x163>
48 03 01 add (%rcx),%rax
ff c2 inc %edx
48 83 c1 10 add $0x10,%rcx

None of these changes makes any sense at all.

This is fully reproducible and the effect on the generated code
depends on the placement of the "extern int bla(void);" line in the
header file.

Note, I disabled BUG and printk and there is no code which might have
a __LINE__ reference which would be affected by the insertion of that
function declaration.

For enhanced fun the problem goes away, when I compile the same kernel
for 32bit with the very same GCC.

Looks to me that GCC has a builtin random code generator for
x86_64. I'd just like to know whether this can be turned off or if
there is some magic way to seed the RCG reliably.

Environment:
F11 x86_64
gcc (GCC) 4.4.1 20090725 (Red Hat 4.4.1-2)

The effect is reproducible with the patch below on top of Linus tree
and just compiling kernel/time/timecompare.o

Also verified that other 4.x versions of GCC have similar
randomization effects just in different source files.

Peter just provided:

@@ -62837,8 +62837,8 @@
3558a: 53 push %rbx
3558b: e8 00 00 00 00 callq 35590 <cleanup_srcu_struct+0x10>
35590: 4c 8b 35 00 00 00 00 mov 0x0(%rip),%r14
- 35597: 83 c9 ff or $0xffffffffffffffff,%ecx
- 3559a: 45 31 ed xor %r13d,%r13d
+ 35597: 45 31 ed xor %r13d,%r13d
+ 3559a: 83 c9 ff or $0xffffffffffffffff,%ecx
3559d: 49 89 fc mov %rdi,%r12
355a0: eb 14 jmp 355b6 <cleanup_srcu_struct+0x36>

Thanks,

tglx
---
include/linux/spinlock.h | 2 ++
1 file changed, 2 insertions(+)

Index: linux-2.6-tip/include/linux/spinlock.h
===================================================================
--- linux-2.6-tip.orig/include/linux/spinlock.h
+++ linux-2.6-tip/include/linux/spinlock.h
@@ -57,6 +57,8 @@

#include <asm/system.h>

+extern int bla(void);
+
/*
* Must define these before including other files, inline functions need them
*/


2009-12-07 18:14:07

by Jakub Jelinek

[permalink] [raw]
Subject: Re: GCC 4.x random code generator for x86_64 ?

On Mon, Dec 07, 2009 at 06:50:17PM +0100, Thomas Gleixner wrote:
> Can anyone shed some light on the following:
>
> Applying a patch which adds a yet unused "extern int bla(void);" line
> to a header file results in something which is beyond me.
>
> The .i files differ as expected in exaclty _one_ line.

The source code is different, so this doesn't seem to be random code
generation. The extra declaration means following decls will have higher
uids and there is a bunch of places in gcc where hash tables are traversed
and code generation depends on the order in the traversal. While hash
tables hashed on pointer values are considered important bugs because
generated code could change in between runs with the same source, traversal
of tables hashed by decl uids are far less severe - gcc makes no promises
that different sources result in the same generated code.
You are using quite oldish gcc, if you reproduce it with something newer
(current 4.5 trunk or recent gcc from redhat/gcc-4_4-branch) and provide
full preprocessed source and exact command line options, I'll have a look
though.

Jakub

2009-12-07 23:10:14

by Thomas Gleixner

[permalink] [raw]
Subject: Re: GCC 4.x random code generator for x86_64 ?

On Mon, 7 Dec 2009, Jakub Jelinek wrote:
> On Mon, Dec 07, 2009 at 06:50:17PM +0100, Thomas Gleixner wrote:
> > Can anyone shed some light on the following:
> >
> > Applying a patch which adds a yet unused "extern int bla(void);" line
> > to a header file results in something which is beyond me.
> >
> > The .i files differ as expected in exaclty _one_ line.
>
> The source code is different, so this doesn't seem to be random code
> generation. The extra declaration means following decls will have higher
> uids and there is a bunch of places in gcc where hash tables are traversed
> and code generation depends on the order in the traversal. While hash
> tables hashed on pointer values are considered important bugs because
> generated code could change in between runs with the same source, traversal
> of tables hashed by decl uids are far less severe - gcc makes no promises
> that different sources result in the same generated code.

Sorry, I do not consider that delta an effective code change and I
don't think that the "no promise" answer is a good explanation for
generated code which is randomly different and in some places worse
for no good reason.

We often use(d) binary comparisions to verify that an assumed zero
change patch actually does what it promises. That way we verified the
bulk of the i386/x86_64 code move and I never saw such odd behaviour
back then (the deltas were way larger than that single line change).

> You are using quite oldish gcc, if you reproduce it with something newer

I was compiling 2.6.32 which is quite oldish code. That deserves an
quite oldish compiler. :)

Seriously, the gcc I'm using is shipped with F11 and that's what a lot
of people (still) have on their machines.

> (current 4.5 trunk or recent gcc from redhat/gcc-4_4-branch) and provide
> full preprocessed source and exact command line options, I'll have a look
> though.

F12 gcc [(GCC) 4.4.2 20091027 (Red Hat 4.4.2-7)] has similar
randomization. I'll send you the preprocessed source + command line
options tomorrow.

The current 4.5 trunk creates identical binary files with and without
the patch.

Thanks,

tglx