温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C/C++程序链接与反汇编工具objdump如何使用

发布时间:2023-02-07 09:47:48 阅读:209 作者:iii 栏目:开发技术
C++开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

C/C++程序链接与反汇编工具objdump如何使用

1. 概述

在C/C++程序开发过程中,链接和反汇编是两个非常重要的步骤。链接是将多个目标文件合并成一个可执行文件的过程,而反汇编则是将机器码转换回汇编代码的过程。objdump是一个强大的工具,可以帮助我们进行这些操作。本文将详细介绍如何使用objdump工具进行C/C++程序的链接与反汇编。

2. objdump简介

objdump是GNU Binutils工具集中的一个工具,主要用于显示目标文件的信息。它可以用来反汇编目标文件、查看符号表、段信息等。objdump支持多种目标文件格式,包括ELF、COFF、Mach-O等。

2.1 安装objdump

在大多数Linux发行版中,objdump已经包含在binutils包中。如果系统中没有安装objdump,可以通过以下命令安装:

sudo apt-get install binutils

在macOS上,可以通过Homebrew安装:

brew install binutils

3. 使用objdump进行反汇编

反汇编是将机器码转换回汇编代码的过程。通过反汇编,我们可以查看程序的底层实现,分析程序的执行流程。

3.1 反汇编目标文件

假设我们有一个简单的C程序hello.c

#include <stdio.h>

int main() {
    printf("Hello, World!\n");
    return 0;
}

首先,我们需要编译这个程序并生成目标文件:

gcc -c hello.c -o hello.o

然后,使用objdump反汇编目标文件:

objdump -d hello.o

输出结果如下:

hello.o:     file format elf64-x86-64

Disassembly of section .text:

0000000000000000 <main>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   48 8d 3d 00 00 00 00    lea    0x0(%rip),%rdi        # b <main+0xb>
   b:   e8 00 00 00 00          callq  10 <main+0x10>
  10:   b8 00 00 00 00          mov    $0x0,%eax
  15:   5d                      pop    %rbp
  16:   c3                      retq

3.2 反汇编可执行文件

我们也可以直接反汇编可执行文件。首先,编译并链接生成可执行文件:

gcc hello.c -o hello

然后,使用objdump反汇编可执行文件:

objdump -d hello

输出结果如下:

hello:     file format elf64-x86-64

Disassembly of section .init:

0000000000401000 <_init>:
  401000:       48 83 ec 08             sub    $0x8,%rsp
  401004:       48 8b 05 ed 2f 00 00    mov    0x2fed(%rip),%rax        # 403ff8 <__gmon_start__>
  40100b:       48 85 c0                test   %rax,%rax
  40100e:       74 02                   je     401012 <_init+0x12>
  401010:       ff d0                   callq  *%rax
  401012:       48 83 c4 08             add    $0x8,%rsp
  401016:       c3                      retq

Disassembly of section .plt:

0000000000401020 <.plt>:
  401020:       ff 35 e2 2f 00 00       pushq  0x2fe2(%rip)        # 404008 <_GLOBAL_OFFSET_TABLE_+0x8>
  401026:       ff 25 e4 2f 00 00       jmpq   *0x2fe4(%rip)        # 404010 <_GLOBAL_OFFSET_TABLE_+0x10>
  40102c:       0f 1f 40 00             nopl   0x0(%rax)

...

Disassembly of section .text:

0000000000401040 <main>:
  401040:       55                      push   %rbp
  401041:       48 89 e5                mov    %rsp,%rbp
  401044:       48 8d 3d b9 0f 00 00    lea    0xfb9(%rip),%rdi        # 402004 <_IO_stdin_used+0x4>
  40104b:       e8 e0 ff ff ff          callq  401030 <puts@plt>
  401050:       b8 00 00 00 00          mov    $0x0,%eax
  401055:       5d                      pop    %rbp
  401056:       c3                      retq

3.3 反汇编特定函数

如果我们只想反汇编某个特定的函数,可以使用-j选项指定段名,并结合-d选项:

objdump -d -j .text hello

这将只反汇编.text段中的代码。

4. 使用objdump查看符号表

符号表包含了程序中定义的函数和变量的信息。通过查看符号表,我们可以了解程序中定义的符号及其地址。

4.1 查看符号表

使用objdump查看符号表:

objdump -t hello

输出结果如下:

hello:     file format elf64-x86-64

