centos7
crash

crashコマンドの使い方

1 環境

[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.3.1611 (Core)

[root@server ~]# uname -r
3.10.0-514.el7.x86_64

2 事前準備

crashコマンドをインストールする。
[root@server ~]# yum -y install crash
[root@server ~]# crash --version
crash 7.1.5-2.el7
-以下、略-

カーネルのシンボル情報を表示するため、kernel-debuginfoをインストールする。
依存関係のあるkernel-debuginfo-commonも同時にインストールされる。カーネルと同じ版数のものをインストールする必要があります。
[root@server ~]# yum --enablerepo=base-debuginfo install kernel-debuginfo-3.10.0-514.el7.x86_64
[root@server ~]# rpm -qa|grep kernel-debuginfo
kernel-debuginfo-common-x86_64-3.10.0-514.el7.x86_64
kernel-debuginfo-3.10.0-514.el7.x86_64

3 crashコマンド起動方法

crashと入力する
[root@server ~]# crash

crash 7.1.5-2.el7
Copyright (C) 2002-2016  Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010  IBM Corporation
Copyright (C) 1999-2006  Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012  Fujitsu Limited
Copyright (C) 2006, 2007  VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011  NEC Corporation
Copyright (C) 1999, 2002, 2007  Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002  Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions.  Enter "help copying" to see the conditions.
This program has absolutely no warranty.  Enter "help warranty" for details.

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-unknown-linux-gnu"...

      KERNEL: /usr/lib/debug/lib/modules/3.10.0-514.el7.x86_64/vmlinux
    DUMPFILE: /dev/crash
        CPUS: 2
        DATE: Thu Jul 13 20:15:51 2017
      UPTIME: 00:25:27
LOAD AVERAGE: 0.22, 0.08, 0.13
       TASKS: 116
    NODENAME: server
     RELEASE: 3.10.0-514.el7.x86_64
     VERSION: #1 SMP Tue Nov 22 16:42:41 UTC 2016
     MACHINE: x86_64  (2393 Mhz)
      MEMORY: 1 GB
         PID: 4022
     COMMAND: "crash"
        TASK: ffff880039cc6dd0  [THREAD_INFO: ffff88003533c000]
         CPU: 1
       STATE: TASK_RUNNING (ACTIVE)

crash>

4 コマンド一覧

crash> help  <=== "help"とタイプする。

*              files          mach           repeat         timer
alias          foreach        mod            runq           tree
ascii          fuser          mount          search         union
bt             gdb            net            set            vm
btop           help           p              sig            vtop
dev            ipcs           ps             struct         waitq
dis            irq            pte            swap           whatis
eval           kmem           ptob           sym            wr
exit           list           ptov           sys            q
extend         log            rd             task

crash version: 7.1.5-2.el7   gdb version: 7.6
For help on any command above, enter "help <command>".
For help on input options, enter "help input".
For help on output options, enter "help output".

5 コマンドのhelp表示方法

コマンド名のあとに、helpとタイプする。

btコマンドのhelpを表示する。
crash> help bt
-以下、略-

modコマンドのhelpを表示する
crash> help mod
-以下、略-

6 modコマンドの使い方

modコマンドでモジュールをロードすると、カーネルモジュールのシンボル情報が表示できるようになります。

6.1 モジュール一覧を表示する方法

"mod"とタイプして、モジュールの一覧を表示する。
crash起動直後は、モジュールはロードされていない。("not loaded"と表示される)
crash> mod
     MODULE       NAME                        SIZE  OBJECT FILE
ffffffffa00062a0  fjes                       32197  (not loaded)  [CONFIG_KALLSYMS]
ffffffffa000e360  ip_tables                  27115  (not loaded)  [CONFIG_KALLSYMS]
-以下、略-

6.2 モジュールをロードする方法(-s)

nfsv4モジュールをロードしてみます。私の環境では、nfsv4モジュールは、crash起動直後にロードされていません。

システム側にnfsv4モジュールがロードされているかどうかを確認する。ロードされていないことがわかる。
[root@server ~]# lsmod |grep nfsv4
[root@server ~]#

nfsv4モジュールが格納されているディレクトリに移動する。
[root@server ~]# cd /usr/lib/modules/3.10.0-514.el7.x86_64/kernel/fs/nfs

nfsv4モジュール(★印)を確認する。
[root@server nfs]# ls
blocklayout  filelayout  flexfilelayout  nfs.ko  nfsv3.ko  ★nfsv4.ko  objlayout

nfsv4モジュールをインストールする。
[root@server nfs]# modprobe nfsv4

モジュールがインストールできたかどうかを確認する。インストールされたことがわかる(★印)。
root@server nfs]# lsmod |grep nfsv4
nfsv4★               546174  0
nfs                   256718  1 nfsv4
dns_resolver           13140  1 nfsv4
sunrpc                334343  3 nfs,lockd,nfsv4
fscache                64891  2 nfs,nfsv4

次にcrashコマンドを実行して、nfsv4のモジュールがロードされているかどうか確認する。ロードされていないことがわかる。
crash> mod|grep nfsv4
crash>

nfsv4モジュールをロードする。モジュールがロードできたことがわかる(★印)。
crash> mod -s nfsv4
     MODULE       NAME                        SIZE  OBJECT FILE
ffffffffa0731360  nfsv4                     546174  ★/lib/modules/3.10.0-514.el7.x86_64/kernel/fs/nfs/nfsv4.ko

6.3 モジュールをアンロードする方法(-d)

