Linux应用程序地址布局
1赞
发表于 7/14/2017 8:55:55 AM
阅读(2214)
一、程序构成
在学习Linux应用程序开发时,经常会遇到如下概念:代码段、数据段、BSS段等。BSS(Block Started by Symbol,又名:未初始化数据段)、堆(heap)、栈(stack)而这些部分也是构成Linux应用程序的重要组成部分。
二、内存布局
当Linux应用程序在内存中运行的时候,以上组成部分在内存中以如下图的方式布局。
从低地址到高地址分别为:代码段、数据段、BSS段、堆、栈
堆向高内存地址生长
栈向低内存地址生长
三、编写代码查看程序各段地址
编辑如下代码:addr.c
#include <stdio.h>#include <malloc.h>#include <string.h>char a[64] = "welcome";char b[64];void main(){ char *c = (char *)malloc(64); int d = 76; strcpy(b,"value b"); strcpy(c,"value c"); printf("var a address: 0x%16x \n",a); printf("var b address: 0x%16x \n",b); printf("var c address: 0x%16x \n",c); printf("var d address: 0x%16x \n",&d); while(1){;} }
编译、运行程序:
gcc -o addr -g addr.c./addr//输出如下:var a address: 0x 601060 var b address: 0x 6010c0 var c address: 0x 6ab010 var d address: 0x 4715986c
另外打开一个shell 进行操作:
ps aux | grep ./addr //这里输出如下 jet 4426 100 0.0 4356 640 pts/18 R+ 20:47 0:21 ./addr jet 4439 0.0 0.0 15964 980 pts/19 S+ 20:47 0:00 grep --color=auto ./addr //可以看出我们的进程PID 是 4426
抓取内存信息:
cat /proc/4426/maps // 输出如下:(我这里是x64机器有点不太一样) 00400000-00401000 r-xp 00000000 08:01 7870415 /home/jet/study/lesson3_memory/addr00600000-00601000 r--p 00000000 08:01 7870415 /home/jet/study/lesson3_memory/addr00601000-00602000 rw-p 00001000 08:01 7870415 /home/jet/study/lesson3_memory/addr006ab000-006cc000 rw-p 00000000 00:00 0 [heap]7f73272bb000-7f732747b000 r-xp 00000000 08:01 12849622 /lib/x86_64-linux-gnu/libc-2.23.so7f732747b000-7f732767b000 ---p 001c0000 08:01 12849622 /lib/x86_64-linux-gnu/libc-2.23.so7f732767b000-7f732767f000 r--p 001c0000 08:01 12849622 /lib/x86_64-linux-gnu/libc-2.23.so7f732767f000-7f7327681000 rw-p 001c4000 08:01 12849622 /lib/x86_64-linux-gnu/libc-2.23.so7f7327681000-7f7327685000 rw-p 00000000 00:00 0 7f7327685000-7f73276ab000 r-xp 00000000 08:01 12845073 /lib/x86_64-linux-gnu/ld-2.23.so7f732788b000-7f732788e000 rw-p 00000000 00:00 0 7f73278a8000-7f73278aa000 rw-p 00000000 00:00 0 7f73278aa000-7f73278ab000 r--p 00025000 08:01 12845073 /lib/x86_64-linux-gnu/ld-2.23.so7f73278ab000-7f73278ac000 rw-p 00026000 08:01 12845073 /lib/x86_64-linux-gnu/ld-2.23.so7f73278ac000-7f73278ad000 rw-p 00000000 00:00 0 7ffc4713a000-7ffc4715b000 rw-p 00000000 00:00 0 [stack]7ffc471c6000-7ffc471c8000 r--p 00000000 00:00 0 [vvar]7ffc471c8000-7ffc471ca000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 这里我们结合进程map信息和程序输出信息可以得出:
代码段位于 400000 - 401000
数据段位于 600000 - 601000
BSS段位于 601000 - 602000
堆空间位于 6ab000 - 6cc000
栈空间地址非常高
四、变量存放段补充
.data段:
全局、已初始化
全局、静态、已初始化
局部、静态、初始化
.BSS段:
全局、未初始化
全局、静态、未初始化
局部、静态、未初始化
.code段:
全局、常量(const)
字符串常量
.stack段:
局部、初始化
局部、未初始化
局部、常量(const)
.heap段:
malloc分配局部变量
注意:
可以通过下面命令读取相关程序的内存分配:
readelf -s addr //输出如下: Symbol table '.dynsym' contains 5 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 4: 0000000000000000 0 FUNC GLOBAL DEFAULT UND malloc@GLIBC_2.2.5 (2) Symbol table '.symtab' contains 75 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000400238 0 SECTION LOCAL DEFAULT 1 2: 0000000000400254 0 SECTION LOCAL DEFAULT 2 3: 0000000000400274 0 SECTION LOCAL DEFAULT 3 4: 0000000000400298 0 SECTION LOCAL DEFAULT 4 5: 00000000004002b8 0 SECTION LOCAL DEFAULT 5 6: 0000000000400330 0 SECTION LOCAL DEFAULT 6 7: 0000000000400376 0 SECTION LOCAL DEFAULT 7 8: 0000000000400380 0 SECTION LOCAL DEFAULT 8 9: 00000000004003a0 0 SECTION LOCAL DEFAULT 9 10: 00000000004003b8 0 SECTION LOCAL DEFAULT 10 11: 0000000000400400 0 SECTION LOCAL DEFAULT 11 12: 0000000000400420 0 SECTION LOCAL DEFAULT 12 13: 0000000000400460 0 SECTION LOCAL DEFAULT 13 14: 0000000000400470 0 SECTION LOCAL DEFAULT 14 15: 0000000000400684 0 SECTION LOCAL DEFAULT 15 16: 0000000000400690 0 SECTION LOCAL DEFAULT 16 17: 00000000004006f4 0 SECTION LOCAL DEFAULT 17 18: 0000000000400728 0 SECTION LOCAL DEFAULT 18 19: 0000000000600e10 0 SECTION LOCAL DEFAULT 19 20: 0000000000600e18 0 SECTION LOCAL DEFAULT 20 21: 0000000000600e20 0 SECTION LOCAL DEFAULT 21 22: 0000000000600e28 0 SECTION LOCAL DEFAULT 22 23: 0000000000600ff8 0 SECTION LOCAL DEFAULT 23 24: 0000000000601000 0 SECTION LOCAL DEFAULT 24 25: 0000000000601040 0 SECTION LOCAL DEFAULT 25 26: 00000000006010a0 0 SECTION LOCAL DEFAULT 26 27: 0000000000000000 0 SECTION LOCAL DEFAULT 27 28: 0000000000000000 0 SECTION LOCAL DEFAULT 28 29: 0000000000000000 0 SECTION LOCAL DEFAULT 29 30: 0000000000000000 0 SECTION LOCAL DEFAULT 30 31: 0000000000000000 0 SECTION LOCAL DEFAULT 31 32: 0000000000000000 0 SECTION LOCAL DEFAULT 32 33: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 34: 0000000000600e20 0 OBJECT LOCAL DEFAULT 21 __JCR_LIST__ 35: 00000000004004a0 0 FUNC LOCAL DEFAULT 14 deregister_tm_clones 36: 00000000004004e0 0 FUNC LOCAL DEFAULT 14 register_tm_clones 37: 0000000000400520 0 FUNC LOCAL DEFAULT 14 __do_global_dtors_aux 38: 00000000006010a0 1 OBJECT LOCAL DEFAULT 26 completed.7585 39: 0000000000600e18 0 OBJECT LOCAL DEFAULT 20 __do_global_dtors_aux_fin 40: 0000000000400540 0 FUNC LOCAL DEFAULT 14 frame_dummy 41: 0000000000600e10 0 OBJECT LOCAL DEFAULT 19 __frame_dummy_init_array_ 42: 0000000000000000 0 FILE LOCAL DEFAULT ABS addr.c 43: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c 44: 0000000000400818 0 OBJECT LOCAL DEFAULT 18 __FRAME_END__ 45: 0000000000600e20 0 OBJECT LOCAL DEFAULT 21 __JCR_END__ 46: 0000000000000000 0 FILE LOCAL DEFAULT ABS 47: 0000000000600e18 0 NOTYPE LOCAL DEFAULT 19 __init_array_end 48: 0000000000600e28 0 OBJECT LOCAL DEFAULT 22 _DYNAMIC 49: 0000000000600e10 0 NOTYPE LOCAL DEFAULT 19 __init_array_start 50: 00000000004006f4 0 NOTYPE LOCAL DEFAULT 17 __GNU_EH_FRAME_HDR 51: 0000000000601000 0 OBJECT LOCAL DEFAULT 24 _GLOBAL_OFFSET_TABLE_ 52: 0000000000400680 2 FUNC GLOBAL DEFAULT 14 __libc_csu_fini 53: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab 54: 0000000000601040 0 NOTYPE WEAK DEFAULT 25 data_start 55: 00000000006010c0 64 OBJECT GLOBAL DEFAULT 26 b 56: 00000000006010a0 0 NOTYPE GLOBAL DEFAULT 25 _edata 57: 0000000000400684 0 FUNC GLOBAL DEFAULT 15 _fini 58: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.2.5 59: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_ 60: 0000000000601040 0 NOTYPE GLOBAL DEFAULT 25 __data_start 61: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 62: 0000000000601048 0 OBJECT GLOBAL HIDDEN 25 __dso_handle 63: 0000000000400690 4 OBJECT GLOBAL DEFAULT 16 _IO_stdin_used 64: 0000000000400610 101 FUNC GLOBAL DEFAULT 14 __libc_csu_init 65: 0000000000000000 0 FUNC GLOBAL DEFAULT UND malloc@@GLIBC_2.2.5 66: 0000000000601100 0 NOTYPE GLOBAL DEFAULT 26 _end 67: 0000000000400470 42 FUNC GLOBAL DEFAULT 14 _start 68: 0000000000601060 64 OBJECT GLOBAL DEFAULT 25 a 69: 00000000006010a0 0 NOTYPE GLOBAL DEFAULT 26 __bss_start 70: 0000000000400566 164 FUNC GLOBAL DEFAULT 14 main 71: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses 72: 00000000006010a0 0 OBJECT GLOBAL HIDDEN 25 __TMC_END__ 73: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable 74: 0000000000400400 0 FUNC GLOBAL DEFAULT 11 _init
通过输出结果可以分析数据段的分配。