塀の中へ
女房が通っている町の図書館、町中にあって時間帯が悪いと駐車場が一杯で駐車出来ないとか。 また、手狭な為か通い詰めたためか、読みたい本がないとか。そんじゃ、隣町の図書館はどうかと 思って調べてみると、場所は田んぼをつぶして作ったとこみたいで、広々してそう。それに、 よその住人でも本を貸してくれるみたい。太っ腹だなあ。
そんな訳で、私が道案内人になって、隣町の図書館まで足を延ばしてみた。地図で予想した 通り、田植えが終わった田んぼの真ん中にありましたよ。駐車場の広い事。土地がたっぷり あるからですね。図書館にこんな広い駐車場は不釣合いと思ったら、市民ホールが併設 されてました。この市民ホールに、氷川きよしあたりが来ると、駐車場は一杯になるんで しょうな。
で、肝心の図書館の内容だけど、本は勿論の事、ビデオとかも貸し出してました。広々してて 長居しても快適に過ごせそう。折角来たんだから、おいらも本を探そうかなと思って、 昔読んだ、『裁判長!ここは懲役4年でどうすか』シリーズがあるかと思ったら、そういう不埒 なのは置いてなかった。このシリーズ面白いんだよな。
温情裁判官とかが、無銭飲食をした老人に、懲役半年執行猶予無しの判決。寒い間は、ム所の 中に居なさい。あそこなら三食付いてるし。。飢えた人は行きましょう。それから、六本木の あの人のように太った人も行きましょう。確実にダイエット出来ます。テレビで何とかダイエット がかなり女性に受けているみたいだけど、どうすか、ム所ダイエットなんてのは、確実に 痩せられますよ。
おいらは、禁煙実行の為にム所へ。10月からタバコが値上がりするんで切実な問題なんだよな。 でも、怖い所なんだろうか? 安部譲二さん作の『塀の中の懲りない面々』でも、借りてきて 読んでみるかな。
塀の中へ
とまあ、だれかさんに罵倒されそうな事を書いてしまった。今は反省してる。もう少し穏やか に行こうや。折角、2年に一度のウブンツ10.04も入れた事だし。
インターンしよう。jailしよう。インターンはLisp用語ですな。jailの方はFreeBSDで言う 隔離された環境。おっとSolarisにはZONEだかも有ったな。昔からunixには、chrootが 有って、閉じ込めた環境って事だな。
この間のKernel/VMにも登場したので、やってみる。まずは、発表記事通りに、armの環境を 作る。
sudo apt-get install rootstock mkdir arm-ubuntu cd arm-ubuntu sudo rootstock --fqdn arm-lucid --login user --password user : It takes more than 1 Hr ... mkdir root cd root sudo tar xvf ../armel-rootfs-201005091335.tgz sudo chroot . /bin/bash mount proc /proc -t proc echo nameserver 8.8.8.8 > /etc/resolv.conf
ム所を作って、chrootで収監されると。そこはめくるめくARMな世界! 糞Intelな石とは 決別だい。で、ム所に入ってもやる事がないとつまらないので、arm用の開発環境を整える。最後の、 bisonはRubyを作るのに必要なので入れた。
apt-get install binutils gcc gdb bison
待つ事数十分。エラーもなく出来上がったみたいだ。armの石ったら、任天堂のゲーム機 とか、iphoneとかipodやみんながオーナーに成りたがっているipadにも使われたはずだから、これって、ipadとかでもrubyが動くって事の証明になるのかな。
その昔、Windows機にVMWareを入れ、ゲストとしてLinuxを動かし、その上でLinux用のVMWare を入れて(FreeBSDを)動かそうとしたんだけど、そんな無茶は駄目とVMWareに怒られた 記憶がある。でも、VMWare上で動いてるウブンツの上で、毛色の違うqemuはお目こぼしなのね。
root@ubuntu:/home/user/ruby-1.8.7-p249# ./ruby -v ruby 1.8.7 (2010-01-10 patchlevel 249) [armv7l-linux] root@ubuntu:/home/user/ruby-1.8.7-p249# time make test test succeeded real 0m29.598s user 0m27.766s sys 0m1.372s
ここまでは良い。(但し、qemuは遅い。上記のtestを、セレロン500MHzのCPUで実行したら、 7秒とかからなかったよ。でも、面白いので許しちゃうぞ。)本当の楽しみはこれからだ。
root@ubuntu:/home/user/ruby-1.8.7-p249# gdb ruby GNU gdb (GDB) 7.1-ubuntu Copyright (C) 2010 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 "arm-linux-gnueabi". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/user/ruby-1.8.7-p249/ruby...done. (gdb) b main Breakpoint 1 at 0x15ae0: file main.c, line 36. (gdb) run Starting program: /home/user/ruby-1.8.7-p249/ruby qemu: Unsupported syscall: 26
qwmuでは、まだそんなニッチな事は用意してませんってか、残念だなあ。まあ、件の方も straceが動かないって言ってたから、だめかなとは思っていたけど。
root@ubuntu:/home/user/ruby-1.8.7-p249# ps PID TTY TIME CMD 2528 ? 00:00:00 bash 2819 ? 00:00:00 gdb 2822 ? 00:00:00 ruby 2831 ? 00:00:00 ps root@ubuntu:/home/user/ruby-1.8.7-p249# kill -9 2819 [1]+ Killed gdb ruby
結局gdbを殺しちゃったよ。これって、ム所の中の殺プロセス事件だわな。おとがめが 無かっただけ幸い。
おいら armな石のアーキが分かっていないんでどんなregisterを装備してるかすら知らない。 そこで、取り合えず gdbで info reg したみたかったんだ。ヘタレですな。何か手は ないかと考える事3秒。coreを作れば見られるんじゃないかいな。
rubyのソースを取ってこようと思って、w3mを入れたんだけど、使えなかった事を思いだした。 こんな場面で役?にたつとは。。。
user@ubuntu:~$ w3m -v qemu: uncaught target signal 11 (Segmentation fault) - core dumped Segmentation fault
みんな大好きSegふぉーー。 けど、core出来てない。
user@ubuntu:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 20 file size (blocks, -f) unlimited pending signals (-i) 16382 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) unlimited virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
えっと、変更はrootになってから、ulimit -c unlimited かな。
user@ubuntu:~$ gdb w3m qemu_w3m_20100518-162406_2664.core Reading symbols from /usr/bin/w3m...(no debugging symbols found)...done. [New Thread 2664] : Reading symbols from /lib/libz.so.1...(no debugging symbols found)...done. Loaded symbols for /lib/libz.so.1 Core was generated by `/usr/bin/w3m -v'. Program terminated with signal 11, Segmentation fault. #0 0x42124c66 in GC_mark_from () from /usr/lib/libgc.so.1 (gdb) bt #0 0x42124c66 in GC_mark_from () from /usr/lib/libgc.so.1 #1 0x42124e22 in GC_mark_from () from /usr/lib/libgc.so.1 Backtrace stopped: previous frame identical to this frame (corrupt stack?) (gdb) info reg r0 0x694 1684 r1 0x40080158 1074266456 r2 0x418 1048 r3 0x40080154 1074266452 r4 0x142ffc 1323004 r5 0x2154a08 34949640 r6 0x7fe62784 2145789828 r7 0x4007ff60 1074265952 r8 0x4007fd5c 1074265436 r9 0x7fe62800 2145789952 r10 0x139128 1282344 r11 0x1390a8 1282216 r12 0x4007f56c 1074263404 sp 0x4007f530 0x4007f530 lr 0x42124e23 1108495907 pc 0x42124c66 0x42124c66 <GC_mark_from+246> fps 0x0 0 cpsr 0x20000030 536870960
Ir って、何するものぞ? やっぱり仕様書見たいな。それはそうと、内心予想してた所 で落ちているね。みんな大好きGC! そして事情は首藤さんのそれと同じっぽいな。 stack frameが壊れているよ。
kernel/VM探検隊のまとめ
まとめ記事 があったので、もういちど見てみる。首藤さんの 「いまどきのBinary Hacks」 は、必見だ。もう一度件の本を読んでみようかな。何を隠そう、この本Linux主体に 書かれていたんで、あまり真面目に読んでいなかったんだ。でも、いろいろとお宝が 眠っていそうなので、もったいないお化けが出てくるよ。
arm
armってどんな石? やっと腰を上げる気分になった。で、見つけてきたのが下記だ。
サンプルのアセンブラコードを吐き出してもらった。
// arm sample hoge(int a, int b){ return a * b; } main (){ int i; i = hoge(511, 1023); }
.syntax unified .arch armv7-a .eabi_attribute 27, 3 .fpu vfpv3-d16 .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 2 .eabi_attribute 30, 6 .eabi_attribute 18, 4 .thumb .file "test.c" .text .align 2 .global hoge .thumb .thumb_func .type hoge, %function hoge: @ args = 0, pretend = 0, frame = 8 @ frame_needed = 1, uses_anonymous_args = 0 @ link register save eliminated. push {r7} sub sp, sp, #12 add r7, sp, #0 str r0, [r7, #4] str r1, [r7, #0] ldr r3, [r7, #4] ldr r2, [r7, #0] mul r3, r2, r3 mov r0, r3 add r7, r7, #12 mov sp, r7 pop {r7} bx lr .size hoge, .-hoge .align 2 .global main .thumb .thumb_func .type main, %function main: @ args = 0, pretend = 0, frame = 8 @ frame_needed = 1, uses_anonymous_args = 0 push {r7, lr} sub sp, sp, #8 add r7, sp, #0 movw r0, #511 movw r1, #1023 bl hoge mov r3, r0 str r3, [r7, #4] add r7, r7, #8 mov sp, r7 pop {r7, pc} .size main, .-main .ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3" .section .note.GNU-stack,"",%progbits
後は、上の資料に首ったけになってみるかな。それとも、 binutils-doc を入れて、info As するか。 Machine Dependencies の章に、呆れる ぐらいな石が載ってるけど、迷わず ARM-Dependent をミロ。
gdb
armな環境でgdbが動かないのは残念。何か資料は無いものかと、発表者の方のリンクを 辿ったら、 QEMUにデバッガをつなぐ なんていうのに 出会った。(デバッガーで)有名な会社の方なんですね。
無駄な抵抗と知りつつ
user@ubuntu:~$ gdbserver localhost:12345 ./a.out qemu: Unsupported syscall: 26
やっぱりだめだ。土台がなっとらんわい。でも、折角なんで、ちゃんとした(i386)環境で gdbserverを試してみるか。(gdbserverはapt-getで入れてやる。何せ、ニッチだからなあ)
片方の端末で、gdbserver(と言う通信設備)経由で、ターゲットを起動する。 すると、ターゲットは多分 break mainして、起動された状態になるんだろうな。 相手側(端末B)からの接続を待ってて、後は相手側に操作を委ねるのか。
---- Terminal A --------------------------------------- sakae@ubuntu:~$ gdbserver :12345 ./a.out Process ./a.out created; pid = 20922 Listening on port 12345 Remote debugging from host 127.0.0.1 child exited with status 1 GDBserver exiting
端末B側は、gdbserverに接続し、contで相手側を実際的に動かす。後は普通にdebugすれば いいのか。watchポイントで監視出来るのは、グローバル変数のみなのね。(まあ、当たり前 っちゃあ、当たり前だけど、最初そんな事知らないから、変数iをmainの中で指定してて、 しばし悩んだのは、秘密だ)
---- Terminal B ---------------------------------------- sakae@ubuntu:~$ gdb : (gdb) target remote :12345 Remote debugging using :12345 Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/ld-linux.so.2 0x003c9850 in ?? () from /lib/ld-linux.so.2 (gdb) b hoge Breakpoint 1 at 0x80483b7: file test.c, line 4. (gdb) cont Continuing. Breakpoint 1, hoge (a=511, b=1023) at test.c:4 4 return a * b; (gdb) watch i Hardware watchpoint 1: i (gdb) cont Continuing. Hardware watchpoint 2: i Old value = 0 New value = 522753 main () at test.c:9 9 } (gdb) c Continuing. Program exited with code 01. (gdb) q
上記で注目すべきは、さりげなく出てくる Hardware watchpoint って案内。armな石には こういう支援無いのかな? 石のマニュアルを舐めるように見たら、見つかったりして。
最後に、arm上では、Unsupported syscall: 26 と言われたやつが、どんなものかを 見ておく。これって、転んでもただでは起きない、けちけち精神の発露?
NAME ptrace - process trace SYNOPSIS #include <sys/ptrace.h> long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data); DESCRIPTION The ptrace() system call provides a means by which a parent process may observe and control the execution of another process, and examine and change its core image and registers. It is primarily used to implement breakpoint debugging and system call tracing.
また、FreeBSDにもptraceってやつが有るんだろうなあと思って調べてみたら、有ったよ。 由緒正しい出のようだ。
PTRACE(2) FreeBSD システムコールマニュアル PTRACE(2) 名称 ptrace - プロセスのトレースとデバッグ ライブラリ 標準 C ライブラリ (libc, -lc) 書式 #include <sys/types.h> #include <sys/ptrace.h> int ptrace(int request, pid_t pid, caddr_t addr, int data); 解説 ptrace() システムコールはトレースとデバッグの機能を提供します。これによっ て 1 つのプロセス (トレースするプロセス) が他のプロセス (トレースされるプ ロセス) を制御できます。トレースするプロセスは、最初にトレースされるプロ セスにアタッチしなければなりません。それから、そのプロセスの実行を制御す るために ptrace() システムコールを発行します。プロセスのメモリおよびレジ スタ状態へのアクセスも同様です。トレースするセッションの期間中、トレース されるプロセスはその親プロセス ID が (その結果の動作として) トレースする プロセスに ``親を変更'' されます。トレースするプロセスが同時に 1 つ以上の プロセスをアタッチすることは、許可されます。トレースするプロセスがその作 業を完了したときには、そのトレースされるプロセスをデタッチしなければなり ません。トレースするプロセスが最初にアタッチされている全てのプロセスをデ タッチせずに exit した場合には、それらのプロセスは kill されます。 : 歴史 ptrace() 関数は Version 7 AT&T UNIX で登場しました。
ちょいとmanしたぐらいではピンとこないので、先のbinary hack本を開いてみた。そしたら、 hack#86に詳しい説明が出ていた。やったね。そしてこの本の ”本書によせて”になんと、 shiroさんが書いているじゃないですか。これはもう、精読するしか。