Это зависит от того, использует ли ваша реализация интерфейс C для низкоуровневых утилит или нет.
Если ваша языковая реализация дает прямой доступ к системным вызовам, минуя оболочку C, вам не нужно использовать VDSO (например, вы можете сгенерировать соответствующую машинную инструкцию SYSENTER для выполнения системного вызова), но вы можете решите использовать VDSO, а затем воспользуйтесь этим. В этом случае вашему языку даже не нужно следовать всем соглашениям ABI, а только соглашениям ядра. (например, вам не нужен ABI, предоставляющий caller-safe calle-safe distinguo для регистров, и вы даже можете избежать использования каких-либо стеков).
Примером языковой реализации, даже не использующей libc.so, является Bones Scheme. Вы можете найти несколько других.
Мое понимание VDSO заключается в том, что это абстракция, предоставляемая ядром, чтобы абстрагироваться от различных небольших различий (связанных с переходами между пользователем и ядром) в реализации системных вызовов между различными семействами процессоров x86. Если вы выбрали конкретную цель процессора, вам не нужен VDSO, и вы всегда можете его избежать.
AFAIU, VDSO — это общий объект ELF, расположенный (на моем Debian/AMD64 с недавно скомпилированным ядром 3.8.3) в сегменте ffffffffff600000-ffffffffff601000; проверьте точно с cat /proc/self/maps где он находится). Так что вам просто нужно понять организацию общих объектов ELF и извлечь из них символы. См. это и который ссылается. VDSO использует соглашения C для вызовов, задокументированные в спецификации x86-64 ABI.
То есть, если вы извлечете из пространства вашего процесса VDSO и запишете его в файл на диске, результатом будет правильно сформированный общий объект ELF
ELF — это хорошо задокументированный формат. Таковы и соглашения ABI x86-64 (которые точно определяют соглашения о вызовах C, и как именно запускается образ процесса. См. также execve(2)) справочная страница и, конечно же, документация по ядру, поэтому я не понимаю, в чем ваша проблема. Я согласен, что понимание ELF требует времени (я делал это 10 лет назад, но моя память заржавела). Прочтите также заголовочный файл <elf.h> на вашем компьютере.
Например; работает (под zsh на 64-битном 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]
См. также этот ответ.
Вероятно, вы хотите, чтобы в вашей среде выполнения была минимальная версия динамического компоновщика, способная просто анализировать VDSO. Вы, конечно, хотите понять, в каком именно состоянии запускается процесс, и в частности роль auxv, вспомогательного вектора (эти подробности я действительно забываю, но помню, что они важны). См., например. эта статья
На самом деле, надежный запуск вашей среды выполнения, вероятно, сложнее, чем проблема с VDSO.
Вы также можете прочитать инструкцию по сборке Linux, которая также объясняет некоторые вещи ( но больше про х86 чем х86-64)
Кстати, код http://musl-libc.org/ (который является альтернативой libc) намного легче читать и понимать (и вы легко узнаете, как они делают динамическую компоновку, pthreads и т.д..)
person
Basile Starynkevitch
schedule
24.03.2013