LINUX.ORG.RU

[ядро][C99]Отладка/анализ кода

 


0

1

Есть код модуля ядра OC, именно, драйвера (DragonFlyBSD:). Ситуация банальна: аллоцировали память, освободить забыли. Где именно освобождать - понятия не имею. Вот вчера весь вечер просидел и удалось только понять, что дело в том, что забыли вызвать некую функцию для освобождения памяти.

Есть ли такие инструменты для анализа кода без его выполнения (ибо использовать отладчик (нормальный, а не встроенный ddb) нету возможности), чтобы построить графы вызова функций (сейчас пробую для этого doxygen:), проанализировать корреляцию вызовов 2 функций/использования 2 переменных. Также анализ схожести/различности 2 участков кода, делающих одну задачу.

Сейчас читаю в википедии про статический анализ кода. Может найду, что мне нужно.

И да, извините за столь непонятный поток сознания, я просто не знаю всех возможностей отладочного софта, не знаю, из чего приходится выбирать. Просто скажите, что бы вы стали использовать для отладки кода ядра.

P.S. Ещё немного о моей проблеме: не работает USB OHCI звуковуха. Чтобы локализовать проблему может быть полезным поработать с USB EHCI (например) звуковухой и с любым другим OHCI-устройством. Есть ли эмуляторы, способные эмулировать (масло-масляное:) большое кол-во USB устройств?

Зачем тебе отладочный софт, ты не можешь просто распечатать выделяемые участки памяти, посмотреть какой переменной соответствует данный участок, посмотреть на код, вставить в нужное место free?

frey ★★
()
Ответ на: комментарий от frey

Ну конечно нет) Понимаешь, я вчера целый вечер искал, куда бы впепить функцию освобождения памяти. Если бы это было так легко, я бы не спрашивал.

Вот представь себе функцию по выпеканию различных булочек. Есть некая функция bake():

int bake(device_t dev, type_t t)
{
   dev->allocmem(t);
   return dev->bake(dev->dev_id, t);
   dev->freemem(t);
   return NORMAL_COMPLETION;
}

В зависимости от того, на что указывает dev->allocmem, dev->bake, dev->freemem, то и будет исполняться, при этом в каждой из dev->allocmem будет такая же каша (скажем аллоцирование для каждого типа булочек). В этом примере я разместил вызов freemem из bake(). В отлаживаемом коде его просто нет. По-моему мой вопрос вполне имеет место быть, куда именно поместить free? Как избежать изпользования уже освобожденной памяти ниже по стеку вызова и вместе с этим не забыть освободить память для всех типов булочек и печей?

Это всё можно сделать с бумажкой, согласен. Но представь, что вызывается 20 (примерно так и есть) таких вложенных функций. Неужели нельзя автоматизировать?

shamazmazum
() автор топика
Ответ на: комментарий от shamazmazum

используй kprintf или аналог

p.s. намучаешься ты применять софт статического анализа на системный код, они же больше на прикладуху рассчитывают, и знают в основном про free и malloc, а не специальные система выделения памяти аля UMA.

dimon555 ★★★★★
()

Здается мне что вы боретесь с мельницами. Мне почему-то кажется что и освобождение и управление памятью есть :) Просто Вы не заметили. Могу Вам предложить открыть у них тикет с указанным вопросом, и не е**ть никому мозги.

Jetty ★★★★★
()
Ответ на: комментарий от shamazmazum

Честно говоря не очень понятно, как ты определил, что проблема в том, что забыли освободить память, это не приведет к краху моментально, а будут проблемы явно позже при memory leak, если же тебе нужен анализ случаев use-after-free, то можно пользоваться первыми ссылками в google типа 'valgrind kernel'. В любом случае вставить free без изучения кода будет проблематично.

frey ★★
()
Ответ на: комментарий от frey

Есть функции usb_allocmem() и usb_freemem(). Это функции, которые всегда вызываются для аллоцирования/освобождения для любого типа USB устройств. Дело в том, что вызовов первой куда больше, чем вызовов второй. Вторая вообще вызывается 3-4 раза (из мест, которые отвечают за обработку всяческих ошибок и которым управление передается крайне редко).

Определил элементарно - по встроенным туда kripntf с сообщениями об отладке.

В любом случае вставить free без изучения кода будет проблематично.

Именно.

shamazmazum
() автор топика
Ответ на: комментарий от Jetty

http://pastebin.com/eNExkXsJ

Посмотрите на devbuf. Всё ещё думаете, что я выдумываю утечку? Более того, я знаю причину - смотрите предыдущий пост. Я не знаю, как её починить.

Хотел не парить мозги, и написал, что утечка есть. Это 100%. Хотите, объясню почему, но это займет у вас много времени)

shamazmazum
() автор топика
Ответ на: комментарий от shamazmazum

int bake(device_t dev, type_t t)
{
dev->allocmem(t);
return dev->bake(dev->dev_id, t);
dev->freemem(t);
return NORMAL_COMPLETION;
}

Что за бред, дай нормальный пример.

anonymous
()
Ответ на: комментарий от anonymous

