ESP32が落ちた(強制リセット)時にBacktraceから該当コードを調べる
Backtraceは行番号に変換できる
ESP32 で開発中、原因不明のまま強制リセットがかかってしまい、シリアルモニタには謎のエラーと 16 進数の羅列っていうのは良くある事かと思います。
付随するエラーメッセージは色々ある気がするんですが、abort() was called at PC 0x400871bf
みたいのとか、Guru Meditation Error: Core 1 panic'ed (StoreProhibited). Exception was unhandled.
みたいなやつとか。
この時表示される Backtrace はエラーが発生した箇所のアドレスを表していて、どうやら ESP32 は密かにこれらのアドレスとソースコードの該当位置の対応表を作ってくれているみたいです。
そしてxtensa-esp32-elf-addr2line.exe
というコマンドラインツールで、アドレスからソースコードファイル名と行番号に変換できます。
スクリーンショットは PlatformIO のシリアルモニタで、Backtrace のアドレスは枠で囲った部分。
書式
xtensa-esp32-elf-addr2line.exe -pfiaC -e "C:\(プロジェクトフォルダ)\.pio\build\esp32dev\firmware.elf" 0x400dd8da:0x3ffaff60
xtensa-esp32-elf-addr2line.exe
この exe がアドレスと行番号を変換するツールで、自分の環境( Windows )だと PlatformIO 用のものがC:\
、Arduino IDE のがC:\
にありました。ESP32 の開発環境がセットアップされていればすぐ見つかると思います。
firmware.elf
拡張子が elf のファイルがアドレスとソースコードの対応表と言うか、マッピングファイルと。普通にバイナリファイルでした。
PlatformIO の場合、プロジェクトフォルダ内に.pio\
というファイルがあるので、これを指定します。firmware.bin
と同じとこにあります。
アドレス
最後のパラメーターに Backtrace の後ろにある、0x4 で始まる 4 バイト 16 進数が 2 つコロンで繋がった “アドレス”を指定します。Backtrace には大量のアドレスが書かれていますが、それぞれがソースコードの異なる 1 箇所を示していて、コールスタックみたいな形になっています。
あまりに沢山あるので、自分はわざわざコマンドに渡すアドレスを変えながら逐一実行する Python スクリプトを作ってしまったんですが、何のことはない、複数のアドレスをそのままパラメータとして指定できます。
xtensa-esp32-elf-addr2line.exe -pfiaC -e "C:\(プロジェクトフォルダ)\.pio\build\esp32dev\firmware.elf" 0x4008b32a:0x3ffafdd0 0x4008d37b:0x3ffafe00 0x4008d9bd:0x3ffafe20 0x400823bd:0x3ffafe40 0x40082469:0x3ffafe60 0x40082539:0x3ffafe80 0x40087115:0x3ffafea0 0x4000bedd:0x3ffafec0 0x400fc503:0x3ffafee0 0x400fc618:0x3ffaff10 0x400fca23:0x3ffaff30 0x400fcb11:0x3ffaff50 0x400dd8ce:0x3ffaff70 0x400d9dee:0x3ffaffa0 0x400da9fa:0x3ffb0950 0x400dad3f:0x3ffb09d0 0x400db025:0x3ffb1260 0x400db0e5:0x3ffb12a0 0x400db41d:0x3ffb12f0 0x400dbb1e:0x3ffb1b60 0x400dc6e6:0x3ffb1c30 0x400d63b8:0x3ffb1f70 0x400e2d88:0x3ffb1f90 0x400ff26d:0x3ffb1fb0 0x4008a30e:0x3ffb1fd0
上記のように、backtrace の後ろのアドレス群をそのままコピペして渡せば OK です。
ちなみにコマンドラインのオプションの意味はさっぱりわかりません(笑)。
出力
コマンドの書式に問題がなければ下記のような形で、対応するソースコードのメソッド名、ファイル名、行番号が出てきます。
はぁ~ ESP32 って本当によく出来てるんですねぇ……
ぶっちゃけこれを見たところで一発解決とはならんのですが、今回の僕のケースだと 「 WString 内の concat メソッドあたりで realloc どうのこうのって出てるからメモリ確保関連?」みたいな感じで推察して、最終的にはヒープが足りなくなっているのかもと自分のコードで使っているバッファの量を少なくしたら落ちなくなりました。
なお出力に'a.out': No such file
みたいなメッセージが出てa.out
って何やねんってなる事がありましたが、シンプルにオプションとかの指定ミスでした。
いじょ!
ここまで辿らないと解決できないケースは稀な気がしますが、最悪こういう方法があるって知っておくだけで安心ですよねー。
参考🙇
開発時以外で ESP32 のシリアルログからバックトレースする方法 - わみめも
https://wamisnet.github.io/blog/2020-07-14-esp32-backtrace/
IDF Monitor - ESP32 - — ESP-IDF Programming Guide latest documentation
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/tools/idf-monitor.html
この記事はここで終わりです。
読んでいただきありがとうございました。
良かったらシェアしてね!
That's all for this article. Thank you for your reading.
Please share this if you like it!