ELF文件结构

目录

ELF文件类型

ELF文件结构

通过链接视角分析目标文件

ELF文件头(ELF Header)

节头表

.text代码节

.data 数据节  .rodata 只读数据节

.bss节

其他常见的节

字符串节

符号表

重定位表

通过运行视角分析目标文件


本节内容:

  1. ELF文件类型
  2. ELF文件结构   从链接视角,运行视角分析

ELF文件类型

ELF(Executable and Linkable Format),即“可执行可链接格式”,Linux 系统上所运行的就是 ELF 格式的文件,相关定义在“/usr/include/elf.h”文件里。

测试代码如下

#include<stdio.h>int global_init_var = 10;
int gloabal_uninit_var;void func(int sum) {printf("%d\n", sum);
}void main()
{static int local_static_init_var = 20;static int local_static_uninit_var;int local_init_val = 30;int local_uninit_var;func(global_init_var + local_init_val + local_static_init_var);
}

使用下面4条命令分别进行编译可以得到5个不同的目标文件( object file ),分别是elfDemo.dyn、elfDemo.exec、elfDemo pic.rel、elfDemo.rel 和 elfDemo_static.exec。

gcc elfDemo.c -o elfDemo.exec
gcc -static elfDemo.c -o elfDemo_static.exec
gcc -c elfDemo.c -o elfDemo.rel
gcc -c -fPIC elfDemo.c -o elfDemo_pic.rel && gcc -shared elfDemo_pic.rel -o elfDemo.dyn

