C/C++程序链接与反汇编工具objdump的使用介绍
1. 前言
在C/C++程序的编译链中,链接是一个非常重要的步骤。链接器主要的任务是把所有的.obj和.lib文件合成一个可执行文件,并解决变量名和函数名的引用关系,生成可执行文件中符号表等信息。objdump是一个反汇编工具,可以将可执行文件中的二进制代码转换为汇编代码,方便开发人员进行调试和优化,同时也便于病毒分析、逆向工程等。
本文主要介绍C/C++程序链接和objdump工具的使用方法,并给出两个示例说明。
2. C/C++程序链接
2.1 静态链接和动态链接
在C/C++程序中,常用的链接方式有静态链接和动态链接。
静态链接是指把所有的库文件和.obj文件打包到一个可执行文件中,程序在运行时不需要加载其他的库文件。
动态链接是指在编译时只链接必要的函数,程序在运行时再去加载其他的库文件,这样可以减小可执行文件的大小。
2.2 链接时出现的错误
在链接时可能会出现符号找不到、符号重复定义等错误。常见的解决方法是:
- 在编译时使用-g选项,生成调试信息,在链接时使用-Wl,-Map选项,生成可执行文件的链接器脚本和符号表,通过查看链接器脚本和符号表来解决问题。
- 如果要使用一个第三方库,需要在编译时指定库文件的路径,并在链接时加上该库的名称。
2.3 示例说明
假设我们要编译一个简单的C++程序,包含两个源文件main.cpp和hello.cpp。其中main.cpp包含一个主函数,调用hello.cpp中的函数say_hello。我们可以按照以下步骤进行编译和链接:
- 编写main.cpp和hello.cpp两个源文件。
//main.cpp
#include <iostream>
#include "hello.h"
using namespace std;
int main()
{
say_hello();
return 0;
}
//hello.h
#ifndef HELLO_H
#define HELLO_H
void say_hello();
#endif
//hello.cpp
#include <iostream>
#include "hello.h"
using namespace std;
void say_hello()
{
cout << "Hello, World!" << endl;
}
- 在编译时生成目标文件
g++ -c main.cpp -o main.o
g++ -c hello.cpp -o hello.o
- 在链接时生成可执行文件
g++ main.o hello.o -o hello_world
- 运行可执行文件
./hello_world
3. objdump工具的使用
3.1 常用参数
objdump的常用参数如下:
- -d:将ELF文件中所有可执行代码的汇编指令反汇编输出。
- -S:将ELF文件中所有可执行代码的汇编指令反汇编输出,并且在每条汇编指令前面加上其对应的源代码(如果ELF中保存了调试信息)。
- -M:设置反汇编的指令集。例如,-Mintel表示使用Intel格式的汇编代码,-Mgnu表示使用GNU格式的汇编代码。
- -C:显示自动类型转换后的C++符号。
- -t:输出符号表。
- -G:输出动态符号表(ELF格式文件才有效)。
3.2 示例说明
- 使用objdump反汇编可执行文件
我们可以使用objdump来反汇编hello_world这个可执行文件,查看其汇编代码。
objdump -d -Mintel hello_world
输出信息如下(部分行省略):
080486c0 <_ZNSt8ios_base4InitC1Ev@plt>:
80486c0: ff 25 28 a0 04 08 jmp *0x804a028
80486c6: 68 00 00 00 00 push $0x0
80486cb: e9 e0 ff ff ff jmp 80486b0 <_init+0x20>
080486d0 <_ZNSt8ios_base4InitD1Ev@plt>:
80486d0: ff 25 2c a0 04 08 jmp *0x804a02c
80486d6: 68 01 00 00 00 push $0x1
80486db: e9 d0 ff ff ff jmp 80486b0 <_init+0x20>
080486e0 <__gmon_start__@plt>:
80486e0: ff 25 30 a0 04 08 jmp *0x804a030
80486e6: 68 02 00 00 00 push $0x2
80486eb: e9 c0 ff ff ff jmp 80486b0 <_init+0x20>
080486f0 <_exit@plt>:
80486f0: ff 25 34 a0 04 08 jmp *0x804a034
80486f6: 68 03 00 00 00 push $0x3
80486fb: e9 b0 ff ff ff jmp 80486b0 <_init+0x20>
08048700 <__libc_start_main@plt>:
8048700: ff 25 38 a0 04 08 jmp *0x804a038
8048706: 68 04 00 00 00 push $0x4
804870b: e9 a0 ff ff ff jmp 80486b0 <_init+0x20>
08048710 <__ctype_tolower_loc@plt>:
8048710: ff 25 3c a0 04 08 jmp *0x804a03c
8048716: 68 05 00 00 00 push $0x5
804871b: e9 90 ff ff ff jmp 80486b0 <_init+0x20>
08048720 <__cxa_atexit@plt>:
8048720: ff 25 40 a0 04 08 jmp *0x804a040
8048726: 68 06 00 00 00 push $0x6
804872b: e9 80 ff ff ff jmp 80486b0 <_init+0x20>
08048730 <__libc_malloc@plt>:
8048730: ff 25 44 a0 04 08 jmp *0x804a044
8048736: 68 07 00 00 00 push $0x7
- 使用objdump反汇编静态库
我们可以使用objdump来反汇编编译生成的静态库libhello.a,并查看符号表。
objdump -t libhello.a
输出信息如下:
libhello.a(hello.o):
00000000 l df *ABS* 00000000 hello.cpp
00000000 l d .text 00000000 .text
00000000 l d .data 00000000 .data
00000000 l d .bss 00000000 .bss
00000000 l O .data 00000001 message
00000000 l F .text 0000000b say_hello
4. 总结
本文介绍了C/C++程序链接和objdump工具的使用方法,并给出了两个示例说明。开发人员可以根据实际需要,灵活运用链接和反汇编工具,提高代码的性能和安全性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C/C++程序链接与反汇编工具objdump的使用介绍 - Python技术站