スタックから関数の呼び出し元を解析する方法

リセットせざるを得ないようなエラーが起こった際、
その関数の呼び出し元をNVMに記憶してリセットするようにしたいのですが、
スタックから関数の呼び出し元を実行時に解析する方法はありますか?

 

CS+のコールスタック機能では、関数の呼び出し元を表示することができています。
これを、実行時に2,3階層さかのぼって、関数の呼び出し元のアドレスを取得したいです。

 

よろしくお願いいたします。

  • スタックがぶっこわれてなければスタックの内容はスタックフレームが連続してる形となってる筈なのでROMの内容と対応を取ることはある程度可能とは思いますが、「リセットせざるを得ないようなエラーが起こった際」になんかできるとは思わないですね。
  • 返信ありがとうございます。
    スタック中のメモリの使われ方は、コンパイラマニュアルには載っていなかったのですが、
    C89等の言語規格で決まってるんでしょうか?

    後で解析する用で、運が良ければNVMに残せればいいなと考えています。
  • > スタック中のメモリの使われ方は、コンパイラマニュアルには載っていなかったのですが、
    > C89等の言語規格で決まってるんでしょうか?

    コンパイラの生成するコードを見る他ないと思いますがそんな難しいものではないです。
  • ありがとうございます
    アセンブラ読んでスタックの使い方を解析してみます。
  • dracenさん、こんにちは。NoMaYと申します。

    残念ながら、実行時に関数の呼び出し元を解析することは、出来ないです。なぜなら、その為には、関数の呼び出し元のアドレス(つまりリターンアドレスですね)がスタックフレーム上のどの場所に格納されているか(それぞれの関数毎に異なります←ここ重要です)という情報が必要になりますが、それはソースレベルデバッグ情報の一部として一応.absファイル(や.xファイル)には含まれているものの、フラッシュメモリに書き込まれる内容(つまりMOTファイルですね)には含まれていないからです。

    実は、デバッグ技法として、Post-mortem debuggingとして知られている方法があります。Linuxでコアダンプした時とか、Windowsでアプリケーションエラーが発生した時とか、致命的エラーが発生した時にひとまずスタック等の内容を(OSの機能によって)ファイルに保存しておき、後から、そのファイルをデバッガで読み込んでデバッグする方法です。(下記の関連リンクを参照して下さい。)

    今回は、以下のようなやり方ならば、RXマイコンで同様なことを行うことが出来るのではないか、と私は考えています。

    (1) 解析に必要な、PC値、SP値、(PSW値、CS値、ES値、汎用レジスタ値、) スタック内容(256バイト程度(プログラム次第ですがもっと少なくても良いかも))、をNVMに書き込む。(括弧内の値は無くても可、とは考えていますが、量も少ないので一緒に書き込むのが良いかも、と考えています。[訂正] すみません、RL78とごっちゃになっている部分がありました。)
    (2) NVMに書き込んだ内容を、パソコンへ読み出して、ファイルに保存する。
    (3) RXシミュレータ(今回の目的では、ルネサスシミュレータでもGDBシミュレータでも、どちらでも可)を起動して、CS+なら.absファイル、e2 studio/GDBなら.xファイル、を読み込む。
    (4) CS+やGDBでPythonスクリプトを使ったり、或いは自作プログラムで(2)で保存したファイルの内容をCS+やe2 studio/GDBで読み込めるレジスタ情報ファイル形式やメモリ情報ファイル形式に変換した後でCS+やGDBのコマンドを使って、保存したファイルの内容をRXシミュレータに読み込む。
    (5) そして、CS+のコールスタックウィンドウ、e2 studioのDebugビュー/GDBのスタックトレースコマンド、を使って関数の呼び出し元を表示させる。

    [関連リンク]

    Wikipedia: Debugging (英文)
    en.wikipedia.org/wiki/Debugging

    Techniques
    ...略...
    ・Post-mortem debugging is debugging of the program after it has already crashed. Related techniques often include various tracing techniques (for example,[9]) and/or analysis of memory dump (or core dump) of the crashed process. The dump of the process could be obtained automatically by the system (for example, when the process has terminated due to an unhandled exception), or by a programmer-inserted instruction, or manually by the interactive user.
    ...略...


    DDJ誌: Postmortem Debugging (英文) (一例ですがWindowsでVisual C++ 6.0で生成されたexe fileとmap fileを使った例です)
    www.drdobbs.com/tools/postmortem-debugging/185300443

    Google検索: post mortem debugging
    www.google.com/search?q=post+mortem+debugging
     

  • 回答ありがとうございます。

    CS+がどうやってコールスタックの情報を表示しているか不思議だったのですが、
    absファイルの中に、スタックフレーム内のメモリ配置に関する情報があって、
    それに基づいて表示しているのですね。

    だから、実行時にはスタックからコール元のアドレスを特定することはできない、
    ということですね。すごく納得しました。

    エラーが起こった時のPC・SP・スタックを保存しておき
    あとから、CS+のシミュレータ上で、それらの情報を反映して、
    コールスタック等を使用して解析するということですね。

    その発想は全くなかったので、目からうろこでした。
    Postmortem Debugging という手法があるのですね。まったく知りませんでした。

    一度、提案していただいた方法で
    実現できるた試してみることにします。

    ありがとうございました!