linux 内核重定位,Linux 内核学习笔记:预备知识之“目标文件”

66b52468c121889b900d4956032f1009.png

8种机械键盘轴体对比

本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?

本文主要阐述 Linux 的目标文件(有可重定位目标文件、可执行目标文件和共享目标文件三种形式),并把重点放在其格式和案例分析上。

注:一般情况下,我们说的目标文件专指可重定位目标文件,而可执行文件专指可执行目标文件,但在本文中,为了使概念更加清晰,我们会使用这两种文件的全称。

按照《程序员的自我修养——链接、装载与库》一书第 3.1 节的说法,从广义上看,目标文件与可执行文件的格式几乎是一模一样的,所以我们可以广义地将目标文件与可执行文件看成是一种类型的文件。

即把它们统称为 ELF(Executable Linkable Format)文件。

实际上,可重定位目标文件跟可执行目标文件还是有区别的。目标文件有三种形式:可重定位目标文件(.o文件),包含二进制代码和数据,其形式可以在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件;

可执行目标文件包含二进制代码和数据,其形式可以被直接拷贝到存储器并执行。

[仅为完整性,本文不阐述]共享目标文件是一种特殊类型的可重定位目标文件,可以在加载或者运行时被动态地加载到存储器并链接。

我们先来看一下可重定位目标文件和可执行目标文件生成的过程。

可重定位目标文件和可执行目标文件生成的过程

源文件经过以下几步生成可重定位目标文件和可执行目标文件:预处理(preprocessor):对 #include、#define、#ifdef/#endif、#ifndef/#endif 等宏进行处理

编译(compiler):将源码编译为汇编代码

汇编(assembler):将汇编代码汇编为可重定位目标代码(文件)

链接(linker):将可重定位目标代码链接为可执行目标文件

整个过程可用图表示如下:

1352c3c5b3965efeb793cfa97154def8.png图片来源

接下来,我们分开对可重定位目标文件与可执行目标文件进行阐述。《深入理解计算机系统》一书第 7 章“链接”和《程序员的自我修养——链接、装载与库》一书第 3 章“目标文件里有什么”将作为主要参考资料。

可重定位目标文件

可重定位目标文件格式

可重定位目标文件的典型格式如下图所示:

90f367e784d294879c4fdc77433a02da.png图片来源:《深入理解计算机系统》

其中,ELF Header: 包含了描述整个文件的基本属性,如 ELF 文件版本、目标机器型号、程序入口地址等。

.text:已编译程序机器(二进制)代码。

.rodata:只读数据,如 printf 语句中的格式串和开关语句的跳转表。

.data:已初始化的全局(静态)变量或静态变量。但如果我们对全局变量或静态变量赋值为 0,那它会被放到 .bss 段。 (注意全局变量和全局静态变量的区别:作用域。)

.bss:未初始化的全局变量或静态变量。该段不占用可重定位目标文件的实际空间,但当它被加载到内存中时,该段内的变量是要占用内存的。

.symtab:一个符号表,它存放在程序中定义和使用的函数和全局变量的信息,但不包含局部变量的条目。

.rel.text:一个 .text 节中位置的列表,当链接器把这个可重定位文件和其他文件结合时,需要修改这些位置。一般而言,任何调用外部函数或者引用全局变量的指令都需要修改。另一方面,调用本地函数的指令不用修改。注意,可执行目标文件中并不需要重定位信息,因此通常省略,除非用户显式地指示链接器包含这些信息。

.ret.data:被模块引用或定义的任何全局变量的重定位信息。一般而言,任何已初始化的全局变量,如果它的初始值是一个全局变量地址或者外部定义函数的地址,都需要被修改。

.debug:一个调试符号表,其条目是程序中定义的局部变量和类型定义、程序中定义和引用的全局变量,以及原始的 C/C++ 源文件。只有以 -g 选项调用编译驱动程序时才会得到这个表。

.line:原始 C/C++ 源程序中的行号和 .text 节中机器指令之间的映射。只有以 -g 选项调用编译驱动程序时才会得到这个表。

.strtab:一个字符串表,其内容包括 .symtab 和 .debug 节中的符号表,以及节头部中的节名字。字符串表就是以 null 结尾的字符串序列。

