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. DESCRIPTION. Summary: 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. Detail: 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'
Are you sure that this is a GCC bug, IIRC the linux kernel uses extern inline.
(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.
You ask a linux kernel person :) or you read the source to make sure that all extern inline functions have a corresponding normal definition.
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 :)
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.
(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. Thanks.