Почему у меня не работает `-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 для этой цели. Проверьте, поможет ли это вам