debian(2)

ダイアモンドは永遠の輝き

これ有名なコマーシャルですね。世界で一番成功したCMとか。仕掛け人はダイアモンド販売の 元締めデビアス社が雇ったCM会社。

ダイアモンド需要を創出する為、婚約指輪にどうぞと言う訳。とは言っても、4Cによって値段は さまざま。どれぐらいのものを贈ったら良いのか庶民には見当もつかず。 抜け目無い会社は、お節介にもその目安を広告したとか。

曰く、欧州では旦那の収入の1月分。アメリカでは2月分。日本では3月分とか。おいらも 昔々、3月分のやつを贈ったような。。

日本は舐められますなあ。搾取されてますよ。そう言えば、いろんな人と浮名を流してた、某モデルさん、 貰った婚約指輪の石が小さいと文句を言ったとか、週刊誌で話題になってましたなあ。この人も デビアスの回し者?

このデビアス、カルテルを組んで価格統制をしてる事で有名。原石の供給量をコントロールする 事により価格維持に努めているとか。血ぬられた宝石とも戦争ダイヤモンドとも言われる、石が 流通したりして、ダークな世界だ事。

先の婚約指輪戦略も冴えてますよ。だって、こういう石は飽きたからと言って、中古市場に 出てくる事は余りないでしょ。世に女性がいる限り、需要は永遠に続きますからね。

そうそう、昔懇意にしてた宝石屋さんが居るんだけど、その人が言うには、資産として持つには ダイヤモンドが一番だそうです。金とかだど、有事の際に持ち出そうとしても、重くて始末悪い そうです。その点、ダイアモンドだと、どこでもすっと隠せるから好いとか。

いずれも、おいらには余り関係なさそうだなあ。せいぜいrubyで戯れるぐらいが関の山ですよ。 ダイアモンドって名前のプログラミング言語は、未だ聞いた事ないからね。世のハッカーも ダイアモンドには恐れを為して命名を躊躇っているんでしょうか?

以上、ダイアモンドなんて本を読んだ時の記録です。

ppc de debian

前週は、ArchLinuxの上で、qemu-* を動かして(* は、mipsとarmelでした)、debianを楽しんだ。 debianも6になってから、FreeBSDのカーネルを採用したものが正式サポートされるようになった みたい。 それって、既にFreeBSDじゃありませんかねって言う突っ込みは、微妙だな。*BSDでは、カーネルと ユーザーランドも合せて、*BSDって名乗ってるからねぇ。それじゃ、debianとの違いは無いじゃんと 一瞬考えたけど、大きく違う事が有ったよ。ライセンス形態が決定的に違うね。 これ以上書くと、ボロが出そうなので、もうやめよう。

今回は、FreeBSDを母艦にして、その上でqemuを動かそうって言う作戦。えせ、debian化です。 石は、まだ試してないものとして、sh4とppcが候補なんだけど、sh4は旧世代しか無かったので 候補から外します。こういう、いいかげんな選択方法でいいのだろうか?

qemuは、パッケージにあるんで、さくっと入れました。 起動スクリプトは、何のひねりもなく

[sakae@secd ~/ppc]$ cat boot
#!/bin/sh

qemu-system-ppc -hda powerpc.qcow2  -nographic -redir tcp:2222::22

armelとかの時と違って、-kernelとか -initrdとか余計なオプションが必要無いのね。この違いは 何処から来てるの? qemuの完成度? それとも、linux側の作りの違い? 偉い人、教えてちょ。

そんじゃ、例によってdmesgから面白そうな所を拾ってみます。

[    0.000000] Using PowerMac machine description
[    0.000000] Total memory = 128MB; using 256kB for hash table (at c7fc0000)
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 2.6.32-5-powerpc (Debian 2.6.32-45) (dannf@debian.org) (gcc version 4.3.5 (Debian 4.3.5-4) ) #1 Sun May 6 03:39:01 UTC 2012
[    0.000000] Found initrd at 0xc0b20000:0xc14c7980
[    0.000000] Found a Heathrow mac-io controller, rev: 0, mapped at 0xff780000
[    0.000000] PowerMac motherboard: PowerMac G3 (Silk)
[    0.000000] boot stdout isn't a display !

