什么是__gmon_start__符号?

时间:2012-10-02 19:38:03

标签: c linux gcc elf binutils

我正在用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 个答案:

答案 0 :(得分:11)

点击了一下,发现了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。

<强>因此...

  1. 是的,它确实与gprof
  2. 有关
  3. 我不确定为什么这个符号会留在那里。也许只是为gprof编译时的占位符?
  4. 更新

    好的,所以我使用和不使用-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
    

    ob_dump of __gmon_start__代码:

    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__程序中存在hello,您可以看到__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