wrymarkX
wrymarkX

Reputation: 99

Display Linux linked list in Trace32

I try to print Linux linked list in user friendly way in Trace32.

1. Is there already any known method available?

If not then let me show an example with modules list.

I have global variable

static struct list_head modules;

where

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

So, in T32 I just see list of next and prev pointers when doing v.v modules, no useful info in fact. However, every node of modules list is a part of a container type. In this case struct module

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

Normally, to extract container pointer Linux uses container_of macro.

/**
  * 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) );})

In our example we know the pointer to struct list_head which is a list member in struct module then we should call container_of(modules->next, struct module, list) to get a pointer to the container.

To be able to archive this in T32 I need to calculate offset of the list member in container type.

Anyone knows how to achieve this?

Upvotes: 1

Views: 1857

Answers (2)

Austin Kim
Austin Kim

Reputation: 9

Between Var.CHAIN and VAR.FixedCHAIN command, I guess Var.CHAIN displayed more detailed linked list information.

In case of linux kernel system, the following command allows for the complete list of linked list.

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),

Upvotes: 0

Holger
Holger

Reputation: 4183

Well, sounds for me that you have two questions:

  1. How to display linked lists?
  2. How to get the byte offset of a member in a struct?

For displaying linked lists I suggest the command Var.CHAIN or VAR.FixedCHAIN. Both commands have two mandatory arguments: Variable name of the struct and name of the next element. (You can look up all the optional arguments and format options in the TRACE32 manual.)

So, view your first simple case with

Var.CHAIN modules modules.next   

A window will open with a table showing you the complete list until 'next' points to NULL.

Note: As stated by Wrymarki below in the comments, this first part of the answer is actually wrong. Var.CHAIN works for ordinary linked lists, but not for "Linux linked lists". Solution for "Linux linked lists" (by Wrymarki) is to write a PRACTICE script which loops through the list and adds the list entries with Var.AddWatch to a watch-window by using the container_of() macro (see below).


For getting the offsset of of a member in a struct I recommend to declare preprocessor macros just like you do in your source code. Or almost like in your source code since TRACE32 does not know GCC specific extensions like typeof() or statement expressions.

Anyway, we can get the offsetof() macro with

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

A preprocessor macro can be used inside every HLL expression in TRACE32 (with all Var.* commands and functions). E.g.:

Var.AddWatch offsetof(struct module,list)

Note: sYmbol.NEW.MACRO does not accept spaces in the macro name: You have to write offsetof(type,member) instead of offsetof(type, member).

You can view your macros in window sYmbol.List.MACRO

You can also get the macros from your source code if your compiler support this (GCC does with option -g3) when loading your ELF with option /MACRO: Data.LOAD.Elf * /MACRO. But again: TRACE32 will not understand GCC specific extensions or internal macros like '__builtin_offsetof()'.


You can also declare a container_of() preprocessor macro with

sYmbol.NEW.MACRO container_of(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))

Use it e.g. as follows:

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

Upvotes: 4

Related Questions