如何查看函数 execve 的实现(在 x86_64 Linux 下),它在库 unistd 中?我想要这个,因为我想知道如何使用汇编程序调用外部程序,而不调用 execve。我知道有一个名为 execve 的系统调用,但我不知道如何使用它。
如何将 char * 类型和 char * [] 类型的变量放入寄存器?
如何查看函数 execve 的实现(在 x86_64 Linux 下),它在库 unistd 中?我想要这个,因为我想知道如何使用汇编程序调用外部程序,而不调用 execve。我知道有一个名为 execve 的系统调用,但我不知道如何使用它。
如何将 char * 类型和 char * [] 类型的变量放入寄存器?
用户空间中函数的实现execve()
类似于:
int execve(const char *filename, char * const argv[], char * const envp[]) {
return syscall(SYS_execve, filename, argv, envp);
}
所有实际的“工作”都在内核中完成。除了一些线程清理之外,libc 中没有什么特别有趣的事情发生。
只需查看内核源代码(更具体地说:arch/YOUR-ARCH/kernel/head*.S),了解体系结构上的系统调用约定(系统调用编号和参数的寄存器和/或堆栈)。
例如,在 ARM 上,您将加载__NR_execve
到 r7,将参数加载到 r0、r1、r2,然后使用swi 0
. 您可能对ARM EABI 系统调用的这种解释感兴趣,以了解更多详细信息。
在 glibc 的源代码中没有真正直接的系统调用实现 - 这是在构建时从定义系统调用号的各种文件生成的。
如果您了解相关信息,可以在sysdep.h中找到,但实际的系统调用号除外(您想要__NR_execve
使用 IIRC,#include <asm/unistd.h>
-我不记得它在 x86_64 上的内容)。
系统调用号在 %rax 中,参数在 %rdi %rsi %rdx 中。所有这些信息(包括堆栈对齐和内核使用的寄存器)都在 sysdep.h 中进行了注释。