什么是“ __gmon_start__”符号?

问题描述 投票:20回答:1

我正在使用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进行编译/链接,该符号也有针对该符号的重定位?哪个库可以解析该符号?

c linux gcc elf binutils
1个回答
12
投票

做了一些谷歌搜索,并从here中找到了它:

函数call_gmon_start初始化gmon分析系统。当使用-pg标志编译二进制文件时,将启用此系统,并创建用于gprof(1)的输出。在这种情况下二进制call_gmon_start直接位于_start的后面功能。 call_gmon_start函数可在全局偏移表(也称为__gmon_start__),如果不为NULL,将控制权传递给指定的地址。 __gmon_start__元素指向gmon初始化函数,它将开始记录分析信息并使用以下命令注册清除功能的atexit()。但是在我们的情况下,没有使用gmon,因此__gmon_start__为NULL。

SO ...

  1. 是,它与gprof有关
  2. 我不确定为什么符号会留在那里。也许只是为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

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

__ gmon_start__代码的objdump:

__gmon_start__

在已编译的hello程序中存在__monstartup的情况下,您可以看到已调用[C​​0]。 (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

© www.soinside.com 2019 - 2024. All rights reserved.