ELF二进制目标文件详解 (一)

2014-11-23 22:04:31 ? 作者: ? 浏览: 10

以下内容为<编程>>笔记

链接程序
找出所有引用的外部模块并链接起来,这些外部模块或函数库一般来自于开发者,操作系统和C运行库。

链接程序取出这些函数库,修订指针位置(重定位),并交叉引用模块中的符号解析,最终产生一个可执行模块。符号可以是全局的也可以是局部的。全局符号可以在模块内部定义,或由另一模块外部引用。

静态库是在链接时被找到并复制的,而动态库和共享库是在运行时才装载的,并让所有的进程共享。linux提供的系统调用dlopen(),dlsym(),dlclose(),用于加载/打开共享库,查找库中的符号,然后关闭共享库

ELF二进制目标文件
可执行ELF目标文件包括:ELF头,程序头表(用于加载的节),第1节,第2节。。。。节头表(可选)

1.ELF文件头

typedef struct elf32_hdr{ 
  unsigned char e_ident[EI_NIDENT]; //标识该文件是否为ELF文件  
  Elf32_Half    e_type;  //指定目标文件类型,例如可执行文件,重定位文件,共享的目标文件  
  Elf32_Half    e_machine;   //被编译文件所在系统的体系结构  
  Elf32_Word    e_version; //目标文件的版本  
  Elf32_Addr    e_entry;  /* Entry point */  //程序的起始地址  
  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_hdr{
  unsigned char e_ident[EI_NIDENT]; //标识该文件是否为ELF文件
  Elf32_Half    e_type;  //指定目标文件类型,例如可执行文件,重定位文件,共享的目标文件
  Elf32_Half    e_machine;   //被编译文件所在系统的体系结构
  Elf32_Word    e_version; //目标文件的版本
  Elf32_Addr    e_entry;  /* Entry point */  //程序的起始地址
  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;


2 节头表

typedef struct elf32_shdr { 
  Elf32_Word    sh_name;   //包含节名  
  Elf32_Word    sh_type;   //包含节的内容  
  Elf32_Word    sh_flags;  //各种属性的内容  
  Elf32_Addr    sh_addr;   //节在内存映像中的地址   
  Elf32_Off     sh_offset; //保存ELF文件中这一节中初始字节的偏移量  
  Elf32_Word    sh_size;   //包含节的大小  
  Elf32_Word    sh_link;   //表链接的索引  
  Elf32_Word    sh_info;   //包含附加信息  
  Elf32_Word    sh_addralign;  //包含地址对其的约束  
  Elf32_Word    sh_entsize;  //节中每项的大小  
} Elf32_Shdr; 

typedef struct elf32_shdr {
  Elf32_Word    sh_name;   //包含节名
  Elf32_Word    sh_type;   //包含节的内容
  Elf32_Word    sh_flags;  //各种属性的内容
  Elf32_Addr    sh_addr;   //节在内存映像中的地址
  Elf32_Off     sh_offset; //保存ELF文件中这一节中初始字节的偏移量
  Elf32_Word    sh_size;   //包含节的大小
  Elf32_Word    sh_link;   //表链接的索引
  Elf32_Word    sh_info;   //包含附加信息
  Elf32_Word    sh_addralign;  //包含地址对其的约束
  Elf32_Word    sh_entsize;  //节中每项的大小
} Elf32_Shdr;


3 非可执行ELF文件的节
bss 为初始化的数据
.data 已初始化的数据
.hash 符号散列表
.init 初始化代码
.symtab 符号表
.text 可执行的指令
.plt 过程链接表
.rodata 只读数据
.dynamic 动态链接信息
等等
4 程序头表

typedef struct elf64_phdr { 
  Elf64_Word p_type;    //描述该段的类型  
  Elf64_Word p_flags;   //以p_type而定  
  Elf64_Off p_offset;   //该段的开始相对于文件开始的偏移量  
  Elf64_Addr p_vaddr;   //段虚拟地址  
  Elf64_Addr p_paddr;   //段的虚拟地址    
  Elf64_Xword p_filesz; //文件映像中该段的字节数  
  Elf64_Xword p_memsz;  //内存映像中该段的字节数  
  Elf64_Xword p_align;  //描述要对齐的段在内存中如何对齐,该值是2的整数次幂         

typedef struct elf64_phdr {
  Elf64_Word p_type;    //描述该段的类型
  Elf64_Word p_flags;   //以p_type而定
  Elf64_Off p_offset;   //该段的开始相对于文件开始的偏移量
  Elf64_Addr p_vaddr;   //段虚拟地址
  Elf64_Addr p_paddr;   //段的虚拟地址 
  Elf64_Xword p_filesz; //文件映像中该段的字节数
  Elf64_Xword p_memsz;  //内存映像中该段的字节数
  Elf64_Xword p_align;  //描述要对齐的段在内存中如何对齐,该值是2的整数次幂        [cpp] view plaincopyprint } Elf64_Phdr; 

} Elf64_Phdr;


通过这些信息,系统函数exec()和链接程序

-->

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: