C++开始前篇,深入编译链接(补充1)

针对这些问题,这次做一个补充:
一,可重定位文件的格式是什么,以main.o为例,
格式为ELF ,包括:{1,ELF Header
它描述了整个文件的文件属性,包括文件是否可以执行,是静态链接还是动态链接及入口地址(若是可执行 文件),目标硬件,目标操作系统等等。
2, .text(代码段) 按四字节对齐
一般C语言编译后执行语句都编译成机器代码,保存在这个段中
3, .data(数据段)
已初始化的全局变量和局部变量都保存在这个段中
4, .bss(占用虚拟内存空间的数据)
未初始化的全局变量和局部静态变量都保存在这个段中
注:.bss段只是为未初始化的全局变量和局部静态变量预留位置而已,故在文件中不占据空间 。
5, .rodata(只读数据段)
6, .comment(注释信息段)
7, .note.GNU-stack(堆栈提示段)
8, symtab(符号表段)
9, 其他段。
}
光说不练假把式,编写一个程序main.c,在Linux底下编译得到main.obj文件

用objdump -h main.o这个命令得到它的格式

其中,size表示该段的大小,File off为段所在的位置。CONTENTS、ALLOC等表示段的属性。有CONTENTS表示该段在文件中存在,但是.bss段没有,表示,.bss段在文件中不存在内容。而.note.GNU-stack的size为0,所以它在ELF文件中也不存在。
再说明一下,关于.bss段,我们可以看到它的size为4,但是它的file off(地址)却跟.rodata的file off相同,故.bss段并不占磁盘空间,它只是预留了未定义的全局变量符号(?底下会有详细说明)和未定义的局部静态变量符号,等到链接时再给它们分配内存。
详细打印一下各个段的内容:
1,text段

我们可以看到,从.text段从0x00到0x50,正好是0x51个字节。与
,中的一样。其中,最左边一行是偏移量,中间四列是十六进制内容,最右边是.text段的ASCII码形式。
反汇编结果如下。

2,.data段和.rodata段

.data段保存的是已经初始化了的全局静态变量和局部静态变量。.
.rodata段中存放的是只读数据,上面的程序中在调用printf时有个参数 '%d\n',这就是一种只读数据。还有const修饰的变量等等。
.data段中,前四个字节从低到高为(小端存储):0x63,0x00,0x00,0x00。转化为10进制正好为99(全局初始化global_init)。同理,后四位为1(局部静态初始化static_init)。
OK,现在已经把主要的几个段了解了,现在来学习一下关于ELF的文件结构
来张图说明

其中,关于ELF header前面已经介绍了,包含着整个文件的基本属性;紧接着是ELF各个段,其中ELF文件中与段相关的重要结构就是section header table(段表),什么是段表呢,它描述了ELF文件包含的所有段的信息!比如每个段的段名,长度,在文件中的偏移读写权限等等其他属性。再接着就是字符串表,符号表等等。接下来详细的介绍一下段表。
用readelf -S 来查看详细的段表结构

我们可以看到,段表其实就是一个一维数组,数组元素的个数等于段的个数,但是第一个是NULL的,所以main.o总共有10个有效的段。
关于段表,最重要是两个,一个是段的类型(Type),一个是段的标志位(Flags),他们决定了段的属性。
段的类型分为无效段,程序段(代码段,数据段都是这种类型)或者符号表等等。
段的标志位表示该段在进程虚拟地址空间中的属性,比如是否可写,是否可执行等等。
在.text段下有一个.rel.text段,这个.rel.text段即就是重定位表。此时先提出了,当谈到链接的时候再解答。
-------------------------------------------------------------------------------------------------------------------------------------
OK,此时已经把第一个问题算是解答完毕了,接下来继续解答剩下的两个问题。
-------------------------------------------------------------------------------------------------------------------------------------
二,可执行文件的格式
可执行文件是什么格式呢?上图
这是可执行文件main中的段,