Oh! パワーマックの真似をしてるよ。ひょっとして、toolboxのROMも内蔵してるんかな?偉いぞ、QEMU。 ROMのおかげかどうか分からんけど、initrdも自力で見つけてるし。。。

[    0.000000] nvram: OF partition at 0x1800
[    0.000000] nvram: XP partition at 0x1300
[    0.000000] nvram: NR partition at 0x1400

やっぱりROM入ってるんか。

[    0.000000] Memory: 113916k/131072k available (4936k kernel code, 17016k reserved, 280k data, 479k bss, 232k init)
[    0.000000] Kernel virtual memory layout:
[    0.000000]   * 0xfffef000..0xfffff000  : fixmap
[    0.000000]   * 0xff800000..0xffc00000  : highmem PTEs
[    0.000000]   * 0xfef5a000..0xff800000  : early ioremap
[    0.000000]   * 0xc9000000..0xfef5a000  : vmalloc & ioremap

ppcって、メモリーバスとI/Oバスがセパレートになってるの?

[    7.528830] ne2k-pci.c:v1.03 9/22/2003 D. Becker/P. Gortmaker
[    7.609855] eth0: RealTek RTL-8029 found at 0x400, IRQ 23, 52:54:00:12:34:56.

蟹さんチップが載ってるとは、MACらしくないな。これって、偏見でしょうか?

[    3.236366] ide-pmac: Found Apple Heathrow ATA controller (macio), bus ID 0,irq 19
[    3.238597] Probing IDE interface ide0...
[    3.547496] hda: QEMU HARDDISK, ATA DISK drive
[    4.267762] hda: host max PIO4 wanted PIO255(auto-tune) selected PIO2
[    4.271246] hda: MWDMA2 mode selected
[    4.273529] ide0 at 0xc9012000-0xc9012070,0xc9012160 on irq 19
[    4.278939] ide-gd driver 1.18
[    4.281080] hda: max request size: 512KiB
[    4.282031] hda: 33554432 sectors (17179 MB) w/256KiB Cache, CHS=16383/255/63
[    4.309255] hda: cache flushes supported
[    4.315016]  hda: [mac] hda1 hda2 hda3 hda4 hda5

ATA controllerまで、しっかりアップル印だよ。中国のそっくりさんでも、ここまで真似する 事は無いかな。偉いよ、QEMU。ちゃんと、アイドルループで、母艦のロードアベレージが 下がるし(HALTを真面目に実装してる)、見えない所も手抜きしてない。

それじゃ、/bootの下をちょっと覗いてみます。

sakae@debian-powerpc:~$ ls -l /boot
total 18137
-rw-r--r-- 1 root root    93211 May  6 06:49 config-2.6.32-5-powerpc
drwxr-xr-x 2 root root     1024 Mar  1  2011 etc
-rw-r--r-- 1 root root     1024 Jul  2  2010 first.b
lrwxrwxrwx 1 root root       27 Mar  1  2011 initrd.img -> initrd.img-2.6.32-5-powerpc
-rw-r--r-- 1 root root 10123648 Aug 10 00:27 initrd.img-2.6.32-5-powerpc
drwxr-xr-x 2 root root    12288 Mar  1  2011 lost+found
-rw-r--r-- 1 root root     1024 Mar  1  2011 old.b
-rw-r--r-- 1 root root    87256 Jul  2  2010 second.b
-rw------- 1 root root      344 Mar  1  2011 second.map.0
-rw-r--r-- 1 root root  1191744 May  6 06:49 System.map-2.6.32-5-powerpc
lrwxrwxrwx 1 root root       24 Mar  1  2011 vmlinux -> vmlinux-2.6.32-5-powerpc
-rw-r--r-- 1 root root  6979055 May  6 06:48 vmlinux-2.6.32-5-powerpc

first.bとかsecond.bってのは、2段式でカーネルをロードする仕組みなんだな。etcの中に

sakae@debian-powerpc:~$ cat /boot/etc/quik.conf
## quik.conf generated by debian-installer

