Реализация функции execve (unistd.h)

Как посмотреть реализацию функции execve (под x86_64 Linux), она есть в библиотеке unistd? Я хочу этого, потому что хочу знать, как я могу вызвать внешнюю программу с помощью ассемблера, не вызывая execve. Я знаю, что есть системный вызов execve, но не знаю, как его использовать.

Как я могу поместить переменную типа char * и тип char * [] в регистры?


person dv1729    schedule 11.09.2011    source источник


Ответы (3)


Реализация функции execve() в пользовательском пространстве выглядит примерно так:

int execve(const char *filename, char * const argv[], char * const envp[]) {
    return syscall(SYS_execve, filename, argv, envp);
}

Вся фактическая «работа» выполняется в ядре. В libc не происходит ничего особенно интересного, кроме, возможно, некоторой очистки потоков.

person Community    schedule 11.09.2011
comment
Всем спасибо, а как мне поставить переменную типа char* и типа char*[] в регистры?, я знаю только как сделать системный вызов записи и выхода, например, когда я делаю системный вызов записи, я должен поместите указатель в регистр, а размер буфера в другой, но как мне это сделать сейчас? - person dv1729; 12.09.2011
comment
Не отличается от предыдущего — поместите указатели на имя файла, массив аргументов и массив окружения в три регистра. Последние два должны быть просто указателями на начало массивов char *, заканчивающихся NULL. - person ; 12.09.2011

Просто взгляните на исходники ядра (точнее: arch/YOUR-ARCH/kernel/head*.S) на наличие соглашения о системных вызовах для вашей архитектуры (регистры и/или стек для номера системного вызова и параметров).

Например, в ARM вы должны загрузить __NR_execve в r7, загрузить аргументы в r0, r1, r2, а затем использовать swi 0. Возможно, вас заинтересует это объяснение системных вызовов ARM EABI для получения более подробной информации.

person Mircea    schedule 12.09.2011

В исходном коде glibc нет реальной прямой реализации системных вызовов — они генерируются во время сборки из различных файлов, определяющих номера системных вызовов.

Соответствующую информацию можно найти в sysdep.h, если вы его понимаете, за исключением собственно номеров системных вызовов (вы хотите __NR_execve with, IIRC, #include <asm/unistd.h> - не могу навскидку вспомнить, что это такое на x86_64).

Номер системного вызова указывается в %rax, а аргументы — в %rdi %rsi %rdx. Вся эта информация (включая выравнивание стека и кое-что об использовании регистров ядром) прокомментирована в sysdep.h.

person Random832    schedule 12.09.2011