9

我正在尝试编写一个非常轻量级的 libc 替换库,以便更好地理解内核 - 应用程序接口。第一个任务显然是让一些系统调用包装器到位。我已经成功地让 1 到 3 个参数包装器工作,但我正在努力处理 4 个参数变量。这是我的出发点:

long _syscall4(long type, long a1, long a2, long a3, long a4)
{
    long ret;
    asm
    (
        "syscall"
        : "=a"(ret)    // return value
        : "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
        : "c", "r11", "memory"  // some syscalls read or write memory
                   // the syscall insn instruction itself destroys RCX and R11
    );
    return ret;
}

(编者注:这是安全且可用的,并且是一个很好的例子,在应用答案的方式来处理之后r10。MUSL libc 有一些类似的宏。)

编译器给我以下错误:

error: matching constraint references invalid operand number

我的 _syscall3 函数工作正常,但不使用 r10 或有一个clobber 列表。

(编者注:没有clobber列表是不安全的:您需要告诉编译器RCX和R11被覆盖,并且“内存”应该在可能读取或写入内存的系统调用之前同步。如果如果您想为特定的系统调用编写特定的包装器,您可以有选择地省略"memory"clobbers,或者根据哪些参数是该系统调用的指针来使用虚拟内存操作数。

如果这个_syscall4函数不能内联,寄存器和"memory"clobbers实际上不会造成任何问题,但你应该让它们能够内联;与调用非内联包装函数相比,内联此系统调用在调用站点需要的代码更少。)

4

2 回答 2

9

寄存器没有限制:%r8... %15但是,最近的(如 gcc-4.x 中)应该接受:

register long r10 asm("r10") = a4;

然后使用输入约束:"r" (r10)为您的 asm 语句。
https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html


请注意,强制"r"为 Extended asm 选择约束是GCC 为 register-asm locals 保证的唯一行为。喜欢register void *rsp asm("rsp");void *stack_pointer = rsp;做的事情有时会起作用,但不能保证也不推荐。


您将希望您的系统调用包装器asm语句成为volatile并拥有一个"memory"clobber,除非您使用虚拟内存输入或输出为特定系统调用编写特定包装器以了解哪些参数是指针(根据我如何指示内存可以使用 *pointed* 由内联 ASM 参数指向的?

它需要volatile因为doingwrite(1, buf, 16)应该打印两次缓冲区,而不仅仅是CSE返回值!系统调用通常不是其输入的纯函数,因此您需要volatile.

(某些特定的系统调用包装器getpid可能是非易失性的,因为它们每次都会返回相同的东西,除非您也使用 fork。但是getpid如果通过 VDSO 完成则效率更高,因此不必在如果您在 Linux 上,则放在首位,因此,如果您正在为其制作自定义包装器,getpid并且clock_gettime您可能一开始就不想要syscall。请参阅Linux 系统调用权威指南

之所以"memory"需要clobber,是因为寄存器中的指针并不意味着指向的内存也是输入或输出。仅由write系统调用读取的缓冲区存储不需要作为死存储进行优化。或者对于,编译器最好在内存未映射之前munmap完成任何加载/存储。一些系统调用不接受任何指针输入,也不需要,但通用包装器必须做出最坏情况的假设。"memory"

register ... asm("r10")通常不需要或破坏,系统调用包装器需要。asm volatile"memory"

于 2013-04-14T23:37:12.353 回答
0

大概是因为没有指令对寄存器有特定要求r10,gcc 人员没有为它创建约束(假设约束主要用于机器描述)。如果您坚持使用内联汇编,我认为您不能比使用通用"r"(或"m")约束并进入r10自己(并将其添加到clobber 列表)做得更好。

于 2013-04-14T19:03:56.373 回答