2015/04/04

gdbでCソースが見えないときは、コンパイル後のデバッグオプションを疑おう

nRF51822で、なぜかブレークポイントが設定できなくなった。
以前はできていたので、その時の環境に戻す、という選択もある。
が、今後のことも考えて、「こうやったら直った」を探そうと思う。

まあ、きっちりした解決にはならないかもしれないが、近づくことはできるだろう。


簡単なソースファイルをarm-none-eabi-gccでビルドした場合は、gdbでソースファイルが確認できた。
では、今のnRF51822で使っているMakefileでそのファイルをビルドしてみよう。

 

コマンドラインでビルド&デバッグ

  • ソースファイルはmain99ma.c、その下にmkdir gcc/_buildしておく。
  • cd gcc
  • arm-none-eabi-gcc ../main99ma.c -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -Wall -Werror -mfloat-abi=soft -flto -fno-builtin -ggdb3 -O0 --specs=nano.specs -lc -lnosys -Xlinker -Map=_build/tst.map
    -Wl,--gc-sections -o _build/tst
  • cd ..
  • arm-none-eabi-gdb gcc/_build/tst
  • (gdb) list main99ma.c:main
#include <stdio.h>
int main(void)
{
    printf("Hello.\n");
    return 0;
}

 

これをmakefileに入れ込む。
結果は・・・・・だめだ。No source file named main99ma.cだ。
ふむ、幸先がよい。


コマンドラインでビルドしたときのオプションだが、よく見るとmakefileのものとまだ違いがあった。
同じにしよう。

  • arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mabi=aapcs --std=gnu99 -Wall -Werror -mfloat-abi=s
    oft -flto -fno-builtin -ggdb3 -O0 -c -o _build/main99ma.o ../main99ma.c
  • arm-none-eabi-gcc -Xlinker -Map=_build/tst.map -mthumb -mabi=aapcs -L .. -mcpu=cortex-m0 -Wl,--gc-sections --specs=nano.specs -lc -lnosys _build/main99ma.o -o _build/tst

あれ・・・リンクエラーが出た。libc_nano.aが参照しているsbrkなどが無い、と。
単に2つに分けただけなんだが・・・。
あ、これはリンクするオブジェクトの並べ方がよくない。

  • arm-none-eabi-gcc -Xlinker -Map=_build/tst.map -mthumb -mabi=aapcs -L .. -mcpu=cortex-m0 -Wl,--gc-sections --specs=nano.specs _build/main99ma.o -lc -lnosys  -o _build/tst

これで通った。
確か、並べた順番に処理していくので、大元になるライブラリは最後の方に並べるとか、そんなルールだったと思う。

 

あららららら。
このtstをgdbで読むと「Reading symbols from gcc/_build/tst...(no debugging symbols found)...done.」だと。
1行だとsymbolがあるのに、2行にすると消える・・・?

mapファイルを見比べると、確かに、なさそうだ。
と、いうことは・・・・!


2つに分けた、リンクの方をさらに修正。

  • arm-none-eabi-gcc -ggdb3 -Xlinker -Map=_build/tst.map -mthumb -mabi=aapcs -L .. -mcpu=cortex-m0 -Wl,--gc-sections --specs=nano.specs _build/main99ma.o -lc -lnosys  -o _build/tst

そうすると、できあがったtstにシンボルが入っていて、gdbもちゃんと読めた。
そうか、デバッグオプションっていうと、コンパイルレベルのものしか考えてなかったんだけど、リンクレベルにも影響があるんだ。

nRF51822アプリのmakefileを書き換えて、eclipseでもちゃんとCソースにブレークが貼れることが確認できた。
満足した。


さて、先ほど「リンクの方を」と書いたが、GCCのリンクオプションを見ると、-gは無い。
まあ、-Xlinkerとか-Wlに続けて書いているわけじゃないから、リンクオプションにはなってないんだが。

しかし、修正した方は特にコンパイルを行っているわけでもない。
だから昔の感覚からすると、

プリプロセス→コンパイル→リンク

のリンクになる、と考えてしまう。

ただ、最近のコンパイラはもう1段挟むようになり、gcc4からそうなったという記事をC Magazineで読んだ記憶がある。
だから、それをリンクする工程でも「デバッグオプションは残しておいてくれ」という意味で付けるのだろうか。

Interface誌のコンパイラ特集を読みながら調べようかと思ったが、これはもうちょっと時間に余裕があるときにやろう。
今回の教訓は、「Cソースレベルのデバッグができないときは、コンパイル以降のデバッグオプションを見てみよう」だ。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。