编译链接objdump教材2.3.1

T1.c

  1 #include <stdio.h>
  2 int g = 1203;
  3 int h;
  4 static int s;
  5 
  6 int main(int argc,char *argv[]){
  7     int a = 1,b;
  8     static int c = 3;
  9     b = 2;
 10     c = mysum(a,b);
 11     printf("sum=%d
",c);
 12 }

T2.c

  1 extern int g;
  2 int mysum(int x,int y){
  3     return x+y+g;
  4 }

隐式声明和想要声明的函数一样,所以没出问题。
但我觉得这样不好。


网上学习objdump命令,提交不少于5篇博客链接和微信读书上的图书链接

https://blog.csdn.net/q2519008/article/details/82349869
https://linux265.com/course/linux-command-objdump.html
https://www.cnblogs.com/baiduboy/p/7061365.html
https://www.jianshu.com/p/a9a1d07302dc
https://blog.csdn.net/weixin_43836778/article/details/90749138
https://www.pianshen.com/article/3362131908/

我认为最好的讲解资源的链接
https://man.linuxde.net/objdump


用objdump分析第1步中的可执行文件和目标文件,提交你的分析截图以及如何和教材讲解内容对应的
比如obj文件的文件头,代码段,数据段等,可执行文件如何链接mysum的。

可重定位目标文件中包含有很多的节,格式如下图:

ELF头
包括16字节的标识信息、文件类型(.o,exec,.so)、机器类型(如Intel 80386)、节头表的偏移、节头表的表项大小及表项个数。

.text节
编译后的代码部分。

.rodata节
只读数据,如 printf用到的格式串、switch跳转表等。

.data节
已初始化的全局变量和静态变量。

.bss节
未初始化全局变量和静态变量,仅是占位符,不占据任何磁盘空间。区分初始化和非初始化是为了空间效率。

.symtab节
存放函数和全局变量(符号表)的信息,它不包括局部变量。

.rel.text节
.text节的重定位信息,用于重新修改代码段的指令中的地址信息。

.rel.data节
.data节的重定位信息,用于对被模块使用或定义的全局变量进行重定位的信息。

.debug节
调试用的符号表(gcc -g)

.strtab节
包含 .symtab节和 .debug节中的符号及节名

节头表(Section header table)
包含每个节的节名在.strtab节中的偏移、节的偏移和节的大小.

  • 既然.obj文件中都没有存储.bss段的信息,那么在程序中那些初始化为0的全局变量和未初始化的局部变量它是怎么识别它们的?

  • 答:由于.bss段中都是0,所以不需要记录。只需要记录其大小即可,所以通过段表即可找到。

链接过程

将.o文件的各个段分别合并

合并符号表,给符号分配正确的地址

依据符号表中的记录替换编译时保留的无效地址(占位用的)

可以看到编译过程并不给数据和函数入口分配内存地址,在.o文件中,由于无法确定具体的地址,此时编译器只是将其赋了一个特殊的地址0x0,然后在最后的链接阶段再完成正确的地址赋值。

目标文件中的符号表

目标文件的.symtab节记录着符号表信息,符号表示一个结构体数组,每个表项(16字节)的结构如下:

符号解析:所有obj文件符号表中对符号引用的地方都要找到符号定义的地方,否则就会出现链接错误。由于源文件是单独编译的,所以对外部的符号处理为UND即undefine。

原文地址:https://www.cnblogs.com/cfqlovem-521/p/15487573.html