Linuxカーネルソースに付属のscripts/の探索

この記事はLinux Advent Calendar 2018の12日目の記事です。

カーネルソースコードに含まれるscripts/を探索してみます。カーネルのビルド中で使うようなものもあるし、それ以外の時に使うものもあります。今回は後者の方を探してみましょう。

diffconfig

ファイルはsrcipts/diffconfigです。カーネルの.configのdiffを見やすくするツールです。

普通にdiffを取るとこんな感じです。

masami@saga:~$ diff -u /boot/config-4.19.9-300.fc29.x86_64 /boot/config-4.19.12-301.fc29.x86_64
--- /boot/config-4.19.9-300.fc29.x86_64 2018-12-14 02:44:50.000000000 +0900
+++ /boot/config-4.19.12-301.fc29.x86_64        2018-12-24 11:20:56.000000000 +0900
@@ -1,10 +1,10 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/x86_64 4.19.9-300.fc29.x86_64 Kernel Configuration
+# Linux/x86_64 4.19.12-301.fc29.x86_64 Kernel Configuration
 #
 
 #
-# Compiler: gcc (GCC) 8.2.1 20181105 (Red Hat 8.2.1-5)
+# Compiler: gcc (GCC) 8.2.1 20181215 (Red Hat 8.2.1-6)
 #
 CONFIG_CC_IS_GCC=y
 CONFIG_GCC_VERSION=80201
@@ -20,7 +20,7 @@
 # CONFIG_COMPILE_TEST is not set
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
-CONFIG_BUILD_SALT="4.19.9-300.fc29.x86_64"
+CONFIG_BUILD_SALT="4.19.12-301.fc29.x86_64"
 CONFIG_HAVE_KERNEL_GZIP=y
 CONFIG_HAVE_KERNEL_BZIP2=y
 CONFIG_HAVE_KERNEL_LZMA=y
@@ -93,6 +93,7 @@
 CONFIG_VIRT_CPU_ACCOUNTING=y
 CONFIG_VIRT_CPU_ACCOUNTING_GEN=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_SCHED_AVG_IRQ=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_TASKSTATS=y
@@ -4655,7 +4656,7 @@
 # CONFIG_DVB_MMAP is not set
 CONFIG_DVB_NET=y
 CONFIG_TTPCI_EEPROM=m
-CONFIG_DVB_MAX_ADAPTERS=8
+CONFIG_DVB_MAX_ADAPTERS=16
 CONFIG_DVB_DYNAMIC_MINORS=y
 # CONFIG_DVB_DEMUX_SECTION_LOSS_LOG is not set
 # CONFIG_DVB_ULE_DEBUG is not set

diifconfigを使うとこのようになります。

masami@saga:~$ ./linux-kernel/scripts/diffconfig /boot/config-4.19.9-300.fc29.x86_64 /boot/config-4.19.12-301.fc29.x86_64
 BUILD_SALT "4.19.9-300.fc29.x86_64" -> "4.19.12-301.fc29.x86_64"
 DVB_MAX_ADAPTERS 8 -> 16
+HAVE_SCHED_AVG_IRQ y

通常のdiffと違って何がどう変わったのかが見やすくなりますね。

objdiff

ファイルはscripts/objdiffです。これはobjectファイル間のdiffを取ります。カーネル以外でも使えます。

例えば、コミット間で以下のようなファイルの変更が有った場合、

