Использование Python GDB для отслеживания различных потоков ОС, когда GDB не осознает ОС
Я все еще учусь отлаживать C, используя python в gdb (arm-none-eabi-gdb, в моем случае). Я пытаюсь использовать эту возможность для получения информации о потоках операционной системы реального времени, работающей на ARM Cortex-M. Читая некоторые структуры ОС, я могу получить доступ к блокам управления потоками ОС. Я знаю ПК и SP каждого потока. Как я могу использовать Python GDB для дамп обратного следа потоков. Существует ли общий API, который может проходить через стек при наличии ПК и SP?
Я прочитал https://sourceware.org/gdb/current/onlinedocs/gdb/Unwinding-Frames-in-Python.html и чувствую, что может быть способ достичь этого, но мне нужно некоторая помощь.
Также, если возможно, могу ли я сделать так, чтобы gdb знал о различных потоках ОС? Эта ссылка: https://sourceware.org/gdb/current/onlinedocs/gdb/Threads-In-Python.html затрагивает темы, но опирается на информацию об ОС. Могут ли они быть перегружены тем, что я знаю о различных потоках ОС из их соответствующих блоков управления?
Спасибо!
2 ответа
После некоторого прочтения и попыток использовать старые знания отладчика, которые я накопил за эти годы, мне это удалось. Не хватает оптимизации, но сейчас я очень рад. Это можно считать отладчиком для плохого человека, использующим поддержку Python в GDB для отслеживания активных потоков в системе. Я предполагаю, что это универсально, но реализация ориентирована на RTX (ОС Кейла). Работало на Cortex-M0. Может потребоваться некоторая настройка, чтобы соответствовать другим операционным системам или другим ядрам.
Главная идея:
- Используйте структуры ОС, чтобы определить, где находится блок управления потоками.
- Из блока управления потоком определите, где находятся различные стеки потоков.
- Считайте из стека все жизненно важные регистры; SP, LR и ПК
- Сохраните те же регистры для текущего, работающего потока.
- Зациклите другой поток, замените регистры жизнедеятельности на те, которые соответствуют потоку, а затем напечатайте обратный след.
- Наслаждайтесь отладчиком с операционной системой для бедного человека.
Сценарий можно найти здесь:
https://gitlab.com/hesham/gdb-rtx-thread-backtrce/blob/master/rtx-threads-bt.py
Это было очень хорошее упражнение для изучения возможностей расширения Python в GDB!
Для FreeRTOS я использую следующий скрипт gdb:
define printtasklist
# $arg0 is a pointer to an uxList of tasks.
set $plist = (List_t*)$arg0
printf ": %d tasks\n", $plist->uxNumberOfItems
set $iter = $plist->xListEnd.pxNext
while ($iter != &$plist->xListEnd)
set $vtask = ($iter->pvOwner)
set $task = (tskTCB*)$vtask
print $task
print $task->pcTaskName
set $iter = $iter->pxNext
end
end
define printtasks
printf "%d tasks:\n", uxCurrentNumberOfTasks
printf "pending ready"
printtasklist &xPendingReadyList
printf "suspended"
printtasklist &xSuspendedTaskList
printf "delayedW"
printtasklist pxDelayedTaskList
printf "delayedO"
printtasklist pxOverflowDelayedTaskList
set $prio = 0
set $maxprio = sizeof(pxReadyTasksLists) / sizeof(pxReadyTasksLists[0])
while ($prio < $maxprio)
printf " ready at prio"
printf "%d", $prio
printtasklist &pxReadyTasksLists[$prio]
set $prio = $prio + 1
end
end
define savestate
set $svpc = $pc
set $svsp = $sp
set $svlr = $lr
end
define restorestate
set $pc = $svpc
set $sp = $svsp
set $lr = $svlr
end
define cm3bttask
# arg0: task handle (pointer to tskTCB)
savestate
set $ptsk = (tskTCB*)$arg0
set $tskstk = (uint32_t*)$ptsk->pxTopOfStack
set $lr = $tskstk[13]
set $pc = $tskstk[14]
set $sp= $tskstk + 16
bt
end
Идея в том, что я использую printtasks
чтобы получить список блоков управления задачами, затем используйте cm3bttask $26
если в задаче, которая меня интересует, указатель блока управления в истории GDB печатается в виде строки $26. Я могу видеть это на выходе printtasks.