免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 949 | 回复: 0
打印 上一主题 下一主题

elf文件格式(2) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-03-07 13:49 |只看该作者 |倒序浏览

  ==================== Symbol Table 符号表=========================
一个object文件的符号表保存了一个程序在定位和重定位时需要的定义和引用的信息。一个符号表索引是相应的下标。0表项特指了该表的第一个入口,就象未定义的符号索引一样。初始入口的内容在该 section 的后续部分被指定。
                             Name       Value
                             ====       =====
                                   STN_UNDEF      0
一个符号表入口有如下的格式:
+ Figure 1-16: Symbol Table Entry
  typedef struct {
      Elf32_Word st_name;
      Elf32_Addr st_value;
      Elf32_Word st_size;
      unsigned char st_info;
      unsigned char st_other;
      Elf32_Half st_shndx;
  } Elf32_Sym;
* st_name
  该成员保存了进入该object文件的符号字符串表入口的索引(保留了符号名的表达字符)。如果该值不为 0 ,则它代表了给出符号名的字符串表索引。否则,该符号无名。注意:External C 符号和object文件的符号表有相同的名称。
* st_value
  该成员给出了相应的符号值。它可能是绝对值或地址等等(依赖于上下文);  细节如下所述。
* st_size
  许多符号和大小相关。比如,一个数据对象的大小是该对象所包含的字节数目。如果该符号的大小未知或没有大小则这个成员为 0 。
* st_info
  成员指出了符号的类型和相应的属性。相应的列表如下所示。下面的代码说明了如何操作该值。
    #define ELF32_ST_BIND(i) ((i)>>4)
    #define ELF32_ST_TYPE(i) ((i)&0xf)
    #define ELF32_ST_INFO(b, t) (((b)
* st_other
  该成员目前为 0 ,没有含义。
* st_shndx
  每一个符号表的入口都定义为和某些 section 相关;该成员保存了相关的section  头索引。就象 Figure 1-8 {*}和相关的文字所描述的那样,某些 section 索引指出了特殊的含义。一个符号的属性决定了可链接性能和行为。
+ Figure 1-17: Symbol Binding, ELF32_ST_BIND
  Name        Value
  ====        =====
  STB_LOCAL       0
  STB_GLOBAL      1
  STB_WEAK        2
  STB_LOPROC     13
  STB_HIPROC     15
* STB_LOCAL
  在包含了其定义的object文件之外的局部符号是不可见的。不同文件中的具有相同名称的局部符号并不相互妨碍。
* STB_GLOBAL
全局符号是对所有的object目标文件可见的。一个文件中的全局符号的定义可以满足另一个文件中对(该文件中)未定义的全局符号的引用。
* STB_WEAK
  弱符号相似于全局符号,但是他们定义的优先级比较低一些。
* STB_LOPROC through STB_HIPROC
  其所包含范围中的值由相应的处理器语义所保留。全局符号和弱符号的区别主要在两个方面。
* 当链接器链接几个可重定位的目标文件时,它不允许 STB_GLOBAL 符号的同名多重定义。另一方面,如果一个全局符号的定义存在则具有相同名称的弱符号名不会引起错误。链接器将认可全局符号的定义而忽略弱符号的定义。与此相似,如果有一个普通符号(比如,一个符号的 st_shndx 域包含 SHN_COMMON),则一个同名的弱符号不会引起错误。链接器同样认可普通符号的定义而忽略弱符号。
* 当链接器搜索档案库的时候,它选出包含了未定义的全局符号的存档成员。该成员的定义或者是全局的或者是一个弱符号。链接器不会为了解决一个未定义的弱符号选出存档成员。未定义的弱符号具有 0 值。在每一个符号表中,所有具有 STB_LOCAL 约束的符号优先于弱符号和全局符号。就象上面 "sections" 中描述的那样,一个符号表部分的 sh_info 头中的成员保留了第一个非局部符号的符号表索引。
符号的类型提供了一个为相关入口的普遍分类。
+ Figure 1-18: Symbol Types, ELF32_ST_TYPE
  Name         Value
  ====         =====
  STT_NOTYPE       0
  STT_OBJECT       1
  STT_FUNC         2
  STT_SECTION      3
  STT_FILE         4
  STT_LOPROC      13
  STT_HIPROC      15
