hugeice 发表于 2010-4-15 16:23:06

求助:如何用-O0优化级别编译Linux内核?

我想调试内核源码,发现代码执行顺序与源码不太一致,根据经验,这应该是打开优化选项的结果,于是我想关闭优化编译Linux内核,也就是将内核的编译选项 -O2 改为 -O0,我直接修改了内核源码顶层目录下 Makefile 文件的 525 行:
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
#CFLAGS    += -Os
CFLAGS      += -O0
else
#CFLAGS    += -O2
CFLAGS      += -O0
endif
其中注释掉到是原来的,注释下面是我改动的地方,也就是只是将-Os和-O2改成-O0而已。
我到目标板用的发行版是 montavista pro 4.0.1,host是 Fedora12,编译器是 arm_v5t_le-gcc。
修改了Makefile之后,重新编译内核出现很多错误,错误信息在后面。
错误信息中提到的那些未定义标号肯定是定义过的,因为用-O2或者-O1优化选项都能够顺利编译通过,那么仅仅修改了优化级别,为什么结果就不一样了呢?
希望高手解答啊 !!

以下是编译错误:
$ make ARCH=arm CROSS_COMPILE=arm_v5t_le- uImage
CHK    include/linux/version.h
SPLITinclude/linux/autoconf.h -> include/config/*
SYMLINK include/asm-arm/arch -> include/asm-arm/arch-davinci
make: `arch/arm/kernel/asm-offsets.s' is up to date.
make: `include/asm-arm/mach-types.h' is up to date.
CHK    include/linux/compile.h
UPD    include/linux/compile.h
CC      init/version.o
LD      init/built-in.o
CHK    usr/initramfs_list
GEN    .version
CHK    include/linux/compile.h
dnsdomainname: 未知的主机
UPD    include/linux/compile.h
CC      init/version.o
LD      init/built-in.o
LD      .tmp_vmlinux1
init/built-in.o(.init.text+0x1e8c): In function `identify_ramdisk_image':
init/do_mounts_rd.c:92: undefined reference to `ntohl'
arch/arm/mm/built-in.o(.text+0x1624): In function `adjust_pte':
arch/arm/mm/fault-armv.c:77: undefined reference to `cpu_tlb'
arch/arm/mm/built-in.o(.text+0x2360): In function `do_translation_fault':
arch/arm/mm/fault.c:363: undefined reference to `cpu_tlb'
arch/arm/mm/built-in.o(.text+0x3c44): In function `free_pgd_slow':
arch/arm/mm/mm-armv.c:249: undefined reference to `cpu_tlb'
arch/arm/mm/built-in.o(.text+0x3de4): In function `setup_mm_for_reboot':
arch/arm/mm/mm-armv.c:590: undefined reference to `cpu_tlb'
arch/arm/mm/built-in.o(.init.text+0x1414): In function `paging_init':
arch/arm/mm/init.c:519: undefined reference to `cpu_tlb'
arch/arm/mm/built-in.o(.init.text+0x2734):arch/arm/mm/mm-armv.c:559: more undefined references to `cpu_tlb' follow
fs/built-in.o(.text+0xf2460): In function `xdr_decode_fattr':
fs/nfs/nfs2xdr.c:125: undefined reference to `ntohl'
fs/built-in.o(.text+0xf2480)s/nfs/nfs2xdr.c:126: undefined reference to `ntohl'
fs/built-in.o(.text+0xf24a0)s/nfs/nfs2xdr.c:127: undefined reference to `ntohl'
fs/built-in.o(.text+0xf24c0)s/nfs/nfs2xdr.c:128: undefined reference to `ntohl'
fs/built-in.o(.text+0xf24e0)s/nfs/nfs2xdr.c:129: undefined reference to `ntohl'
fs/built-in.o(.text+0xf2500)s/nfs/nfs2xdr.c:130: more undefined references to `ntohl' follow
fs/built-in.o(.text+0xf2958): In function `nfs_xdr_sattrargs':
fs/nfs/nfs2xdr.c:155: undefined reference to `htonl'
fs/built-in.o(.text+0xf29ac):fs/nfs/nfs2xdr.c:156: undefined reference to `htonl'
fs/built-in.o(.text+0xf2a00):fs/nfs/nfs2xdr.c:157: undefined reference to `htonl'
fs/built-in.o(.text+0xf2a54):fs/nfs/nfs2xdr.c:158: undefined reference to `htonl'
fs/built-in.o(.text+0xf2aa8):fs/nfs/nfs2xdr.c9: undefined reference to `htonl'
fs/built-in.o(.text+0xf2b04):fs/nfs/nfs2xdr.c:91: more undefined references to `htonl' follow
……

k0059 发表于 2010-5-12 18:35:26

http://linux.derkeiler.com/Maili ... 08-09/msg04441.html
Hi,

last time I check kernel build for x86 and arm with -O0, there was several issues.

First there some code that rely in function inline and code elimination, and cause usage of disable symbol at -O0

#ifdef CONFIG_FOO
int foo()
{
}
static inline int toto()
{
}
#else
static inline int toto()
{
return 0
}
#endif


if (toto())
foo();

This doesn't work even when using __always_inline (try to build attached undec.c at -O0).


Second, I saw problem with swab macro .
When using -O0, __OPTIMIZE__ is not defined, and constant initialisation of some code fails (I don't remeber exactly the case but removing the defined(__OPTIMIZE__) fix the issue).

Next for x86 there a driver with asm optimisation that fail to build because gcc fail to allocate register.

And finaly as Andi say there some code doing check if undefined symbol. For example slab index_of

In the end I build the kernel at -O instead of -O0.

Matthieu

PS : I am not sure __always_inline always work at -O0...


#if defined(__GNUC__) && defined(__OPTIMIZE__)
# define __swab16(x) \
(__builtin_constant_p((__u16)(x)) ? \
___constant_swab16((x)) : \
__fswab16((x)))
# define __swab32(x) \
(__builtin_constant_p((__u32)(x)) ? \
___constant_swab32((x)) : \
__fswab32((x)))
# define __swab64(x) \
(__builtin_constant_p((__u64)(x)) ? \
___constant_swab64((x)) : \
__fswab64((x)))
#else
# define __swab16(x) __fswab16(x)
# define __swab32(x) __fswab32(x)
# define __swab64(x) __fswab64(x)
#endif /* OPTIMIZE */


