最下位apiの実装

44213 ワード

//
// Created by lichao26 on 2017/8/16 0016.
//

#include 
#include 
#include 

#define str(s) #s

#if defined(__arm__) || defined(__i386__)

#if defined(__arm__)
#define linux_syscall_0(syscallnum) {\
    static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \
    asm volatile(                           \
        "PUSH   {R0,R7}
" \
"MOV R7, " str(syscallnum) "
" \
"SWI #0
" \
"MOV %[ret_],R0
" \
"POP {R0,R7}
" \
:[ret_]"=r"(asm_ret) \ : \ :"r0"); \ } #elif defined(__i386__) #define linux_syscall_0(syscallnum) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSHL %%EAX
"
\ "MOVL $" str(syscallnum) ", %%EAX
"
\ "INT $0x80
"
\ "MOVL %%EAX,%[ret_]
"
\ "POPL %%EAX
"
\ :[ret_]"=r"(asm_ret) \ : \ :); \ } #else #define linux_syscall_0(syscallnum) static_assert(false, "linux_syscall wrong arch") #endif #if defined(__arm__) #define linux_syscall_1(syscallnum, arg0) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSH {R0,R7}
" \
"MOV R0, %[arg0_]
" \
"MOV R7, " str(syscallnum) "
" \
"SWI #0
" \
"MOV %[ret_],R0
" \
"POP {R0,R7}
" \
:[ret_]"=r"(asm_ret) \ :[arg0_]"r"(arg0) \ :"r0"); \ } #elif defined(__i386__) #define linux_syscall_1(syscallnum, arg0) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSHL %%EAX
"
\ "PUSHL %%EBX
"
\ "MOVL 8(%%EBP),%%EBX
"
\ "MOVL $" str(syscallnum) ",%%EAX
"
\ "INT $0x80
"
\ "MOVL %%EAX,%[ret_]
"
\ "POPL %%EBX
"
\ "POPL %%EAX
"
\ :[ret_]"=r"(asm_ret) \ : \ :"ebx"); \ } #else #define linux_syscall_1(syscallnum, arg0) static_assert(false, "linux_syscall wrong arch") #endif #if defined(__arm__) #define linux_syscall_2(syscallnum, arg0, arg1) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSH {R0-R1,R7}
" \
"MOV R0, %[arg0_]
" \
"MOV R1, %[arg1_]
" \
"MOV R7, " str(syscallnum) "
" \
"SWI #0
" \
"MOV %[ret_],R0
" \
"POP {R0-R1,R7}
" \
:[ret_]"=r"(asm_ret) \ :[arg0_]"r"(arg0), [arg1_]"r"(arg1) \ :"r0", "r1"); \ } #elif defined(__i386__) #define linux_syscall_2(syscallnum, arg0, arg1) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSHL %%EAX
"
\ "PUSHL %%EBX
"
\ "PUSHL %%ECX
"
\ "MOVL 8(%%EBP),%%EBX
"
\ "MOVL 12(%%EBP),%%ECX
"
\ "MOVL $" str(syscallnum) ",%%EAX
"
\ "INT $0x80
"
\ "MOVL %%EAX,%[ret_]
"
\ "POPL %%ECX
"
\ "POPL %%EBX
"
\ "POPL %%EAX
"
\ :[ret_]"=r"(asm_ret) \ : \ :"ebx", "ecx"); \ } #else #define linux_syscall_2(syscallnum, arg0, arg1) static_assert(false, "linux_syscall wrong arch") #endif #if defined(__arm__) #define linux_syscall_3(syscallnum, arg0, arg1, arg2) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSH {R0-R2,R7}
" \
"MOV R0, %[arg0_]
" \
"MOV R1, %[arg1_]
" \
"MOV R2, %[arg2_]
" \
"MOV R7, " str(syscallnum) "
" \
"SWI #0
" \
"MOV %[ret_],R0
" \
"POP {R0-R2,R7}
" \
:[ret_]"=r"(asm_ret) \ :[arg0_]"r"(arg0), [arg1_]"r"(arg1), [arg2_]"r"(arg2)\ :"r0", "r1", "r2"); \ } #elif defined(__i386__) #define linux_syscall_3(syscallnum, arg0, arg1, arg2) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSHL %%EAX
"
\ "PUSHL %%EBX
"
\ "PUSHL %%ECX
"
\ "PUSHL %%EDX
"
\ "MOVL 8(%%EBP),%%EBX
"
\ "MOVL 12(%%EBP),%%ECX
"
\ "MOVL 16(%%EBP),%%EDX
"
\ "MOVL $" str(syscallnum) ",%%EAX
"
\ "INT $0x80
"
\ "MOVL %%EAX,%[ret_]
"
\ "POPL %%EDX
"
\ "POPL %%ECX
"
\ "POPL %%EBX
"
\ "POPL %%EAX
"
\ :[ret_]"=r"(asm_ret) \ : \ :"ebx", "ecx", "edx"); \ } #else #define linux_syscall_3(syscallnum, arg0, arg1, arg2) \ static_assert(false, "linux_syscall wrong arch") #endif #if defined(__arm__) #define linux_syscall_4(syscallnum, arg0, arg1, arg2, arg3) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSH {R0-R3,R7}
" \
"MOV R0, %[arg0_]
" \
"MOV R1, %[arg1_]
" \
"MOV R2, %[arg2_]
" \
"MOV R3, %[arg3_]
" \
"MOV R7, " str(syscallnum) "
" \
"SWI #0
" \
"MOV %[ret_],R0
" \
"POP {R0-R3,R7}
" \
:[ret_]"=r"(asm_ret) \ :[arg0_]"r"(arg0), [arg1_]"r"(arg1), [arg2_]"r"(arg2), [arg3_]"r"(arg3)\ :"r0", "r1", "r2", "r3"); \ } #elif defined(__i386__) #define linux_syscall_4(syscallnum, arg0, arg1, arg2, arg3) {\ static_assert(sizeof(asm_ret) <= 4, "linux_syscall wrong return size"); \ asm volatile( \ "PUSHL %%EAX
"
\ "PUSHL %%EBX
"
\ "PUSHL %%ECX
"
\ "PUSHL %%EDX
"
\ "PUSHL %%ESI
"
\ "MOVL 8(%%EBP),%%EBX
"
\ "MOVL 12(%%EBP),%%ECX
"
\ "MOVL 16(%%EBP),%%EDX
"
\ "MOVL 20(%%EBP),%%ESI
"
\ "MOVL $" str(syscallnum) ",%%EAX
"
\ "INT $0x80
"
\ "MOVL %%EAX,%[ret_]
"
\ "POPL %%ESI
"
\ "POPL %%EDX
"
\ "POPL %%ECX
"
\ "POPL %%EBX
"
\ "POPL %%EAX
"
\ :[ret_]"=r"(asm_ret) \ : \ :"ebx", "ecx", "edx", "esi"); \ } #else #define linux_syscall_4(syscallnum, arg0, arg1, arg2, arg3) \ static_assert(false, "linux_syscall wrong arch") #endif #define _syscall_exit(status) linux_syscall_1(__NR_exit_group, status) // not __NR_exit #define _syscall_fork() linux_syscall_0(__NR_fork) #define _syscall_read(fd, buf, count) linux_syscall_3(__NR_read, fd, buf, count) #define _syscall_write(fd, buf, count) linux_syscall_3(__NR_write, fd, buf, count) #define _syscall_open(pathname, flags) linux_syscall_2(__NR_open, pathname, flags) #define _syscall_close(fd) linux_syscall_1(__NR_close, fd) #define _syscall_unlink(pathname) linux_syscall_1(__NR_unlink, pathname) #define _syscall_execve(filename, argv, envp) linux_syscall_3(__NR_execve, filename, argv, envp) #define _syscall_chmod(path, mode) linux_syscall_2(__NR_chmod, path, (int)mode) #define _syscall_lseek(fd, offset, whence) linux_syscall_3(__NR_lseek, fd, offset, whence) #define _syscall_getpid() linux_syscall_0(__NR_getpid) #define _syscall_ptrace(req, pid, addr, data) linux_syscall_4(__NR_ptrace, req, pid, addr, data) #define _syscall_access(pathname, mode) linux_syscall_2(__NR_access, pathname, (int)mode) #define _syscall_kill(pid, sig) linux_syscall_2(__NR_kill, pid, sig) #define _syscall_mkdir(pathname, mode) linux_syscall_2(__NR_mkdir, pathname, (int)mode) #define _syscall_rmdir(pathname) linux_syscall_1(__NR_rmdir, pathname) #define _syscall_getppid() linux_syscall_0(__NR_getppid) #define _syscall_sigaction(signum, act, oldact) linux_syscall_3(__NR_sigaction, signum, act, oldact) #define _syscall_symlink(oldpath, newpath) linux_syscall_2(__NR_symlink, oldpath, newpath) #define _syscall_readlink(path, buf, bufsize) linux_syscall_3(__NR_readlink, path, buf, bufsize) #define _syscall_stat(path, buf) linux_syscall_2(__NR_stat, path, buf) #define _syscall_mprotect(addr, len, prot) linux_syscall_3(__NR_mprotect, addr, len, prot) // callnumber > 255 => MOV R7,num error void safe_exit(int status) { void *asm_ret; _syscall_exit(status); return; } pid_t safe_fork(void) { pid_t asm_ret; _syscall_fork(); return asm_ret; } ssize_t safe_read(int fd, void *buf, size_t count) { ssize_t asm_ret; _syscall_read(fd, buf, count); return asm_ret; } ssize_t safe_write(int fd, const void *buf, size_t count) { ssize_t asm_ret; _syscall_write(fd, buf, count); return asm_ret; } int safe_open(const char *pathname, int flags) { ssize_t asm_ret; _syscall_open(pathname, flags); return asm_ret; } int safe_close(int fd) { int asm_ret; _syscall_close(fd); return asm_ret; } int safe_unlink(const char *pathname) { int asm_ret; _syscall_unlink(pathname); return asm_ret; } int safe_execve(const char *filename, char *const argv[], char *const envp[]) { int asm_ret; _syscall_execve(filename, argv, envp); return asm_ret; } int safe_chmod(const char *path, mode_t mode) { int asm_ret; _syscall_chmod(path, mode); return asm_ret; } off_t safe_lseek(int fd, off_t offset, int whence) { off_t asm_ret; _syscall_lseek(fd, offset, whence); return asm_ret; } pid_t safe_getpid() { pid_t asm_ret; _syscall_getpid(); return asm_ret; } long safe_ptrace(int request, pid_t pid, void *addr, void *data) { long asm_ret; _syscall_ptrace(request, pid, addr, data); return asm_ret; } int safe_access(const char *pathname, int mode) { int asm_ret; _syscall_access(pathname, mode); return asm_ret; } int safe_kill(pid_t pid, int sig) { int asm_ret; _syscall_kill(pid, sig); return asm_ret; } int safe_mkdir(const char *pathname, mode_t mode) { int asm_ret; _syscall_mkdir(pathname, mode); return asm_ret; } int safe_rmdir(const char *pathname) { int asm_ret; _syscall_rmdir(pathname); return asm_ret; } pid_t safe_getppid() { pid_t asm_ret; _syscall_getppid(); return asm_ret; } int safe_sigaction(int signum, const struct sigaction *act, struct sigaction *oldact) { int asm_ret; _syscall_sigaction(signum, act, oldact); return asm_ret; } int safe_symlink(const char *oldpath, const char *newpath) { int asm_ret; _syscall_symlink(oldpath, newpath); return asm_ret; } ssize_t safe_readlink(const char *path, char *buf, size_t bufsize) { ssize_t asm_ret; _syscall_readlink(path, buf, bufsize); return asm_ret; } int safe_stat(const char *path, struct stat *buf) { int asm_ret; _syscall_stat(path, buf); return asm_ret; } int safe_mprotect(void *addr, size_t len, int prot) { int asm_ret; _syscall_mprotect(addr, len, prot); return asm_ret; } #endif