C/C++——elf文件分析

导读:本篇文章讲解 C/C++——elf文件分析,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

C/C++代码经过编译后会生成elf文件,里面包含了平台、代码、数据,调试信息等。

编译过程参考:https://blog.csdn.net/qq_39815222/article/details/108526580

1. elf文件格式

C/C++——elf文件分析

  • ELF Header
    链接后的elf文件有三种类型,分别是可重定位文件rel(包含适合于与其他目标文件链接来创建可执行文件,或者共享目标文件的代码和数据);可执行文件exec(包含适合于执行的的一个程序,此文件规定了exec()如何创建一个程序的进程映像);共享目标文件dyn(包含可在两种上下文链接的代码和数据,如linux中已.so结尾的文件)

简写为Ehdr,  包含以下信息:
e_ident[**]                   //elf标识
e_type;                       //elf类型(上述三种类型)
e_ machine;               //目标文件体系类型,即运行架构,如x86、riscv、arm等
e_version;                  //目标文件版本
e_entry;                      //elf入口地址
e_ phoff;                     //程序头部偏移
e_shoff;                      //节区头部偏移
e_flags;                     
e_ehsize;                  //ELF格式头部大小
e_phentsize;             //程序头部表项大小
e_phnum;                  //程序头表项个数,即segment数
e_shentsize;              //节区头部表项大小
e_shnum;                  //节区表项个数,即section数
e_shstrndx;

  • Program Header Table

简写为Phdr,包含以下信息:
p_type;                    //segment类型
p_offset;                  //segment在文件中的偏移
p_vaddr;                 //segment虚地址
p_paddr;                 //物理地址
p_filesz;                  //文件中segment字节数
p_memsz;              //内存中segment字节数
p_flags;
p_align;

  • segment
    内容包括text segment,data segment等,segment包含多个section,
  1. .text
    已编译程序的指令代码段
  2. .rodata
    ro代表read only,表示只读数据
  3. .data
    已初始化的C程序全局变量和静态局部变量。C程序普通变量在运行是被保存在堆栈中,既不在.data中,也不在.bss中,此外,如果变量初始化值为0,也可能会放到bss段。
  4. .bss
    未初始化的C程序变量和静态局部变量。目标文件格式区分初始化和未初始化变量是为了空间效率,在ELF文件中.bss段不占据实际的存储器空间,仅仅是一个占位符。
  5. .debug
    调试符号表,调试器用此段的信息帮助调试

简称sym,包含以下信息:
st_name;        
st_value;
st_size;
st_info;
st_other;
st_shndx;

  • section header table

简称Shdr,包含信息:
sh_name;                 //节区名称,字符串表索引值
sh_type;                   //节区种类,如rel*
sh_flags;                 //
sh_addr;                  /地址
sh_offset;                //输出节区第一个字节偏移
sh_size;                   //节区大小
sh_link;                    //给出字节头部表索引链接
sh_info;                   //给出节区附加信息
sh_addralign;          //对齐约束
sh_entsize;             //给出对于某些有固定项目的大小,如符号表

2. elf的内存加载

实际上,编译后的elf文件的加载在不同平台上的情况是不一样的。
C/C++——elf文件分析

  • 对于含有文件系统和动态加载功能操作系统的CPU

elf文件会通过某种方式(FTP或者网络文件系统)被写入到OS的文件系统。

首先先说明一下OS的启动。对该类型CPU来说,其操作系统kernel已经存储在硬盘中了,上电后bootloader会对CPU进行初始化,随后就会将操作系统镜像加载到SRAM特定的地址,随后CPU整个的控制权全部移交给kernel。

OS接管系统后,会进一步初始化并挂载文件系统,此时kernel便可加载文件系统中的elf文件。kernel首先将该文件加载到CPU中的SRAM,完成相应的初始化后将控制权交给应用程序。

  • 对于简单操作系统和无操作系统的CPU

该类型的CPU由于不能提供加载功能,因此在生成elf文件后需要使用二进制处理工具objcopy将elf文件转换成bin文件,然后通过相应的烧写工具将该文件写入flash中。

若有操作系统,则需要将目标程序和OS并在一起编译和链接,目标程序只作为操作系统的一个内部函数调用。此情况下,操作系统的启动一般不需要单独的bootloader去加载,在上电完成初始化后就直接跳转到操作系统的代码。

  1. 对于静态链接的内存加载:
    对于以静态链接形式编译的程序,由于其已经是一个完整的不依赖于任何其他东西的可执行程序,可以直接被执行。
  2. 对于动态链接的内存加载工作步骤:
    loader程序将elf文件读入内存,然后启动链接器程序根据elf文件头的说明,将其所需要的其他程序段找到读入内存并装配在一起(相似段融合,然后重新编排符号表和重定位表,并根据重定位表来做重定位)。装配完后返回loader程序继续执行,然后loader直接跳转到装配完成的程序中的入口地址处执行。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82504.html

(1)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!