Разница между -ffreestanding и -nostdlib при компиляции с помощью gcc - PullRequest
1 голос
/ 06 января 2020

Я использую 64-битную linux машину с компилятором x84-elf64-g cc. Я только начал программирование низкого уровня и хотел бы понять, как код C фактически переводится в двоичный код. Это в основном для разработки операционных систем, так как я знаю, что процессор не понимает ELF или любой другой формат, а понимает только двоичный.

Например, следующий файл c:

//test.c
int func()
{
    return 0x12345678;
}

Когда я компилирую с g cc:

gcc test.c

, я получаю следующую ошибку:

(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status

Итак, я предполагаю, что есть проблема с линкер. Я делаю:

gcc test.c -c 

Я получаю объектный файл ELF, и я делаю objdump и получаю ожидаемое:

0000000000000000 <func>:
   0:   55                      push   %rbp
   1:   48 89 e5                mov    %rsp,%rbp
   4:   b8 78 56 34 12          mov    $0x12345678,%eax
   9:   5d                      pop    %rbp
   a:   c3                      retq   

Но когда я "кросс-компилирую" 32-битную версию, используя опция -m32 и objdump, я получаю:

hello.o:     file format elf32-i386


Disassembly of section .text:

00000000 <func>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   e8 fc ff ff ff          call   4 <func+0x4>
   8:   05 01 00 00 00          add    $0x1,%eax
   d:   b8 78 56 34 12          mov    $0x12345678,%eax
  12:   5d                      pop    %ebp
  13:   c3                      ret    

Disassembly of section .text.__x86.get_pc_thunk.ax:

00000000 <__x86.get_pc_thunk.ax>:
   0:   8b 04 24                mov    (%esp),%eax
   3:   c3                      ret    

В предыдущем ответе я читал, что это связано с позиционно-независимым кодом: неопределенная ссылка на ` _GLOBAL_OFFSET_TABLE_ 'в g cc 32-битный код для тривиальной функции, отдельно стоящая ОС

Почему происходят такие изменения при компиляции с параметром -m32? Более того, мне посоветовали использовать опцию -ffreestanding при компиляции, но здесь, похоже, это не дает никакого эффекта. Я читал, что -ffreedtanding говорит компилятору, что стандартной библиотеки нет, так что же тогда -nostdlib?

Примечание: я относительно новичок в этом hardcore c программирования, и я думаю, что главная проблема здесь в том, что я не очень понимаю, как работают компоновщики / компиляторы. :(

Ответы [ 2 ]

2 голосов
/ 06 января 2020

Опции управляют двумя частями процесса:

  • -freedtanding указывает компилятору, что он должен быть автономным, AFAIK единственный эффект - отключение некоторые встроенные функции, такие как memcpy ;

  • -nostdlib , указывают на то, что по умолчанию никакие библиотеки и файлы запуска не должны быть связаны.

2 голосов
/ 06 января 2020

Я не знаю, что -ffreestanding делает точно , эта часть - хороший вопрос.

Но, к сожалению, ваш вопрос имеет большой побочный эффект в 32-битном P IE код:

Почему происходит такое изменение при компиляции с параметром -m32?

Поскольку вы пропустили любой параметр оптимизации -O и 32 -битный режим не имеет EIP-относительного режима адресации для данных (только относительные переходы / вызовы). Таким образом, очевидно, что режим отладки всегда устанавливает регистр в качестве указателя GOT в качестве основы для адресации данных stati c, даже в функциях, которые его не используют.

Всегда используйте -fno-pie, чтобы отключить это по умолчанию, если только вы не хотите сделать исполняемый файл P IE.

Возможно, вы также захотите -mcmodel=kernel - это хорошая идея, если вы компилируете 64-битную верхнюю половину ядро (для адресов stati c можно использовать 32-разрядные расширения с непосредственным расширением знака, но не 32-разрядные расширения с нулевым расширением). Но IDK, если он что-то делает для 32-битного кода.

...