[img]/upload/attachment/58875/d209d0c8-9704-325f-9933-bf7843dd86a8.jpg[/img]
可以看到链接器和加载器看待elf是完全不同的,链接器看到的是由区段头部表描述的一系列逻辑区段的集合(也就是说它忽略了程序头部表)。而加载器则是看成是由程序头部表描述的一系列的段的集合(忽略了区段头部表)。
elf它可以表示不同类型的二进制文件(由e_type来决定):
elf的头结构
区段头部表项:
程序头部表--紧跟在elf头下面,其实也就是可执行文件用到的,由于可执行文件需要将文件映射到内存,并运行,因此这里的头部增加了要被映射的段:
符号表结构:
可以看到链接器和加载器看待elf是完全不同的,链接器看到的是由区段头部表描述的一系列逻辑区段的集合(也就是说它忽略了程序头部表)。而加载器则是看成是由程序头部表描述的一系列的段的集合(忽略了区段头部表)。
elf它可以表示不同类型的二进制文件(由e_type来决定):
#define ET_NONE 0
#define ET_REL 1 //可重定位
#define ET_EXEC 2 //可执行
#define ET_DYN 3 //动态链接库
#define ET_CORE 4
#define ET_LOPROC 0xff00
#define ET_HIPROC 0xffff
elf的头结构
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT];//魔幻数
Elf32_Half e_type; //文件类型.
Elf32_Half e_machine; //机器类型,也就是架构
Elf32_Word e_version; //版本
Elf32_Addr e_entry; //入口地址(如果是可执行文件)
Elf32_Off e_phoff; //头表在程序中的相对位置
Elf32_Off e_shoff; //区段头部的位移
Elf32_Word e_flags; //体系结构相关的标志
Elf32_Half e_ehsize; //该elf的头部大小
Elf32_Half e_phentsize; //程序头部表项的大小
Elf32_Half e_phnum; //程序头部表项的个数
Elf32_Half e_shentsize; //区段头部表项的大小
Elf32_Half e_shnum; //区段头部表项的个数
Elf32_Half e_shstrndx; //区段序号
} Elf32_Ehdr;
区段头部表项:
typedef struct {
Elf32_Word sh_name; //名字
Elf32_Word sh_type; //类型
Elf32_Word sh_flags; //区段的一些属性
Elf32_Addr sh_addr; //Section virtual addr at execution
Elf32_Off sh_offset; //区段起始点在文件中的位置
Elf32_Word sh_size; //区段大小
Elf32_Word sh_link; //其他的区段号(比如链接了其他的elf文件)
Elf32_Word sh_info; //附加的一些区段信息
Elf32_Word sh_addralign; //对齐粒度
Elf32_Word sh_entsize; //
} Elf32_Shdr;
程序头部表--紧跟在elf头下面,其实也就是可执行文件用到的,由于可执行文件需要将文件映射到内存,并运行,因此这里的头部增加了要被映射的段:
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;
符号表结构:
typedef struct elf32_sym{
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;