Почему у меня не работает `-finstrument-functions`?

Согласно этому ответу должны быть напечатаны все имена функций:

[root@ test]# cat hw.c
#include <stdio.h>

int func(void)
{  
  return 1;
}
int main(void)
{
  func();
  printf("%d",6);
  return 6;
}
[root@ test]# gcc -Wall hw.c -o hw -finstrument-functions
[root@ test]# ./hw 
6
[root@ test]# gcc --version
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.

Но почему это не работает для меня?

4 ответа

Решение

Это из руководства gcc:

-finstrument-функции

Генерация инструментария вызовов для входа и выхода в функции. Сразу после ввода функции и непосредственно перед выходом из функции будут вызваны следующие функции профилирования с адресом текущей функции и ее сайта вызова. (На некоторых платформах __builtin_return_address не работает за пределами текущей функции, поэтому в противном случае информация сайта вызова может быть недоступна для функций профилирования.)

void __cyg_profile_func_enter (void * this_fn, void * call_site);

void __cyg_profile_func_exit (void * this_fn, void * call_site);

Если что-то не реализует эти функции, вы получите ошибки компоновщика (что и происходит с MinGW). Вероятно, ваша версия GCC предоставляет пустые реализации.

Я получил его для работы с MinGW GCC, предоставив эту реализацию:

#include  <stdio.h>

void __cyg_profile_func_enter (void *this_fn, void *call_site) {
    printf( "entering %p\n", this_fn );
}

void __cyg_profile_func_exit (void *this_fn, void *call_site) {
    printf( "leaving %p\n", this_fn );
}

но это дает только адреса функций. Я бы подумал, что это должна быть реализация GCC по умолчанию, но, похоже, ее нет.

Людей также может заинтересовать эта визуализация дерева вызовов, в которой используется флаг -fintrument-functions - caveat, я сам не пробовал.

Вы на самом деле не реализовали никаких инструментов. -finstrument-functions switch просто указывает gcc на вызов какой-либо функции при входе и выходе из каждой функции. Но вы должны определить эти функции самостоятельно (обычно это делается путем связывания библиотеки профилировщика в).

Кодирование __cyg_profile_func_enter и __cyg_profile_func_exit не сложно. Простейшим решением будет обеспечить, чтобы вышеуказанные функции записывали сведения об адресе в файл и имели отдельный процесс для считывания адресов из файла и их разрешения с использованием таблицы символов исполняемого файла. Если вы попытаетесь разрешить адрес в самой функции, это может занять некоторое время.

Я наткнулся на следующую статью - http://balau82.wordpress.com/2010/10/06/trace-and-profile-function-calls-with-gcc/

Который использует addr2line из binutils для этой цели. Проверьте, поможет ли это вам

Реализация того, что вы ищете, представлена здесь.

Другие вопросы по тегам