Section Header Table:描述了 ELF 文件包含的所有段的信息,如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。

案例分析

接下来,我们利用《程序员的自我修养——链接、装载与库》一书第 3 章提供的一个样例来分析下这些段。

编译样例

样例如下:1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30> File Name: SimpleSection.c

> Compile on Linux:

gcc -c SimpleSection.c

> Compile on Windows:

cl SimpleSection.c /c /Za

*************************************/

int (cont char* format, ...);

int global_init_var = 84;// .data

int global_uninit_var;// .bss

void func(int i)

{

printf("%dn", i);

}

int main()

{

static int static_init_var = 85; // .data

static int static_uninit_var; // .bss

int a = 1;// Stack

int b;// Stack

func(static_init_var + static_uninit_var + a + b);

return 0;

}

编译该程序可得可重定位目标文件 SimpleSection.o:1$ gcc -c SimpleSection.c

查看 ELF Header

我们可以查看该目标文件的 ELF Header:1$ readelf -h SimpleSection.o

并得到如下结果:

41a29afb1f6b037b73b5d0810085c388.png

我们可以看到,ELF Header 定义了诸多该目标文件的属性。关于各个属性详细信息请参考《程序员的自我修养——链接、装载与库》一书第 3.4.1 节“文件头”。

查看 Section Header Table

我们还可以继续查看一下该目标文件的 Section Header Table:1$ readelf -S SimpleSection.o

并得到如下结果:

2c7d08083dc2b72250db7feb183a6b8b.png

结合该图和上边关于 ELF Header 的图,我们可以将 SimpleSection.o 的 Section Header Table 及所有段的位置和长度画出来:

3a59bb5c794619c2db267e085add183d.png

正如我们在前边提到的,Section Header Table 描述了 ELF 文件包含的所有段的信息,如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。具体地,它是利用了Elf32_Shdr (也称为段描述符)这样一个结构体来描述每一段的属性,该结构体长度为 40 个字节。在 SimpleSection.o 文件中总共有 13 个段,也就需要 13 个Elf32_Shdr来描述它们,总共长度为 13 * 40 = 0x208 个字节。另外,Section Header Table 的第一个元素是无效的Elf32_Shdr,它的类型为 NULL。

整个 SimpleSection.o 文件的长度为 1336 个字节,这跟我们用du命令查看的结果是一致的:

587a0c46989a6f5592b0792e5d55ac63.png

关于 Section Header Table 详细信息请参考《程序员的自我修养——链接、装载与库》一书第 3.4.2 节“段表”。

可执行目标文件

可执行目标文件格式

可执行目标文件的典型格式如下图所示:

4a298c312725ff10f3a485538f5aa75f.png图片来源:《深入理解计算机系统》

案例分析

我们还接着可重定位文件的例子继续分析。

静态链接

我们先将 SimpleSection.o 文件静态链接成可执行文件 SimpleSection.static:1$ gcc -static SimpleSection.o -o SimpleSection.static

再查看下 SimpleSection.static 文件的 Section Header Table:1$ readelf -S SimpleSection.static

并得到如下结果:

d5c44e2e41c073689704322c03375c7c.png

具体分析过程跟“可重定位目标文件”部分相同。

动态链接

我们先将 SimpleSection.o 文件动态链接成可执行文件 SimpleSection.dynamic:1$ gcc SimpleSection.o -o SimpleSection.dynamic

再查看下 SimpleSection.dynamic 文件的 Section Header Table:1$ readelf -S SimpleSection.dynamic

并得到如下结果:

fdd5ea96d14b8a12b0f3de513a47e92a.png

重定位段信息

值得注意的是上图(动态链接)中的两个属性为重定位表的段.rel.dyn和.rel.plt。它们跟.rel.text或.rel.data并不一样。

我们先用readelf -r命令来查看一下可重定位目标文件和可执行目标文件中的可重定位段的区别:可重定位目标文件1$ readelf -r SimpleSection.o

并得到结果如下:

5b383513eb76a247e34d2a5c87109429.png可执行目标文件1$ readelf -r SimpleSection.dynamic

并得到结果如下:

7b144bc9e687e5af02eeb64b1461bc65.png

