しばらく前にRaspbian上でAudioインタフェース用のコマンド群がトラブったときに活躍したのが、システムコールをトレースしてくれる
strace
コマンドでした。お陰で何故止まってしまったように見えるのか理由が分かり、解決につながりました。ありがたい限り。この strace に似たコマンドで、ライブラリ呼び出しをトレースしてくれる
ltrace
というコマンドもあります。これをRaspbianの上で不用意にインストールして動かそうとしたところ、ハングしました。なぜ?
※「トホホな疑問」投稿順Indexはこちら
straceも、ltraceも困ったときに役に立つお道具じゃないかと思います。特にデバッグ用の情報など埋め込んでいない、よく分からないプログラムでも内部の動作をさらけ出してくれる優れものです。その上、私のようなLinuxにあまり慣れない人でも直ぐに使える簡単さ。どちらのコマンドも調べたいプログラムを引数にしてとりあえずRETURN叩けばずらずらと情報を吐き出してくれます。本道のLinuxマシンは勿論、下位レイヤは実はWindowsである WSL 環境(私がテストしたのはWSL上のUbuntuですが)でさえ、「普通に」straceとltraceを使うことができます。ですから、Raspbianの上で ltrace が動かないとかまったく予想しておりませんでした。
勿論、インストールは普通にできます。
$ sudo apt-get install ltrace
などすればOK。最初はRaspberry Pi 3 model B+ 上のRaspbian (バージョン 4.19.57-v7+)にインストールしてみました。
$ ltrace 調べたいコマンド
などとすると、エラーを吐いてハングしてしまいます。いくら待っても音沙汰ないのでプロセスをキル。これは、Pi 3だけの問題? Pi ZeroはCPUは違うけれどOSバージョンは同じだったので、見込み薄。そこで、大分古いバージョンのRaspbianで動いている Raspberry Pi 1 model B+(CPUはPi Zeroと同じ)でも確認してみました。
$ ltrace ls __libc_start_main(0x11e90, 1, 0xbed67d84, 0x22524PTRACE_SINGLESTEP: Input/output error 1539 couldn't continue when handling __libc_start_main (0x11c10) at 0x11c10
やっぱり駄目でした。そこで上のエラーメッセージ PTRACE_SINGLESTEP: Input/output error を手掛かりに調べていくと、最後に行きついたのはここです。
ARM: 6668/1: ptrace: remove single-step emulation code
ARM用のLinuxカーネルから、ptraceのsingle-step emulationというコードをとりはずしちゃったもんね、という感じでしょうか。3つ理由が挙げてあり、そのうちの一つは、昨日「ぐだぐだ」書いていたThumbの件でした。カーネルサポートしていないんだ、こりゃ駄目だ。ltraceそのものが何か別な方法で動くようにならない限り望みは薄い? 諦めが早いので Raspbian上での ltrace 断念です。
しかしね、Raspbianに似ているけれど違うものも調べてみました。
Jetson nano の Ubuntu
Raspbianに似ているといいながら、こちらはArmでも64ビットです。その上、NvidiaはGPUのフロントエンドのCPUとしてArmを使っているためか「無駄なThumb」などサポートしておらず。もしかすると。。。
$ ltrace ls __libc_start_main(0x5576d1a240, 1, 0x7fdd88d098, 0x5576d2d990 <unfinished ...> strrchr("ls", '/') = nil setlocale(LC_ALL, "") = "LC_CTYPE=en_US.UTF-8;LC_NUMERIC="... bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale" textdomain("coreutils") = "coreutils" __cxa_atexit(0x5576d22ef0, 0, 0x5576d44008, 0) = 0 isatty(1) = 1 getenv("QUOTING_STYLE") = nil getenv("COLUMNS") = nil ioctl(1, 21523, 0x7fdd88cf40) = 0 getenv("TABSIZE") = nilxxxxx ~途中略~ fflush(0x7f87222480) = 0 fclose(0x7f87222480) = 0 __cxa_finalize(0x5576d44008, 0x5576d1bca0, 0x5576d439c8, 0) = 0x7f87225f20 +++ exited (status 0) +++
「同じ」Armコア上で動作しているLinuxといいながら、こちらはltraceが普通に動作するのでありました。なかなかね、一筋縄ではいきませぬ。