Подтвердить что ты не робот

Автоматическое добавление журналов входа/выхода в проект

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

printf("Entered into %s", __FUNCTION__)

и

printf("Exited from %s", __FUNCTION__)

для каждой функции, и я не хочу касаться какого-либо исходного файла.

Есть ли у вас предложения? Есть ли флаг компилятора, который автоматически делает это для меня?

Пояснения к комментариям:

  • Я буду перекрестно скомпилировать источник, чтобы запустить его на ARM.
  • Я скомпилирую его с помощью gcc.
  • Я не хочу анализировать статический код. Я хочу отслеживать время выполнения. Так что doxygen не облегчит мою жизнь.
  • У меня есть источник, и я могу его скомпилировать.
  • Я не хочу использовать Aspect Oriented Programming.

EDIT: Я обнаружил, что команда "frame" в приглашении gdb печатает текущий фрейм (или имя функции, которое вы могли бы сказать) в этот момент времени. Возможно, возможно (используя скрипты gdb) вызывать команду "frame" каждый раз, когда вызывается функция. Как вы думаете?

4b9b3361

Ответ 1

Помимо обычных методов отладки и аспектно-ориентированного программирования, вы также можете вводить свои собственные инструментальные функции, используя параметры командной строки gcc -finstrument-functions. Вам нужно будет реализовать свои собственные функции __cyg_profile_func_enter() и __cyg_profile_func_exit() (объявите их как extern "C" в С++).

Они предоставляют средства для отслеживания того, какая функция была вызвана откуда. Однако интерфейс немного сложно использовать, поскольку адрес вызываемой функции и его сайт вызова передаются вместо имени функции, например. Вы можете регистрировать адреса, а затем вытаскивать соответствующие имена из таблицы символов, используя что-то вроде objdump --syms или nm, если, конечно, символы не были удалены из соответствующих двоичных файлов.

Это может быть проще использовать gdb. YMMV.:)

Ответ 2

Вы сказали "и я не хочу прикасаться к любому исходному файлу"... честная игра, если вы позволите script сделать это за вас?

Запустите это на всех ваших .cpp файлах

sed 's/^{/{ENTRY/'

Чтобы преобразовать их в это:

void foo()
{ENTRY
  // code here
}

Поместите это в заголовок, который может быть # включен в каждую единицу:

#define ENTRY EntryRaiiObject obj ## __LINE__ (__FUNCTION__);

struct EntryRaiiObject {
  EntryRaiiObject(const char *f) : f_(f) { printf("Entered into %s", f_); }
  ~EntryRaiiObject() { printf("Exited from %s", f_); }
  const char *f_;
};

Вам может понадобиться стать sed script. Вы также можете поместить макрос ENTRY в другое место, которое вы хотите зондировать, например, глубоко глубоко вложенную внутреннюю область функции.

Ответ 3

Использовать /Gh (Включить функцию _penter Hook) и /GH (Enable _pexit Hook Function) компиляторы (если вы можете скомпилировать источники)

ПРИМЕЧАНИЕ. Вы не сможете использовать эти макросы. См. здесь ( "вам нужно будет получить адрес функции (в регистре EIP) и сравнить его с адресами в файле карты, который может быть сгенерирован по линкеру (при условии, что переполнение не произошло). Это будет очень медленно, хотя." )

Ответ 4

Согласитесь с Уильямом, используйте gdb, чтобы увидеть поток времени выполнения.
Есть некоторый статический анализатор кода, который может определить, какие функции вызывают, и который может дать вам некоторый график потока вызовов. Одним из инструментов является "Понять С++" (поддержка C/С++), но это не бесплатно. Но вы можете найти похожие инструменты.

Ответ 5

Если вы используете gcc, флаг волшебного компилятора -g. Компилируйте с помощью отладочных символов, запустите программу под gdb и создайте трассировки стека. Вы также можете использовать ptrace, но, вероятно, гораздо проще просто использовать gdb.