比较上边两图,我们(从Offset属性)可以知道:.rel.text属于普通重定位段,由编译器编译产生,存在于可重定位目标文件内;用于最终可执行目标文件或者动态库的重定位。

.rel.dyn和.rel.plt属于动态重定位段,由链接器产生,存在于可执行目标文件或者动态库内;借助这两个段可动态修改对应的.got和.got.plt段,从而实现运行时重定位。.rel.dyn对应.got段;.rel.plt对应.got.plt。

后记

本来的打算是先阐述目标文件,再说明如何将可执行文件加载到进程虚拟地址空间,从而达到叙述虚拟地址空间的目的。很明显,我失误了。光是目标文件这么少的知识点我都要写这么长的博文,再加上加载和虚拟地址空间,可以预计博文将会很长。那时,不但读者受不了,自己也受不了…所以还是将大的主题继续拆分。关于加载和虚拟地址空间请见下一博文。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux虚拟内存api,Linux虚拟内存空间分布-Go语言中文社区

平常总说cpu的位数,其实说的是cpu一次能运算的最长整数的宽度,既ALU(算术逻辑单元)的宽度。cpu的位数也是数据总线的条数数据总线:数据线的总和,数据线就是cpu与内存进行数据传递的通道,一条数据线,一次可以…

2019 d serv 激活_化疗过程中肌肉减少症的发生机制及维生素D、ω-3脂肪酸的作用...

文章来源:蔡丽雅,赵文芝,杨振鹏,贺源,邓丽,张艳,石汉平.肿瘤化疗过程中肌肉减少症的发生机制及维生素D、ω-3脂肪酸的作用[J].中国医学前沿杂志(电子版),2020,12(1):13-19.正 文1998年,Baumgartner等【1】首次提出“肌肉减少症”的概念,用以描…

电脑鸿蒙运行Linux程序,Linux下的Hi3861一站式鸿蒙开发烧录(附工具)-鸿蒙开发烧录工具软件电脑版-东坡下载...

HarmonyOS 智能设备一站式集成开发环境,支持 HarmonyOS 组件按需定制、一键编译和烧录、可视化调试、分布式能力集成等,帮助开发者高效开发和创新新硬件。介绍2021春节前夕,华为发布了 HUAWEI DevEco Device Tool 2.0 Beta1,整体提…

终端软件_DMSTerminal现场管控终端软件正式发布

目前军工企业的信息化建设及管理大多停留在企业内部的管理层,各种任务信息、作业流程等无法直接下达到真正的一线现场层,导致工作在一线的大量技术人员仍然使用传统的纸质工单、纸质记录、口头交流等工作模式进行现场工作。很多工作模式普遍都是以人力来…

深度残差网络_注意力机制+软阈值化=深度残差收缩网络

顾名思义,深度残差收缩网络是由“残差网络”和“收缩”两部分所组成的,是在“残差网络”基础上的一种改进算法。其中,残差网络在2016年斩获了ImageNet图像识别竞赛的冠军,目前已经成为了深度学习领域的基础网络;收缩就…

linux 网络io命令详解,Linux下五种网络IO模型详解

本文我们主要来了解一下Unix/Linux下5种网络IO模型:blocking IO, nonblocking IO, IO multiplexing, signal driven IO, asynchronous IO的基本原理,更好的理解在高级语言中的异步编程,一起来看看吧,希望对大家学习linux有所帮助。…

安卓与Linux共存,Android和Linux重新合并成一个操作系统

Linux又回到了Android中,Android又回到了Linux中。Android一直都是Linux,但多年来Android项目走了自己的路,它的代码没有被合并回主Linux树中。现在,比Linux的创始人和主要开发人员Linux的预期要快得多,Android已经正式…

edit控件自动换行 mfc_VS2010/MFC编程入门:如何创建对话框模板和修改对话框属性?...

创建对话框主要分两大步,第一,创建对话框资源,主要包括创建新的对话框模板、设置对话框属性和为对话框添加各种控件;第二,生成对话框类,主要包括新建对话框类、添加控件变量和控件的消息处理函数等。在本节…

linux vim tag,Vim基础知识之ctags 及 Taglist 插件

