4.背景知识4.1 进程地址空间布局 进程的地址空间布局(下图为32b系统)。
这个不够直观,我们来看一个具体的程序: //memory.cpp
#include<stdlib.h>
#include<iostream>
#include<stdio.h>
int a[100] = {0};
int b[200];
static char* global_static_inited = "static_data";
static char* global_static_uninited;
int main()
{
int tmp[1024*1024];
void *heap_small = malloc(10);
void *heap_start = malloc(4*1024*1024 + 30);
void *heap_second = malloc(4*1024*1024);
printf("a:%p, \nb:%p, \nstatic_data:%p, \nglobal_static_uninited:%p, \ntmp:%p, \nhead_small:%p, \nheap_start:%p, \nheap_second:%p\n",\
a, b, global_static_inited, &global_static_uninited, tmp, heap_small, heap_start, heap_second);
while(1);
return 0;
}
/*
a:0x601080,
b:0x601220,
static_data:0x4008e0,
global_static_uninited:0x601548,
tmp:0x7fffb3267ef0,
head_small:0x1e64040,
heap_start:0x7f65e8ab2010,
heap_second:0x7f65e86b1010
*/
启动程序,运行pmap -d $thread_id Address Kbytes Mode Offset Device Mapping
0000000000400000 4 r-x-- 0000000000000000 0fd:00017 a.out
0000000000600000 4 r---- 0000000000000000 0fd:00017 a.out
0000000000601000 4 rw--- 0000000000001000 0fd:00017 a.out
0000000001e64000 132 rw--- 0000000000000000 000:00000 [ anon ]
00007f65e86b1000 8200 rw--- 0000000000000000 000:00000 [ anon ]
00007f65e8eb3000 88 r-x-- 0000000000000000 0fd:00017 libpthread-2.17.so
00007f65e8ec9000 2048 ----- 0000000000016000 0fd:00017 libpthread-2.17.so
00007f65e90c9000 4 r---- 0000000000016000 0fd:00017 libpthread-2.17.so
00007f65e90ca000 4 rw--- 0000000000017000 0fd:00017 libpthread-2.17.so
00007f65e90cb000 16 rw--- 0000000000000000 000:00000 [ anon ]
00007f65e90cf000 12 r-x-- 0000000000000000 0fd:00017 libdl-2.17.so
00007f65e90d2000 2044 ----- 0000000000003000 0fd:00017 libdl-2.17.so
00007f65e92d1000 4 r---- 0000000000002000 0fd:00017 libdl-2.17.so
00007f65e92d2000 4 rw--- 0000000000003000 0fd:00017 libdl-2.17.so
00007f65e92d3000 1752 r-x-- 0000000000000000 0fd:00017 libc-2.17.so
00007f65e9489000 2048 ----- 00000000001b6000 0fd:00017 libc-2.17.so
00007f65e9689000 16 r---- 00000000001b6000 0fd:00017 libc-2.17.so
00007f65e968d000 8 rw--- 00000000001ba000 0fd:00017 libc-2.17.so
00007f65e968f000 20 rw--- 0000000000000000 000:00000 [ anon ]
00007f65e9694000 84 r-x-- 0000000000000000 0fd:00017 libgcc_s-4.8.5-20150702.so.1
00007f65e96a9000 2044 ----- 0000000000015000 0fd:00017 libgcc_s-4.8.5-20150702.so.1
00007f65e98a8000 4 r---- 0000000000014000 0fd:00017 libgcc_s-4.8.5-20150702.so.1
00007f65e98a9000 4 rw--- 0000000000015000 0fd:00017 libgcc_s-4.8.5-20150702.so.1
00007f65e98aa000 1028 r-x-- 0000000000000000 0fd:00017 libm-2.17.so
00007f65e99ab000 2044 ----- 0000000000101000 0fd:00017 libm-2.17.so
00007f65e9baa000 4 r---- 0000000000100000 0fd:00017 libm-2.17.so
00007f65e9bab000 4 rw--- 0000000000101000 0fd:00017 libm-2.17.so
00007f65e9bac000 932 r-x-- 0000000000000000 0fd:00017 libstdc++.so.6.0.19
00007f65e9c95000 2048 ----- 00000000000e9000 0fd:00017 libstdc++.so.6.0.19
00007f65e9e95000 32 r---- 00000000000e9000 0fd:00017 libstdc++.so.6.0.19
00007f65e9e9d000 8 rw--- 00000000000f1000 0fd:00017 libstdc++.so.6.0.19
00007f65e9e9f000 84 rw--- 0000000000000000 000:00000 [ anon ]
00007f65e9eb4000 24 r-x-- 0000000000000000 0fd:00017 gundam_preload.so
00007f65e9eba000 2044 ----- 0000000000006000 0fd:00017 gundam_preload.so
00007f65ea0b9000 4 r---- 0000000000005000 0fd:00017 gundam_preload.so
00007f65ea0ba000 4 rw--- 0000000000006000 0fd:00017 gundam_preload.so
00007f65ea0bb000 132 r-x-- 0000000000000000 0fd:00017 ld-2.17.so
00007f65ea2b3000 28 rw--- 0000000000000000 000:00000 [ anon ]
00007f65ea2da000 8 rw--- 0000000000000000 000:00000 [ anon ]
00007f65ea2dc000 4 r---- 0000000000021000 0fd:00017 ld-2.17.so
00007f65ea2dd000 4 rw--- 0000000000022000 0fd:00017 ld-2.17.so
00007f65ea2de000 4 rw--- 0000000000000000 000:00000 [ anon ]
00007fffb3267000 4104 rw--- 0000000000000000 000:00000 [ stack ]
00007fffb372f000 8 r-x-- 0000000000000000 000:00000 [ anon ]
ffffffffff600000 4 r-x-- 0000000000000000 000:00000 [ anon ]
mapped: 31104K writeable/private: 12640K shared: 0K
我们逐一解释: 上文中0000000000400000是段的开始地址,并不是代码的开始地址。这个位置本身是不可访问的。代码段本身的权限是r + x. 需要注意的是static_data 这个字符串本身,是在代码段中。
(gdb) x/100i 0x000000000400000
0x400000: Cannot access memory at address 0x400000
(gdb) disassemble main
Dump of assembler code for function main():
0x0000000000400730 <+0>: push %rbp
0x0000000000400731 <+1>: mov %rsp,%rbp
0x0000000000400734 <+4>: sub $0x400010,%rsp
0x000000000040073b <+11>: mov $0x40001e,%edi
0x0000000000400740 <+16>: callq 0x400600 <malloc@plt>
0x0000000000400745 <+21>: mov %rax,-0x8(%rbp)
0x0000000000400749 <+25>: mov $0x400000,%edi
0x000000000040074e <+30>: callq 0x400600 <malloc@plt>
0x0000000000400753 <+35>: mov %rax,-0x8(%rbp)
0x0000000000400757 <+39>: jmp 0x400757 <main()+39>
End of assembler dump.
(gdb) x/20i 0x0000000000400730
0x400730 <main()>: push %rbp
0x400731 <main()+1>: mov %rsp,%rbp
0x400734 <main()+4>: sub $0x400010,%rsp
0x40073b <main()+11>: mov $0x40001e,%edi
0x400740 <main()+16>: callq 0x400600 <malloc@plt>
0x400745 <main()+21>: mov %rax,-0x8(%rbp)
0x400749 <main()+25>: mov $0x400000,%edi
0x40074e <main()+30>: callq 0x400600 <malloc@plt>
0x400753 <main()+35>: mov %rax,-0x8(%rbp)
0x400757 <main()+39>: jmp 0x400757 <main()+39>
|