【问题标题】:Why symbols malloc, __malloc and __libc_malloc point to the same code address?为什么符号 malloc、__malloc 和 __libc_malloc 指向同一个代码地址?
【发布时间】:2014-04-05 00:01:57
【问题描述】:

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

readelf -s bin | grep malloc

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

【问题讨论】:

  • @user1147800 所以您将代码编译为 C 和 C++ 并得到相同的输出?
  • @crashmstr,使用 gcc 而不是 g++ 编译
  • @user1147800 那么为什么要标记 C++?
  • @crashmstr,无论是 g++ 还是 gcc,使用 malloc/free,cstdlib 都用 g++ 调用,这也适用于 glibc。所以不管g++还是gcc都是一样的。我认为它仍然与 g++ 和 c++ 用户相关。
  • @crashmstr,如果你能添加回 c++ 标签,我将不胜感激,因为我就是这么认为的,如果你不这么认为,如果你能用理由说服我,我将不胜感激,非常感谢!跨度>

标签: c++ c linux gcc symbols


【解决方案1】:

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

举个例子:

#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 进行库拦截,这是一个完全不同的问题。

【讨论】:

    猜你喜欢
    • 2019-07-15
    • 1970-01-01
    • 2021-06-28
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    相关资源
    最近更新 更多