【问题标题】:Using gdb's Python to backtrace different OS threads, when gdb is not OS-aware当 gdb 不支持操作系统时,使用 gdb 的 Python 回溯不同的操作系统线程
【发布时间】:2017-01-28 15:52:42
【问题描述】:

我仍在学习如何在 gdb 中使用 python 调试 C(在我的例子中是 arm-none-eabi-gdb)。我正在尝试使用此工具来获取在 ARM Cortex-M 上运行的实时操作系统的线程信息。阅读一些操作系统结构,我可以访问操作系统的 the 线程控制块。我知道每个线程的 PC 和 SP。如何使用 gdb 的 Python 转储线程的回溯。在给定 PC 和 SP 时,是否有可以遍历堆栈的通用 API?

我已阅读https://sourceware.org/gdb/current/onlinedocs/gdb/Unwinding-Frames-in-Python.html#Unwinding-Frames-in-Python,我觉得可能有办法实现这一目标,但我需要一些帮助。

另外,如果可能的话,我可以让 gdb 了解操作系统的不同线程吗?这个链接: https://sourceware.org/gdb/current/onlinedocs/gdb/Threads-In-Python.html#Threads-In-Python 涉及线程但依赖于操作系统信息。这些是否会因我对各自控制块中不同操作系统线程的了解而过载?

谢谢!

【问题讨论】:

    标签: c debugging operating-system gdb gdb-python


    【解决方案1】:

    对于 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 的输出中看到这一点。

    【讨论】:

      【解决方案2】:

      经过更多阅读并尝试利用我多年来积累的旧调试器知识,我设法让它工作。它缺乏优化,但现在,我很高兴。这可以被认为是一个穷人的调试器,它利用 GDB 的 Python 支持来跟踪系统中的活动线程。我认为它是通用的,但实现的目标是 RTX(Keil 的操作系统)。它适用于 Cortex-M0。它可能需要一些调整以适应其他操作系统或不同的内核。

      主要思想:

      1. 使用操作系统结构来确定线程控制块所在的位置。
      2. 从线程控制块中确定不同线程堆栈的位置。
      3. 从堆栈中读取所有重要寄存器; SP、LR 和 PC
      4. 为当前正在运行的线程保存相同的寄存器。
      5. 遍历不同的线程,将重要寄存器更改为与线程匹配的寄存器,然后打印回溯。
      6. 享受穷人的操作系统感知调试器。

      脚本可以在这里找到:

      https://gitlab.com/hesham/gdb-rtx-thread-backtrce/blob/master/rtx-threads-bt.py

      探索 GDB 的 Python 扩展的强大功能是一个很好的练习!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-12-25
        • 1970-01-01
        • 2018-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-06
        相关资源
        最近更新 更多