Как связать программу сборки газа, которая использует стандартную библиотеку C с ld без использования gcc?
Как упражнение, чтобы более точно узнать, как работают c-программы и какой минимальный уровень контента должен существовать для программы, чтобы иметь возможность использовать libc, я взял на себя задачу попытаться запрограммировать в первую очередь на сборке x86 с использованием газа и л.д..
Как забавная небольшая проблема, я успешно собрал и связал несколько программ, связанных с различными самодельными динамическими библиотеками, но я не смог скомпоновать программу с нуля, чтобы использовать вызовы функций libc без непосредственного использования gcc.
Я понимаю соглашения о вызовах отдельных функций библиотеки c и тщательно проверял программы, составленные из gcc, используя objdump и readelf, но не получил нигде, насколько какая информация должна включать в файл газовой сборки и что параметры для вызова в ld для успешной ссылки на libc. Кто-нибудь может понять это?
Я запускаю Linux на машине x86.
Ответы
Ответ 1
Для успешного использования libc с динамическим связыванием необходимо выполнить по крайней мере три вещи:
- Ссылка
/usr/lib/crt1.o
, которая содержит _start
, которая будет точкой входа для двоичного файла ELF;
- Ссылка
/usr/lib/crti.o
(до libc) и /usr/lib/crtn.o
(после), которые предоставляют некоторый код инициализации и завершения,
- Сообщите компоновщику, что двоичный файл будет использовать динамический компоновщик,
/lib/ld-linux.so
.
Например:
$ cat hello.s
.text
.globl main
main:
push %ebp
mov %esp, %ebp
pushl $hw_str
call puts
add $4, %esp
xor %eax, %eax
leave
ret
.data
hw_str:
.asciz "Hello world!"
$ as -o hello.o hello.s
$ ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc hello.o /usr/lib/crtn.o
$ ./hello
Hello world!
$
Ответ 2
Если вы определяете main
в сборке
Ответ Мэтью отлично справляется с минимальными требованиями.
Позвольте мне показать вам, как найти эти пути в вашей системе. Run:
gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n'
а затем возьмите файлы, упомянутые Матфеем.
gcc -v
дает вам точную команду компоновщика, которую использует GCC.
collect2 является внутренним исполняемым GCC, используемым в качестве линкера front-end, который имеет аналогичный интерфейс с ld
.
В Ubuntu 14.04 64-бит (GCC 4.8) я закончил с:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
/usr/lib/x86_64-linux-gnu/crt1.o \
/usr/lib/x86_64-linux-gnu/crti.o \
-lc hello_world.o \
/usr/lib/x86_64-linux-gnu/crtn.o
Вам также могут понадобиться -lgcc
и -lgcc_s
. Смотрите также: Мне действительно нужен libgcc?
Если вы определяете _start
в сборке
Если я определил _start
, мир hello из glibc работал с просто:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc hello_world.o
Я не уверен, является ли это надежным, т.е. если инициализация crt
может быть безопасно пропущена для вызова функций glibc. Смотрите также: Почему программа сборки работает только при соединении с crt1.o crti.o и crtn.o?
Ответ 3
Я думаю, что что-то вроде этого должно работать:
- сделать простую программу C
- gcc -S file.c
- изменить файл .s
- gas file.s
- ld file.o -lc crt1.o -o myprog