0%

linux program address space and nm command tutorial

Guide

Linux/Unix Address Space

memory area address space segment executable section
Code Text .text
Initialized data Data .data
Zero-Initialized Data .bss
Heap Data Heap
Stack Stack Stack

BSS: Block Started by Symbol

program memory area

program memory area:

  • code: executable instructions (和 const 字符串常量???)
  • initialized-data: static/global 初始化不为0的
  • zero-initialized data(BSS): static/global 初始化为0的
  • heap: malloc/new 动态分配,大小不固定
  • stack: 非static的local variable; functin parameter; return value

bss它不占用程序文件的大小,但是占用程序运行时的内存空间。
zero-initialized data(BSS)区域的变量不占用exe的磁盘空间,其内容由操作系统初始化(清零),而initialized-data需要占用exe的磁盘空间,其内容由程序初始化
同一个program的N个不同process,在内存中共享同一个code/text segment,同时都有自己的initialized-data,zero-initialized data(BSS)对应的data segment
字符串常量

address space segment

address space segment

  • text
  • data
  • stack
  1. text,data,stack占用3块不同的地址空间。
  2. initialized-data,zero-initialized data(BSS),heap占用同一块连续的物理内存空间;
  3. heap地址空间从小到大增长;stack的地址空间从大往小减小;

Heap,BSS,Data这三个段在物理内存中是连续存放的,可以这么理解:这三个是一体的。Text、Stack是独立存放的

executable file section

executable file section

  • .text: 在进程最初被加载到内存中开始,该节的大小就被固定,只读readonly。
  • .data: 该节的大小在运行时固定的
  • .bss: 该节的大小在运行时固定的
  • heap: 从内存的低地址向高地址增长
  • stack: 从内存的高地址向低地址增长
  • .rodata: readonly data section

eg

size a.out 
   text	   data	    bss	    dec	    hex	filename
   1551	    600	     40	   2191	    88f	a.out

a.out加载到内存中的大小为2191 bytes.

rodata

(1) const修饰的global放在.rodata, const修饰的local例外,没有放入常量区。
(3)对于global/local字符串常量,编译器会去掉重复的常量,让程序的每个字符串常量只有一份,放在.rodata。(数组内容为字符串的除外)

1
2
3
4
5
6
7
8
9
10
11
12
const int num = 100; // .rodata 

char *str = "123456789"; // 123456789 ===>.rodata LC0
char *str1 = "helloworld"; // helloworld===>.rodata LC1

int main()
{
  const int local_num = 99; // 没有放入.rodata
char* a = "helloworld"; // helloworld===>.rodata LC1
char b[10] = "helloworld";// helloworld 没有放入.rodata
return 1;
}

Example code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>  

int add(int x, int y)
{
return x + y;
}

int aaa,bbb; // auto zero-intialized(.bss)
int ccc000 = 0; // auto zero-initialized(.bss)
int ccc111 = 1; // initialized(.data)

char *str1 = "123"; // str1--->.data 123--->.rodata A
char *str2 = "xyz"; // str2--->.data xyz--->.rodata B
char str3[] = "abc"; // str3--->.data
char *str4; // .bss

static int hhh; // .bss
static int iii00 = 0; // .bss
static int iii99 = 99; // .data

const int NUM99 = 99; // .rodata
const int NUM00 = 0; // .rodata

int main()
{
static int jjj; // .bss
static int kkk=1; // .data

const int local_const00 = 0; //
const int local_const99 = 99; //

char *str5 = "xyz"; // str5===> stack, xyz===> .rodata B
char str6[] = "abc"; // str6--->stack, abc ===> stack


int local = 2; // stack
int *local_new = new int(5); // heap
delete local_new;
return 0;
}

output

g++ hello.cpp
nm a.out

0000000000601078 B aaa
000000000060107c B bbb
000000000060106c B __bss_start
0000000000601080 B ccc000
0000000000601048 D ccc111
0000000000601070 b completed.7594
0000000000601038 D __data_start
0000000000601038 W data_start
00000000004005e0 t deregister_tm_clones
0000000000400660 t __do_global_dtors_aux
0000000000600e08 t __do_global_dtors_aux_fini_array_entry
0000000000601040 D __dso_handle
0000000000600e18 d _DYNAMIC
000000000060106c D _edata
00000000006010a0 B _end
00000000004007a4 T _fini
0000000000400680 t frame_dummy
0000000000600e00 t __frame_dummy_init_array_entry
0000000000400910 r __FRAME_END__
0000000000601000 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
00000000004007c4 r __GNU_EH_FRAME_HDR
0000000000400530 T _init
0000000000600e08 t __init_array_end
0000000000600e00 t __init_array_start
00000000004007b0 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000600e10 d __JCR_END__
0000000000600e10 d __JCR_LIST__
                 w _Jv_RegisterClasses
00000000004007a0 T __libc_csu_fini
0000000000400730 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
00000000004006ba T main
0000000000400620 t register_tm_clones
                 U __stack_chk_fail@@GLIBC_2.4
00000000004005b0 T _start
0000000000601050 D str1
0000000000601058 D str2
0000000000601060 D str3
0000000000601088 B str4
0000000000601070 D __TMC_END__
00000000004006a6 T _Z3addii
                 U _ZdlPv@@GLIBCXX_3.4
0000000000601090 b _ZL3hhh
0000000000601094 b _ZL5iii00
0000000000601064 d _ZL5iii99
00000000004007c0 r _ZL5NUM00
00000000004007bc r _ZL5NUM99
                 U _Znwm@@GLIBCXX_3.4
0000000000601098 b _ZZ4mainE3jjj
0000000000601068 d _ZZ4mainE3kkk

other commands

1
2
strings a.out
readelf -s a.out

Reference

History

  • 20181031: created.