1

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

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

如果没有,那么让我展示一个带有模块列表的示例。

我有全局变量

static struct list_head modules;

在哪里

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

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

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 哪个list成员的指针,struct module然后我们应该调用container_of(modules->next, struct module, list)以获取指向容器的指针。

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

任何人都知道如何实现这一目标?

4

2 回答 2

4

好吧,听起来你有两个问题:

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

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

因此,查看您的第一个简单案例

Var.CHAIN modules modules.next   

将打开一个窗口,其中包含一个显示完整列表的表格,直到“下一个”指向 NULL。

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


为了获取结构中成员的偏移量,我建议像在源代码中一样声明预处理器宏。或者几乎就像在您的源代码中一样,因为 TRACE32 不知道 GCC 特定的扩展,如 typeof() 或语句表达式

无论如何,我们可以得到 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).

您可以在窗口 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)
于 2015-11-05T10:44:35.767 回答
0

在 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),
于 2017-07-25T00:38:24.537 回答