init-message="Debian GNU/Linux PowerPC"
default=Linux
timeout=100
root=/dev/hda3
partition=2
image=/vmlinux
        label=Linux
        read-only
        initrd=/initrd.img

どこかで見たようなデータが入っていたぞ。/bootの中にlost+foundが有るって事は、/bootが 独立したパーテションになってるんか。調べてみるか。

sakae@debian-powerpc:~$ mount
/dev/hda3 on / type ext3 (rw,errors=remount-ro)
 :
/dev/hda2 on /boot type ext2 (rw)

そうすると、hda1は、swap担当者だな。(こう書くと、銀行や証券会社の担当者みたいだな。) ざっと見るのはこれぐらいにしとくか。

speed比べ

として、カーネルでもコンパイルしてもいいんだけど、それは電力の無駄だと思うので、 度々登場してるSchemeをコンパイルしてみます。

sakae@debian-powerpc:~/Simple$ time make
  :
real    0m52.792s
user    0m40.772s
sys     0m9.832s

QEMUの中では、一番早いじゃん。それじゃ、母艦のFreeBSDでもやってみる。

[sakae@secd ~/Simple]$ time make
  :
real    0m2.473s
user    0m0.193s
sys     0m1.100s

果たして、母艦とMACの中で時間の進み方は同じんだろうか? 数時間動かしてみて、dateの 出力が現世界と一致してたから、相対性理論は99.99%の確率で成り立つ事が実証されました。 (CERNの人が神の粒子の発見を発表した時は、かっこ良かったな。)

爆弾炸裂

折角コンパイルしたんで、走らせてみます。

sakae@debian-powerpc:~/Simple$ ./simp
educational Scheme compiler Simple Ver0.31.3 (written by Kenichi.Sasagawa)
Exception: incorrect argument count in call ((null))
Exception: incorrect argument count in call (map)
*** glibc detected *** ./simp: double free or corruption (!prev): 0x10af4b38 ***
======= Backtrace: =========
/lib/libc.so.6(+0x82de4)[0xfe22de4]
/lib/libc.so.6(cfree+0x8c)[0xfe2845c]
/lib/libc.so.6(fclose+0x18c)[0xfe0daec]
./simp[0x1000159c]
./simp[0x100046c8]
./simp[0x10002944]
./simp[0x10002fb4]
./simp[0x10001e90]
./simp[0x10002050]
./simp[0x10001610]
./simp[0x1001bdd8]
./simp[0x10000d4c]
/lib/libc.so.6(+0x1f69c)[0xfdbf69c]
/lib/libc.so.6(+0x1f860)[0xfdbf860]
======= Memory map: ========
00100000-00103000 r-xp 00000000 00:00 0          [vdso]
0fda0000-0ff0a000 r-xp 00000000 03:03 559584     /lib/libc-2.11.3.so
0ff0a000-0ff1a000 ---p 0016a000 03:03 559584     /lib/libc-2.11.3.so
0ff1a000-0ff1e000 r--p 0016a000 03:03 559584     /lib/libc-2.11.3.so
0ff1e000-0ff1f000 rw-p 0016e000 03:03 559584     /lib/libc-2.11.3.so
0ff1f000-0ff22000 rw-p 00000000 00:00 0
0ff32000-0ffdc000 r-xp 00000000 03:03 559588     /lib/libm-2.11.3.so
0ffdc000-0ffec000 ---p 000aa000 03:03 559588     /lib/libm-2.11.3.so
0ffec000-0ffef000 r--p 000aa000 03:03 559588     /lib/libm-2.11.3.so
0ffef000-0fff0000 rw-p 000ad000 03:03 559588     /lib/libm-2.11.3.so
10000000-10029000 r-xp 00000000 03:03 870088     /home/sakae/Simple/simp
10038000-1003a000 rw-p 00028000 03:03 870088     /home/sakae/Simple/simp
1003a000-10654000 rwxp 00000000 00:00 0
10aed000-10b0e000 rwxp 00000000 00:00 0          [heap]
48000000-48020000 r-xp 00000000 03:03 559595     /lib/ld-2.11.3.so
48020000-48021000 rw-p 00000000 00:00 0
48021000-48022000 r--p 00021000 03:03 559595     /lib/ld-2.11.3.so
48022000-48023000 rw-p 00022000 03:03 559595     /lib/ld-2.11.3.so
48023000-48024000 rw-p 00000000 00:00 0
48027000-48029000 rw-p 00000000 00:00 0
48100000-48121000 rw-p 00000000 00:00 0
48121000-48200000 ---p 00000000 00:00 0
bfb61000-bfb76000 rw-p 00000000 00:00 0          [stack]
Aborted

