我尝试在用户友好的方式在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
list
成员struct module
成员的指针,然后我们应该调用container_of(modules->next, struct module, list)
来获取指向容器的指针。
为了能够在T32中存档,我需要计算容器类型中list
成员的偏移量。
任何人都知道如何实现这一目标?
答案 0 :(得分:4)
嗯,听起来你有两个问题:
对于显示链接列表,我建议使用命令Var.CHAIN或VAR.FixedCHAIN。这两个命令都有两个必需参数:结构的变量名和下一个元素的名称。 (您可以在TRACE32 manual中查找所有可选参数和格式选项。)
所以,用
查看你的第一个简单案例Var.CHAIN modules modules.next
将打开一个窗口,其中会有一个表格,显示完整列表,直到下一个'指向NULL。
注意 :如下面评论中Wrymarki所述,答案的第一部分实际上是错误的。 Var.CHAIN适用于普通的链接列表,但不适用于" Linux链接列表"。 " Linux链接列表的解决方案" (由Wrymarki编写)是编写一个PRACTICE脚本,它循环遍历列表,并使用container_of()宏将列表条目与Var.AddWatch一起添加到监视窗口(见下文)。
对于获取结构中成员的偏移,我建议像在源代码中一样声明预处理器宏。或者几乎在您的源代码中,因为TRACE32不知道GCC特定的扩展名,如typeof()或statement expressions。
无论如何,我们可以用
获取offsetof()宏sYmbol.NEW.MACRO offsetof(type,member) ((int)(&((type*)0)->member))
预处理器宏可以在TRACE32中的每个HLL表达式中使用(包含所有Var。*命令和函数)。 E.g:
Var.AddWatch offsetof(struct module,list)
注意:sYmbol.NEW.MACRO不接受宏名称中的空格:您必须写offsetof(type,member)
而不是offsetof(type, member)
。
您可以在窗口sYmbol.List.MACRO
中查看您的宏如果您的编译器在使用选项/ MACRO Data.LOAD.Elf * /MACRO
加载ELF时支持此编码(GCC使用选项-g3),您也可以从源代码中获取宏。但同样: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)
答案 1 :(得分: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),