📄 linux_syscall_support.h
字号:
#define LSS_ERRNO errno #endif #undef LSS_INLINE #ifdef SYS_INLINE #define LSS_INLINE SYS_INLINE #else #define LSS_INLINE static inline #endif /* Allow the including file to override the prefix used for all new * system calls. By default, it will be set to "sys_". */ #undef LSS_NAME #ifndef SYS_PREFIX #define LSS_NAME(name) sys_##name #elif SYS_PREFIX < 0 #define LSS_NAME(name) name #elif SYS_PREFIX == 0 #define LSS_NAME(name) sys0_##name #elif SYS_PREFIX == 1 #define LSS_NAME(name) sys1_##name #elif SYS_PREFIX == 2 #define LSS_NAME(name) sys2_##name #elif SYS_PREFIX == 3 #define LSS_NAME(name) sys3_##name #elif SYS_PREFIX == 4 #define LSS_NAME(name) sys4_##name #elif SYS_PREFIX == 5 #define LSS_NAME(name) sys5_##name #elif SYS_PREFIX == 6 #define LSS_NAME(name) sys6_##name #elif SYS_PREFIX == 7 #define LSS_NAME(name) sys7_##name #elif SYS_PREFIX == 8 #define LSS_NAME(name) sys8_##name #elif SYS_PREFIX == 9 #define LSS_NAME(name) sys9_##name #endif #undef LSS_RETURN #define LSS_RETURN(type, res) \ do { \ if ((unsigned long)(res) >= (unsigned long)(-4095)) { \ LSS_ERRNO = -(res); \ res = -1; \ } \ return (type) (res); \ } while (0) #if defined(__i386__) /* In PIC mode (e.g. when building shared libraries), gcc for i386 * reserves ebx. Unfortunately, most distribution ship with implementations * of _syscallX() which clobber ebx. * Also, most definitions of _syscallX() neglect to mark "memory" as being * clobbered. This causes problems with compilers, that do a better job * at optimizing across __asm__ calls. * So, we just have to redefine all of the _syscallX() macros. */ #undef LSS_BODY #define LSS_BODY(type,args...) \ long __res; \ __asm__ __volatile__("push %%ebx\n" \ "movl %2,%%ebx\n" \ "int $0x80\n" \ "pop %%ebx" \ args \ : "memory"); \ LSS_RETURN(type,__res) #undef _syscall0 #define _syscall0(type,name) \ type LSS_NAME(name)(void) { \ long __res; \ __asm__ volatile("int $0x80" \ : "=a" (__res) \ : "0" (__NR_##name) \ : "memory"); \ LSS_RETURN(type,__res); \ } #undef _syscall1 #define _syscall1(type,name,type1,arg1) \ type LSS_NAME(name)(type1 arg1) { \ LSS_BODY(type, \ : "=a" (__res) \ : "0" (__NR_##name), "ri" ((long)(arg1))); \ } #undef _syscall2 #define _syscall2(type,name,type1,arg1,type2,arg2) \ type LSS_NAME(name)(type1 arg1,type2 arg2) { \ LSS_BODY(type, \ : "=a" (__res) \ : "0" (__NR_##name),"ri" ((long)(arg1)), "c" ((long)(arg2))); \ } #undef _syscall3 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type LSS_NAME(name)(type1 arg1,type2 arg2,type3 arg3) { \ LSS_BODY(type, \ : "=a" (__res) \ : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ "d" ((long)(arg3))); \ } #undef _syscall4 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ LSS_BODY(type, \ : "=a" (__res) \ : "0" (__NR_##name), "ri" ((long)(arg1)), "c" ((long)(arg2)), \ "d" ((long)(arg3)),"S" ((long)(arg4))); \ } #undef _syscall5 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5) \ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ type5 arg5) { \ long __res; \ __asm__ __volatile__("push %%ebx\n" \ "movl %2,%%ebx\n" \ "movl %1,%%eax\n" \ "int $0x80\n" \ "pop %%ebx" \ : "=a" (__res) \ : "i" (__NR_##name), "ri" ((long)(arg1)), \ "c" ((long)(arg2)), "d" ((long)(arg3)), \ "S" ((long)(arg4)), "D" ((long)(arg5)) \ : "memory"); \ LSS_RETURN(type,__res); \ } #undef _syscall6 #define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5,type6,arg6) \ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \ type5 arg5, type6 arg6) { \ long __res; \ struct { long __a1; long __a6; } __s = { (long)arg1, (long) arg6 }; \ __asm__ __volatile__("push %%ebp\n" \ "push %%ebx\n" \ "movl 4(%2),%%ebp\n" \ "movl 0(%2), %%ebx\n" \ "movl %1,%%eax\n" \ "int $0x80\n" \ "pop %%ebx\n" \ "pop %%ebp" \ : "=a" (__res) \ : "i" (__NR_##name), "0" ((long)(&__s)), \ "c" ((long)(arg2)), "d" ((long)(arg3)), \ "S" ((long)(arg4)), "D" ((long)(arg5)) \ : "memory"); \ LSS_RETURN(type,__res); \ } LSS_INLINE int LSS_NAME(clone)(int (*fn)(void *), void *child_stack, int flags, void *arg, int *parent_tidptr, void *newtls, int *child_tidptr) { long __res; __asm__ __volatile__(/* if (fn == NULL) * return -EINVAL; */ "movl %3,%%ecx\n" "jecxz 1f\n" /* if (child_stack == NULL) * return -EINVAL; */ "movl %4,%%ecx\n" "jecxz 1f\n" /* Set up alignment of the child stack: * child_stack = (child_stack & ~0xF) - 20; */ "andl $-16,%%ecx\n" "subl $20,%%ecx\n" /* Push "arg" and "fn" onto the stack that will be * used by the child. */ "movl %6,%%eax\n" "movl %%eax,4(%%ecx)\n" "movl %3,%%eax\n" "movl %%eax,(%%ecx)\n" /* %eax = syscall(%eax = __NR_clone, * %ebx = flags, * %ecx = child_stack, * %edx = parent_tidptr, * %esi = newtls, * %edi = child_tidptr) * Also, make sure that %ebx gets preserved as it is * used in PIC mode. */ "movl %8,%%esi\n" "movl %7,%%edx\n" "movl %5,%%eax\n" "movl %9,%%edi\n" "pushl %%ebx\n" "movl %%eax,%%ebx\n" "movl %2,%%eax\n" "int $0x80\n" /* In the parent: restore %ebx * In the child: move "fn" into %ebx */ "popl %%ebx\n" /* if (%eax != 0) * return %eax; */ "test %%eax,%%eax\n" "jnz 1f\n" /* In the child, now. Terminate frame pointer chain. */ "movl $0,%%ebp\n" /* Call "fn". "arg" is already on the stack. */ "call *%%ebx\n" /* Call _exit(%ebx). Unfortunately older versions * of gcc restrict the number of arguments that can * be passed to asm(). So, we need to hard-code the * system call number. */ "movl %%eax,%%ebx\n" "movl $1,%%eax\n" "int $0x80\n" /* Return to parent. */ "1:\n" : "=a" (__res) : "0"(-EINVAL), "i"(__NR_clone), "m"(fn), "m"(child_stack), "m"(flags), "m"(arg), "m"(parent_tidptr), "m"(newtls), "m"(child_tidptr) : "memory", "ecx", "edx", "esi", "edi"); LSS_RETURN(int, __res); } #elif defined(__x86_64__) /* There are no known problems with any of the _syscallX() macros * currently shipping for x86_64, but we still need to be able to define * our own version so that we can override the location of the errno * location (e.g. when using the clone() system call with the CLONE_VM * option). */ #undef LSS_BODY #define LSS_BODY(type,name, ...) \ long __res; \ __asm__ __volatile__("syscall" : "=a" (__res) : "0" (__NR_##name), \ ##__VA_ARGS__ : "r11", "rcx", "memory"); \ LSS_RETURN(type, __res) #undef _syscall0 #define _syscall0(type,name) \ type LSS_NAME(name)() { \ LSS_BODY(type, name); \ } #undef _syscall1 #define _syscall1(type,name,type1,arg1) \ type LSS_NAME(name)(type1 arg1) { \ LSS_BODY(type, name, "D" ((long)(arg1))); \ } #undef _syscall2 #define _syscall2(type,name,type1,arg1,type2,arg2) \ type LSS_NAME(name)(type1 arg1, type2 arg2) { \ LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2))); \ } #undef _syscall3 #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3) { \ LSS_BODY(type, name, "D" ((long)(arg1)), "S" ((long)(arg2)), \ "d" ((long)(arg3))); \ } #undef _syscall4 #define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ long __res; \ __asm__ __volatile__("movq %5,%%r10; syscall" : \ "=a" (__res) : "0" (__NR_##name), \ "D" ((long)(arg1)), "S" ((long)(arg2)), "d" ((long)(arg3)), \ "g" ((long)(arg4)) : "r10", "r11", "rcx", "memory"); \ LSS_RETURN(type, __res); \ } #undef _syscall5 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ type5,arg5) \ type LSS_NAME(name)(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -