【问题标题】:Registers used by exec() system call argumentsexec() 系统调用参数使用的寄存器
【发布时间】:2013-01-18 14:16:20
【问题描述】:

我想知道 exec() 系统调用参数存储在哪些寄存器中。

我首先运行了一个简单的 C 程序,该程序执行 exec 系统调用并获取其对象转储,发现 RDI 被用于包含要执行的进程的参数,并且 syscall 指令被用于在内核中调用 execve .我是在 64 位 Ubuntu 12.04 操作系统中完成的

然后我在 QEMU 上运行的 Ubuntu 11.10 OS(32 位)上运行了这个程序。但是现在在对象转储中断中没有使用 0x80,并且参数在 EBX 中。

我在两个方面感到困惑..为什么 int80 在一个地方使用而 syscall 在另一个地方使用,以及如何选择 execve 系统调用的寄存器?

【问题讨论】:

    标签: x86 system-calls execve


    【解决方案1】:

    您看到的是,不同的芯片架构在向正在运行的操作系统发出服务请求时使用不同的系统调用约定。这些约定是操作系统定义的ABI(应用程序二进制接口)的一部分——ABI 定义的其他内容包括:

    • 用于将参数传递给函数的寄存器(和/或堆栈布局)

    • 注册函数可以用作暂存空间,而返回时必须恢复到以前的值

    • 处理器地址空间内程序的(虚拟)内存布局

    请记住,尽管它们通常都由同一个物理处理器支持(出于向后兼容性的原因),但英特尔 64 位 (IA64) 和 32 位 (IA32) 架构仍然是独立的,具有不同的(如果重叠)寄存器可用,并且使用不同的 ABI。正如您所注意到的,这两个 ABI 在系统调用的参数位置以及向内核发出系统调用的信号方面都不同。

    如今,操作系统 ABI 通常由提供特定芯片架构的公司定义(至少作为建议),因此在给定架构上运行的所有(或大多数)操作系统通常都提供相同的 ABI,但情况并非总是如此 - 仍然可以找到在完全相同的硬件上运行的不同操作系统之间的类型差异。

    【讨论】:

    • 好的,我明白了。但是为什么 64 位的 EAX(包含系统调用号)的值是 59,而 32 位的值是 11?毕竟两者都运行相似的内核。
    • 不幸的是,在 Linux 上,系统调用号到系统调用的映射对于每个体系结构都是不同的——如果我不得不猜测,我猜这是许多Linux 到不同处理器类型的端口开始作为独立项目,但我不知道。作为一个比较点,BSD Unix 传统上维护一个供所有部分使用的单一系统调用映射。
    • 您可以通过在运行该架构的主机上查看/usr/include/asm/unistd.h 来找到给定 Linux 架构的系统调用映射。作为例外,在 Intel 主机上,IA32 和 IA64 标头都安装在 /usr/include/asm-i386/usr/include/x86_64 中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-15
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    相关资源
    最近更新 更多