Быстрая обратная трассировка для генерации графа вызовов? - PullRequest
0 голосов
/ 22 января 2019

Я использую следующий подход для генерации графов вызовов.

https://github.com/tarun27sh/gdb_graphs

Но GDB резко (x100) замедляется обратным следом. Есть ли намного более быстрый способ генерировать графы вызовов?

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Есть ли намного более быстрый способ генерировать графы вызовов?

Конечно, есть (использование GDB для этого совершенно неуместно).

Самым простым решением является использование GCC -finstrument-functions для вставки вызова при каждом входе и выходе из функции и реализации сбора данных в этих «введенных» функциях. Вот пример здесь .

0 голосов
/ 22 января 2019

Поскольку вы публикуете этот вопрос в SO и помечаете его как llvm Я предполагаю, что это означает, что вы ищете решение для программирования с использованием LLVM.

Напишите проход, который преобразует каждую функцию вВаша программа добавляет три новые инструкции перед каждым вызовом.Примерно так:

struct RecordCallGraph : public PassInfoMixin<RecordCallGraph> {
  RecordCallGraph() = default;
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
};

Вам необходимо реализовать этот run (), который будет содержать около 15 строк кода.Просканируйте основные блоки в функции, проверьте, каждая ли инструкция isa<CallBase> и, если она есть, то вставьте немного дополнительного кода перед CallBase.(CallBase - это базовый класс инструкций, которые вызывают функции.) Вы вставляете вызов для своей новой новой функции, void emitTraceInfo(char* caller, char* called) или что-то в этом роде.Так как LLVM IR безопасен для типов, вам необходимо привести вызывающую функцию (&F) и вызываемую функцию (callBase->getCalledValue()) к нужному типу для вашей функции (char* в примере).

Самый простой способчтобы получить этот бросок, скорее всего, будет CastInst::Create(CastInst::BitCast, &F, charStarType, "", callBase), который создаст новый бросок с &F до charStarType и вставит его непосредственно перед callBase.

Наконец вы должны реализовать свой новый emitTraceInfoи свяжите это в программу.Он будет вызываться каждый раз, когда одна функция вызывает другую, и может записывать вызов.Вы найдете это примерно в сто раз быстрее, чем GDB.Самая медленная часть может состоять в записи 16-ти с лишним байтов в файл.

...