スタックトレースの生成に関する問題を理解するにはgdb
、最初にgdb
スタックトレースの生成方法を理解する必要があります。コンパイラーは、関数を作成するときに標準のプロローグとエピローグC
を使用します。これは、関数の開始時と終了時のアセンブラー・コードです。これの一部はlr
、スタックに保存し、ローカル変数用のスペースを予約し、前のフレームポインタまたはをリンクすることです。これらのスタックフレームは、でルート化され、通常はゼロで終了するタイプのリンクリストを提供します。これはABIによって異なります( -mabiを参照)fp
fp
)。詳細はARMABIタイプごとにわずかに異なりますが、概念は似ています。
したがって、 (または何らかの例外が発生すると)コンパイルされたコードSWI
のフローが完全に中断され、特にスタックが破損した場合に、フレームポインタリストのデコードが困難になる可能性があります。また、プログラムのコンテキストをデコードしません。一部のシステムでは、フレームポインタが変更され、すぐにからに切り替わる場合があります。例外のは、スクラッチレジスタとしても使用できます。が入力されると、ハンドラーの仕事の一部はレジスター()を保存することです。マルチタスクO/Sの場合、これにより、あるタスクから別のタスクにスタック が完全に変更される可能性があります。C
gdb
exception mode
system/supervisor mode
sp
SWI
user
r0-r12
user
例外モードでを調べることにより、障害/原因の命令をいつでも特定できます。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を使用して、スタックをスタックにリンクできます。これを行うと、スタックトレースを与えることができます。ただし、検討中のシステムにはサポートコードはありません。lr
SWI
lr
SWI
supervisor
user
fp
gdb
SWI
gdb
この状況でスタックトレースを提供するマクロを作成することもできます。gdb
ただし、これを一般的に行うのは難しい作業になることは明らかだと思います。