为啥 GCC 编译的应用程序总是包含 _mcount 符号?

Posted

技术标签:

【中文标题】为啥 GCC 编译的应用程序总是包含 _mcount 符号?【英文标题】:Why do applications compiled by GCC always contain the _mcount symbol?为什么 GCC 编译的应用程序总是包含 _mcount 符号? 【发布时间】:2011-01-02 23:44:14 【问题描述】:

库并不总是包含 _mcount 符号,但应用程序包含(您可以使用 gobjdump 或 nm 实用程序验证这一点)。我读过 _mcount 用于实现分析,但即使禁用了分析并启用了优化 (-O2),该符号仍然存在。它还有其他用途吗?

更新:我在 Solaris 上,所以这是结合 GCC 的 Solaris 链接器,我不确定这是否会有所不同。 GCC 版本是 4.2.2。即使我编译的文件只包含代码 int main() return 0; 而没有链接库,也会发生这种情况。

更新2:我输入:

$ g++ -O2 mytest.cpp
$ nm a.out | grep _mcount
[65]    | 134547444|       1|FUNC |GLOB |0    |11     |_mcount

而且 g++ 没有任何别名。另外,我试过用sun CC编译器编译,没有这个问题。我也试过更新 GCC,符号在 4.4.1 中仍然存在。

【问题讨论】:

您的系统不会碰巧将gcc(或您正在使用的命令)别名为使用一些默认开关调用编译器的东西,是吗?你能发布你用来编译这个的确切调用吗? 无别名,用命令更新帖子。 【参考方案1】:

嗯。奇怪,在我的机器上(ubuntu 9.10)这不会发生。

为了一个测试,我刚刚编译了一个小的 hello-word:

#include <stdio.h>

int main (int argc, char **args)

  printf ("hello world\n");

编译
gcc test.c

它没有 _mcount 符号。我检查过:

nm a.out | grep -i count

尝试一些编译器开关(-g、-pg 等),结果发现该符号仅在您使用 -pg 编译应用程序时出现,在这种情况下,您在启用分析的情况下进行编译,因此 _mcount 符号有理由存在。

【讨论】:

我更新了我的帖子以澄清我没有指定 pg,但它仍然会发生。想知道有什么区别...【参考方案2】:

您是否链接到启用了分析的库?这将拉入_mcount

【讨论】:

【参考方案3】:

有关信息,

在我的 Linux 机器 (Archlinux x86) 上,GCC 4.4.2,在 a.out 上运行 nm 给出:

$ nm ./a.out 
08049594 d _DYNAMIC
08049680 d _GLOBAL_OFFSET_TABLE_
0804852c R _IO_stdin_used
         w _Jv_RegisterClasses
08049584 d __CTOR_END__
08049580 d __CTOR_LIST__
0804958c D __DTOR_END__
08049588 d __DTOR_LIST__
0804857c r __FRAME_END__
08049590 d __JCR_END__
08049590 d __JCR_LIST__
080496a0 A __bss_start
08049698 D __data_start
080484e0 t __do_global_ctors_aux
080483d0 t __do_global_dtors_aux
0804969c D __dso_handle
         w __gmon_start__
         U __gxx_personality_v0@@CXXABI_1.3
080484da T __i686.get_pc_thunk.bx
08049580 d __init_array_end
08049580 d __init_array_start
08048470 T __libc_csu_fini
08048480 T __libc_csu_init
         U __libc_start_main@@GLIBC_2.0
080496a0 A _edata
080496a8 A _end
0804850c T _fini
08048528 R _fp_hw
08048324 T _init
080483a0 T _start
080496a0 b completed.5829
08049698 W data_start
080496a4 b dtor_idx.5831
08048430 t frame_dummy
08048460 T main

a.out 上运行ldd 给出

$ ldd ./a.out 
linux-gate.so.1 =>  (0xb77b1000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb769b000)
    libm.so.6 => /lib/libm.so.6 (0xb7675000)
    libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xb7658000)
    libc.so.6 => /lib/libc.so.6 (0xb7511000)
    /lib/ld-linux.so.2 (0xb77b2000)

通过在其上运行nm 来尝试确定是否已使用分析支持构建了依赖库之一。正如@Emerick 所说,这将引入_mcount

【讨论】:

我没有链接任何库,请参阅我的原始帖子。 好吧g++自动链接libc,试试看 有趣,我试过了,libc有一个符号_mcount_newent,但没有_mcount。其他人在搜索 _mcount 时没有显示任何内容。仍然没有解释为什么 _mcount 会出现:/ 谷歌搜索 _mcount_newent 我得到了一些晦涩的源代码结果,但没有很好的英文解释。【参考方案4】:

没有帮助,但可能提供信息:

在全新安装 OpenSolaris 和 g++ 时,我看到了相同的结果。

在 OpenSolaris 上 gcc/++ 的手册页中,它指出调试信息的默认级别是“2”……但将其更改为 1 或 0 并不会消除 _mcount 符号。

如果我使用 cc-5.0 编译,_mcount 符号不存在。 (虽然用 cc 编译它是因为 cc 只是 gcc 的别名/包装器)。

在 Ubuntu 和 Fedora 上,符号不存在,除非使用 -pg 选项进行编译(在这种情况下,符号是 mcount 而不是 _mcount)。

【讨论】:

这很有趣,我可以把它放在 GCC 开发者的错误报告中,赞成 :)

以上是关于为啥 GCC 编译的应用程序总是包含 _mcount 符号?的主要内容,如果未能解决你的问题,请参考以下文章

gcc编译线程程序,为啥要加-lpthread,头文件已经包含了<pthread.h>了啊

gcc编译线程程序,为啥要加-lpthread,头文件已经包含了<pthread.h>了啊

为啥我的 gcc 编译器不能识别 bzip2 函数,但允许我包含它们所属的库?

GCC - 包含编译标志的宏

为啥这段代码不能用 VS2010 和 gcc 4.8.1 编译

为啥某些 LLVM 标准库标头包含其他标头但 GCC 不 [重复]