4

ベアメタル (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 組み込みコンパイラプロジェクトの一部であり、完全なソースはここにあります

4

1 に答える 1