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 shm->do32bit 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
)
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
->syscallno
[childno
];
82 unsigned long a1
, a2
, a3
, a4
, a5
, a6
;
83 unsigned long ret
= 0;
85 a1
= shm
->a1
[childno
];
86 a2
= shm
->a2
[childno
];
87 a3
= shm
->a3
[childno
];
88 a4
= shm
->a4
[childno
];
89 a5
= shm
->a5
[childno
];
90 a6
= shm
->a6
[childno
];
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
->do32bit
[childno
] == 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 long mkcall(int childno
)
119 struct syscallentry
*entry
;
120 unsigned int call
= shm
->syscallno
[childno
];
121 unsigned long ret
= 0;
124 entry
= syscalls
[call
].entry
;
128 shm
->a1
[childno
] = (unsigned long)rand64();
129 shm
->a2
[childno
] = (unsigned long)rand64();
130 shm
->a3
[childno
] = (unsigned long)rand64();
131 shm
->a4
[childno
] = (unsigned long)rand64();
132 shm
->a5
[childno
] = (unsigned long)rand64();
133 shm
->a6
[childno
] = (unsigned long)rand64();
135 generic_sanitise(childno
);
137 entry
->sanitise(childno
);
139 output_syscall_prefix(childno
, call
);
141 /* If we're going to pause, might as well sync pre-syscall */
145 if (((unsigned long)shm
->a1
== (unsigned long) shm
) ||
146 ((unsigned long)shm
->a2
== (unsigned long) shm
) ||
147 ((unsigned long)shm
->a3
== (unsigned long) shm
) ||
148 ((unsigned long)shm
->a4
== (unsigned long) shm
) ||
149 ((unsigned long)shm
->a5
== (unsigned long) shm
) ||
150 ((unsigned long)shm
->a6
== (unsigned long) shm
)) {
151 BUG("Address of shm ended up in a register!\n");
154 /* Some architectures (IA64/MIPS) start their Linux syscalls
155 * At non-zero, and have other ABIs below.
157 call
+= SYSCALL_OFFSET
;
159 ret
= do_syscall(childno
, &errno_saved
);
160 shm
->retval
[childno
] = ret
;
167 output_syscall_postfix(ret
, errno_saved
, IS_ERR(ret
));
171 /* If the syscall doesn't exist don't bother calling it next time. */
172 if ((ret
== -1UL) && (errno_saved
== ENOSYS
)) {
174 /* Futex is awesome, it ENOSYS's depending on arguments. Sigh. */
175 if (call
== (unsigned int) search_syscall_table(syscalls
, max_nr_syscalls
, "futex"))
178 /* Unknown ioctls also ENOSYS. */
179 if (call
== (unsigned int) search_syscall_table(syscalls
, max_nr_syscalls
, "ioctl"))
182 /* sendfile() may ENOSYS depending on args. */
183 if (call
== (unsigned int) search_syscall_table(syscalls
, max_nr_syscalls
, "sendfile"))
186 output(1, "%s (%d) returned ENOSYS, marking as inactive.\n",
189 if (biarch
== FALSE
) {
190 deactivate_syscall(call
);
192 if (shm
->do32bit
[childno
] == TRUE
)
193 deactivate_syscall32(call
);
195 deactivate_syscall64(call
);
202 entry
->post(childno
);
204 /* store info for debugging. */
205 shm
->previous_syscallno
[childno
] = shm
->syscallno
[childno
];
206 shm
->previous_a1
[childno
] = shm
->a1
[childno
];
207 shm
->previous_a2
[childno
] = shm
->a2
[childno
];
208 shm
->previous_a3
[childno
] = shm
->a3
[childno
];
209 shm
->previous_a4
[childno
] = shm
->a4
[childno
];
210 shm
->previous_a5
[childno
] = shm
->a5
[childno
];
211 shm
->previous_a6
[childno
] = shm
->a6
[childno
];
218 bool this_syscallname(const char *thisname
, int childno
)
220 unsigned int call
= shm
->syscallno
[childno
];
221 struct syscallentry
*syscall_entry
= syscalls
[call
].entry
;
223 return strcmp(thisname
, syscall_entry
->name
);