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

2011年(1)

2010年(28)

2008年(15)

分类:

2010-03-08 13:28:04

3. 内核链接脚本 --- vmlinux_32.lds.S 3.1 Overview

2. 内核image整体布局

2显示了内核image的布局,其中深色部分位于内核的虚拟地址空间3G~4G,共有textdatanote三个segment,其中note segment又是包含在text segment中。每个segment包含多个section,后面我们会讲到这些section是如何生成的。在这之前,需要了解链接脚本用到的两个地址:虚拟地址(VMA)和加载地址(LMA)。这里虚拟地址和我们平常说的虚拟地址是一样的,即section[*]在目标文件加载后所在的虚拟地址。例如在一个可执行的ELF文件中,.text sectionVMA0x08048310,即.text section的基地址位于虚拟地址空间的0x08048310处。加载地址指section被加载到内存中的地址,对于应用程序来说它通常和VMA相同,但对于内核来说,LMA是指section被加载到的物理地址。例如内核.textVMA0xc1001000,则LMA0x01001000。很明显,这就是我们所熟知的内核虚拟地址 = 物理地址 + 0xC00000003G)的identify mapping关系。

[*]前面提到目标文件的加载是若干segment被加载到内存中的过程,这和section的加载并不冲突。实际上,当我们不指定segmentLMAVMA时,这个两个值取segment中第一个sectionLMAVMA。加载segment也就是将其包含的各个section加载到内存中的过程。

好了,下面我们来看看内核链接脚本是怎么干的。

  3.2 链接脚本的开始

除去一些文件包含和宏定义,内核链接脚本以下面内容开始:

 

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")

OUTPUT_ARCH(i386)

ENTRY(phys_startup_32)

jiffies = jiffies_64;

 

PHDRS {

       text PT_LOAD FLAGS(5);   /* R_E */

       data PT_LOAD FLAGS(7);   /* RWE */

       note PT_NOTE FLAGS(0);   /* ___ */

}

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")

OUTPUT_ARCH(i386)

ENTRY(phys_startup_32)

jiffies = jiffies_64;

 

PHDRS {

       text PT_LOAD FLAGS(5);   /* R_E */

       data PT_LOAD FLAGS(7);   /* RWE */

       note PT_NOTE FLAGS(0);   /* ___ */

}

OUTPUT_FORMATOUTPUT都是链接脚本的关键字,它们指定了目标文件的格式和所运行平台的架构,这些公式化的东西我们不关心它,具体内容详见参考文献1ENTRY指定了整个目标文件的入口点(或入口函数),这里phys_startup_32是个地址,从名字我们就可以看出它是startup_32()函数的物理地址,在后面会看到该地址是如何计算得到的。jiffies = jiffes_64的魔术与本文无关,感兴趣的朋友可以参见ULK36.2.1.2节。

下面进入正题。PHDRS关键字描述了3segmenttextdatanote,它们分别具有PT_LOADPT_NOTE类型,并指定了每个segment的属性。PT_LOAD类型表示该segment是从文件加载入内存的,在这个上下文中文件应该指最后生成的内核imageFLAG关键字指定segment的属性,如注释所示,text segment为可读可执行、data segment为可读可写可执行,note段留到后面再说。至此,PHDRS定义了内核image的大体框架,它包含两个最主要的segment —— textdata,并确定了它们的属性,后面的代码就是向两个segment填充section了。

链接脚本知识:

PHDRS关键字的完整格式如下:

PHDRS{  name type [ FILEHDR ] [ PHDRS ] [ AT ( address ) ]        [ FLAGS ( flags ) ] ;}

其中name表示segment的名字,它位于单独的名字空间,不会和后面的section name冲突。typesegment的类型,如上的PT_LOAD,详细列表参见参考文献1FILEHDRPHDRS指定是否要包含ELF文件头和ELF程序头。AT指定segment的加载地址,FLAGS指定segment的属性。

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