解析目标文件

2023-11-11

最近在看《程序员的自我修养》,颇有体会,故化繁为简,整理书中部分内容,作为学习笔记。

  1. PC平台上流行的可执行文件格式主要是windows下的PE(Portable Executable)和Linux下的ELF(Executable Linkable Format),他们都是COFF(common file format)格式的变种。
  2. 可执行文件(windows下.exe和Linux下的ELF可执行文件)、动态链接库(DLL,Dynamic Linking Library)(windows下的.dll和Linux下的.so)、静态链接库(Static Linking Library)(windows下的.lib和Linux下的.a)文件都是按照可执行文件格式存储。
  3. 目标文件中的内容至少有编译后的机器指令代码、数据,还有链接时需要的一些信息,如符号表、调试信息、字符串等。以“段”的形式存储。
  4. 代码段(.text或.code):程序源代码编译后的机器指令;
  5. 数据段(.data):放置全局变量和局部静态变量;
  6. .bss段:放置未初始化的全局变量和局部静态变量;
  7. 程序指令和数据分开存放的好处:
  • 程序被装载后,数据和指令分别被映射到两个虚存区域。数据区域对于进程来说可读写,指令区域对于进程来说是只读的,所以两个虚存区域的权限可以被分别设置成可读写和只读,这样可以防止程序的指令被有意或者无意的修改;
  • 程序的指令和数据分开存对CPU的缓存命中率提高有好处;
  • 当系统中运行多个改程序的副本时,他们的指令都是一样,因此在内存中只须保存一份该程序的指令部分。当然每个副本进程的数据区域是不一样的,他们是进程私有的。

挖掘目标文件SimpleSection.o

1.    程序代码清单

只编译不链接此文件:

$ gcc –c SimpleSection.c

利用binutils的工具objdump查看object内容的结构:

$ objdump –h SimpleSection.o

参数-h就是把ELF文件的各个段的基本信息打印出来。结果如下:

除了最基本的代码段、数据段、BSS段之外,SimpleSection.o还有只读数据段(.rodata)、注释信息段(.comment)、堆栈提示段(.note.GNU-stack)、eh_frame段。

从上图可以理解,段的长度(Size)和段所在的位置(File Offset),“CONTENTS”表示该段在文件中存在,“ALLOC”表示实际上ELF文件中不存在的内容。各段在ELF中的结构如下图所示。

  

$size SimpleSection.o

用于查看ELF文件的代码段、数据段和BSS段的长度。dec表示三段长度和的十进制,hex表示长度和的十六进制。

2.  代码段

objdump的“-s”参数可以将所有段的内容以十六进制的方式打印出来,“-d”参数可以将所有包含指令的段反汇编。

$ objdump –s –d SimpleSection.o

最左面一列是偏移量,中间4列是十六进制内容,最右面的一列是.text段的ASCII码。

3.  数据段和只读数据段

.data段保存的是那些已经初始化了的全局静态变量和局部静态变量。

.rodata段存放的是只读数据,一般是程序里面的只读变量,如const修饰的变量和字符串常量。

$objdump –x –s –d SimpleSection.o

可以看出.data段里的前四个字节,从低到高分别是0x54、0x00、0x00、0x00。这个值刚好是global_init_varable,即十进制84。

4.  BSS段

.bss段存放的是未初始化的全局变量和局部静态变量。如代码中的global_uninit_var和static_var2就是存放在.bss段,更准确的说法是.bss段为它们预留了空间。有些编译器会将全局的未初始化变量存放在目标文件的.bss段,有些则不放,只是预留一个未定义的全局变量符号,等到最终链接成可执行文件的时候再在.bss段分配空间。

$objdump –x –s –d SimpleSection.o

5.  其他段

ELF文件结构

ELF目标文件格式的最前端是ELF文件头(ELF Header),包含了描述整个文件的基本属性,如ELF版本、目标机器型号、程序入口地址等。

ELF文件中与段有关的重要结构就是段表(Section Header Table),该表描述了所有段的信息,如每个段的段名、段的长度、在文件中的偏移、读写权限和段的其他属性。

ELF中的其他辅助结构,如字符串表、符号表等。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

1.         ELF文件头

$readelf –h SimpleSection.o

从上图可以看出,ELF文件头中定义了ELF魔数、文件机器字节长度、数据存储方式、版本、运行平台、ABI版本、ELF重定位类型、硬件平台、硬件平台版本、入口地址、程序头入口和长度、段表的入口和长度、段表的位置和长度、段的数量等。

ELF文件头结构及相关常熟被定义在“/usr/include/elf.h”里,因为ELF文件在各种平台下都通用,ELF文件有32位版本和64版本。分为为 “Elf32_Ehdr”和 “Elf64_Ehdr”。

