Как я могу определить, скомпилирован ли двоичный файл с указателями фреймов или нет в Linux? - PullRequest
8 голосов
/ 23 марта 2011

У меня есть бинарный файл / библиотека в Linux. Как я могу определить, был ли он составлен с помощью указателей фреймов?

1 Ответ

9 голосов
/ 23 марта 2011

Zan / blackwing:

Компиляция некоторых простых вещей с / без оптимизации указателя кадра и использование diff -u на разобранном выводе дает некоторые подсказки:

$ diff -u with*
--- with-fp 2011-03-23 09:49:29.366277002 +0000
+++ without-fp  2011-03-23 09:49:35.046277002 +0000
@@ -5,14 +5,12 @@
 Disassembly of section .text:

 00000000 <func>:
-   0:  55                      push   %ebp
+   0:  53                      push   %ebx
    1:  31 c0                   xor    %eax,%eax
-   3:  89 e5                   mov    %esp,%ebp
-   5:  53                      push   %ebx
-   6:  81 ec 00 04 00 00       sub    $0x400,%esp
-   c:  8b 4d 08                mov    0x8(%ebp),%ecx
-   f:  8d 9d fc fb ff ff       lea    -0x404(%ebp),%ebx
-  15:  8d 76 00                lea    0x0(%esi),%esi
+   3:  81 ec 00 04 00 00       sub    $0x400,%esp
+   9:  8b 8c 24 08 04 00 00    mov    0x408(%esp),%ecx
+  10:  89 e3                   mov    %esp,%ebx
+  12:  8d b6 00 00 00 00       lea    0x0(%esi),%esi
   18:  8b 14 81                mov    (%ecx,%eax,4),%edx
   1b:  89 14 83                mov    %edx,(%ebx,%eax,4)
   1e:  83 c0 01                add    $0x1,%eax
@@ -28,5 +26,4 @@
   3e:  75 f0                   jne    30 <func+0x30>
   40:  81 c4 00 04 00 00       add    $0x400,%esp
   46:  5b                      pop    %ebx
-  47:  5d                      pop    %ebp
-  48:  c3                      ret    
+  47:  c3                      ret    

Вы видите несколько видов изменений:

  1. Код с указателями кадра всегда будет содержать оба двух инструкций push %ebp и mov %esp, %ebp.
    Код без указания фрейма может (не в показанном случае, поскольку он не использует регистр %ebp для чего-либо) имеет push %ebp, но не будет иметь mov %esp, %ebp, поскольку это не такнеобходимо инициализировать framepointer.
  2. Код с framepointers обращается к аргументам в стеке относительно framepointer , как mov 0x8(%ebp), %ecx в показанном случае.
    Код без Framepointer делает это относительнок stackpointer с дополнительным смещением размера стекового фрейма функции, например mov 0x408(%esp), %ecx.
    То же самое может быть верно для локальных переменных, в показанном коде это lea -0x404(%ebp), %ebx для framepointer-использование кода против mov %esp, %ebx (возможно, lea 0x0(%esp), %ebx) для кода без указателей фреймов.
  3. Вероятно, есть некоторые изменения в распределении регистров между ними, особенно если код становится достаточно сложным, чтобы использовать регистр %ebp для локальной переменной (в показанном примере это не показано)

Уровни оптимизации компилятора довольно сильно влияют на то, как на самом деле выглядит сгенерированный код, ноупомянутые конкретные элементы (mov %esp, %ebp и использование %ebp -относительной адресации для аргументов / локальных переменных) только когда-либо встречаются в коде, использующем указатели фреймов, и отсутствуют, если вы скомпилировали с -fomit-frame-pointer.

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