塀の中へ

女房が通っている町の図書館、町中にあって時間帯が悪いと駐車場が一杯で駐車出来ないとか。 また、手狭な為か通い詰めたためか、読みたい本がないとか。そんじゃ、隣町の図書館はどうかと 思って調べてみると、場所は田んぼをつぶして作ったとこみたいで、広々してそう。それに、 よその住人でも本を貸してくれるみたい。太っ腹だなあ。

そんな訳で、私が道案内人になって、隣町の図書館まで足を延ばしてみた。地図で予想した 通り、田植えが終わった田んぼの真ん中にありましたよ。駐車場の広い事。土地がたっぷり あるからですね。図書館にこんな広い駐車場は不釣合いと思ったら、市民ホールが併設 されてました。この市民ホールに、氷川きよしあたりが来ると、駐車場は一杯になるんで しょうな。

で、肝心の図書館の内容だけど、本は勿論の事、ビデオとかも貸し出してました。広々してて 長居しても快適に過ごせそう。折角来たんだから、おいらも本を探そうかなと思って、 昔読んだ、『裁判長!ここは懲役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ってどんな石? やっと腰を上げる気分になった。で、見つけてきたのが下記だ。

manual

ja-page

日本語総合サイト

gnu-as

ARM-model-japan

サンプルのアセンブラコードを吐き出してもらった。

// 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さんが書いているじゃないですか。これはもう、精読するしか。