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
玩游戏
那里还有另外两个实用程序:
readelf
和elfedit
,它使我们可以更详细地查看和修改二进制文件。如果我们如上所述创建共享对象,但是在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
尽管类型已更改,但仍将用作共享库。
#2 楼
动态重定位是由动态链接器(通常是ld.so
或等价的东西)应用的重定位,与对象文件的重定位的链接编辑器(例如ld
)相反。它们由诸如DT_REL
,DT_RELA
和DT_JMPREL
的动态节条目指向。动态链接器通常仅支持有限的重定位集。不仅共享对象而且动态(非静态)可执行文件都可能具有动态重定位。未剥离的二进制文件可能还具有其余的非动态重定位,但动态链接程序未使用这些重定位。
评论
在此二进制文件(不是共享对象)上,-r不起作用,而-R有效。你怎么解释呢?
– Holmes.Sherlock
16 Dec 20'在16:49
我已经在答案中添加了确切显示其操作方法的信息。
–爱德华
16 Dec 20 '18:00