在32位机器的linux系统同进程的地址空间大小是4G.
0~3G( 0x0000 0000 ~ 0xBFFF FFFF) 属于用户空间
3~4G( 0xC000 0000 ~ 0xFFFF FFFF) 属于内核空间
进程地址空间由以下几部分组成
高地址 内核空间 | 0xc000 0000
| 命令行参数和环境变量
| (ramdom stack offset)
| 栈 (RLIMIT_STACK ... 8M)
| (ramdom mmap offset)
| 内存映射空间( file mmapings and anonymous mappings, grow down)
| 堆(start brk, grow up)
| (random brk offset)
| 未初始化的数据(bss)
| 已初始化的数据(data)
低地址 代码区(text) | 0x0804 8000
新版本中为了防止缓冲区溢出攻击给堆和栈都加了一个随机偏移, 是程序每次的堆栈信息都不一样.
1) 代码区是可共享的, 即有可能多个进程只使用了一个代码区. 为了防止程序异常而修改代码区的代码, 代码区通常设置为只读的.
2) data区存放一些已经初始化的全局变量
3) 程序的入口地址在编译阶段已经确定了, 通过 readelf -h a.out 命令输出的"Entry point address"字段就可以知道程序的入口地址是多少了.
编译时可以通过 "-Ttext [addr]" 命令选项 或者 "-T [ lds file ]" 中的lds文件来指定函数的入口地址.
其他地址选项可以通过ld的帮助文档(快速查看: ld --help | grep "\-T" ).
下面给出一个lds的片段(也可以通过ld -verbose 查看默认的lds文件).
============ start of lds =====================
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
start.o (.text)
*(.text)
}
.............
.............
}
============== end of lds =========================