Záleží, zda vaše implementace používá C rozhraní pro nízkoúrovňové nástroje nebo ne.
Pokud vaše jazyková implementace poskytuje přímý přístup k systémovým voláním, aniž byste museli procházet C wrapper nemusíte používat VDSO (můžete například vygenerovat příslušný SYSENTER
strojové instrukce k provedení syscall), ale můžete se rozhodnout použít VDSO a poté jej využít. V takovém případě váš jazyk ani nemusí dodržovat všechny konvence ABI, stačí konvence jádra. (Například nepotřebujete v registrech distinguo caller-safe-safe, které poskytuje ABI, a dokonce se můžete vyhnout použití jakýchkoli zásobníků).
Příklad implementace jazyka ani pomocí libc.so
je Bones Scheme. Mohli byste najít několik dalších.
VDSO chápu tak, že jde o abstrakci poskytovanou jádrem k abstrahování různých malých rozdílů (souvisejících s přechody mezi uživatelskou zemí -> jádrem) v implementaci systémových volání mezi různými rodinami procesorů x86. Pokud jste si vybrali konkrétní cílový procesor, nepotřebujete VDSO a vždy se mu můžete vyhnout.
AFAIU, VDSO je sdílený objekt ELF, sedící (na mém Debianu/AMD64 s nedávno zkompilovaným jádrem 3.8.3) v segmentu ffffffffff600000-ffffffffff601000
; zkontrolujte přesně pomocí cat /proc/self/maps
kde to je). Stačí tedy porozumět organizaci sdílených objektů ELF a získat z ní symboly. Viz tento a tamto odkaz. VDSO používá C konvence pro volání zdokumentované ve specifikaci x86-64 ABI.
ELF je dobře zdokumentovaný formát. A stejně tak i x86-64 konvence ABI (které přesně definují konvence C volání a jak přesně začíná obraz procesu. Viz také manuálová stránka execve(2)) a samozřejmě dokumentace jádra, takže nerozumím jaký je váš problém. Souhlasím, že pochopení ELF vyžaduje čas (udělal jsem to před 10 lety, ale moje paměť je rezavá). Přečtěte si také <elf.h>
hlavičkový soubor na vašem počítači.
Například; běžící (pod zsh
na 64bitovém Debianu 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]
Viz také tato odpověď.
Pravděpodobně budete chtít ve svém běhovém prostředí minimální verzi dynamického linkeru schopného jednoduše analyzovat VDSO. Určitě chcete pochopit přesný stav, ve kterém je proces spuštěn, a zejména roli auxv
, pomocný vektor (na tyto detaily opravdu zapomínám, ale pamatuji si, že jsou důležité). Viz např. tento článek
Ve skutečnosti je spolehlivé spuštění runtime pravděpodobně těžší než problém VDSO.
Můžete si také přečíst návod na sestavení linuxu, který také vysvětluje některé věci (ale více o x86 než x86-64)
BTW, kód http://musl-libc.org/ (což je alternativní knihovna libc) je mnohem snazší číst a pochopit (a snadno se naučíte, jak dělají dynamické odkazy, pthreads atd..)
Tyto soubory ve stromu jádra Linuxu mi pomohly:
Documentation/ABI/stable/vdso
(co je objekt vDSO?)Documentation/vDSO/parse_vdso.c
(Referenční analyzátor pro objekt vDSO)
Objekt vDSO je virtuální dynamický sdílený objekt, který je vždy mapován do adresního prostoru procesu amd64 pod linuxem. Lze jej použít k implementaci rychlých systémových volání. Pro přístup k funkcím uvnitř objektu vDSO potřebujete
- najděte objekt
- extrahujte adresu z tabulky symbolů
Obě věci lze provést pomocí licencované referenční implementace CC0 parse_vdso.c.