我正在尝试编写一个重量很轻的libc替换库,以便可以更好地了解内核-应用程序接口(interface)。首要任务显然是准备好一些系统调用包装程序。我已经成功地使用了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或没有内容 list 。
(编者注:没有破坏列表是不安全的:您需要告诉编译器RCX和R11被覆盖,并且“内存”应该在系统调用之前处于同步状态,这可能会读取或写入内存。如果您想为特定的系统调用编写特定的包装器,可以有选择地省略"memory"修饰符,或根据参数是该系统调用的指针使用虚拟内存操作数。
如果此_syscall4函数不能内联,则register和"memory"修饰符实际上不会引起任何问题,但是您应该使它们能够内联;与调用非内联包装函数相比,内联此系统调用将在调用站点上花费更少的代码。)

最佳答案

寄存器没有任何限制:%r8 .. %15。但是,更新的版本(如gcc-4.x)应该接受:

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

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

请注意,强制为扩展asm强制选择"r"约束是GCC保证针对register-asm本地用户的唯一行为。诸如register void *rsp asm("rsp");void *stack_pointer = rsp;之类的东西有时可以工作,但不能保证,不建议再使用。

您将希望您的syscall包装器asm语句为volatile并具有"memory" Clobber,除非您使用虚拟内存输入或输出(针对How can I indicate that the memory *pointed* to by an inline ASM argument may be used?)为特定的系统调用编写特定的包装器以知道哪些args是指针

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

(某些特定的系统调用包装器,例如getpid可能是非 volatile 的,因为它们每次都会返回相同的东西,除非您也使用fork。但是getpid如果通过VDSO完成则效率更高,因此不必进入内核首先,如果您使用的是Linux,那么,如果要为getpidclock_gettime创建自定义包装,则您可能首先不希望syscall。请参见The Definitive Guide to Linux System Calls)

之所以需要"memory"破坏器,是因为寄存器中的指针并不意味着指向的存储器也是输入或输出。只需要通过write系统调用读取到缓冲区的存储就不需要像死存储一样进行优化。或者对于munmap,编译器最好在取消映射内存之前完成所有加载/存储。一些系统调用不接受任何指针输入,也不需要"memory",但是通用包装必须做出最坏的假设。
register ... asm("r10")通常不需要asm volatile"memory"修饰符,但是syscall包装器需要。

关于在gcc内联x86_64程序集中约束r10寄存器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15997759/

10-15 12:20