masami@saga:~/codes/objdiff-test (test %)$ git diff master a.c
diff --git a/a.c b/a.c
index ab39f2e..a0068b8 100644
--- a/a.c
+++ b/a.c
@@ -7,7 +7,7 @@ struct test {
 int main(int argc, char **argv)
 {
        struct test t = {
-               .s = "hello",
+               .s = "hello\n",
        };
 
        printf("%s\n", t.s);

こんな感じになります。

masami@saga:~/codes/objdiff-test (test %)$ ~/linux-kernel/scripts/objdiff diff
which: no colordiff in (/usr/share/Modules/bin:/usr/lib64/ccache:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/home/masami/bin:/home/masami/.gem/ruby/2.2.0/bin:/home/masami/go/bin:/home/masami/ltp:/home/masami/ltp/bin:/home/masami/.local/bin:/home/masami/bin:/home/masami/bin:/home/masami/.gem/ruby/2.2.0/bin:/home/masami/go/bin:/home/masami/ltp:/home/masami/ltp/bin:/home/masami/.local/bin:/home/masami/bin)
diff -Nurd /home/masami/codes/objdiff-test/.tmp_objdiff/b5b839d/a.dis /home/masami/codes/objdiff-test/.tmp_objdiff/374a3c2/a.dis
--- /home/masami/codes/objdiff-test/.tmp_objdiff/b5b839d/a.dis  2018-12-30 23:36:28.063937470 +0900
+++ /home/masami/codes/objdiff-test/.tmp_objdiff/374a3c2/a.dis  2018-12-30 23:37:13.345071254 +0900
@@ -10,8 +10,8 @@
 :      48 81 ec 10 01 00 00    sub    $0x110,%rsp
 :      89 bd fc fe ff ff       mov    %edi,-0x104(%rbp)
 :      48 89 b5 f0 fe ff ff    mov    %rsi,-0x110(%rbp)
-:      48 b8 68 65 6c 6c 6f    movabs $0x6f6c6c6568,%rax
-:      00 00 00 
+:      48 b8 68 65 6c 6c 6f    movabs $0xa6f6c6c6568,%rax
+:      0a 00 00 
 :      ba 00 00 00 00          mov    $0x0,%edx
 :      48 89 85 00 ff ff ff    mov    %rax,-0x100(%rbp)
 :      48 89 95 08 ff ff ff    mov    %rdx,-0xf8(%rbp)
Binary files /home/masami/codes/objdiff-test/.tmp_objdiff/b5b839d/a.stripped and /home/masami/codes/objdiff-test/.tmp_objdiff/374a3c2/a.stripped differ

bootgraph.pl

ファイルはscripts/bootgraph.plです。 カーネルの起動時にprintk.time=1とinitcall_debugをカーネルコマンドラインオプションに付けて起動する必要があります。dmesgの経過時間のところから何にどれだけ時間を使ったかを見る感じですね。

全体像はこんな感じです。

f:id:masami256:20181230224632p:plain
boot graph

拡大するとこうなってます。

f:id:masami256:20181230225324p:plain
bootgraph2

show_delta

ファイルはscripts/show_deltaです。 これも実行時間の計測ですね。前回のprintkの時刻から今回までの時間を表示してくれます。

('[0.280670 < 0.003444 >] pci 0000:00:06.0: reg 0x20: [io  0xc0a0-0xc0bf]\n',)
('[0.281820 < 0.001150 >] pci 0000:00:06.1: [8086:2935] type 00 class 0x0c0300\n',)
('[0.306576 < 0.000002 >] initcall xen_setup_shutdown_event+0x0/0x30 returned -19 after 0 usecs\n',)
('[0.307587 < 0.000000 >] calling  power_supply_class_init+0x0/0x40 @ 1\n',)
('[0.309641 < 0.000000 >] NetLabel:  domain hash size = 128\n',)
('[0.309642 < 0.000001 >] NetLabel:  protocols = UNLABELED CIPSOv4 CALIPSO\n',)
('[0.359181 < 0.000003 >] initcall proc_version_init+0x0/0x22 returned 0 after 1 usecs\n',)
('[0.359707 < 0.000090 >] pnp 00:02: Plug and Play ACPI device, IDs PNP0f13 (active)\n',)
('[0.365880 < 0.000002 >] calling  thermal_init+0x0/0xe1 @ 1\n',)
('[0.370580 < 0.000040 >] initcall intel_pmc_ipc_init+0x0/0x5f returned 0 after 37 usecs\n',)
('[0.370701 < 0.000006 >] initcall ipv4_offload_init+0x0/0x74 returned 0 after 0 usecs\n',)
('[0.890552 < 0.000001 >] calling  crypto_module_init+0x0/0x11 @ 1\n',)

faddr2line

ファイルはscripts/faddr2lineです。oopsにある関数名+オフセット/関数サイズからそれがどのファイルの何行目かを調べることができます。自作したカーネルモジュールでは使えなかったけど。。

こんな風に使えます。

masami@kerntest:~/a2l$ ~/linux-kernel/scripts/faddr2line ~/linux-kernel/vmlinux do_init_module+0x22/0x210
do_init_module+0x22/0x210:
do_init_module at kernel/module.c:3436

decode_stacktrace.sh

ファイルはscripts/decode_stacktrace.shです。カーネルoopsを読み込んでデコードしてくれます。使い方はlinux-3.16で入ったdecode_stacktrace.shを試してみる - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモを参照してください。

decodecode

ファイルはscripts/decodecodeです。decode_stacktrace.shと似たような感じです。使い方はlinuxカーネルデバッグめも decodecodeでoopsの機械語列を逆アセンブル - φ(・・*)ゞ ウーン カーネルとか弄ったりのメモを参照してください。

ver_linux

ファイルはscripts/ver_linuxです。カーネル、ビルドとか諸々のツール類の情報表示します。

masami@saga:~/linux-kernel (test %)$ ./scripts/ver_linux 
If some fields are empty or look unusual you may have an old version.
Compare to the current minimal requirements in Documentation/Changes.

Linux saga 4.19.12-301.fc29.x86_64 #1 SMP Mon Dec 24 01:58:57 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

GNU Make                4.2.1
Binutils                2.31.1
Util-linux              2.32.1
Mount                   2.32.1
Module-init-tools       25
E2fsprogs               1.44.3
Xfsprogs                4.17.0
Quota-tools             4.04
PPP                     2.4.7
Nfs-utils               2.3.3
Linux C Library         2.28
Dynamic linker (ldd)    2.28
Linux C++ Library       6.0.25
Procps                  3.3.15
Net-tools               2.10
Kbd                     2.0.4
Console-tools           2.0.4
Sh-utils                8.30
Udev                    239
Wireless-tools          29
Modules Loaded          binfmt_misc bridge coretemp crc32c_intel crc32_pclmul crct10dif_pclmul devlink drm drm_kms_helper e1000e ebtable_filter ebtable_nat ebtables fat fuse ghash_clmulni_intel hid_logitech_dj hid_logitech_hidpp i2c_algo_bit i2c_i801 intel_cstate intel_powerclamp intel_rapl intel_rapl_perf intel_uncore intel_wmi_thunderbolt ip6table_filter ip6table_mangle ip6table_nat ip6table_raw ip6_tables ip6table_security ip6t_REJECT ip6t_rpfilter ip_set iptable_mangle iptable_nat iptable_raw iptable_security ipt_MASQUERADE irqbypass iTCO_vendor_support iTCO_wdt kvm kvm_intel libcrc32c llc lpc_ich mei mei_me mxm_wmi nf_conntrack nf_conntrack_broadcast nf_conntrack_netbios_ns nf_defrag_ipv4 nf_defrag_ipv6 nf_nat nf_nat_ipv4 nf_nat_ipv6 nfnetlink nf_reject_ipv6 nouveau pcc_cpufreq snd snd_hda_codec snd_hda_codec_ca0132 snd_hda_codec_hdmi snd_hda_core snd_hda_intel snd_hwdep snd_pcm snd_seq snd_seq_device snd_seq_dummy snd_timer soundcore stp sunrpc tap ttm tun uas usb_storage vfat vhost vhost_net video wmi x86_pkg_temp_thermal xfs xt_CHECKSUM xt_conntrack xt_CT

spelling.txt

ファイルはscripts/spelling.txtです。このファイルは単体で使うと言うか、checkpatch.plでスペルチェックに使っています。ファイルの書式はこんな感じで、左側がよく有る間違いで右側が正解です。

abov||above

まとめ

他にもスクリプトは色々有ります。たとえばscripts/gdbカーネルgdbデバッグする時のスクリプトで.gdbinitで add-auto-load-safe-path /home/masami/codes/slmb/scripts/gdb/vmlinux-gdb.py という感じに読み込ませます。

ということで、なんとなくscripts/を探索してみました( ´ー`)フゥー...

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習

ハッキング・ラボのつくりかた 仮想環境におけるハッカー体験学習