remove the ->type field in the child ops
[trinity.git] / syscall.c
blobe367ca83fdd1463f8e3d9a84f2ec848f9ddfb022
1 /*
2 * Functions for actually doing the system calls.
3 */
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <sys/types.h>
11 #include <sys/ptrace.h>
12 #include <sys/syscall.h>
13 #include <sys/wait.h>
15 #include "arch.h"
16 #include "child.h"
17 #include "random.h"
18 #include "sanitise.h"
19 #include "shm.h"
20 #include "syscall.h"
21 #include "pids.h"
22 #include "log.h"
23 #include "params.h"
24 #include "maps.h"
25 #include "tables.h"
26 #include "trinity.h"
27 #include "uid.h"
28 #include "utils.h"
30 #define __syscall_return(type, res) \
31 do { \
32 if ((unsigned long)(res) >= (unsigned long)(-125)) { \
33 errno = -(res); \
34 res = -1; \
35 } \
36 return (type) (res); \
37 } while (0)
39 #ifdef ARCH_IS_BIARCH
41 * This routine does 32 bit syscalls on 64 bit kernel.
42 * 32-on-32 will just use syscall() directly from do_syscall() because do32bit flag is biarch only.
44 long syscall32(unsigned int call,
45 unsigned long a1, unsigned long a2, unsigned long a3,
46 unsigned long a4, unsigned long a5, unsigned long a6)
48 long __res = 0;
50 //FIXME: Move the implementations out to arch header files.
52 #if defined(__x86_64__)
53 __asm__ volatile (
54 "pushq %%rbp\n\t"
55 "pushq %%r10\n\t"
56 "pushq %%r11\n\t"
57 "movq %7, %%rbp\n\t"
58 "int $0x80\n\t"
59 "popq %%r11\n\t"
60 "popq %%r10\n\t"
61 "popq %%rbp\n\t"
62 : "=a" (__res)
63 : "0" (call),"b" ((long)(a1)),"c" ((long)(a2)),"d" ((long)(a3)), "S" ((long)(a4)),"D" ((long)(a5)), "g" ((long)(a6))
64 : "%rbp" /* mark EBP reg as dirty */
66 __syscall_return(long, __res);
68 #else
69 /* non-x86 implementations go here. */
70 #error Implement 32-on-64 syscall in syscall.c:syscall32() for this architecture.
72 #endif
73 return __res;
75 #else
76 #define syscall32(a,b,c,d,e,f,g) 0
77 #endif /* ARCH_IS_BIARCH */
79 static unsigned long do_syscall(int childno, int *errno_saved)
81 int nr = shm->syscall[childno].nr;
82 unsigned long a1, a2, a3, a4, a5, a6;
83 unsigned long ret = 0;
85 a1 = shm->syscall[childno].a1;
86 a2 = shm->syscall[childno].a2;
87 a3 = shm->syscall[childno].a3;
88 a4 = shm->syscall[childno].a4;
89 a5 = shm->syscall[childno].a5;
90 a6 = shm->syscall[childno].a6;
92 shm->total_syscalls_done++;
93 shm->child_syscall_count[childno]++;
94 (void)gettimeofday(&shm->tv[childno], NULL);
96 if (syscalls[nr].entry->flags & NEED_ALARM)
97 (void)alarm(1);
99 errno = 0;
101 if (shm->syscall[childno].do32bit == FALSE)
102 ret = syscall(nr, a1, a2, a3, a4, a5, a6);
103 else
104 ret = syscall32(nr, a1, a2, a3, a4, a5, a6);
106 *errno_saved = errno;
108 if (syscalls[nr].entry->flags & NEED_ALARM)
109 (void)alarm(0);
111 return ret;
115 * Generate arguments, print them out, then call the syscall.
117 long mkcall(int childno)
119 struct syscallentry *entry;
120 unsigned int call = shm->syscall[childno].nr;
121 unsigned long ret = 0;
122 int errno_saved;
124 entry = syscalls[call].entry;
126 shm->regenerate++;
128 shm->syscall[childno].a1 = (unsigned long) rand64();
129 shm->syscall[childno].a2 = (unsigned long) rand64();
130 shm->syscall[childno].a3 = (unsigned long) rand64();
131 shm->syscall[childno].a4 = (unsigned long) rand64();
132 shm->syscall[childno].a5 = (unsigned long) rand64();
133 shm->syscall[childno].a6 = (unsigned long) rand64();
135 generic_sanitise(childno);
136 if (entry->sanitise)
137 entry->sanitise(childno);
139 output_syscall_prefix(childno, call);
141 /* If we're going to pause, might as well sync pre-syscall */
142 if (dopause == TRUE)
143 synclogs();
145 /* Some architectures (IA64/MIPS) start their Linux syscalls
146 * At non-zero, and have other ABIs below.
148 call += SYSCALL_OFFSET;
150 ret = do_syscall(childno, &errno_saved);
151 shm->syscall[childno].retval = ret;
153 if (IS_ERR(ret))
154 shm->failures++;
155 else
156 shm->successes++;
158 output_syscall_postfix(ret, errno_saved, IS_ERR(ret));
159 if (dopause == TRUE)
160 sleep(1);
162 /* If the syscall doesn't exist don't bother calling it next time. */
163 if ((ret == -1UL) && (errno_saved == ENOSYS)) {
165 /* Futex is awesome, it ENOSYS's depending on arguments. Sigh. */
166 if (call == (unsigned int) search_syscall_table(syscalls, max_nr_syscalls, "futex"))
167 goto skip_enosys;
169 /* Unknown ioctls also ENOSYS. */
170 if (call == (unsigned int) search_syscall_table(syscalls, max_nr_syscalls, "ioctl"))
171 goto skip_enosys;
173 /* sendfile() may ENOSYS depending on args. */
174 if (call == (unsigned int) search_syscall_table(syscalls, max_nr_syscalls, "sendfile"))
175 goto skip_enosys;
177 output(1, "%s (%d) returned ENOSYS, marking as inactive.\n",
178 entry->name, call);
180 if (biarch == FALSE) {
181 deactivate_syscall(call);
182 } else {
183 if (shm->syscall[childno].do32bit == TRUE)
184 deactivate_syscall32(call);
185 else
186 deactivate_syscall64(call);
190 skip_enosys:
192 if (entry->post)
193 entry->post(childno);
195 /* store info for debugging. */
196 shm->previous[childno].nr = shm->syscall[childno].nr;
197 shm->previous[childno].a1 = shm->syscall[childno].a1;
198 shm->previous[childno].a2 = shm->syscall[childno].a2;
199 shm->previous[childno].a3 = shm->syscall[childno].a3;
200 shm->previous[childno].a4 = shm->syscall[childno].a4;
201 shm->previous[childno].a5 = shm->syscall[childno].a5;
202 shm->previous[childno].a6 = shm->syscall[childno].a6;
203 shm->previous[childno].do32bit = shm->syscall[childno].do32bit;
205 check_uid();
207 return ret;
210 bool this_syscallname(const char *thisname, int childno)
212 unsigned int call = shm->syscall[childno].nr;
213 struct syscallentry *syscall_entry = syscalls[call].entry;
215 return strcmp(thisname, syscall_entry->name);