nfsv4モジュールをアンロードする。
crash> mod -d nfsv4

モジュールがアンロードできたかどうかを確認する。アンロードできたことがわかる。
crash> mod|grep nfsv4
     MODULE       NAME                        SIZE  OBJECT FILE
ffffffffa0731360  nfsv4                     546174  (not loaded)  [CONFIG_KALLSYMS]

6.4 モジュールをロードしないとシンボル情報が使えないことの確認

システムにnfsv4モジュールがロードされていないことを確認する。
[root@server nfs]# lsmod |grep nfsv4
[root@server nfs]#

crashにもモジュールがロードされていない。
crash> mod|grep nfvs4
crash>

nfsv4モジュールに含まれる関数を逆アセンブルする。しかし、モジュールがロードされていないので、逆アセンブルできない
crash> dis do_renew_lease
symbol not found: do_renew_lease
possible alternatives:
  (none found)

システムにnfsv4モジュールをロードする。
[root@server nfs]# pwd
/lib/modules/3.10.0-514.el7.x86_64/kernel/fs/nfs
[root@server nfs]# modprobe nfsv4
[root@server nfs]# lsmod |grep nfsv4
nfsv4★               546174  0
dns_resolver           13140  1 nfsv4
nfs                   256718  1 nfsv4
sunrpc                334343  3 nfs,lockd,nfsv4
fscache                64891  2 nfs,nfsv4

crashにモジュールをロードする。モジュールがロードできたことがわかる(★印)。
crash> mod -s nfsv4
mod: NOTE: modules have changed on this system -- reinitializing
     MODULE       NAME                        SIZE  OBJECT FILE
ffffffffa06ed360  nfsv4                     546174  ★/lib/modules/3.10.0-514.el7.x86_64/kernel/fs/nfs/nfsv4.ko

nfsv4モジュールに含まれる関数を逆アセンブルする。今度は逆アセンブルができた。
crash> dis do_renew_lease
0xffffffffa067e2a0 <do_renew_lease>:    data32 data32 data32 xchg %ax,%ax [FTRACE NOP]
0xffffffffa067e2a5 <do_renew_lease+5>:  push   %rbp
0xffffffffa067e2a6 <do_renew_lease+6>:  mov    %rsp,%rbp
0xffffffffa067e2a9 <do_renew_lease+9>:  push   %r13
0xffffffffa067e2ab <do_renew_lease+11>: mov    %rsi,%r13
-以下、略-

7 netコマンドの使い方

7.1 net_device構造体を表示する方法

オプションなしでnetコマンドを実行する。lo,eth0,eth1のnet_device構造体が存在することがわかる。
crash> net
   NET_DEVICE     NAME   IP ADDRESS(ES)
ffff88003b7e3000  lo     127.0.0.1
ffff8800324be000  eth0   192.168.0.10
ffff880039d84000  eth1   172.16.0.10

7.2 arpキャッシュを表示する方法(-a)

crash> net -a
NEIGHBOUR        IP ADDRESS      HW TYPE    HW ADDRESS         DEVICE  STATE
ffff880034987800 192.168.0.5     ETHER      b4:82:fe:d2:8c:1a  eth0    REACHABLE
ffff88003a077200 192.168.0.1     ETHER      00:3a:9d:1e:da:07  eth0    REACHABLE
ffff88003492f000 127.0.0.1       UNKNOWN    00 00 00 00 00 00  lo      NOARP

7.3 プロセスがオープンしているソケットの情報を表示する方法(-s,-S)

-s(小文字)はソケットの関する簡易的な表示、-S(大文字)はソケットに関する詳細情報を表示します。

別ターミナルをオープンして、ncコマンドを実行する。11111番ポートでListenする。
[root@server ~]# nc -l 11111

ncコマンドのPIDを求める。PIDは4364であることがわかる(★印)。
crash> ps nc
   PID    PPID  CPU       TASK        ST  %MEM     VSZ    RSS  COMM
 ★4364   4156   0  ffff880031f62f10  IN   0.2   43512   2004  nc

-------------
1. 簡易表示
-------------
ncコマンドが使っているソケットの簡易情報を表示する。11111番ポートでListenしていることがわかる(★印)。
crash> net -s 4364
PID: 4364   TASK: ffff880031f62f10  CPU: 0   COMMAND: "nc"
FD      SOCKET            SOCK       FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
 3 ffff8800390e5000 ffff880035ee8000 INET6:STREAM
 4 ffff8800390e3c00 ffff88003b3d3640 INET:STREAM  0.0.0.0-★11111 0.0.0.0-0

-------------
2. 詳細表示
-------------
ncコマンドが使っているソケットの詳細情報を表示する。
crash> net -S 4364
PID: 4364   TASK: ffff880031f62f10  CPU: 0   COMMAND: "nc"
FD       SOCKET             SOCK
 3  ffff8800390e5000  ffff880035ee8000      <=★FD3のソケットの詳細情報

