Linux:ELF

文章目录

  • 前置知识
    • 从文本文件到可执行文件经历的阶段
    • 编译器gcc
    • 目标文件
  • ELF
    • Section(节)
    • Segment(段)
    • 从链接角度和从程序角度看ELF文件
      • 1. Section Header Table:
      • 2. Program Header Table:
  • 参考

前置知识

从文本文件到可执行文件经历的阶段

一个用C语言编写的高级语言程序从编写到打包、再到编译执行的基本过程如下:
在这里插入图片描述

编写 - 预处理 - 编译 - 汇编 - 链接 。
其中,编译和汇编可以合并成一步,称为编译。

  1. 编写程序:使用任意文本编辑器,如Notepad、Sublime Text、Visual Studio等。

  2. 预处理:使用预处理器对程序进行处理,例如宏替换、头文件包含等。使用预处理器,通常是C语言编译器的一部分,例如gcc、clang等。预处理器处理的文件是源代码文件,生成的文件通常是.i后缀的中间文件,例如hello.i。

  3. 编译:使用编译器将程序转换为汇编语言。使用编译器,例如gcc、clang等。编译器处理的文件是预处理器生成的.i文件,生成的文件通常是.s后缀的汇编代码文件,例如hello.s。

  4. 汇编:使用汇编器将汇编代码转换成机器码。使用汇编器,例如gas、nasm等。处理的文件是编译器生成的.s文件,生成的文件通常是.o后缀的目标文件,例如hello.o。

  5. 链接:使用链接器将程序中的不同模块连接起来,并生成可执行文件。使用链接器,例如ld、gcc等。处理的文件是目标文件(.o文件),可以链接多个目标文件,生成可执行文件。 可执行文件通常是没有后缀的,例如hello。

  6. 打包:使用压缩工具,例如tar、zip等。打包的文件通常是可执行文件和相关依赖文件,文件名可以自定义,例如hello.tar.gz或hello.zip。

在整个编译过程中,涉及到的文件可以分为源代码文件(.c文件)、预处理生成的文件(.i文件)、编译器生成的文件(.s文件、.o文件)和链接器生成的文件(可执行文件)。

因此在本示例中,文件名可以为hello.c、hello.i、hello.s、hello.o、hello等。

编译器gcc

gcc是GNU Compiler Collection的缩写,是一款开源的C编译器,支持多种操作系统和CPU架构。它由许多不同的编译器组成,包括C、C ++、Objective-C、Fortran、Ada和其他语言的编译器,并支持众多的开源项目。gcc是GNU工程的一部分,由自由软件基金会(FSF)维护。由于它的灵活性和可移植性,gcc被广泛应用于编译开源项目和商业软件。

目标文件

目标文件(Object File)是编译源代码后生成的中间文件,其中包含了编译器产生的机器代码、符号表、重定位信息等。目标文件的主要作用是在链接阶段将多个目标文件合并成一个可执行文件或者库文件。

目标文件的命名约定和后缀可以因编译器和操作系统而异。在Unix/Linux系统中,通常使用".o"作为目标文件的后缀,例如example.o。在Windows系统中,常见的目标文件后缀包括".obj"等。

目标文件是编译过程中的一个重要中间产物,通过链接器将多个目标文件合并,最终生成可执行文件或者共享库。

目标文件的详细介绍可以参阅:
计算机的目标文件是什么? 在程序中充当什么角色?

ELF

ELF(Executable and Linkable Format)是一种通用的二进制文件格式,用于可执行文件、目标文件、共享库等在Unix和类Unix系统中。ELF格式是一种规范,定义了二进制文件的结构,使得不同的编译器、链接器和操作系统能够共同使用这种格式的文件。

ELF文件包含了以下主要部分:

  1. 文件头(ELF Header): 包含了文件的基本信息,如文件类型、架构、入口点地址等。

  2. 程序头表(Program Header Table): 描述了可执行文件的段(段包含可执行代码、数据、BSS等),以及这些段在内存中的加载位置和属性。

  3. 节头表(Section Header Table): 描述了目标文件的各个节(sections),包括代码段、数据段、符号表、字符串表等。每个节都有自己的类型、大小、偏移量等属性。

  4. 数据节(Sections): 包含实际的数据,例如代码、数据、符号表等。

  5. 重定位信息: 描述了需要在链接时进行重定位的位置,以便正确地将不同目标文件的代码和数据链接在一起。

  6. 符号表(Symbol Table): 记录了各种符号(函数、变量等)的信息,包括名称、类型、地址等。