Это, парень, называется различия в мышлении профессионала и новичка.

Профессионал понимает фразы без указания контекста, зная каким он может быть. Новичку же нужно все разжевать, иначе ничего не поймет.

ИМХО, вполне понятный кусок кода, хорошо разъясняющий в чем сложность.

anonymous
()
Ответ на: комментарий от anonymous

Не выеживайся! Это бред, а не понятный кусок кода.

anonymous
()
Ответ на: комментарий от anonymous

> Что за бред, дай нормальный пример.

http://gitweb.dragonflybsd.org/dragonfly.git

Их здесь есть. Что именно не понятно? Есть функции, на которые указывает dev->allocmem. Ести функции вызывают ещё allocmem (сначала общую, потом более и более специфичные для каждого типа печи, булочек, итд.) Где-то забыли вызвать freemem(). Как узнать где?

Пока ничего круче вставок kprintf () с пересобиранием не нашел. Doxygen ужасно монструозен. Ищу инструмент, чтобы по крайней мере рисовал call/caller graph для нужной функции.

В википедии, что обидно, куча таких программ, но все они ущербны. То перекомпиляция особым образом нужна (egypt), то caller graph рисовать не умеет (cflow).

shamazmazum
() автор топика
Ответ на: комментарий от shamazmazum

попробуй что-нибудь из llvm

после компиляции в bitcode можно несколько объектных файлов объединить и попробовать поисследовать

сначала clang -emit-llvm
а потом пытаться opt применять

ну а так сам посуди, если во время исполнения регестрируются какие-то обработчики памяти, как статически узнать это? а если какие хитрые slab аллокаторы используются и прочие оптимизации? переопредели free malloc(точнее их kernel аналоги, чтобы при каждом вызове kprintf звался) и попытайся исследовать эти вызовы запоминая выделенные адреса.

dimon555 ★★★★★
()
Ответ на: комментарий от ACR

Чувак, если ты сможешь сходу сказать, где ошибка, то может тебе одному стоит писать все ядра. Я багрепорт послал, они сходу тоже не знают

shamazmazum
() автор топика
Ответ на: комментарий от ACR

И вообще, сам-то ты лез в хоть какое-то ядро? Что, сразу всё ясно?

Да, я обиделсо

shamazmazum
() автор топика
Ответ на: комментарий от shamazmazum

Безусловно я не знаю что такое devbuf, но КО подсказывает что он может алоцировать и больше :), исходя из названия.... Но то что в 4-ке БСДе у меня за все время работы с нею(это порядка 3-4 лет) проблем не было - это указывает только на чистоту и условную безглючность БСДи 4.х, вот почему я по прежнему подозреваю борьбу с мельницами :)

Jetty ★★★★★
()
Ответ на: комментарий от Jetty

Во-первых это не FreeBSD 4, во-вторых kmalloc (аналог malloc для ядра) аллоцирует память по типам (чтобы легче было отслеживать её распределение). devbuf - это такой тип. У меня аллоцированно 200 метров. Это предел. За ним следует kernel panic.

http://bugs.dragonflybsd.org/issue1884 (на мои выводы не смотри, смотри на факты)

Вообще, по последнему сообщению видно, что это проявляется не только при работе с USB/звуком, так что подозреваю худшее.

Так что если даже главный-по-проекту говорит, что это утечка, то твой КО явно ошибается)

shamazmazum
() автор топика
Ответ на: комментарий от Jetty

Можно пропробовать модуль собрать и потом его выгрузить. Если он там что-то понаалоцировал и не сделала free(), то у тебя должен быть красивый бек трейс, по которому будет видно кто выделил память. Это в линуксе так, как в BSD я не знаю. Еще есть CONFIG_DEBUG_KMEMLEAK какой-то, можно им попробовать. Но самое наверное простое это прееопределить малоки и фрии, так что-бы они печатали сколько и откуда они выделили и почистили. Код у тебя довольно сложный, что-бы так сходу сказать. Удачи.

anonymous
()

Не возникает ли проблема при подключении большого количества USB утройств, или при частом их подключении/отключении?

Дело в том, что вы, скорее всего, не найдете, где именно освобождается память в явном виде. Структуры, описывающие устройства, в подобных системах подсчитывают количество ссылок на себя, и позволяют освобждение только в безопасном случае. В условиях многопоточности чаще всего это единственное решение.

Вполне возможно, проблема кроется не в самом освобождении/неосвобождении, а неправильном подсчете количества ссылок на структуру. Это, как вы понимаете, намного сложнее детектировать и устранить.

Не уверен, что конкретно во FreeBSD, DragonflyBSD, Linux, и прочих это именно так, но что-то мне подсказывает, что именно так.

anonymous
()
Ответ на: комментарий от anonymous

> Не возникает ли проблема при подключении большого количества USB утройств, или при частом их подключении/отключении?

Действительно, возникает. Более того, она возникает при выполнении mkinitrd несколько раз. Проблема глобальна, пока так ничего и не придумал.

shamazmazum
() автор топика
Ответ на: комментарий от shamazmazum

Оставить тикет разработчикам это самое верное решение в этом случае.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.