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