目录
- 虚拟地址空间(虚拟内存)布局
- 编译与链接
- 例子源码
- 看看obj文件的组成格式
- 主要的段
- 全部的段
- 组成格式:头信息+段
- 一些概念和命令的总结
- 概念
- 命令
虚拟地址空间(虚拟内存)布局
-
bss段节省的是文件的空间,不是虚拟地址空间
-
指令段和数据段在程序运行起来后是不变的,不可伸缩
-
从0地址开始到0x08048000的128M地址空间,禁止访问,比如这种操作:
char *p = NULL; ... strlen(p); // 访问出错
编译与链接
下图说明了编译与链接的核心步骤,后面会用一个例子来说明其中的关键信息
链接器,只对global 符号处理,不对local 符号处理
例子源码
int g_data1 = 10;
int g_data2 = 0;
int g_data3;static int g_data4 = 11;
static int g_data5 = 0;
static int g_data6;int main()
{int a = 12;int b = 0;int c;static int d = 13;static int e = 0;static int f;return 0;
}
PS:上面的源码哪些是指令,哪些是数据?红色的是数据,绿色的是指令
局部变量、函数属于指令
全局变量、静态局部变量属于数据
看看obj文件的组成格式
主要的段
gcc -c main.c
得到main.o
文件,使用objdump -h main.o
看看obj文件的段:
VMA:
虚拟地址
LMA:
加载地址
VMA
和LMA
此时都是0,说明编译步骤不给符号分配内存地址,符号解析完成后才会分配(链接时)
File off
:地址偏移
Algn
:对齐字节
结合ELF header
、File off
和Algn
可以算出每个段在虚拟地址空间占的大小,这里也可以发现.bss段不占文件空间(虚拟地址空间需要占,否则符号放哪里呢)
全部的段
readelf -S main.o
可以查看所有的段
组成格式:头信息+段
file main.o
查看文件属性,obj文件为可重定位的文件,不可执行
readelf -h main.o
显示obj文件开始的文件头信息
- 结合前面的段,加上这里的ELF Header,可以看出obj文件的组成格式:
一些概念和命令的总结
概念
- CPU的位数是一次性能加载的最长的整数宽度,ALU的宽度,数据总线的条数
- 虚拟内存(虚拟地址空间)的大小 =2^CPU位数