编译链接 |3 目标文件里面有什么 | 3.3 挖掘 SimpleSection.o

源码 SimpleSection.c

示例程序如下,该示例程序在ubuntu环境下编译和查看:

/*
 * SimpleSection.c
 *
 * Linux:
 *      gcc -c SimpleSection.c
 *
 * Windows:
 *      cl SimpleSection.c /c /Za
 */

int printf( const char * format, ...);

int global_init_var = 84;
int global_uninit_var;

void func1(int i)
{
        printf("%d\n", i);
}

int main(void)
{
        static int static_var = 85;
        static int static_var2;

        int a = 1;
        int b;

        func1(static_var + static_var2 + a + b);

        return a;
}

目标文件 SimpleSection.o 详细解析

1. 编译和dump

首先我们将.c文件编译成目标文件然后objdump查看。
编译命令 gcc -c SimpleSection.c -o SimpleSection.o,得到目标文件SimpleSection .o。使用objdump – 分析ELF文件结构的利器来查看细节:

objdump -s -d SimpleSection.o

其中:-s 参数用来将ELF文件所有段的内容以十六进制输出;-d 参数将包含指令的段反汇编(一般是.text代码段)。
在这里插入图片描述

2. 段分析

  • .text(代码段)
    代码段的详细说明见上图,包含的正式fun1()和main()这两个函数的机器指令。
    这里有个细节要注意,代码段(其他段也一样)中间黄色方框部分形如 554889e5 总共占4个字节,这四个字节内部字节序按大小端排序(与机器有关),这里每4个字节组成的字节序单元从左往右地址递增排序。

  • .data(数据段)
    保存的是初始化了的全局变量和局部静态变量。
    global_init_var 和 static_var。

  • .rodata(只读数据段)
    存放只读数据。
    只读数据有:
    (1) const修饰的变量;
    (2) 字符串常量。上例中的打印语句 printf 中的 %d\n
    单独设立 .rodata 段的好处

    • 支持关键字 const
    • 操作系统加载时可将.rodata段映射成只读属性,以后对该段的修改会判定为非法操作,增加了程序的安全性
    • 某些嵌入式平台中经常会采用只读存储器(ROM),将.rodata段放在这里可保证程序访问存储器的正确性

说明:有些编译器会把字符串常量放到.data段(例如MSVC编译器)

  • .bss(block started by symbol)
    前面有说过,.bss段只是为未初始化的全局变量和局部静态变量预留位置,实际并不占空间。更多细节如下:
    • 首先ELF文件存放在磁盘上未被执行时.bss段是不占空间的。这一点可以通过objdump -s xxx.o 来查看具体ELF文件的所有段的内容,可以发现并没有.bss段的内容。
    • 其次ELF文件被链接成可执行文件执行时才会为.bss段中的内容分配内存空间。这里面又有四个细节:
      1)未初始化的局部静态变量在ELF文件中是被标记在真正的 .bss 段中的(见下图 static_var2)
      2)未初始化的全局变量在EFL文件中是被用符号 “*COM*” 标记的(见下图 global_uninit_var),也就是说并不是标记在.bss段的。只是待到被链接成可执行文件执行时,才会在.bss段分配空间给该变量。这与编译器的实现有关。
      3)未初始化的全局变量如果添加static修饰(未初始化的全局静态变量),在ELF文件中也会被标记在.bss段,而不是用 “*COM*” 标记。这点可以修改后再通过 objdump -x来确认。
      4)初始化为0的静态变量也是被标记在EFL文件的.bss段的,而不是放在 .data 段。这是因为未初始化的都是0,编译器优化将初始化为0等同于未初始化,一同放到了.bss 段,来节省磁盘空间。

在这里插入图片描述

扫描二维码关注公众号,回复: 10183822 查看本文章

思考

从实际工作经验来看,目标文件的反汇编部分经常会用来分析一些复杂问题。

上面介绍的分析方法除了可以分析.o文件,同样也可以用于分析死机 sysdump 文件,因为sysdump文件也是符合COFF格式规范的,同理动态和静态链接文件也可以如此分析(可参考3.1+3.2 目标文件格式和内容)。

发布了60 篇原创文章 · 获赞 27 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/xiaosaerjt/article/details/100527995
3.3