继续获得e8 00 00 00 00作为在装配中调用函数的机器代码

时间:2017-06-21 23:40:35

标签: assembly linker x86 disassembly machine-code

我知道在我的文件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

3 个答案:

答案 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,那么对象代码中可能会有5e8 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>