什么是“__gmon_start__”符号?
Posted
技术标签:
【中文标题】什么是“__gmon_start__”符号?【英文标题】:What is the "__gmon_start__" symbol? 【发布时间】:2012-09-23 16:58:41 【问题描述】:我正在用gcc hello.c -o hello -O3
编译这段代码:
#include <stdio.h>
int main(void)
printf("Hello world\n");
return 0;
当我列出我得到的重定位时:
test@southpark$ readelf -r hello | grep gmon
080495a4 00000106 R_386_GLOB_DAT 00000000 __gmon_start__
080495b4 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
当我列出这个文件中的符号时,我得到:
test@southpark$ readelf -s hello | grep gmon
1: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
48: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
gmon_start
和 gprof 有关系吗?为什么即使我没有使用-pg
或-g
编译/链接,它也会重新定位该符号?哪个库会解析这个符号?
【问题讨论】:
【参考方案1】:做了一点谷歌搜索,从here找到了这个:
函数 call_gmon_start 初始化 gmon 分析系统。 当使用 -pg 标志编译二进制文件时启用此系统, 并创建用于 gprof(1) 的输出。在情景的情况下 二进制 call_gmon_start 直接位于 _start 之后 功能。 call_gmon_start 函数在 全局偏移表(也称为 __gmon_start__),如果不是 NULL, 将控制权传递给指定的地址。 __gmon_start__ 元素 指向 gmon 初始化函数,该函数开始录制 分析信息并注册清理功能 退出()。然而,在我们的例子中,gmon 没有被使用,因此 __gmon_start__ 为 NULL。
那么...
-
是的,它确实与 gprof 有关
我不确定为什么符号会留在里面。也许只是为 gprof 编译时的占位符?
更新:
好的,所以我编译了你的代码,有没有-pg
。看起来__gmon_start__
被映射到已编译程序中的地址。话虽如此,我不认为有一个库可以解析该符号,而是程序本身。
-pg
:
akyserr@orion:~$ readelf -r hello
Relocation section '.rel.dyn' at offset 0x32c contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049fec 00000806 R_386_GLOB_DAT 08048460 __gmon_start__
Relocation section '.rel.plt' at offset 0x334 contains 6 entries:
Offset Info Type Sym.Value Sym. Name
0804a000 00000607 R_386_JUMP_SLOT 080483b0 _mcleanup
0804a004 00000107 R_386_JUMP_SLOT 00000000 __monstartup
0804a008 00000207 R_386_JUMP_SLOT 00000000 mcount
0804a00c 00000307 R_386_JUMP_SLOT 00000000 __cxa_atexit
0804a010 00000407 R_386_JUMP_SLOT 00000000 puts
0804a014 00000507 R_386_JUMP_SLOT 00000000 __libc_start_main
__gmon_start__ 代码的objdump:
akyserr@orion:~$ objdump -S hello | grep "460 <__gmon_start__>:" -A 20
08048460 <__gmon_start__>:
8048460: 83 ec 1c sub $0x1c,%esp
8048463: a1 20 a0 04 08 mov 0x804a020,%eax
8048468: 85 c0 test %eax,%eax
804846a: 75 2a jne 8048496 <__gmon_start__+0x36>
804846c: c7 05 20 a0 04 08 01 movl $0x1,0x804a020
8048473: 00 00 00
8048476: c7 44 24 04 36 86 04 movl $0x8048636,0x4(%esp)
804847d: 08
804847e: c7 04 24 30 84 04 08 movl $0x8048430,(%esp)
8048485: e8 36 ff ff ff call 80483c0 <__monstartup@plt>
804848a: c7 04 24 b0 83 04 08 movl $0x80483b0,(%esp)
8048491: e8 1a 01 00 00 call 80485b0 <atexit>
8048496: 83 c4 1c add $0x1c,%esp
8048499: c3 ret
804849a: 90 nop
804849b: 90 nop
804849c: 90 nop
804849d: 90 nop
在已编译的hello
程序中存在__gmon_start__
,您可以看到__monstartup
被调用。 (monstartup man page)
没有-pg
:
akyserr@orion:~$ readelf -r hello
Relocation section '.rel.dyn' at offset 0x290 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
08049ff0 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x298 contains 3 entries:
Offset Info Type Sym.Value Sym. Name
0804a000 00000107 R_386_JUMP_SLOT 00000000 puts
0804a004 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__
0804a008 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main
您可以在这里看到,__gmon_start__
的符号值设置为00000000
。
【讨论】:
关于第三个问题?我应该将 GOT 中的最后一个条目视为 gmon_start 的地址吗?此外,检查“hello”的二进制文件,发现有一个条目:__gmon_start__@plt 和另一个(PLT 条目)__gmon_start__@plt-0x10> 那么gmon_start
的偏移量是如何映射到物理地址的呢?以上是关于什么是“__gmon_start__”符号?的主要内容,如果未能解决你的问题,请参考以下文章