[Linux] kprobes

kernel や module をデバッグしたいと思ったときにいろんな方法がありますが、真っ先に思いつくのが printk() でメッセージや観測値を表示することだと思います。しかしいちいちビルドし直さなければならないこと、ソースを改変する必要があること、などあまりいい方法ではありません。

Linux にはデバッグのための手段がたくさん用意されています。kernel 内蔵の kdb/kgdb、kernel 動作の追跡を行う ftrace、プロセス動作に手を入れる ptrace、syscall やシグナルを監視する strace、実行状況や実行回数を監視する perf など。これらはプログラム動作を外から監視するものですが、動作そのものに割り込む機能として kprobes があります。

kprobes は特定の場所に breakpoint 命令を設定し、実行時に命令をフックして予め用意した関数を実行することができます。特定の場所の設定と関数は module として用意することで、kernel が起動した後でも module をロードして設定することができます。

kprobes は kernel config の以下を有効にします。使い方を見るために下の2行にてサンプルも有効にしておきます。

CONFIG_KPROBES=y
CONFIG_SAMPLES=y
CONFIG_SAMPLE_KPROBES=m

サンプルは samples/kprobes/kprobe_sample.c にあります。make modules でビルドすると、samples/kprobes/kprobe_sample.ko ができあがるので、以下のように割り込みたい関数ラベルを指定してロードします。

# insmod kprobe_sample.ko symbol=_do_fork
Planted kprobe at 0xffff000080102050

このサンプルでは、struct kprobe の .symbol に関数ラベルの文字列、.pre_handler に割り込む箇所を実行する前に実行したい関数、.post_handler に割り込む箇所を実行した後に実行したい関数をそれぞれ設定しています。この関数に表示したい情報や実行したい操作を呼び出すことで任意の場所に割り込んで操作することができます。割り込む箇所が関数ラベルから離れている場合は .offset に関数ラベルからのオフセットを記載します。

しかしながら、kprobes では任意の箇所に割り込むため、この割り込ませる関数はレジスタレベルで情報を取得することになります。引数の struct pt_regs はアーキテクチャ依存のレジスタセットを表しています。

static int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
#ifdef CONFIG_X86
	pr_info("<%s> pre_handler: p->addr = 0x%p, ip = %lx, flags = 0x%lx\n",
		p->symbol_name, p->addr, regs->ip, regs->flags);
#endif
	...
	/* A dump_stack() here will give a stack backtrace */
	return 0;
}

struct kprobes を設定したら、register_kprobe() で登録、unregister_kprobe() で登録を解除するだけです。module の probe 関数に必要なだけ登録すれば、複数箇所に割り込むことができます。

レジスタレベルで情報を扱うため、c言語レベルのデバッグにはやや不向きなところもありますが、ビルドが不要でどこにでも割り込めるため強力なデバッグツールと言えます。

CONTINUE 展示 in 城陽

城陽市歴史民俗資料館にて、特別展示として表題のイベントが9/2まで実施されていました。
内容としては主に1970~2000年代のゲーム機の展示ですが、いろんな方面からさまざまな所蔵品が集められていて、これだけの数のゲーム機が揃うのはなかなか見られない機会でした。

ただ、コンパクトな展示場に凝縮されて並べている展示方法だったため、一つ一つの機材について解説を見たり思い返したりするというよりも、これだけの数の圧巻さを提示している感じでちょっともったいなかった気もします。

続きを読む

ALL ABOUT マイコン BASIC マガジン II SP in 大阪

今年初めに「ALL ABOUT マイコンBASICマガジンII」が有楽町のよみうりホールで1000人規模で開催され参加したのですが,その半年後にまさかの大阪でのスペシャル版として南港ATCホールにて開催されました.これまでの内容を踏襲しながらも,300人規模とあってより近い感じ,より踏み込んだ形でトークを聞くことができました.

続きを読む

[RPi][Linux] Raspberry Pi で SPI 通信

SPI通信が使える環境がないか探していて、Raspberry Pi なら 40pin ヘッダに出ていて直接使えるのでこれで何かモジュールを繋げば通信できそうということで試してみます。
Raspbian 環境なら手順がいろいろ書かれているので、ここでは敢えて mainline kernel 環境で SPI を有効にしてみることにします。SPI はシリアル通信の一つでI2Cと同様に周辺デバイスのアクセス手段として利用されています。

SPI 通信の動作を確認するため、対向デバイスとして温度センサモジュールを接続して温度を取得してみることにします。温度センサは ADT7310 を使いますが、モジュール化された “MDK001” が便利です。

続きを読む

GPD Pocket

Cloud Funding の “Indiegogo” で募集され 3,182,160 USD も集めた “GPD Pocket” ですが、やはり気になる機種ということで出資してたところ、無事出荷され入手できました。

Ubuntu 版は同価格ながら Windows ライセンスが付属しないのであまり選択する旨味はないのですが、BIOS update と OS の自力入れ替えが必要でハマると文鎮ループのリスクも考えられるので、敢えてこちらを選択したのでした。

続きを読む

[RPi] Pi Zero W

Raspberry Pi 3 を入手して間もないですが、海外通販にて Pi Zero W を入手しました。PIROMONI にて注文掛けていたのですが6日で無事到着しました。Anniversary 期間に間に合ったので £10 で入手でき(通常は £12)、せっかくなので Pibow ケースや Speaker pHAT も追加しました。送料は £5.5 です。

SoC は RPi 無印と同じ BCM2835 で ARM1176 コア、RAMは 512MB の Elpida チップが SoC 上にボンディングされています。外部端子は micro USB(OTG)、mini HDMI、micro SD カード、GPIO ピン、と RPi の互換を保ちながら最小構成でできています。Pi Zero W ではさらに Wi-Fi と Bluetooth が内蔵されています。

続きを読む

[RPi][Linux] boot upstream Linux from U-boot on Raspberry Pi 3

U-boot を Raspberry Pi 3 に導入して、ビルドした mainline Linux kernel を起動してみました。

Raspberry Pi は 既存の bootloader が提供されているので、SDカードの FATパーティションに kernel image を置けば起動するのですが、ビルドした kernel を直接投入するには network 経由で起動したくなるものです。

続きを読む

[QEMU] Hello world on QEMU

QEMU で Hello world を動かす試みは探してみるといくつか実施されています。

いずれも versatilepb モデルで実施されているので、vexpress や virt でもできるかどうか試してみました。toolchain は Linaro toolchain を使いましたが、外部関数を呼び出さないので baremetal toolchain でなくても使えます。

続きを読む