SYMBOL TABLE:
0000000000401000 l    d  .init  0000000000000000              .init
0000000000401020 l    d  .plt   0000000000000000              .plt
0000000000401040 l    d  .text  0000000000000000              .text
0000000000401058 l    d  .fini  0000000000000000              .fini
0000000000402000 l    d  .rodata        0000000000000000              .rodata
0000000000402004 l    d  .eh_frame      0000000000000000              .eh_frame
0000000000403ff0 l    d  .data  0000000000000000              .data
0000000000404000 l    d  .bss   0000000000000000              .bss
0000000000000000 l    df *ABS*  0000000000000000              crtstuff.c
0000000000401040 g     F .text  0000000000000017              main
0000000000402000 g     O .rodata        0000000000000004              _IO_stdin_used
0000000000403ff0 g     O .data  0000000000000000              __data_start
0000000000403ff0 g     O .data  0000000000000000              __dso_handle
0000000000404000 g     O .bss   0000000000000000              __bss_start
0000000000404000 g     O .bss   0000000000000000              _end
0000000000401000 g     F .init  0000000000000016              _init
0000000000401058 g     F .fini  0000000000000009              _fini

4.2 查看动态符号表

动态符号表包含了动态链接库中的符号信息。使用-T选项查看动态符号表:

objdump -T hello

输出结果如下:

hello:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 puts
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __libc_start_main
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_finalize

5. 使用objdump查看段信息

段信息包含了程序中各个段的大小、地址等信息。通过查看段信息,我们可以了解程序的内存布局。

5.1 查看段信息

使用objdump查看段信息:

objdump -h hello

输出结果如下:

hello:     file format elf64-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .interp       0000001c  0000000000400238  0000000000400238  00000238  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  0000000000400254  0000000000400254  00000254  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  0000000000400274  0000000000400274  00000274  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     0000001c  0000000000400298  0000000000400298  00000298  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000060  00000000004002b8  00000000004002b8  000002b8  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       0000003a  0000000000400318  0000000000400318  00000318  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  00000008  0000000000400352  0000000000400352  00000352  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  0000000000400360  0000000000400360  00000360  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rela.dyn     00000018  0000000000400380  0000000000400380  00000380  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rela.plt     00000030  0000000000400398  0000000000400398  00000398  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         00000017  0000000000401000  0000000000401000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000030  0000000000401020  0000000000401020  00001020  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text         00000117  0000000000401040  0000000000401040  00001040  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .fini         00000009  0000000000401058  0000000000401058  00001058  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .rodata       00000004  0000000000402000  0000000000402000  00002000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .eh_frame     00000038  0000000000402004  0000000000402004  00002004  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .data         00000010  0000000000403ff0  0000000000403ff0  00002ff0  2**3
                  CONTENTS, ALLOC, LOAD, DATA
 17 .bss          00000008  0000000000404000  0000000000404000  00003000  2**0
                  ALLOC
 18 .comment      0000002a  0000000000000000  0000000000000000  00003000  2**0
                  CONTENTS, READONLY

6. 使用objdump查看重定位信息

重定位信息包含了程序中需要重定位的符号及其地址。通过查看重定位信息,我们可以了解程序在链接时需要进行哪些重定位操作。

6.1 查看重定位信息

使用objdump查看重定位信息:

objdump -r hello

输出结果如下:

hello:     file format elf64-x86-64

RELOCATION RECORDS FOR [.rela.dyn]:
OFFSET           TYPE              VALUE
0000000000403ff0 R_X86_64_RELATIVE  *ABS*+0x0000000000403ff0
0000000000403ff8 R_X86_64_RELATIVE  *ABS*+0x0000000000403ff8

RELOCATION RECORDS FOR [.rela.plt]:
OFFSET           TYPE              VALUE
0000000000404018 R_X86_64_JUMP_SLOT  puts
0000000000404020 R_X86_64_JUMP_SLOT  __libc_start_main
0000000000404028 R_X86_64_JUMP_SLOT  __cxa_finalize

7. 总结

objdump是一个功能强大的工具,可以帮助我们进行C/C++程序的链接与反汇编。通过objdump,我们可以查看目标文件的反汇编代码、符号表、段信息以及重定位信息。这些信息对于理解程序的底层实现、调试程序以及分析程序的内存布局非常有帮助。

在实际开发中,objdump常常与其他工具(如gdbnm等)结合使用,以更全面地分析和调试程序。希望本文的介绍能够帮助你更好地理解和使用objdump工具。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×