* STT_NOTYPE
  该符号的类型没有指定。
* STT_OBJECT
  该符号和一个数据对象相关,比如一个变量、一个数组等。
* STT_FUNC
  该符号和一个函数或其他可执行代码相关。
* STT_SECTION
  该符号和一个 section 相关。这种类型的符号表入口主要是为了重定位,一般的  具有 STB_LOCAL 约束。
* STT_FILE
  按惯例而言,该符号给出了和目标文件相关的源文件名称。一个具有 STB_LOCAL约束的文件符号,其 section 索引为 SHN_ABS ,并且它优先于当前对应该文件的其他 STB_LOCAL 符号。
* STT_LOPROC through STT_HIPROC
  该范围中的值是为处理器语义保留的。
共享文件中的函数符号(具有 STT_FUNC 类型)有特殊的意义。当其他的目标文件从一个共享文件中引用一个函数时,链接器自动的为引用符号创建一个链接表。除了STT_FUNC 之外,共享的目标符号将不会自动的通过链接表引用。如果一个符号涉及到一个 section 的特定定位,则其 section 索引成员 st_shndx将保留一个到该 section 头的索引。当该 section 在重定位过程中不断移动一样,符号的值也相应变化,而该符号的引用在程序中指向同样的定位。某些特殊的 section 索引有其他的语义。
* SHN_ABS
  该符号有一个不会随重定位变化的绝对值。
* SHN_COMMON
  该符号标识了一个没有被分配的普通块。该符号的值给出了相应的系统参数,就象一个 section 的 sh_addralign 成员。也就是说,链接器将分配一个地址给该符号,地址的值是 st_value 的倍数。该符号的大小指出了需要的字节数。
* SHN_UNDEF
  该 section 表索引表明该符号是未定义的。当链接器将该目标文件和另一个定义该符号的文件相装配的时候,该文件内对该符号的引用将链接到当前实际的定义。如上所述,符号表的 0 索引(STN_UNDEF)是保留的,它包含了如下内容:
+ Figure 1-19: Symbol Table Entry: Index 0
  Name        Value    Note
  ====        =====    ====
  st_name       0      No name
  st_value      0      Zero value
  st_size       0      No size
  st_info       0      No type, local binding
  st_other      0
  st_shndx  SHN_UNDEF  No section
       Symbol Values(符号值)
符号表入口对于不同的目标文件而言对 st_value 成员有一些不同的解释。
* 在可重定位文件中, st_value 保存了 section 索引为 SHN_COMMON 符号的强制对齐值。
* 在可重定位文件中, st_value 保存了一个符号的 section 偏移。也就是说,st_value 是从 st_shndx 定义的 section 开头的偏移量。
* 在可执行的和可共享的目标文件中, st_value 保存了一个虚拟地址。为了使这些文件符号对于动态链接器更为有效,文件层面上的 section 偏移让位于内存层面上的虚拟地址( section 编号无关的)。尽管符号表值对于不同的目标文件有相似的含义,相应的程序还是可以有效地访问数据。
   ======= Relocation (重定位)==========================
重定位是连接符号引用和符号定义的过程。比如,当一个程序调用一个函数的时候,相关的调用必须在执行时把控制传送到正确的目标地址。换句话说,重定位文件应当包含有如何修改他们的 section 内容的信息,从而允许可执行文件或共享目标文件为一个进程的程序映像保存正确的信息。重定位入口就是这样的数据。
+ Figure 1-20: Relocation Entries
  typedef struct {
      Elf32_Addr r_offset;
      Elf32_Word r_info;
  } Elf32_Rel;
  typedef struct {
      Elf32_Addr r_offset;
      Elf32_Word r_info;
      Elf32_Sword r_addend;
  } Elf32_Rela;
* r_offset
  该成员给出了应用重定位行为的地址。对于一个重定位文件而言,该值是从该ection 开始处到受到重定位影响的存储单位的字节偏移量。对一个可执行文件或一个共享目标而言,该值是受到重定位影响的存储单位的虚拟地址。
* r_info
  该成员给出了具有受重定位影响因素的符号表索引和重定位应用的类型。比如, 一个调用指令的重定位入口应当包含被调用函数的符号索引。如果该索引是STN_UNDEF (未定义的符号索引),重定位将使用 0 作为该符号的值。重定位类型是和处理器相关的。当正文(text)引用到一个重定位入口的重定位类型或符号表索引,它表明相应的应用 ELF32_R_TYPE或 ELF32_R_SYM 于入口的 r_info成员。
    #define ELF32_R_SYM(i) ((i)>>8)
    #define ELF32_R_TYPE(i) ((unsigned char)(i))
    #define ELF32_R_INFO(s, t) ((s)
* r_addend
  该成员指定一个常量加数(用于计算将要存储于重定位域中的值)。如上所述,只有 Elf32_Rela 入口包含一个明确的加数。Elf32_Rel 类型的入口在可以修改的地址中存储一个隐含的加数。依赖于处理器结构,一种形式或其他形式也许是必须的或更为方便的。因此,特定机器的应用应当使用一种排他性的形式或依赖于上下文的另一种形式。
一个重定位 section 关联了两个其他的 section :一个符号表和一个可修改的 section 。该 section 头的成员 sh_info 和 sh_link (在上文中的 “ section ”部分中有描述)指示了这种关系。重定位入口中的成员 r_offset对于不同的目标文件有少许差异。
* 在可重定位文件中,r_offset 表示了一个 section 偏移。也就是说,重定位section自己描述了如何修改其他在文件中的其他section; 重定位偏移量指明了一个在第二个section中的存储器单元。
* 在可执行和共享的目标文件中,r_offset 表示一个虚拟地址。为了使得这些文件的重定位入口更为有用(对于动态链接器而言),该 section 偏移(文件)应当让位于一个虚拟地址(内存中的)。尽管为了允许相关的程序更为有效的访问而让 r_offset 的解释对于不同的目标文件有所不同,重定位类型的含义是相同的。
      Relocation Types(重定位类型)
重定位入口描述了怎样变更下面的指令和数据域(位数在表的两边角下)。
+ Figure 1-21: Relocatable Fields
    +---------------------------+
    |          word32           |
   31---------------------------0
* word32
  指定一个以任意字节对齐方式占用 4 字节的 32 位域。这些值使用与 32 位Intel体系相同的字节顺序。
                           3------2------1------0------+
      0x01020304    |  01  |  02  |  03  |  04  |
                          31------+------+------+------0
下面的计算假设正在将一个可重定位文件转换为一个可执行或共享的目标文件。从概念上来说,链接器合并一个或多个可重定位文件来组成输出。它首先决定怎样合并、定位输入文件,然后更新符号值,最后进行重定位。对于可执行文件和共享的目标文件而言,重定位过程是相似的并有相同的结果。下面的描述使用如下的约定符号。
* A
  表示用于计算可重定位的域值的加数。
* B
  表示了在执行过程中一个共享目标被加载到内存时的基地址。一般情况下,一个共享object文件使用的基虚地址为0,但是一个可执行地址就跟共享object文件不同了。
* G
  表示了在执行过程中重定位入口符号驻留在全局偏移表中的偏移。请参阅第二部分中的“ Global Offset Table (全局偏移表)”获得更多 的信息。
* GOT
  表示了全局偏移表的地址。请参阅第二部分中的“ Global Offset Table(全局偏移表)”获得更多的信息。
* L
  表示一个符号的过程链接表入口的位置( section 偏移或地址)。一个过程链接表入口重定位一个函数调用到正确的目的单元。链接器创建初始的链接表,而动态链接器在执行中修改入口。请参阅第二部分中的“ Procedure Linkage Table (过程链接表)”获得更多的信息
* P
  表示(section 偏移或地址)被重定位的存储单元位置(使用 r_offset 计算的)。
* S
  表示索引驻留在重定位入口处的符号值。一个重定位入口的 r_offset 值指定了受影响的存储单元的首字节的偏移或虚拟地址。重定位类型指定了哪一位(bit)将要改变,以及怎样计算它们的值。 SYSTEM V 体系中仅仅使用 Elf32_Rel 重定位入口,将要被重定位的域中保留了加数。在所有的情况下,加数和计算结果使用相同字节顺序。
