Использование PUSH {lr} и POP {pc} для возврата из функции main / _start в ARM - PullRequest
0 голосов
/ 13 апреля 2019

Я пытаюсь понять, как правильно выйти из базовой программы в ARM, и я видел много кода, который использует PUSH {lr} для сохранения адреса возврата вызывающей функции (при условии, что вызывающая сторона использовала BL чтобы сохранить адрес возврата в lr), чтобы затем позднее получить его и перейти к адресу возврата, используя POP {pc}.У меня нет проблем, заставляя это работать с подпрограммами внутри функции main / _start, так как регистр lr изменяется на BL в этих случаях, но использование кода ниже значения, помещенного в стек, будет просто 0x0, вызывая ошибкупо возвращении.

    .text
    .global main

    main:
            PUSH {lr}  
            MOV r0, #42 
            POP {pc}
    .end

Я запустил код с гораздо большим количеством внешних вещей, которые используют этот точный метод для возврата из основной функции без Segmentation Fault, но когда я пытаюсь запустить эту базовую программу, используяОтладчик GDB очевидно, что lr остается на нуле в первой строке main и, таким образом, выдает ошибку при возврате.По сути, мой вопрос заключается в том, как получить правильное значение для lr, когда оно помещается в стек основной функции.

Я использовал

     $ as -g ex.s -o ex && ld -e main ex.o -o ex

для компиляции исполняемого файла.

РЕДАКТИРОВАТЬ: я обнаружил, что использование

     $ gcc ex.o -o ex

для связи с программой частично ответил на мой вопрос, глядя на вывод GDB, я обнаружил, что gcc кажется инициализировать lr с правильнымзначение, заставляющее пример программы завершиться нормально.Однако я все еще хотел бы знать, существует ли способ получения этого адреса при использовании ld, как я делал раньше.

1 Ответ

4 голосов
/ 13 апреля 2019

Точка входа ELF не является функцией , нет вызывающего абонента из пользовательского пространства, к которому можно вернуться, и нигде нет адреса возврата. Все, что вы получаете, это указатель стека, указывающий на argc, затем массив argv[] (не указатель на него), затем env[].

Вам нужно сделать системный вызов sys_exit (например, функцию libc _exit(2)).


Связывание с ld -e main ex.o -o ex делает статический исполняемый файл с main в качестве точки входа ELF. Изменение имени по умолчанию _start не поможет вам, а просто сбивает с толку всех. Я не рекомендую это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...