struct socket {
  state = SS_UNCONNECTED,
  type = 1,
  flags = 0,
  wq = 0xffff88003b33a4c0,
  file = 0xffff880032354600,
  sk = 0xffff880035ee8000,
  ops = 0xffffffff8173d7c0 <inet6_stream_ops>

-中略-

FD       SOCKET             SOCK
 4  ffff8800390e3c00  ffff88003b3d3640     <=★FD4のソケットの詳細情報

struct socket {
  state = SS_UNCONNECTED,
  type = 1,
  flags = 0,
  wq = 0xffff88003b33a640,
  file = 0xffff880032355f00,
  sk = 0xffff88003b3d3640,
  ops = 0xffffffff8173a420 <inet_stream_ops>
}
-以下、略-

7.4 数値をIPアドレスに変換する方法(-N)

crash> net -N 1041236234
10.1.16.62

7.5 特定の条件で絞り込みをする方法(-R)

全プロセスが使用しているソケットの中から、特定の条件に合致するものだけを表示します。
foreachコマンドと組み合わせて絞り込みを行います。

-----------------------
1. FD番号で絞り込む方法
-----------------------
全プロセスが使用しているソケットの中から、FD=3(★印)のものだけを表示する。
crash> foreach net -s -R 3
PID: 357    TASK: ffff880033645e20  CPU: 1   COMMAND: "systemd-journal"
FD      SOCKET            SOCK       FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
★3 ffff88003acc2300 ffff880035333400 UNIX:STREAM

PID: 378    TASK: ffff880039d3edd0  CPU: 1   COMMAND: "systemd-udevd"
FD      SOCKET            SOCK       FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
★3 ffff880034b5a300 ffff880034623800 NETLINK/ROUTE:RAW
-以下、略-

---------------------------------
2. SOCKETのアドレスで絞り込む方法
---------------------------------
全プロセスが使用しているソケットの中から、SOCKETのアドレスがffff88003acc4880のものだけを表示する。
systemdとlvmetadが、同じSOCKET(★印)を使っていることがわかる。
crash> foreach net -s -R ffff88003acc4880
PID: 1      TASK: ffff88003bec8000  CPU: 1   COMMAND: "systemd"
FD      SOCKET            SOCK       FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
32 ★ffff88003acc4880 ffff880035337c00 UNIX:STREAM

PID: 379    TASK: ffff880039d3de20  CPU: 0   COMMAND: "lvmetad"
FD      SOCKET            SOCK       FAMILY:TYPE SOURCE-PORT DESTINATION-PORT
 3 ★ffff88003acc4880 ffff880035337c00 UNIX:STREAM

8 disコマンドの使い方

8.1 逆アセンブルを表示する方法

do_fork関数の逆アセンブルを表示する。
crash> dis do_fork
0xffffffff81084950 <do_fork>:   data32 data32 data32 xchg %ax,%ax [FTRACE NOP]
0xffffffff81084955 <do_fork+5>: push   %rbp
0xffffffff81084956 <do_fork+6>: mov    %rsp,%rbp
0xffffffff81084959 <do_fork+9>: push   %r15
0xffffffff8108495b <do_fork+11>:        push   %r14
0xffffffff8108495d <do_fork+13>:        xor    %r14d,%r14d
-以下、略-

8.2 逆アセンブル表示とソースファイルの対比を表示する方法(-l)

逆アセンブルが、ソースファイルのどの部分対応しているのかを表示します。

crash> dis -l do_fork
/usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/kernel/fork.c: 1690
0xffffffff81084950 <do_fork>:   data32 data32 data32 xchg %ax,%ax [FTRACE NOP]
0xffffffff81084955 <do_fork+5>: push   %rbp
0xffffffff81084956 <do_fork+6>: mov    %rsp,%rbp
0xffffffff81084959 <do_fork+9>: push   %r15
0xffffffff8108495b <do_fork+11>:        push   %r14
/usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/kernel/fork.c: 1692
0xffffffff8108495d <do_fork+13>:        xor    %r14d,%r14d
/usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/kernel/fork.c: 1690
-以下、略-

8.3 ソースファイルを表示する方法(-s)

do_fork関数を表示する。
crash> dis -s do_fork
FILE: kernel/fork.c
LINE: 1690

  1685  long do_fork(unsigned long clone_flags,
  1686                unsigned long stack_start,
  1687                unsigned long stack_size,
  1688                int __user *parent_tidptr,
  1689                int __user *child_tidptr)
* 1690  {
  1691          struct task_struct *p;
  1692          int trace = 0;
  1693          long nr;
-以下、略-

8.4 関数の間接呼び出しをしている部分のソースを表示する方法(-l)

下記★印が、関数の間接呼び出しをしている部分です。
crash> dis -l neigh_probe
/usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/net/core/neighbour.c: 869
0xffffffff8157b1e0 <neigh_probe>:       data32 data32 data32 xchg %ax,%ax [FTRACE NOP]
0xffffffff8157b1e5 <neigh_probe+5>:     push   %rbp
-中略-
0xffffffff8157b222 <neigh_probe+66>:    callq  *0x8(%rax)  <==★


間接呼び出しをしている部分のソースコードを表示する。
間接呼び出しをしているソースコードは、neigh->ops->solicitであることがわかる(★印)。
crash> dis -s 0xffffffff8157b222
FILE: net/core/neighbour.c
LINE: 875

  870           struct sk_buff *skb = skb_peek(&neigh->arp_queue);
  871           /* keep skb alive even if arp_queue overflows */
  872           if (skb)
  873                   skb = skb_copy(skb, GFP_ATOMIC);
  874           write_unlock(&neigh->lock);
* 875         ★neigh->ops->solicit(neigh, skb);
  876           atomic_inc(&neigh->probes);
  877           kfree_skb(skb);
  878   }

9 treeコマンドの使い方

9.1 確認に使うデータ

help treeの例題にでてくるvmap_area構造体を使います。

【図中の説明】
{}は構造体を意味しています。
()はred black treeの中での各ノードの位置を表しています。lは"left",rは"right"を意味しています。
ノードとは、ここでは、vmap_area構造体のことです。

