2010-08-26 4 views
13

Als eine Übung, um genauer zu lernen, wie c Programme funktionieren und welche minimale Ebene des Inhalts muss für ein Programm vorhanden sein, um libc verwenden zu können, habe ich es auf mich genommen zu versuchen, in erster Linie in x86 Assembly mit Gas und ld zu programmieren .Wie wird ein Gas-Assembly-Programm, das die C-Standard-Bibliothek verwendet, mit ld verknüpft, ohne gcc zu verwenden?

Als eine lustige kleine Herausforderung, habe ich erfolgreich mehrere Programme zusammengestellt und verknüpft mit verschiedenen selbst erstellten dynamischen Bibliotheken, aber ich konnte nicht ein Programm von Grund auf neu zu combusieren, um libc Funktionsaufrufe zu verwenden, ohne gcc direkt zu verwenden .

Ich verstehe die Aufrufkonventionen der einzelnen c-Bibliotheksfunktionen, und gründlich geprüft Programme aus gcc durch Verwendung von objdump und readelf kompiliert, aber sind nicht soweit, was Informationen in eine Gas-Assembly-Datei und enthalten Welche Parameter rufen in ld auf, um erfolgreich mit libc zu verknüpfen. Hat jemand einen Einblick darauf?

Ich verwende Linux, auf einer x86-Maschine.

Antwort

17

Es gibt mindestens drei Dinge, die Sie t tun müssen o erfolgreich libc mit dynamischer Verknüpfung:

  1. Link-/usr/lib/crt1.o, die _start enthält, die der Einstiegspunkt für den ELF-Binaries sein wird;
  2. Link /usr/lib/crti.o (vor libc) und /usr/lib/crtn.o (nach), die einige Initialisierung und Finalisierung Code bieten;
  3. Sagen Sie dem Linker, dass die Binärdatei den dynamischen Linker /lib/ld-linux.so verwenden wird.

Zum Beispiel:

$ 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

das ist sehr hilfreich, das eine Menge Informationen verdeutlicht. wenn ich das auf meinen Code anwende, bekomme ich 2 Fehler, "undefinierter Verweis auf '__libc_csu_fini'" und "undefinierter Verweis auf '__libc_csu_init'" nachdem ich einen Symbol-Dump auf allen Objektdateien gemacht habe, konnte ich diese nicht finden Symbole, und crt1.o scheint die Symbole zu nennen. Gibt es irgendetwas, das diese Symbole möglicherweise in ihrer Objektdatei enthalten könnte? – Cyro

+0

Diese stammen aus einem nicht freigegebenen Teil der C-Bibliothek; Die Verknüpfung mit '-lc' sollte'/usr/lib/libc.so' enthalten, was eigentlich ein Linker-Skript-Fragment ist, das auf die richtige Datei verweist ('/ usr/lib/libc_nonshared.a'). Vielleicht ein Problem mit der Linkreihenfolge? Ich bin mir ziemlich sicher, dass Sie zuerst 'crt1.o' gefolgt von' crti.o' wollen, dann Ihre Objekte und Bibliotheken, dann 'crtn.o' direkt am Ende - aber vielleicht sollte' -lc' nach Ihren Objekten kommen (kurz vor 'crtn.o'), nicht vorher. –

+0

Ich ging weiter und verband einfach mit /usr/lib/libc_nonshared.a direkt nach der Eingabe in -lc und das Ganze hat funktioniert! tausend Dank! – Cyro

-1

Ich denke, so etwas wie dies funktionieren sollte:

  1. ein einfaches C-Programm
  2. gcc -S file.c
  3. bearbeiten file.s
  4. Gas file.s
  5. ld machen file.o -lc crt1.o -o myprog
2

Wenn Sie main in der Montage

Matthew Antwort definieren hat eine große Aufgabe, um die Mindestanforderungen zu erzählen.

Lassen Sie mich Ihnen zeigen, wie Sie diese Pfade in Ihrem System finden. Run:

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

und dann holen Sie sich die Dateien Matthew erwähnt.

gcc -v gibt Ihnen den genauen Linker-Befehl, den GCC verwendet.

collect2 ist die interne ausführbare GCC verwendet als Linker Front-End, die eine ähnliche Schnittstelle zu ld hat.

In Ubuntu 14.04 64-Bit (GCC 4.8), landete ich mit:

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 

könnten Sie auch benötigen -lgcc und -lgcc_s. Siehe auch: Do I really need libgcc?

Wenn Sie _start in der Montage definieren

Wenn ich die _start definiert, arbeitete die Hallo Welt von glibc mit nur:

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

Ich bin nicht sicher, ob dies robust, dh wenn die crt Initialisierungen sicher übersprungen werden können, um glibc-Funktionen aufzurufen. Siehe auch: Why does an assembly program only work when linked with crt1.o crti.o and crtn.o?

Verwandte Themen