crash命令 —— list


參考:

說明

頭節點是A_head:

struct A_head {                     // -h: 內嵌了list_head的結構體的地址
    ...                             // -O: list_head在頭節點中的偏移量,只能跟-h搭配
    struct list_head list;          // -H: list_head的地址
    int b;                          // -s: 想要查看的結構體的成員的偏移量
};

普通節點是A:

struct A {                          // -h: 內嵌了list_head的結構體的地址
    ...                             // -o: list_head普通中的偏移量
    struct list_head list;          // -H: list_head的地址
    char pid;                       // -s: 想要查看的結構體的成員的偏移量
};

假設將來A通過A.list掛到A_head.

-H: list_head的地址
-h: 內嵌了list_head的結構體A_head或者A的地址
-o: 在普通節點中list_head在A中的偏移,格式A.list
-O: 在頭結點中list_head在A中的偏移,格式A_head.list。當頭節點跟普通節點不同的時候需要這個參數,在輸出的內容里不會輸出頭節點的內容。
-s: 要查看的結構體的成員

示例

  • 遍歷線程組thread_group
    當創建線程的時候,當前進程下的所有線程的task_struct都通過thread_node掛在了task_struct->signal->thread_head下面。
	list_add_tail_rcu(&p->thread_group,
		  &p->group_leader->thread_group);
	list_add_tail_rcu(&p->thread_node,
		  &p->signal->thread_head);

線程組中的task的signal是相同的,所以先獲取signal的地址,然后遍歷thread_head鏈表即可。

以task 714為例:

crash> task -R signal 714
PID: 714    TASK: ffff889e1449c000  CPU: 14  COMMAND: "kvm"
  signal = 0xffff889ecdaab600,

然后查看thread_head的地址:

crash> signal_struct.nr_threads,thread_head 0xffff889ecdaab600
  nr_threads = 17
  thread_head = {
    next = 0xffff889ecd9789b8,
    prev = 0xffff88a031cf89b8
  }

當前線程組有17個線程,開始遍歷:

crash> list -o task_struct.thread_node -s task_struct.pid,tgid -H ffff889ecdaab610
ffff889ecd978000
  pid = 451
  tgid = 451
ffff889ed1c44000
  pid = 452
  tgid = 451
ffff8899f8bb2000
  pid = 456
  tgid = 451
ffff8897bc884000
  pid = 480
  tgid = 451
ffff8897bc880000
  pid = 487
  tgid = 451
ffff8897bc882000
  pid = 488
  tgid = 451
ffff8897bc886000
...
  • 遍歷cgroup_root

  • 以下面的數據結構關系為例:
    image

說明:

  • head_node使用head_list連接到list_head_test中
  • head_node之間有父子關系
  • head_node的node通過node.list連到head_node.node_list下面
  • 所有的node通過node.slib連接在一起
  • 上面的標號表示的是下面的對應的示例程序使用的起始地址
  1. 查看list_head_test地址
crash> sym list_head_test
ffffffffad245b30 (d) list_head_test
  1. 查看list_head_test鏈表下掛的head_node
crash> list -o head_node.head_list -s head_node.name -H ffffffffad245b30
ffff93b2850c3b40  // struct head_node的地址
  name = 0xfffffffface7a68f "head1",
ffff93b2850c3b80  // struct head_node的地址
  name = 0xfffffffface7a695 "head2",
ffff93b2850c3bc0  // struct head_node的地址
  name = 0xfffffffface7a69b "head3",
  1. 查看head1parent
crash> list -o head_node.parent -s head_node.name ffff93b2850c3b40
ffff93b2850c3b40
  name = 0xfffffffface7a68f "head1",
ffff93b2850c3b80
  name = 0xfffffffface7a695 "head2",
ffff93b2850c3bc0
  name = 0xfffffffface7a69b "head3",

在結構體中,parent沒有采用list_head鏈表,所以不能用-h或者-H

  1. 查看head_node1下的node成員
crash> list -o node.list -s node.name -O head_node.node_list -h ffff93b2850c3b40
ffff93b2850c3c00
  name = 0xfffffffface7a6a1 "node1",
