Es hängt davon ab, ob Ihre Implementierung C verwendet Schnittstelle für Low-Level-Dienstprogramme oder nicht.
Wenn Ihre Sprachimplementierung direkten Zugriff auf Systemaufrufe gewährt, ohne über C zu gehen Wrapper müssen Sie VDSO nicht verwenden (Sie könnten beispielsweise den entsprechenden SYSENTER
generieren Maschinenanweisung, um den Syscall auszuführen), aber Sie könnten sich entscheiden, VDSO zu verwenden und es dann zu nutzen. In diesem Fall muss Ihre Sprache nicht einmal alle ABI-Konventionen befolgen, sondern nur die Konventionen des Kernels. (Zum Beispiel benötigen Sie nicht die von ABI bereitgestellte caller-safe calle-safe distinguo auf Registern, und Sie könnten sogar die Verwendung von Stacks vermeiden).
Ein Beispiel für eine Sprachimplementierung, die nicht einmal libc.so
verwendet ist Bones Scheme. Du könntest noch ein paar andere finden.
Mein Verständnis des VDSO ist, dass es eine vom Kernel bereitgestellte Abstraktion ist, um die verschiedenen kleinen Unterschiede (im Zusammenhang mit Benutzerland -> Kernel-Übergängen) bei der Implementierung von Systemaufrufen zwischen verschiedenen Familien von x86-Prozessoren zu abstrahieren. Wenn Sie sich für ein bestimmtes Prozessorziel entschieden haben, benötigen Sie VDSO nicht und können es jederzeit vermeiden.
AFAIU, das VDSO ist ein gemeinsames ELF-Objekt, das (auf meinem Debian/AMD64 mit einem kürzlich kompilierten 3.8.3-Kernel) im Segment ffffffffff600000-ffffffffff601000
sitzt; genau prüfen mit cat /proc/self/maps
wo ist es). Sie müssen also nur die Organisation von gemeinsam genutzten ELF-Objekten verstehen und die Symbole daraus abrufen. Siehe dies-und-das-Links. Der VDSO verwendet die C-Konventionen zum Aufrufen, die in der x86-64-ABI-Spezifikation dokumentiert sind.
ELF ist ein gut dokumentiertes Format. Und das gilt auch für die x86-64-ABI-Konventionen (die genau die C-Aufrufkonventionen definieren und wie genau das Image eines Prozesses beginnt. Siehe auch die Manpage execve(2)) und natürlich die Kernel-Dokumentation, also verstehe ich das nicht Was ist dein Problem. Ich stimme zu, dass es Zeit braucht, ELF zu verstehen (ich habe das vor 10 Jahren gemacht, aber mein Gedächtnis ist eingerostet). Lesen Sie auch <elf.h>
Header-Datei auf Ihrem Rechner.
Zum Beispiel; läuft (unter zsh
auf 64-Bit-Debian x86-64)
% file $(which sash)
/bin/sash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
statically linked, for GNU/Linux 2.6.26,
BuildID[sha1]=0x0347fcc08fba2f811f58af99f26111d0f579a9f6, stripped
% ldd $(which sash)
not a dynamic executable
% sash
Stand-alone shell (version 3.7)
> ps |grep sash
21635 pts/3 00:00:00 sash
> cat /proc/21635/maps
00400000-004da000 r-xp 00000000 08:01 4985590 /bin/sash
006da000-006dc000 rw-p 000da000 08:01 4985590 /bin/sash
006dc000-006e1000 rw-p 00000000 00:00 0
017e3000-01806000 rw-p 00000000 00:00 0 [heap]
7fe4950e5000-7fe4950e7000 rw-p 00000000 00:00 0
7fff3f130000-7fff3f151000 rw-p 00000000 00:00 0 [stack]
7fff3f173000-7fff3f175000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Siehe auch diese Antwort.
Sie möchten wahrscheinlich in Ihrer Laufzeit eine minimale Version eines dynamischen Linkers, der in der Lage ist, das VDSO einfach zu analysieren. Sie möchten sicherlich den genauen Zustand verstehen, in dem ein Prozess gestartet wird, und insbesondere die Rolle von auxv
, der Hilfsvektor (ich habe diese Details wirklich vergessen, aber ich erinnere mich, dass sie wichtig sind). Siehe z.B. diesen Artikel
Tatsächlich ist das zuverlässige Starten Ihrer Laufzeit wahrscheinlich schwieriger als das VDSO-Problem.
Vielleicht möchten Sie auch das Linux-Assembler-Howto lesen, das auch einige Dinge erklärt (aber mehr über x86 als über x86-64)
Übrigens, der Code von http://musl-libc.org/ (das eine alternative libc ist) ist viel einfacher zu lesen und zu verstehen (und Sie werden leicht lernen, wie sie dynamisches Linken, Pthreads usw. machen.)
Ich fand diese Dateien im Linux-Kernelbaum hilfreich:
Documentation/ABI/stable/vdso
(Was ist das vDSO-Objekt?)Documentation/vDSO/parse_vdso.c
(Referenzparser für das vDSO-Objekt)
Das vDSO-Objekt ist ein virtuelles dynamisches gemeinsam genutztes Objekt, das unter Linux immer in den Adressraum eines amd64-Prozesses abgebildet wird. Es kann verwendet werden, um schnelle Systemaufrufe zu implementieren. Um auf die Funktionen innerhalb des vDSO-Objekts zuzugreifen, müssen Sie
- Suche das Objekt
- eine Adresse aus der Symboltabelle extrahieren
Beides lässt sich mit der CC0-lizenzierten Referenzimplementierung parse_vdso.c erledigen.