+ Figure 1-22(表 1-22): Relocation Types(重定位类型)
  Name            Value  Field   Calculation
  ====            =====  =====   ===========
  R_386_NONE        0    none    none
  R_386_32     1    word32  S + A
  R_386_PC32     2    word32  S + A - P
  R_386_GOT32     3    word32  G + A - P
  R_386_PLT32     4    word32  L + A - P
  R_386_COPY     5    none    none
  R_386_GLOB_DAT    6    word32  S
  R_386_JMP_SLOT    7    word32  S
  R_386_RELATIVE    8    word32  B + A
  R_386_GOTOFF     9    word32  S + A - GOT
  R_386_GOTPC    10    word32  GOT + A - P
有的重定位类型有不同于简单计算的语义。
* R_386_GOT32
  这种重定位类型计算全局偏移表基地址到符号的全局偏移表入口之间的间隔。这样另外通知了 link editor 建立一个全局偏移表 。
* R_386_PLT32
  这种重定位类型计算符号的过程链接表入口地址,并另外通知链接器建立一个过程链接表。
* R_386_COPY
  链接器创建该重定位类型用于动态链接。它的偏移成员涉及一个可写段中的一个位置。符号表索引指定一个可能存在于当前 object file 或在一个shared object中的符号。在执行过程中,动态链接器把和 shared object 符号相关的数据拷贝到该偏移所指定的位置。
* R_386_GLOB_DAT
  这种重定位类型用于设置一个全局偏移表入口为指定符号的地址。该特定的重定位类型允许你决定符号和全局偏移表入口之间的一致性。
* R_386_JMP_SLOT {*}
  链接器创建该重定位类型用于动态链接。其偏移成员给出了一个过程链接表入口的位置。动态链接器修改该过程链接表入口以便向特定的符号地址传递控制。[参阅第二部分中的 "Procedure Linkage Table(过程链接表)"]
* R_386_RELATIVE
  链接器创建该重定位类型用于动态链接。其偏移成员给出了包含表达相关地址值的一个 shared object 中的位置。动态链接器计算相应的虚拟地址(把该shared object 装载地址和相对地址相加)。该类型的重定位入口必须为符号表索引指定为 0 。
* R_386_GOTOFF
  这种重定位类型计算符号值和全局偏移表地址之间的不同。另外还通知链接器建立全局偏移表(GOT)。
* R_386_GOTPC
  这种重定位类型类似于 R_386_PC32 ,不同的是它在计算中使用全局偏移表。这种重定位中引用的符号通常是 _GLOBAL_OFFSET_TABLE_ ,该符号通知了链接器建立全局偏移表(GOT)。
   ________________________________________________________________
  2. PROGRAM LOADING AND DYNAMIC LINKING
                   程序装入和动态链接
   ________________________________________________________________
   ================ Introduction(介绍) =========================
第二部分描述了 object file 信息和创建运行程序的系统行为。其中部分信息适合所有的系统,其他信息是和特定处理器相关的。可执行和共享的 object file 静态的描绘了程序。为了执行这样的程序,系统用这些文件创建动态的程序表现,或进程映像。一个进程映像有用于保存其代码、数据、堆栈等等的段。这个部分的主要章节讨论如下的内容。
* 程序头(Program header)。该章节补充第一部分,描述和程序运行相关的object file 结构。即文件中主要的数据结构、程序头表、定位段映像,也含了为该程序创建内存映像所需要的信息。
* 载入程序(Program loading)。在给定一个 object file 时,系统为让它运行必须将它载入内存。
* 动态链接(Dynamic linking)。在载入了程序之后,系统必须通过解决组成该进程的 object file之间的符号引用问题来完成进程映像的过程。
注意:指定了处理器范围的 ELF 常量是有命名约定的。比如,DT_ , PT_ ,用于特定处理器扩展名,组合了处理器的名称(如 DT_M32_SPECIAL )。没有使用这种约定但是预先存在的处理器扩展名是允许的。
         Pre-existing Extensions
                       (预先存在的扩展名)
         =======================
         DT_JMP_REL
   ================= Program Header(程序头) ======================