“elf.h”使用typedef定义了一套自己的变量体系,如下图。

以32位版本的文件头结构“Elf32_Ehdr”为例,其定义如下:

  1 typedef struct{
  2     unsigned char e_ident[16];
  3     Elf32_Half e_type;
  4     Elf32_Half e_machine;
  5     Elf32_Word e_version;
  6     Elf32_Addr e_entry;
  7     Elf32_Off e_phoff;
  8     Elf32_Off e_shoff;
  9     Elf32_Word e_flags;
 10     Elf32_Half e_ehsize;
 11     Elf32_Half e_phentsize;
 12     Elf32_Half e_phnum;
 13     Elf32_Half e_shentsize;
 14     Elf32_Half e_shnum;
 15     Elf32_Half e_shstrndx;
 16 }Elf32_Ehdr;
 17     

各个成员的含义如下:

  • ELF魔数

最开始的4个字节是所有ELF文件都必须相同的标识码,分别为0x7F、0x45、0x4c、0x46,第一个字节对应的ASCII字符里的DEL控制符,后面的3个字符刚好是ELF这三个字符的ASCII码。这4个字节被称为ELF文件的魔数,几乎所有的可执行文件格式的最开始几个字节都是魔数。

  • 文件类型

即前面提到过的3种ELF文件类型,每个文件类型对应一个常量。系统通过这个常量来判断ELF文件的真正文件类型,而不是通过文件的扩展名。

2.  段表

段表(Section Header Table)就是保持ELF文件各段基本属性的结构。编译器、链接器、装载器都是依靠段表来定位和访问各个段的属性的。使用readelf工具来查看ELF文件段的结构。

$readelf –S SimpleSection.o

段表的结构比较简单,它是以“Elf32_Shdr”结构体为元素的数组,数组元素的个数等于段的个数。“Elf32_Shdr”也被称为段描述符(Section Descriptor)

Elf32_Shdr各成员的含义如下:

至此,才把SimpleSection的所有段的位置和长度分析清楚,如下图所示。段表Section Table长度为0x208,即520个字节,包含了13个段描述符。每个段描述符为4×10=40Bytes。

3.  重定位表

链接器在处理目标文件时,需要对目标文件中的某些部位进行重定位,即代码段和数据段中的那些对绝对位置的引用的位置,如.rel.text就是针对.text段的重定位表,因为.text段中至少有一个绝对地址的引用,那就是printf函数的调用。

4.  字符串表

ELF文件中用到了很多字符串,如段名、变量名等,由于字符串的长度往往不定,因此常把字符串集中起来存放到一个表,然后使用字符串在表中的偏移来引用字符串。

一般字符串在ELF文件中也以段的形式保存,常见的段名如.strtab和.shstrtab。字符串表(.strtab)保存普通的字符串,段表字符串表(.shstrtab)保存段表中用到的字符串,最常见的就是段名。

 

参考资料:《程序员的自我修养——链接、装载与库》

Jacky Liu


FROM: http://www.cnblogs.com/liu-jun/archive/2013/01/28/2880577.html

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

解析目标文件 的相关文章

  • 编译原理笔记

    目录 序章 编译原理 编译器 程序设计语言 第一章 概述 机器语言 第一代语言 特点 汇编语言 高级程序设计语言 鼻祖 时期 特点 翻译程序 汇编语言 解释语言 编译程序 编译过程 词法分析 语法分析 语义分析 中间代码生成 之前三步都是编
  • LLVM里的寄存器分配 - 线性扫描算法(二)

    1 背景介绍 在上一篇博文 LLVM 里的寄存器分配 准备工作 一 里 我主要整理了 LLVM 在做寄存器分配前所做的准备工作 介绍了 LLVM 是在怎样的 MIR 上做的寄存器分配 接下来 就需要讲讲 LLVM 是如何做寄存器分配了 虽然
  • 从简入难makefile文件编写,Linux C++编程,简单vi命令

    1 一个最基本的C 程序 2 第二个c 程序 3 第一个入门级别的简单的makefile 4 在makefile中定义变量 5 编写makefile的依赖 如果start 标识后面的某个 o没有 则重新编译没有编译的那个文件 6 最终的ma
  • Code Block & Basic Block

    Code Block In a programming language a code block typically starts with certain syntactical constructs such as loops con
  • Makefile中使用Shell

    http blog csdn net zdl1016 article details 6448989 http blog csdn net absurd article details 636418 Makefile与Shell的问题 大概
  • 编译执行与解释执行的区别

    今天在看到一篇关于分层编译优化的文章时 看到了解释执行与编译执行两个专业词汇 看着熟悉 但不甚理解 然后在网上搜索了一下 说一下自己的理解 对于我们平时写的代码 一般计算机是没办法直接识别的 需要相应的编译器将其编译层机器代码 一些计算机可
  • 初识 flex & bison

    基本概念 flex 和 bison 经常结合使用 分别用于词法分析和语法分析 词法分析器 flex flex 用于生成词法分析器或者说是扫描器 scanner 它将输入的文本分解为称为 tokens 的序列 每个 token 都有一个特定的
  • LLVM IR / LLVM指令集入门

    本文基于LLVM 12官方文档的LLVM Language Reference Manual 以学习笔记为主 所以本文会摘录一些常见 常用的指令 对于一些更加深层次的指令属性 特性 待我对LLVM有更深的理解再单独写文章记录 1 LLVM
  • 龙书学习笔记

    目录 第一章 引论 1 1 语言处理器 1 2 一个编译器的结构 1 2 1 词法分析 1 2 2 语法分析 1 2 3 语义分析器 1 2 4 中间代码生成
  • 简单的递归下降语法分析程序

    简单递归分析程序 其代码如下 include
  • 编译原理 实验四 LR(1)分析法程序

    源代码仓库 CompilePrincipleLearning experiment 4 yusixian CompilePrincipleLearning github com 源代码在demo文件夹中 一 实验目的 掌握LR 1 分析法的
  • 【编译原理】课程一:编译原理入门

    目录 1 为什么要学习编译原理 2 什么是编译原理 3 编译与计算机程序设计语言的关系 3 1 程序设计语言的转换方式 3 2 编译的转换过程 3 3 编译器在语言处理系统中的位置 3 4 编译系统的结构 3 4 1 词法分析 扫描 3 4
  • YACC工具ParserGenerator的下载和配置过程

    工具准备 parser generator http www bumblebeesoftware com downloads htm VC6 0 网上到处都是 1 parser generator的环境设置 安装好parser genera
  • 编译原理实验一:词法分析

    实验一 词法分析程序 一 实验目的 通过设计编制调试一个具体的词法分析程序 加深对词法分析原理的理解 并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法 编制一个读单词过程 从输入的源程序中 识别出各个具有独立意义的
  • 编译原理绪论

    1 美图 5 编译过程一语法分析 任务 在词法分析的基础上 根据语言的语法规则把单词符号串分解成各类语法单位 语法范畴 依循的原则 语法规则 描述工具 上下文无关文法 6 编译过程一中间代码产生 任务 对各类不同语法范畴按语言的语义进行初步
  • OCaml 安装以及简单的加减乘除Demo(以Ubuntu16.04为例)

    安装nix 参考 https mirrors tuna tsinghua edu cn help nix 安装nix sh lt curl https mirrors tuna tsinghua edu cn nix latest inst
  • 编译原理三大经典书籍(龙书 虎书 鲸书)

    1 龙书 Dragon book 英文名 Compilers Principles Techniques and Tools 作者 Alfred V Aho Ravi Sethi Jeffrey D Ullman 中文名 编译原理技术和工具
  • LLVM是如何编译指令的

    本文将会通过一条指令在LLVM中的不同阶段 从源程序语言中的语义结构到成为机器二进制码来研究LLVM的工作原理 本文不会介绍LLVM是如何工作的 这需要理解LLVM的设计以及code以及各种细节 输入代码 我们从一段C代码开始探险 如下 i
  • linux下几种目标文件的分析

    本文中用到的命令 gcc c addvec c 生成可重定位目标文件addvec o readelf addvec o a 读取可重定位目标文件addvec o gcc O2 c main c 生成可重定位目标文件main o gcc st
  • Go 程序编译过程(基于 Go1.21)

    版本说明 Go 1 21 官方文档 Go 语言官方文档详细阐述了 Go 语言编译器的具体执行过程 Go1 21 版本可以看这个 https github com golang go tree release branch go1 21 sr

