ELF文件数据布局探索(1)
作为一名Linux小白,第一次看到a.out这个名字,感觉实在是奇怪,搜了一下才知道这是编译器输出的默认可执行文件名
然后vi一下,哇,各种乱码,仔细看看,发现了三个清晰的字符ELF。继续搜索, 第一感觉就是这就是windows下的*.exe
顺便看到了readelf这条命令,就读了一下这个文件,发现这里边好多东西都不懂,后来在学习linux的过程中渐渐明白了
一部分,前几天刚好跟同学说到了关于ELF文件数据布局的问题,今天总结一下(罗嗦了这么多,真是不好意思)。
今天讨论的问题是:我们在源程序中定义的变量是否会被存储在ELF中以及存放在什么地方。让我们一步一步往下看:
先抛出两个结论:
a. data段的数据存储在ELF文件中;
b. bss段的数据不存储在ELF文件中,ELF文件中的bss段只是记录bss段所需要的大小。
1. 对比代码, 下面这段代码用于对比测试:
int main( ) {
return ;
}
测试结果:
du -h a.out
.0K a.out size a.out
text data bss dec hex filename
1056 252 8 1316 524 a.out
2. 全局变量
2.1 未初始化:
int a[];
int main( ) {
return ;
}
测试结果:
du -h a.out
.0K a.out
size a.out
text data bss dec hex filename
153c a.out
可以看出,bss段的值变为了4128,正好是32 + 4096,为什么不是8 + 4096,我想应该是bss段是32字节对齐的,至于初始为什么没有对齐,留待大神解释。
那么为什么a.out的大小还是8.0K呢?大家先想一想。
2.2 初始化
int a[] = { };
int main( ) {
return ;
}
可能有同学要说了,你这只初始化了一个值吗?先往下看:
测试结果:
du -h a.out
12K a.out
size a.out
text data bss dec hex filename
153c a.out
这次bss段值没变,而数据段多了4372 - 252 = 4120,为什么不是4096,说明data段应该也是32字节对齐的。细心的同学肯定发现了,a.out的大小增加
了4K,这说明什么,说明a[1024]数据被写入了ELF文件中,也就是说data段中变量的值全部被写入到了ELF文件中。那现在想一想,为什么bss段增加了而a.out
没有增加呢,说明bss段只是记录了变量占据存储空间的大小,并没有在ELF中为变量分配存储,这里可以证明上面的两个结论是正确的。
现在回答一下上面的问题,为什么我只初始化了一个值,其实我们知道,数组是连续存放的,因此,只要初始化了一个值,其它的数据地址也就确定了。
3. 静态变量
3.1 未初始化
int main( ) {
static int a[];
return ;
}
测试结果:
du -h a.out
.0K a.out
size a.out
text data bss dec hex filename
153c a.out
bss段增加了4096 + 对齐字节,说明未经初始化的静态变量在bss段。
3.2 初始化
int main( ) {
static int a[] = { };
return ;
}
测试结果:
du -h a.out
12K a.out
size a.out
text data bss dec hex filename
153c a.out
data段增加了4096 + 对齐字节,目标文件a.out增加了4K,说明经过初始化的静态变量在data段。
4. 字符串常量
int main( ) {
char *p = "";
return ;
}
测试结果:
du -h a.out
7122 a.out
size a.out
text data bss dec hex filename
a.out
1 int main( ) {
char *p = "";
return ;
}
测试结果:
du -h a.out
.0K a.out
size a.out
text data bss dec hex filename
a.out
可以看到只有text段增加了,而且通过设置不同的长度,第二次比第一增加了10B,说明“确实”是被放在text段了。但经过进一步分析,使用readelf命令,发现实际上
"666666666666"的地址在rodata段范围内,实际上字符串常量是被存储在rodata段中的,size命令看来也是个坑啊!需要指出,rodata段的内容也是要占据ELF文件
存储的,并不仅仅只记录数据大小。
5. 局部变量
这些变量不会存储在ELF中,只有装载ELF时,才会在内存中分配,下一篇文章我会讨论这个问题。
下表是我在Linux内核版本3.2.0的测试结果:
| 变量属性 | 是否在ELF中 | 是否存储在ELF中 | 段 |
| 未经初始化的全局变量 | 是 | 否 | bss段 |
| 经过初始化的全局变量 | 是 | 是 | data段 |
| 未经初始化的静态变量 | 是 | 否 | bss段 |
| 经过初始化的静态变量 | 是 | 是 | data段 |
| 字符串常量 | 是 | 是 | rodata段 |
| 宏定义常量 | 是 | 是 | rodata段 |
| 局部变量 | 否 | 否 |
由于本人水平有限,文章中不当和错误之处不可避免,欢迎大家批评指正,愿共同进步!!!
ELF文件数据布局探索(1)的更多相关文章
- ELF文件之一——
ELF文件整体布局 下图是后来例子中main.o和main.elf的布局. 其中,只有elf header的位置是固定的,固定在文件开始,其它部分的位置都不确定. 比如下面的main.o布局中,.te ...
- ELF文件
ELF文件格式是一个开发标准,各种UNIX系统的可执行文件都采用ELF格式,它有三种不同的类型: 可重定位的目标文件 可执行文件 共享库 现在分析一下上一篇文章中经过汇编之后生成的目标文件max.o和 ...
- ELF文件解析(二):ELF header详解
上一篇讲了ELF文件的总体布局,以及section和segment的概念.按照计划,今天继续讲 ELF header. 讲新的内容之前,先更正一个错误:上一篇中讲section header tabl ...
- ELF文件解析(一):Segment和Section
ELF 是Executable and Linking Format的缩写,即可执行和可链接的格式,是Unix/Linux系统ABI (Application Binary Interface)规范的 ...
- ELF文件加载与动态链接(二)
GOT应该保存的是puts函数的绝对虚地址,这里为什么保存的却是puts@plt的第二条指令呢? 原来“解释器”将动态库载入内存后,并没有直接将函数地址更新到GOT表中,而是在函数第一次被调用时,才会 ...
- 程序运行之ELF文件的段
我们将之前的代码增加下变量来具体看下 在代码中增加了全局变量以及静态变量,还有一个简单的函数. #include <stdio.h> int global_var=1; int globa ...
- ARM 之一 ELF文件、镜像(Image)文件、可执行文件、对象文件 详解
[转]https://blog.csdn.net/ZCShouCSDN/article/details/100048461 ELF 文件规范 ELF(Executable and Linking ...
- 【DSP开发】DSP COFF 与 ELF文件
本文介绍了C6000最新的v7.2或者之后的编译器如何支持ELF(EABI)和COFF-ABI格式,首先由ARM引入嵌入式(Embedded) EABI的介绍,之后比较了COFF-ABI和EABI的区 ...
- 《操作系统真象还原》ELF文件
下面是第五章部分内容的收获. 用C语言编写内核 一直以来我们都是用汇编语言编写程序的,但接下来我们或许很少用汇编语言编写代码了,大多数都是使用C语言.为什么要这样呢?书上的解释我看的不是很懂,只能结合 ...
随机推荐
- 数组序列的capacity及size函数
#include<iostream>#include<vector>using namespace std;int main(){ vector<int> i ...
- HDU 2167 Pebbles
题目大意:有个N*N( 3<=N<=15 )方阵, 可从中若干个数, 使其总和最大.取数要求, 当某一个数被选, 其周围8个数都不能选. 题解:记s数组为合法状态,即没有相邻的数字同时被选 ...
- 《windows程序设计》学习_3.3:利用xp扫雷资源
#include<windows.h> #include "resource.h" LRESULT CALLBACK WndProc (HWND, UINT, WPAR ...
- SBT模版
/*Author:WNJXYK*/ #include<cstdio> using namespace std; ; struct SBT{ int left; int right; int ...
- opencv 简单、常用的图像处理函数(2)
opencv的项目以来配置和环境变量的配置都很简单,对于我这个没有c++基础的来说,复杂的是opencv的api和一些大部分来自国外没有翻译的资料,以及一些常见的编码问题. 资料 opencv 中文a ...
- Boost源代码学习---shared_ptr.hpp
最近观看Boost库源代码.Boost功能强大的库,但它的许多源代码,十一细读太费时间,毕竟,还有其他东西要学.所以我决定脱脂感兴趣的章节,他们的设计思路和难以理解的地方记录. shared_ptr是 ...
- API和DLL
API API(Application Programming Interface,应用编程接口)其实就是操作系统留给应用程序的一个调用接口,应用程序通过调用操作系统的 API 而使操作系统去执行应用 ...
- POJ 2142:The Balance_扩展欧几里得(多组解)
先做出两个函数的图像,然后求|x|+|y|的最小值.|x|+|y|=|x0+b/d *t |+|y0-a/d *t| 这个关于t的函数的最小值应该在t零点附近(在斜率大的那条折线的零点附近,可以观察出 ...
- Navicat Premium 11.0.x(for Mac)激活方法
激活步骤: 1.将解压后的Navicat Premium.app放入Applications(应用目录),但一定不要打开它2.彻底断网3.将keygen.app复制到桌面->右键->Get ...
- Find the k-th Smallest Element in the Union of Two Sorted Arrays
(http://leetcode.com/2011/01/find-k-th-smallest-element-in-union-of.html) Given two sorted arrays A, ...