objdump -r 和 -R 开关之间的区别

逆向工程 二元分析 转储
2021-06-17 03:05:07

objdump 手册页说,

-r
--reloc
      Print the relocation entries of the file.  If used with -d or -D,
      the relocations are printed interspersed with the disassembly.

-R
--dynamic-reloc
      Print the dynamic relocation entries of the file. This is only
      meaningful for dynamic objects, such as certain types of shared
      libraries. As for -r, if used with -d or -D, the relocations are
      printed interspersed with the disassembly.

有人可以解释一下这两个选项有何不同吗?重定位和动态重定位条目有什么区别?

2个回答

普通目标文件

正如注释所说,-R仅对动态对象有意义。对于.o来自简单程序的普通文件,-r将显示重定位条目。例如,这个简单的程序:

#include <stdio.h>
int main() {
    puts("Hello, world!\");
}

我们可以用这个生成一个目标文件:

cc -Wall -Wextra -pedantic -std=c11   -c -o sample.o sample.c

当我们运行命令时产生这个输出objdump -r sample.o

sample.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
0000000000000005 R_X86_64_32       .rodata
000000000000000a R_X86_64_PC32     puts-0x0000000000000004


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE 
0000000000000020 R_X86_64_PC32     .text

(这是一个 x86_64 Linux 机器。)

随着objdump -R sample.o我们得到这样的:

objdump: sample.o: not a dynamic object
objdump: sample.o: Invalid operation

这是意料之中的,因为这不是共享库。

共享库

相比之下,我们可以使用以下代码:

#include <stdio.h>
int hello() {
    return puts("Hello, world!\n");
}

并用这个创建一个库:

gcc -Wall -Wextra -pedantic -std=c11 -fPIC -shared -o libsample.so sample.c

现在-R是有道理的:

objdump -R libsample.so 

输出:

libsample.so:     file format elf64-x86-64

DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE 
0000000000200df8 R_X86_64_RELATIVE  *ABS*+0x0000000000000660
0000000000200e00 R_X86_64_RELATIVE  *ABS*+0x0000000000000620
0000000000200e10 R_X86_64_RELATIVE  *ABS*+0x0000000000200e10
0000000000200fd8 R_X86_64_GLOB_DAT  _ITM_deregisterTMCloneTable
0000000000200fe0 R_X86_64_GLOB_DAT  __gmon_start__
0000000000200fe8 R_X86_64_GLOB_DAT  _Jv_RegisterClasses
0000000000200ff0 R_X86_64_GLOB_DAT  _ITM_registerTMCloneTable
0000000000200ff8 R_X86_64_GLOB_DAT  __cxa_finalize@GLIBC_2.2.5
0000000000201018 R_X86_64_JUMP_SLOT  puts@GLIBC_2.2.5

玩游戏

还有其他两个工具:readelfelfedit,让我们来看看和修改二进制的更多细节。如果我们创建一个如上图所示的共享对象,但是在 32 位 Linux 机器上然后运行readelf -a libsample.so输出很长,但从这个开始:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x3f0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          5884 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 26

然后我们可以玩游戏,例如将文件更改为 EXEC 类型而不是 DYN 类型:

elfedit --output-type=EXEC test.so

现在,如果我们重新运行readelf,除了那个标签之外,一切都是一样的:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x3f0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          5884 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 26

尽管类型已更改,但它仍将用作共享库。

动态重定位是由动态链接器(通常ld.so或等效的)应用的重定位,而不是链接编辑器(例如ld)用于目标文件的重定位。它们由动态部分条目(例如DT_RELDT_RELA和 )指向DT_JMPREL动态链接器通常只支持有限的一组重定位。不仅共享对象而且动态(非静态)可执行文件都可能具有动态重定位。未剥离的二进制文件可能还有剩余的非动态重定位,但动态链接器不使用这些重定位。