程序员的自我修养(2)

目标文件的学习

1.什么是目标文件以及格式
目标文件为编译器编译后生成的文件,就是window下的.obj,linux下的.o文件。与可执行文件格式几乎一样,因为只是缺少链接过程。所以可执行文件,动态链接库,静态链接库,目标文件广义上都可以算是一个格式,即可执行文件的格式
2.目标文件是怎么样的
目标文件很明显包含编译后的机器指令代码,数据,还包含了链接需要的符号表,调试信息,字符串等等。我们通常以段分隔。
代码段(.code .text):机器指令
数据段(.data):全局变量和局部静态变量
bss段(.bss):未初始化的全局变量和局部静态变量

还有一个部分,文件头
描述整个文件的文件属性,是否可以执行,是静态还是动态链接,目标硬件,目标操作系统等信息。还包括一个段表,描述各个段的数组,各个段在文件中的偏移地址以及段的属性。(这里的段就是指的是代码,数据,bss等段)
(目标文件通常是ELF结构)
3.为什么目标文件需要分段
1.将代码与数据分开,数据和代码被映射到不同的虚拟内存中,可以给其设置不同的权限,保护代码段指令不被修改。
2.缓存在现代计算机地位非常重要,分段能提高缓存的命中概率。
3.增加了存储空间利用率,共享数据。能将系统中运行多个同样的程序只用保存一份指令,数据能够共享。window系统中超过一半是共享部分。
4.以一个程序来讲解各段细节
程序
simply.c

#include<stdio.h>
int global_init_var = 84;
int global_uninit_var;void func1(int i)
{printf("%d\n", i );
}
int main()
{static int static_var = 85;static int static_var2;int a = 1;int b;func1(static_var+static_var2+a+b);return a;
}

经过gcc -c simply.c 得到simply.o
通过objdump工具可以查看.o文件的内容结构

objdump -h simply.o

得到内容(参数-h是将elf文件各个段基本信息打印),很明显分成了.text,.data,.bss,.rodata,.comment,.note.GNU-stack等段,分别为代码,数据,bss,只读数据,注释信息,堆栈提示段。
size为大小,file off起始位置这两行最为重要的信息。,每个段底下的第二行表示段的属性,CONTENTS表示该段在文件中存在等等。
那么实际存在的段为.text,.data,.rodata,.comment(.note段存在但是大小为0)
请添加图片描述
size命令可以获取各个段的大小

size simply.o

其中dec3个段长度的十进制,hex16进制
请添加图片描述

5.代码段
以上面程序为例子
-s将所有段的内容以16进制打印。-d将所有包含指命的段反汇编

objdump -s -d 

结果可以很明显的看出反汇编的结构.text包含的正是funch1和main函数的指令
请添加图片描述
6.数据段与只读数据段
.data段保存的是那些已经初始化的全局变量和局部静态变量
根据程序可以知道为global_init_var与static_var。两个变量都为int类型,故共8个字节。
.rodata存放只读数据,例如printf函数中的%d\n是一种只读数据,就是const修饰的和字符串常量。
由下图.data区内容0x54与0x55刚好对应84与85,就是上面两个变量的值
.rodata区中的25640a00对应ascil表就是%d\n
(注意是16进制,然后我用的是ubunte系统为小端模式)
请添加图片描述
7.bss段
bss段放置的是位初始化的全局变量和静态局部变量
上面程序代码中static_var2与global_uninit_var就是
这里不做多解释,通常c语言有一个步骤叫bss段清零,所以放入bss段的变量初值都是0,如果定义全局变量或静态局部变量值=0,同样放入bss段。
8.其它的段
除了.text,.data,.rodata,.bss这些常见的段,还有一些比较特殊的段,还有被遗弃(不使用了)的段
.comment 编译器版本信息
.debug 调试信息
.dynamic 动态链接信息
.hash 符号哈希表
.line 调试的行号表O
.note 额外的编译器信息
.strtab 存储elf结构用到的各种字符串
.symtab 符号表
.shstrtab 段名表
.plt .got 动态链接的跳转表和全局入口表
.init.fini 程序初始化和终结代码段
这些段都是.开头的,我们也可以自定义段,例如定义music段存放音乐信息,但是不能以.开头
9.ELF文件结构描述
上面我们已经讲了各个段的作用,接下来讲述这些段在ELF怎么放置,还有ELF结构还有那些内容
1.整体结构
ELF Header
.text
.data
.bss