                                                        (root)
                                                       vmap_area{}
                            ffff88003b528800 -> +---------------------+  -*-
                                                |    ulong va_start   |   |
                                                +---------------------+   |
                                                |    ulong va_end     |  24byte(offset) <= -oオプションで指定する。
                                                +---------------------+   |
                                                |                     |   |
                           rb_root{}            |                     |   |
                     +------------------+       |      rb_node{}      |   |
      vmap_area_root | ffff88003b528818 | ----> |+-------------------+|  -*-
                     +------------------+       || __rb_parent_color ||
                                                |+-------------------+|
                                                ||     *rb_right     ||-+
                                                |+-------------------+| |
                          (root/l)            +-||     *rb_left      || |         (root/r)
                          vmap_area{}         | |+-------------------+| |       vmap_area{}
   ffff8800345e4280->+---------------------+  | |                     | |  +---------------------+ <-ffff88003b7e9580
                     |                     |  | |                     | |  |                     |        |
                     |                     |  | |                     | |  |                     |        |
                     |                     |  | +---------------------+ |  |                     |    24byte(offset)
                     |                     |  | +---------------------+ |  |                     |        |
                     |     rb_node{}       |  |                         |  |     rb_node{}       |        |
   ffff8800345e4298->|+-------------------+|<-+                         +->|+-------------------+| <-ffff88003b7e9598
                     || __rb_parent_color ||                               || __rb_parent_color ||
                     |+-------------------+|                               |+-------------------+|
                     ||     *rb_right     ||--+                            ||     *rb_right     ||--->
                     |+-------------------+|  |                            |+-------------------+|
                  +--||     *rb_left      ||  |                        <---||     *rb_left      ||
                  |  |+-------------------+|  |                            |+-------------------+|
    (root/l/l)    |  |                     |  |    (root/l/r)              |                     |
    vmap_area{}   |  |                     |  |    vmap_area{}             |                     |
  +-------------+ |  +---------------------+  |  +-------------+           +---------------------+
  |             | |                           |  |             |
  |+-----------+|<+                           +->|+-----------+|
  || rb_node{} ||                                || rb_node{} ||
  |+-----------+|                                |+-----------+|
  |             |                                |             |
  +-------------+                                +-------------+


vmap_area_rootデータの型を求める。rb_root構造体であることがわかる。
crash> whatis vmap_area_root
struct rb_root vmap_area_root;

rb_root構造体は、rb_node構造体へのポインタであることがわかる。
crash> whatis rb_root
struct rb_root {
    struct rb_node *rb_node;
}
SIZE: 8

rb_node構造体を確認する。
crash> struct rb_node
struct rb_node {
    unsigned long __rb_parent_color;
    struct rb_node *rb_right;
    struct rb_node *rb_left;
}
SIZE: 24

vmap_area_rootデータのアドレス(★1)、およびvmap_area_rootが示すアドレス(★2)を求める.
crash> rd vmap_area_root
ffffffff81ef1830★1:  ffff88003b528818★2                    ..R;....

vmap_area構造体内のrb_nodeメンバのオフセットを求める。オフセットが24バイト(★印)であることがわかる。
crash> struct -o vmap_area
struct vmap_area {
    [0] unsigned long va_start;
    [8] unsigned long va_end;
   [16] unsigned long flags;
 ★[24] struct rb_node rb_node;
   [48] struct list_head list;

9.2 ノードの先頭アドレスを求める方法

前述したred black treeの各ノード(vmap_area構造体)の先頭アドレスを求める方法を以下に示します。

----------------------------------
1. 開始アドレスに数値を使う方法(-N)
----------------------------------
crash> tree -t rbtree -o vmap_area.rb_node -N 0xffff88003b528818
ffff88003b528800  ★rootのアドレス
ffff8800345e4280  ★root/lのアドレス
ffff88003f8aa700
ffff88003f8aa780
ffff88003f8aa100
-中略-
ffff88003a79ed80
ffff88003b09c600
ffff88003b7e9580  ★root/rのアドレス
ffff88003b528000
ffff8800345e4400
-以下、略-

---------------------------------------
2. 開始アドレスにシンボル名を使う方法
---------------------------------------
crash> tree -t rbtree -o vmap_area.rb_node vmap_area_root
ffff88003b528800  ★rootのアドレス
ffff8800345e4280  ★root/lのアドレス
ffff88003f8aa700
ffff88003f8aa780
ffff88003f8aa100
-中略-
ffff88003a79ed80
ffff88003b09c600
ffff88003b7e9580  ★root/rのアドレス
ffff88003b528000
ffff8800345e4400
-以下、略-

9.3 各ノードの位置を求める方法(-p)

crash> tree -t rbtree -o vmap_area.rb_node vmap_area_root -p

ffff88003b528800  <==図に示したrootの先頭アドレス
  position: root    <==位置
ffff8800345e4280    <==図に示したノードの先頭アドレス
  position: root/l  <==位置
ffff88003f8aa700
  position: root/l/l
ffff88003f8aa780
  position: root/l/l/l
ffff88003f8aa100
  position: root/l/l/l/l

-中略-

ffff88003a79ed80
  position: root/l/r/r/r/l/r/r
ffff88003b09c600
  position: root/l/r/r/r/r
ffff88003b7e9580   <==図に示したノードの先頭アドレス
  position: root/r  <==位置
ffff88003b528000
  position: root/r/l
ffff8800345e4400
  position: root/r/l/l
-以下、略-

9.4 各ノードのメンバの値を求める方法(-s)

各ノード(構造体)のメンバを表示する方法を示します。
ここでは、vmap_area構造体のva_startメンバとva_endメンバの値を表示します。

crash> tree -t rbtree -o vmap_area.rb_node vmap_area_root -s vmap_area.va_start,va_end
ffff88003b528800
  va_start = 18446744072098938880
  va_end = 18446744072098975744
ffff8800345e4280
  va_start = 18446683600572252160
  va_end = 18446683600572325888
ffff88003f8aa700
  va_start = 18446683600571727872
  va_end = 18446683600571809792

-以下、略-

9.5 16進数で表示する方法(-x)

前述で求めたva_startとva_endの出力を12進数で表示します。

crash> tree -t rbtree -o vmap_area.rb_node vmap_area_root -s vmap_area.va_start,va_end -x
ffff88003b528800
  va_start = 0xffffffffa0000000
  va_end = 0xffffffffa0009000
ffff8800345e4280
  va_start = 0xffffc90000220000
  va_end = 0xffffc90000232000
ffff88003f8aa700
  va_start = 0xffffc900001a0000
  va_end = 0xffffc900001b4000

-以下、略-

10 listコマンドの使い方

10.1 確認に使うデータ(その1)

構造体が単方向にリンクされたリストの表示方法について説明します。

【図中の説明】
{}は構造体を意味しています。