おお、ブルースクリーンだ。いや、MACだから爆弾マークかな。爆弾マークはFinderが出して いたけど、これは誰が出しているの? 親切なQEMU/MAC担当者が出してくれてるかと思って 調べてみたけど、該当コードは見つからなかったよ。そうすると、libcの中にでも、爆弾表示機が 入っているのかな? 探してみる。

sakae@debian-powerpc:~/Simple$ ldd simp
        linux-vdso32.so.1 =>  (0x00100000)
        libm.so.6 => /lib/libm.so.6 (0x0ff32000)
        libc.so.6 => /lib/libc.so.6 (0x0fda0000)
        /lib/ld.so.1 (0x20079000)
sakae@debian-powerpc:~/Simple$ strings /lib/libc.so.6 | grep Backtrace
======= Backtrace: =========

これって、ppcだけの親切設計なの?

それじゃ、得意のgdbさんに登場願おう。

(gdb) bt
#0  0x0fdd795c in raise () from /lib/libc.so.6
#1  0x0fddd014 in abort () from /lib/libc.so.6
#2  0x0fe155ec in ?? () from /lib/libc.so.6
#3  0x0fe22de4 in ?? () from /lib/libc.so.6
#4  0x0fe2845c in free () from /lib/libc.so.6
#5  0x0fe0daec in fclose () from /lib/libc.so.6
#6  0x1000159c in exception (fn=0x1065c008 "map", code=22, arg=2883)
    at main.c:220
#7  0x100046c8 in vm () at main.c:894
#8  0x10002944 in comp (expr=2848, env=2858, code=2859, tail=1, lmac=0)
    at main.c:440
#9  0x10002fb4 in comp_body (body=2849, env=2858, code=2859, lmac=0)
    at main.c:510
#10 0x10001e90 in comp (expr=2851, env=0, code=2857, tail=2, lmac=0)
    at main.c:325
#11 0x10002050 in comp (expr=2854, env=0, code=2855, tail=2, lmac=0)
    at main.c:343
#12 0x10001610 in compile (expr=2854) at main.c:231
#13 0x1001bdd8 in f_load (lvar=677) at function.c:3188
#14 0x10000d4c in main () at main.c:38

これ、例によってアプリの問題っぽい。無謀にも最下層を覗いてみる。

    /*通常の場合はトップレベルへ復帰。 */
    else
        longjmp(toplevel, 1);
}
1000159c:       39 7f 00 20     addi    r11,r31,32
100015a0:       80 0b 00 04     lwz     r0,4(r11)
100015a4:       7c 08 03 a6     mtlr    r0
100015a8:       83 eb ff fc     lwz     r31,-4(r11)
100015ac:       7d 61 5b 78     mr      r1,r11
100015b0:       4e 80 00 20     blr
    if (loadflag == 1)
        fclose(input_port);

    /*通常の場合はトップレベルへ復帰。 */
    else
        longjmp(toplevel, 1);
100015b4:       3c 00 10 65     lis     r0,4197
100015b8:       30 60 3b c0     addic   r3,r0,15296
100015bc:       38 80 00 01     li      r4,1
100015c0:       48 02 57 f1     bl      10026db0 <longjmp@plt>

100015c4 <compile>:
}

Uum...

backtrace and pmap

上の悩ましいのは置いておいて、折角のbacktraceなんて文字列がlibcに埋め込まれているんだから 、それを使う手段が有るはず。こんな時には、あれだな。(老人性、物忘れ症候群発症)

sakae@debian-powerpc:~$ man -k backtrace
backtrace (3)        - support for application self-debugging
backtrace_symbols (3) - support for application self-debugging
backtrace_symbols_fd (3) - support for application self-debugging

