Предположим, у вас есть следующие файлы сборки:
.file "print.s"
.intel_syntax noprefix
.text
.globl _start
.type _start, @function
_start:
mov rax, 1
mov rdi, 1
lea rsi, hello_string
mov rdx, 14
syscall
mov rax, 60
mov rdi, 0
syscall
.size _start, .-_start
и
.file "string.s"
.intel_syntax noprefix
.data
.globl hello_string
.type hello_string, @object
hello_string:
.string "Hello, world!\n"
.size hello_string, 14
Если вы запустите as string.s -o string.o
, as print.s -o print.o
, а затем ld *.o -o hello.elf
, вы получите исполняемый файл, который печатает Hello, world !. Теперь предположим, что вы изменили метку _start
в print.s на print
, и у вас есть следующий файл C:
// main.c
void print(void);
int main (void) {
print();
return 0;
}
Я хочу запустить что-то вроде gcc -o main.elf main.c string.s print.s
, чтобы взять два моих файла сборки и связать их со стандартной средой выполнения C. Эта команда, как написано, не работает. Я получаю следующее сообщение об ошибке:
/usr/bin/ld: /tmp/ccc1yRif.o: relocation R_X86_64_32S against symbol `hello_string' can not be used when making a shared object; recompile with -fPIC
Я не могу понять, как правильно использовать флаг -fPIC, чтобы все заработало. Я даже не уверен, что это то, что я должен делать. Я мог бы попытаться использовать встроенный ассемблер, чтобы сделать это, но для моих реальных случаев использования это было бы крайне раздражающим, и я бы предпочел научиться правильно связывать куски сборки в мои программы на Си. Я не смог найти много информации об этом онлайн.
Вопрос: Как правильно использовать компоновщик GNU для привязки файлов сборки к среде выполнения C?
РЕДАКТИРОВАТЬ: В Как связать объектный файл C с объектным файлом на языке ассемблера? , ОП спрашивает о том, как решить аналогичную проблему связывания, просто используя ld
. Я хочу использовать gcc
, который является рекомендуемым решением в связанном вопросе, но я даже не могу заставить это работать.