一、概述
ELF是一种用于二进制文件、可执行文件、目标代码、共享库、和核心转储的标准文件格式。也是linux下的主要可执行文件格式
ELF文件由四部分组成,分别是ELF头(ELF header)、程序头表(program header table)、节(section)和节头表(section table header)
ELF header格式代码如下:
#define EI_NIDENT
typedef struct elf32_hdr{
unsigned char
Elf32_Half
Elf32_Half
Elf32_Word
Elf32_Addr
Elf32_Off
Elf32_Off
Elf32_Word
Elf32_Half
Elf32_Half
Elf32_Half
Elf32_Half
Elf32_Half
Elf32_Half
} Elf32_Ehdr;
大小是52B (32位;64位则为64B)
代码项含义:
e_type; /* 文件类型*/
e_machine; /* 表示运行该程序需要的体系结构 */
e_version; /* 表示文件的版本*/
e_entry; /* 程序的入口地址 */
e_phoff; /* 程序头表在文件中的偏移量 */
e_shoff; /* 节头表在文件中的偏移量 */
e_flags; /* 此项为 0*/
e_ehsize; /* ELF头字节大小 */
e_phentsize; /* 程序头表每一个条目的大小 */
e_phnum; /* 程序头表有多少个条目 */
e_shentsize; /* 节头表每一个条目的大小 */
e_shnum; /* 节头表有多少个条目 */
e_shstrndx; /* 包含节名称的字符串是第几个节 */
Program header(描述的是一个段在文件中的位置、大小、以及它被放进内存后所在的位置和大小)
Section header格式代码如下;
tyypedef struct {
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Addr
Elf32_Off
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Word
} Elf32_Shdr;
代码项含义:
sh_name;/*section名字
sh_type;/类别
sh_flags;/section在进程执行时的特性
sh_addr;/开始的虚拟地址
sh_offset;/在文件中的偏移
sh_size;
sh_link;
sh_info;
sh_addralign;
sh_entsize;
ELF文件中常见的段.
.text 保存程序的指令序列
.data&rodata 保存初始化了的全局静态变量和局部静态变量
.bss存放未初始化的全局变量和局部静态变量
二、实践步骤
1、编写一个elf.c程序:
#include <stdio.h>
int f(int x){
return 0;
}
int main(void){
static int a=7;
char str[]="变量为:";
printf("%s%d",str,f(a)+1);
return f(a)+1;
}
2、实践代码
1.gcc -c elf.c -o elf.o(生成.o文件)
file elf.o
2.ls -l elf.o(查看.o文件大小字节)
3.hexdump -x elf.o(用16进制的数字来显示.o的内容)
4.objdump -x elf.o(显示.o中各个段和符号表的相关信息)
readelf -a elf.o(查看各个段信息)
二、实践内容分析
第一行:实际表示内容为7f45 4c46 0201 0100 0000 0000 0000 0000;前四个字节是一个魔数(magic number),表示这是一个ELF对象,接下来的一个字节02表示是一个64位对象(32位的对象是01),再接下来的一个字节01表示采用小端法表示,再接下来的一个字节01表示文件头版本,剩下的默认都设置为0。
第二行:e_type(两个字节)值为0x0001,表示是一个重定位文件。
e_machine(两个字节)值为0x003e,表示是X86-64的处理器体系结构。
e_version(四个字节)值为0x00000001,表示是当前版本。
e_entry(八个字节)值为0x0000000000000000,表示没有入口点
第三行:e_phoff(八个字节)值为0x0000000000000000,表示没有程序头表。
e_shoff(八个字节)值为0x0000000000000420,表示段表的偏移地址。
第四行:e_flags(四个字节)值为0x00000000,表示未知处理器特定标志
e_ehsize(两个字节)值为0x0040,表示elf文件头大小;
e_phentsize(两个字节)值均为0x0000,因为重定位文件没有程序头表。
e_phnum(两个字节)的值为0x0000,因为重定位文件没有程序头表。
e_ehentsize(两个字节)值为0x0040表示段头大小为64个字节(由这里知道section header table里面每个header的大小)。
e_shnum(两个字节)值为0x000d,表示段表入口有13个(由这里知道段表有13个段)。
e_shstrndx(两个字节)值为0x000a,表示段名串表的在段表中的索引号(由这里知道.shstrtab段(符号表)的信息在段表的索引号是10)。
查看文件头:
程序头表:
符号表: