3-3 objdump挖掘目标文件
objdump挖掘目标文件
准备
分析代码如下:
/* |
只编译不链接:
gcc -c Simple.c |
objdump -h
命令结果
使用-h查看目标文件各个段的基本信息:
objdump -h Simple.o |
各个节说明
各个节的意义:
-
.text
:包含程序的执行代码。属性包括:CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE。 -
.data
:包含初始化的全局变量和静态变量。属性包括:CONTENTS, ALLOC, LOAD, DATA。 -
.bss
:包含未初始化的全局变量和静态变量。属性只有:ALLOC。 -
.rodata
:包含只读数据,如字符串常量。属性包括:CONTENTS, ALLOC, LOAD, READONLY, DATA。 -
.comment
:包含文件的注释信息,常用于存放编译器的版本信息。属性包括:CONTENTS, READONLY。 -
.note.GNU-stack
:这是一个特殊的节,用于指定堆栈是否可以执行代码。这里的大小为 0,表示没有这个节。 -
.note.gnu.property
:包含 GNU 属性,如 ABI 版本信息。属性包括:CONTENTS, ALLOC, LOAD, READONLY, DATA。 -
.eh_frame
:包含异常处理信息,用于 C++ 异常和非局部跳转。属性包括:CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA。
属性说明
各种属性的说明:
-
CONTENTS
:表示该节包含一些数据内容,这些内容在文件中实际存在。 -
ALLOC
:表示该节在内存中分配空间。即使节中没有内容(如未初始化的数据),也会在内存中为其保留空间。 -
LOAD
:表示该节在程序加载到内存时会被加载。如果一个节没有LOAD
属性,它可能只在文件中存在,不会被加载到内存中。 -
RELOC
:表示该节包含需要在加载时或运行时进行地址重定位的信息。这通常用于代码和数据,因为它们可能包含需要在不同地址运行的引用。 -
READONLY
:表示该节的数据是只读的,不能在运行时被修改。 -
CODE
:表示该节包含可执行代码。 -
DATA
:表示该节包含数据,可以是初始化或未初始化的全局变量、静态变量等。
bss
bss段没有CONTENTS
属性,代表该段在文件中实际不存在。
objdump -s -d
-
-s
:将所有段内容以16进制打印出来 -
-d
:将包含指令的段反汇编打印出来
objdump -s -d Simple.o |
data
.data段中一共8个字节,分别是global_init_var
和static_var
。其值是0x54和0x55。
rodata
.rodata段存储了只读数据(一般是用const
修饰的变量),这里面存储了printf中的%d\n
字符串常量(字符串常量有时会存储在data段,这与编译器和版本有关)。
单独设立rodata段不仅在语义上支持了C++的const
,而且操作系统在加载时会将rodata段的属性映射为只读,这样任何对该段的修改操作都是非法的,保证了程序的安全性。
bss
有些编译器会将全局的未初始化变量存储在bss段,有些不会存放。而是只是预留一个未定义的全局变量符号,等到最终链接成可执行文件时再在bss段分配空间。
原则上可以简单地讲,全局的未初始化变量和局部的静态未初始化变量存储在bss段。
另外如果全局变量初始化的值与默认值一样,那么也可能放在bss段而不是data段,为了节省文件大小。
其它段与说明
下面是常见的其它段的说明:
段名 | 说明 |
---|---|
.rodata1 |
只读数据段,存放字符串常量、全局 const 变量等只读数据,和rodata 一样。 |
.comment |
存放编译器版本信息,例如字符串:“GCC: (GNU) 4.2.0”。 |
.debug |
调试信息。 |
.dynamic |
动态链接信息。 |
.hash |
符号哈希表。 |
.line |
调试时的行号表,即源代码行号与编译后指令的对应表。 |
.note |
额外的编译器信息,如程序的公司名、发布版本号等。 |
.strtab |
字符串表,用于存储 ELF 文件中用到的各种字符串。 |
.symtab |
符号表。 |
.shstrtab |
段名表,用于存储节名。 |
.plt |
动态链接的跳转表。 |
.got |
全局入口表。 |
.init |
程序初始化代码段。 |
.fini |
程序终结代码段。 |
段名可能由于某些历史原因存在多个一样的,例如存在两个.text
。另外也会存在一些保留的段名但是不会使用。
系统保留段名一般以.
开头,自定义的一般没有。
自制二进制段(图片、音频等)
如果要将图片、MP3音乐、字典之类的东西添加进目标文件作为其中的一个段,可以使用objcopy工具。
objcopy -I binary -O elf32-i386 -B i386 image.jpg image.o |

自定义段
如果由于某些原因,希望将变量或函数放到自定义的某个段中,可以使用GCC提供的一个扩展机制:__attribute__((section("name")))
:
__attribute__((section("FOO"))) int global = 42; |