在 Trace32 中显示 Linux 个链表

Display Linux linked list in Trace32

我尝试在 Trace32 中以用户友好的方式打印 Linux 链表。

1.是否已经有任何已知的方法可用?

如果没有,那么让我用 modules 列表来展示一个例子。

我有全局变量

static struct list_head modules;

其中

struct list_head {
        struct list_head *next, *prev;
};

所以,在 T32 中,我在执行 v.v modules 时只看到下一个和上一个指针的列表,实际上没有任何有用的信息。但是,模块列表的每个节点都是容器类型的一部分。在这种情况下 struct module

struct module {
         ...
         struct list_head list;
         ...
}

通常,要提取容器指针 Linux 使用 container_of 宏。

/**
  * container_of - cast a member of a structure out to the containing structure
  * @ptr:        the pointer to the member.
  * @type:       the type of the container struct this is embedded in.
  * @member:     the name of the member within the struct.
  *
  */
 #define container_of(ptr, type, member) ({                      \
         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
         (type *)( (char *)__mptr - offsetof(type,member) );})

在我们的示例中,我们知道指向 struct list_head 的指针,它是 struct module 中的 list 成员,那么我们应该调用 container_of(modules->next, struct module, list) 来获取指向容器的指针。

为了能够在 T32 中存档,我需要计算 list 成员在容器类型中的偏移量。

有人知道如何实现吗?

嗯,听起来你有两个问题:

  1. 如何显示链表?
  2. 如何获取结构体成员的字节偏移量?

对于显示链接列表,我建议使用命令Var.CHAIN 或VAR.FixedCHAIN。这两个命令都有两个强制参数:结构的变量名称和下一个元素的名称。 (您可以在 TRACE32 manual 中查找所有可选参数和格式选项。)

所以,查看您的第一个简单案例

Var.CHAIN modules modules.next   

A window 将打开 table 显示完整列表,直到 'next' 指向 NULL。

注意:正如 Wrymarki 在下面的评论中所述,答案的第一部分实际上是错误的。 Var.CHAIN 适用于普通链表,但不适用于 "Linux linked lists"。 "Linux linked lists" 的解决方案(由 Wrymarki 编写)是编写一个 PRACTICE 脚本,该脚本循环遍历列表并使用 container_of 将带有 Var.AddWatch 的列表条目添加到 watch-window () 宏(见下文).


对于获取结构中成员的偏移量,我建议像在源代码中那样声明预处理器宏。或者 almost 就像在你的源代码中一样,因为 TRACE32 不知道 GCC 特定的扩展,比如 typeof() 或 statement expressions.

无论如何,我们可以用

得到 offsetof() 宏
sYmbol.NEW.MACRO offsetof(type,member) ((int)(&((type*)0)->member))

预处理器宏可用于 TRACE32 中的每个 HLL 表达式(包含所有 Var.* 命令和函数)。 例如:

Var.AddWatch offsetof(struct module,list)

注意:sYmbol.NEW.MACRO 不接受宏名称中的空格:您必须写 offsetof(type,member) 而不是 offsetof(type, member)

您可以在 window sYmbol.List.MACRO

中查看您的宏

如果您的编译器在使用选项 /MACRO 加载 ELF 时支持此功能(GCC 使用选项 -g3),您也可以从源代码中获取宏:Data.LOAD.Elf * /MACRO。但同样:TRACE32 不会理解 GCC 特定扩展或内部宏,如 '__builtin_offsetof()'.


你也可以用

声明一个container_of()预处理器宏
sYmbol.NEW.MACRO container_of(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))

使用它,例如如下:

Var.View container_of(modules->next,struct module,list)

在Var.CHAIN和VAR.FixedCHAIN命令之间,我想Var.CHAIN显示了更详细的链表信息。

如果是linux内核系统,下面的命令可以得到链表的完整列表。

v.chain %m %l %tree.open %hex init_task.tasks init_task.tasks.next

  0x0 (0)|  [D:0xC1612588] (
         |    [D:0xC1612588] next = 0xEE058220,
         |    [D:0xC161258C] prev = 0xE5C0B3A0),
  0x1 (1)|  [D:0xEE058220] (
         |    [D:0xEE058220] next = 0xEE0587A0,
         |    [D:0xEE058224] prev = 0xC1612588),
  0x2 (2)|  [D:0xEE0587A0] (
         |    [D:0xEE0587A0] next = 0xEE058D20,
         |    [D:0xEE0587A4] prev = 0xEE058220),
  0x3 (3)|  [D:0xEE058D20] (
         |    [D:0xEE058D20] next = 0xEE0592A0,
         |    [D:0xEE058D24] prev = 0xEE0587A0),
  0x4 (4)|  [D:0xEE0592A0] (
         |    [D:0xEE0592A0] next = 0xEE059820,
         |    [D:0xEE0592A4] prev = 0xEE058D20),
  0x5 (5)|  [D:0xEE059820] (
         |    [D:0xEE059820] next = 0xEE059DA0,
         |    [D:0xEE059824] prev = 0xEE0592A0),
  0x6 (6)|  [D:0xEE059DA0] (
         |    [D:0xEE059DA0] next = 0xEE05A320,
         |    [D:0xEE059DA4] prev = 0xEE059820),
  0x7 (7)|  [D:0xEE05A320] (
         |    [D:0xEE05A320] next = 0xEE05A8A0,
         |    [D:0xEE05A324] prev = 0xEE059DA0),
  0x8 (8)|  [D:0xEE05A8A0] (
         |    [D:0xEE05A8A0] next = 0xEE05AE20,
         |    [D:0xEE05A8A4] prev = 0xEE05A320),
  0x9 (9)|  [D:0xEE05AE20] (
         |    [D:0xEE05AE20] next = 0xEE05B3A0,
         |    [D:0xEE05AE24] prev = 0xEE05A8A0),
0x0A (10)|  [D:0xEE05B3A0] (
         |    [D:0xEE05B3A0] next = 0xEE05B920,
         |    [D:0xEE05B3A4] prev = 0xEE05AE20),
0x0B (11)|  [D:0xEE05B920] (
         |    [D:0xEE05B920] next = 0xEE05BEA0,
         |    [D:0xEE05B924] prev = 0xEE05B3A0),
0x0C (12)|  [D:0xEE05BEA0] (
         |    [D:0xEE05BEA0] next = 0xEE05C420,
         |    [D:0xEE05BEA4] prev = 0xEE05B920),
0x0D (13)|  [D:0xEE05C420] (
         |    [D:0xEE05C420] next = 0xEE05DA20,
         |    [D:0xEE05C424] prev = 0xEE05BEA0),
0x0E (14)|  [D:0xEE05DA20] (
         |    [D:0xEE05DA20] next = 0xEE05DFA0,
         |    [D:0xEE05DA24] prev = 0xEE05C420),
0x0F (15)|  [D:0xEE05DFA0] (
         |    [D:0xEE05DFA0] next = 0xEE05E520,
         |    [D:0xEE05DFA4] prev = 0xEE05DA20),