一个可执行的或共享的 object file 的程序头表是一个结构数组,每一个结构描述一个段或其他系统准备执行该程序所需要的信息。一个 object file段包含一个或多个部分(就象下面的“段目录”所描述的那样)。程序头仅仅对于可执行或共享的 object file 有意义。一个文件使用 ELF 头的 e_phentsize和 e_phnum 成员来指定其拥有的程序头大小。[参阅 第一部分中的 "ELF 头"]
+ Figure 2-1: Program Header
  typedef struct {
      Elf32_Word p_type;
      Elf32_Off  p_offset;
      Elf32_Addr p_vaddr;
      Elf32_Addr p_paddr;
      Elf32_Word p_filesz;
      Elf32_Word p_memsz;
      Elf32_Word p_flags;
      Elf32_Word p_align;
  } Elf32_Phdr;
* p_type
  该成员指出了这个数组的元素描述了什么类型的段,或怎样解释该数组元素的信息。  类型值和含义如下所述。
* p_offset
  该成员给出了该段的驻留位置相对于文件开始处的偏移。
* p_vaddr
  该成员给出了该段在内存中的首字节地址。
* p_paddr
  在物理地址定位有关联的系统中,该成员是为该段的物理地址而保留的。由于 System V 忽略了应用程序的物理地址定位,该成员对于可执行文件和共享的object 而言是未指定内容的。
* p_filesz
  该成员给出了文件映像中该段的字节数;它可能是 0 。
* p_memsz
  该成员给出了内存映像中该段的字节数;它可能是 0 。
* p_flags
  该成员给出了和该段相关的标志。定义的标志值如下所述。
* p_align
  就象在后面“载入程序”部分中所说的那样,可载入的进程段必须有合适的p_vaddr 、 p_offset 值,取页面大小的模。该成员给出了该段在内存和文件中排列值。 0 和 1 表示不需要排列。否则, p_align 必须为正的 2 的幂, 并且 p_vaddr 应当等于 p_offset 模 p_align 。某些入口描述了进程段;其他的则提供补充信息并且无益于进程映像。已经定义的入口可以以任何顺序出现,除非是下面明确声明的。后面是段类型值;其他的值保留以便将来用于其他用途。
+ Figure 2-2: Segment Types, p_type
  Name             Value
  ====             =====
  PT_NULL              0
  PT_LOAD              1
  PT_DYNAMIC           2
  PT_INTERP            3
  PT_NOTE              4
  PT_SHLIB             5
  PT_PHDR              6
  PT_LOPROC   0x70000000
  PT_HIPROC   0x7fffffff
* PT_NULL
  该数组元素未使用;其他的成员值是未定义的。这种类型让程序头表忽略入口。
* PT_LOAD
  该数组元素指定一个可载入的段,由 p_filesz 和 p_memsz 描述。文件中字节被映射到内存段中。如果该段的内存大小( p_memsz )比文件大小( p_filesz )要大,则多出的字节将象段初始化区域那样保持为 0 。文件的大小不会比内存大小值大。在程序头表中,可载入段入口是以 p_vaddr 的升序排列的。
* PT_DYNAMIC
  该数组元素指定动态链接信息。参阅 后面的“动态部分”以获得更多信息。
* PT_INTERP
  该数组元素指定一个 null-terminated 路径名的位置和大小(作为解释程序)。这种段类型仅仅对可执行文件有意义(尽管它可能发生在一个共享 object 上); 它在一个文件中只能出现一次。如果它出现,它必须先于任何一个可载入段入口。参阅 后面的“程序解释器”(Program Interpreter)以获得更多的信息。
* PT_NOTE
  该数组元素指定辅助信息的位置和大小。参阅 后面的“注意部分”以获得细节。
* PT_SHLIB
  该段类型保留且具有未指定的语义。具有一个这种类型数组元素的程序并不遵守 ABI 。
* PT_PHDR
  该数组元素(如果出现),指定了程序头表本身的位置和大小(包括在文件中和在该程序的内存映像中)。更进一步来说,它仅仅在该程序头表是程序内存映像的一部分时才有效。如果它出现,它必须先于任何可载入段入口。参阅 后面的“程序解释器”(Program Interpreter)以获得更多的信息。
* PT_LOPROC through PT_HIPROC
  该范围中的值保留用于特定处理器的语义。注意:除非在别处的特殊要求,所有的程序头的段类型是可选的。也就是说,一个文件的程序头表也许仅仅包含和其内容相关的元素。
     Base Address(基地址)
