root / linux-user / strace.c @ a4c075f1
History | View | Annotate | Download (38.8 kB)
1 |
#include <stdio.h> |
---|---|
2 |
#include <errno.h> |
3 |
#include <sys/ipc.h> |
4 |
#include <sys/msg.h> |
5 |
#include <sys/sem.h> |
6 |
#include <sys/shm.h> |
7 |
#include <sys/select.h> |
8 |
#include <sys/types.h> |
9 |
#include <sys/mount.h> |
10 |
#include <sys/mman.h> |
11 |
#include <unistd.h> |
12 |
#include <sched.h> |
13 |
#include "qemu.h" |
14 |
|
15 |
int do_strace=0; |
16 |
|
17 |
struct syscallname {
|
18 |
int nr;
|
19 |
const char *name; |
20 |
const char *format; |
21 |
void (*call)(const struct syscallname *, |
22 |
abi_long, abi_long, abi_long, |
23 |
abi_long, abi_long, abi_long); |
24 |
void (*result)(const struct syscallname *, abi_long); |
25 |
}; |
26 |
|
27 |
#ifdef __GNUC__
|
28 |
/*
|
29 |
* It is possible that target doesn't have syscall that uses
|
30 |
* following flags but we don't want the compiler to warn
|
31 |
* us about them being unused. Same applies to utility print
|
32 |
* functions. It is ok to keep them while not used.
|
33 |
*/
|
34 |
#define UNUSED __attribute__ ((unused))
|
35 |
#else
|
36 |
#define UNUSED
|
37 |
#endif
|
38 |
|
39 |
/*
|
40 |
* Structure used to translate flag values into strings. This is
|
41 |
* similar that is in the actual strace tool.
|
42 |
*/
|
43 |
struct flags {
|
44 |
abi_long f_value; /* flag */
|
45 |
const char *f_string; /* stringified flag */ |
46 |
}; |
47 |
|
48 |
/* common flags for all architectures */
|
49 |
#define FLAG_GENERIC(name) { name, #name } |
50 |
/* target specific flags (syscall_defs.h has TARGET_<flag>) */
|
51 |
#define FLAG_TARGET(name) { TARGET_ ## name, #name } |
52 |
/* end of flags array */
|
53 |
#define FLAG_END { 0, NULL } |
54 |
|
55 |
UNUSED static const char *get_comma(int); |
56 |
UNUSED static void print_pointer(abi_long, int); |
57 |
UNUSED static void print_flags(const struct flags *, abi_long, int); |
58 |
UNUSED static void print_at_dirfd(abi_long, int); |
59 |
UNUSED static void print_file_mode(abi_long, int); |
60 |
UNUSED static void print_open_flags(abi_long, int); |
61 |
UNUSED static void print_syscall_prologue(const struct syscallname *); |
62 |
UNUSED static void print_syscall_epilogue(const struct syscallname *); |
63 |
UNUSED static void print_string(abi_long, int); |
64 |
UNUSED static void print_raw_param(const char *, abi_long, int); |
65 |
UNUSED static void print_timeval(abi_ulong, int); |
66 |
UNUSED static void print_number(abi_long, int); |
67 |
UNUSED static void print_signal(abi_ulong, int); |
68 |
|
69 |
/*
|
70 |
* Utility functions
|
71 |
*/
|
72 |
static void |
73 |
print_ipc_cmd(int cmd)
|
74 |
{ |
75 |
#define output_cmd(val) \
|
76 |
if( cmd == val ) { \
|
77 |
gemu_log(#val); \
|
78 |
return; \
|
79 |
} |
80 |
|
81 |
cmd &= 0xff;
|
82 |
|
83 |
/* General IPC commands */
|
84 |
output_cmd( IPC_RMID ); |
85 |
output_cmd( IPC_SET ); |
86 |
output_cmd( IPC_STAT ); |
87 |
output_cmd( IPC_INFO ); |
88 |
/* msgctl() commands */
|
89 |
#ifdef __USER_MISC
|
90 |
output_cmd( MSG_STAT ); |
91 |
output_cmd( MSG_INFO ); |
92 |
#endif
|
93 |
/* shmctl() commands */
|
94 |
output_cmd( SHM_LOCK ); |
95 |
output_cmd( SHM_UNLOCK ); |
96 |
output_cmd( SHM_STAT ); |
97 |
output_cmd( SHM_INFO ); |
98 |
/* semctl() commands */
|
99 |
output_cmd( GETPID ); |
100 |
output_cmd( GETVAL ); |
101 |
output_cmd( GETALL ); |
102 |
output_cmd( GETNCNT ); |
103 |
output_cmd( GETZCNT ); |
104 |
output_cmd( SETVAL ); |
105 |
output_cmd( SETALL ); |
106 |
output_cmd( SEM_STAT ); |
107 |
output_cmd( SEM_INFO ); |
108 |
output_cmd( IPC_RMID ); |
109 |
output_cmd( IPC_RMID ); |
110 |
output_cmd( IPC_RMID ); |
111 |
output_cmd( IPC_RMID ); |
112 |
output_cmd( IPC_RMID ); |
113 |
output_cmd( IPC_RMID ); |
114 |
output_cmd( IPC_RMID ); |
115 |
output_cmd( IPC_RMID ); |
116 |
output_cmd( IPC_RMID ); |
117 |
|
118 |
/* Some value we don't recognize */
|
119 |
gemu_log("%d",cmd);
|
120 |
} |
121 |
|
122 |
static void |
123 |
print_signal(abi_ulong arg, int last)
|
124 |
{ |
125 |
const char *signal_name = NULL; |
126 |
switch(arg) {
|
127 |
case TARGET_SIGHUP: signal_name = "SIGHUP"; break; |
128 |
case TARGET_SIGINT: signal_name = "SIGINT"; break; |
129 |
case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break; |
130 |
case TARGET_SIGILL: signal_name = "SIGILL"; break; |
131 |
case TARGET_SIGABRT: signal_name = "SIGABRT"; break; |
132 |
case TARGET_SIGFPE: signal_name = "SIGFPE"; break; |
133 |
case TARGET_SIGKILL: signal_name = "SIGKILL"; break; |
134 |
case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break; |
135 |
case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break; |
136 |
case TARGET_SIGALRM: signal_name = "SIGALRM"; break; |
137 |
case TARGET_SIGTERM: signal_name = "SIGTERM"; break; |
138 |
case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break; |
139 |
case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break; |
140 |
case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break; |
141 |
case TARGET_SIGCONT: signal_name = "SIGCONT"; break; |
142 |
case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break; |
143 |
case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break; |
144 |
case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break; |
145 |
} |
146 |
if (signal_name == NULL) { |
147 |
print_raw_param("%ld", arg, 1); |
148 |
return;
|
149 |
} |
150 |
gemu_log("%s%s", signal_name, get_comma(last));
|
151 |
} |
152 |
|
153 |
#ifdef TARGET_NR__newselect
|
154 |
static void |
155 |
print_fdset(int n, abi_ulong target_fds_addr)
|
156 |
{ |
157 |
int i;
|
158 |
|
159 |
gemu_log("[");
|
160 |
if( target_fds_addr ) {
|
161 |
abi_long *target_fds; |
162 |
|
163 |
target_fds = lock_user(VERIFY_READ, |
164 |
target_fds_addr, |
165 |
sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1), |
166 |
1);
|
167 |
|
168 |
if (!target_fds)
|
169 |
return;
|
170 |
|
171 |
for (i=n; i>=0; i--) { |
172 |
if ((tswapl(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1) |
173 |
gemu_log("%d,", i );
|
174 |
} |
175 |
unlock_user(target_fds, target_fds_addr, 0);
|
176 |
} |
177 |
gemu_log("]");
|
178 |
} |
179 |
#endif
|
180 |
|
181 |
/*
|
182 |
* Sysycall specific output functions
|
183 |
*/
|
184 |
|
185 |
/* select */
|
186 |
#ifdef TARGET_NR__newselect
|
187 |
static long newselect_arg1 = 0; |
188 |
static long newselect_arg2 = 0; |
189 |
static long newselect_arg3 = 0; |
190 |
static long newselect_arg4 = 0; |
191 |
static long newselect_arg5 = 0; |
192 |
|
193 |
static void |
194 |
print_newselect(const struct syscallname *name, |
195 |
abi_long arg1, abi_long arg2, abi_long arg3, |
196 |
abi_long arg4, abi_long arg5, abi_long arg6) |
197 |
{ |
198 |
gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1); |
199 |
print_fdset(arg1, arg2); |
200 |
gemu_log(",");
|
201 |
print_fdset(arg1, arg3); |
202 |
gemu_log(",");
|
203 |
print_fdset(arg1, arg4); |
204 |
gemu_log(",");
|
205 |
print_timeval(arg5, 1);
|
206 |
gemu_log(")");
|
207 |
|
208 |
/* save for use in the return output function below */
|
209 |
newselect_arg1=arg1; |
210 |
newselect_arg2=arg2; |
211 |
newselect_arg3=arg3; |
212 |
newselect_arg4=arg4; |
213 |
newselect_arg5=arg5; |
214 |
} |
215 |
#endif
|
216 |
|
217 |
#ifdef TARGET_NR_semctl
|
218 |
static void |
219 |
print_semctl(const struct syscallname *name, |
220 |
abi_long arg1, abi_long arg2, abi_long arg3, |
221 |
abi_long arg4, abi_long arg5, abi_long arg6) |
222 |
{ |
223 |
gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2); |
224 |
print_ipc_cmd(arg3); |
225 |
gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); |
226 |
} |
227 |
#endif
|
228 |
|
229 |
static void |
230 |
print_execve(const struct syscallname *name, |
231 |
abi_long arg1, abi_long arg2, abi_long arg3, |
232 |
abi_long arg4, abi_long arg5, abi_long arg6) |
233 |
{ |
234 |
abi_ulong arg_ptr_addr; |
235 |
char *s;
|
236 |
|
237 |
if (!(s = lock_user_string(arg1)))
|
238 |
return;
|
239 |
gemu_log("%s(\"%s\",{", name->name, s);
|
240 |
unlock_user(s, arg1, 0);
|
241 |
|
242 |
for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { |
243 |
abi_ulong *arg_ptr, arg_addr; |
244 |
|
245 |
arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); |
246 |
if (!arg_ptr)
|
247 |
return;
|
248 |
arg_addr = tswapl(*arg_ptr); |
249 |
unlock_user(arg_ptr, arg_ptr_addr, 0);
|
250 |
if (!arg_addr)
|
251 |
break;
|
252 |
if ((s = lock_user_string(arg_addr))) {
|
253 |
gemu_log("\"%s\",", s);
|
254 |
unlock_user(s, arg_addr, 0);
|
255 |
} |
256 |
} |
257 |
|
258 |
gemu_log("NULL})");
|
259 |
} |
260 |
|
261 |
#ifdef TARGET_NR_ipc
|
262 |
static void |
263 |
print_ipc(const struct syscallname *name, |
264 |
abi_long arg1, abi_long arg2, abi_long arg3, |
265 |
abi_long arg4, abi_long arg5, abi_long arg6) |
266 |
{ |
267 |
switch(arg1) {
|
268 |
case IPCOP_semctl:
|
269 |
gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2); |
270 |
print_ipc_cmd(arg3); |
271 |
gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); |
272 |
break;
|
273 |
default:
|
274 |
gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")", |
275 |
name->name, arg1, arg2, arg3, arg4); |
276 |
} |
277 |
} |
278 |
#endif
|
279 |
|
280 |
/*
|
281 |
* Variants for the return value output function
|
282 |
*/
|
283 |
|
284 |
static void |
285 |
print_syscall_ret_addr(const struct syscallname *name, abi_long ret) |
286 |
{ |
287 |
if( ret == -1 ) { |
288 |
gemu_log(" = -1 errno=%d (%s)\n", errno, target_strerror(errno));
|
289 |
} else {
|
290 |
gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); |
291 |
} |
292 |
} |
293 |
|
294 |
#if 0 /* currently unused */
|
295 |
static void
|
296 |
print_syscall_ret_raw(struct syscallname *name, abi_long ret)
|
297 |
{
|
298 |
gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret);
|
299 |
}
|
300 |
#endif
|
301 |
|
302 |
#ifdef TARGET_NR__newselect
|
303 |
static void |
304 |
print_syscall_ret_newselect(const struct syscallname *name, abi_long ret) |
305 |
{ |
306 |
gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); |
307 |
print_fdset(newselect_arg1,newselect_arg2); |
308 |
gemu_log(",");
|
309 |
print_fdset(newselect_arg1,newselect_arg3); |
310 |
gemu_log(",");
|
311 |
print_fdset(newselect_arg1,newselect_arg4); |
312 |
gemu_log(",");
|
313 |
print_timeval(newselect_arg5, 1);
|
314 |
gemu_log(")\n");
|
315 |
} |
316 |
#endif
|
317 |
|
318 |
UNUSED static struct flags access_flags[] = { |
319 |
FLAG_GENERIC(F_OK), |
320 |
FLAG_GENERIC(R_OK), |
321 |
FLAG_GENERIC(W_OK), |
322 |
FLAG_GENERIC(X_OK), |
323 |
FLAG_END, |
324 |
}; |
325 |
|
326 |
UNUSED static struct flags at_file_flags[] = { |
327 |
#ifdef AT_EACCESS
|
328 |
FLAG_GENERIC(AT_EACCESS), |
329 |
#endif
|
330 |
#ifdef AT_SYMLINK_NOFOLLOW
|
331 |
FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), |
332 |
#endif
|
333 |
FLAG_END, |
334 |
}; |
335 |
|
336 |
UNUSED static struct flags unlinkat_flags[] = { |
337 |
#ifdef AT_REMOVEDIR
|
338 |
FLAG_GENERIC(AT_REMOVEDIR), |
339 |
#endif
|
340 |
FLAG_END, |
341 |
}; |
342 |
|
343 |
UNUSED static struct flags mode_flags[] = { |
344 |
FLAG_GENERIC(S_IFSOCK), |
345 |
FLAG_GENERIC(S_IFLNK), |
346 |
FLAG_GENERIC(S_IFREG), |
347 |
FLAG_GENERIC(S_IFBLK), |
348 |
FLAG_GENERIC(S_IFDIR), |
349 |
FLAG_GENERIC(S_IFCHR), |
350 |
FLAG_GENERIC(S_IFIFO), |
351 |
FLAG_END, |
352 |
}; |
353 |
|
354 |
UNUSED static struct flags open_access_flags[] = { |
355 |
FLAG_TARGET(O_RDONLY), |
356 |
FLAG_TARGET(O_WRONLY), |
357 |
FLAG_TARGET(O_RDWR), |
358 |
FLAG_END, |
359 |
}; |
360 |
|
361 |
UNUSED static struct flags open_flags[] = { |
362 |
FLAG_TARGET(O_APPEND), |
363 |
FLAG_TARGET(O_CREAT), |
364 |
FLAG_TARGET(O_DIRECTORY), |
365 |
FLAG_TARGET(O_EXCL), |
366 |
FLAG_TARGET(O_LARGEFILE), |
367 |
FLAG_TARGET(O_NOCTTY), |
368 |
FLAG_TARGET(O_NOFOLLOW), |
369 |
FLAG_TARGET(O_NONBLOCK), /* also O_NDELAY */
|
370 |
FLAG_TARGET(O_SYNC), |
371 |
FLAG_TARGET(O_TRUNC), |
372 |
#ifdef O_DIRECT
|
373 |
FLAG_TARGET(O_DIRECT), |
374 |
#endif
|
375 |
FLAG_END, |
376 |
}; |
377 |
|
378 |
UNUSED static struct flags mount_flags[] = { |
379 |
#ifdef MS_BIND
|
380 |
FLAG_GENERIC(MS_BIND), |
381 |
#endif
|
382 |
#ifdef MS_DIRSYNC
|
383 |
FLAG_GENERIC(MS_DIRSYNC), |
384 |
#endif
|
385 |
FLAG_GENERIC(MS_MANDLOCK), |
386 |
#ifdef MS_MOVE
|
387 |
FLAG_GENERIC(MS_MOVE), |
388 |
#endif
|
389 |
FLAG_GENERIC(MS_NOATIME), |
390 |
FLAG_GENERIC(MS_NODEV), |
391 |
FLAG_GENERIC(MS_NODIRATIME), |
392 |
FLAG_GENERIC(MS_NOEXEC), |
393 |
FLAG_GENERIC(MS_NOSUID), |
394 |
FLAG_GENERIC(MS_RDONLY), |
395 |
#ifdef MS_RELATIME
|
396 |
FLAG_GENERIC(MS_RELATIME), |
397 |
#endif
|
398 |
FLAG_GENERIC(MS_REMOUNT), |
399 |
FLAG_GENERIC(MS_SYNCHRONOUS), |
400 |
FLAG_END, |
401 |
}; |
402 |
|
403 |
UNUSED static struct flags umount2_flags[] = { |
404 |
#ifdef MNT_FORCE
|
405 |
FLAG_GENERIC(MNT_FORCE), |
406 |
#endif
|
407 |
#ifdef MNT_DETACH
|
408 |
FLAG_GENERIC(MNT_DETACH), |
409 |
#endif
|
410 |
#ifdef MNT_EXPIRE
|
411 |
FLAG_GENERIC(MNT_EXPIRE), |
412 |
#endif
|
413 |
FLAG_END, |
414 |
}; |
415 |
|
416 |
UNUSED static struct flags mmap_prot_flags[] = { |
417 |
FLAG_GENERIC(PROT_NONE), |
418 |
FLAG_GENERIC(PROT_EXEC), |
419 |
FLAG_GENERIC(PROT_READ), |
420 |
FLAG_GENERIC(PROT_WRITE), |
421 |
FLAG_TARGET(PROT_SEM), |
422 |
FLAG_GENERIC(PROT_GROWSDOWN), |
423 |
FLAG_GENERIC(PROT_GROWSUP), |
424 |
FLAG_END, |
425 |
}; |
426 |
|
427 |
UNUSED static struct flags mmap_flags[] = { |
428 |
FLAG_TARGET(MAP_SHARED), |
429 |
FLAG_TARGET(MAP_PRIVATE), |
430 |
FLAG_TARGET(MAP_ANONYMOUS), |
431 |
FLAG_TARGET(MAP_DENYWRITE), |
432 |
FLAG_TARGET(MAP_FIXED), |
433 |
FLAG_TARGET(MAP_GROWSDOWN), |
434 |
FLAG_TARGET(MAP_EXECUTABLE), |
435 |
#ifdef MAP_LOCKED
|
436 |
FLAG_TARGET(MAP_LOCKED), |
437 |
#endif
|
438 |
#ifdef MAP_NONBLOCK
|
439 |
FLAG_TARGET(MAP_NONBLOCK), |
440 |
#endif
|
441 |
FLAG_TARGET(MAP_NORESERVE), |
442 |
#ifdef MAP_POPULATE
|
443 |
FLAG_TARGET(MAP_POPULATE), |
444 |
#endif
|
445 |
#ifdef TARGET_MAP_UNINITIALIZED
|
446 |
FLAG_TARGET(MAP_UNINITIALIZED), |
447 |
#endif
|
448 |
FLAG_END, |
449 |
}; |
450 |
|
451 |
UNUSED static struct flags fcntl_flags[] = { |
452 |
FLAG_TARGET(F_DUPFD), |
453 |
FLAG_TARGET(F_GETFD), |
454 |
FLAG_TARGET(F_SETFD), |
455 |
FLAG_TARGET(F_GETFL), |
456 |
FLAG_TARGET(F_SETFL), |
457 |
FLAG_TARGET(F_GETLK), |
458 |
FLAG_TARGET(F_SETLK), |
459 |
FLAG_TARGET(F_SETLKW), |
460 |
FLAG_END, |
461 |
}; |
462 |
|
463 |
UNUSED static struct flags clone_flags[] = { |
464 |
FLAG_GENERIC(CLONE_VM), |
465 |
FLAG_GENERIC(CLONE_FS), |
466 |
FLAG_GENERIC(CLONE_FILES), |
467 |
FLAG_GENERIC(CLONE_SIGHAND), |
468 |
FLAG_GENERIC(CLONE_PTRACE), |
469 |
FLAG_GENERIC(CLONE_VFORK), |
470 |
FLAG_GENERIC(CLONE_PARENT), |
471 |
FLAG_GENERIC(CLONE_THREAD), |
472 |
FLAG_GENERIC(CLONE_NEWNS), |
473 |
FLAG_GENERIC(CLONE_SYSVSEM), |
474 |
FLAG_GENERIC(CLONE_SETTLS), |
475 |
FLAG_GENERIC(CLONE_PARENT_SETTID), |
476 |
FLAG_GENERIC(CLONE_CHILD_CLEARTID), |
477 |
FLAG_GENERIC(CLONE_DETACHED), |
478 |
FLAG_GENERIC(CLONE_UNTRACED), |
479 |
FLAG_GENERIC(CLONE_CHILD_SETTID), |
480 |
#if defined(CLONE_NEWUTS)
|
481 |
FLAG_GENERIC(CLONE_NEWUTS), |
482 |
#endif
|
483 |
#if defined(CLONE_NEWIPC)
|
484 |
FLAG_GENERIC(CLONE_NEWIPC), |
485 |
#endif
|
486 |
#if defined(CLONE_NEWUSER)
|
487 |
FLAG_GENERIC(CLONE_NEWUSER), |
488 |
#endif
|
489 |
#if defined(CLONE_NEWPID)
|
490 |
FLAG_GENERIC(CLONE_NEWPID), |
491 |
#endif
|
492 |
#if defined(CLONE_NEWNET)
|
493 |
FLAG_GENERIC(CLONE_NEWNET), |
494 |
#endif
|
495 |
#if defined(CLONE_IO)
|
496 |
FLAG_GENERIC(CLONE_IO), |
497 |
#endif
|
498 |
FLAG_END, |
499 |
}; |
500 |
|
501 |
/*
|
502 |
* print_xxx utility functions. These are used to print syscall
|
503 |
* parameters in certain format. All of these have parameter
|
504 |
* named 'last'. This parameter is used to add comma to output
|
505 |
* when last == 0.
|
506 |
*/
|
507 |
|
508 |
static const char * |
509 |
get_comma(int last)
|
510 |
{ |
511 |
return ((last) ? "" : ","); |
512 |
} |
513 |
|
514 |
static void |
515 |
print_flags(const struct flags *f, abi_long flags, int last) |
516 |
{ |
517 |
const char *sep = ""; |
518 |
int n;
|
519 |
|
520 |
if ((flags == 0) && (f->f_value == 0)) { |
521 |
gemu_log("%s%s", f->f_string, get_comma(last));
|
522 |
return;
|
523 |
} |
524 |
for (n = 0; f->f_string != NULL; f++) { |
525 |
if ((f->f_value != 0) && ((flags & f->f_value) == f->f_value)) { |
526 |
gemu_log("%s%s", sep, f->f_string);
|
527 |
flags &= ~f->f_value; |
528 |
sep = "|";
|
529 |
n++; |
530 |
} |
531 |
} |
532 |
|
533 |
if (n > 0) { |
534 |
/* print rest of the flags as numeric */
|
535 |
if (flags != 0) { |
536 |
gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last)); |
537 |
} else {
|
538 |
gemu_log("%s", get_comma(last));
|
539 |
} |
540 |
} else {
|
541 |
/* no string version of flags found, print them in hex then */
|
542 |
gemu_log("%#x%s", (unsigned int)flags, get_comma(last)); |
543 |
} |
544 |
} |
545 |
|
546 |
static void |
547 |
print_at_dirfd(abi_long dirfd, int last)
|
548 |
{ |
549 |
#ifdef AT_FDCWD
|
550 |
if (dirfd == AT_FDCWD) {
|
551 |
gemu_log("AT_FDCWD%s", get_comma(last));
|
552 |
return;
|
553 |
} |
554 |
#endif
|
555 |
gemu_log("%d%s", (int)dirfd, get_comma(last)); |
556 |
} |
557 |
|
558 |
static void |
559 |
print_file_mode(abi_long mode, int last)
|
560 |
{ |
561 |
const char *sep = ""; |
562 |
const struct flags *m; |
563 |
|
564 |
for (m = &mode_flags[0]; m->f_string != NULL; m++) { |
565 |
if ((m->f_value & mode) == m->f_value) {
|
566 |
gemu_log("%s%s", m->f_string, sep);
|
567 |
sep = "|";
|
568 |
mode &= ~m->f_value; |
569 |
break;
|
570 |
} |
571 |
} |
572 |
|
573 |
mode &= ~S_IFMT; |
574 |
/* print rest of the mode as octal */
|
575 |
if (mode != 0) |
576 |
gemu_log("%s%#o", sep, (unsigned int)mode); |
577 |
|
578 |
gemu_log("%s", get_comma(last));
|
579 |
} |
580 |
|
581 |
static void |
582 |
print_open_flags(abi_long flags, int last)
|
583 |
{ |
584 |
print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1);
|
585 |
flags &= ~TARGET_O_ACCMODE; |
586 |
if (flags == 0) { |
587 |
gemu_log("%s", get_comma(last));
|
588 |
return;
|
589 |
} |
590 |
gemu_log("|");
|
591 |
print_flags(open_flags, flags, last); |
592 |
} |
593 |
|
594 |
static void |
595 |
print_syscall_prologue(const struct syscallname *sc) |
596 |
{ |
597 |
gemu_log("%s(", sc->name);
|
598 |
} |
599 |
|
600 |
/*ARGSUSED*/
|
601 |
static void |
602 |
print_syscall_epilogue(const struct syscallname *sc) |
603 |
{ |
604 |
(void)sc;
|
605 |
gemu_log(")");
|
606 |
} |
607 |
|
608 |
static void |
609 |
print_string(abi_long addr, int last)
|
610 |
{ |
611 |
char *s;
|
612 |
|
613 |
if ((s = lock_user_string(addr)) != NULL) { |
614 |
gemu_log("\"%s\"%s", s, get_comma(last));
|
615 |
unlock_user(s, addr, 0);
|
616 |
} else {
|
617 |
/* can't get string out of it, so print it as pointer */
|
618 |
print_pointer(addr, last); |
619 |
} |
620 |
} |
621 |
|
622 |
/*
|
623 |
* Prints out raw parameter using given format. Caller needs
|
624 |
* to do byte swapping if needed.
|
625 |
*/
|
626 |
static void |
627 |
print_raw_param(const char *fmt, abi_long param, int last) |
628 |
{ |
629 |
char format[64]; |
630 |
|
631 |
(void) snprintf(format, sizeof (format), "%s%s", fmt, get_comma(last)); |
632 |
gemu_log(format, param); |
633 |
} |
634 |
|
635 |
static void |
636 |
print_pointer(abi_long p, int last)
|
637 |
{ |
638 |
if (p == 0) |
639 |
gemu_log("NULL%s", get_comma(last));
|
640 |
else
|
641 |
gemu_log("0x" TARGET_ABI_FMT_lx "%s", p, get_comma(last)); |
642 |
} |
643 |
|
644 |
/*
|
645 |
* Reads 32-bit (int) number from guest address space from
|
646 |
* address 'addr' and prints it.
|
647 |
*/
|
648 |
static void |
649 |
print_number(abi_long addr, int last)
|
650 |
{ |
651 |
if (addr == 0) { |
652 |
gemu_log("NULL%s", get_comma(last));
|
653 |
} else {
|
654 |
int num;
|
655 |
|
656 |
get_user_s32(num, addr); |
657 |
gemu_log("[%d]%s", num, get_comma(last));
|
658 |
} |
659 |
} |
660 |
|
661 |
static void |
662 |
print_timeval(abi_ulong tv_addr, int last)
|
663 |
{ |
664 |
if( tv_addr ) {
|
665 |
struct target_timeval *tv;
|
666 |
|
667 |
tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1); |
668 |
if (!tv)
|
669 |
return;
|
670 |
gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}%s", |
671 |
tv->tv_sec, tv->tv_usec, get_comma(last)); |
672 |
unlock_user(tv, tv_addr, 0);
|
673 |
} else
|
674 |
gemu_log("NULL%s", get_comma(last));
|
675 |
} |
676 |
|
677 |
#undef UNUSED
|
678 |
|
679 |
#ifdef TARGET_NR_accept
|
680 |
static void |
681 |
print_accept(const struct syscallname *name, |
682 |
abi_long arg0, abi_long arg1, abi_long arg2, |
683 |
abi_long arg3, abi_long arg4, abi_long arg5) |
684 |
{ |
685 |
print_syscall_prologue(name); |
686 |
print_raw_param("%d", arg0, 0); |
687 |
print_pointer(arg1, 0);
|
688 |
print_number(arg2, 1);
|
689 |
print_syscall_epilogue(name); |
690 |
} |
691 |
#endif
|
692 |
|
693 |
#ifdef TARGET_NR_access
|
694 |
static void |
695 |
print_access(const struct syscallname *name, |
696 |
abi_long arg0, abi_long arg1, abi_long arg2, |
697 |
abi_long arg3, abi_long arg4, abi_long arg5) |
698 |
{ |
699 |
print_syscall_prologue(name); |
700 |
print_string(arg0, 0);
|
701 |
print_flags(access_flags, arg1, 1);
|
702 |
print_syscall_epilogue(name); |
703 |
} |
704 |
#endif
|
705 |
|
706 |
#ifdef TARGET_NR_brk
|
707 |
static void |
708 |
print_brk(const struct syscallname *name, |
709 |
abi_long arg0, abi_long arg1, abi_long arg2, |
710 |
abi_long arg3, abi_long arg4, abi_long arg5) |
711 |
{ |
712 |
print_syscall_prologue(name); |
713 |
print_pointer(arg0, 1);
|
714 |
print_syscall_epilogue(name); |
715 |
} |
716 |
#endif
|
717 |
|
718 |
#ifdef TARGET_NR_chdir
|
719 |
static void |
720 |
print_chdir(const struct syscallname *name, |
721 |
abi_long arg0, abi_long arg1, abi_long arg2, |
722 |
abi_long arg3, abi_long arg4, abi_long arg5) |
723 |
{ |
724 |
print_syscall_prologue(name); |
725 |
print_string(arg0, 1);
|
726 |
print_syscall_epilogue(name); |
727 |
} |
728 |
#endif
|
729 |
|
730 |
#ifdef TARGET_NR_chmod
|
731 |
static void |
732 |
print_chmod(const struct syscallname *name, |
733 |
abi_long arg0, abi_long arg1, abi_long arg2, |
734 |
abi_long arg3, abi_long arg4, abi_long arg5) |
735 |
{ |
736 |
print_syscall_prologue(name); |
737 |
print_string(arg0, 0);
|
738 |
print_file_mode(arg1, 1);
|
739 |
print_syscall_epilogue(name); |
740 |
} |
741 |
#endif
|
742 |
|
743 |
#ifdef TARGET_NR_clone
|
744 |
static void |
745 |
print_clone(const struct syscallname *name, |
746 |
abi_long arg0, abi_long arg1, abi_long arg2, |
747 |
abi_long arg3, abi_long arg4, abi_long arg5) |
748 |
{ |
749 |
print_syscall_prologue(name); |
750 |
#if defined(TARGET_M68K)
|
751 |
print_flags(clone_flags, arg0, 0);
|
752 |
print_raw_param("newsp=0x" TARGET_ABI_FMT_lx, arg1, 1); |
753 |
#elif defined(TARGET_SH4) || defined(TARGET_ALPHA)
|
754 |
print_flags(clone_flags, arg0, 0);
|
755 |
print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0); |
756 |
print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); |
757 |
print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg3, 0); |
758 |
print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg4, 1); |
759 |
#elif defined(TARGET_CRIS)
|
760 |
print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg0, 0); |
761 |
print_flags(clone_flags, arg1, 0);
|
762 |
print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); |
763 |
print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0); |
764 |
print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1); |
765 |
#else
|
766 |
print_flags(clone_flags, arg0, 0);
|
767 |
print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0); |
768 |
print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); |
769 |
print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0); |
770 |
print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1); |
771 |
#endif
|
772 |
print_syscall_epilogue(name); |
773 |
} |
774 |
#endif
|
775 |
|
776 |
#ifdef TARGET_NR_creat
|
777 |
static void |
778 |
print_creat(const struct syscallname *name, |
779 |
abi_long arg0, abi_long arg1, abi_long arg2, |
780 |
abi_long arg3, abi_long arg4, abi_long arg5) |
781 |
{ |
782 |
print_syscall_prologue(name); |
783 |
print_string(arg0, 0);
|
784 |
print_file_mode(arg1, 1);
|
785 |
print_syscall_epilogue(name); |
786 |
} |
787 |
#endif
|
788 |
|
789 |
#ifdef TARGET_NR_execv
|
790 |
static void |
791 |
print_execv(const struct syscallname *name, |
792 |
abi_long arg0, abi_long arg1, abi_long arg2, |
793 |
abi_long arg3, abi_long arg4, abi_long arg5) |
794 |
{ |
795 |
print_syscall_prologue(name); |
796 |
print_string(arg0, 0);
|
797 |
print_raw_param("0x" TARGET_ABI_FMT_lx, arg1, 1); |
798 |
print_syscall_epilogue(name); |
799 |
} |
800 |
#endif
|
801 |
|
802 |
#ifdef TARGET_NR_faccessat
|
803 |
static void |
804 |
print_faccessat(const struct syscallname *name, |
805 |
abi_long arg0, abi_long arg1, abi_long arg2, |
806 |
abi_long arg3, abi_long arg4, abi_long arg5) |
807 |
{ |
808 |
print_syscall_prologue(name); |
809 |
print_at_dirfd(arg0, 0);
|
810 |
print_string(arg1, 0);
|
811 |
print_flags(access_flags, arg2, 0);
|
812 |
print_flags(at_file_flags, arg3, 1);
|
813 |
print_syscall_epilogue(name); |
814 |
} |
815 |
#endif
|
816 |
|
817 |
#ifdef TARGET_NR_fchmodat
|
818 |
static void |
819 |
print_fchmodat(const struct syscallname *name, |
820 |
abi_long arg0, abi_long arg1, abi_long arg2, |
821 |
abi_long arg3, abi_long arg4, abi_long arg5) |
822 |
{ |
823 |
print_syscall_prologue(name); |
824 |
print_at_dirfd(arg0, 0);
|
825 |
print_string(arg1, 0);
|
826 |
print_file_mode(arg2, 0);
|
827 |
print_flags(at_file_flags, arg3, 1);
|
828 |
print_syscall_epilogue(name); |
829 |
} |
830 |
#endif
|
831 |
|
832 |
#ifdef TARGET_NR_fchownat
|
833 |
static void |
834 |
print_fchownat(const struct syscallname *name, |
835 |
abi_long arg0, abi_long arg1, abi_long arg2, |
836 |
abi_long arg3, abi_long arg4, abi_long arg5) |
837 |
{ |
838 |
print_syscall_prologue(name); |
839 |
print_at_dirfd(arg0, 0);
|
840 |
print_string(arg1, 0);
|
841 |
print_raw_param("%d", arg2, 0); |
842 |
print_raw_param("%d", arg3, 0); |
843 |
print_flags(at_file_flags, arg4, 1);
|
844 |
print_syscall_epilogue(name); |
845 |
} |
846 |
#endif
|
847 |
|
848 |
#if defined(TARGET_NR_fcntl) || defined(TARGET_NR_fcntl64)
|
849 |
static void |
850 |
print_fcntl(const struct syscallname *name, |
851 |
abi_long arg0, abi_long arg1, abi_long arg2, |
852 |
abi_long arg3, abi_long arg4, abi_long arg5) |
853 |
{ |
854 |
print_syscall_prologue(name); |
855 |
print_raw_param("%d", arg0, 0); |
856 |
print_flags(fcntl_flags, arg1, 0);
|
857 |
/*
|
858 |
* TODO: check flags and print following argument only
|
859 |
* when needed.
|
860 |
*/
|
861 |
print_pointer(arg2, 1);
|
862 |
print_syscall_epilogue(name); |
863 |
} |
864 |
#define print_fcntl64 print_fcntl
|
865 |
#endif
|
866 |
|
867 |
|
868 |
#ifdef TARGET_NR_futimesat
|
869 |
static void |
870 |
print_futimesat(const struct syscallname *name, |
871 |
abi_long arg0, abi_long arg1, abi_long arg2, |
872 |
abi_long arg3, abi_long arg4, abi_long arg5) |
873 |
{ |
874 |
print_syscall_prologue(name); |
875 |
print_at_dirfd(arg0, 0);
|
876 |
print_string(arg1, 0);
|
877 |
print_timeval(arg2, 0);
|
878 |
print_timeval(arg2 + sizeof (struct target_timeval), 1); |
879 |
print_syscall_epilogue(name); |
880 |
} |
881 |
#endif
|
882 |
|
883 |
#ifdef TARGET_NR_link
|
884 |
static void |
885 |
print_link(const struct syscallname *name, |
886 |
abi_long arg0, abi_long arg1, abi_long arg2, |
887 |
abi_long arg3, abi_long arg4, abi_long arg5) |
888 |
{ |
889 |
print_syscall_prologue(name); |
890 |
print_string(arg0, 0);
|
891 |
print_string(arg1, 1);
|
892 |
print_syscall_epilogue(name); |
893 |
} |
894 |
#endif
|
895 |
|
896 |
#ifdef TARGET_NR_linkat
|
897 |
static void |
898 |
print_linkat(const struct syscallname *name, |
899 |
abi_long arg0, abi_long arg1, abi_long arg2, |
900 |
abi_long arg3, abi_long arg4, abi_long arg5) |
901 |
{ |
902 |
print_syscall_prologue(name); |
903 |
print_at_dirfd(arg0, 0);
|
904 |
print_string(arg1, 0);
|
905 |
print_at_dirfd(arg2, 0);
|
906 |
print_string(arg3, 0);
|
907 |
print_flags(at_file_flags, arg4, 1);
|
908 |
print_syscall_epilogue(name); |
909 |
} |
910 |
#endif
|
911 |
|
912 |
#ifdef TARGET_NR__llseek
|
913 |
static void |
914 |
print__llseek(const struct syscallname *name, |
915 |
abi_long arg0, abi_long arg1, abi_long arg2, |
916 |
abi_long arg3, abi_long arg4, abi_long arg5) |
917 |
{ |
918 |
const char *whence = "UNKNOWN"; |
919 |
print_syscall_prologue(name); |
920 |
print_raw_param("%d", arg0, 0); |
921 |
print_raw_param("%ld", arg1, 0); |
922 |
print_raw_param("%ld", arg2, 0); |
923 |
print_pointer(arg3, 0);
|
924 |
switch(arg4) {
|
925 |
case SEEK_SET: whence = "SEEK_SET"; break; |
926 |
case SEEK_CUR: whence = "SEEK_CUR"; break; |
927 |
case SEEK_END: whence = "SEEK_END"; break; |
928 |
} |
929 |
gemu_log("%s",whence);
|
930 |
print_syscall_epilogue(name); |
931 |
} |
932 |
#endif
|
933 |
|
934 |
#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \
|
935 |
defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) |
936 |
static void |
937 |
print_stat(const struct syscallname *name, |
938 |
abi_long arg0, abi_long arg1, abi_long arg2, |
939 |
abi_long arg3, abi_long arg4, abi_long arg5) |
940 |
{ |
941 |
print_syscall_prologue(name); |
942 |
print_string(arg0, 0);
|
943 |
print_pointer(arg1, 1);
|
944 |
print_syscall_epilogue(name); |
945 |
} |
946 |
#define print_lstat print_stat
|
947 |
#define print_stat64 print_stat
|
948 |
#define print_lstat64 print_stat
|
949 |
#endif
|
950 |
|
951 |
#if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
|
952 |
static void |
953 |
print_fstat(const struct syscallname *name, |
954 |
abi_long arg0, abi_long arg1, abi_long arg2, |
955 |
abi_long arg3, abi_long arg4, abi_long arg5) |
956 |
{ |
957 |
print_syscall_prologue(name); |
958 |
print_raw_param("%d", arg0, 0); |
959 |
print_pointer(arg1, 1);
|
960 |
print_syscall_epilogue(name); |
961 |
} |
962 |
#define print_fstat64 print_fstat
|
963 |
#endif
|
964 |
|
965 |
#ifdef TARGET_NR_mkdir
|
966 |
static void |
967 |
print_mkdir(const struct syscallname *name, |
968 |
abi_long arg0, abi_long arg1, abi_long arg2, |
969 |
abi_long arg3, abi_long arg4, abi_long arg5) |
970 |
{ |
971 |
print_syscall_prologue(name); |
972 |
print_string(arg0, 0);
|
973 |
print_file_mode(arg1, 1);
|
974 |
print_syscall_epilogue(name); |
975 |
} |
976 |
#endif
|
977 |
|
978 |
#ifdef TARGET_NR_mkdirat
|
979 |
static void |
980 |
print_mkdirat(const struct syscallname *name, |
981 |
abi_long arg0, abi_long arg1, abi_long arg2, |
982 |
abi_long arg3, abi_long arg4, abi_long arg5) |
983 |
{ |
984 |
print_syscall_prologue(name); |
985 |
print_at_dirfd(arg0, 0);
|
986 |
print_string(arg1, 0);
|
987 |
print_file_mode(arg2, 1);
|
988 |
print_syscall_epilogue(name); |
989 |
} |
990 |
#endif
|
991 |
|
992 |
#ifdef TARGET_NR_rmdir
|
993 |
static void |
994 |
print_rmdir(const struct syscallname *name, |
995 |
abi_long arg0, abi_long arg1, abi_long arg2, |
996 |
abi_long arg3, abi_long arg4, abi_long arg5) |
997 |
{ |
998 |
print_syscall_prologue(name); |
999 |
print_string(arg0, 0);
|
1000 |
print_syscall_epilogue(name); |
1001 |
} |
1002 |
#endif
|
1003 |
|
1004 |
#ifdef TARGET_NR_rt_sigaction
|
1005 |
static void |
1006 |
print_rt_sigaction(const struct syscallname *name, |
1007 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1008 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1009 |
{ |
1010 |
print_syscall_prologue(name); |
1011 |
print_signal(arg0, 0);
|
1012 |
print_pointer(arg1, 0);
|
1013 |
print_pointer(arg2, 1);
|
1014 |
print_syscall_epilogue(name); |
1015 |
} |
1016 |
#endif
|
1017 |
|
1018 |
#ifdef TARGET_NR_rt_sigprocmask
|
1019 |
static void |
1020 |
print_rt_sigprocmask(const struct syscallname *name, |
1021 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1022 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1023 |
{ |
1024 |
const char *how = "UNKNOWN"; |
1025 |
print_syscall_prologue(name); |
1026 |
switch(arg0) {
|
1027 |
case TARGET_SIG_BLOCK: how = "SIG_BLOCK"; break; |
1028 |
case TARGET_SIG_UNBLOCK: how = "SIG_UNBLOCK"; break; |
1029 |
case TARGET_SIG_SETMASK: how = "SIG_SETMASK"; break; |
1030 |
} |
1031 |
gemu_log("%s,",how);
|
1032 |
print_pointer(arg1, 0);
|
1033 |
print_pointer(arg2, 1);
|
1034 |
print_syscall_epilogue(name); |
1035 |
} |
1036 |
#endif
|
1037 |
|
1038 |
#ifdef TARGET_NR_mknod
|
1039 |
static void |
1040 |
print_mknod(const struct syscallname *name, |
1041 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1042 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1043 |
{ |
1044 |
int hasdev = (arg1 & (S_IFCHR|S_IFBLK));
|
1045 |
|
1046 |
print_syscall_prologue(name); |
1047 |
print_string(arg0, 0);
|
1048 |
print_file_mode(arg1, (hasdev == 0));
|
1049 |
if (hasdev) {
|
1050 |
print_raw_param("makedev(%d", major(arg2), 0); |
1051 |
print_raw_param("%d)", minor(arg2), 1); |
1052 |
} |
1053 |
print_syscall_epilogue(name); |
1054 |
} |
1055 |
#endif
|
1056 |
|
1057 |
#ifdef TARGET_NR_mknodat
|
1058 |
static void |
1059 |
print_mknodat(const struct syscallname *name, |
1060 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1061 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1062 |
{ |
1063 |
int hasdev = (arg2 & (S_IFCHR|S_IFBLK));
|
1064 |
|
1065 |
print_syscall_prologue(name); |
1066 |
print_at_dirfd(arg0, 0);
|
1067 |
print_string(arg1, 0);
|
1068 |
print_file_mode(arg2, (hasdev == 0));
|
1069 |
if (hasdev) {
|
1070 |
print_raw_param("makedev(%d", major(arg3), 0); |
1071 |
print_raw_param("%d)", minor(arg3), 1); |
1072 |
} |
1073 |
print_syscall_epilogue(name); |
1074 |
} |
1075 |
#endif
|
1076 |
|
1077 |
#ifdef TARGET_NR_mq_open
|
1078 |
static void |
1079 |
print_mq_open(const struct syscallname *name, |
1080 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1081 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1082 |
{ |
1083 |
int is_creat = (arg1 & TARGET_O_CREAT);
|
1084 |
|
1085 |
print_syscall_prologue(name); |
1086 |
print_string(arg0, 0);
|
1087 |
print_open_flags(arg1, (is_creat == 0));
|
1088 |
if (is_creat) {
|
1089 |
print_file_mode(arg2, 0);
|
1090 |
print_pointer(arg3, 1);
|
1091 |
} |
1092 |
print_syscall_epilogue(name); |
1093 |
} |
1094 |
#endif
|
1095 |
|
1096 |
#ifdef TARGET_NR_open
|
1097 |
static void |
1098 |
print_open(const struct syscallname *name, |
1099 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1100 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1101 |
{ |
1102 |
int is_creat = (arg1 & TARGET_O_CREAT);
|
1103 |
|
1104 |
print_syscall_prologue(name); |
1105 |
print_string(arg0, 0);
|
1106 |
print_open_flags(arg1, (is_creat == 0));
|
1107 |
if (is_creat)
|
1108 |
print_file_mode(arg2, 1);
|
1109 |
print_syscall_epilogue(name); |
1110 |
} |
1111 |
#endif
|
1112 |
|
1113 |
#ifdef TARGET_NR_openat
|
1114 |
static void |
1115 |
print_openat(const struct syscallname *name, |
1116 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1117 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1118 |
{ |
1119 |
int is_creat = (arg2 & TARGET_O_CREAT);
|
1120 |
|
1121 |
print_syscall_prologue(name); |
1122 |
print_at_dirfd(arg0, 0);
|
1123 |
print_string(arg1, 0);
|
1124 |
print_open_flags(arg2, (is_creat == 0));
|
1125 |
if (is_creat)
|
1126 |
print_file_mode(arg3, 1);
|
1127 |
print_syscall_epilogue(name); |
1128 |
} |
1129 |
#endif
|
1130 |
|
1131 |
#ifdef TARGET_NR_mq_unlink
|
1132 |
static void |
1133 |
print_mq_unlink(const struct syscallname *name, |
1134 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1135 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1136 |
{ |
1137 |
print_syscall_prologue(name); |
1138 |
print_string(arg0, 1);
|
1139 |
print_syscall_epilogue(name); |
1140 |
} |
1141 |
#endif
|
1142 |
|
1143 |
#if defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)
|
1144 |
static void |
1145 |
print_fstatat64(const struct syscallname *name, |
1146 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1147 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1148 |
{ |
1149 |
print_syscall_prologue(name); |
1150 |
print_at_dirfd(arg0, 0);
|
1151 |
print_string(arg1, 0);
|
1152 |
print_pointer(arg2, 0);
|
1153 |
print_flags(at_file_flags, arg3, 1);
|
1154 |
print_syscall_epilogue(name); |
1155 |
} |
1156 |
#define print_newfstatat print_fstatat64
|
1157 |
#endif
|
1158 |
|
1159 |
#ifdef TARGET_NR_readlink
|
1160 |
static void |
1161 |
print_readlink(const struct syscallname *name, |
1162 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1163 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1164 |
{ |
1165 |
print_syscall_prologue(name); |
1166 |
print_string(arg0, 0);
|
1167 |
print_pointer(arg1, 0);
|
1168 |
print_raw_param("%u", arg2, 1); |
1169 |
print_syscall_epilogue(name); |
1170 |
} |
1171 |
#endif
|
1172 |
|
1173 |
#ifdef TARGET_NR_readlinkat
|
1174 |
static void |
1175 |
print_readlinkat(const struct syscallname *name, |
1176 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1177 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1178 |
{ |
1179 |
print_syscall_prologue(name); |
1180 |
print_at_dirfd(arg0, 0);
|
1181 |
print_string(arg1, 0);
|
1182 |
print_pointer(arg2, 0);
|
1183 |
print_raw_param("%u", arg3, 1); |
1184 |
print_syscall_epilogue(name); |
1185 |
} |
1186 |
#endif
|
1187 |
|
1188 |
#ifdef TARGET_NR_rename
|
1189 |
static void |
1190 |
print_rename(const struct syscallname *name, |
1191 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1192 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1193 |
{ |
1194 |
print_syscall_prologue(name); |
1195 |
print_string(arg0, 0);
|
1196 |
print_string(arg1, 1);
|
1197 |
print_syscall_epilogue(name); |
1198 |
} |
1199 |
#endif
|
1200 |
|
1201 |
#ifdef TARGET_NR_renameat
|
1202 |
static void |
1203 |
print_renameat(const struct syscallname *name, |
1204 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1205 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1206 |
{ |
1207 |
print_syscall_prologue(name); |
1208 |
print_at_dirfd(arg0, 0);
|
1209 |
print_string(arg1, 0);
|
1210 |
print_at_dirfd(arg2, 0);
|
1211 |
print_string(arg3, 1);
|
1212 |
print_syscall_epilogue(name); |
1213 |
} |
1214 |
#endif
|
1215 |
|
1216 |
#ifdef TARGET_NR_statfs
|
1217 |
static void |
1218 |
print_statfs(const struct syscallname *name, |
1219 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1220 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1221 |
{ |
1222 |
print_syscall_prologue(name); |
1223 |
print_string(arg0, 0);
|
1224 |
print_pointer(arg1, 1);
|
1225 |
print_syscall_epilogue(name); |
1226 |
} |
1227 |
#define print_statfs64 print_statfs
|
1228 |
#endif
|
1229 |
|
1230 |
#ifdef TARGET_NR_symlink
|
1231 |
static void |
1232 |
print_symlink(const struct syscallname *name, |
1233 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1234 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1235 |
{ |
1236 |
print_syscall_prologue(name); |
1237 |
print_string(arg0, 0);
|
1238 |
print_string(arg1, 1);
|
1239 |
print_syscall_epilogue(name); |
1240 |
} |
1241 |
#endif
|
1242 |
|
1243 |
#ifdef TARGET_NR_symlinkat
|
1244 |
static void |
1245 |
print_symlinkat(const struct syscallname *name, |
1246 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1247 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1248 |
{ |
1249 |
print_syscall_prologue(name); |
1250 |
print_string(arg0, 0);
|
1251 |
print_at_dirfd(arg1, 0);
|
1252 |
print_string(arg2, 1);
|
1253 |
print_syscall_epilogue(name); |
1254 |
} |
1255 |
#endif
|
1256 |
|
1257 |
#ifdef TARGET_NR_mount
|
1258 |
static void |
1259 |
print_mount(const struct syscallname *name, |
1260 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1261 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1262 |
{ |
1263 |
print_syscall_prologue(name); |
1264 |
print_string(arg0, 0);
|
1265 |
print_string(arg1, 0);
|
1266 |
print_string(arg2, 0);
|
1267 |
print_flags(mount_flags, arg3, 0);
|
1268 |
print_pointer(arg4, 1);
|
1269 |
print_syscall_epilogue(name); |
1270 |
} |
1271 |
#endif
|
1272 |
|
1273 |
#ifdef TARGET_NR_umount
|
1274 |
static void |
1275 |
print_umount(const struct syscallname *name, |
1276 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1277 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1278 |
{ |
1279 |
print_syscall_prologue(name); |
1280 |
print_string(arg0, 1);
|
1281 |
print_syscall_epilogue(name); |
1282 |
} |
1283 |
#endif
|
1284 |
|
1285 |
#ifdef TARGET_NR_umount2
|
1286 |
static void |
1287 |
print_umount2(const struct syscallname *name, |
1288 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1289 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1290 |
{ |
1291 |
print_syscall_prologue(name); |
1292 |
print_string(arg0, 0);
|
1293 |
print_flags(umount2_flags, arg1, 1);
|
1294 |
print_syscall_epilogue(name); |
1295 |
} |
1296 |
#endif
|
1297 |
|
1298 |
#ifdef TARGET_NR_unlink
|
1299 |
static void |
1300 |
print_unlink(const struct syscallname *name, |
1301 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1302 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1303 |
{ |
1304 |
print_syscall_prologue(name); |
1305 |
print_string(arg0, 1);
|
1306 |
print_syscall_epilogue(name); |
1307 |
} |
1308 |
#endif
|
1309 |
|
1310 |
#ifdef TARGET_NR_unlinkat
|
1311 |
static void |
1312 |
print_unlinkat(const struct syscallname *name, |
1313 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1314 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1315 |
{ |
1316 |
print_syscall_prologue(name); |
1317 |
print_at_dirfd(arg0, 0);
|
1318 |
print_string(arg1, 0);
|
1319 |
print_flags(unlinkat_flags, arg2, 1);
|
1320 |
print_syscall_epilogue(name); |
1321 |
} |
1322 |
#endif
|
1323 |
|
1324 |
#ifdef TARGET_NR_utime
|
1325 |
static void |
1326 |
print_utime(const struct syscallname *name, |
1327 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1328 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1329 |
{ |
1330 |
print_syscall_prologue(name); |
1331 |
print_string(arg0, 0);
|
1332 |
print_pointer(arg1, 1);
|
1333 |
print_syscall_epilogue(name); |
1334 |
} |
1335 |
#endif
|
1336 |
|
1337 |
#ifdef TARGET_NR_utimes
|
1338 |
static void |
1339 |
print_utimes(const struct syscallname *name, |
1340 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1341 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1342 |
{ |
1343 |
print_syscall_prologue(name); |
1344 |
print_string(arg0, 0);
|
1345 |
print_pointer(arg1, 1);
|
1346 |
print_syscall_epilogue(name); |
1347 |
} |
1348 |
#endif
|
1349 |
|
1350 |
#ifdef TARGET_NR_utimensat
|
1351 |
static void |
1352 |
print_utimensat(const struct syscallname *name, |
1353 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1354 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1355 |
{ |
1356 |
print_syscall_prologue(name); |
1357 |
print_at_dirfd(arg0, 0);
|
1358 |
print_string(arg1, 0);
|
1359 |
print_pointer(arg2, 0);
|
1360 |
print_flags(at_file_flags, arg3, 1);
|
1361 |
print_syscall_epilogue(name); |
1362 |
} |
1363 |
#endif
|
1364 |
|
1365 |
#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
|
1366 |
static void |
1367 |
print_mmap(const struct syscallname *name, |
1368 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1369 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1370 |
{ |
1371 |
print_syscall_prologue(name); |
1372 |
print_pointer(arg0, 0);
|
1373 |
print_raw_param("%d", arg1, 0); |
1374 |
print_flags(mmap_prot_flags, arg2, 0);
|
1375 |
print_flags(mmap_flags, arg3, 0);
|
1376 |
print_raw_param("%d", arg4, 0); |
1377 |
print_raw_param("%#x", arg5, 1); |
1378 |
print_syscall_epilogue(name); |
1379 |
} |
1380 |
#define print_mmap2 print_mmap
|
1381 |
#endif
|
1382 |
|
1383 |
#ifdef TARGET_NR_mprotect
|
1384 |
static void |
1385 |
print_mprotect(const struct syscallname *name, |
1386 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1387 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1388 |
{ |
1389 |
print_syscall_prologue(name); |
1390 |
print_pointer(arg0, 0);
|
1391 |
print_raw_param("%d", arg1, 0); |
1392 |
print_flags(mmap_prot_flags, arg2, 1);
|
1393 |
print_syscall_epilogue(name); |
1394 |
} |
1395 |
#endif
|
1396 |
|
1397 |
#ifdef TARGET_NR_munmap
|
1398 |
static void |
1399 |
print_munmap(const struct syscallname *name, |
1400 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1401 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1402 |
{ |
1403 |
print_syscall_prologue(name); |
1404 |
print_pointer(arg0, 0);
|
1405 |
print_raw_param("%d", arg1, 1); |
1406 |
print_syscall_epilogue(name); |
1407 |
} |
1408 |
#endif
|
1409 |
|
1410 |
#ifdef TARGET_NR_futex
|
1411 |
static void print_futex_op(abi_long tflag, int last) |
1412 |
{ |
1413 |
#define print_op(val) \
|
1414 |
if( cmd == val ) { \
|
1415 |
gemu_log(#val); \
|
1416 |
return; \
|
1417 |
} |
1418 |
|
1419 |
int cmd = (int)tflag; |
1420 |
#ifdef FUTEX_PRIVATE_FLAG
|
1421 |
if (cmd & FUTEX_PRIVATE_FLAG) {
|
1422 |
gemu_log("FUTEX_PRIVATE_FLAG|");
|
1423 |
cmd &= ~FUTEX_PRIVATE_FLAG; |
1424 |
} |
1425 |
#endif
|
1426 |
print_op(FUTEX_WAIT) |
1427 |
print_op(FUTEX_WAKE) |
1428 |
print_op(FUTEX_FD) |
1429 |
print_op(FUTEX_REQUEUE) |
1430 |
print_op(FUTEX_CMP_REQUEUE) |
1431 |
print_op(FUTEX_WAKE_OP) |
1432 |
print_op(FUTEX_LOCK_PI) |
1433 |
print_op(FUTEX_UNLOCK_PI) |
1434 |
print_op(FUTEX_TRYLOCK_PI) |
1435 |
#ifdef FUTEX_WAIT_BITSET
|
1436 |
print_op(FUTEX_WAIT_BITSET) |
1437 |
#endif
|
1438 |
#ifdef FUTEX_WAKE_BITSET
|
1439 |
print_op(FUTEX_WAKE_BITSET) |
1440 |
#endif
|
1441 |
/* unknown values */
|
1442 |
gemu_log("%d",cmd);
|
1443 |
} |
1444 |
|
1445 |
static void |
1446 |
print_futex(const struct syscallname *name, |
1447 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1448 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1449 |
{ |
1450 |
print_syscall_prologue(name); |
1451 |
print_pointer(arg0, 0);
|
1452 |
print_futex_op(arg1, 0);
|
1453 |
print_raw_param(",%d", arg2, 0); |
1454 |
print_pointer(arg3, 0); /* struct timespec */ |
1455 |
print_pointer(arg4, 0);
|
1456 |
print_raw_param("%d", arg4, 1); |
1457 |
print_syscall_epilogue(name); |
1458 |
} |
1459 |
#endif
|
1460 |
|
1461 |
#ifdef TARGET_NR_kill
|
1462 |
static void |
1463 |
print_kill(const struct syscallname *name, |
1464 |
abi_long arg0, abi_long arg1, abi_long arg2, |
1465 |
abi_long arg3, abi_long arg4, abi_long arg5) |
1466 |
{ |
1467 |
print_syscall_prologue(name); |
1468 |
print_raw_param("%d", arg0, 0); |
1469 |
print_signal(arg1, 1);
|
1470 |
print_syscall_epilogue(name); |
1471 |
} |
1472 |
#endif
|
1473 |
|
1474 |
/*
|
1475 |
* An array of all of the syscalls we know about
|
1476 |
*/
|
1477 |
|
1478 |
static const struct syscallname scnames[] = { |
1479 |
#include "strace.list" |
1480 |
}; |
1481 |
|
1482 |
static int nsyscalls = ARRAY_SIZE(scnames); |
1483 |
|
1484 |
/*
|
1485 |
* The public interface to this module.
|
1486 |
*/
|
1487 |
void
|
1488 |
print_syscall(int num,
|
1489 |
abi_long arg1, abi_long arg2, abi_long arg3, |
1490 |
abi_long arg4, abi_long arg5, abi_long arg6) |
1491 |
{ |
1492 |
int i;
|
1493 |
const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; |
1494 |
|
1495 |
gemu_log("%d ", getpid() );
|
1496 |
|
1497 |
for(i=0;i<nsyscalls;i++) |
1498 |
if( scnames[i].nr == num ) {
|
1499 |
if( scnames[i].call != NULL ) { |
1500 |
scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6); |
1501 |
} else {
|
1502 |
/* XXX: this format system is broken because it uses
|
1503 |
host types and host pointers for strings */
|
1504 |
if( scnames[i].format != NULL ) |
1505 |
format = scnames[i].format; |
1506 |
gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6); |
1507 |
} |
1508 |
return;
|
1509 |
} |
1510 |
gemu_log("Unknown syscall %d\n", num);
|
1511 |
} |
1512 |
|
1513 |
|
1514 |
void
|
1515 |
print_syscall_ret(int num, abi_long ret)
|
1516 |
{ |
1517 |
int i;
|
1518 |
|
1519 |
for(i=0;i<nsyscalls;i++) |
1520 |
if( scnames[i].nr == num ) {
|
1521 |
if( scnames[i].result != NULL ) { |
1522 |
scnames[i].result(&scnames[i],ret); |
1523 |
} else {
|
1524 |
if( ret < 0 ) { |
1525 |
gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", -ret, target_strerror(-ret)); |
1526 |
} else {
|
1527 |
gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); |
1528 |
} |
1529 |
} |
1530 |
break;
|
1531 |
} |
1532 |
} |