other sections
section header table (段表)
string tables
symbol tables
首先是文件头,描述了整个文件的基本属性,如elf文件版本号,目标机器型号,程序入口地址等。
然后接下来是各个段的内容,其中与段有关的重要结构体就是段表,该表描述了所有段的信息,例如段命,长度,文件偏移,读写权限等
10.段表
我们之前使用的命令只是打印重要的段,例如.text,.data等等
我们现在使用这个命令将会打印段表的信息,即打印所有段的信息

readelf -S   simply.c    

结果
请添加图片描述
由图可以知道,该程序总共10个段,
段表描述了段的信息有10个重要信息
sh_name
段命
sh_type
段的类型
sh_flags
段的标志位
sh_addr
段虚拟地址
sh_offset
段偏移
sh_size
段大小
sh_link
段的链接信息
sh_info
段的链接信息
sh_addralign
段对齐长度
sh_entsize
项的长度
10.重定位表
就是目标程序中有哪些部位需要重定位,就是代码段和数据段内需要重定位的函数或变量
这些重定位信息都记录在.rel.text或.rel.data内
由于我们的程序变量都是存在该程序内,所以没有.rel.data段
但是我们使用了printf函数,是需要在链接的时候重定位的,故存在.rel.text段
(为什么需要重定位,因为一些函数或变量就不存在在主程序中,绝对地址无法调用,需要调用其它.h或.c文件内的变量和函数,我们就需要其定位到正确的位置,去调用,才能正常使用。
11.字符串表
为什么需要字符串表,因为ELF结构里面有太多的字符串变量了,段命,变量名等等,而且大小不定,难以定义,我们可以直接定义一块大的空间,只用给下标,遇到\0就放回字符串,将普通的字符串通通保存,只有给下标直接可以访问。
12.链接的接口-符号
链接的本质就是将多个目标文件之间互相粘到一起,合为一个整体,能够互相使用对方需要的函数与变量,功能模块等。
按正常思考,我们要用一个函数和变量,底层该如何去找到,肯定是要靠地址。无法使用,肯定就是地址不对或没有该函数的地址,故其实本质上就是目标文件之间地址的引用,我找不到,我就问你要,因为你有这个函数或变量的地址。
我们将函数和变量称为符号,函数名与变量名称为符号名。故为什么需要引用的函数和变量一定不能重名,否则报错,就是因为符号重名会导致链接混乱。(这里要注意C++有其特殊性,函数重载,函数可以重名,但参数不能相同)
最后我们每一个目标文件都有符号表,记录了目标文件中使用到的所有符号,每个符号有一个符号值,就是符号的地址,也就是函数或变量的地址。
(我们最关心的是全局符号,因为这些符号最有可能被其它目标文件使用)
13.符号重复的问题
由于C语音和C++语言非常的庞大,我们可能定义一个函数就会导致符号重复,故为了防止重定义,C语言规定了定义一个函数或变量后,都在其前面加‘_’,形成新的符号名,这样就可以简单而原始的解决用户与C库的符号冲突。但程序一但很大,仍然有很大可能重复,故C++考虑到了这个问题,增加名称空间的方法来解决。
上面讲到了函数重载,还有一个情况就是不同类可以有同名同参数函数。
处理其实很简单,函数和变量会根据所处的类和返回值,函数参数不同会先生成一个函数签名,很容易知道,不同的类,函数签名肯定不同,在经过修饰,那么修饰后的符号肯定是不同的,在符号表肯定不会冲突的。

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

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

相关文章

mac批量提取文件夹的名称,怎么操作?

mac批量提取文件夹的名称&#xff0c;怎么操作&#xff1f;很多小伙伴想知道在mac电脑上可以一键快速批量的将大量文件夹的名提取出来&#xff0c;而不是采用一个一个名称提取的方法&#xff0c;这是一个有利于提高工作效率的办法&#xff0c;这一项技能在网上几乎找不到解决办…

k210学习篇(一)环境搭建

一、为什么选择Canmv开发板? 便宜!便宜!便宜!淘宝200即可买到一个能带摄像头和LCD屏等等的开发板 二、利用Maix Hub在线训练 Maix Hub官网https://maixhub.com/home Maix Hub使用教程:K210学习笔记——MaixHub在线训练模型(新版) 注意: 三、配置开发环境 1.MaixPy IDE…

transformer 学习

原理学习: (3条消息) The Illustrated Transformer【译】_于建民的博客-CSDN博客 代码学习: https://github.com/jadore801120/attention-is-all-you-need-pytorch/tree/master/transformer mask学习: (3条消息) NLP 中的Mask全解_mask在自然语言处理代表什么_郝伟博士的…

基于深度学习的高精度安全帽及背心检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度安全帽及背心检测识别系统可用于日常生活中或野外来检测与定位安全帽及背心目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的安全帽及背心目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系…

Azure AD混合部署,实现在本地AD同步到AAD上面

一、前期准备 1、进入 Azure云 注册一个账号 2、进入 AAD 管理后台 3、创建一个新的租户 &#xff08;1&#xff09;打开管理租户 &#xff08;2&#xff09;创建 &#xff08;3&#xff09;选择类型 &#xff08;4&#xff09;配置目录名 "xielong" 4、切换目录&…

6.2.8 网络基本服务----万维网(www)

6.2.8 网络基本服务----万维网&#xff08;www&#xff09; 万维网即www&#xff08;World Wide Web&#xff09;是开源的信息空间&#xff0c;使用URL也就是统一资源标识符标识文档和Web资源&#xff0c;使用超文本链接互相连接资源&#xff0c;万维网并非某种特殊的计算机网…

SpringCloud分布式搜索引擎、数据聚合、ES和MQ的结合使用、ES集群的问题

目录 数据聚合 聚合的分类 ​编辑 DSL实现Bucket聚合 ​编辑 DSL实现Metrics聚合​编辑 RestAPI实现聚合 对接前端接口​编辑 自定义分词器​编辑 Completion suggester查询 Completion suggester查询 酒店数据自动补全 实现酒店搜索框界面输入框的自动补全 数据同步问…

ASO优化之在海外如何进行竞品分析

进行竞争对手研究&#xff0c;需要分析当前的市场形势&#xff0c;确定竞争对手表现的模式&#xff0c;并将其应用到我们应用营销策略中。不同的应用可以在直观的用户界面上进行简单的比较&#xff0c;很容易看到长期趋势。 在App Store和Google Play上获取竞争对手评论区的信…

怎么用PDF派工具将Word转成PDF

Word是我们最常用的一种格式文件&#xff0c;它易于编辑&#xff0c;但是安全性和稳定性较差&#xff0c;有时候我们发送给别人的Word文件&#xff0c;接收到打开内容已经乱码。遇到这种情况&#xff0c;我们可以优先将Word文件转换成稳定性好的PDF文件。那么如何进行文件格式转…

opencv 基础学习08-图像通道操作

opencv 基础学习08-图像通道操作 什么是图像通道&#xff1f;通道操作&#xff1a;**1 通过索引拆分**2 通过opencv 函数拆分通道合并 什么是图像通道&#xff1f; OpenCV的通道拆分功能可用于将多通道图像拆分成单独的通道&#xff0c;这在图像处理和计算机视觉任务中具有许多…

7月6日华为云盘古气象大模型登上《Nature》杂志:相比传统数值预报快10000倍

7月6日&#xff0c;国际顶级学术期刊《自然》&#xff08;Nature&#xff09;杂志正刊发表了华为云盘古大模型研发团队的最新研究成果——《三维神经网络用于精准中期全球天气预报》&#xff08;《Accurate medium-range global weather forecasting with 3D neural networks》…

解析!1V1直播源码开发搭建技术实时语音识别翻译功能的应用

语言是我们人类交流的工具&#xff0c;它的种类繁多&#xff0c;比如世界语言&#xff0c;像是中国的汉语、英国的英语、法国的法语等&#xff1b;又或是我们中国的方言&#xff0c;像是山东话、北京话、上海话等。可谓是五花八门&#xff0c;争奇斗艳&#xff0c;每一种世界语…