static __always_inline int index_of(const size_t size)
{
extern void __bad_size(void);

if (__builtin_constant_p(size)) {
int i = 0;

#define CACHE(x) \
if (size <=x) \
return i; \
else \
i++;
#include <linux/kmalloc_sizes.h>
#undef CACHE
__bad_size();
} else
__bad_size();
return 0;
}
static inline __attribute__((always_inline)) int foo()
{
return 0;
}

int main()
{
if (foo())
bar();
}

也就是说最少也要-O1优化编译,我也在搞这个问题
优化后的代码不太好用调试器调试

shazoo 发表于 2010-5-14 18:29:55

axd+system.map可以勉强调试。如果有vmlinux,好像加载后也可以调。不过得好机器才可以。加载爆慢无比。

主意源码路径,最好作出samba来,否则不好指定哦。

minux 发表于 2010-5-14 23:41:17

内核依赖某些函数的inline,所以-O0的时候至少还得指定-finline-small-functions

调试Linux,还是用gdb调试最方便…… 另外,不明白为啥有些人非要在Linux环境下编译,然后切换到在Windows底下调试……
既然是搞Linux,调试为啥不敢在Linux下面做(且不说比在Windows底下调试方便)?

hugeice 发表于 2010-5-15 10:08:02

回复【1楼】k0059
-----------------------------------------------------------------------

回复【3楼】minux啊啊?
-----------------------------------------------------------------------

谢谢,我当时逐个查看了gcc报告没有定义到那些函数,发现都有inline修饰,当时也想可能和inline有关,不过没想通原因,后来新电路板内核启动正常就没有再尝试调试了。

(后来发现原来的板子内核启动死机是板子PCB DDR2布线的问题,其实当初应该可以通过配置PLL2降低DDR2的工作频率来确定问题的所在。)
页: [1]
查看完整版本: 求助:如何用-O0优化级别编译Linux内核?