Почему gcc помещает инструкцию «привал» в программы после вызова «main»? - PullRequest
9 голосов
/ 07 марта 2011

Когда вы смотрите на исполняемый файл elf, созданный gcc в системе Linux / i386, кажется, что он всегда помещает инструкцию остановки (0xf4) после вызова «main» и перед заполнением «nop», например так:

│ ....... ! entrypoint:
│ ....... !   xor         ebp, ebp
│ 80482e2 !   pop         esi
│ 80482e3 !   mov         ecx, esp*emphasized text*
│ 80482e5 !   and         esp, 0fffffff0h
│ 80482e8 !   push        eax
│ 80482e9 !   push        esp
│ 80482ea !   push        edx
│ 80482eb !   push        __libc_csu_fini
│ 80482f0 !   push        __libc_csu_init
│ 80482f5 !   push        ecx
│ 80482f6 !   push        esi
│ 80482f7 !   push        main
│ 80482fc !   call        wrapper_804a004_80482c4
│ 8048301 !   hlt                                      <--- halt instruction
│ 8048302 !   nop
│ 8048303 !   nop
│ 8048304 !   nop
               ⋮

Какова цель этого? Этот код никогда не должен быть достигнут. Это какая-то защита?

Ответы [ 3 ]

11 голосов
/ 07 марта 2011

После основного возврата будет вызван выход.Hlt существует, если системная версия выхода не останавливает выполнение процесса немедленно.В пользовательском режиме это вызовет ошибку защиты, которая убьет процесс.Если процесс по какой-то причине выполняется в кольце 0, он просто остановит процессор до следующего прерывания, что, как мы надеемся, заставит ОС удалить процесс.В процессах, предназначенных для работы в кольце 0, после hlt часто есть инструкция jmp, которая заставляет hlt выполняться снова и снова, пока процесс не завершится.

3 голосов
/ 07 марта 2011

Я бы предположил, что это защита, которая, вероятно, на самом деле не работает. Например, hlt является привилегированной инструкцией, которая означает, что она вызовет исключение при выполнении в кольце 3 (где выполняется большинство приложений). В лучшем случае это может быть полезно для кода ядра, но если включены прерывания, то hlt будет длиться только до тех пор, пока процессор не получит прерывание, а затем процессор продолжит и выполнит заполнение nop.

0 голосов
/ 07 марта 2011

вы правы - этот код никогда не должен быть достигнут и оставлен там, вероятно, при разработке в качестве гарантии.Существует стековая манипуляция для предотвращения возврата вызова.

подробнее здесь: http://www.win.tue.nl/~aeb/linux/hh/stack-layout.html

...