It depends on whether your implementation uses the C interface for low-level utilities or not.
If your language provides direct access to system calls without going through the C shell, you do not need to use VDSO (for example, you can generate the appropriate SYSENTER statement to make a system call), but you can decide to use VDSO and then use this. In this case, your the language does not even need to follow all ABI conventions, only kernel conventions. (for example, you do not need the ABI to provide calle-safe caller-safe case distinction, and you could even avoid using any stacks).
My understanding of VDSO is that it is an abstraction provided by the kernel to abstract away from various small differences (associated with user-land β transitions in the kernel) when implementing system calls between different x86 processor families. If you have chosen a specific processor target, you do not need VDSO, and you can always avoid this.
AFAIU, VDSO is a common ELF object located (on my Debian / AMD64 with the recently compiled kernel 3.8.3) in the ffffffffff600000-ffffffffff601000 ; check exactly with cat/proc/self/maps where it is located). So you just need to understand the organization of common ELF objects and extract characters from them. See this and these links. VDSO uses the C conventions for calls described in the ABI x86-64 specification.
That is, if you extract VDSO processes from your space and write it to a file on disk, the result is a properly formed common ELF object.
ELF is a well-documented format. As well as the x86-64 ABI conventions (which pinpoint the C calling conventions and how the process image starts. See also the execve (2) manual page) and, of course, the kernel documentation, so I donβt understand what your problem is I agree that understanding ELF takes time (I did it 10 years ago, but my memory is rusty). Also read the <elf.h> header file on your computer.
For instance; works (under zsh on 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]
See also this answer .
You will probably want at runtime a minimal version of a dynamic linker that can simply parse VDSO. Of course, you want to understand the exact state in which the process is running, and, in particular, the role of the auxiliary vector auxv (I really forget these details, but I remember that they are important). See, for example, this article.
In fact, running your runtime environment reliably is probably harder than the VDSO issue.
You can also read the Linux build guide , which also explains some things (but more about x86 than x86-64)
By the way, the code http://musl-libc.org/ (which is an alternative to libc) is much easier to read and understand (and you will easily learn how they perform dynamic linking, pthreads, etc.)