ffff93b2850c3c40
  name = 0xfffffffface7a6a7 "node2",
ffff93b2850c3c80
  name = 0xfffffffface7a6ad "node3",
  1. 查看head_node2下的node成員
crash> list -o node.list -s node.name -O head_node.node_list -h ffff93b2850c3b80
ffff93b2850c3cc0
  name = 0xfffffffface7a6b3 "node4",
ffff93b2850c3d00
  name = 0xfffffffface7a6b9 "node5",
ffff93b2850c3d40
  name = 0xfffffffface7a6bf "node6",
  1. 查看head_node3下的node成員
crash> list -o node.list -s node.name -O head_node.node_list -h ffff93b2850c3bc0
ffff93b2850c3d80
  name = 0xfffffffface7a6c5 "node7",
ffff93b2850c3dc0
  name = 0xfffffffface7a6cb "node8",
ffff93b2850c3e00
  name = 0xfffffffface7a6d1 "node9",
  1. 查看node.slib鏈表中的成員

使用node1的起始地址

crash> list -o node.slib -s node.name -h ffff93b2850c3c00
ffff93b2850c3c00
  name = 0xfffffffface7a6a1 "node1",
ffff93b2850c3c40
  name = 0xfffffffface7a6a7 "node2",
ffff93b2850c3c80
  name = 0xfffffffface7a6ad "node3",
ffff93b2850c3cc0
  name = 0xfffffffface7a6b3 "node4",
ffff93b2850c3d00
  name = 0xfffffffface7a6b9 "node5",
ffff93b2850c3d40
  name = 0xfffffffface7a6bf "node6",
ffff93b2850c3d80
  name = 0xfffffffface7a6c5 "node7",
ffff93b2850c3dc0
  name = 0xfffffffface7a6cb "node8",
ffff93b2850c3e00
  name = 0xfffffffface7a6d1 "node9",

如果使用-O參數,那么會把傳入地址當作頭節點,輸出的內容不包含頭節點的內容:

crash> list -o node.slib -s node.name  -O node.slib -h ffff93b2850c3c00
ffff93b2850c3c40
  name = 0xfffffffface7a6a7 "node2",
ffff93b2850c3c80
  name = 0xfffffffface7a6ad "node3",
ffff93b2850c3cc0
  name = 0xfffffffface7a6b3 "node4",
ffff93b2850c3d00
  name = 0xfffffffface7a6b9 "node5",
ffff93b2850c3d40
  name = 0xfffffffface7a6bf "node6",
ffff93b2850c3d80
  name = 0xfffffffface7a6c5 "node7",
ffff93b2850c3dc0
  name = 0xfffffffface7a6cb "node8",
ffff93b2850c3e00
  name = 0xfffffffface7a6d1 "node9",

其他

-o

那么list只能查看list_head串起來的鏈表嗎?

當然不是,上面的輸出parent鏈表也說明了這一點。在list的幫助文檔里說:

  [-o] offset  The offset within the structure to the "next" pointer
               (default is 0).  If non-zero, the offset may be entered
               in either of two manners:

               1. In "structure.member" format; the "-o" is not necessary.
               2. A number of bytes; the "-o" is only necessary on processors
                  where the offset value could be misconstrued as a kernel
  • 場景1

image

list -s structA.value addr
or
list -o 0 -s structA.value addr

  • 場景2

image

list -o structB.next -s structB.value addr
or
list -o offset -s structB.value addr

-l

-l參數的幫助:

    -l offset  Only used in conjunction with -s, if the start address argument
               is a pointer to an embedded list head (or any other similar list
               linkage structure whose first member points to the next linkage
               structure), the offset to the embedded member may be entered
               in either of the following manners:

                 1. in "structure.member" format.
                 2. a number of bytes.

image

list -l structC.next -s structC.value addr
or
list -l offset -s structC.value addr

示例:
image

可以想象,如果next位置移到了結構體開頭,那么下面幾種做法都可以:
image

list -o structD.next -s strcutD.value addr
or
list -l structD.next -s structD.value vaddr
or
list -s structD.value addr

示例:
image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM