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语言.为什么要这样呢?书上的解释我看的不是很懂,只能结合 ...
随机推荐
- JAVA并发,同步锁性能测试
测试主要从运行时间差来体现,数据量越大,时间差越明显,例子如下: package com.xt.thinks21_2; /** * 同步锁性能测试 * * @author Administrator ...
- 看日记学git摘要~灰常用心的教程
看日记学git linux 命令行 cd ls / ls -a clear mkdir rmdir echo "hi, good day" > hi.txt touch he ...
- win7使用的一些误区以及困惑
总结了一些新人在使用win7时容易产生的误区和困惑,罗列出来说明一下,以便新人能尽快适应新的操作系统. 1.内存使用的问题:这是个大误区,很多人都用xp时代的眼光来审视win7,这是错误的,因为两者的 ...
- Android-设置PullToRefresh下拉刷新样式
以下是开源控件PullToRefresh的自定义样式属性: <?xml version="1.0" encoding="utf-8"?> <r ...
- Codeforces 700A As Fast As Possible(二分答案)
[题目链接] http://codeforces.com/problemset/problem/700/A [题目大意] 有一辆限载k人速度为v2的车,n个步行速度均为v1的人要通过一段长度为l的距离 ...
- EGit with eclipse to clone project from GitHub(Step by step)
转载请注明出处! 1. To find your project URL inside GitHub: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWF ...
- Android企业级程序完全退出的解决方案【转】
http://blog.csdn.net/wangjinyu501/article/details/8763552 问题描述 在平常开发的过程中可以发现,很多开发者对于程序的退出都没有去认真的解决.一 ...
- zoj 1366 Cash Machine
01背包加变形 动态规划的时候就犯浑了,每个状态都要记录的,我却只记录了当前状态的!! #include<stdio.h> #include<string.h> int max ...
- C# 课堂总结3-语句
一.顺序语句 二.条件,分支语句 1.if语句 关键是能够熟练运用 if的嵌套.要考虑好所有的情况. 如果说 条件是两种+情况相互对应的,那么就可以只用 if 与else .但必须要想好 每个else ...
- C++中头文件(.h)和源文件(.cpp)都应该写些什么
头文件(.h): 写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但一般来说不写出具体的实现. 在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句(如下): ...