可见,可执行文件也是由很多段组成的,在mian.o的基础上多了更多的段。因此,可执行文件之所以可以运行,肯定与链接之后多出来的这些段有关系。这些都是些什么东东呢,在深入链接之前,我们先解决第三个问题。
程序要运行,需要三步。
第一,需创建虚拟地址空间到物理内存的映射(创建内核地址映射结构体),创建页目录和页表。
第二,加载代码段和数据段。
第三,把可执行文件的入口地址写到cpu的pc寄存器中。
所以为什么可执行文件可以运行而可重定位文件不可运行的问题可以得到解决,
1,.obj中无符号地址,.exe中有符号地址。因为编译环节并不为符号分配地址,故没有内存,数据的地址都统一的0地址。而链接之后为符号分配了内存地址。
2,.obj中无函数入口地址,.exe中有函数入口地址。我们知道程序要运行就必须知道函数入口地址。
3,.exe中有链接之后一个”特殊段“,跟页表有关。
然而这些答案依然让人难以理解透彻,比如说,链接之后究竟产生了什么新东西,函数入口地址又是如何产生的,.exe中的跟页表有关的段到底是什么。。。ok,这些东西都会得到解答。
接下来,我们更加深入到静态链接中去。
C++开始前篇,深入编译链接(补充1)的更多相关文章
- C++开始前篇,深入编译链接(3)
一,COMMON块 什么是COMMON块,这是一种机制,早期的Fortran没有动态分配空间的机制,程序员必须事先声明它所需要的临时使用空间的大小.Fortran把这种空间叫做COMMON块,当不同的 ...
- C++开始前篇,深入编译链接
C++开始,为什么要写这个东西,因为按照课堂进度的话,现在的C++已经学到模板以及重载了,有时却仍然因为一些小问题无法解答,原因是忘记了开始时学到的知识,深知不能像猴子掰棒子一样,掰一个扔一个,因此, ...
- linux 编译,链接和加载
1. 序 最近在折腾各种.so,碰到了一些问题,一开始对于很多错误也没有头绪,茫然不知所措.索性化了一天多时间将<<程序员的自我修养—链接.装载与库>>中部分内容略读了一遍 ...
- 【原创】构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施
原文:[原创]构建高性能ASP.NET站点 第六章-性能瓶颈诊断与初步调优(下前篇)-简单的优化措施 构建高性能ASP.NET站点 第六章—性能瓶颈诊断与初步调优(下前篇)—简单的优化措施 前言:本篇 ...
- webpack2 前篇
webpack2 前篇 #webpack 前两天用了一天半时间琢磨了下webpack2,想起去年这时候,面对webpack1那样恶心的文档,前前后后搞了好几次才摸索清楚,那真是吐了. 划重点 其实we ...
- 【C编程基础】C编译链接命令gccc
1.gcc安装 rpm -qa|grep gcc ==>检查gcc是否安装 gcc -v ==>检查gcc版本 yum -y install gcc ==>安装gcc 2.基本语法 ...
- G++编译链接的那些事
语言 CPP 前言 虽然 VSCodeC++ 编辑器非常受大家的欢迎,无论是大佬还是小白都说对其爱不释手... 我...用了一段时间后发现实在是麻烦,配置往往花费我大量时间.可以说真的是吃力不 ...
- 【原创】Linux下编译链接中常见问题总结
前言 一直以来对Linux下编译链接产生的问题没有好好重视起来,出现问题就度娘一下,很多时候的确是在搜索帮助下解决了BUG,但由于对原因不求甚解,没有细细研究,结果总是在遇到在BUG时弄得手忙脚乱得. ...
- 关于tcc、tlink的编译链接机制的研究
1.学习过程 在c:\下建立文件夹c,并将编译器tcc.exe.连接器tlink.exe.相关文件c0s.obj.cs.lib.emu.lib.maths.lib放入文件夹中. 要搭建一个简单的C语言 ...
- ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇
原文:ASP.NET自定义控件组件开发 第三章 为控件添加事件 前篇 第三章 为控件添加事件 好了,我们之前以前开发一个控件.而且也添加了属性,开发也很规范,但是那个控件还差最后一点:添加事件. 系列 ...
随机推荐
- MYSQL索引结构原理、性能分析与优化
[转]MYSQL索引结构原理.性能分析与优化 第一部分:基础知识 索引 官方介绍索引是帮助MySQL高效获取数据的数据结构.笔者理解索引相当于一本书的目录,通过目录就知道要的资料在哪里, 不用一页一页 ...
- PowerShell自动部署IIS站点(Windows Server 2008 R2)
1.功能描述 1. 连接软件源服务器下载.NET Framework 4.0..NET Framework 4.5. 2. 检测并判断当前.NET Framework版本是否小于v4.0,如果小于则进 ...
- Markdown与标记语言
Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的语法十分简单.常用的标记符号也不 ...
- SNMP协议以及著名的MIB详解
SNMP协议介绍 简单网络管理协议(SNMP:Simple Network Management Protocol)是由互联网工程任务组(IETF:Internet Engineering Task ...
- UML大战需求与分析--阅读笔记4
今天阅读了UML大战需求与分析第五.六章. 第五章,状态机图(State Machine Diagram),状态机图是通过描述某事物状态的改变来展现流程的.一般适用于流程围绕某个事物展开,例如请假的流 ...
- Django基础,Day5 - form表单投票详解
投票URL polls/urls.py: # ex: /polls/5/vote/ url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, ...
- eclipse自动补全的设置
eclipse自动补全的设置 如果你用过Visual Studio的自动补全功能后,再来用eclipse的自动补全功能,相信大家会有些许失望. 但是eclipse其实是非常强大的,eclipse的 ...
- fedora配置163为yum的源
一种方法: 1.下载 http://mirrors.163.com/.help/fedora-163.repo 和 http://mirrors.163.com/.help/fedora-updat ...
- jcFeather Maya 羽毛插件
jcFeather 2.8.6 插件持续更新地址为:http://www.jerrykon.com/jcFeather.html 和 http://www.creativecrash.com/maya ...
- 【bzoj1708】[USACO2007 Oct]Money奶牛的硬币
题目描述 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统的货币系统中,硬币的面值通常是1,5,10,20或25,50,以及100单位的 ...