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.


谁能解释两个选项有何不同?重定位条目和动态重定位条目有什么区别?

#1 楼

普通对象文件

如注所述,-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


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

评论


在此二进制文件(不是共享对象)上,-r不起作用,而-R有效。你怎么解释呢?

– Holmes.Sherlock
16 Dec 20'在16:49

我已经在答案中添加了确切显示其操作方法的信息。

–爱德华
16 Dec 20 '18:00

#2 楼

动态重定位是由动态链接器(通常是ld.so或等价的东西)应用的重定位,与对象文件的重定位的链接编辑器(例如ld)相反。它们由诸如DT_RELDT_RELADT_JMPREL的动态节条目指向。动态链接器通常仅支持有限的重定位集。
不仅共享对象而且动态(非静态)可执行文件都可能具有动态重定位。未剥离的二进制文件可能还具有其余的非动态重定位,但动态链接程序未使用这些重定位。