程序员的自我修养(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.mfbz.cn/a/37768.html

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

相关文章

【从零到Offer】反射那些事

什么是反射&#xff1f; ​ 反射简单来说&#xff0c;就是在代码运行期间&#xff0c;通过动态指定任意一个类&#xff0c;从而构建对象&#xff0c;并了解该类的成员变量和方法&#xff0c;甚至可以调用任意一个对象的属性和方法。以String对象为例子&#xff0c;传统构造方式…

计算机网络 - http协议 与 https协议(2)

前言 本篇介绍了构造http请求的的五种方式&#xff0c;简单的使用postman构造http请求&#xff0c;进一步了解https, 学习https的加密过程&#xff0c;了解对称密钥与非对称密钥对于加密是如何进行的&#xff0c;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流…

SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试【3】静态编译 invalid run

上篇 SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试【2】_hkNaruto的博客-CSDN博客 修改gcc41.cfg&#xff0c;全部添加上-static 测试指令 runspec -c gcc41.cfg -T all -n 3 -r 1 -I -i ref all 结果&#xff1a;正常运行并生成报告 invalid run Invalid SPEC CFP2006…

自学网络安全(成为黑客)

一、前言 黑客这个名字一直是伴随着互联网发展而来&#xff0c;给大家的第一印象就是很酷&#xff0c;而且技术精湛&#xff0c;在网络世界里无所不能。目前几乎所有的公司企业甚至国家相关部门都会争相高薪聘请技术精湛的黑客作为互联网机构的安全卫士&#xff0c;所以黑客也…

rapid_latex_ocr: 更快更好用的公式图像转latex工具

Rapid Latex OCR rapid_latex_ocr是一个将公式图像转为latex格式的工具。仓库中的推理代码来自修改自LaTeX-OCR&#xff0c;模型已经全部转为ONNX格式&#xff0c;并对推理代码做了精简&#xff0c;推理速度更快&#xff0c;更容易部署。仓库只有基于ONNXRuntime或者OpenVINO推…

【Linux】基础开发工具——make

文章目录 前言&#xff1a;一、认识make和makefile二、依赖关系和依赖方法三、make工作原理 前言&#xff1a; 上一期分享了在Linux下编译源代码的两个工具&#xff0c;gcc和g。每次编译源代码&#xff0c;都要输入一串很长的指令&#xff0c;这个过程显然是十分复杂&#xff…

【Go|第8期】Lorca读取HTML的三种方式

日期&#xff1a;2023年7月16日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xf…

天天刷题-->LeetCode(最长回文子串)

个人名片&#xff1a; &#x1f405;作者简介&#xff1a;一名大二在校生&#xff0c;热爱生活&#xff0c;爱好敲码&#xff01; \ &#x1f485;个人主页 &#x1f947;&#xff1a;holy-wangle ➡系列内容&#xff1a; &#x1f5bc;️ tkinter前端窗口界面创建与优化 &…

JVM内存结构——前言

前提 1. 认识JVM&#xff0c;什么是JVM 简单来说&#xff0c;就是java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 1.1 JVM &#xff08;java虚拟机&#xff09;的好处 &#xff1a; 一次编写&#xff0c;到处运行的机制 &#xff08;因为java语言是跨…

残差网络(ResNet) -深度学习(Residual Networks (ResNet) – Deep Learning)

在第一个基于cnn的架构(AlexNet)赢得ImageNet 2012比赛之后&#xff0c;每个随后的获胜架构都在深度神经网络中使用更多的层来降低错误率。这适用于较少的层数&#xff0c;但当我们增加层数时&#xff0c;深度学习中会出现一个常见的问题&#xff0c;称为消失/爆炸梯度。这会导…

可靠的手机问题修复工具分享 - 修复各种 Android 系统问题

一般来说&#xff0c;安卓手机都可以流畅运行。但不幸的是&#xff0c;有时您的Android手机可能无法正常运行&#xff0c;例如无响应、突然重启等。在这种情况下&#xff0c;您将需要Android手机维修软件。这些 Android 修复工具可以帮助您轻松解决此类问题&#xff0c;并还给您…

5.3 Python高级特性之-列表生成式、生成器、迭代器

一、 列表生成式 是Python内置的非常简单却强大的可以用来创建list的生成式 具体可根据如下案例理解&#xff0c;且代码也是可用的""" 1、 生成[0,1,2,3,4,5,6]这样列表 """ print(list(range(0, 7))) """ 2、 生成[0&#xff0…

【数据结构】树与二叉树(上)

目录 前言&#xff1a; 一、树&#xff1a; 1.树的概念&#xff1a; 2.树的相关概念&#xff1a; 3.树的表示&#xff1a; 4.书的实际使用场景&#xff1a; 二、二叉树&#xff1a; 1.二叉树的概念&#xff1a; 2.两种特殊二叉树&#xff1a; ①.满二叉树&#xff1a;…

在Vue种使用Vant框架

第一步&#xff1a;打开Vant框架地址 https://vant-contrib.gitee.io/vant/v2/#/zh-CN/home 第二步&#xff1a; 安装 第三步&#xff1a;引入&#xff08;我这里使用的是按需导入&#xff09; 执行命令&#xff1a; npm i babel-plugin-import -D ①&#xff1a;src下创建个…

Oracle解析JSON字符串

Oracle解析JSON字符串 假设某个字段存储的JSON字符串&#xff0c;我们不想查出来后通过一些常见的编程语言处理&#xff08;JSON.parse()或者是JSONObject.parseObject()等&#xff09;&#xff0c;想直接在数据库上处理&#xff0c;又该如何书写呢&#xff1f; 其实在ORACLE中…

小程序api的promise化

小程序根目录cmd运行安装命令 npm install --save miniprogram-api-promise1.0.4 安装完成之后先到根目录中删除miniprogram_npm文件夹(不删除构建npm时可能会出现问题) 删除之后再在工具中点击构建npm 构建成功之后会看到根目录中重新出现了miniprogram_npm文件夹 在app.j…

RNN LSTM

参考资料&#xff1a; 《机器学习2022》李宏毅史上最详细循环神经网络讲解&#xff08;RNN/LSTM/GRU&#xff09; - 知乎 (zhihu.com) LSTM如何来避免梯度弥散和梯度爆炸&#xff1f; - 知乎 (zhihu.com) 1 RNN 的结构 首先考虑这样一个 slot filling 问题&#xff1a; 注意…

(简单)剑指Offer 21. 调整数组顺序使奇数位于偶数前面 Java

记数组nums的长度为n。从先nums左侧开始遍历&#xff0c;如果遇到的是奇数&#xff0c;就表示这个元素已经调整完成&#xff0c;继续从左往右遍历&#xff0c;直到遇到一个偶数。然后从nums右侧开始遍历&#xff0c;如果遇到的是偶数&#xff0c;就表示这个元素已经调整完成了&…

[JVM] 1. 初步认识JVM

核心思想&#xff1a; “Write Once, Run anywhere”. 各种语言通过编译器转换成字节码文件&#xff0c;在JVM上运行。 一、Java虚拟机 Java虚拟机是一台执行Java字节码的虚拟计算机&#xff0c;它拥有独立的运行机制&#xff0c;其运行的Java字节码也未必由Java语言编译而成…

辅助驾驶功能开发-功能规范篇(27)-2-导航式巡航辅助NCA

书接上回 2.2.2.3规划控制模块 2.2.2.3.1.全局导航规划 当用户输入导航终点时&#xff0c;全局导航规划模块会根据高精地图的覆盖区域将全局导航路径分为ICA,NCA可用段。实现ICA/NCA功能的划分及自动升降级。 当自车未按照导航路径行驶时(如未使出指定匝道&#xff0c;路口未…
最新文章