Vim基础知识之ctags 及 Taglist 插件1. 我的界面2. ctagsexuberant ctags是一般Linux系统上缺省的ctags我的ctags版本:Exuberant Ctags 5.9~svn20110310简单介绍Used in at least 50 countries in all 7 continents (including Antarctica!)Supports 41 programming…

c语言程序设计整人,C语言进程间通信练习作品 - 整人小程序之剪切板

主程序界面:程序介绍:如果对方执行了主程序生成的【server.exe】,【server.exe】会自复制、自启动、自删除(仿木马)。【server.exe】会后台每秒/次检测对方的剪切板,一有文本数据则在尾部加入【附加内容】,达到&#x…

Android怎么自定义充电铃声,安卓手机怎么自定义充电提示音_自定义安卓充电提示音教程_3DM手游...

安卓手机其实也是可以设置充电提示音的,我们只需要下载一个第三方软件,然后在APP中进行一些简单的设置,就可以实现自定义更换手机充电提示音了。安卓手机怎么自定义充电提示音?下面小编就为大家带来了详细的教程,希望能…

android logcat 根据包名过滤,adb logcat通过包名过滤(dos命令find后跟变量)

过滤条件:该app在运行实现原理:1、获取该app运行时的pid2、通过find命令,过滤pid的日志,就是该包的运行日志实现:1、在同一目录建立一文件:getpid.batecho offadb shell "ps | grep com.example.testp…

android 最新的框架搭建,Android之Mvp模式框架搭建

前言在做Android开发时,我们通常为了更合理,更高效,优质的开发项目,并不是直接上来就开始开发功能,而是先搭建好自己的一个开发框架,一个好的开发框架,通常会让我们事倍功半,它就好比我们去建造一个房子,如果你的地基打的越深,越牢固,那么就可以建造出很高很大的房子.在搭建一个…

英特尔nuc能代替主机吗_python编程,热度为什么越来越高,python能代替JAVA吗?...

大家好,我是你们的软件主讲老师宁彤天,python编程是这几年刚火起来了,这可能是这几年人工智能的普及吧,现在是人工智能非python,没有第二,当能其它语言也能实现人工智能,但python的代码量能用最…

mix2s 升级android p,小米推送小米MIX2S 安卓P稳定版更新 这两个隐藏升级你发现了吗?...

原标题:小米推送小米MIX2S 安卓P稳定版更新 这两个隐藏升级你发现了吗?今天上午,小米推送了小米MIX2S的稳定版更新,版本号为MIUI V10.0.4.0,体积为2GB,这一次更新将系统底层更新至了Android P,不…

python求出五位数的回文数_python之递归

#codingutf-8#题目:打印出如下图案(菱形)nu 1 # 开始值k 2 # 变量值while nu > 0:print(int((7 - nu) / 2) * * * nu)nu kif nu 7:k -k#题目:有一分数序列:2/1 ,3/2 ,5/3 ,8/5 ,1…

html正则判断全数字,javascript如何判断是不是数字?

javascript判断是不是数字的方法:方法一、使用js自带的全局函数isNaN()判断是不是数字。方法二、使用正则表达式判断是不是数字。方法三、通过typeof的返回值判断。JavaScript中判断是不是数字方法详解:第一种方法:isNaN()使用js自带全局函数…

law是什么的缩写_Lawyer和Attorney 有什么不同?

据美国劳工统计局(Bureau of Labor Statistics)预计,2016年至2026年间,律师的就业增长率为8.2%。在此期间,预计将新增6.5万个就业岗位。而且美国律师行业的,律师行业在US.NEWS 的Best Social Services Jobs中排名第一,…

选择座位html,影厅座位预览效果(css3)_html/css_WEB-ITnose

查看 demo 下载源码你可能对那些购买时需要选择座位的订票系统比较熟悉。通常在比赛,电影,搏击或者演唱会售票的时候需要这样做。如果能有一种座位的预览效果该有多酷啊,比如能够从你选择的位置的角度去预览舞台或者屏幕。这个问题引出了今天…

html 使用百度搜索,百度搜索uzer,进入主页

windows7的uzer.me怎么 安全上网百度搜索uzer,进入主页下载完成以后,点击,快捷方式,运行。登陆后,首先出现的是文档库,点击文档库。UZER上的软件和文件都打不开,网络没问题。因为安装的软件版本…