nm命令的学习以及可执行文件中的段

今天学习专家c的运行时数据结构,顺便简单地学习了一下nm命令

就目标文件而言,段是二进制文件中的简单区域里面保存了一定信息,section是ELF文件中最小组织单元,一个段包含几个section.

nm命令的作用是显示对象文件,可执行文件以及对象文件库的符号信息.这里只对可执行文件的符号信息进行研究.

以hello world 程序为例

#include <stdio.h>

int lemon[1000];                    
int main(){                                                                                                      
  printf("Hello World!
");                                                        
  return 0;                                                                        
}                                                                                  

/*test.c*/

用gcc test.c 命令编译后默认生成 a.out 这个默认名字的文件是由链接器产生的,之所以叫a.out是因为在遥远的过去,也就是链接器还没有被发明时,汇编产生的程序

就保存在这个a.out文件中(assembler output的缩写),发明链接器后由链接器产生的文件仍然保留了这个称呼.

生成的a.out文件我们先来看看它的大小 即 ls -l a.out 以及它的各个端的大小即 size a.out

再来用nm 命令来看看符号信息 这里用了 -S 选项和 -t FORMAT 选项来方便显示.  -S选项是打印定义了的符号的大小的开关. -t FORMAT 是以十进制,十六进制

八进制来打印数字的开关.

观察一下得到的结果第一列为该符号的地址,第三列可能为该符号的大小,可以看到lemon的大小就是4000字节,最后一列为符号的名字

我们来看看第二列有大小的T,t,大小写的B,b等等

这里的大写为GLOBAL小写为LOCAL

b(B)为BSS

d(D)为DATA

t(T)为TEXT

U表示该符号在该文件中是未定义的,即在其他的文件中定义

再来看看当该数组赋值时的情况

文件的大小增加了大约4000字节

而看看可执行的文件中的段,data段大概增加了4000字节,bss段减少了大约4000字节,段总大小几乎不变

所以可以得出结论bss段并不占用可执行文件的任何空间,只是记录其大小.

再来看看把数组声明在函数中会怎样

文件的size比以前少了大约4000字节,段的总的大小也少了4000字节左右

利用nm命令看看

可以发现可执行文件已经没有lemon这个符号了,当对数组进行初始化后也一样.可见在函数中声明的数组并没有存在段中.

最后看看调试选项对可执行文件的影响

可见调试编译对可执行文件大小有影响,但对段的大小并没有影响

总结:

数据段保存在可执行文件中

bss段不保存在可执行文件中

a.out文件大小受调试状态编译的影响,而段不受影响

疑惑:

为什么说文本段是最易受优化措施影响的段.

(看完这章后来试试解决这个疑问)

Yosoro
原文地址:https://www.cnblogs.com/tclan126/p/8306422.html