ELF格式的设计提供了灵活性和可扩展性,使得不同的操作系统和硬件架构能够支持这一格式。在Linux和许多其他类Unix系统中,可执行文件和共享库通常采用ELF格式。

Section(节)

Section(段)是在汇编和链接中用于组织和描述不同类型数据的一个概念。在汇编程序中,.section指令用于声明一个Section。每个Section都包含特定类型的数据,比如代码、数据、符号表、字符串表等。

以下是一些常见的Section类型:

  1. 代码段(.text): 包含可执行的机器代码。

  2. 数据段(.data): 包含已初始化的全局和静态变量。

  3. BSS段: 包含未初始化的全局和静态变量。BSS是"Block Started by Symbol"的缩写。

  4. 符号表段(.symtab): 包含符号表,记录了程序中的符号(函数、变量等)信息。

  5. 字符串表段(.strtab): 包含字符串表,存储了符号表中的字符串。

  6. 重定位表段(.rel.text、.rel.data等): 包含重定位信息,记录了需要在链接时进行重定位的位置。

每个Section都有一个名称和一组属性,这些属性描述了Section的内容和用途。在链接过程中,多个目标文件中的相同类型的Section会被合并成一个更大的Section,以便最终生成可执行文件或共享库。

Section在汇编和链接中起到了组织和管理代码、数据以及其他信息的作用,使得程序的各个部分能够被正确地组合在一起。

Segment(段)

Segment(段)是在可执行文件在运行时加载到内存时用于组织和描述内存布局的一个概念。一个Segment通常包含一个或多个相邻的Section,这些Section在运行时被映射到内存中的相邻区域。

ELF文件格式中的Program Header Table描述了可执行文件在内存中的布局,其中的每一项对应一个Segment。Segment的类型和属性决定了在运行时如何加载和使用这一段内存。

常见的Segment类型包括:

  1. 加载可执行代码的Segment: 包含机器代码的Section,通常标记为可执行和可读。在内存中,这一段被映射为可执行的代码段。

  2. 加载可读写数据的Segment: 包含已初始化的全局和静态变量的Section,通常标记为可读和可写。在内存中,这一段被映射为可读写的数据段。

  3. 加载可读写BSS段的Segment: 包含未初始化的全局和静态变量的Section,通常标记为可读和可写。在内存中,这一段被映射为可读写的BSS段。

  4. 加载只读数据的Segment: 包含只读数据的Section,通常标记为只读。在内存中,这一段被映射为只读数据段。

每个Segment都有一个虚拟地址和一个文件偏移量,描述了它在内存中的位置和在文件中的位置。加载器(Loader)使用这些信息来将文件中的Segment映射到内存中的相应位置。

Segment在可执行文件加载时决定了程序在内存中的布局,它通过包含相关的Section来组织和描述内存中的数据和代码。这种设计提供了对内存分布的更高级别的抽象,使得可执行文件能够在不同环境中正确地加载和运行。

从链接角度和从程序角度看ELF文件

ELF文件在汇编器和链接器看来是由Section Header Table描述的一系列Section的集合,而在加载器(Loader)看来是由Program Header Table描述的一系列Segment(段)的集合。这两个表提供了不同的视角,分别对应着文件在链接和加载过程中的不同需求。如图:
在这里插入图片描述

1. Section Header Table:

  • 描述: Section Header Table包含了关于文件中各个Section的信息。每个Section对应于文件中的一部分数据,如代码段、数据段、符号表等。
  • 用途: 汇编器和链接器使用Section信息来组织和管理不同类型的数据。符号表、字符串表、代码段、数据段等都以Section的形式存在。

