LINUX下目标文件的BSS段、数据段、代码段

http://blog.chinaunix.net/uid-27018250-id-3867588.html

bss 未初始化的全局数据

data 已经初始化的全局数据

text 代码段,机器指令

rodata 字符串常量

参考:《程序员自我修养》

代码编译后的机器指令经常被放在代码段里,代码段名为".text";已初始化的全局变量和已初始化的局部静态变量经常放在数据段里,数据段名为".data";未初始化的全局变量和未初始化局部静态变量一般放在“.bss”段里,.bss在文件中不占据空间。字符串常量一般放在“.rodata”段里。

通过代码编译后查看文件内部结构来论证一下上面观点,代码如下:
代码:

点击(此处)折叠或打开

  1. int printf(const char* format, ...);
  2. int global_init_var = 84; //已初始化的全局变量
  3. int global_uninit_var;    //未初始化的全局变量
  4. char *str1 = "hello world!"; //字符串常量
  5. void func1(int i)
  6. {
  7. printf("%d\n", i);
  8. }
  9. int main(void)
  10. {
  11. static int static_var = 85; //已初始化的静态局部变量
  12. static int static_var2;     //未初始化的静态局部变量
  13. char *str2 = "22222";       //字符串常量
  14. int a = 1;
  15. int b;
  16. func1(static_var+static_var2+a+b);
  17. return a;
  18. }

上面代码保存为1.c,编译生成目标文件1.o:

点击(此处)折叠或打开

  1. gcc -c 1.c

使用objdump来查看目标文件的结构和内容,命令如下:

点击(此处)折叠或打开

  1. objdump -s -d 1.o

目标文件结构和内容如下(只保留.bss段、.text段、.data段、.rodata段):

点击(此处)折叠或打开

  1. 1.o: file format elf32-i386
  2. Contents of section .text:
  3. 0000 5589e583 ec188b45 08894424 04c70424 U......E..D$...$
  4. 0010 0d000000 e8fcffff ffc9c355 89e583e4 ...........U....
  5. 0020 f083ec20 c7442414 11000000 c7442418 ... .D$......D$.
  6. 0030 01000000 8b150800 0000a100 00000001 ................
  7. 0040 c28b4424 1801c28b 44241c01 d0890424 ..D$....D$.....$
  8. 0050 e8fcffff ff8b4424 18c9c3            ......D$...
  9. Contents of section .data:
  10. 0000 54000000 00000000 55000000          T.......U...
  11. Contents of section .rodata:
  12. 0000 68656c6c 6f20776f 726c6421 0025640a hello world!.%d.
  13. 0010 00323232 323200                     .22222.
  14. Disassembly of section .text:
  15. 00000000 <func1>:
  16. 0:    55                     push %ebp
  17. 1:    89 e5                  mov %esp,%ebp
  18. 3:    83 ec 18               sub $0x18,%esp
  19. 6:    8b 45 08               mov 0x8(%ebp),%eax
  20. 9:    89 44 24 04            mov %eax,0x4(%esp)
  21. d:    c7 04 24 0d 00 00 00   movl $0xd,(%esp)
  22. 14:    e8 fc ff ff ff         call 15 <func1+0x15>
  23. 19:    c9                     leave
  24. 1a:    c3                     ret
  25. 0000001b <main>:
  26. 1b:    55                       push %ebp
  27. 1c:    89 e5                    mov %esp,%ebp
  28. 1e:    83 e4 f0                 and $0xfffffff0,%esp
  29. 21:    83 ec 20                 sub $0x20,%esp
  30. 24:    c7 44 24 14 11 00 00     movl $0x11,0x14(%esp)
  31. 2b:    00
  32. 2c:    c7 44 24 18 01 00 00     movl $0x1,0x18(%esp)
  33. 33:    00
  34. 34:    8b 15 08 00 00 00        mov 0x8,%edx
  35. 3a:    a1 00 00 00 00           mov 0x0,%eax
  36. 3f:    01 c2                    add %eax,%edx
  37. 41:    8b 44 24 18              mov 0x18(%esp),%eax
  38. 45:    01 c2                    add %eax,%edx
  39. 47:    8b 44 24 1c              mov 0x1c(%esp),%eax
  40. 4b:    01 d0                    add %edx,%eax
  41. 4d:    89 04 24                 mov %eax,(%esp)
  42. 50:    e8 fc ff ff ff           call 51 <main+0x36>
  43. 55:    8b 44 24 18              mov 0x18(%esp),%eax
  44. 59:    c9                       leave
  45. 5a:    c3                       ret

我们先来看一下.data段里数据:

点击(此处)折叠或打开

  1. Contents of section .data:
  2. 0000 54000000 00000000 55000000 T.......U...

因为已初始化的全局变量和已初始化的局部静态变量经常放在.data段里,因为偶的CPUX86是小端,低字节放低位,54000000转化十进制为84,55000000转化为十进制为85,刚好对应代码中的global_init_var = 84和static_var = 85。

然后我们来看一下.rodata段的数据:

点击(此处)折叠或打开

  1. Contents of section .rodata:
  2. 0000 68656c6c 6f20776f 726c6421 0025640a hello world!.%d.
  3. 0010 00323232 323200                     .22222.

.rodata里面你可以看到有个数据,分别为“hello world!”、“%d\n”、"22222",这三个数据分别对应了代码中的三个字符串常量。所以字符串常量一般放在“.rodata”段里。

接下来就是代码段.text:

点击(此处)折叠或打开

  1. Contents of section .text:
  2. 0000 5589e583 ec188b45 08894424 04c70424 U......E..D$...$
  3. 0010 0d000000 e8fcffff ffc9c355 89e583e4 ...........U....
  4. 0020 f083ec20 c7442414 11000000 c7442418 ... .D$......D$.
  5. 0030 01000000 8b150800 0000a100 00000001 ................
  6. 0040 c28b4424 1801c28b 44241c01 d0890424 ..D$....D$.....$
  7. 0050 e8fcffff ff8b4424 18c9c3            ......D$...

看到.text段中的两个以"55 89 e5 83 ec ec 18 8b 45"和"89 e5 83 e4 f0 83 ec 20"开头的数据。分别对应汇编代码编译以后的机器指令(十六进制数据相同),见如下:

点击(此处)折叠或打开

  1. Disassembly of section .text:
  2. 00000000 <func1>:
  3. 0:    55                       push %ebp
  4. 1:    89 e5                    mov %esp,%ebp
  5. 3:    83 ec 18                 sub $0x18,%esp
  6. 6:    8b 45 08                 mov 0x8(%ebp),%eax
  7. 9:    89 44 24 04              mov %eax,0x4(%esp)
  8. d:    c7 04 24 0d 00 00 00     movl $0xd,(%esp)
  9. 14:    e8 fc ff ff ff           call 15 <func1+0x15>
  10. 19:    c9                       leave
  11. 1a:    c3                       ret
  12. 0000001b <main>:
  13. 1b:    55                       push %ebp
  14. 1c:    89 e5                    mov %esp,%ebp
  15. 1e:    83 e4 f0                 and $0xfffffff0,%esp
  16. 21:    83 ec 20                 sub $0x20,%esp
  17. 24:    c7 44 24 14 11 00 00     movl $0x11,0x14(%esp)
  18. 2b:    00
  19. 2c:    c7 44 24 18 01 00 00     movl $0x1,0x18(%esp)
  20. 33:    00
  21. 34:    8b 15 08 00 00 00        mov 0x8,%edx
  22. 3a:    a1 00 00 00 00           mov 0x0,%eax
  23. 3f:    01 c2                    add %eax,%edx
  24. 41:    8b 44 24 18              mov 0x18(%esp),%eax
  25. 45:    01 c2                    add %eax,%edx
  26. 47:    8b 44 24 1c              mov 0x1c(%esp),%eax
  27. 4b:    01 d0                    add %edx,%eax
  28. 4d:    89 04 24                 mov %eax,(%esp)
  29. 50:    e8 fc ff ff ff           call 51 <main+0x36>
  30. 55:    8b 44 24 18              mov 0x18(%esp),%eax
  31. 59:    c9                       leave
  32. 5a:    c3                       ret

所以说代码编译后的机器指令经常被放在代码段里。

再看一下.bss段,输入命令:

点击(此处)折叠或打开

  1. objdump -x -s -d 1.o

查看:

点击(此处)折叠或打开

  1. Sections:
  2. Idx Name Size VMA LMA File off Algn
  3. 2 .bss 00000004 00000000 00000000 0000009c 2**2
  4. ALLOC

看到.bss的大小为4,《程序员自我修养》上说只有static_var2存放到.bss段,而global_uninit_var只是一个未定义的“COMMON符号“没有放在任何段里,这是跟不同的语言与不同的编译器实现有关。看完书后在来补充吧。

最后,说bbs段在文件中不不占用空间,请参考下面代码:
1.

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. return 0;
  5. }

编译查看大小:

点击(此处)折叠或打开

  1. [email protected]:/usr/local/src# gcc -c 1.c
  2. [email protected]:/usr/local/src# size 1.o
       text       data        bss        dec        hex    filename
         66          0          0         66         42    2.o
  3. [email protected]:/usr/local/src# ls -l 1.o
  4. -rw-r--r-- 1 root root 852 8月 27 11:03 2.o

2.比上面代码多了16字节的”int a[10] = {0};“

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. int a[10] = {0};
  3. int main(void)
  4. {
  5. return 0;
  6. }

再来编译查看大小:

点击(此处)折叠或打开

  1. [email protected]:/usr/local/src# gcc -c 2.c
  2. [email protected]:/usr/local/src# ll 2.o
  3. -rw-r--r-- 1 root root 868 8月 27 11:13 2.o
  4. [email protected]:/usr/local/src# size 2.o
  5. text     data     bss     dec     hex    filename
  6. 66     0     40     106     6a    2.o

两段代码便以后,BSS段大小发生了变化多了40个字节,但是实际文件大小只相差16个字节,刚好就是加入代码的”int a[10] = {0};“这十六个字节。所以说bbs段在文件中不不占用空间。

时间: 2024-09-30 14:34:25

LINUX下目标文件的BSS段、数据段、代码段的相关文章

Linux下搜索文件find、which、whereis、locate

Linux下搜索文件find.which.whereis.locate: - which 寻找“执行文件” - -a 将所有可找到的命令均列出,而不仅仅列出第一个找到的命令名称 - whereis 寻找特定文件   whereis [-bmsu] 文件或目录 - -b : 只找二进制文件 - -m : 只找在帮助文件manual路径下的文件 - -s :  只找源文件 - -u :  没有帮助文件的文件 - locate [filename] -- 例:  locate passwd - fin

修改Linux下的文件以及文件夹的权限

如何在Linux中管理文件和文件夹的权限? 2014-02-12 10:58 布加迪编译 51CTO 字号:T | T Linux系统有严格的权限管理制度,操作者权限与文件权限不匹配时将无法对文件进行任何操作.对许多Linux用户来说,习惯于文件的权限和所有权可能有点难度.本文从命令行开始入手,教您在Linux中管理文件和文件夹权限的方法. AD:51CTO学院:IT精品课程在线看! [51CTO精选译文]对许多Linux用户来说,习惯于文件的权限和所有权可能有点难度.人们通常认为,想进入到这种

Linux下各个文件夹的作用

linux下的文件结构,看看每个文件夹都是干吗用的/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示 /lib 标准程序设计库,又叫动态链接共享库,作用类似windows里的.dll文件 /sbin 系统管理命令,这里存放的是系统管理员使用的管理程序 /tmp 公用的临时文件存储点 /root 系统管理员的主目录(呵呵,特权

linux下的文件IO缓冲区,及其相关操作

linux下的文件IO操作 浅谈文件IO缓冲 Read()和write()函数在操作磁盘文件时不会直接发起磁盘访问,而是仅仅在用户空间缓冲区与内核缓冲区高速缓存之间复制数据. 当调用write()函数的写入3个字节的时候,由于系统调用与磁盘操作并不同步,在write()函数结束后续某个时刻,内核才会将其缓冲区中的数据写入磁盘.如果在此期间,另一个进程试图读取该文件的这几个字节,那么内核将自动从缓冲区高速缓存中提供这些数据,而不是文件中. 与此同理,对输入而言,内核从磁盘中读取数据并存储到内核缓冲

linux下各文件夹的结构说明及用途介绍

linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令.   /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示.   /lib:标准程序设计库,又 叫动态链接共享库,作用类似windows里的.dll文件.   /sbin:系统管理命令,这 里存放的是系统管理员使用的管理程序. /tmp:公用的临时文件存储 点. /root:

【转】linux下各文件夹的结构说明及用途介绍

linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示. /lib:标准程序设计库,又 叫动态链接共享库,作用类似windows里的.dll文件. /sbin:系统管理命令,这 里存放的是系统管理员使用的管理程序. /tmp:公用的临时文件存储 点. /root:系统管理员的

纯干货!Linux 下各文件夹的结构说明及用途介绍

linux下各文件夹的结构说明及用途介绍: /bin:二进制可执行命令. /dev:设备特殊文件. /etc:系统管理和配置文件. /etc/rc.d:启动的配 置文件和脚本. /home:用户主目录的基点,比如用户user的主目录就是/home/user,可以用~user表示. /lib:标准程序设计库,又 叫动态链接共享库,作用类似windows里的.dll文件. /sbin:系统管理命令,这 里存放的是系统管理员使用的管理程序. /tmp:公用的临时文件存储 点. /root:系统管理员的

【Linux/Ubuntu学习 14】Linux下查看文件和文件夹大小

当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力.    du可以查看文件及文件夹的大小. 两者配合使用,非常有效.比如用df查看哪个一级目录过大,然后用df查看文件夹或文件的大小,如此便可迅速确定症结. 下面分别简要介绍 df命令可以显示目前所有文件系统的可用空间及使用情形,请看下列这个例子: 以下是代码片段: [[email protected] ~]$ df -hFilesystem

Linux下的文件压缩归档与系统进程管理

Linux下的文件压缩归档与系统进程管理   一:实验环境 1):在虚拟机下配置好linux系统 2):了解文件压缩归档的含义 二:实验目标 1):理解并会用文件的压缩归档 2):熟练掌握文件压缩归档的命令 3):理解各种压缩形式的使用环境 4):理解个文件的压缩区别 三:实验步骤 一:压缩的常用形式及命令 1):常用形式 grub.tar grub.tar.bz2 grub.tar.gz grub.tar.zip 2):压缩命令分析 [[email protected] test]#tar -