GDB Stub (sh-stub.c) を組み込んだ時のメモ (SH-4)

2011 年 5 月 22 日 はてなブックマークへ追加 はてなブックマーク - GDB Stub (sh-stub.c) を組み込んだ時のメモ (SH-4) Bookmark this on Delicious

とりあえずスタックトレースが取れればいいよ、ぐらいのノリなので適当に実装した。 対象は OS なしの野良ファームで、 CPU は SH7750R 。

やることはざっと 3 つ。

まず、 sh-stub.c のコンパイル。

文字入出力として getDebugChar()putDebugChar(c) が用意されているので、 それにシリアル(UART)入出力処理をつなぐ。とっても簡単。

ついでに、 sh-stub.c のバグ修正。関数のシグネチャが違うのが一カ所と、 putpacket()runlen > 100 で無限ループする問題に対処した。

if (src[0] != src[runlen] || runlen == 99)

次に GDB Stub のコマンドループ gdb_handle_exception() を何らかの方法で叩かせる。 とりあえずシリアル(UART)のキー入力で GDB Stub モードへ入るようにしてみた。

この時点で GDB と通信できるので、ひとまず確認してみよう。

% sh-hitachi-elf-gdb _build/foo.elf
(gdb) set remotebaud 115200
(ggb) set debug remote 1
(gdb) target remote /dev/ttyS0
...

何か色々出て (gdb) のプロンプトに行けば成功。

最後にレジスタの値を registers[] に格納。 スタックポインタ R15PC(プログラムカウンタ) PR(戻り先アドレス)は、 それぞれ退避レジスタから registers[] へコピーすればよい。

その他の汎用レジスタ Rn は割り込みに入った直後に保存しないといけない。 C 関数の呼び出しは当然レジスタの値を書き換えるので、大人しくアセンブリで書こう。 特に重要なのが R14 (フレームポインタ)で、 gcc が関数突入時のスタックポインタ(R15)をここに保存している場合がある。 R14 が変だとバックトレースが途中で壊れる。まぁ、 PCPR で 2 階層は辿れるけどね。

参考資料: - Renesas SH-4 コーリング シーケンスの使用 - MSDN

コメント

blog comments powered by Disqus