美味しそうなのが並んでますなあ。取りあえず、そのものズバリを見て行くと

DESCRIPTION
       backtrace() returns a backtrace for the calling program, in  the  array
       pointed  to  by  buffer.  A backtrace is the series of currently active
       function calls for the program.  Each item in the array pointed  to  by
       buffer  is  of  type  void *, and is the return address from the corre‐
       sponding stack frame.  The size argument specifies the  maximum  number
       of  addresses that can be stored in buffer.  If the backtrace is larger
       than size, then the addresses corresponding to  the  size  most  recent
       function  calls  are  returned;  to obtain the complete backtrace, make
       sure that buffer and size are large enough.

英語に負けないで、下の方まで丹念に見て行くと、C語の例が出てたよ。これなら英語よりは すらすら読めるぞ。

EXAMPLE
       The program  below  demonstrates  the  use  of  backtrace()  and  back‐
       trace_symbols().   The  following shell session shows what we might see
       when running the program:

           $ cc -rdynamic prog.c -o prog
           $ ./prog 3
           backtrace() returned 8 addresses
           ./prog(myfunc3+0x5c) [0x80487f0]
           ./prog [0x8048871]
           ./prog(myfunc+0x21) [0x8048894]
           ./prog(myfunc+0x1a) [0x804888d]
           ./prog(myfunc+0x1a) [0x804888d]
           ./prog(main+0x65) [0x80488fb]
           /lib/libc.so.6(__libc_start_main+0xdc) [0xb7e38f9c]
           ./prog [0x8048711]

   Program source

       #include <execinfo.h>
       #include <stdio.h>
       #include <stdlib.h>
       #include <unistd.h>
         :

manは何にも勝る、電子書籍だなあ。ipadが無くたってキンドル持ってなくたって、読めるん だから利用しない手は無いよ。自炊しなくたっていいしね。

そんじゃ、調子に乗って、もう一つの美味しそうな機能、メモリーマップ表示はどうやってるんだろう? 探してみる。キーワードは、memory ぐらいで探せばいいかな。

NAME
       pmap - report memory map of a process


SYNOPSIS
       pmap [-x|-d] [-q] pid  ...
       pmap -V

WindowsのHELPを使いこなせないおいらでも、unixのHELPは大丈夫。早速、お試しをば。

sakae@debian-powerpc:~$ ps
  PID TTY          TIME CMD
  739 ttyPZ0   00:00:20 bash
  965 ttyPZ0   00:00:00 ps
sakae@debian-powerpc:~$ pmap 739
739:   -bash
00100000     12K r-x--    [ anon ]
0fd2b000     48K r-x--  /lib/libnss_files-2.11.3.so
0fd37000     60K -----  /lib/libnss_files-2.11.3.so
  :
48029000   2048K r----  /usr/lib/locale/locale-archive
48229000   1140K r----  /usr/lib/locale/locale-archive
48346000     28K r--s-  /usr/lib/gconv/gconv-modules.cache
bfc68000     84K rw---    [ stack ]
 total    10976K

上で出てきたのとちょっと違うけど、言わんとしてる事は分かるんで、これで好しとするか。 これで不満足だったら、-dを付けてみるといい鴨。

爆弾はどう設計されてた

何だか、CIAとかFBIが喜びそうなタイトルだけど、決して怪しい話ではありませんよ。 上の爆弾はどうやって破裂させたんだろう?

何らかの理由によりsimpが不都合をきたし、自助のエラー発見機能によりExceptionが発令 したんだな。Exceptionの最後で、ロード中ならファイルをクローズして抜ける。 2回目のExceptionでも、ファイルをクローズしようとして、ここで信管に火がついたとな。

となると、爆弾がどう設計されているか想像出来るよね。gdbで追跡出来ないかしら? 作戦は、まず上記のタイトル文字列の格納場所を探し出し、次はそれを呼び出している場所を 見つけ出す。そうすれば、ひょっとして、逆アセンブルのアドレスに付いているラベルから エラーを出してる所が分かるんじゃなかろうか?

