ベアメタル (OS なし) で ARM 用の Linux 標準 C ライブラリを使用する小さなプロジェクトを行っています。実行プラットフォームとして qemu-system-arm を使用し、GDB をデバッグに使用しています。C ライブラリが行う SVC 呼び出しを処理するための小さなシステム コール ハンドラを作成しましたが、処理されていないシステム コール関数がスタックをトラバースして呼び出し元に戻ることができないという事実に混乱しています。ハンドラー コードは次のとおりです。
SVC_Handler:
srsfd sp!, #Mode_SYS // Save LR_svc and SPSR_svc on the sys stack.
cpsid i, #Mode_SYS // Switch to sys mode.
push {r4-r12, lr} // Save registers.
// In a system call.
// r7 is the call number.
__in_syscall: // The stack frame is valid here.
cmp r7, #512
blhs Unhandled_SVC // Jump if too big for a syscall.
adr r8, SVC_Table // Get the system call table.
str r7, SysCall // Save call number for error reporting.
ldr r7, [r8, r7, lsl #2]// Get the stystem call entry.
blx r7 // Dispatch. Return value is in r0/r1
goback:
pop {r4-r12, lr} // Restore registers.
rfeia sp! // And return.
SysCall:
.word 0
// Unhandled system calls.
Unhandled_SVC:
stmfd sp!, {r12, lr}
push {r2-r5} // Push extra arguments.
mov r3, r1
mov r2, r0
ldr r1, SysCall // And the system call number.
ldr r0, stringPtr // Get the format string.
bl printf
add sp, #16 // clean up the stack.
mov r0, #-ENOSYS
ldmfd sp!, {r12, pc}
__in_syscall にブレークポイントを設定すると、スタック フレームが正常に表示されます。分岐を介して、または SVC_Table のポインターを介して間接的に Unhandled_SVC に入ると、プログラムが正しく実行されていても、GDB はスタック フレームの表示に混乱します。
私は何が欠けていますか?
これは私のELLCC 組み込みコンパイラプロジェクトの一部であり、完全なソースはここにあります。