2009年1月8日木曜日

昨日の書き込みで、GDBがステップ実行されない件について書いたけど、どうも気持ち悪いの引き続き調べてみた。
原因は、リモートデバッグの's'コマンドに対して、ブレークしたときにはSIGILLではなく、SIGTRAPを返さないといけないようだ。そんなこと、どこに書いてある?!いちおうGDBのマニュアルとか読んでみたんだけどなー。

実際には、これに気付く前から's'で止まったときにはSIGTRAPをつもりで作ってはいた。しかし、うまく動いていなかっただけだった。ターゲットのARMのマニュアルを見直してみると、BKPT命令はデバッグモニタ割り込みではなくて、HardFault割り込みで実行される<ことがある>らしい。ってか、レジスタをいじってBKPTがデバッグモニタ割り込みで動作するように切り替えないといけなかったらしい・・・。そんな落とし穴・・・簡単に気付くかよ!ってんだ。
タイトルに「健忘録」という言葉を使ってみたが、嫁にそれはちょっとおかしい、[ぼうびろく]じゃないかと突っ込まれた。
調べてみると・・・・、正しくは

 [びぼうろく](備忘録)

というのが一番正しいらしい。
でもどうやら一概に間違いだと切って捨てるにはまだ早いかもしれない。Google先生によると、

 備忘録>>忘備録>健忘録

の順でそれなりの数でhitする。ま、もちろん備忘録がダントツに多いわけだが・・・。

なんだか恥ずかしい。
でも言葉なんて生き物、使い続ければそれが一番正しいってことになるかも知れない。ガンバレ、「健忘録」族!(なんて、強がりです・・・)

2009年1月6日火曜日

ARM thumb2(Cortex-M3)開発環境構築

かなり手こずった。

C級出版の付録Cortex-M3開発ボードを手にして、直ぐに具体的な開発(という名のお遊び)に取りかかれると思ったのに、意外と大変だったワイ。ちなみに目標はSDカードへのFATファイルシステムアクセスをモノにすること!!
とりあえず、interface誌にならってbintuils、GCC、GDBをインストールしてコンパイルするのは無問題。GDBのスタブもinterface誌にあるものを流用して、とりあえずはターゲットとconnectしてダウンロードとかCtrl+Cでブレークするところまでは直ぐに確認できた。しかし、ここからが長かった・・・

まず、's'でステップ実行ができない!'s'でも'c'でも同じようにLEDチカチカが走り続けてしまう。なんでだ?

'b'でbreakpointを張ってみる。とりあえず、止まるのだが訳の分からないところで止まっている。アドレスから見るとGDBスタブの中で止まっているように見えるな。なんでだ?

では、ソフトの方にBKPT命令を入れてGDBでキャッチできるかどうか見てみよう。とりあえず止まる。が、やはりbreakpointを張ったときと同じように、スタブの中で止まっているように見える。breakはできないのか?GDBの意味無いじゃん!なんでだろう?

まあよい、'c'でcontinueはできるはずだ。Ctrl+Cでブレークした時はstepはできなくてもcontinueはできていたんだ。breakpointの続きから実行再開してくれるはず・・・、あれっ?しないな~。同じアドレスで止まったままGDBに戻ってくるな。なんでだ?

ここから堂々巡り。
GCCは正式にはthumb2命令には対応していないらしく、ややこしいことにCortex-M3はthumb2命令しか対応していないため、ARMモードに戻るようなコードは御法度!。何か変なコードが紛れ込んでるのかと思って、GDBからdisassembleしてみるとどうもおかしい。thumb命令って基本16bit長じゃなかったっけ?逆アセの結果は全部32bit単位で出てる。メモリの内容がおかしいのか、それとも・・・「GDBがthumb2のデバッグに対応していない!」なんてオチなのか?そんなことはあるまい。
しかし確かにdisassembleの結果はおかしい。ダウンロード前のelfバイナリをobjdumpすればちゃんとthumb2で逆アセされてるから、おかしなコードがあるわけでもないようだ。困った困った・・・

それからも、いろいろ紆余曲折した挙げ句に分かった原因は・・・。

interface誌のGDBスタブが間違がっとるやないかいっ!

GDBスタブ側の割り込みハンドラから、ユーザープログラム側の割り込みハンドラへ飛んでくるときのユーザーベクタアドレスは、0x02000000じゃなくて、0x20000000ね。もう一度言う、にひゃくまんエイチじゃなくて、にせんまんエイチです!ったく、だからいつまで経ってもC級なんだよ!

もう面倒だから、スタブの方を改造してデバッグモニタ割り込みは全部スタブ側だけで処理するようにしてしまった。ユーザープログラム側に渡そうとして変な動きしてたからとりあえずはより安定して動くことを目標にした方がよさそう。

それから、GDBでシングルステップ実行ができない件。なんだよ、このスタブ、's'も'c'も同じ扱いじゃねーか!そりゃ's'したら走り続ける罠。ううぅぅ、オノレ、C級出版め。余計な面倒かけやがって。
途中で入手したCortex-M3のマニュアルを見て、サクッと's'コマンドに対応させてみる。う~ん、いい感じ、stepもできるようになったゾ。breakpointも張れるし、これで苦節半年、ようやく本来の目標に戻れる。と思いきや、正月休みも終わりタイムオーバー。
やっぱり今年も中途半端な一年に終わりそうな予感。。。

あっ、disassembleがうまく行かなかった件、これはもしかするとGDBがTバリアントを見てARMモードかthumbモードかを見て逆アセしてたからなのかなぁ。今はちゃんとdisassembleできてる。GDB6.8はthumb2で何とか使えそうではある。

それから疑問が1点残った。's'はソースレベルのstep実行、'si'がアセンブラレベルのstep実行だったような記憶があるのだが、なぜか's'でも'si'の動きをしている。GDBは's'でも'si'でも同じパケットをスタブに投げているようなので、どうもGDB自体がソースレベルでstep実行しようとはしていない模様。なんでだ?これも今後の課題だ。

とりあえず、breakpointを張って止める、変数のinspectionができる、これだけでも大進歩だ。あとは時間を確保すること・・・それが問題だな。