-
Notifications
You must be signed in to change notification settings - Fork 25
/
Copy pathsyscall_ext.cc
155 lines (143 loc) · 6.88 KB
/
syscall_ext.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include "syscall_ext.h"
#include <cstdint>
#include "lss_wrapper.h"
// remove the errno, we do not have TLS, return -errno if error
#undef LSS_RETURN
#if defined(__i386__) || defined(__x86_64__) || defined(__ARM_ARCH_3__) \
|| defined(__ARM_EABI__) || defined(__aarch64__) || defined(__s390__) \
|| defined(__e2k__) || defined(__riscv) || defined(__loongarch_lp64)
/* Failing system calls return a negative result in the range of
* -1..-4095. These are "errno" values with the sign inverted.
*/
#define LSS_RETURN(type, res) \
do { \
return (type) (res); \
} while (0)
#elif defined(__mips__)
/* On MIPS, failing system calls return -1, and set errno in a
* separate CPU register.
*/
#define LSS_RETURN(type, res, err) \
do { \
if (err) { \
unsigned long __errnovalue = (res); \
res = -(signed long)__errnovalue; \
} \
return (type) (res); \
} while (0)
#endif
// we do not support powerpc
#if defined(__x86_64__)
#undef _LSS_RETURN
#define _LSS_RETURN(type, res, cast) \
do { \
return (type)(cast)(res); \
} while (0)
#undef LSS_RETURN
#define LSS_RETURN(type, res) _LSS_RETURN(type, res, uintptr_t)
#endif
__attribute__((noinline))
EXPORT uintptr_t syscall_ext
(int number, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6) {
auto nr = (uintptr_t) number;
uintptr_t __NR_name = nr;
#if defined(__x86_64__)
LSS_BODY(6, uintptr_t, name, LSS_SYSCALL_ARG(arg1), LSS_SYSCALL_ARG(arg2),
LSS_SYSCALL_ARG(arg3), LSS_SYSCALL_ARG(arg4),
LSS_SYSCALL_ARG(arg5), LSS_SYSCALL_ARG(arg6));
#elif defined(__i386__)
long __res;
struct {
long __a1;
long __a6;
long __nr;
} __s = {(long) arg1, (long) arg6, (long) __NR_name};
__asm__ __volatile__("push %%ebp\n"
"push %%ebx\n"
"movl 4(%1),%%ebp\n"
"movl 0(%1),%%ebx\n"
"movl 8(%1),%%eax\n"
LSS_ENTRYPOINT
"pop %%ebx\n"
"pop %%ebp"
: "=a" (__res)
:
"0" ((long) (&__s)),
"c" ((long) (arg2)), "d" ((long) (arg3)),
"S" ((long) (arg4)), "D" ((long) (arg5))
: "memory");
LSS_RETURN(uintptr_t, __res);
#elif defined(__aarch64__)
#undef LSS_BODY
#define LSS_BODY(type,name,args...) \
register int64_t __res_x0 __asm__("x0"); \
int64_t __res; \
__asm__ __volatile__ ("mov x8, %1\n" \
"svc 0x0\n" \
: "=r"(__res_x0) \
: "r"(__NR_##name) , ## args \
: "x8", "memory"); \
__res = __res_x0; \
LSS_RETURN(type, __res)
LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3);
LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6);
LSS_BODY(jlong, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3),
"r"(__r4), "r"(__r5));
#elif defined(__ARM_EABI__)
#undef LSS_BODY
#define LSS_BODY(type,name,args...) \
register long __res_r0 __asm__("r0"); \
long __res; \
__asm__ __volatile__ ("push {r7}\n" \
"mov r7, %1\n" \
"swi 0x0\n" \
"pop {r7}\n" \
: "=r"(__res_r0) \
: "r"(__NR_##name) , ## args \
: "lr", "memory"); \
__res = __res_r0; \
LSS_RETURN(type, __res)
LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3);
LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6);
LSS_BODY(jlong, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3),
"r"(__r4), "r"(__r5));
#elif defined(__ARM_ARCH_3__)
LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3);
LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6);
LSS_BODY(jlong, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3),
"r"(__r4), "r"(__r5));
#elif defined(__riscv) && __riscv_xlen == 64
LSS_REG(0, arg1); LSS_REG(1, arg2); LSS_REG(2, arg3);
LSS_REG(3, arg4); LSS_REG(4, arg5); LSS_REG(5, arg6);
LSS_BODY(jlong, name, "r"(__r0), "r"(__r1), "r"(__r2), "r"(__r3),
"r"(__r4), "r"(__r5));
#elif defined(__mips__)
#if _MIPS_SIM == _MIPS_SIM_ABI32
LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3);
LSS_REG(7, arg4);
register unsigned long __v0 __asm__("$2") = nr;
__asm__ __volatile__ (".set noreorder\n"
"subu $29, 32\n"
"sw %5, 16($29)\n"
"sw %6, 20($29)\n"
"syscall\n"
"addiu $29, 32\n"
".set reorder\n"
: "+r"(__v0), "+r" (__r7)
: "r"(__r4), "r"(__r5),
"r"(__r6), "r" ((unsigned long)arg5),
"r" ((unsigned long)arg6)
: "$8", "$9", "$10", "$11", "$12",
"$13", "$14", "$15", "$24", "$25",
"memory");
LSS_RETURN(jlong, __v0, __r7);
#else
LSS_REG(4, arg1); LSS_REG(5, arg2); LSS_REG(6, arg3);
LSS_REG(7, arg4); LSS_REG(8, arg5); LSS_REG(9, arg6);
LSS_BODY(jlong, name, "+r", "r"(__r4), "r"(__r5), "r"(__r6),
"r"(__r8), "r"(__r9));
#endif
#else
#error "Unsupported architecture"
#endif
}