Chinaunix首页 | 论坛 | 博客
  • 博客访问: 376856
  • 博文数量: 44
  • 博客积分: 2060
  • 博客等级: 上尉
  • 技术积分: 528
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-17 20:50
文章分类
文章存档

2011年(1)

2010年(28)

2008年(15)

分类:

2010-03-08 13:42:28

3.3.2 Note Segment

前面提到内核image分为三个segment,其中就有note segment,它是包含在text segment中的。NOTE segment被用于不同的vendorELF文件中添加一些标识,让运行这些二进制代码的系统确定能否为该ELF提供其所需要的系统调用接口。它对我们了解内核用处不大,详细内容参见参考文献2

NOTES :text :note

上面代码中,NOTE是一个宏,展开的格式和构建其它section的格式一样,这里”:text:note”表示把生成的section即加入text segment又加入note segment。从objdump的内容可以看到后者包含在前者之中,如下:

    LOAD off    0x00001000 vaddr 0xc1000000 paddr 0x01000000 align 2**12

         filesz 0x004de000 memsz 0x004de000 flags r-x

NOTE off    0x0037b844 vaddr 0xc137a844 paddr 0x0137a844 align 2**2

         filesz 0x00000024 memsz 0x00000024 flags ---

    LOAD off    0x00001000 vaddr 0xc1000000 paddr 0x01000000 align 2**12

         filesz 0x004de000 memsz 0x004de000 flags r-x

NOTE off    0x0037b844 vaddr 0xc137a844 paddr 0x0137a844 align 2**2

         filesz 0x00000024 memsz 0x00000024 flags ---


3.3.3 .rodata section
的构造

前面提到,只读数据被放到了text segment,链接脚本中的RODATA宏完成了这项工作。RODATA创建了大量不同名称的section,它们有些是内置的,有些则是自定义的。创建方式并无特别之处,有了前面的知识,你可以轻易的看懂它们。这里要说的是关于自定义section的第二个例子——内核符号表。

读过LDD的朋友都知道,在module中导出符号给内核其它部分应该使用__ksymtab,我们也经常在内核中看到类似的代码,如:

EXPORT_SYMBOL(boot_cpu_data);

但,内核是怎么做的?符号表如何被创建?如果你看了/path_to_your_kernel_src/include/linux/module.hEXPORT_SYMBOL的定义,再配合自定义section的知识,很快就能明白内核只是创建了一个名为__ksymtab的自定义section,当调用EXPROT_SYMBOL宏时会生成一个struct kernel_symbol变量记录下函数/数据的名称和地址,最后将这个变量存入__ksymtab section中。RODATA宏的如下代码:

       /* Kernel symbol table: Normal symbols */                \

       __ksymtab         : AT(ADDR(__ksymtab) - LOAD_OFFSET) {        \

              VMLINUX_SYMBOL(__start___ksymtab) = .;                 \

              *(__ksymtab)                                     \

              VMLINUX_SYMBOL(__stop___ksymtab) = .;                 \

       }                                                      \

                                                   \

             

将输入文件中的__kysmtab section合并生成新的__ksymtab section,这就是内核最终的导出符号表,同样,__start___ksymtab__stop___ksymtab记录下了表的起始地址和结束地址。如此一来,动态加载module时内核如何将module中调用的函数替换成相应的地址就不难理解了吧。

链接脚本知识:

或许你已经注意到,上述创建__ksymtab section的代码中,并没有在最后加上:text标明将该section放到text segment。实际上这是链接脚本的一个简化,当没有为section指定segment时,以上一个明确指定的segment为准。例如之前最后一次明确指定segment__ex_table section指定了text segment,则其后没有指定segmentsection也被放到了text segment,直到下一次明确指定segmentsection出现为止。

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