为什么符号malloc,__ mayoc和__libc_malloc指向相同的代码地址?

时间:2014-03-03 19:13:00

标签: c++ c linux gcc symbols

当我从符号表中grep malloc时,使用以下命令

readelf -s bin | grep malloc

我可以看到符号malloc,__ mayoc和__libc_malloc共享相同的代码地址。我可以获取PC地址,想知道用户程序何时调用malloc,但是__malloc和__libc_malloc给了我嘈杂的信息,有什么好办法区分malloc吗?当我使用-static编译二进制文件时,所以dlsym在这种情况下不起作用。

1 个答案:

答案 0 :(得分:6)

除非你使用动态链接,否则你将无法区分它们,因为它们将是同一个东西,静态链接的行为将用例程的地址替换名称引用。

举个例子:

#include <stdlib.h>

extern void *__malloc(size_t);
extern void *__libc_malloc(size_t);

int
main(int argc, char **argv)
{
    void *v = malloc(200);
    free(v);
    v = __malloc(200);
    free(v);
    v = __libc_malloc(200);
    free(v);
    return 0;
}

使用:gcc -static -o example example.c编译时,然后我们反汇编我们看到的主程序:

  40103e:       55                      push   %rbp
  40103f:       48 89 e5                mov    %rsp,%rbp
  401042:       48 83 ec 20             sub    $0x20,%rsp
  401046:       89 7d ec                mov    %edi,-0x14(%rbp)
  401049:       48 89 75 e0             mov    %rsi,-0x20(%rbp)
  40104d:       bf c8 00 00 00          mov    $0xc8,%edi
  401052:       e8 19 52 00 00          callq  406270 <__libc_malloc>
  401057:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  40105b:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  40105f:       48 89 c7                mov    %rax,%rdi
  401062:       e8 09 56 00 00          callq  406670 <__cfree>
  401067:       bf c8 00 00 00          mov    $0xc8,%edi
  40106c:       e8 ff 51 00 00          callq  406270 <__libc_malloc>
  401071:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  401075:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  401079:       48 89 c7                mov    %rax,%rdi
  40107c:       e8 ef 55 00 00          callq  406670 <__cfree>
  401081:       bf c8 00 00 00          mov    $0xc8,%edi
  401086:       e8 e5 51 00 00          callq  406270 <__libc_malloc>
  40108b:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  40108f:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  401093:       48 89 c7                mov    %rax,%rdi
  401096:       e8 d5 55 00 00          callq  406670 <__cfree>
  40109b:       b8 00 00 00 00          mov    $0x0,%eax
  4010a0:       c9                      leaveq 
  4010a1:       c3                      retq   
  4010a2:       66 2e 0f 1f 84 00 00    nopw   %cs:0x0(%rax,%rax,1)
  4010a9:       00 00 00 
  4010ac:       0f 1f 40 00             nopl   0x0(%rax)

即。代码不区分条目。

现在,如果你使用动态链接;你会得到不同的结果。首先,__malloc在结果二进制文件中不可用 - 这是因为__malloc名称是静态链接的副作用(有一种方法可以防止它被生成,但是机制让我逃脱了。)因此,当我们编译二进制文件(删除__malloc调用)时,main看起来像:

  40058d:       55                      push   %rbp
  40058e:       48 89 e5                mov    %rsp,%rbp
  400591:       48 83 ec 20             sub    $0x20,%rsp
  400595:       89 7d ec                mov    %edi,-0x14(%rbp)
  400598:       48 89 75 e0             mov    %rsi,-0x20(%rbp)
  40059c:       bf c8 00 00 00          mov    $0xc8,%edi
  4005a1:       e8 ea fe ff ff          callq  400490 <malloc@plt>
  4005a6:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  4005aa:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  4005ae:       48 89 c7                mov    %rax,%rdi
  4005b1:       e8 9a fe ff ff          callq  400450 <free@plt>
  4005b6:       bf c8 00 00 00          mov    $0xc8,%edi
  4005bb:       e8 c0 fe ff ff          callq  400480 <__libc_malloc@plt>
  4005c0:       48 89 45 f8             mov    %rax,-0x8(%rbp)
  4005c4:       48 8b 45 f8             mov    -0x8(%rbp),%rax
  4005c8:       48 89 c7                mov    %rax,%rdi
  4005cb:       e8 80 fe ff ff          callq  400450 <free@plt>
  4005d0:       b8 00 00 00 00          mov    $0x0,%eax
  4005d5:       c9                      leaveq 
  4005d6:       c3                      retq   
  4005d7:       66 0f 1f 84 00 00 00    nopw   0x0(%rax,%rax,1)
  4005de:       00 00

因此,要确定__libc_mallocmalloc的使用,您可以检查对例程的plt条目的调用。

这当然都假设您实际上正在对二进制文件执行某种类型的静态分析。如果你在运行时这样做,通常的方法是使用LD_PRELOAD进行库拦截,这是一个完全不同的问题。