我知道在我的文件objdump -dr
中使用call
时,机器代码显示为e8 00 00 00 00
,因为它尚未链接。但是我需要找出链接器完成它之后00 00 00 00
会变成什么。我知道它应该计算偏移量,但我对此有点困惑。
作为下面代码的示例,在链接器部分完成之后,e8 00 00 00 00
应该如何?我如何得到答案?
我正在测试这个示例代码:(我正试着打电话给moo)
Disassembly of section .text:
0000000000000000 <foo>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 89 7d fc mov %edi,-0x4(%rbp)
7: 8b 45 fc mov -0x4(%rbp),%eax
a: 83 e8 0a sub $0xa,%eax
d: 5d pop %rbp
e: c3 retq
000000000000000f <moo>:
f: 55 push %rbp
10: 48 89 e5 mov %rsp,%rbp
13: 89 7d fc mov %edi,-0x4(%rbp)
16: b8 01 00 00 00 mov $0x1,%eax
1b: 5d pop %rbp
1c: c3 retq
000000000000001d <main>:
1d: 55 push %rbp
1e: 48 89 e5 mov %rsp,%rbp
21: 48 83 ec 10 sub $0x10,%rsp
25: c7 45 fc 8e 0c 00 00 movl $0xc8e,-0x4(%rbp)
2c: 8b 45 fc mov -0x4(%rbp),%eax
2f: 89 c7 mov %eax,%edi
31: e8 00 00 00 00 callq 36 <main+0x19>
32: R_X86_64_PC32 moo-0x4
36: 89 45 fc mov %eax,-0x4(%rbp)
39: b8 00 00 00 00 mov $0x0,%eax
3e: c9 leaveq
3f: c3 retq
答案 0 :(得分:4)
使用objdump -r
,您的反汇编打印了您的反汇编-d
:
31: e8 00 00 00 00 callq 36 <main+0x19>
32: R_X86_64_PC32 moo-0x4
ld-linux.so.2
加载器将重定位对象(在现代世界中,它甚至可以将可执行文件重定位到随机地址)并使用正确的地址填充重定位。
通过在gdb
添加断点并启动程序(链接器在main
函数启动之前工作)来检查main
:
gdb ./program
(gdb) start
(gdb) disassemble main
如果要编译没有重定位的代码,请显示源代码和编译选项。
答案 1 :(得分:3)
我所知道的几个架构上的对象文件和可执行文件 not 必然会在链接时修复跳转目标。
这是一项提供灵活性的功能。
跳转目标地址不会必须修复,直到指令执行之前。它们不需要在链接时修复 - 甚至也不需要在程序启动时!
大多数系统(Windows,Linux,Unix,VAX / VMS)将目标代码中的这些位置标记为需要调整的地址。还有关于目标地址是什么,它的引用类型(例如绝对或相对; 16位,24位,32位,64位等)的其他信息。
零值不一定是占位符,而是评估结果的基值。例如,如果指令是 - 无论出于何种原因 - call 5+external_address
,那么对象代码中可能会有5
(e8 05 00 00 00
)。
如果要查看执行时的地址,请在调试器下运行程序,在该指令处放置断点,然后在执行之前查看该指令。
一种常见的反病毒安全增强功能,称为ASLR(address space layout randomization),故意在不一致的地址加载程序部分,以阻止恶意代码改变程序或数据。在此环境中运行的程序可能没有分配某些目标地址,直到程序运行一段时间。
(相关兴趣,特别是VAX / VMS有一个复杂的修正模式,其中一个等式描述了计算一个值所需的操作。操作包括加法,减法,乘法,除法,移位,旋转,可能是其他人。我从未看到它实际使用过,但考虑如何应用这种能力是很有趣的。)
答案 2 :(得分:0)
但你清楚知道如何做到这一切。你知道如何在链接之后进行反汇编,之后再查看链接器如何修改这些指令。
asm(".globl _start; _start: nop\n");
unsigned int foo ( unsigned int x )
{
return(x+5);
}
unsigned int moo ( unsigned int x )
{
return(foo(x)+3);
}
int main ( void )
{
return(moo(3)+2);
}
0000000000000000 <_start>:
0: 90 nop
0000000000000001 <foo>:
1: 55 push %rbp
2: 48 89 e5 mov %rsp,%rbp
5: 89 7d fc mov %edi,-0x4(%rbp)
8: 8b 45 fc mov -0x4(%rbp),%eax
b: 83 c0 05 add $0x5,%eax
e: 5d pop %rbp
f: c3 retq
0000000000000010 <moo>:
10: 55 push %rbp
11: 48 89 e5 mov %rsp,%rbp
14: 48 83 ec 08 sub $0x8,%rsp
18: 89 7d fc mov %edi,-0x4(%rbp)
1b: 8b 45 fc mov -0x4(%rbp),%eax
1e: 89 c7 mov %eax,%edi
20: e8 00 00 00 00 callq 25 <moo+0x15>
25: 83 c0 03 add $0x3,%eax
28: c9 leaveq
29: c3 retq
000000000000002a <main>:
2a: 55 push %rbp
2b: 48 89 e5 mov %rsp,%rbp
2e: bf 03 00 00 00 mov $0x3,%edi
33: e8 00 00 00 00 callq 38 <main+0xe>
38: 83 c0 02 add $0x2,%eax
3b: 5d pop %rbp
3c: c3 retq
0000000000001000 <_start>:
1000: 90 nop
0000000000001001 <foo>:
1001: 55 push %rbp
1002: 48 89 e5 mov %rsp,%rbp
1005: 89 7d fc mov %edi,-0x4(%rbp)
1008: 8b 45 fc mov -0x4(%rbp),%eax
100b: 83 c0 05 add $0x5,%eax
100e: 5d pop %rbp
100f: c3 retq
0000000000001010 <moo>:
1010: 55 push %rbp
1011: 48 89 e5 mov %rsp,%rbp
1014: 48 83 ec 08 sub $0x8,%rsp
1018: 89 7d fc mov %edi,-0x4(%rbp)
101b: 8b 45 fc mov -0x4(%rbp),%eax
101e: 89 c7 mov %eax,%edi
1020: e8 dc ff ff ff callq 1001 <foo>
1025: 83 c0 03 add $0x3,%eax
1028: c9 leaveq
1029: c3 retq
000000000000102a <main>:
102a: 55 push %rbp
102b: 48 89 e5 mov %rsp,%rbp
102e: bf 03 00 00 00 mov $0x3,%edi
1033: e8 d8 ff ff ff callq 1010 <moo>
1038: 83 c0 02 add $0x2,%eax
103b: 5d pop %rbp
103c: c3 retq
例如
20: e8 00 00 00 00 callq 25 <moo+0x15>
1033: e8 d8 ff ff ff callq 1010 <moo>