Что такое символ __gmon_start__?

Я компилирую этот код с помощью 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? Какая библиотека разрешит этот символ?


person JohnTortugo    schedule 02.10.2012    source источник


Ответы (1)


Немного погуглил и нашел вот это здесь:

Функция 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. Я не уверен, почему символ остается там. Может быть, просто заполнитель, когда он скомпилирован для 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

objdump кода __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)

без -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.

person rkyser    schedule 02.10.2012
comment
про третий вопрос? Должен ли я считать последнюю запись в GOT адресом gmon_start? Также при проверке бинарника hello оказывается, что есть запись: __gmon_start__@plt и еще одна (запись PLT) __gmon_start__@plt-0x10› - person JohnTortugo; 03.10.2012
comment
Так как же смещение для gmon_start сопоставляется с физическим адресом? - person RouteMapper; 19.07.2013