2. Program Header Table:

  • 描述: Program Header Table描述了可执行文件在内存中的布局,以及如何加载这些Segment。如前面描述的,Segment是一个更高层次的概念,它可能包含多个Section,但是在内存中以更连续的方式存在。
  • 用途: 加载器使用Program Header信息来决定如何加载文件中的Segment,将它们映射到内存中的合适位置,并设置程序的入口点等。

通过这两个表,ELF文件格式在设计上实现了灵活性和可扩展性。Section提供了对文件中不同类型数据的详细描述,而Segment则更侧重于在运行时的内存布局。这样的设计使得ELF文件在不同阶段(编译、链接、加载)都能够提供必要的信息,以便于文件的正确处理和执行。

参考

https://blog.csdn.net/daide2012/article/details/73065204

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

树莓派zero w入坑指南

树莓派zero w入坑指南 入坑契机 说起创客不得不提到开源硬件Raspberry Pi(树莓派)。它是一款基于ARM的微型电脑主板,以MicroSD卡为硬盘,提供HDMI和USB等外部接口,可连接显示器和键鼠。以上部件全部整合在一张仅比信用卡稍大的主板上&#x…

jvm阶段小节

文章目录 静态变量与局部变量的对比: 我们知道类变量有两次初始化的机会,第一次是在“准备阶段”(链接),执行系统初始化,对类变量设置默认值,另一次则是在“初始化”阶段,赋予程序员…

Postman测试 restful 接口!

日常开发中经常会遇到没有前提界面,直接调用后台 restful 接口的情景,不管时后台代码先行,并且开发完之后开发人员进行自测还是,或者是专业测试进行 restful 接口测试,都需要一款工具,现在就来介绍 postman…

如何在本地搭建Oracle数据库并实现无公网ip通过PLSQL工具远程连接数据库

文章目录 前言1. 数据库搭建2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射 3. 公网远程访问4. 配置固定TCP端口地址4.1 保留一个固定的公网TCP端口地址4.2 配置固定公网TCP端口地址4.3 测试使用固定TCP端口地址远程Oracle 正文开始前给大家推荐个网站,前些天发…

PythonStudio:一款国人写的python及窗口开发编辑IDE,可以替代pyqt designer等设计器了

本款软件只有十几兆,功能算是强大的,国人写的,很不错的python界面IDE.顶部有下载链接。下面有网盘下载链接,或者从官网直接下载。 目前产品免费,以后估计会有收费版本。主页链接:PythonStudio-硅量实验室 作…

期末数组函数加强练习

前言:由于时间问题,部分题解取自网友,但都是做过的好题。 对于有些用c实现的题目,可以转化成c实现,cin看成c的读入,可以用scanf,输出cout看作printf,endl即换行符 开胃菜&#xff…

从零构建属于自己的GPT系列6:模型部署2(文本生成函数解读、模型本地化部署、文本生成文本网页展示、代码逐行解读)

🚩🚩🚩Hugging Face 实战系列 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在PyCharm中进行 本篇文章配套的代码资源已经上传 从零构建属于自己的GPT系列1:数据预处理 从零构建属于自己的GPT系列2:模型训…

在线学习平台-学生端

在线学习平台------手把手教程👈 学生端课程分页查询 sql: 学生登入时,只能看见自己的所属课程,需要关联查询,查出学生对应的课程 SELECTt2.course_id,t2.course_name,t2.course_cover,t2.teacher_id,t3.nick_name,t2.remarkfrom sys_user t1LEFT JOIN ms_course t…

计算机系统结构MIPS流水线

题目 其中:R3的初值是R2396。假设:在整个代码序列的运行过程中,所有的存储器访问都是命中的,并且在一个时钟周期中对同一个寄存器的读操作和写操作可以通过寄存器文件“定向”。问: (1)在没有任…

C++模板编程浅析

函数模板 声明与定义函数模板 #include <iostream> using namespace std; template <class T> void swap_new(T& a, T& b);int main() {int a 1, b 2;float c 1.5, d 3.6;swap_new(a, b);swap_new(c, d);cout << a << " " &…

Redis HyperLogLog 数据结构模型统计