随机推荐

  • 狂野飙车9服务器维护中,狂野飙车9传奇进不去怎么办

    狂野飙车9 国际服IOS进入办法 苹果端的小伙伴如果想要进入 狂野飙车9 的国际服应该怎么办呢 下面 就跟随玩游戏网的小编一起来看一下具体的进入办法吧 感兴趣的小伙伴可千万不要错过哦 进入方法 第一步 首先我们需要推出AppStore账号
  • 魔方机器人之结构篇

    魔方颜色识别和魔方复原算法以及串口通信都解决完了 感觉自己该松口气了吧 结构可以反正仿照别人的来嘛 做出来就的了 事实又打了我一耳光 我怎么发现我的预判总是那么的不靠谱 总结就是自己没做过的东西再也不要说很简单了 即使看上去简单的再也不能简
  • 5-8 以特殊方式跟管理员打招呼

    创建一个至少包含5个用户名的列表 且其中一个用户名为 admin 想象你要编写代码 在每位用户登录网站后都打印一条问候消息 遍历用户名列表 并向每位用户打印一条问候消息 如果用户名为 admin 就打印一条特殊的问候消息 如 Hello a
  • 使用EasyExcel实现导入导出功能

    使用EasyExcel实现导入导出功能 一 导出 1 使用ideal新建一个maven项目 并在pom xml文件中引入EasyExcel依赖
  • impala 错误

    问题一 impala state store unrecognized service 原因 当前节点未成功安装impala server impala state store impala catalog 解决方案 yum install
  • ulua源码分析

    对于NestClass的Type 用了2次被Cache了两次 主要是因为PushType这个函数 对每个Type对象 不进行Cache检测 总是push一个新的proxy对象
  • 蓝桥杯省赛2021 括号序列 python

    给定一个括号序列 要求尽可能少地添加若干括号使得括号序列变得合法 当添加完成后 会产生不同的添加结果 请问有多少种本质不同的添加结果 两个结果是本质不同的是指存在某个位置一个结果是左括号 而另一个是右括号 例如 对于括号序列 只需要添加两个
  • MQTT:用Mosquitto搭建轻量级的设备接入网关

    开发部署在云端的设备接入网关服务就不得不提到MQTT 使用MQTT不论是从设备到设备 还是设备到云端服务的双向通讯 都可以获得较好的支持 MQTT的起源和我的理解 用tcpdump分析下MQTT的通讯时序 这里基于mosquitto 以一组
  • One PUNCH Man——半监督学习

    文章目录 半监督学习介绍 半监督SVM 基于分歧的方法 半监督学习介绍 我们在丰收的季节来到瓜田 满地都是西瓜 瓜农抱来四个西瓜说这都是好瓜 然后指着地里面六个瓜说这些不好 还需要再生长几天 基于这些信息 我们能否构建一个模型 用于判别地里
  • 优雅的玩转Fast-DDS

    优雅的玩转Fast DDS 安装依赖 sudo apt install cmake g python3 pip wget git pip3 install U colcon common extensions vcstool Fast DD
  • Web开发权威指南笔记(二)

    书 Web开发权威指南 美 Chris Aquino Todd Gandee著 为2nd实战项目CoffeeRun练习以及代码整理 全为个人借鉴本书产出 若需要转载请联系通知我 请尊重原创 谢谢 整理了大概5天了 内容比较多 很多重点都整理
  • mysql区别

    mysql区别 5 0之后与5 0之前 mysql5 0以及5 0以上的版本都存在一个系统自带的系统数据库 是information schema 而5 0之前的版本不存在且5 0以下的版本是多用户单操作 information schem
  • 如何创建NFT-独家设计

    如何创建NFT 第一步 下载并安装 MetaMask小狐狸钱包 第二步 打开官网https opensea io 点击右上角的钱包标志 进行链接 第三步 右上角弹出钱包提示 点击下一步就成功了 第四步 回到首页 点击create按钮 进入创
  • feign使用注意

    参数使用注意 参数name value属性 这两个的作用是一样的 指定的是调用服务的微服务名称 参数url 指定调用服务的全路径 经常用于本地测试 如果同时指定name和url属性 则以url属性为准 name属性指定的值便当做客户端的名称
  • c#正确用smtp.office365.com发邮件

  • Python自动化测试Unittest框架基本使用

    Unittest 框架 首先要知道这个框架是Python自带的 不需要安装 这个框架最重要的4 个核心 TestCase TestSuite TextTestRunner Fixture TestCase 个人总结一下 这个就是用测试用例继
  • SpringCloud与SpringBoot的版本对应关系

    在SpringCloud官网 https spring io projects spring cloud 可以看到 当前 2021年11月 SpringCloud的最新GA版本是2020 0 4这一版 除了2020 0 X版本外 Sprin
  • 基于掌控板+二哈+TinyWebDB+Easy_IoT的人脸识别测温

    文章目录 前言 一 部分硬件及平台介绍 1 二哈识图 HuskyLens 2 TinyWebDB 3 Easy IoT 二 操作步骤 1 二哈的使用 2 TinyWebDB的使用 3 Easy IoT的使用 三 硬件连接 四 图形化代码编写
  • jdk8 免登录安装

    1 注册一大堆 麻烦死了 程序员怎么可能做被迫的事情 2 复制下载链接https www oracle com webapps redirect signon nexturl https download oracle com otn ja
  • 解析目标文件

    最近在看 程序员的自我修养 颇有体会 故化繁为简 整理书中部分内容 作为学习笔记 PC平台上流行的可执行文件格式主要是windows下的PE Portable Executable 和Linux下的ELF Executable Linkab