曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 8461|回复: 0
打印 上一主题 下一主题

[Kernel] vmlinux.o

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2011-7-23 11:59:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Makefile 对应内核版本:2.6.35.13

vmlinux.o 是生成 vmlinux 的依赖之一,在链接出 vmlinux 之前会先链接出 vmlinux.o 。

vmlinux.o 定义在顶层 Makefile 中:
[code=Makefile]vmlinux.o: $(modpost-init) $(vmlinux-main) FORCE
        $(call if_changed_rule,vmlinux-modpost)[/mw_shl_code]

上面 $(modpost-init) 定义在顶层 Makefile 中:
[code=Makefile]modpost-init := $(filter-out init/built-in.o, $(vmlinux-init))[/mw_shl_code]
它只是从 $(vmlinux-init) 中去掉 init/built-in.o 文件。比如在默认的配置下,$(vmlinux-init) 指代的生成文件为:
arch/x86/kernel/head_32.o arch/x86/kernel/head32.o arch/x86/kernel/head.o arch/x86/kernel/init_task.o init/built-in.o
则 $(modpost-init) 就是:
arch/x86/kernel/head_32.o arch/x86/kernel/head32.o arch/x86/kernel/head.o arch/x86/kernel/init_task.o

在 vmlinux.o 底下的 if_changed_rule 函数和 if_changed 函数类似,它会使构建系统调用 rule_vmlinux-modpost --- 该变量也定义在顶层 Makefile 中:
[code=Makefile]define rule_vmlinux-modpost
        :
        +$(call cmd,vmlinux-modpost)
        $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost $@
        $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd
endef[/mw_shl_code]
一开始就使用 $(call cmd,vmlinux-modpost) 即为 cmd_vmlinux-modpost ,它也定义在顶层 Makefile 中:
[code=Makefile]cmd_vmlinux-modpost = $(LD) $(LDFLAGS) -r -o $@                          \
         $(vmlinux-init) --start-group $(vmlinux-main) --end-group             \
         $(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^)[/mw_shl_code]
上面 $(LD) 即为 ld 链接命令。
$(LDFLAGS) 指代 -m elf_i386 (编译内核在 x86 平台,如果是交叉编译,则 -m 选项后会有相应更改)。
ld 的 --start-group 和 --end-group 之间放置目标文件列表,ld 会对列表中列出的目标文件进行重复的搜索,目的是查看各个文件之间再也没有未决的互相引用,当然这么做是相当耗时的,除非是非做不可。自然的,对于内核而言,这非做不可。
接着 $(filter-out $(vmlinux-init) $(vmlinux-main) FORCE ,$^) 是从所有的依赖中去掉伪目标 FORCE,$(vmlinux-init) 和 $(vmlinux-main) 这几个依赖后看看还有什么别的依赖。默认配置情况下没有,所以这里为空。

在链接出 vmlinux.o 目标后,接着使用 scripts/Makefile.modpost 这个文件来处理 vmlinux.o 目标。跟到  scripts/Makefile.modpost 中看到:
[code=Makefile]vmlinux.o: FORCE
        $(call cmd,kernel-mod)[/mw_shl_code]
所以执行的是 cmd_kernel-mod 中的语句,这些语句也在 scripts/Makefile.modpost 中:
[code=Makefile]quiet_cmd_kernel-mod = MODPOST $@
      cmd_kernel-mod = $(modpost) $@
[/mw_shl_code]
其中  $(modpost) 的定义为:
[code=Makefile]
# Step 2), invoke modpost
#  Includes step 3,4
modpost = scripts/mod/modpost                    \
$(if $(CONFIG_MODVERSIONS),-m)                  \
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,)       \
$(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile)   \
$(if $(KBUILD_EXTMOD),-I $(modulesymfile))      \
$(if $(KBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(KBUILD_EXTRA_SYMBOLS))) \
$(if $(KBUILD_EXTMOD),-o $(modulesymfile))      \
$(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S)      \
$(if $(KBUILD_EXTMOD)$(KBUILD_MODPOST_WARN),-w) \
$(if $(cross_build),-c)[/mw_shl_code]
由上可见,这里实际使用的是  scripts/mod/ 目录下的 modpost 用来解析 vmlinux.o 对象文件,它检查目标中的 sections 是否 mis match,然后还将基本内核导出的所有符号都记录到文件 Module.symvers 中去。详情可以看 Makefile.modpost 中的注释以及参考 scripts/mod/modpost.c 中的代码。

在上面的诸多判断中,在默认的内核配置下,CONFIG_MODVERSION,CONFIG_MODULE_SRCVERSION,KBUILD_EXTMOD,KBUILD_EXTRA_SYMBOLS,CONFIG_DEBUG_SECTION_MISMATCH 以及 KBUILD_MODPOST_WARN 这些变量都为空,所以最后综合起来得到的命令为:
scripts/mod/modpost -o /home/beyes/Downloads/linux-2.6.35.13/Module.symvers -S vmlinux.o

上面调用 modpost 处理完后,再返回到主 Makefile 中,使用  $(Q)echo 'cmd_$@ := $(cmd_vmlinux-modpost)' > $(dot-target).cmd 将编译 vmlinux.o 的命令写入到.vmlinux.o.cmd 文件中保存起来,以便下次再编译内核时可以进行新旧命令的比较。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 06:47 , Processed in 0.077372 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表