Chinaunix首页 | 论坛 | 博客
  • 博客访问: 254833
  • 博文数量: 49
  • 博客积分: 1684
  • 博客等级: 上尉
  • 技术积分: 458
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-09 22:45
文章分类

全部博文(49)

文章存档

2023年(1)

2021年(2)

2018年(2)

2017年(7)

2016年(2)

2015年(6)

2014年(13)

2013年(7)

2012年(7)

2011年(1)

2010年(1)

分类: LINUX

2013-03-17 00:49:53

已有各种工具可以帮助我们调试内核,比如、kgdb、qemu等,但比较麻烦的是gdb经常给我一个“value
optimized
out”的提示,而且执行的路径与gdb的显示也不对应,最近我在利用UML调试ext3文件系统的逻辑时就为此而感到非常麻烦(2.6.30.8的内核):








1
2
3
4
5

Breakpoint 1, journal_invalidatepage (journal=0x6c4bd800, page=0x61918b28, offset=0) at fs/jbd/transaction.c:2036
2036    {
(gdb) p bh
$2 =
(gdb)

这应该是因为Linux内核打开gcc的-O2选项优化导致,于是我尝试修改内核Makefile文件(/usr/src/uml/linux-2.6.30.8/Makefile):








1
2
3
4
5

ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS   += -Os
else
KBUILD_CFLAGS   += -O2
endif

改为这样(CONFIG_CC_OPTIMIZE_FOR_SIZE可以通过内核选项:General setup —> [ ] Optimize for
size,进行开启/关闭,这里不管该选项而也就统一改了):








1
2
3
4
5

ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS   += -O0
else
KBUILD_CFLAGS   += -O0
endif

执行编译,gcc给了我一个华丽的错误:








1
2
3
4
5
6
7
8
9
10
11
12
13
14

[root@lenky linux-2.6.30.8]# make ARCH=um -B V=1
...
mm/built-in.o: In function `index_of':
/usr/src/uml/linux-2.6.30.8/mm/slab.c:341: undefined reference to `__bad_size'
/usr/src/uml/linux-2.6.30.8/mm/slab.c:341: undefined reference to `__bad_size'
/usr/src/uml/linux-2.6.30.8/mm/slab.c:341: undefined reference to `__bad_size'
/usr/src/uml/linux-2.6.30.8/mm/slab.c:341: undefined reference to `__bad_size'
/usr/src/uml/linux-2.6.30.8/mm/slab.c:341: undefined reference to `__bad_size'
mm/built-in.o:/usr/src/uml/linux-2.6.30.8/mm/slab.c:341: more undefined references to `__bad_size' follow
collect2: ld returned 1 exit status
  KSYM    .tmp_kallsyms1.S
nm: '.tmp_vmlinux1': No such file
No valid symbol.
make: *** [.tmp_kallsyms1.S] Error 1

根据上面的提示信息,我尝试把文件slab.c的编译选项调为-O2,即编辑mm/Makefile文件,在最后加上如下一行:








1
2
3
4
5
6
7

[root@lenky linux-2.6.30.8]# vi mm/Makefile
[root@lenky linux-2.6.30.8]# tail -n 5 mm/Makefile
endif
obj-$(CONFIG_QUICKLIST) += quicklist.o
obj-$(CONFIG_CGROUP_MEM_RES_CTLR) += memcontrol.o page_cgroup.o
CFLAGS_slab.o = -O2

格式是:
CFLAGS_对应源文件[要去除通常意义上扩展名].o = gcc选项
所以上面加的是:
CFLAGS_slab.o =
-O2


重新编译:








1

[root@lenky linux-2.6.30.8]# make ARCH=um -B V=1

选项-B:以强制所有内核源文件全部重新编译(因为我前面编译过一次了,为了保险起见,就让目标文件全部重新生成吧)
选项V=1:显示详细的编译信息,而不再是简单的“CC
init/main.o”。


编译出来的可执行程序linux比-O2的情况还小几M,一启动UML没多久,果然奔溃。


看来内核里有大量的底层代码在书写时只兼容了-O2选项,所以如果以-O0的形式强制编译会导致出错,这即便不在编译时报错,也有极大可能会在实际执行时候出错,完全关闭所有内核源文件的的风险太大。


退而求次,我是为了调试journal_invalidatepage()函数,那么可以仅把对应源文件transaction.c的优化选项关闭即可,这个源文件的实现在比较高的层次,关闭优化选项应该不会出错。


编辑文件fs/jbd/Makefile,再其最后加上一行:
CFLAGS_transaction.o = -O0


重新编译(之前的其它改动需回滚)后启动UML,一切OK。


试试最开始的示例,用gdb绑定到UML主进程,调试函数journal_invalidatepage(),打印变量bh:








1
2
3
4
5
6
7
8
9

Breakpoint 1, journal_invalidatepage (journal=0x6c06e800, page=0x61502e30, offset=0) at fs/jbd/transaction.c:2038
2038        unsigned int curr_off = 0;
(gdb) p bh
$1 = (struct buffer_head *) 0x6bd5f0c8
(gdb) p *bh
$2 = {b_state = 3211305, b_this_page = 0x6bd5f268, b_page = 0x61501fc0, b_blocknr = 263, b_size = 1024, b_data = 0x6a648c00 "",
  b_bdev = 0x6bc02380, b_end_io = 0x600aa760 , b_private = 0x6bdc46d8, b_assoc_buffers = {
    next = 0x6bd5f110, prev = 0x6bd5f110}, b_assoc_map = 0x0, b_count = {counter = 2}}
(gdb)

嗯,效果不错。


另外Google到由teawater提供了对应的补丁对整个内核进行关闭-O2优化,有没有问题不知道,我暂没有测试:

阅读(1767) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~