为什么gcc在汇编中使用相对于函数指针的相对地址?

时间:2019-02-16 23:50:03

标签: c gcc assembly x86-64

C来源:

int sum(int a, int b) {    
    return a + b;    
}    

int main() {    
    int (*ptr_sum_1)(int,int) = sum;   // assign the address of the "sum" 
    int (*ptr_sum_2)(int,int) = sum;   // to the function pointer 
    int (*ptr_sum_3)(int,int) = sum;    

    int a = (*ptr_sum_1)(2,4);   // call the "sum" through the pointer 
    int b = sum(2,4);            // call the "sum" by usual way

    return 0;    
}

汇编代码的关键部分:

lea rax, sum[rip]
mov QWORD PTR -24[rbp], rax
lea rax, sum[rip]
mov QWORD PTR -16[rbp], rax
lea rax, sum[rip]
mov QWORD PTR -8[rbp], rax

来自GDB的执行程序指令:

   0x5fa <sum>: push   rbp
   0x5fb <sum+1>:   mov    rbp,rsp
   0x5fe <sum+4>:   mov    DWORD PTR [rbp-0x4],edi
   0x601 <sum+7>:   mov    DWORD PTR [rbp-0x8],esi
   0x604 <sum+10>:  mov    edx,DWORD PTR [rbp-0x4]
   0x607 <sum+13>:  mov    eax,DWORD PTR [rbp-0x8]
   0x60a <sum+16>:  add    eax,edx
   0x60c <sum+18>:  pop    rbp
   0x60d <sum+19>:  ret    
   0x60e <main>:    push   rbp
   0x60f <main+1>:  mov    rbp,rsp
   0x612 <main+4>:  sub    rsp,0x20
   0x616 <main+8>:  lea    rax,[rip+0xffffffffffffffdd]        # 0x5fa <sum>
   0x61d <main+15>: mov    QWORD PTR [rbp-0x18],rax
   0x621 <main+19>: lea    rax,[rip+0xffffffffffffffd2]        # 0x5fa <sum>
   0x628 <main+26>: mov    QWORD PTR [rbp-0x10],rax
   0x62c <main+30>: lea    rax,[rip+0xffffffffffffffc7]        # 0x5fa <sum>
   0x633 <main+37>: mov    QWORD PTR [rbp-0x8],rax
   0x637 <main+41>: mov    rax,QWORD PTR [rbp-0x18]
   0x63b <main+45>: mov    esi,0x4
   0x640 <main+50>: mov    edi,0x2
   0x645 <main+55>: call   rax
   0x647 <main+57>: mov    DWORD PTR [rbp-0x20],eax
   0x64a <main+60>: mov    esi,0x4
   0x64f <main+65>: mov    edi,0x2
   0x654 <main+70>: call   0x5fa <sum>
   0x659 <main+75>: mov    DWORD PTR [rbp-0x1c],eax
   0x65c <main+78>: mov    eax,0x0
   0x661 <main+83>: leave  
   0x662 <main+84>: ret  

我认为sum标签只是sum过程的起始地址-0x5fa,所以我不明白为什么gcc无法使用它直接,但是为此使用计算sum[rip]

问题:

  1. 为什么在汇编中的sum[rip]指令中使用lea rax, sum[rip]而不是简单的sum标签,例如lea rax, sum
  2. mov rax, 0x5fa指令会做同样的事情吗?因为我们知道链接后的sum地址:call 0x5fa <sum>指令只是直接使用它。

1 个答案:

答案 0 :(得分:-1)

我相信这可能取决于您的GCC构建,但是取决于我使用的Linux发行版,所有设置都默认设置为PIC构建。那是位置独立代码。这对于共享库可执行文件都更好,因为可以将结果映射到任何位置的内存中,而无需进行修正。因为可以应用ASLR,所以对安全性更好。

使用x86-64,使用PIC并不会受到很大的惩罚,那么为什么不将它在所有地方都使用?