Как настроить рамку стека ARM так, чтобы GDB могла ее пересечь?
Я делаю небольшой проект по использованию стандартной библиотеки Linux C для ARM на голом металле (без ОС). Я использую qemu-system-arm в качестве платформы выполнения и GDB для отладки. Я написал небольшой обработчик системных вызовов для обработки вызовов SVC, которые делает библиотека C, но меня смущает тот факт, что моя необработанная функция syscall не может пересечь стек обратно к вызывающему объекту, хотя обработчик 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}
Если я установлю точку останова в _ _ в _ syscall, я смогу увидеть стек кадр просто отлично. Если я ввожу Unhandled_SVC либо через ветвь, либо косвенно через указатель в SVC_Table, GDB запутывается, отображая кадр стека, даже если программа выполняется правильно.
Что я упускаю?
Это часть моей ELLCC встроенного компилятора и полной источник здесь.
1 ответ:
Tl; dr - Вероятно, вы не можете сделать то, что хотите для вашего случая использования системного вызова.
Однако, следующее полезно для трассировки ARM ассемблера, который не включает переключение режимов.
Существует несколько GNU assembler или gas псевдо-ops, которые используются для трассировки стека в ассемблере. Тем не менее, вы всегда можете создать ассемблер, который выходит за рамки обычной процедуры; например, планировщик с переключением контекста, и т.д.
.fnstart
- начало функции (текстовый диапазон).fnend
- конец функции (текстовый диапазон).setfp
- расположение кадра стека АСУ ТП..save
- список сохраненных регистров в стеке..pad
- другое зарезервированное место в стеке.movsp
- увеличение стека..cantunwind
- Не пытайтесь раскрутить эту функцию; когда вы вышли за пределы нормального.Ваша текущая процедура пропускает регистр
pc
(дляSVC_Handler
) рутина и не обновляетfp
. Это нормально, но вы должны сказать отладчику, чтобы он не смотрел на аргументы, которые могут быть в несохраненных регистрах. Особенно полезен ГАЗ разматывание учебника .Ваш пользователь
sp
и системаsp
различны. Поэтому, когда вы отслеживаете, он будет только в одном стеке. GDB не будет знать, чтобы перейти режимы и / или стека. Один механизм состоит в том, чтобы обнулить указатель кадра в записи syscall так, чтобы он был завершение трассировки кадра. Затем вам нужно настроить реальный кадр стека вUnhandled_SVC
. Вам нужно будет написать макрос GDB, чтобы извлечь информацию о вызове SVC ядра и перейти к стекуexcepted , если вы хотите продолжить трассировку.См.: соединения рукоятки и рамка указателя для некоторых информация в стеке структуры руки.