2

を使用して、ベアメタルARMプラットフォームで実行されているプログラムをデバッグしようとしていますgdb。ある時点で、SWI(ソフトウェア割り込み)例外が生成されます。ただし、バックトレースには、次のように例外が生成されたものは表示されません。

(gdb)c

Continuing. 
^C 
Program received signal SIGTRAP, Trace/breakpoint trap. 0xffff0008 in ?? ()
(gdb) bt
#0  0xffff0008 in ?? ()

ARMで実行されているプログラムはでコンパイルされましたがarm-none-linux-gnueabi-gcc -O2 -c -ggdb、私も-O0同じ結果で使用してみました。

どうすれば意味のあるコールスタックを取得できますか?この例外を生成しているものを見つける別の方法はありますか?

4

1 に答える 1

4

スタックトレースの生成に関する問題を理解するにはgdb、最初にgdbスタックトレースの生成方法を理解する必要があります。コンパイラーは、関数を作成するときに標準のプロローグエピローグCを使用します。これは、関数の開始時と終了時のアセンブラー・コードです。これの一部はlr、スタックに保存し、ローカル変数用のスペースを予約し、前のフレームポインタまたはリンクすることです。これらのスタックフレームは、でルート化され、通常はゼロで終了するタイプのリンクリストを提供します。これはABIによって異なります( -mabiを参照)fpfp)。詳細はARMABIタイプごとにわずかに異なりますが、概念は似ています。

したがって、 (または何らかの例外が発生すると)コンパイルされたコードSWIのフローが完全に中断され、特にスタックが破損した場合に、フレームポインタリストのデコードが困難になる可能性があります。また、プログラムのコンテキストをデコードしません。一部のシステムでは、フレームポインタが変更され、すぐにからに切り替わる場合があります。例外のは、スクラッチレジスタとしても使用できます。が入力されると、ハンドラーの仕事の一部はレジスター()を保存することです。マルチタスクO/Sの場合、これにより、あるタスクから別のタスクにスタック が完全に変更される可能性があります。Cgdbexception modesystem/supervisor modespSWIuserr0-r12user

例外モードでを調べることにより、障害/原因の命令をいつでも特定できます。lrこれはARMArchitechureで指定されており、どのARMCPUでも同じです。0xfff0008デフォルトのSWIハンドラーアドレスです(高メモリベクトルテーブルを使用する場合)。ARM ARM(アーキテクチャリファレンスマニュアル)SWIのを除いて、次のとおりです。


A2.6.4ソフトウェア割り込み例外

ソフトウェア割り込み命令(SWI)は、スーパーバイザーモードに入り、特定のスーパーバイザー(オペレーティングシステム)機能を要求します。SWIが実行されると、次のアクションが実行されます。

   R14_svc    = address of next instruction after the SWI instruction
   SPSR_svc   = CPSR
   CPSR[4:0]  = 0b10011                 /* Enter Supervisor mode */
   CPSR[5]    = 0                       /* Execute in ARM state */
                                        /* CPSR[6] is unchanged */
   CPSR[7]    = 1                       /* Disable normal interrupts */
                                        /* CPSR[8] is unchanged */
   CPSR[9]    = CP15_reg1_EEbit         /* Endianness on exception entry */
   if high vectors configured then
       PC     = 0xFFFF0008
   else
       PC     = 0x00000008

SWI操作の実行後に戻るには、次の命令を使用してPC(R14_svcから)およびCPSR(SPSR_svcから)を復元し、SWIに続く命令に戻ります。

       MOVS PC,R14

ご覧のとおり、スーパーバイザーモードR14_svcのときはinstruction+4に設定されています。これは、通常の復帰で次の命令が再開されるようにするためです。がどこにあるかを調べることにより、どこで発生したかを判断できます。ユーザースタックが破損していない場合は、コンパイラが使用しているABIを使用して、スタックをスタックにリンクできます。これを行うと、スタックトレースを与えることができます。ただし、検討中のシステムにはサポートコードはありません。lrSWIlrSWIsupervisoruserfpgdbSWI

gdbこの状況でスタックトレースを提供するマクロを作成することもできます。gdbただし、これを一般的に行うのは難しい作業になることは明らかだと思います。

于 2013-03-02T18:14:55.533 に答える