gdbでメモリー内の検索ってどうやるか調べてみた。10.21 メモリの検索 うまい具合に文字列も検索出来るみたいだ。

(gdb) find 0x0ff1a000, 0x0ff1e000, "====="
Pattern not found.

探してる場所は間違い無いと思うんだけどなあ。こんな事をやるとちゃんと見つけてくれるから。

(gdb) find 0x1003a000, 0x10675000, "room"
0x10658ae8
1 pattern found.

もう、この方針は却下するかと思って、いろいろ漁っていたら、あの人が gdbでメモリーダンプして... なんてTipsを上げていた。面白いね。

ソースを見てみる

奥の手を登場させましょ。ソース嫁ですな。libcはGNU製の glibcへのリンクになってるんで、適当な所からglibを落としてくる。適当に中を探し回って みると、

[sakae@archbang linux]$ pwd
/home/sakae/glibc-2.16.0/sysdeps/unix/sysv/linux
[sakae@archbang linux]$ vim libc_fatal.c
  :
/* Abort with an error message.  */
void
__libc_message (int do_abort, const char *fmt, ...)
{
  :
              writestr (strnsize ("======= Backtrace: =========\n"));
              __backtrace_symbols_fd (addrs + 1, n - 1, fd);

              writestr (strnsize ("======= Memory map: ========\n"));
              int fd2 = open_not_cancel_2 ("/proc/self/maps", O_RDONLY);
              char buf[1024];
              ssize_t n2;
              while ((n2 = read_not_cancel (fd2, buf, sizeof (buf))) > 0)
                if (write_not_cancel (fd, buf, n2) != n2)
                  break;
              close_not_cancel_no_status (fd2);
  :

これを呼び出しているのは、malloc.cの中のfree中のエラーチェックルーチン。エラーが 見つかると

static void
malloc_printerr(int action, const char *str, void *ptr)
{
  if ((action & 5) == 5)
    __libc_message (action & 2, "%s\n", str);
  else if (action & 1)
    {
      char buf[2 * sizeof (uintptr_t) + 1];

      buf[sizeof (buf) - 1] = '\0';
      char *cp = _itoa_word ((uintptr_t) ptr, &buf[sizeof (buf) - 1], 16, 0);
      while (cp > buf)
        *--cp = '0';

      __libc_message (action & 2,
                      "*** glibc detected *** %s: %s: 0x%s ***\n",
                      __libc_argv[0] ?: "<unknown>", str, cp);
    }
  else if (action & 2)
    abort ();
}

このルーチンが呼び出される。 どうも、この機能は、linux限定のようだ。

また、Memory mapは、カーネル様ご提供データを 表示してんのね。Linuxは、ソースを見たい時、その都度御取り寄せしないといけなくて、面倒 だなあ。その点、*BSDは、インストールの時に一緒に入れてしまえるので、ソースはいつでも 参照出来る。

ソースにご加護あれ!

おまけのvimでカッコ、コッカ

Lispに限らず、対で入力せにゃならん文字種がある。(),{},[],"",''。相方を忘れると、つまらん エラーに見舞われる事になってやる気メーターが下がっちゃうね。

入力した時に、相方も同時に入力しちゃうのが得策。emacsとかだとそんなのが普通にあるけど vi系の場合は? おいらが知らないだけなんだけど、とあるHPに紹介されたので。

smartinputを入れましょう。

   Before | Input | After
   -------+-------+--------
   #      | (     | (#)
   #      | {     | {#}
   #      | "     | "#"

Leave from the current block easily:

   Before | Input | After
   -------+-------+--------
   (#)    | )     | ()#
   [#]    | ]     | []#
   "foo#" | "     | "foo"#

Undo the completion easily:

   Before | Input | After
   -------+-------+--------
   (#)    | <BS>  | #
   ()#    | <BS>  | #

docの中のHelpテキストから例を持ってきた。(#は、カーソルが有る場所です)

この作者さん、Gauche interfaceも 開発されているようで、vimの魔怪に頭を悩まされたようです。

vimのスクリプトは捨ててPythonでって希望を出してる人をしばしば見かけるけど、それを超越して、 いっその事Pythonでeditorを書いちゃえって 流れも有るんですね。