                   ffffffff81a4fd80    file_system_type{}                         file_system_type{}
  file_systems --------------------> +--------------------+           +-------> +--------------------+
                                     |      *name         | -> sysfs  |         |      *name         | -> rootfs
                                     +--------------------+           |         +--------------------+
                                     |      fs_flags      | -> 8      |         |      fs_flags      | -> 0
                                     +--------------------+           |         +--------------------+
                                     |                    |           |         |                    |
                                     +--------------------+           |         +--------------------+
                                     |       *next        | ----------+         |       *next        | ----->
                                     +--------------------+                     +--------------------+
                                     |                    |                     |                    |
                                     |                    |                     |                    |
                                     +--------------------+                     +--------------------+

crash> whatis file_systems
struct file_system_type *file_systems;
crash> rd file_systems
ffffffff81f55740:  ffffffff81a4fd80   

10.2 リストにつながれた構造体のメンバの値を表示する方法

crash> list file_system_type.next -s file_system_type.name,fs_flags ffffffff81a4fd80
ffffffff81a4fd80
  name = 0xffffffff8192af24 "sysfs"
  fs_flags = 8
ffffffff819c1420
  name = 0xffffffff818e6a65 "rootfs"
  fs_flags = 0
ffffffff81a507c0
  name = 0xffffffff818e9888 "ramfs"
  fs_flags = 8
-以下、略-

10.2 確認に使うデータ(その2)

list_head構造体で構造体が双方向にリンクされたリストの表示方法について説明します。