从上面 file命令的输出以及文件后缀可以看到,ELF文件分为三种类型,可执行文件(.exec可重定位文件( .rel)和共享目标文件( .dyn ):

  1. 可执行文件( executable file,.exec):经过链接的、可执行的目标文件,通常也被称为程序。
  2. 可重定位文件( relocatable file ,.rel):由源文件编译而成且尚未链接的目标文件,通常以“.o”作为扩展名。用于与其他目标文件进行链接以构成可执行文件或动态链接库,通常是一段位置独立的代码( Position Independent Code, PIC )。
  3. 共享目标文件( shared object file,.dyn):动态链接库文件。用于在链接过程中与其他动态链接库或可重定位文件一起构建新的目标文件,或者在可执行文件加载时,链接到进程中作为运行代码的一部分。

ELF文件结构

        ELF文件被统称为 Object file,与之前的 .o 文件不同,遵循规范,提到目标文件就是指各种ELF文件。.o文件时重定位文件,包含有代码和数据,被链接成为可执行 .exec , .rel , .dyn

分析目标文件时,有两种视角可以选择:

  • 链接视角:通过节(Section)划分目标文件结构;
  • 运行视角:通过段(Segment)划分目标文件结构;

从程序的不同状态在内存的形态来分析的,链接时和运行时

通过链接视角分析目标文件

目标文件通常包含有 .text,.data,.bss文件 三个节,还有其他节以及文件头等

  • .text:用于保存机器指令
  • .data:用于保存已经初始化的全局变量和静态局部变量
  • .bss:用于保存未初始化的全局变量和静态局部变量

ELF文件头(ELF Header)

        ELF文件头(ELF header )位于目标文件最开始的位置,包含描述整个文件的一些基本信息,例如ELF文件类型、版本/ABI版本、目标机器、程序人口、段表和节表的位置和长度等。文件头部存在魔术字符(7f 45 4c 46 ),即字符串“\177ELF”,当文件被映射到内存时,可以通过搜索该字符确定映射地址,这在 dump内存时非常有用。

查看elf文件头信息 

readelf -h elfDemo.rel

ELF Header本质是一个结构体

Elf64_Ehdr结构体如下:

节头表

        一个目标文件中包含许多节,节的信息保存在节头表( Section header table )中,表的每一项都是一个 Elf64_Shdr结构体(也称为节描述符),记录了节的名字、长度、偏移、读写权限等信息。节头表的位置记录在文件头的e_shoff域中。

节头表对于程序运行并不是必须的,因为它与程序内存布局无关,是程序头表的任务,所以常有程序去除节头表,以增加反编译器的分析难度。

查看目标文件节头表

readelf -S elfDemo.rel

接下来使用objdump工具分析程序,objdump 是一个用于分析和显示目标文件(object file)或可执行文件的工具。它可以提供有关二进制文件的各种信息,包括头部信息、符号表、段信息、反汇编代码等。

Elf64_shdr结构体如下

.text代码节

objdump -x -s -d elfDemo.rel
  • -x:显示更详细的头部信息、段(section)信息和符号表等。
  • -s:显示每个段的内容,包括十六进制字节和对应的ASCII字符。
  • -d:进行反汇编,显示机器代码的汇编指令。

Contents of section .text

section .text部分是.text数据的十六进制形式,总共0x40个字节,最左边一列是偏移量,中间四列是内容,最右边一列是ASCII码形式。

Disassembly of section .text

是反汇编的结果。

.data 数据节  .rodata 只读数据节

.data节保存已经初始化的全局变量和局部静态变量。源代码中共有两个这样的变量: global_init_var ( 0a000000 )和 local_static_init_var ( 14000000 )每个变量4个字节,一共8个字节。
.rodata节保存只读数据,包括只读变量和字符串常量。源代码中调用printf()函数时,用到了一个字符串“%d\n”,它是一种只读数据,因此保存在.rodata节中,可以看到字符串常量的ASCII形式.以“\0”结尾。

.bss节

用于保存未初始化的全局变量和局部静态变量。如果仔细观察,会发现该节没有CONTENTS属性,这表示该节在文件中实际上并不存在,只是为变量预留了位置而已,因此该节的sh_offset域也就没有意义了。

其他常见的节

字符串节

字符串表中包含了以null结尾的字符序列,用来表示符号名和节名,引用字符串时只需给出字符序列在表中的偏移即可。字符串表的第一个字符和最后一个字符都是 null 字符,以确保所有字符串的开始和终止。

readelf -x .strtab elfDemo.relreadelf -x .shstrtab elfDemo.rel

符号表

符号表记录了目标文件中所用到的所有符号信息,通常分为.dynsym和.symtab前者是后者的子集。

  • .dynsym保存了引用自外部文件的符号,只能在运行时被解析;
  • 而.symtab还保存了本地符号,用于调试和链接。

目标文件通过一个符号在表中的索引值来使用该符号。索引值从0开始计数,但值为0的表项不具有实际的意义,它表示未定义的符号。每个符号都有一个符号值( symbol value ),对于变量和函数,该值就是符号的地址。

raedelf -s elfDemo.rel


Elf64_sym结构体如下

重定位表

        重定位是连接符号定义与符号引用的过程。可重定位文件在构建可执行文件或共享目标文件时,需要把节中的符号引用换成这些符号在进程空间中的虚拟地址。包含这些转换信息的数据就是重定位项( relocation entries )。

raedelf -r elfDemo.rel

offest:表示在重定位时需要被修改符号的偏移

INFO:TYPE,SYMBOL部分

  • TYPE表示如何修改引用
  • SYMBOL表示应该修改引用为哪个符号

ADDEND:用于对被修改的引用做偏移调整

Elf64_Rel  Elf64_Rela 结构体如下

通过运行视角分析目标文件

当运行一个可执行文件时,首先需要将该文件和动态链接库装载到进程空间中,形成一个进程镜像。每个进程都拥有独立的虚拟地址空间,这个空间如何布局是由记录在段头表中的程序头( Program header)决定的。ELF文件头的e_phoff域给出了段头表的位置。

readelf -l elfDemo.exec

可以看到每个段都包含了一个或多个节,相当于是对这些节进行分组,段的出现也正是出于这个目的。随着节的数量增多,在进行内存映射时就产生空间和资源浪费的问题。实际上,系统并不关心每个节的实际内容,而是关心这些节的权限(读、写、执行),那么通过将不同权限的节分组,即可同时装载多个节,从而节省资源。例如.data和.bss 都具有读和写的权限,而.text和.plt.got则具有读和执行的权限。

常见的段:

  • LOAD段:用于描述可装载的节,动态链接的可执行文件有两个:.data和.text文件分开存放。
  • DYNAMIC段:包含一些动态链接器必须的信息,如共享列表,GOT表,重定位表
  • NOTE段:保存系统相关的附加信息
  • INSERT段:把位置和大小信息存放在一个字符串中,是对程序解释器的描述
  • PHDR段:保存程序头表本身位置和大小

Elf64_Phdr结构体

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/142762.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

san.js源码解读之工具(util)篇——splitStr2Obj函数

一、 源码解析 /*** 将字符串逗号切分返回对象** param {string} source 源字符串* return {Object}*/ function splitStr2Obj(source) {var result {};each( // 2source.split(,), // 1function (key) { // 3result[key] key;});return result; }把字符串通过 split 函数以…

【AI视野·今日Robot 机器人论文速览 第三十六期】Tue, 19 Sep 2023

AI视野今日CS.Robotics 机器人学论文速览 Tue, 19 Sep 2023 (showing first 100 of 112 entries) Totally 112 papers &#x1f449;上期速览✈更多精彩请移步主页 Interesting: &#x1f4da;In-Hand Object Rotation, RotateIt 提出了一种基于视觉与触觉的物体旋转朝向的方法…

一文了解优先考虑结果的以「意图」为中心的 Intent-Centric 架构

Web3 用户体验成是阻碍区块链被大规模采用的原因之一&#xff0c;而 Intent-Centric 架构形式极大简化了用户的体验门槛。 Ac-Core&#xff1a;实现意图所需元素&#xff1a;1&#xff09;账户抽象&#xff1a;利用捆绑器加代付合约完成适合开发者的狭义意图&#xff1b;2&…

【萌新的RiscV学习之流水线结构的概述-7】

萌新的RiscV学习之流水线结构的概述-7 之前写完了单周期的指令 目前朝着流水线迈进 由于涉及学业机密 就不展示代码了 主要展示学习过程和一些想法 由于时钟周期必须满足所有指令中最坏的情况&#xff0c;所以不能使用那些缩短常用指令执行时间而不改变最坏情况的实现技术。因…

链表(单链表、双链表)

前言&#xff1a;链表是算法中比较难理解的部分&#xff0c;本博客记录单链表、双链表学习&#xff0c;理解节点和指针的使用&#xff0c;主要内容包括&#xff1a;使用python创建链表、实现链表常见的操作。 目录 单链表 双链表 单链表 引入链表的背景&#xff1a; 先来看…

2023年最新电商某东app端sign签名算法与cipher加解密逆向分析(2023-09-26)

前言&#xff1a; 本文仅供学习交流&#xff0c;只提供关键思路不会给出完整代码&#xff0c;严禁用于非法用途&#xff0c;若有侵权请联系我删除&#xff01;技术交流合作请私信&#xff01; 一.工具的选择&#xff08;抓包工具的选择&#xff0c;是门学问&#xff09; 用…

Android存储权限完美适配(Android11及以上适配)

一、Bug简述 一个很普通的需求&#xff0c;需要下载图片到本地&#xff0c;我的三个测试机&#xff08;荣耀Android10&#xff0c;红米 11 和小米Android 13都没有问题&#xff09;。 然后&#xff0c;主角登场了&#xff0c;测试的三星Android 13 死活拉不起存储权限弹窗。 …

深入理解红黑树

小白慎入&#xff01;本文难度比较高&#xff0c;需要对红黑树有一定的了解再来看&#xff01; 红黑树 红黑树是一种高级数据结构&#xff0c;是平衡树大家族中的一员&#xff0c;并且听名字就知道这个玩意不是凡物&#xff0c;可能你从未听过&#xff0c;但是你一定会为这样的…

华为OD七日集训第6期 十一特辑 - 按算法分类,由易到难,循序渐进,玩转OD

目录 专栏导读华为OD机试算法题太多了&#xff0c;知识点繁杂&#xff0c;如何刷题更有效率呢&#xff1f; 一、逻辑分析二、数据结构1、线性表① 数组② 双指针 2、map与list3、优先队列4、滑动窗口5、二叉树6、并查集7、栈 三、算法1、基础算法① 贪心算法② 二分查找③ 分治…

大咖共探AGI时代机遇,腾讯云助力大模型规模化应用提速

引言 2023 年&#xff0c;科技圈的“顶流”莫过于大模型。自 ChatGPT 的问世拉开大模型与生成式 AI 产业的发展序幕后&#xff0c;国内大模型快速跟进&#xff0c;已完成从技术到产品、再到商业的阶段跨越&#xff0c;并深入垂直行业领域。 新技术的爆发&#xff0c;催生新的应…

mdobus ASCII转CAN OPEN JAE1939协议网关

Modbus RTU协议转换网关是一种常见的设备&#xff0c;用于将Modbus RTU协议转换为其他通信协议。而CANopen是一种基于CAN总线的通信协议&#xff0c;主要用于工业自动化和控制系统中。本文将介绍Modbus RTU协议转换网关如何支持CANopen协议&#xff0c;以及该功能的应用场景和优…

洗地机哪个牌子好用又实惠?口碑最好的洗地机推荐

智能技术飞速发展的时代&#xff0c;扫地机器人这类智能家电其实也在顺应潮流和用户需求&#xff0c;不断更新迭代。暂且不说市面上现有多少个洗地机品牌&#xff0c;单单一个洗地机品牌旗下&#xff0c;其实每年都会有多个系列的新品亮相&#xff0c;我们面对的选择多了&#…

javaee之黑马乐优商城6

商品品牌的查询 上面就是我们需要根据分类id去找品牌 假设我们现在拿到的是 商品的分类id&#xff0c;我们需要根据分类id查询出对应的品牌即可 下面我们拿到上面的接口&#xff0c;直接撸代码 这个是和品牌相关联的操作&#xff0c;因为先去看一下BrandMapper,这个mapper是…

OpenCV显示10bit Raw数据

参考&#xff1a;10 12 14bit图像存储格式&#xff0c;利用Opencv显示10bit Raw数据,并根据鼠标的移动显示对应位置的灰度值。其他bit位数的Raw数据方法类似。 代码实现&#xff1a; #include<opencv2/opencv.hpp> #include<iostream> #include<opencv/highgu…

Qt扩展-QCustomPlot 简介及配置

QCustomPlot 简介及配置 一、概述二、安装教程三、帮助文档的集成 一、概述 QCustomPlot是一个用于绘图和数据可视化的Qt 控件。它没有进一步的依赖关系&#xff0c;并且有良好的文档记录。这个绘图库专注于制作好看的、发布质量的2D绘图、图形和图表&#xff0c;以及为实时可…

中间相遇法(分治类问题非等大分治的平衡做法)

分治&#xff0c;如果分成两半大小不一样&#xff0c;很容易被卡到 O ( n 2 ) O(n^2) O(n2) 在某些题目中&#xff0c;利用中间相遇法&#xff0c;我们可以优化这个过程 其优化的前提是分治的大头在找分界点 复杂度不用证&#xff0c;很好理解吧 这层找地越久&#xff0c;下…

一维卷积神经网络

假设输入数据维度为8&#xff0c;filter维度为5&#xff1b; 不加padding时&#xff0c;输出维度为4&#xff0c;如果filter的数量为16&#xff0c;那么输出数据的shape就是4*16. 一维卷积不代表卷积核只有一维&#xff0c;也不代表被卷积的feature也是一维。一维的意思是说卷…

regexp 应用

今天同事拿出个小栗子 1 如果用like的话 1,22 的情况会被字符串2匹配到这样会有问题 这里需要用concat将uids处理下 比如第一条处理成&#xff0c;1,2&#xff0c;3&#xff0c; 的形式 去模糊匹配 ‘%,1,%’ 当然like这种模糊匹配不太建议使用 2 regexp 用法 单个值 &#x…

MySQL作业1

目录 一.创建一张表&#xff0c;包含以下所有数据类型 建表&#xff1a;​编辑 二.使用以下六种约束 1.非空约束 2.唯一约束 3.主键约束 4.外键约束 5.检查约束 6.默认值约束 一.创建一张表&#xff0c;包含以下所有数据类型 Text 类型&#xff1a; Number 类型&#…

2023-9-26 JZ 复杂链表的复制

题目链接&#xff1a;复杂链表的复制 import java.util.*; /* public class RandomListNode {int label;RandomListNode next null;RandomListNode random null;RandomListNode(int label) {this.label label;} } */ public class Solution {public RandomListNode Clone(Ra…