HyperLogLog HyperLogLog 不是一种新的数据结构 &#xff0c; 本质上是字符串类型。 是一种基数算法。 通过 HyperLogLog 可以节省内存空间&#xff0c;并完成独立总数的统计。 HyperLogLog 数据结构可用于仅使用少量恒定内存来计算集合中的唯一元素&#xff0c;具体而言&…

Centos硬盘操作合集

一、硬盘命令说明 lsblk 列出系统上的所有磁盘列表 查看磁盘列表 参数意义 blkid 列出硬盘UUID [rootzs ~]# blkid /dev/sda1: UUID"77dcd110-dad6-45b8-97d4-fa592dc56d07" TYPE"xfs" /dev/sda2: UUID"oDT0oD-LCIJ-Xh7r-lBfd-axLD-DRiN-Twa…

【coco】掩膜mask影像转coco格式txt(含python代码)

最近在做实例分割&#xff0c;遇到二值掩膜影像——coco格式txt的实例分割转换问题&#xff0c;困扰很久&#xff0c;不知道怎么转换&#xff0c;转出来的txt没法用代码成功读取。一系列问题&#xff0c;索性记录下自己的结局路程&#xff0c;方便大家python代码自取。 目录 &…

Python开发运维:Python调用K8S API实现资源管理

目录 一、实验 1.Python操作K8S API获取资源 2.Python操作K8S API创建deployment资源 3.Python操作K8S API删除k8s资源 4.Python操作K8S API修改k8s资源 5.Python操作K8S API查看k8s资源 二、问题 1.Windows11安装kubernetes报错 2.Python通过调用哪些方法实现Pod和De…

C4D云渲染怎么提升速度小技巧?C4D云渲染速度提升技巧

当许多C4D用户转向云渲染时&#xff0c;他们常常会发现渲染速度并没有预期中的提升&#xff0c;这让人产生疑问&#xff0c;为什么使用云渲染服务后&#xff0c;渲染时间依然没有显著缩短&#xff0c;C4D云渲染情况取决于多个因素&#xff0c;如&#xff1a;渲染任务特点以及所…

图的搜索(二):贝尔曼-福特算法、狄克斯特拉算法和A*算法

图的搜索&#xff08;二&#xff09;&#xff1a;贝尔曼-福特算法、狄克斯特拉算法和A*算法 贝尔曼-福特算法 贝尔曼-福特&#xff08;Bellman-Ford&#xff09;算法是一种在图中求解最短路径问题的算法。最短路径问题就是在加权图指定了起点和终点的前提下&#xff0c;寻找从…

代码上传的gitee平台

1.首先我们访问工作台 - Gitee.com进行注册和登录 2.我们创建一个仓库&#xff1a; 3.在本地创建我们的项目 在这文件夹里面我们打开git bush,执行 一下操作&#xff1a; git init &#xff1a;初始化仓库 git status&#xff1a;检查状态 git add . &#xff1a;将当前文件…

【wimdows电脑上管理员账户与管理员身份的区别】

管理员账户 在控制面板的用户账户中&#xff0c;点击更改账户类型&#xff0c;可以看到目前的账户是“管理员账户”还是“标准账户”。 管理员身份 在快捷方式上右击&#xff0c;可以看到&#xff0c;可以选择以管理员身份运行该软件。 如何查看某个应用是否以管理员身份…

6.Jetson Orin Nano 系统在NVME SSD上备份与恢复

Jetson Orin Nano 系统在NVME SSD上备份与恢复 刚开始我也参考其它博主写的系统备份与恢复&#xff0c;由于我Jetson 的系统盘是1t的&#xff0c;用dd命令拷贝的到另外一个1t的硬盘里面时&#xff0c;总会出现硬盘空间不足的情况出现。只能从小硬盘容量往大硬盘容量拷贝&#…

单通道led线性驱动芯片推荐:SM2082EGS

单通道LED线性驱动芯片是一种用于控制LED灯的芯片&#xff0c;它能够提供恒定的电流输出&#xff0c;从而实现LED灯的稳定亮度调节。这种芯片主要由输入端、控制电路、放大器和输出端构成&#xff0c;通过控制输入端的电压和信号来调节LED的亮度。 单通道led线性驱动芯片推荐&a…