2010-08-26 8 views
13

Jako ćwiczenie, aby dowiedzieć się dokładniej, jak działają programy c oraz jaki minimalny poziom zawartości musi istnieć, aby program mógł korzystać z biblioteki libc, zdecydowałem się na programowanie głównie w x86 przy użyciu gazu i ld .Jak połączyć program do montażu gazu, który korzysta ze standardowej biblioteki C z ld bez użycia gcc?

Jako zabawne, małe wyzwanie, udało mi się zebrać i połączyć kilka programów powiązanych z różnymi samodzielnie tworzonymi bibliotekami dynamicznymi, ale nie udało mi się zakodować programu od zera, aby korzystać z wywołań funkcji libc bez bezpośredniego korzystania z gcc .

Rozumiem konwencje wywoływania poszczególnych funkcji biblioteki c oraz dokładnie sprawdziłem programy skompilowane z gcc za pomocą obiektów objdump i readelf, ale nie dotarły nigdzie, o ile informacje zawierają się w pliku zespołu gazowego i jakie parametry wywołać w ld, aby pomyślnie połączyć z libc. Ktoś ma wgląd w to?

Używam systemu Linux na maszynie x86.

Odpowiedz

17

Istnieją co najmniej trzy rzeczy, które należy wykonać O powodzeniem używać libc z dynamicznego łączenia:

  1. link /usr/lib/crt1.o, który zawiera _start, która będzie punktem wyjścia do pliku binarnego ELF;
  2. Link /usr/lib/crti.o (przed libc) i /usr/lib/crtn.o (po), które zapewniają pewien kod inicjalizacyjny i końcowy;
  3. Powiedz linkerowi, że plik binarny użyje dynamicznego linkera, /lib/ld-linux.so.

Na przykład:

$ 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! 
$ 
+0

to bardzo pomocne, że wyjaśnia wiele informacji. po zastosowaniu tego do mojego kodu, otrzymuję 2 błędy, "niezdefiniowane odwołanie do" __libc_csu_fini "" i "niezdefiniowane odwołanie do" __libc_csu_init "" po wykonaniu zrzutu symbolu na wszystkich plikach obiektowych, nie udało mi się znaleźć tych symbole i crt1.o wydaje się nazywać symbole. czy jest coś, co może mieć te symbole w ich pliku obiektowym? – Cyro

+0

Te pochodzą z niepochodzącej części biblioteki C; połączenie z '-lc' powinno pociągnąć plik'/usr/lib/libc.so', który jest właściwie fragmentem skryptu linker, który odwołuje się do właściwego pliku ('/ usr/lib/libc_nonshared.a'). Może problem z kolejnością linków? Jestem całkiem pewien, że najpierw chcesz 'crt1.o', po którym następuje' crti.o', potem twoje obiekty i biblioteki, a następnie 'crtn.o' na samym końcu - ale może' -lc' powinno przyjść po twoich obiektach (tuż przed 'crtn.o'), nie wcześniej. –

+0

Połączyłem się z /usr/lib/libc_nonshared.a zaraz po wpisaniu w -lc i wszystko działało! stukrotne dzięki! – Cyro

-1

Myślę, że coś jak to powinno działać:

  1. zrobić prosty program w C
  2. gcc -S file.c
  3. edit file.s
  4. file.s gazu
  5. ld file.o -lc crt1.o -o myprog
2

Jeśli zdefiniujemy main w montażu

odpowiedź Matthew robi wielką pracę z informacją, minimalne wymagania.

Pozwól mi pokazać, jak znaleźć te ścieżki w systemie. Uruchom:

gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n' 

, a następnie podnieś pliki wspomniane przez Matthew.

gcc -v podaje dokładne polecenie łącznika, którego używa GCC.

collect2 jest wewnętrznym wykonywalnym GCC używa jako frontera łączącego, który ma podobny interfejs do ld.

W systemie Ubuntu 14.04 w wersji 64-bitowej (GCC 4.8), skończyło się z:

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 

Można również trzeba -lgcc i -lgcc_s. Zobacz także: Do I really need libgcc?

Jeśli zdefiniujemy _start w montażu

Gdybym zdefiniował _start świat cześć z glibc pracował tylko:

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -lc hello_world.o 

Nie jestem pewien, czy to solidne, tj. jeśli inicjatory crt można bezpiecznie pominąć, aby wywołać funkcje glibc. Zobacz także: Why does an assembly program only work when linked with crt1.o crti.o and crtn.o?

Powiązane problemy