ILD

ELF:Segments
作者:Herbert Yuan 邮箱:yuanjp89@163.com
发布时间:2017-6-17 站点:Inside Linux Development

1 Segments

段并不是目标文件的新内容,段只是程序加载角度的内容块,一个段可以包含多个section,也可以包含头。段通过Program header table索引。

通常,可执行文件和共享库目标文件才具有段。

2 Program header table

Program header table是一个数组,每个成员描述了一个段。ELF头中的e_phoff存储了表在文件中的偏移。e_phentsize存储了表中一个条目的大小。e_phnum存储了有多个条目。Program header的结构体表示如下:

1
2
3
4
5
6
7
8
9
10
typedef struct elf32_phdr {
    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,段的物理地址,和操作系统相关。

p_filesz,段在文件中的大小,可能是0。

p_memsz,段加载到内存后的大小,可能是0。

p_flags,段相关的标识。

p_align,段在文件和内存中的对齐要求,因为p_vaddr可能并不是最后加载到内存的地址,所以p_align给出对齐的需求。

2.1 Segment type

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,program header没有被使用,其它字段没有意义。

PT_LOAD,可加载段,将文件p_offset处p_filesz大小的文件内容加载到内存,p_memsz可以比p_filesz大,多出的内容初始化为0。显而易见,这是为.bss section设计的。

PT_DYNAMIC,描述动态链接信息。

PT_INTERP,这个段包含一个'\0'结尾的字符串。这个字符串是动态加载器的路径。

PT_NOTE,包含辅助信息。

PT_SHLIB,保留。

PT_PHDR,指定Program header table本身的大小和位置,这个段不能出现多次,而且只有在Program header table是内存镜像的一部分时,才能出现,而且必须在任何可加载段前。

2.2 Note section

一些厂商或系统创建者,需要标记一些特殊的信息,Note section就是做这个用的。ELF标准没有规范note的内容,但是给出了note的格式。

namesz

descsz

type

name

desc

。。。

上述格式中,每个条目至少有4个字节,不足的填充0。

3 Special section names

对于可执行文件和共享目标文件,有下述特殊的section name,一部分在之前sections章节的已经描述了。

name

.bss

.comment

.data

.data1

.debug

.dynamic

.dynstr

.dynsym

.fini

.got

.hash

.init

.interp

.line

.note

.plt

.relname

.relaname

.rodata

.rodata1

.shstrtab

.strtab

.symtab

.text

新的section在后续相关文章描述。

4 示例

通过readelf,读取一个可执行文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
  INTERP         0x000154 0x08048154 0x08048154 0x00013 0x00013 R   0x1
      [Requesting program interpreter: /lib/ld-linux.so.2]
  LOAD           0x000000 0x08048000 0x08048000 0x00604 0x00604 R E 0x1000
  LOAD           0x000f08 0x08049f08 0x08049f08 0x0011c 0x00120 RW  0x1000
  DYNAMIC        0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW  0x4
  NOTE           0x000168 0x08048168 0x08048168 0x00044 0x00044 R   0x4
  GNU_EH_FRAME   0x0004e4 0x080484e4 0x080484e4 0x00034 0x00034 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R   0x1
 
 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     
   08     .init_array .fini_array .jcr .dynamic .got

可以发现,不同的段可以有重叠的区域,因为不同的段有不同的用途。段也只是各个section和header的集合。

Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.