程序的本质之二ELF文件的文件头、ctionheader和programheader

更新时间:2023-06-29 19:40:30 阅读: 评论:0

程序的本质之⼆ELF⽂件的⽂件头、ctionheader和
programheader
操作系统:CentOS Linux relea 7.7.1908
内核版本:3.10.0-1062.1.1.el7.x86_64
运⾏平台:x86_64
本⽂根据/usr/include/elf.h⽂件和⽂中所述的tanglinux来分析可执⾏⽂件的⽂件头、ction header和program header的构成。
本⽂只介绍32位的可执⾏⽂件,64位的可执⾏⽂件与32位的构成基本⼀致,除了地址和偏移量的长度不同以外。Elf32_Half、
Elf32_Section和Elf32_Versym等类型都是16位的⽆符号整数;Elf32_Addr和Elf32_Off都是32位的⽆符号整数;Elf32_Word和
Elf32_Sword分别为32位的⽆符号和有符号整数(带S);Elf32_Xword和Elf32_Sxword分别为64位的⽆符号和有符号整数(带S)。
⼀、ELF⽂件头
Linux可执⾏⽂件采⽤ELF(Executable and Linkable Format)格式来存储数据。每个ELF⽂件都以以下的数据来开头:
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half    e_type;        /* Object file type */
Elf32_Half    e_machine;      /* Architecture */
Elf32_Word    e_version;      /* Object file version */
Elf32_Addr    e_entry;        /* Entry point virtual address */
Elf32_Off e_phoff;        /* Program header table file offt */
Elf32_Off e_shoff;        /* Section header table file offt */
Elf32_Word    e_flags;        /* Processor-specific flags */
Elf32_Half    e_ehsize;      /* ELF header size in bytes */
Elf32_Half    e_phentsize;    /* Program header table entry size */
Elf32_Half    e_phnum;        /* Program header table entry count */
Elf32_Half    e_shentsize;    /* Section header table entry size */
Elf32_Half    e_shnum;        /* Section header table entry count */
Elf32_Half    e_shstrndx;    /* Section header string table index */
} Elf32_Ehdr;
从中可知,ELF⽂件中的主要内容为program header和ction header,两者的⼤⼩、在ELF⽂件中的位置和数量都能通过⽂件头来获取。⽽后⼜可以通过program header来获得每个gment的属性,通过ction header来获得每个ction的属性。
ELF⽂件头的说明如下表所⽰:
其中,由于每个ction header的⼤⼩是固定的,⽽它们的名称属性不可能⼀样长,所以需要⼀个专门的string ction来保存它们的名称属性,⽽⽤来描述这个string ction的ction header在ction表中的位置就由e_shstrndx来确认(e_shoff+ e_shentsize*
e_shstrndx),以达到快速查询的⽬的。
如果e_phnum的值为PN_XNUM(即0xffff),则表⽰program header的数量超过了它所能存储的最⼤值,因此它的值另外保存在索引号为SHN_UNDEF(即0)的ction的Elf32_Shdr. sh_info的位置。
法师ELF⽂件头的标志位总共有16个字节的⼤⼩,⽬前只⽤到9个字节,剩余字节的值都为0。它们的说明如下表所⽰:
风范其中,2's complement的意思就是补码,⽽1's complement的意思为反码。
通过执⾏readelf命令可获得可执⾏⽂件tanglinux的⽂件头信息,如下所⽰:
$ readelf -h tanglinux
ELF Header:
Magic:  7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class:                            ELF32
Data:                              2's complement, little endian
Version:                          1 (current)
OS/ABI:                            UNIX - System V
ABI Version:                      0
Type:                              EXEC (Executable file)
Machine:                          Intel 80386
Version:                          0x1
Entry point address:              0x80482e0
Start of program headers:          52 (bytes into file)
Start of ction headers:          5944 (bytes into file)
Flags:                            0x0
Size of this header:              52 (bytes)
Size of program headers:          32 (bytes)
Number of program headers:        9
Size of ction headers:          40 (bytes)
Number of ction headers:        31
Section header string table index: 30
从以上所输出的⽂件头信息可知可执⾏⽂件tanglinux中数据的⼤概分布,如下图所⽰:
⽂件的总⼤⼩为7184个字节。
⼆、ELF⽂件中的ction header
ction header⽤来描述每个ction的特性,如⼤⼩、类型、名称等等,它们都使⽤以下的数据结构来表⽰:
typedef struct
青蛙妈妈{
Elf32_Word    sh_name;        /* Section name (string tbl index) */
Elf32_Word    sh_type;        /* Section type */
Elf32_Word    sh_flags;      /* Section flags */
Elf32_Addr    sh_addr;        /* Section virtual addr at execution */
Elf32_Off  sh_offt;      /* Section file offt */
Elf32_Word    sh_size;        /* Section size in bytes */
Elf32_Word    sh_link;        /* Link to another ction */
Elf32_Word    sh_info;        /* Additional ction information */
Elf32_Word    sh_addralign;  /* Section alignment */
Elf32_Word    sh_entsize;    /* Entry size if ction holds table */
} Elf32_Shdr;
在ELF⽂件中,每个ction header都有⼀个索引号,从1开始,依次递增。不过ction header表的开头必须定义⼀个类型为
SHT_NULL的表项,它的索引号为SHN_UNDEF(也就是0)。由于ction header使⽤相同的数据结构来定义,并且它们的⼤⼩相同,所以所有的ction header依次存储在⼀起看起来就是⼀个表,因此可以叫它ction header表。类似的,所有program header看起来也是⼀个表。
1、sh_name表⽰ction的名称。由于每个ction名称的长度不相同,并且为了节约空间,于是就将所有ction的名称都存放在⼀个特定的名叫.shstrtab的ction(⽂件头信息中的Elf32_Ehdr. e_shstrndx就是⽤来快速查找它)中,所以这⾥的sh_name的值指的就是在这个特定ction中的偏移量,通过它可以获得⼀个字符串,也就是所需要的ction名。0值表⽰⽆名称,⼀般⽤于类型为SHT_NULL 的ction中。
2、sh_type表⽰ction的类型。它可能的取值有以下这些:
#define SHT_NULL      0    /* Section header table entry unud */
#define SHT_PROGBITS      1    /* Program data */
#define SHT_SYMTAB    2    /* Symbol table */
#define SHT_STRTAB    3    /* String table */
#define SHT_RELA      4    /* Relocation entries with addends */
#define SHT_HASH      5    /* Symbol hash table */
#define SHT_DYNAMIC  6    /* Dynamic linking information */
#define SHT_NOTE      7    /* Notes */
#define SHT_NOBITS    8    /* Program space with no data (bss) */
立秋的谚语#define SHT_REL      9    /* Relocation entries, no addends */
#define SHT_SHLIB    10        /* Rerved */
#define SHT_DYNSYM    11        /* Dynamic linker symbol table */
#define SHT_INIT_ARRAY    14        /* Array of constructors */
#define SHT_FINI_ARRAY    15        /* Array of destructors */
#define SHT_PREINIT_ARRAY 16        /* Array of pre-constructors */
#define SHT_GROUP    17        /* Section group */
#define SHT_SYMTAB_SHNDX  18        /* Extended ction indeces */
#define SHT_NUM      19        /* Number of defined types.  */
#define SHT_LOOS      0x60000000    /* Start OS-specific.  */
#define SHT_GNU_ATTRIBUTES 0x6ffffff5  /* Object attributes.  */
#define SHT_GNU_HASH      0x6ffffff6    /* GNU-style hash table.  */
#define SHT_GNU_LIBLIST  0x6ffffff7    /* Prelink library list */
#define SHT_CHECKSUM      0x6ffffff8    /* Checksum for DSO content.  */
阴跷脉草原旅游#define SHT_LOSUNW    0x6ffffffa    /* Sun-specific low bound.  */
农村住宅围墙
#define SHT_SUNW_move    0x6ffffffa
#define SHT_SUNW_COMDAT  0x6ffffffb
#define SHT_SUNW_syminfo  0x6ffffffc
#define SHT_GNU_verdef    0x6ffffffd    /* Version definition ction.  */
#define SHT_GNU_verneed  0x6ffffffe    /* Version needs ction.  */
#define SHT_GNU_versym    0x6fffffff    /* Version symbol table.  */
天歌唱起来原唱#define SHT_HISUNW    0x6fffffff    /* Sun-specific high bound.  */
#define SHT_HIOS      0x6fffffff    /* End OS-specific type */
#define SHT_LOPROC    0x70000000    /* Start of processor-specific */
#define SHT_HIPROC    0x7fffffff    /* End of processor-specific */
#define SHT_LOUSER    0x80000000    /* Start of application-specific */
#define SHT_HIUSER    0x8fffffff    /* End of application-specific */
其中,每个ELF⽂件中都有⼀个SHT_NULL类型的ction,它只有ction header,没有相应的ction数据,ction header中的数据都为0,没有意义。
SHT_PROGBITS类型的ction中的内容为程序数据,如代码、全局变量等。例如,.interp ction⽤于保存动态链接器的绝对地址,如/lib/ld-linux.so.2;.comment ction⽤于保存版本控制信息,如GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-
39);.eh_frame_hdr和.eh_frame ction⽤于保存异常处理信息,.eh_frame_hdr是对.eh_frame的补充,通过执⾏$ readelf -wf tanglinux命令可以查看.eh_frame ction中的内容。
NOBITS类型⼀般⽤于名叫.bss的ction,该ction也只有ction header,没有实际的内容,不占⽤可执⾏⽂件的空间。
SHT_STRTAB类型的ction⽤于保存字符串,它的格式如下例所⽰:
通过图中的索引Index就可以获得从Index开始到空字符为⽌的⼀段字符串。例如若Index取值为1则可获得字符串“name.”。
.shstrtab就是⼀个典型的SHT_STRTAB类型的ction,执⾏以下命令就可以输出该段中的内容,如下所⽰:

本文发布于:2023-06-29 19:40:30,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/89/1060533.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   保存   名称   属性   获得   没有   内容
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图