Подтвердить что ты не робот

Как связать программу сборки газа, которая использует стандартную библиотеку C с ld без использования gcc?

Как упражнение, чтобы более точно узнать, как работают c-программы и какой минимальный уровень контента должен существовать для программы, чтобы иметь возможность использовать libc, я взял на себя задачу попытаться запрограммировать в первую очередь на сборке x86 с использованием газа и л.д..

Как забавная небольшая проблема, я успешно собрал и связал несколько программ, связанных с различными самодельными динамическими библиотеками, но я не смог скомпоновать программу с нуля, чтобы использовать вызовы функций libc без непосредственного использования gcc.

Я понимаю соглашения о вызовах отдельных функций библиотеки c и тщательно проверял программы, составленные из gcc, используя objdump и readelf, но не получил нигде, насколько какая информация должна включать в файл газовой сборки и что параметры для вызова в ld для успешной ссылки на libc. Кто-нибудь может понять это?

Я запускаю Linux на машине x86.

4b9b3361

Ответ 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