2 * Functions for actually doing the system calls.
10 #include <sys/types.h>
11 #include <sys/ptrace.h>
12 #include <sys/syscall.h>
30 #define __syscall_return(type, res) \
32 if ((unsigned long)(res) >= (unsigned long)(-125)) { \
36 return (type) (res); \
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 static 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
)
50 //FIXME: Move the implementations out to arch header files.
52 #if defined(__x86_64__)
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
);
69 /* non-x86 implementations go here. */
70 #error Implement 32-on-64 syscall in syscall.c:syscall32() for this architecture.
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
)
101 if (shm
->syscall
[childno
].do32bit
== FALSE
)
102 ret
= syscall(nr
, a1
, a2
, a3
, a4
, a5
, a6
);
104 ret
= syscall32(nr
, a1
, a2
, a3
, a4
, a5
, a6
);
106 *errno_saved
= errno
;
108 if (syscalls
[nr
].entry
->flags
& NEED_ALARM
)
115 * Generate arguments, print them out, then call the syscall.
117 * returns a bool that determines whether we can keep doing syscalls
120 bool mkcall(int childno
)
122 struct syscallentry
*entry
;
123 unsigned int call
= shm
->syscall
[childno
].nr
;
124 unsigned long ret
= 0;
127 entry
= syscalls
[call
].entry
;
131 shm
->syscall
[childno
].a1
= (unsigned long) rand64();
132 shm
->syscall
[childno
].a2
= (unsigned long) rand64();
133 shm
->syscall
[childno
].a3
= (unsigned long) rand64();
134 shm
->syscall
[childno
].a4
= (unsigned long) rand64();
135 shm
->syscall
[childno
].a5
= (unsigned long) rand64();
136 shm
->syscall
[childno
].a6
= (unsigned long) rand64();
138 generic_sanitise(childno
);
140 entry
->sanitise(childno
);
142 output_syscall_prefix(childno
, call
);
144 /* If we're going to pause, might as well sync pre-syscall */
148 /* Some architectures (IA64/MIPS) start their Linux syscalls
149 * At non-zero, and have other ABIs below.
151 call
+= SYSCALL_OFFSET
;
153 /* This is a special case for things like execve, which would replace our
154 * child process with something unknown to us. We use a 'throwaway' process
155 * to do the execve in, and let it run for a max of a seconds before we kill it */
157 if (syscalls
[call
].entry
->flags
& EXTRA_FORK
) {
162 ret
= do_syscall(childno
, &errno_saved
);
163 shm
->syscall
[childno
].retval
= ret
;
166 if (pid_alive(extrapid
)) {
168 kill(extrapid
, SIGKILL
);
175 /* common-case, do the syscall in this child process. */
176 ret
= do_syscall(childno
, &errno_saved
);
177 shm
->syscall
[childno
].retval
= ret
;
184 output_syscall_postfix(ret
, errno_saved
, IS_ERR(ret
));
188 /* If the syscall doesn't exist don't bother calling it next time. */
189 if ((ret
== -1UL) && (errno_saved
== ENOSYS
)) {
191 /* Futex is awesome, it ENOSYS's depending on arguments. Sigh. */
192 if (call
== (unsigned int) search_syscall_table(syscalls
, max_nr_syscalls
, "futex"))
195 /* Unknown ioctls also ENOSYS. */
196 if (call
== (unsigned int) search_syscall_table(syscalls
, max_nr_syscalls
, "ioctl"))
199 /* sendfile() may ENOSYS depending on args. */
200 if (call
== (unsigned int) search_syscall_table(syscalls
, max_nr_syscalls
, "sendfile"))
203 output(1, "%s (%d) returned ENOSYS, marking as inactive.\n",
206 if (biarch
== FALSE
) {
207 deactivate_syscall(call
);
209 if (shm
->syscall
[childno
].do32bit
== TRUE
)
210 deactivate_syscall32(call
);
212 deactivate_syscall64(call
);
219 entry
->post(childno
);
221 /* store info for debugging. */
222 shm
->previous
[childno
].nr
= shm
->syscall
[childno
].nr
;
223 shm
->previous
[childno
].a1
= shm
->syscall
[childno
].a1
;
224 shm
->previous
[childno
].a2
= shm
->syscall
[childno
].a2
;
225 shm
->previous
[childno
].a3
= shm
->syscall
[childno
].a3
;
226 shm
->previous
[childno
].a4
= shm
->syscall
[childno
].a4
;
227 shm
->previous
[childno
].a5
= shm
->syscall
[childno
].a5
;
228 shm
->previous
[childno
].a6
= shm
->syscall
[childno
].a6
;
229 shm
->previous
[childno
].do32bit
= shm
->syscall
[childno
].do32bit
;
236 bool this_syscallname(const char *thisname
, int childno
)
238 unsigned int call
= shm
->syscall
[childno
].nr
;
239 struct syscallentry
*syscall_entry
= syscalls
[call
].entry
;
241 return strcmp(thisname
, syscall_entry
->name
);