Wie ein Gasmontage Programm zu verknüpfen, die die C-Standardbibliothek mit ld verwendet, ohne Verwendung von gcc?
Frage
Als Übung genauer zu erfahren, wie c-Programme funktionieren und was Mindestmaß an Inhalt für ein Programm existieren muss in der Lage sein, libc zu verwenden, ich habe es auf mich genommen, um Programm zu versuchen, in erster Linie in x86-Assembler Gas und ld.
Als wenig Spaß Herausforderung, habe ich erfolgreich zusammengebaut und mehrere Programme im Zusammenhang mit verschiedenen selbstgemachten verknüpft dynamischen Bibliotheken, aber ich habe versagt ein Programm von Grund auf neu Code in der Lage sein zu verwenden libc Funktionsaufrufe ohne gcc direkt zu verwenden.
Ich verstehe die Aufrufkonventionen der einzelnen C-Bibliotheksfunktionen und gründlich Programme von gcc zusammengestellt aus durch die Verwendung von objdump und readelf kontrolliert, aber nicht überall so weit wie welche Informationen bekam in einer Gasbaugruppendatei aufzunehmen und was Parameter in ld erfolgreich Link zu libc aufzurufen. Wer noch keine Einsicht dazu?
Ich bin mit Linux, auf einem x86-Computer.
Lösung
Es gibt mindestens drei Dinge, die Sie erfolgreich tun müssen, um verwenden libc mit dynamischer Verknüpfung:
- Link
/usr/lib/crt1.o
, die_start
enthält, die der Einstiegspunkt für den ELF-Binaries sein wird; - Link
/usr/lib/crti.o
(vor libc) und/usr/lib/crtn.o
(nach), die eine Initialisierung und Finalisierung Code bereitzustellen; - Sagen Sie den Linker, dass die binäre den dynamischen Linker verwenden,
/lib/ld-linux.so
.
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!
$
Andere Tipps
Wenn Sie definieren main
in der Montage
Matthew Antwort hat eine große Aufgabe, um die Mindestanforderungen zu erzählen.
Lassen Sie mich Ihnen zeigen, wie wie diese Pfade in Ihrem System zu finden. Führen Sie:
gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n'
und dann die Dateien abholen Matthew erwähnt.
gcc -v
gibt Ihnen die genauen Linker Befehl GCC Anwendungen.
collect2 ist die internen ausführbaren GCC Anwendungen 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
Sie können auch -lgcc
und -lgcc_s
braucht. Siehe auch: brauche ich wirklich libgcc
Wenn Sie definieren _start
in der Montage
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 sicher nicht, ob das robust ist, das heißt, wenn die crt
Initialisierungen sicher übersprungen werden glibc Funktionen aufzurufen. Siehe auch: Warum funktioniert ein Assembler-Programm nur, wenn sie mit crt1.o crti.o und crtn.o verknüpft?
Wenn Sie _start
tun statt main
(wie in einigen der Kommentare oben erwähnt), werden Sie auch das Programm beendet die Art und Weise ändern müssen, oder du wirst eine seg Fehler bekommen:
.text
.globl _start
_start:
mov $hw_str, %rdi
call puts
movl $0,%ebx # first argument: exit code.
movl $1,%eax # system call number: sys_exit.
int $0x80 # call kernel.
.data
hw_str: .asciz "Hello world!"
Auf Kubuntu 18.04.2 (gcc (Ubuntu 7.3.0-27ubuntu1 ~ 18.04) 7.3.0):
$ as -o hello.o hello.s
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o hello hello.o -lc
Auch eine einfache Möglichkeit, um herauszufinden, was der dynamische Linker auf Ihrem System ist ein kleines C-Programm zu kompilieren und dann ldd
auf dem binären laufen:
test.c:
int main() { return 0; }
Kompilieren und Ausführen LDD gegen ausführbar:
$ gcc -o test test.c
$ ldd test
linux-vdso.so.1 (0x00007ffd0a182000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff24d8e6000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff24ded9000)
Ich denke, so etwas wie dies funktionieren soll:
- ein einfaches C-Programm machen
- gcc -S file.c
- bearbeiten file.s
- Gas file.s
- ld file.o -lc crt1.o -o myprog