Пролог сгенерированных функций ARM GCC

Я упоминал, что наборы инструментов ARM могут генерировать прологи различных функций. На самом деле, я видел два файла obj (vmlinux) с совершенно разными прологами функций:

Первый случай выглядит так:

push {some registers maybe, fp, lr} (lr ommited in leaf function)

Второй случай выглядит так:

push {some registers maybe, fp, sp, lr, pc} (i can confuse the order)

Так что, как я вижу, второй толкает дополнительно пк и зр. Также я видел некоторые комментарии в утилите аварийного отключения (проект kdump), где было указано, что стек-кадр ядра должен иметь формат {..., fp, sp, lr, pc}, что меня больше смущает, потому что я вижу, что в некоторых случаях это не так правда.

1.) Прав ли я, что некоторые дополнительные флаги gcc необходимы для добавления дополнительных функций pc и sp в пролог функции? Если да, то что они?

2.) Для чего это используется? В принципе, как я понимаю, я могу раскрутить стек только с FP и LR, зачем мне эти дополнительные значения?

3.) Если это ничего не мешает с флагами компиляции - как я могу форсировать генерацию этого пролога расширенной функции и снова, какова цель?

Спасибо.

1 ответ

Решение

1.) Прав ли я, что некоторые дополнительные флаги gcc необходимы для добавления дополнительных функций pc и sp в пролог функции? Если да, то что они?

Есть много опций gcc, которые влияют на кадры стека (-march, -mtune и т. д. может повлиять на инструкции, используемые, например). В вашем случае это было -mapcs-frame, Также, -fomit-frame-pointer удалит кадры из конечных функций. Несколько статических функций могут быть объединены в одну сгенерированную функцию, что дополнительно уменьшает количество кадров. APCS может вызвать немного более медленный код, но необходим для трассировки стека.

2.) Для чего это используется? В принципе, как я понимаю, я могу раскрутить стек только с FP и LR, зачем мне эти дополнительные значения?

Все регистры, которые не являются параметрами (r0-r3), должны быть сохранены, поскольку они должны быть восстановлены при возврате к вызывающей стороне. Компилятор выделит дополнительные локальные элементы в стеке так, sp будет почти всегда меняться, когда fp изменения. Почему pc хранится, см. ниже.

3.) Если это ничего не мешает с флагами компиляции - как я могу форсировать генерацию этого пролога расширенной функции и снова, какова цель?

Это флаги компилятора, как вы уже догадались.

; Prologue - setup
mov     ip, sp                 ; get a copy of sp.
stm     sp!, {fp, ip, lr, pc}  ; Save the frame on the stack. See Addendum
sub     fp, ip, #4             ; Set the new frame pointer.
    ...
; Epilogue - return
ldm     sp, {fp, sp, lr}       ; restore stack, frame pointer and old link.
    ...                        ; maybe more stuff here.
bx      lr                     ; return.

Типичное сохранение stm sp!, {fp, ip, lr, pc} и восстановление ldm sp, {fp, sp, lr}, Это правильно, если вы изучаете документы ABI/APCS. Обратите внимание, что нет! чтобы попытаться исправить стек. Загружается явно из сохраненного ip значение.

Также сохранены pc не используется в эпилоге. Это просто сброшенные данные в стеке. Так зачем это делать? Обработчики исключений (прерывания, сигналы или исключения C++) и другие механизмы трассировки стека хотят знать, кто сохранил кадр. ARM всегда имеет только один пролог функции (одна точка входа). Однако есть несколько выходов. В некоторых случаях возврат, как return function(); может фактически превратиться в b function в, возможно, больше вещей здесь. Это известно как хвостовой вызов. Также, когда листовая функция вызывается в середине процедуры и возникает исключение, она увидит PC диапазон листа, но лист может не иметь рамки вызова. Сохраняя pc, кадр вызова может быть исследован, когда в листе возникает исключение, чтобы узнать, кто действительно спас стек. Таблицы pc по сравнению с деструктором и т. д. может храниться, чтобы позволить объектам быть освобожденными или выяснить, как вызвать обработчик сигнала. Экстра pc это просто замечательно при трассировке стека, и операция почти бесплатна из-за футеровки трубы.

Смотрите также: ARM Link и фрейм регистров вопрос о том, как компилятор использует эти регистры.

Другие вопросы по тегам