Here is some description about walk command regarding list_head support and
use of
iteration_threshold. (my comments are surrounded by /* */)
>> ? walk
COMMAND: walk
-l
struct field|offset addr [-f] [-n] [-h n|p]
struct field|offset addr -s [-h n|p]
struct field|offset addr -h n|p -t
address offset size
[-i iteration_threshold]
[-w outfile]
Walk a linked list of kernel structures or memory blocks.
OPTIONS:
-l
Show a list of special structures that can be displayed in a
predefined formatted manner.
Currently there is support for a handful special structures.
struct field|offset addr [-f] [-n] [-h n|p]
Display each entry of a linked list of special structures in
a predefined formatted way.
By default the output consists of one line for each structure.
Using "-f" and/or "-n" a more detailed output is given.
"-f" can be used for all special structures. "-n" works for
special structures mm_struct and task_struct.
struct field|offset addr -s [-h n|p]
Each structure of a linked list is displayed in its entirety -
in a C-like format. All structures for which type information is
available can be displayed in this manner.
-h n|p
A linked list is constructed by following 'list_head' structures
instead of next pointers. The argument specifies wether to
follow
the next pointers of struct list_head (using 'n') or to follow
the prev pointers of struct list_head (by using 'p').
'field' or 'offset' is regarded as a member of type 'list_head'
instead of a next pointer within the 'struct'. 'addr' is
interpreted as a pointer to an anchor of a linked list of
'struct list_head' structures.
struct field|offset addr -h n|p -t
Display each entry of a linked 'list_head'-list in one line.
For each entry the address to the 'struct' structure, the
address to the 'list_head' member within 'struct', and previous
and next pointer of the embedded 'list_head' are given.
address offset size
Do a hex memory dump of each structure in a list.
A start address ('address') of a structure, a byte offset
('offset') for the next pointer in the structure, and a
structure size ('size') are required. 'size' bytes will be
dumped for each entry in the constructed list.
-i iteration_threshold
By default certain loops are interrupted after 10'000 iterations
to avoid endless loops while following invalid pointers. Using
this option you can change the threshold for the current
command.
A value '0' means infinite iteration threshold, i.e. no
interruption of the loop is caused by reaching the threshold.
While using "struct field|offset addr" without "-h" a structure name
('struct'), a field name ('field') or byte offset ('offset') for the
next
pointer within the structure, and a pointer ('addr') to the first entry
of the linked list must be given.
Note: Using "-h" the anchor is not displayed as a structure 'struct'.
/* Example 1: walking through list_head lists
Lets see of what use are list_head structures. */
>> task
ADDR UID PID PPID STATE FLAGS NAME
===============================================================================
0x1ac000 0 0 0 0 0 swapper
0x9dc000 0 1 0 1 0x100 init
0x9bc000 0 2 1 1 0x40 kmcheck
0x9b4000 0 3 1 1 0x40 keventd
0x960000 0 4 1 1 0x840 kswapd
0x95c000 0 5 1 1 0x840 kreclaimd
0x958000 0 6 1 1 0x40 bdflush
0x954000 0 7 1 2 0x40 kupdated
0x7844000 0 63 1 1 0x40 mdrecoveryd
0x73cc000 0 303 1 2 0x40 syslogd
0x7c24000 0 308 1 1 0x140 klogd
0x697c000 32 318 1 1 0x140 portmap
0x6910000 29 331 1 1 0x140 rpc.statd
0x66cc000 0 378 1 1 0x140 sshd
0x6644000 0 394 1 1 0x140 xinetd
0x61a0000 0 413 1 1 0x140 sendmail
0x7da4000 0 424 1 1 0x40 crond
0x5d48000 43 522 1 1 0x140 xfs
0x7db8000 0 542 1 1 0x100 login
0x5904000 0 615 542 1 0x100 bash
0x5688000 0 680 3 1 0x40 keventd
0x55f4000 0 848 615 0 0 cat
0x568c000 0 849 394 0 0x100 in.telnetd
0x5594000 0 850 849 0 0 login
===============================================================================
24 active task structs found
>> offset task_struct.run_list
Offset: 104 bytes.
/* task_struct.run_list is of type (list_head*) */
>> print 0x5594000+104 -x
0x5594068
/* Now we've got a pointer to a list_head, we use it as the anchor */
>> walk task_struct run_list 0x5594068 -h n -t
STRUCT ADDR PREV LISTHEAD
NEXT
============================================================================
0 0x568c068 0x5594068
0x55f4068
0x55f4000 0x5594068 0x55f4068
0x1b25b0
0x1b2548 0x55f4068 0x1b25b0
0x568c068
0x568c000 0x1b25b0 0x568c068
0x5594068
============================================================================
>> walk task_struct run_list 0x5594068 -h n
ADDR UID PID PPID STATE FLAGS NAME
===============================================================================
0x55f4000 0 848 615 0 0 cat
0x1b2548 1780328 0 0 0 0
0x568c000 0 849 394 0 0x100 in.telnetd
===============================================================================
/* We have chosen a wrong anchor, the 2nd element seems not to be a
task_struct. You can see this by looking up 0x1b2548 in the task table
above.
So we choose this 2nd element as the new anchor.
Take care, it corresponds to the 3rd element in the table before the
last one. Up there we get from line 3, column 3 the desired address of
the anchor: 0x1b25b0. */
>> walk task_struct run_list 0x1b25b0 -h n -t
STRUCT ADDR PREV LISTHEAD
NEXT
============================================================================
0 0x55f4068 0x1b25b0
0x568c068
0x568c000 0x1b25b0 0x568c068
0x5594068
0x5594000 0x568c068 0x5594068
0x55f4068
0x55f4000 0x5594068 0x55f4068
0x1b25b0
============================================================================
>> walk task_struct run_list 0x1b25b0 -h n
ADDR UID PID PPID STATE FLAGS NAME
===============================================================================
0x568c000 0 849 394 0 0x100 in.telnetd
0x5594000 0 850 849 0 0 login
0x55f4000 0 848 615 0 0 cat
===============================================================================
/* Cool. What we've got is the list of running tasks.
What a waste of time. We could have seen this by looking up
"STATE 0" processes in the task table above.
But, let's look for more information about the anchor: */
>> fsym 0x1b25b0
ADDR OFFSET TYPE NAME
============================================================
0x1b25b0 0 LOCAL_DATA runqueue_head
============================================================
1 symbol found
/* Ok, makes sens to me. */
/* Using '-h p' changes the direction of our walk: */
>> walk task_struct run_list 0x1b25b0 -h p
ADDR UID PID PPID STATE FLAGS NAME
===============================================================================
0x55f4000 0 848 615 0 0 cat
0x5594000 0 850 849 0 0 login
0x568c000 0 849 394 0 0x100 in.telnetd
===============================================================================
>> walk task_struct run_list 0x1b25b0 -h p -t
STRUCT ADDR NEXT LISTHEAD
PREV
============================================================================
0 0x568c068 0x1b25b0
0x55f4068
0x55f4000 0x1b25b0 0x55f4068
0x5594068
0x5594000 0x55f4068 0x5594068
0x568c068
0x568c000 0x5594068 0x568c068
0x1b25b0
============================================================================
/* Example 2: iteration threshold */
>> fsym inode_in_use inode_unused /* Further anchors of some list_head
lists. */
ADDR OFFSET TYPE NAME
============================================================
0xc0243e40 0 GLOBAL_DATA inode_in_use
0xc0243e48 0 LOCAL_DATA inode_unused
============================================================
2 symbols found
>> walk inode i_list 0xc0243e40 -h n
Neither a "predefined"structure, nor options '-s' or '-t' specified. Can't
print structure.
/* Bad luck.
We will use '-t' and not '-s' for this demonstration.
(Just take a look at 'whatis inode', and you know why.) */
>> walk inode i_list 0xc0243e40 -h n -t
STRUCT ADDR PREV LISTHEAD NEXT
============================================
0 0xcff38008 0xc0243e40 0xc5501c38
WARNING: Pointer broken. 0xc579c3e0, SHOULD BE: 0xc0243e40
0xc5501c30 0xc579c3e0 0xc5501c38 0xc6314f68
0xc6314f60 0xc5501c38 0xc6314f68 0xc2c44e20
0xc2c44e18 0xc6314f68 0xc2c44e20 0xc8671340
0xc8671338 0xc2c44e20 0xc8671340 0xc54da528
0xc54da520 0xc8671340 0xc54da528 0xcbde6528
0xcbde6520 0xc54da528 0xcbde6528 0xcf8771f8
...
0xcaa8f710 0xca663340 0xcaa8f718 0xcb472b90
0xcb472b88 0xcaa8f718 0xcb472b90 0xcb3e8b90
0xcb3e8b88 0xcb472b90 0xcb3e8b90 0xcb3e9af0
0xcb3e9ae8 0xcb3e8b90 0xcb3e9af0 0xcc279860
0xcc279858 0xcb3e9af0 0xcc279860 0xcc2f9488
0xcc2f9480 0xcc279860 0xcc2f9488 0xcd00c900
0xcd00c8f8 0xcc2f9488 0xcd00c900 0xcceeb488
WARNING: Iteration threshold reached. Current threshold: 10000.
Use "-i" to change threshold.
/* Ooops, something broken ... My dump was generated using 'livedump'
in lcrash. So probably some inodes have changed.
Furthermore the default iteration threshold was reached.
We try again without any threshold value: */
>> walk inode i_list 0xc0243e40 -h n -t -i 0
STRUCT ADDR PREV LISTHEAD NEXT
============================================
0 0xcff38008 0xc0243e40 0xc5501c38
WARNING: Pointer broken. 0xc579c3e0, SHOULD BE: 0xc0243e40
0xc5501c30 0xc579c3e0 0xc5501c38 0xc6314f68
0xc6314f60 0xc5501c38 0xc6314f68 0xc2c44e20
0xc2c44e18 0xc6314f68 0xc2c44e20 0xc8671340
0xc8671338 0xc2c44e20 0xc8671340 0xc54da528
0xc54da520 0xc8671340 0xc54da528 0xcbde6528
0xcbde6520 0xc54da528 0xcbde6528 0xcf8771f8
...
0xcfbfe7b0 0xcf985488 0xcfbfe7b8 0xcf8df9a8
0xcf8df9a0 0xcfbfe7b8 0xcf8df9a8 0xcf9383e0
0xcf9383d8 0xcf8df9a8 0xcf9383e0 0xcfbfe298
0xcfbfe290 0xcf9383e0 0xcfbfe298 0xcfbfe3e0
0xcfbfe3d8 0xcfbfe298 0xcfbfe3e0 0xcfbfe528
0xcfbfe520 0xcfbfe3e0 0xcfbfe528 0xcfbff340
0xcfbff338 0xcfbfe528 0xcfbff340 0xcff38e20
0xcff38e18 0xcfbff340 0xcff38e20 0xcff395d0
0xcff395c8 0xcff38e20 0xcff395d0 0xcff39860
0xcff39858 0xcff395d0 0xcff39860 0xcff39c38
0xcff39c30 0xcff39860 0xcff39c38 0xcff39d80
0xcff39d78 0xcff39c38 0xcff39d80 0xcff38008
0xcff38000 0xcff39d80 0xcff38008 0xc0243e40
============================================
/* In fact after some time we came to a happy end. So there was no
endless loop.
But let's look at the broken prev pointer again: */
>> walk inode i_list 0xc0243e40 -h n -t -i 5
STRUCT ADDR PREV LISTHEAD NEXT
============================================
0 0xcff38008 0xc0243e40 0xc5501c38
WARNING: Pointer broken. 0xc579c3e0, SHOULD BE: 0xc0243e40
0xc5501c30 0xc579c3e0 0xc5501c38 0xc6314f68
0xc6314f60 0xc5501c38 0xc6314f68 0xc2c44e20
0xc2c44e18 0xc6314f68 0xc2c44e20 0xc8671340
0xc8671338 0xc2c44e20 0xc8671340 0xc54da528
0xc54da520 0xc8671340 0xc54da528 0xcbde6528
WARNING: Iteration threshold reached. Current threshold: 5.
Use "-i" to change threshold.
/* Walking the other way around everything seems ok: */
>> walk inode i_list 0xc0243e40 -h p -t -i 5
STRUCT ADDR NEXT LISTHEAD PREV
============================================
0 0xc5501c38 0xc0243e40 0xcff38008
0xcff38000 0xc0243e40 0xcff38008 0xcff39d80
0xcff39d78 0xcff38008 0xcff39d80 0xcff39c38
0xcff39c30 0xcff39d80 0xcff39c38 0xcff39860
0xcff39858 0xcff39c38 0xcff39860 0xcff395d0
0xcff395c8 0xcff39860 0xcff395d0 0xcff38e20
WARNING: Iteration threshold reached. Current threshold: 5.
Use "-i" to change threshold.
>>
Regards,
Andreas
--
Linux for eServer Development
Tel : +49-7031-16-4640
Notes mail : Andreas Herrmann/GERMANY/IBM@IBMDE
email : aherrman@xxxxxxxxxx
|