Bug 20217 - Switching off the optimization triggers undefined reference at link time when building Linux kernel.
Summary: Switching off the optimization triggers undefined reference at link time when...
Alias: None
Product: gcc
Classification: Unclassified
Component: middle-end (show other bugs)
Version: 3.2.3
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Depends on:
Reported: 2005-02-25 22:03 UTC by Steve Tiriac
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Known to work:
Known to fail:
Last reconfirmed:


Note You need to log in before you can comment on or make changes to this bug.
Description Steve Tiriac 2005-02-25 22:03:18 UTC
1. the exact version of GCC;
% gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-49)

2. the system type;
% uname -a
Linux engst3lux.afceng.afc.local 2.4.21-27.0.1.EL #1 Mon Dec 20 18:56:53 EST
2004 i686 i686 i386 GNU/Linux

3. the options given when GCC was configured/built;
Please see #1.

4. the complete command line that triggers the bug;
Please see the description below.

5. the compiler output (error messages, warnings, etc.)
Please see the description below.

6. the preprocessed file (*.i*) 
Out of scope.


Building the Linux kernel with "-O2" ends successfully.
Building the Linux kernel with "-O0" or "no optimization flags" breaks at final
link with undefined symbols.

I got this problem when building a Linux kernel without optimization for debug
purpose on an embedded target. I retested on my host (#2) which is a Dell PC
with preinstalled RedHat Entreprise Linux (#1). I tested building the Linux
kernel 2.6.6, 2.6.8 and 2.6.10. The behavior is present with all these
distributions. I think is a Gcc problem because depends of the presence/absence
of the "-O[0|1|2|3|s]" flags. The undefined symbols are the whole family of
network conversion macros: "htonl, htons,...".

To get the faulty behaviour:
1. Get a Linux kernel distribution (2.6.10 by example)
2. Install it
3. cd in linux-2-6-10
4. do a "make defconfig"
5. edit the Makefile
6. look for the line: "ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE"
7. change the third line beneath from: "CFLAGS          += -O2"
    to: "CFLAGS          += -O0" (uppercase o zero)
8. do a "make 2>&1 | tee make.log"
9. the final link phase fails with undefined symbols:

Extract from output:
   ld -m elf_i386  -r -o init/built-in.o init/main.o init/version.o
init/mounts.o init/initramfs.o
        ld -m elf_i386  -T arch/i386/kernel/vmlinux.lds.s
arch/i386/kernel/head.o arch/i386/kernel/init_task.o  
 init/built-in.o --start-group  usr/built-in.o  arch/i386/kernel/built-in.o 
arch/i386/mm/built-in.o  arch/i386/
mach-default/built-in.o  arch/i386/crypto/built-in.o  kernel/built-in.o 
mm/built-in.o  fs/built-in.o  ipc/built
-in.o  security/built-in.o  crypto/built-in.o  lib/lib.a  arch/i386/lib/lib.a 
lib/built-in.o  arch/i386/lib/bui
lt-in.o  drivers/built-in.o  sound/built-in.o  arch/i386/pci/built-in.o 
arch/i386/oprofile/built-in.o  arch/i38
6/power/built-in.o  net/built-in.o --end-group  -o .tmp_vmlinux1
fs/built-in.o(.text+0xa0969): In function `ext3_get_dev_journal':
: undefined reference to `ntohl'
fs/built-in.o(.text+0xa0980): In function `ext3_get_dev_journal':
: undefined reference to `ntohl'
Comment 1 Andrew Pinski 2005-02-25 22:08:17 UTC
Are you sure that this is a GCC bug, IIRC the linux kernel uses extern inline.
Comment 2 Steve Tiriac 2005-02-25 22:48:24 UTC
(In reply to comment #1)
> Are you sure that this is a GCC bug, IIRC the linux kernel uses extern inline.

How to judge ? I do change nothing to the Linux kernel but I change a 
compilation flag and I get undefined symbols at link. The compiler does not 
signal any error even a warning. I'm not a Gcc expert but the common sense 
tells me is someting the compiler should report as error or warning before 
reaching the link phase.
Comment 3 Andrew Pinski 2005-02-25 22:51:10 UTC
You ask a linux kernel person :) or you read the source to make sure that all extern inline functions 
have a corresponding normal definition.
Comment 4 Steve Tiriac 2005-02-25 23:25:25 UTC
You mean this behavior is perfectly normal for the compiler ? 
This means the optimization flag plays somehow a redundant role with the 
options enabling/disabling error or warning messages ?

I haven't seen anything like this in the Gcc doc, though I cannot say I learnt 
it by heart :)
Comment 5 Jim Wilson 2005-03-10 02:48:24 UTC
The linux kernel requires optimization to be correctly compiled.  This is a
deliberate design decision by the linux kernel developers.

Part of the reason is the kernel's use of extern inline as already mentioned. 
If used as intended, extern inline works without -O.  The linux kernel however
slightly abuses the feature in the interest of reducing kernel code size, thus
resulting in code that can't be compiled correctly without -O.

I believe there is also another issue.  I think there is a process creation
routine that takes advantage of the fact that gcc won't create a stack frame
with optimization in a leaf routine, thus allowing them to have C code to set
the initial stack pointer for the new process.  Normally, setting the stack
pointer would cause all kinds of havoc, but it works in this one special case,
and it only works if you compile with optimization.  I don't recall exactly
where I saw this trick, but I think it was in the linux kernel.

Anyways, a linux kernel developer could answer these kinds of questions better
than a gcc developer.  There may be other reasons why they require optimization.
Comment 6 Steve Tiriac 2005-03-14 18:30:35 UTC
(In reply to comment #5)
> The linux kernel requires optimization to be correctly compiled.  This is a
> deliberate design decision by the linux kernel developers.
Thanks for the explanation. Looking for hints on Google I stumbled on a note
debating if "inline" was correctly used or not in the Linux kernel but I didn't
understant to the extend you describe.

The corollary question is now how I close this bug request.