Использование 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. Может потребоваться некоторая настройка, чтобы соответствовать другим операционным системам или другим ядрам.

Главная идея:

  1. Используйте структуры ОС, чтобы определить, где находится блок управления потоками.
  2. Из блока управления потоком определите, где находятся различные стеки потоков.
  3. Считайте из стека все жизненно важные регистры; SP, LR и ПК
  4. Сохраните те же регистры для текущего, работающего потока.
  5. Зациклите другой поток, замените регистры жизнедеятельности на те, которые соответствуют потоку, а затем напечатайте обратный след.
  6. Наслаждайтесь отладчиком с операционной системой для бедного человека.

Сценарий можно найти здесь:

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.

Другие вопросы по тегам