可执行和共享的 object file 有一个基地址,该基地址是与程序的 object file在内存中映像相关的最低虚拟地址。基地址的用途之一是在动态链接过程中重定位该程序的内存映像。一个可执行的 object file 或 一个共享的 object file 的基地址是在执行的时候从三个值计算而来的:内存载入地址、页面大小的最大值 和 程序可载入段的最低虚拟地址。就象在“程序载入”中所描述的那样,程序头中的虚拟地址也许和程序的内存映像中实际的虚拟地址并不相同。为了计算基地址,必须确定与 PT_LOAD 段 p_vaddr 的最小值相关的内存地址。获得基地址的方法是将内存地址截去最大页面大小的最接近的整数倍。由于依赖载入内存中的文件类型,该内存地址和 p_vaddr 值可能匹配也可能不匹配。
就象在第一部分中 "Section" 中描述的那样, .bss section 具有 SHT_NOBITS的类型。尽管在文件中不占用空间,它在段的内存映像中起作用。通常,没有初始化的数据驻留在段尾,因此使得在相关的程序头元素中的 p_memsz 比 p_filesz 大。
     Note Section(注解部分)
有的时候供应商或系统设计者需要用特定的信息标记一个object file 以便其他程序检查其兼容的一致性,等等此类。 SHT_NOTE类型的 section 和 PT_NOTE 类型的程序头元素能够被用于此目的。 section和程序头中的注解信息包含了任意数目的入口,每一个入口的格式都是对应于特定处理器格式的 4-字节数组。下面的标签有助于解释注释信息的组织形式,但是这些标签不是规格说明的一部分。
+ Figure 2-3: Note Information
  namesz
  descsz
  type
  name ...
  desc ...
* namesz and name
  名字中 namesz 的第一个字节包含了一个 null-terminated 字符表达了该入口的拥有者或始发者。没有正式的机制来避免名字冲突。从惯例来说,供应商使用他们自己的名称,比如 "XYZ Computer Company" ,作为标志。如果没有提供名字, namesz 值为 0 。 如果有必要,确定描述信息4-字节对齐。 这样的填充信息并不包含在namesz 中。
* descsz and desc
  desc 中 descsz 的首字节包含了注解描述符。ABI 不会在一个描述符内容中放入任何系统参数。如果没有描述符, descsz 将为 0 。  如果有必要,确定 描述信息4-字节对齐。 这样的填充信息并不包含在descsz中。
* type
  该 word 给出了描述符的解释。每一个创造着(originator) 控制着自己的类型;对于单单一个类型值的多种解释是可能存在的。因此,一个程序必须辨认出该名字和其类型以便理解一个描述符。这个时候的类型必须是非负的。ABI 没有定义描述符的含义。
为了举例说明,下面的解释段包含两个入口。
+ Figure 2-4: Example Note Segment
           +0   +1   +2   +3
          -------------------
  namesz           7
  descsz           0           No descriptor
    type           1
    name   X    Y    Z    spc
           C    o    \0   pad
  namesz           7
  descsz           8
    type           3
    name   X    Y    Z    spc
           C    o    \0   pad
    desc         word0
                 word1
注意:系统保留的注解信息没有名字 (namesz==0) ,有一个零长度的名字 (name[0]==‘\0‘) 现在还没有类型为其定义。所有其他的名字必须至少有一个非空的字符。
注意:注解信息是可选的。注解信息的出现并不影响一个程序的 ABI 一致性,前提是该信息不影响程序的执行行为。否则,该程序将不遵循 ABI 并将出现未定义的行为。
   ================ Program Loading(程序载入) =====================
