How do I set up the ARM stack frame so that GDB can cross it?

I am doing a small project to use the standard C library for Linux for ARM on bare metal (without OS). I use qemu-system-arm as a runtime platform and GDB for debugging. I wrote a small system call handler to handle the SVC calls that the C library creates, but I am confused by the fact that my raw syscall function cannot go through the stack back to the caller, even if the SVC handler can. Handler Code:

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}

If I set a breakpoint in __in_syscall, I see that the stack frame is fine. If I enter Unhandled_SVC either through a branch or indirectly using a pointer to SVC_Table, GDB gets confused by showing the stack frame, even if the program runs correctly.

What am I missing?

ELLCC .

+4
1

tl; dr - , , .

ARM-, , :


gnu , . , , ; , ..

  • .fnstart - ( )
  • .fnend - ( )
  • .setfp - APCS.
  • .save - .
  • .pad -
  • .movsp - .
  • .cantunwind - ; .

pc register ( SVC_Handler) fp. , , , . , .

sp sp . , , . GDB , / . - syscall, . Unhandled_SVC. GDB SVC , .

: ARM Link ARM.

+1

Source: https://habr.com/ru/post/1536236/


All Articles