Выполнение gcc-шагов вручную, компиляция, сборка, компоновка
Если у вас простая программа на C, например
int main(void) {return 0;}
Его можно скомпилировать с помощью gcc -o test test.c
.
Как я понимаю, gcc выполняет компиляцию, сборку, затем компоновку. Последние два шага выполняются с помощью as
и ld
.
Я могу сгенерировать код сборки с помощью gcc -S test.c
.
Что бы вы ввели в терминал, чтобы преобразовать код сборки в исполняемый файл?
(причина для этого - изучить сборку)
Ответы
Ответ 1
Это разные этапы с использованием gcc
gcc -E --> Preprocessor, but don't compile
gcc -S --> Compile but don't assemble
gcc -c --> Preprocess, compile, and assemble, but don't link
gcc with no switch will link your object files and generate the executable
Ответ 2
gcc test.s -o test
скомпилирует test
из test.s
для вас.
NASM также может стоить вашего времени - это может быть проще/более дружелюбно, чем gcc
для компиляции сборки.
Ответ 3
// main.c
#include <stdio.h>
int main(void)
{
printf("Hello World !\n");
return 0;
}
Для предварительной обработки, компиляции, сборки и, наконец, связывания простой вышеупомянутой программы hello world выполните следующие действия:
Шаг 1/4) Предварительная обработка main.c для генерации main.i:
$: gcc -E main.c -o main.i
Шаг 2/4) Скомпилируйте main.i для генерации main.s:
$: gcc -S main.i -o main.s
Шаг 3/4) Соберите main.s для генерации main.o:
$: as main.s -o main.o
ПРИМЕЧАНИЕ. Вы можете объединить вышеупомянутые шаги 1, 2 и 3, используя флаг -c (small C) для gcc:
$: gcc -c main.s -o main.o // OR $: gcc -c main.c -o main.o
Шаг 4/4) Свяжите main.o с другими необходимыми объектными файлами, а именно, crti.o & crtn.o (они определяют прологи функций и эпилоги соответственно), crt1.o (содержит символ _start для начальной загрузки программы), путь libc.so или флаг -lc для libc, а затем, наконец, задают имя динамический компоновщик, чтобы сгенерировать динамически связанный исполняемый файл ELF:
На x86_64:
$: ld /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o /usr/lib/x86_64-linux-gnu/crt1.o -lc main.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main_ELF_executable
ИЛИ (если вы хотите указать путь к libc.so)
$: ld /usr/lib/x86_64-linux-gnu/crti.o /usr/lib/x86_64-linux-gnu/crtn.o /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/libc.so main.o -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o main_ELF_executable
На 32-битной ARM:
$: ld /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/arm-linux-gnueabihf/crt1.o -lc main.o -dynamic-linker /lib/ld-linux.so.3 -o main_ELF_executable
ИЛИ (если вы хотите указать путь к libc.so)
$: ld /usr/lib/arm-linux-gnueabihf/crti.o /usr/lib/arm-linux-gnueabihf/crtn.o /usr/lib/arm-linux-gnueabihf/crt1.o /usr/lib/arm-linux-gnueabihf/libc.so main.o -dynamic-linker /lib/ld-linux.so.3 -o main_ELF_executable
Затем вы можете запустить исполняемый файл ELF 'main_ELF_executable':
$: ./main_ELF_executable
Привет, мир!
Источники:
https://linux.die.net/man/1/gcc
https://linux.die.net/man/1/ld
https://dev.gentoo.org/~vapier/crt.txt
Ответ 4
После выполнения gcc -S -o test.s test.c
введите gcc -o test test.s
.
Ответ 5
У вас может быть gcc
запуск и остановка процесса компиляции там, где вы хотите. gcc test.s -o test
будет компилировать test.s
из сборки в исполняемый файл.
Ответ 6
Как вы можете или не можете знать, четыре этапа компиляции состоят в предварительной обработке (-E), компиляции в сборку (-S), сборке в код объекта (-c) и, наконец, ссылку. Самое сложное для меня выяснить, как использовать вывод препроцессора. Вот как это сделать:
gcc -E hello.c | gcc -S -xc -o hello.s -
gcc -c hello.s -o hello.o
gcc hello.o -o hello