Хронологическая трассировка вызовов функций в C ++ с использованием etrace
Фон:
У меня есть один большой инструмент моделирования, и мне нужно понять его логическое поведение. Чтобы сделать это, большую часть помощи я бы получил, если бы у меня был хронологический порядок вызовов функций, для минимального рабочего примера.
Я нашел много инструментов в Интернете, какCygProfiler а такжеetrace, Я стал настолько несчастным, когда нашел решение, что начал следовать сумасшедшему решению использовать «шаг в» с отладчиком. Это хороший вариант, если у вас небольшая программа, но не полный инструмент моделирования.
Проблема:
Одна из проблем, с которыми я сталкиваюсь, заключается в том, что вышеупомянутые решения изначальноC
и они генерируют статический файл (*.o
) при компиляции. С другой стороны, инструмент моделирования создает общую библиотеку (.so
). Я не очень разбираюсь в вещах более низкого уровня, поэтому, кажется, я терплю неудачу, когда пытаюсь их связать
Я специально посмотрел наetrace
документацияи это говорит:
Чтобы узнать, как изменить ptrace.c для работы с динамической библиотекой, посмотрите каталог example2. Источники там также создают автономный исполняемый файл, но макрос PTRACE_REFERENCE_FUNCTION определяется так же, как и для динамической библиотеки.
Если вы посмотрите на репо, нет никакой разницы между файлами вexample
а такжеexample2
папки. Только есть доп.h
файл вexample2
.
С другой стороны, если вы посмотрите наsrc/ptrace.c
там говорится:
При использовании ptrace в динамической библиотеке вы должны установить макрос PTRACE_REFERENCE_FUNCTION в качестве имени функции в библиотеке. Адрес этой функции при загрузке будет первой строкой, выводимой в файл трассировки, и позволит переводить другие указатели входа и выхода в их символические имена. Вы можете установить макрос PTRACE_INCLUDE с любыми директивами #include, необходимыми для того, чтобы эта функция была доступна для этого исходного файла.
чуть ниже есть закомментированный код:
/* When using ptrace on a dynamic library, the following must be defined:
#include "any files needed for PTRACE_REFERENCE_FUNCTION"
#define PTRACE_REFERENCE_FUNCTION functionName
`*/
Вопрос:
По сути, вопрос заключается в следующем: как использоватьetrace
с динамической библиотекой?
Нужно ли #include какие-либо файлы?
Чтобы отследить автономную программу, нет необходимости #include каких-либо дополнительных файлов. Просто свяжите ваш код с ptrace.c и используйте опцию -finstrument-functions в качестве опции компиляции для gcc. Это должно сделать это.
Как связать код C ++, который построен с помощью make-файлов, противptrace.c
Заключительное примечание: Буду признателен, если кто-то смирится с моим невежеством и предоставит пошаговое решение моего вопроса.
Обновление 1:
Мне удалось добавить библиотеки, связанные с etrace, в инструмент моделирования, и он работает нормально.
Однако (возможно, из-за того, что скрипты слишком старые или не предназначены для использования с C ++), я получаю следующую ошибку при использованиискрипт на Perl предоставляется по умолчаниюetrace
Hexadecimal number > 0xffffffff non-portable"
Вероятно, это немного меняет природу этого вопроса, превращая его больше в проблему, связанную с Perl на данный момент.
Если эта проблема решена, я надеюсьetrace
будет работать со сложным проектом, и я предоставлю детали
Обновление 2:
Я принял предложения от @Harry и считаю, что это сработает в большинстве проектов. Однако в моем случае я получаю следующее из сценария perl:
Use of uninitialized value within %SYMBOLTABLE in list assignment at etrace2.pl line 99, <CALL_DATA> line 1.
\-- ???
| \-- ???
\-- ???
| \-- ???
| | \-- ???
\-- ???
| \-- ???
\-- ???
| \-- ???
\-- ???
| \-- ???
\-- ???
| \-- ???
\-- ???
| \-- ???
Из-за сгенерированных make-файлов я использовалLD_PRELOAD загрузить общую библиотеку для etrace.so, которую я получил следующим образом:
gcc -g -finstrument-functions -shared -fPIC ptrace.c -o etrace.so -I <path-to-etrace>
Я создал фиктивный etrace.h внутри инструмента:
#ifndef __ETRACE_H_
#define __ETRACE_H_
#include <stdio.h>
void Crumble_buy(char * what, int quantity, char * unit);
void Crumble_buy(char * what, int quantity, char * unit)
{
printf("buy %d %s of %s\n", quantity, unit, what);
}
#endif
и использовалCrumble_buy
для#define
иetrace.h
для#include
.