 ffffffff819c1460   task_struct{}                        task_struct{}
     init_task-> +----------------+                  +----------------+
                 |     pid=0      |                  |     pid=1      |
                 +----------------+                  +----------------+
                 | comm=swapper/0 |                  |  comm=systemd  |
                 +----------------+                  +----------------+
                 |                |                  |                |
                 |                |                  |                |
                 |                |                  |                |
                 |  list_head{}   |                  |   list_head{}  |
           -*-   +----------------+ <---+   +------> +----------------+
            |    |      *next     | ----|---+        |      *next     | ------->
          tasks  +----------------+     |            +----------------+
            |    |      *prev     |     +----------- |      *prev     |
           -*-   +----------------+                  +----------------+
                 |                |                  |                |
                 |                |                  |                |
                 |                |                  |                |
                 +----------------+                  +----------------+

crash> whatis init_task
struct task_struct init_task;

crash> rd init_task
ffffffff819c1460:  0000000000000000                    ........

10.4 リストにつながれた構造体のメンバの値を表示する方法

task_struct構造体のcommメンバを表示する方法
crash> list task_struct.tasks -s task_struct.comm -h ffffffff819c1460
ffffffff819c1460
  comm = "swapper/0\000\000\000\000\000\000"
ffff88003bec8000
  comm = "systemd\000\060\000\000\000\000\000\000"
ffff88003bec8fb0
  comm = "kthreadd\000\000\000\000\000\000\000"
ffff88003bec9f60
  comm = "ksoftirqd/0\000\000\000\000"
-以下、略-

task_struct構造体をすべて表示する方法
crash> list task_struct.tasks -s task_struct -h ffffffff819c1460
-以下、略-

task_struct構造体のcommメンバとpidメンバを表示する方法
crash> list task_struct.tasks -s task_struct.comm,pid -h ffffffff819c1460
ffffffff819c1460
  comm = "swapper/0\000\000\000\000\000\000"
  pid = 0
ffff88003bec8000
  comm = "systemd\000\060\000\000\000\000\000\000"
  pid = 1
ffff88003bec8fb0
  comm = "kthreadd\000\000\000\000\000\000\000"
  pid = 2
ffff88003bec9f60
  comm = "ksoftirqd/0\000\000\000\000"
  pid = 3
-以下、略-

11 setコマンドの使い方

11.1 現在のプロセスコンテキストの表示方法(set)

引数なしでsetコマンドを実行すると、現在のプロセスコンテキストを表示します。

crashコマンド起動直後にsetコマンドを実行する。プロセスコンテキストがcrashであることがわかる(★印)。
crash> set
    PID: 4038
COMMAND: "crash"★
   TASK: ffff880035ee6dd0  [THREAD_INFO: ffff880035edc000]
    CPU: 1
  STATE: TASK_RUNNING (ACTIVE)

11.2 プロセスコンテキストの切り替え方法(set <PID>)

コンテキストを切り替えることで、PIDの指定を省略することができるようになります。

プロセスコンテキストをsystemd(PID=1)に切り替える。
crash> set 1
    PID: 1
COMMAND: "systemd"
   TASK: ffff88003bec8000  [THREAD_INFO: ffff88003bed0000]
    CPU: 0
  STATE: TASK_INTERRUPTIBLE

btコマンドを実行する。btコマンドにPIDを指定しなくても、systemdのバックトレースが表示できるようになる。
crash> bt
PID: 1      TASK: ffff88003bec8000  CPU: 0   COMMAND: ★"systemd"
 #0 [ffff88003bed3d58] __schedule at ffffffff8168b025
 #1 [ffff88003bed3dc0] schedule at ffffffff8168b679
-以下、略-

11.3 表示画面のスクロールオフ・オンの切り替え方法(set scroll off/set scroll on)

デフォルトでは画面のスクロールはオンになっています。

スクロールオフに設定変更する。
crash> set scroll off
scroll: off (/usr/bin/less)

modコマンドを実行する。画面が途中で停止することなく、最後までスクロールした。
crash> mod
-中略-
ffffffffa0616c00  nfs                       256718  (not loaded)  [CONFIG_KALLSYMS]
ffffffffa06bb300  fscache                    64891  (not loaded)  [CONFIG_KALLSYMS]
ffffffffa0731360  nfsv4                     546174  (not loaded)  [CONFIG_KALLSYMS]
crash>

スクロールオンに設定変更する。
crash> set scroll on
scroll: on (/usr/bin/less)

modコマンドを実行する。画面が途中で停止するする。
crash> mod

12 taskコマンドの使い方

12.1 task_struct構造体の値を表示する方法

crashプロセスのtask_struct構造体の値を表示する。
crash> task
PID: 7711   TASK: ffff880032ec3ec0  CPU: 0   COMMAND: "crash"
struct task_struct {
  state = 0,
  stack = 0xffff880031bac000,
  usage = {
    counter = 2
  },
-以下、略-

12.2 task_struct構造体の特定のメンバの値を表示する方法(-R)

---------
1. その1
---------
task_struct 構造体のstateメンバとstackメンバの値を表示する。
struct task_struct {
  state = 0,
  stack = 0xffff880032ce8000,
 :
}

task_struct構造体のstateメンバとstackメンバの値を表示する。
crash> task -R state,stack
PID: 7711   TASK: ffff880032ec3ec0  CPU: 0   COMMAND: "crash"
  state = 0,
  stack = 0xffff880031bac000,

crash>

---------
2. その2
---------
task_struct構造体の中のse構造体のon_rqメンバの値を表示する。"その1"に比べ、1つ深い場所のメンバを表示することになる。
struct task_struct {
  :
  se = {
     :
    on_rq = 1,
     :
    },
  :
}

crash> task -R se.on_rq
PID: 7811   TASK: ffff880032ec3ec0  CPU: 0   COMMAND: "crash"
  se.on_rq = 1,

13 filesコマンドの使い方

13.1 絞りこみの方法(-R)

-----------------------------------
1. TCPソケットだけを表示する(-R TCP)
-----------------------------------
crash> foreach files -R TCP
PID: 965    TASK: ffff880037f7ce70  CPU: 1   COMMAND: "sshd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  3 ffff880031ead900 ffff88003a947800 ffff88003affb230 SOCK TCP
  4 ffff880031ead100 ffff88003a9478c0 ffff88003aff8a30 SOCK TCPv6

PID: 2261   TASK: ffff880037f7de20  CPU: 1   COMMAND: "sshd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  3 ffff88003b329f00 ffff88003aa73d40 ffff88003a9275b0 SOCK TCP

PID: 4038   TASK: ffff88003bb95e20  CPU: 1   COMMAND: "sshd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  3 ffff880031865f00 ffff88003aaf4e40 ffff88003a923eb0 SOCK TCP

-----------------------------------
2. UDPソケットだけを表示する(-R UDP)
-----------------------------------
crash> foreach files -R UDP
PID: 505    TASK: ffff880034c79f60  CPU: 1   COMMAND: "chronyd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  1 ffff8800384fb800 ffff880033339ec0 ffff88003affcdb0 SOCK UDP
  2 ffff8800384f8600 ffff880033339b00 ffff88003affc130 SOCK UDPv6
-以下、略-

--------------------------------------------
3. Netlinkソケットだけを表示する(-R NETLINK)
--------------------------------------------
crash> foreach files -R NETLINK
PID: 1      TASK: ffff88003bec8000  CPU: 0   COMMAND: "systemd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  8 ffff88003b477700 ffff88003aec8780 ffff880034810a30 SOCK NETLINK
 19 ffff88003457d400 ffff88003aedcfc0 ffff88003affb730 SOCK NETLINK
 34 ffff8800345d5000 ffff88003af37380 ffff880034811930 SOCK NETLINK
 38 ffff880035e6ec00 ffff880034bbfc80 ffff88003affd530 SOCK NETLINK

PID: 381    TASK: ffff880034f78fb0  CPU: 0   COMMAND: "systemd-udevd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  4 ffff8800345d5000 ffff88003af37380 ffff880034811930 SOCK NETLINK
-以下、略-

-----------------------------------------------
4. UNIXドメインのソケットだけを表示する(-R UNIX)
-----------------------------------------------
crash> foreach files -R UNIX
PID: 1      TASK: ffff88003bec8000  CPU: 0   COMMAND: "systemd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
 12 ffff88003457c100 ffff88003af023c0 ffff88003affb9b0 SOCK UNIX
 22 ffff880034c83700 ffff88003afbecc0 ffff88003afcee30 SOCK UNIX
 23 ffff880034c80000 ffff88003afbe600 ffff88003afcf0b0 SOCK UNIX
-以下、略-

--------------------------------------------------
5. /var/log配下のファイルだけを表示する(-R /var/log)
--------------------------------------------------
crash> foreach files -R /var/log
PID: 353    TASK: ffff880034cd0000  CPU: 0   COMMAND: "systemd-journal"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
 13 ffff880034454400 ffff88003ad93140 ffff8800331834b8 REG  /var/log/journal/71accf2a38ab4143b4d73a911d172f19/system.journal

PID: 473    TASK: ffff880035c49f60  CPU: 0   COMMAND: "auditd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  4 ffff880033684f00 ffff88003aec8cc0 ffff880033273d38 REG  /var/log/audit/audit.log
-以下、略-

14 fuserコマンドの使い方

ファイルやinode番号から、それらを使っているプロセスを表示します。

/var/log/firewalldを使っているプロセスを調べる。firewalldとgmainの2つであることがわかる(★印)。
crash> foreach files -R /var/log/firewalld
PID: 536    TASK: ffff880031f29f60  CPU: 0   COMMAND: ★"firewalld"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  3 ffff880034011900 ffff88003323dc80 ffff8800333fce38 REG  /var/log/firewalld

PID: 677    TASK: ffff88003a610000  CPU: 1   COMMAND: ★"gmain"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  3 ffff880034011900 ffff88003323dc80 ffff8800333fce38 REG  /var/log/firewalld


fuserコマンドを実行する。/var/log/firewalldを使っているプロセスはfirewalldとgmainであることがわかる(★印)。
crash> fuser /var/log/firewalld
 PID         TASK        COMM             USAGE
  536  ffff880031f29f60  ★"firewalld"      fd
  677  ffff88003a610000  ★"gmain"          fd

fuserコマンドを実行する。
inode番号がffff8800333fce38のファイルを使っているプロセスがfirewalldとgmainであることがわかる(★印)。
crash> fuser ffff8800333fce38
 PID         TASK        COMM             USAGE
  536  ffff880031f29f60  ★"firewalld"      fd
  677  ffff88003a610000  ★"gmain"          fd

15 symコマンドの使い方

15.1 シンボル情報の一覧を表示する方法(-l)

crash> sym -l
0 (D) __per_cpu_start
0 (D) irq_stack_union
4000 (d) exception_stacks
9000 (D) gdt_page
a000 (D) cpu_llc_shared_map
a008 (D) cpu_core_map
a010 (D) cpu_sibling_map
a018 (D) cpu_llc_id
a01c (D) cpu_number
-以下、略-

15.2 モジュールに含まれるシンボル情報だけを表示する方法(-s)

ここでは、nfsv4モジュールに含まれるシンボル情報だけを表示します。

nfsv4モジュールをロードする。
crash> mod -s nfsv4
     MODULE       NAME                        SIZE  OBJECT FILE
ffffffffa0666360  nfsv4                     546174  /lib/modules/3.10.0-514.el7.x86_64/kernel/fs/nfs/nfsv4.ko

nfsv4モジュールに含まれるシンボル情報を表示する。
crash> sym -m nfsv4
ffffffffa05f7000 MODULE START: nfsv4
ffffffffa05f7000 (t) nfs4_proc_rename_setup
ffffffffa05f7050 (t) nfs4_proc_read_setup
ffffffffa05f70a0 (t) nfs4_proc_commit_setup
ffffffffa05f7110 (t) nfs_alloc_no_seqid
ffffffffa05f7120 (T) nfs40_setup_sequence
ffffffffa05f7210 (t) nfs4_open_confirm_prepare
ffffffffa05f7250 (t) nfs4_release_lockowner_prepare
-以下、略-

15.3 特定の文字列を含むシンボル情報だけを表示する方法(-q)

"ip_forward"という文字列を含むシンボル情報だけを表示する。
crash> sym -q ip_forward
ffffffff812b10e0 (t) selinux_ip_forward
ffffffff815b2160 (t) ip_forward_finish
ffffffff815b21e0 (T) ip_forward
ffffffff815b38c0 (T) ip_forward_options
crash>

15.4 シンボル情報の前後のシンボル情報を表示する方法(-p,-n)

ip_forwardの前にあるシンボル情報を表示する(-p)。
crash> sym -p ip_forward
ffffffff815b2160 (t) ip_forward_finish /usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/net/ipv4/ip_forward.c: 60
ffffffff815b21e0 (T) ip_forward /usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/net/ipv4/ip_forward.c: 73

ip_forwardの後にあるシンボル情報を表示する(-n)。
crash> sym -n ip_forward
ffffffff815b21e0 (T) ip_forward /usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/net/ipv4/ip_forward.c: 73
ffffffff815b2650 (T) ip_options_compile /usr/src/debug/kernel-3.10.0-514.el7/linux-3.10.0-514.el7.x86_64/net/ipv4/ip_options.c: 259

16 repeatコマンドの使い方

コマンドを定期的に実行します。
ここでは、chronydがオープンしているファイルを2秒間隔で監視してみます。

crash> set scroll off
scroll: off (/usr/bin/less)

chronydのPIDを求める。PIDは505であることがわかる。
crash> ps chronyd
   PID    PPID  CPU       TASK        ST  %MEM     VSZ    RSS  COMM
  ★505      1   1  ffff880034c79f60  IN   0.2  115848   1896  chronyd

PIDに505を指定して、コンテキストをchronydに変更する。
crash> set 505
    PID: 505

COMMAND: "chronyd"
   TASK: ffff880034c79f60  [THREAD_INFO: ffff880031df0000]
    CPU: 1
  STATE: TASK_INTERRUPTIBLE

2秒間隔で、chronydがオープンしているファイルを監視する。
crash> repeat -2 files
PID: 505    TASK: ffff880034c79f60  CPU: 1   COMMAND: "chronyd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  0 ffff880034457c00 ffff8800332c92c0 ffff88003affe930 SOCK UNIX
  1 ffff8800384fb800 ffff880033339ec0 ffff88003affcdb0 SOCK UDP
  2 ffff8800384f8600 ffff880033339b00 ffff88003affc130 SOCK UDPv6
PID: 505    TASK: ffff880034c79f60  CPU: 1   COMMAND: "chronyd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  0 ffff880034457c00 ffff8800332c92c0 ffff88003affe930 SOCK UNIX
  1 ffff8800384fb800 ffff880033339ec0 ffff88003affcdb0 SOCK UDP
  2 ffff8800384f8600 ffff880033339b00 ffff88003affc130 SOCK UDPv6
PID: 505    TASK: ffff880034c79f60  CPU: 1   COMMAND: "chronyd"
ROOT: /    CWD: /
 FD       FILE            DENTRY           INODE       TYPE PATH
  0 ffff880034457c00 ffff8800332c92c0 ffff88003affe930 SOCK UNIX
  1 ffff8800384fb800 ffff880033339ec0 ffff88003affcdb0 SOCK UDP
  2 ffff8800384f8600 ffff880033339b00 ffff88003affc130 SOCK UDPv6
-以下、略-

17 swapコマンドの使い方

swapデバイスの情報を表示します

crash> swap
SWAP_INFO_STRUCT    TYPE       SIZE       USED     PCT  PRI  FILENAME
ffff880039fab400  PARTITION  1048572k     172k      0%   -1  /dev/sda2

X カーネルモジュールの作成方法

[root@admin test]# pwd
/root/test
[root@admin test]# cat test.c
#include <linux/module.h>

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("hana_shin");
MODULE_DESCRIPTION("for testing module");

static int test_init(void)
{
        printk(KERN_ERR "Insert module\n");
        return 0;
}

static void test_exit(void)
{
        printk(KERN_ERR "Delete module\n");
}

module_init(test_init);
module_exit(test_exit);

Makefielを作成する。
[root@admin test]# vi Makefile
obj-m := test.o

KDIR    := /lib/modules/$(shell uname -r)/build
PWD     := $(shell pwd)
VERBOSE = 0

default:
        $(MAKE) -C $(KDIR) M=$(PWD) KBUILD_VERBOSE=$(VERBOSE) modules

clean:
        rm -f *.o *.ko *.mod.c Module.symvers modules.order

[root@admin test]# ls
Makefile  test.c

makeを実行する。
[root@admin test]# make
make -C /lib/modules/3.10.0-514.el7.x86_64/build M=/root/test KBUILD_VERBOSE=0 modules
make[1]: ディレクトリ `/usr/src/kernels/3.10.0-514.el7.x86_64' に入ります
  CC [M]  /root/test/test.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /root/test/test.mod.o
  LD [M]  /root/test/test.ko
make[1]: ディレクトリ `/usr/src/kernels/3.10.0-514.el7.x86_64' から出ます


モジュールをインストールする。
[root@admin test]# lsmod |grep test
[root@admin test]# insmod test.ko
[root@admin test]# lsmod |grep test
test                   12494  0

モジュールを削除する。
[root@admin test]# rmmod test
[root@admin test]# lsmod |grep test
[root@admin test]#

Y メモ

下記データのentry_sizeとidを表示する

                       ffffffff81aa7f40   neigh_table{}           ffffffff81aa3660  neigh_table{}
  neigh_tables  ----------------------> +----------------+        +------------->+----------------+
                                        |     *next      ---------+              |     *next      |
                                        +----------------+                       +----------------+
                                        |                |                       |                |
                                        |                |                       |                |
                                        +----------------+                       +----------------+
                                        |   entry_size   | -> 392                |   entry_size   | -> 384
                                        +----------------+                       +----------------+
                                        |                |                       |                |
                                        +----------------+                       |----------------+
                                        |      *id       |-> ndisc_cache         |      *id       |-> arp_cache
                                        +----------------+                       |----------------+
                                        |                |                       |                |
                                        +----------------+                       +----------------+


crash> list ffffffff81aa7f40 neigh_table.next -s neigh_table.id,entry_size
ffffffff81aa7f40       <=== 1つ目のneigh_table構造体の先頭アドレス(実体はnd_tbl)
  id = 0xffffffff8194c6c6 "ndisc_cache"
  entry_size = 392
ffffffff81aa3660     <=== 2つ目のneigh_table構造体の先頭アドレス(実体はarp_tbl)
  id = 0xffffffff8194a871 "arp_cache"
  entry_size = 384