ELF文件格式

2023-11-18

在介绍ELF格式之前,先简单说明一下可执行文件的生成流程:1)编写C源文件,或汇编源文件;2)准备共享库格式的目标文件(shared object file),如数学库、标准库;2)用编译器(compiler)将C编译成可重定位格式的目标文件(relocatable object file),用汇编器(assembler)将汇编源文件编译成可重定位格式的目标文件;3)用连接器(linker)将第二步的共享个库文件和第三步生成的目标文件链接生成可执行文件(executable file)。

(也就是说,内存中程序存在的状态就是ELF格式,当自己编写某个程序,定义指针*p,则p+4的地址为p的地址加4,其实已经在编译时确定了p+4的大小,所以打印出来的地址是+4的,不出错,我yazhouren09的理解)

ELF(excutable and linking format)是一种可执行可链接格式的二进制文件,它可以用来表示relocatable file、executable file或者shared object file,这三者都是目标文件(object file)。所谓“可执行”指可以被调入内存供CPU直接运行;“可链接”指多个ELF格式的目标文件可以被链接在一起形成一个可执行文件。下图左边是可链接格式的ELF文件格式,右边是可执行格式的ELF文件格式。

无论是linking view还是execution view的ELF文件,他们都包含一个ELF Header,它包含文件的基本信息。ELF自定义了一些类型,并强制规定了他们所占的字节个数,以实现跨平台,如Elf32_Half占2字节、Elf32_Word占4字节、Elf32_Off占4字节等。


 1 typedef struct
 2 {
 3 unsigned char     e_ident[EI_NIDENT];     /* Magic number and other info */
 4 Elf32_Half        e_type;                  /*目标文件类型 */
 5 Elf32_Half        e_machine;               /*Architecture */
 6 Elf32_Word       e_version;               /* Object file version */
 7 Elf32_Addr       e_entry;                  /*入口地址 */
 8 Elf32_Off        e_phoff;                  /* Program header table文件偏移 */
 9 Elf32_Off        e_shoff;                  /* Section header table 文件偏移 */
10 Elf32_Word      e_flags;                  /* Processor-specific flags */
11 Elf32_Half       e_ehsize;                 /* ELF header 大小 */
12 Elf32_Half       e_phentsize;              /*每个Program header大小 */
13 Elf32_Half       e_phnum;                /*一共多少个Program header */
14 Elf32_Half       e_shentsize;             /* 每个Section header大小 */
15 Elf32_Half       e_shnum;               /*一共多少个 Section header */
16 Elf32_Half     e_shstrndx;     /*Section的字符表在section header table的索引值 */
17 } Elf32_Ehdr;
18
复制代码
e_ident[EI_NIDENT]是一个有16个字节的数组,e_ident[0]=0x7f,e_ident[1]=”E”,e_ident[2]=”L”, e_ident[3]=”F”, e_ident[4]指示ELFCLASS(0:ELFCLASSNONE;1:ELFCLASS32;2:ELFCLASS64),e_ident[5]指示程序中的数据格式(0:无效;1:小端;2:大端),e_ident[6]指示版本固定为0x1,e_ident[7]到e_ident[14]固定为0,e_ident[15]固定为16用于指示e_ident[]数组有16个元素。e_type指示该ELF文件的类型,占2字节,可以为ET_NONE(0, No file type)/ ET_REL(1, Relocatable file)/ ET_EXEC(2, Executable file)/ ET_DYN(3, Shared object file)/ ET_CORE(4, Core file)/ ET_LOPROC(0xff00, Processor-specific)/ ET_HIPROC(0xffff, Processor-specific),常见的是ET_EXEC、ET_DYN、ET_REL。e_machine定义CPU的指令集架构,ELF标准中定义的有EM_NONE(0)/ EM_M32(1)/ EM_SPARC(2)/ EM_386(3)/ EM_68K(4)/ EM_88K(5)/ EM_860(6)/EM_MIPS(7),其它的值保留,有用户使用,比如EM_OR32=0x8472。e_version定义该ELF文件的版本号。e_entry定义程序的启动地址,也即CPU启动后读取的第一条指令所在的地址。e_phoff定义代表Program header table的数据结构在文件中的以字节为单位的偏移量,为0表示没有Program header table。e_shoff定义代表Section header table数据结构在文件中的以字节为单位的偏移量,为0表示没有Section header table。e_flags定义了和CPU相关的一些参数,不同的CPU对e_flags的定义是不一样的。e_ehsize定义ELF header这个数据结构的以字节为单位的实际大小,之所以出现这个参数,是因为各个平台上ELF自定义类型所表示的字节数不同。一个Program header table包含多个entry即多个Program header,每个entry的占用的文件字节数相同,e_phentsize定义了每个entry的大小,e_phnum定义当前Program header table中entry的个数。一个Section header table包含多个entry即多个Section header,每个entry的占用的文件字节数相同,e_shentsize定义了每个entry的大小,e_shnum定义当前Section header table中entry的个数。在Section header table中有一个特殊的entry,它定义了Section header table中各个entry的名字,e_shstrndx用于指示这个特殊的entry在Section header table中的索引,即它在第几个entry,这个特殊的entry称为section name string table。
Code
复制代码

前面已经提到,Section header table有多个entry,其实每个entry都是一个Elf32_Shdr类型数据结构,用这个数据结构可以找到每个Section在文件中的位置,e_shentsize=sizeof(Elf32_Shdr),e_shnum=numof(Elf32_Shdr)。sh_name是一个字符串数组的索引,它指示当前Section header所描述的这个Section的名字在Section name string table中的位置。sh_type指示当前Section header的类型,SHT_NULL(0,该Section header所指示的section无效,不占用文件空间)/ SHT_PROGBITS(1,该Section header所指示的section包含程序指令)/ SHT_SYMTAB(2,该Section header所指示的section包含重定位符号表)/ SHT_STRTAB(3,该Section header所指示的section包含字符表)/ SHT_RELA(4,重定位相关,用于链接过程)/ SHT_HASH(5,重定位相关,用于链接过程)/ SHT_DYNAMIC(6,用于链接过程)/ SHT_NOTE(7,信息说明)/ SHT_NOBITS(8,,该Section header所指示的section不占用文件字节,除此之外和SHT_PROGBITS含义相同) /SHT_REL(9,重定位相关)/ SHT_SHLIB(10,保留类型)/ SHT_DYNSYM(11,重定位相关)/ SHT_LOPROC(0x70000000)- SHT_HIPROC(0x7fffffff)(这一范围的类型值跟CPU相关)/ SHT_LOUSER(0x80000000)- SHT_HIUSER(0xffffffff)(这一范围的类型值保留给应用程序)。sh_flags指示当前Section header所对应的section的属性,WRITE(0x1,当前Section header所对应的section包含可写的数据)/ALLOC(0x2,当前Section header所对应的section在程序执行时占用实际的存储空间)/EXECINSTR(0x4,当前Section header所对应的section包含可执行的指令)/MASKPROC(0xf0000000,保留)。sh_addr指示当前Section header所对应的section在内存中起始地址。sh_offset指示当前Section header所对应的section在文件中以字节为单位的偏移量。sh_size指示当前Section header所对应的section在文件中占用的字节数。sh_link和sh_info供链接器使用。sh_addralign指示对sh_addr的对其要求。有一些特殊的section,它内部仍然包含多个entry,每个entry大小相同,如symbol table,sh_entsize用于指示这个特殊的section中每个entry的大小。

Code
复制代码

上表列出了一些常见的section。.bss中,包含未初始化的全局数据变量,这些变量不占用ELF文件的空间(SHT_NOBITS),但占用实际内存空间(SHF_ALLOC),在程序运行启动时由OS负责初始化为0。.comment包含版本控制信息。.data和.data1包含已经初始化的全局数据变量,这些变量占用ELF文件空间,也占用实际内存空间。.fini包含主函数退出时执行的指令。.init包含主函数执行前所执行的指令。.rodata和.rodata1包含只读数据。.shstrtab包含section header string table。.text包含程序指令。

typedef struct
{
Elf32_Word     p_type;      /* Segment type */
Elf32_Off       p_offset;      /* Segment offset in file */
Elf32_Addr    p_vaddr;      /* Segment virtual address in memory*/
Elf32_Addr     p_paddr;      /* Segment physical address */
Elf32_Word     p_filesz;      /* Segment size in file */
Elf32_Word     p_memsz;     /* Segment size in memory */
Elf32_Word     p_flags;       /* Segment flags */
Elf32_Word     p_align;      /* Segment alignment */
} Elf32_Phdr;
复制代码
 

前面已经提到,Program header table有多个entry,其实每个entry都是一个Elf32_Phdr类型数据结构,用这个数据结构可以找到每个Segment在文件中的位置,e_phentsize=sizeof(Elf32_Phdr),e_phnum=numof(Elf32_Phdr),每个Segment包含若干个section,只有对executable file和shared object file才能存在Program header。p_type指示当前Program header所指的Segment的类型,PT_NULL(0,指示无效的segment)/ PT_LOAD(1,指示当前Program header所指的Segment须加载到内存中执行)/ PT_DYNAMIC(2)/ PT_INTERP(3)/ PT_NOTE(4)/ PT_SHLIB(5)/ PT_PHDR(6)/PT_LOPROC(0x70000000)/PT_HIPROC(0x7fffffff)。p_offset指示Program header所指的Segment在文件中偏移量。p_vaddr指示Program header所指的Segment在内存中的虚拟地址。p_vaddr指示Program header所指的Segment在内存中的物理地址,一般可忽略。p_filesz指示Program header所指的Segment在文件中的大小。p_memsz指示Program header所指的Segment在内存中的大小,一般地,p_memsz>=p_filesz,对p_filesz不足的内存区域填0。

来源:http://www.cnblogs.com/brianhxh/archive/2009/07/04/1517020.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ELF文件格式 的相关文章

随机推荐

  • 会议通知

    全国高校Python数据分析与实训课程 高级研修班 通 知 各高校教务处 各相关院系负责人 依据 教育部高等学校教学指导委员会章程 规定 教育部高等学校教学指导委员会的任务之一是 组织师资培训 沟通信息 交流教学建设和教学改革经验 宣传推广
  • 2022 Java面试题

    Java面向对象有哪些特征 如何应用 面向对象编程是利用类和对象编程的一种思想 万物可归类 类是对于世界事物的高度抽象 不同的事物之间有不同的关系 一个类自身与外界的封装关系 一个父类和子类的继承关系 一个类和多个类的多态关系 万物皆对象
  • 基于MATLAB GUI的LSB语音信号数字水印

    基于MATLAB GUI的LSB语音信号数字水印 数字水印是一种在数字媒体中嵌入信息的技术 它可以用于版权保护 身份验证以及数据完整性验证等应用 在本文中 我们将介绍如何使用MATLAB GUI和最低有效位 Least Significan
  • Vue2.0知识点

    Vue2 0指令 v text指令 内容渲染指令 它会覆盖元素内部原有的内容 语法 插值表达式 专门用来解决v text会覆盖默认文本内容的问题 v text和插值表达式只能渲染纯文本内容 插值表达式不能用到属性节点 v html指令 可以
  • FFmpeg H264增加SEI

    先看使用场景 https blog csdn net lsheevyfg article details 80951415 https www jianshu com p 4d9120dfcd69 参考文章 https blog csdn
  • 【Python基础】Jupyter Notebook最常用的五大配置技巧

    说到Jupyter Notebook 以下简称Jupyter 想必很多人都不陌生 这是一款神奇的web应用 权且可以把它当作python超级笔记本 当然它还支持R Julia Scala Js等几十种语言 在Jupyter上 可以使用pyt
  • Spring Security OAuth2.0(四)-----OAuth2+JWT

    传统的通过 session 来记录用户认证信息的方式我们可以理解为这是一种有状态登录 而 JWT 则代表了一种无状态登录 无状态登录天然的具备单点登录能力 1 无状态登录 1 1 什么是有状态 有状态服务 即服务端需要记录每次会话的客户端信
  • Python中__str__的用法

    str 和 repr 如果要把一个类的实例变成 str 就需要实现特殊方法 str 不使用 str print打印出来是个对象 使用了就把对象变成字符串 class Person object def init self name gend
  • 蓝桥杯模块练习6-AD

    main c include
  • ag-grid Column API(机器翻译)

    Column API 一些API方法采用colKey类型为的列关键字 名为 Column string 这意味着您可以传递一个Column对象 通过调用其他方法之一接收到的对象 也可以传递Column ID 即string 列ID是列定义的
  • 【毕业设计】深度学习卫星遥感图像检测与识别系统(目标检测)

    文章目录 0 前言 1 课题背景 2 实现效果 3 Yolov5算法 4 数据处理和训练 5 最后 0 前言 Hi 大家好 这里是丹成学长的毕设系列文章 对毕设有任何疑问都可以问学长哦 这两年开始 各个学校对毕设的要求越来越高 难度也越来越
  • 远程控制,从个人便捷走向企业安全

    根据风险基础安全 Risk Based Security 的数据显示 2020年全球数据泄漏达到360亿条 创历史新高 对比传统的网络安全威胁 数据安全威胁更加多样化 80 的安全风险来自于内部人员或合作伙伴 威胁形式也更集中在账号体系薄弱
  • mybatis中association和collection的column传入多个参数问题

    mybatis中association和collection的column传入多个参数值 项目中在使用association和collection实现一对一和一对多关系时需要对关系中结果集进行筛选 如果使用懒加载模式 即联合使用select
  • mysql mariadb不能启动原因_centOS7 (64) MariaDB无法启动 跪求解决方法

    在CentOS7中mysql被 MariaDB所代替 幸得 贵在坚持 提点 顺利下载 MariaDB等相关软件但是安装完毕后 mariadb还是无法正常启动 root localhost service mariadb start Redi
  • mysql怎么替换部分字符串

    mysql替换部分字符串的方法 1 使用REPLACE 函数 语法 REPLACE 字符串 查找值 替换值 2 使用INSERT 函数 语法 INSERT 字符串 替换开始位置 要替换的字符数 替换值 mysql替换部分字符串 1 使用RE
  • 多租户mysql架构_团队开发框架实战—多租户架构

    1 对多租户的理解 多租户定义 多租户技术或称多重租赁技术 简称SaaS 是一种软件架构技术 是实现如何在多用户环境下 此处的多用户一般是面向企业用户 共用相同的系统或程序组件 并且可确保各用户间数据的隔离性 简单讲 在一台服务器上运行单个
  • XSS 跨站脚本

    XSS 跨站脚本 一 什么是XSS XSS Cross site Scripting 中文名跨站脚本攻击 其原理是攻击者利用浏览器执行前端代码 HTML CSS JavaScript 的特性 将恶意的JavaScript代码插入到页面中 当
  • LVGL动态图GIF实现 v7 version

    lvglv8 1以上的版本自带动态图库 github网址 LVGL GitHub 主要包含四个文件 gifdec c gifdec h lv gif c lvgif h 目录 lvgl release v8 1 lvgl release v
  • Cortex-AX系列性能对比

    首先要明确一个概念 Cortex并不是一种架构 而是ARM的一个系列 Cortex A系列 而我们通常意义的ARM7 ARM9 ARM11才是所谓的架构 同时需注意 Cortex A5 Cortex A8 Cortex A9 Cortex
  • ELF文件格式

    在介绍ELF格式之前 先简单说明一下可执行文件的生成流程 1 编写C源文件 或汇编源文件 2 准备共享库格式的目标文件 shared object file 如数学库 标准库 2 用编译器 compiler 将C编译成可重定位格式的目标文件