当创建或增加一个进程映像的时候,系统在理论上将拷贝一个文件的段到一个虚拟的内存段。系统什么时候实际地读文件依赖于程序的执行行为,系统载入等等。一个进程仅仅在执行时需要引用逻辑页面的时候才需要一个物理页面,实际上进程通常会留下许多未引用的页面。因此推迟物理上的读取常常可以避免这些情况,改良系统的特性。为了在实践中达到这种效果,可执行的和共享的 object file 必须具有
合适于页面大小取模值的文件偏移和虚拟地址这样条件的段映像。虚拟地址和文件偏移在 SYSTEM V 结构的段中是模 4KB(0x1000) 或大的 2 的幂。由于 4KB 是最大的页面大小,因此无论物理页面大小是多少,文件必须去适合页面。
+ Figure 2-5: Executable File
           File Offset   File                  Virtual Address
           ===========   ====                  ===============
                     0   ELF header
                             Program header table
                         Other information
                 0x100   Text segment          0x8048100
                         ...
                         0x2be00 bytes         0x8073eff
               0x2bf00   Data segment          0x8074f00
                         ...
                         0x4e00 bytes          0x8079cff
               0x30d00   Other information
                         ...
+ Figure 2-6: Program Header Segments(程序头段)
  Member    Text  Data
  ======    ====         ====
  p_type    PT_LOAD      PT_LOAD
  p_offset  0x100  0x2bf00
  p_vaddr   0x8048100  0x8074f00
  p_paddr   unspecified  unspecified
  p_filesz  0x2be00  0x4e00
  p_memsz   0x2be00  0x5e24
  p_flags   PF_R+PF_X    PF_R+PF_W+PF_X
  p_align   0x1000  0x1000
尽管示例中的文件偏移和虚拟地址在文本和数据两方面都适合模 4KB ,但是还有4 个文件页面混合了代码和数据(依赖于页面大小和文件系统块的大小)。
* 第一个文本页面包含了 ELF 头、程序头以及其他信息。
* 最后的文本页包含了一个数据开始的拷贝。
* 第一个数据页面有一个文本结束的拷贝。
* 最后的数据页面也许会包含与正在运行的进程无关的文件信息。理论上,系统强制内存中段的区别;段地址被调整为适应每一个逻辑页面在地址空间中有一个简单的准许集合。在上面的示例中,包含文本结束和数据开始的文件区域将被映射两次:在一个虚拟地址上为文本而另一个虚拟地址上为数据。数据段的结束处需要对未初始化的数据进行特殊处理(系统定义的以 0 值开始)。因此如果一个文件包含信息的最后一个数据页面不在逻辑内存页面中,则无关的数据应当被置为 0 (这里不是指未知的可执行文件的内容)。在其他三个页面中 "Impurities" 理论上并不是进程映像的一部分;系统是否擦掉它们是未指定的。
下面程序的内存映像假设了 4KB 的页面。
+ Figure 2-7: Process Image Segments(进程映像段)
  Virtual Address  Contents            Segment
  ===============  ========            =======
        0x8048000  Header padding      Text
                   0x100 bytes
        0x8048100  Text segment
                   ...
                   0x2be00 bytes
        0x8073f00  Data padding
                   0x100 bytes
        0x8074000  Text padding        Data
                   0xf00 bytes
        0x8074f00  Data segment
                   ...
                   0x4e00 bytes
        0x8079d00  Uninitialized data
                   0x1024 zero bytes
        0x807ad24  Page padding
                   0x2dc zero bytes
可执行文件和共享文件在段载入方面有所不同。典型地,可执行文件段包含了绝对代码。为了让进程正确执行,这些段必须驻留在建立可执行文件的虚拟地址处。因此系统使用不变的 p_vaddr 作为虚拟地址。另一方面,共享文件段包含与位置无关的代码。这让不同进程的相应段虚拟地址各不相同,且不影响执行。虽然系统为各个进程选择虚拟地址,它还要维护各个段的相对位置。因为位置无关的代码在段间使用相对定址,故而内存中的虚拟地址的不同必须符合文件中虚拟地址的不同。下表给出了几个进程可能的共享对象虚拟地址的分配,演示了不变的相对定位。该表同时演示了基地址的计算。地址的分配,演示了不变的相对定位。该表同时演示了基地址的计算。
+ Figure 2-8: Example Shared Object Segment Addresses
  Sourc             Text        Data  Base Address
  =====             ====        ====  ============
  File             0x200     0x2a400           0x0
  Process 1   0x80000200  0x8002a400    0x80000000
  Process 2   0x80081200  0x800ab400    0x80081000
  Process 3   0x900c0200  0x900ea400    0x900c0000
  Process 4   0x900c6200  0x900f0400    0x900c6000


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15169/showart_82130.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP