Russian Qt Forum

Qt => Установка, сборка, отладка, тестирование => Тема начата: lit-uriy от Март 22, 2010, 12:09



Название: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 22, 2010, 12:09
Подскажите, как выполнить "автоматическую" трассировку приложения. Т.е. мне нужно получить файл содержащий последовательность вызовов (граф) функций (с их именами). Но не в рукопашную, как пошаговая отладка в отладчике. а примерно в таком стиле:
Запуск приложения (напрямую, или через некую софтину), после того как приложение отработало, нужно получить текстовый файл с графом. При этом нужно пройти и внутрь библиотеки Qt.

Вроде это можно сделать с помощью gdb и его макросов, но я совершенно не представляю, как это сделать.

П.С.
Я пробовал использовать  gprof, для этих целей, но он почему-то даже мою софтину проходит не всю, т.е.
Имеется такой псевдокод:
func1()
func2()
func3()
...
fincN()

он на выходе даёт граф, содержащий только func1 и func2 (ну и внутрь их), а дальше нету.


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: alexman от Март 23, 2010, 09:13
Есть пакет IBM Rational Purify/Quantify. Там есть возможность просмотра графа вызовов функций графически... Может есть и вывод в файл!?


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: kuzulis от Март 23, 2010, 11:03
Цитировать
Есть пакет IBM Rational Purify/Quantify. Там есть возможность просмотра графа вызовов функций графически... Может есть и вывод в файл!?
так там поддержка под винду только MSVC (судя по описанию)!! + как я понял кряк нужен для этого пакета?


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: alexman от Март 23, 2010, 11:07
Цитировать
Есть пакет IBM Rational Purify/Quantify. Там есть возможность просмотра графа вызовов функций графически... Может есть и вывод в файл!?
так там поддержка под винду только MSVC (судя по описанию)!! + как я понял кряк нужен для этого пакета?
В инете все есть ;)


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 23, 2010, 12:46
крякнутое ПО выискивать, желания ни какого нет.

Жаль, я думал, что в коллекции гнутых товарищей что-то есть.


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: SABROG от Март 24, 2010, 16:13
он на выходе даёт граф, содержащий только func1 и func2 (ну и внутрь их), а дальше нету.

А дальше это куда, в Qt?


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 24, 2010, 19:43
нет, в моём коде (func3, ...).
Через func1 и func2 проходит в классы Qt, ну и разумеется возвращается обратно,


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: SABROG от Март 24, 2010, 21:21
нет, в моём коде (func3, ...).
Через func1 и func2 проходит в классы Qt, ну и разумеется возвращается обратно,

Может быть такое, что она inline'ниться, так как ты пытаешься проанализировать не debug, а release версию, где включена оптимизация?


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 24, 2010, 22:53
только отладочную смотрю, релизная даже не собрана


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: SABROG от Март 24, 2010, 23:46
только отладочную смотрю, релизная даже не собрана
Можешь исходник выложить?


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 24, 2010, 23:54
глянь тут (http://www.forum.crossplatform.ru/index.php?showtopic=4571&view=findpost&p=31878) (там и результат профилирования и исходник)


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: SABROG от Март 25, 2010, 18:33
Цитировать
Имеется такой псевдокод:
func1()
func2()
func3()
...
fincN()

он на выходе даёт граф, содержащий только func1 и func2 (ну и внутрь их), а дальше нету.

Это происходит потому, что func1 и func2 являются твоими собственными функциями или функциями, исходный код которых находится в подключаемых хедерах (в том числе и Qt), в то время как func3() и т.д. являются функциями, которые вызываются из разделяемых библиотек, прилинкованных к приложению, но при этом они собирались без включенного профилирования.

Я собрал свой Qt в debug с дополнительными ключами -pg. К сожалению это особо не помогло. Профилирование для основного приложения теперь выдает:

Код:
Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name   
  0.00      0.00     0.00   513092     0.00     0.00  etext

Вместо вызова статических функций, при этом gmon.out файл стал весить 2Мб. Я попробовал вот так:

Код:
gprof -q debug\QtCored4.dll >profiling.txt

Это сгенерело файл размером в 1Мб. Граф вызовов совпадает с тем, что происходит в моей программе. Количество функций 1739.

Затем
Код:
gprof -q debug\QtGuid4.dll >profiling.txt

Он оказался поменьше, но было в нем интересно найти вызовы функций которых я не ожидал. Функций больше 500.

Попытка сделать так:

Код:
gprof -q debug\QtGuid4.dll debug\QtCored4.dll debug\main.exe >profiling.txt

Привела к ошибке:

Код:
gprof: out of memory allocating 4294967280 bytes

То есть вариант с gprof отпал.

Затем я начал искать другие средства и наткнулся на такую статью:
http://www.ibm.com/developerworks/library/l-graphvis

Из нее могу сказать, что метод действительно работает причем как в linux, так и в mingw. Но я не знаю как она будет работать с динамическими библиотеками. Про утилиту pvtrace (http://www.mtjones.com/developerworks/pvtrace.zip) могу сказать, что с помощью mingw собирается хорошо. Ужимается до 10Кб. Работоспособность с файлом не проверял.

Искал также информацию по gdb. Кроме простеньких вариантов макросов ничего не нашел. backtrace не подходит хотябы потому, что нужно четко знать глубину на каторой остановится, чтобы "оглянуться" на стек вызовов.

Пробовал также gcov, задача которой вывести "покрытие" кода. Конечно она не работает с динамическими библиотеками, пока их не соберешь со спец ключами. Для неё нашел "front-end" - lcov (http://ltp.sourceforge.net/coverage/lcov.php), который генерит отчеты в html формате. Написан на Perl, но в Windows не работает, так как использует Linux специфичные команды. Зато нашел замену gcov - trucov (http://code.google.com/p/trucov). Написана на C++, умеет генерить графики. Front-end на Qt. Использует boost, в связи с чем у меня возникла накладка с компиляцией под MinGW. Может позже все-таки дособираю.

А это ссылки, который могут пригодится как мне, в будущем, если буду искать, так и другим:
http://www.graphviz.org/About.php - бесплатная кроссплатформенная программа генерации и визуализации графиков
http://code.google.com/p/jrfonseca/wiki/Gprof2Dot#Download - скрипт на питоне, позволяющий преобразовать вывод gprof'a в формат dot, который можно скормить GraphViz для построения графика.
Вызывать например так:
Код:
gprof -q main.exe >profiling.txt
c:\Python25\python gprof2dot.py -n0 -e0 -o dots.txt profiling.txt
dot -Tpng -o output.png dots.txt
Параметры n и e контролируют глубину графа, нули означают выводить всё.

Наглядное представление:
http://img707.imageshack.us/img707/2495/qtcoregraph.png
http://img707.imageshack.us/img707/7091/qtcoregraphchunk.png

ZGRViewer (http://sourceforge.net/projects/zvtm/files) - программа для просмотра графов, в основном сконверченные GraphViz'ом в формат SVG, нежели PNG или другие. Довольно шустро работает на больших графах, но не без лагов. Написана на Java, SWIG интерфейс.

Tau (http://www.cs.uoregon.edu/research/tau/downloads.php) - профайлер, который "кушает" вывод gprof'a и выводит статистику, графики и т.п. На больших объемах тормозит. Написана на Java, SWIG интерфейс.


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 25, 2010, 19:44
Цитировать
Это происходит потому, что func1 и func2 являются твоими собственными функциями или функциями, исходный код которых находится в подключаемых хедерах (в том числе и Qt), в то время как func3() и т.д. являются функциями, которые вызываются из разделяемых библиотек, прилинкованных к приложению, но при этом они собирались без включенного профилирования.
Это не соответствует тому, что я увидел.
например у меня в логе (http://www.forum.crossplatform.ru/index.php?showtopic=4571&view=findpost&p=31878) есть запись:
Код:
[34]     0.0    0.00    0.00       1         work() [34] - это моя функция
                0.00    0.00      64/64          QDebug::operator<<(char const*) [8]
                0.00    0.00      62/64          QDebug::~QDebug() [7]
                0.00    0.00      44/45          qDebug() [11]
                0.00    0.00      40/40          QModelIndex::~QModelIndex() [20]
                0.00    0.00      30/30          QModelIndex::QModelIndex() [21]
                0.00    0.00      21/142         QString::~QString() [5]
                0.00    0.00      11/13          QString::QString(char const*) [22]
                0.00    0.00      10/10          QLatin1Char::QLatin1Char(char) [23]
                0.00    0.00      10/10          QChar::QChar(QLatin1Char) [25]
                0.00    0.00      10/10          QString::arg(int, int, int, QChar const&) const [28]
                0.00    0.00      10/10          QDebug::operator<<(QString const&) [26]
                0.00    0.00      10/10          QAbstractItemModel::insertRow(int, QModelIndex const&) [24] - это уже библиотечная функция, но в моём коде
                0.00    0.00       9/9           QDebug::QDebug(QDebug const&) [29]

При этом отсутствует submitAll(), который есть в моём коде (http://www.forum.crossplatform.ru/index.php?showtopic=4561&view=findpost&p=31825) единственная мысль, которая это бы объяснила. gprof просто подавился длинной цепочкой вызовов


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: SABROG от Март 26, 2010, 02:37
Цитировать
QAbstractItemModel::insertRow(int, QModelIndex const&) [24] - это уже библиотечная функция, но в моём коде

Да, но она все-таки inline:

Код
C++ (Qt)
inline bool QAbstractItemModel::insertRow(int arow, const QModelIndex &aparent)
{ return insertRows(arow, 1, aparent); }
 

Сам вызов обертки зафиксировался, но вот insertRows() нигде не видать. Кстати это мысль, попробуй оберни в inline функции интересующие тебя методы (submitAll() например), глянь профилирует ли он их.

Когда я проверял у себя, то не нашел очень много функций, которые вызывал. Например все функции относящиеся к QStateMachine. Как будто я её вообще нигде не использовал...


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: lit-uriy от Март 26, 2010, 12:47
я уже пошёл по простому: нашпиговал исходники QtSQL и драйвера отладочной информацией.


Название: Re: Трассировка приложения и библиотеки (MinGW32)
Отправлено: SABROG от Март 26, 2010, 21:48
К сожалению gprof не идеален. Нельзя профилировать разделяемые библиотеки и много-нитевые приложения. Проблему с разделяемыми библиотеками, как я понял, можно решить только одним способом - статическая сборка Qt с включенными флагами профилирования.