extern struct pt_regs tile_regs;
#endif
+struct sysent {
+ unsigned nargs;
+ int sys_flags;
+ int (*sys_func)();
+ const char *sys_name;
+};
+
+struct ioctlent {
+ const char *doth;
+ const char *symbol;
+ unsigned long code;
+};
+
/* Trace Control Block */
struct tcb {
int flags; /* See below for TCB_ values */
int pid; /* Process Id of this entry */
- int u_nargs; /* System call argument count */
+ int qual_flg; /* qual_flags[scno] or DEFAULT_QUAL_FLAGS + RAW */
int u_error; /* Error code */
long scno; /* System call number */
long u_arg[MAX_ARGS]; /* System call arguments */
int curcol; /* Output column for this process */
FILE *outf; /* Output file for this process */
const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */
+ const struct sysent *s_ent; /* sysent[scno] or dummy struct for bad scno */
struct timeval stime; /* System time usage as of last process wait */
struct timeval dtime; /* Delta for system time usage */
struct timeval etime; /* Syscall entry time */
#endif
/* qualifier flags */
-#define QUAL_TRACE 0001 /* this system call should be traced */
-#define QUAL_ABBREV 0002 /* abbreviate the structures of this syscall */
-#define QUAL_VERBOSE 0004 /* decode the structures of this syscall */
-#define QUAL_RAW 0010 /* print all args in hex for this syscall */
-#define QUAL_SIGNAL 0020 /* report events with this signal */
-#define QUAL_FAULT 0040 /* report events with this fault */
-#define QUAL_READ 0100 /* dump data read on this file descriptor */
-#define QUAL_WRITE 0200 /* dump data written to this file descriptor */
+#define QUAL_TRACE 0x001 /* this system call should be traced */
+#define QUAL_ABBREV 0x002 /* abbreviate the structures of this syscall */
+#define QUAL_VERBOSE 0x004 /* decode the structures of this syscall */
+#define QUAL_RAW 0x008 /* print all args in hex for this syscall */
+#define QUAL_SIGNAL 0x010 /* report events with this signal */
+#define QUAL_FAULT 0x020 /* report events with this fault */
+#define QUAL_READ 0x040 /* dump data read on this file descriptor */
+#define QUAL_WRITE 0x080 /* dump data written to this file descriptor */
+#define UNDEFINED_SCNO 0x100 /* Used only in tcp->qual_flg */
+
+#define DEFAULT_QUAL_FLAGS (QUAL_TRACE | QUAL_ABBREV | QUAL_VERBOSE)
#define entering(tcp) (!((tcp)->flags & TCB_INSYSCALL))
#define exiting(tcp) ((tcp)->flags & TCB_INSYSCALL)
# define widen_to_long(v) ((long)(v))
#endif
-struct sysent {
- unsigned nargs;
- int sys_flags;
- int (*sys_func)();
- const char *sys_name;
-};
-
-struct ioctlent {
- const char *doth;
- const char *symbol;
- unsigned long code;
-};
-
extern const struct sysent *sysent;
extern unsigned nsyscalls;
extern const char *const *errnoent;
decode_socket_subcall(struct tcb *tcp)
{
unsigned long addr;
- unsigned int i, size;
+ unsigned int i, n, size;
if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_socket_nsubcalls)
return;
tcp->scno = SYS_socket_subcall + tcp->u_arg[0];
+ tcp->qual_flg = qual_flags[tcp->scno];
+ tcp->s_ent = &sysent[tcp->scno];
addr = tcp->u_arg[1];
- tcp->u_nargs = sysent[tcp->scno].nargs;
size = current_wordsize;
- for (i = 0; i < tcp->u_nargs; ++i) {
+ n = tcp->s_ent->nargs;
+ for (i = 0; i < n; ++i) {
if (size == sizeof(int)) {
unsigned int arg;
if (umove(tcp, addr, &arg) < 0)
static void
decode_ipc_subcall(struct tcb *tcp)
{
- unsigned int i;
+ unsigned int i, n;
if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= SYS_ipc_nsubcalls)
return;
tcp->scno = SYS_ipc_subcall + tcp->u_arg[0];
- tcp->u_nargs = sysent[tcp->scno].nargs;
- for (i = 0; i < tcp->u_nargs; i++)
+ tcp->qual_flg = qual_flags[tcp->scno];
+ tcp->s_ent = &sysent[tcp->scno];
+ n = tcp->s_ent->nargs;
+ for (i = 0; i < n; i++)
tcp->u_arg[i] = tcp->u_arg[i + 1];
}
#endif
{
if (entering(tcp)) {
int i;
-
- for (i = 0; i < tcp->u_nargs; i++)
+ int n = tcp->s_ent->nargs;
+ for (i = 0; i < n; i++)
tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
}
return 0;
{
if (entering(tcp)) {
int i;
-
- for (i = 0; i < tcp->u_nargs; i++)
+ int n = tcp->s_ent->nargs;
+ for (i = 0; i < n; i++)
tprintf("%s%lu", i ? ", " : "", tcp->u_arg[i]);
}
return 0;
{
if (entering(tcp)) {
int i;
-
- for (i = 0; i < tcp->u_nargs; i++)
+ int n = tcp->s_ent->nargs;
+ for (i = 0; i < n; i++)
tprintf("%s%ld", i ? ", " : "", tcp->u_arg[i]);
}
return 0;
mips_r2 = regs[REG_V0];
scno = mips_r2;
- if (!SCNO_IS_VALID(scno)) {
+ if (!SCNO_IN_RANGE(scno)) {
if (mips_a3 == 0 || mips_a3 == -1) {
if (debug_flag)
fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
if (upeek(tcp, REG_V0, &scno) < 0)
return -1;
- if (!SCNO_IS_VALID(scno)) {
+ if (!SCNO_IN_RANGE(scno)) {
if (mips_a3 == 0 || mips_a3 == -1) {
if (debug_flag)
fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno);
* Do some sanity checks to figure out if it's
* really a syscall entry
*/
- if (!SCNO_IS_VALID(scno)) {
+ if (!SCNO_IN_RANGE(scno)) {
if (alpha_a3 == 0 || alpha_a3 == -1) {
if (debug_flag)
fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno);
#endif
tcp->scno = scno;
+ if (SCNO_IS_VALID(tcp->scno)) {
+ tcp->s_ent = &sysent[scno];
+ tcp->qual_flg = qual_flags[scno];
+ } else {
+ static const struct sysent unknown = {
+ .nargs = MAX_ARGS,
+ .sys_flags = 0,
+ .sys_func = printargs,
+ .sys_name = "unknown", /* not used */
+ };
+ tcp->s_ent = &unknown;
+ tcp->qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS;
+ }
return 1;
}
* CLONE_UNTRACED, so we keep the same logic with that option
* and don't trace it.
*/
- if ((sysent[tcp->scno].sys_func == sys_clone) &&
- (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED))
+ if ((tcp->s_ent->sys_func == sys_clone)
+ && (tcp->u_arg[ARG_FLAGS] & CLONE_UNTRACED)
+ )
return;
setbpt(tcp);
} else {
*/
int (*func)();
- if (!SCNO_IS_VALID(tcp->scno))
- return;
-
- func = sysent[tcp->scno].sys_func;
+ func = tcp->s_ent->sys_func;
if ( sys_fork == func
|| sys_vfork == func
{
int i, nargs;
- if (SCNO_IS_VALID(tcp->scno))
- nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
- else
- nargs = tcp->u_nargs = MAX_ARGS;
+ nargs = tcp->s_ent->nargs;
#if defined(S390) || defined(S390X)
for (i = 0; i < nargs; ++i)
printleader(tcp);
if (scno_good != 1)
tprints("????" /* anti-trigraph gap */ "(");
- else if (!SCNO_IS_VALID(tcp->scno))
+ else if (tcp->qual_flg & UNDEFINED_SCNO)
tprintf("%s(", undefined_scno_name(tcp));
else
- tprintf("%s(", sysent[tcp->scno].sys_name);
+ tprintf("%s(", tcp->s_ent->sys_name);
/*
* " <unavailable>" will be added later by the code which
* detects ptrace errors.
}
#if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
- while (SCNO_IS_VALID(tcp->scno)) {
+ while (1) {
# ifdef SYS_socket_subcall
- if (sysent[tcp->scno].sys_func == sys_socketcall) {
+ if (tcp->s_ent->sys_func == sys_socketcall) {
decode_socket_subcall(tcp);
break;
}
# endif
# ifdef SYS_ipc_subcall
- if (sysent[tcp->scno].sys_func == sys_ipc) {
+ if (tcp->s_ent->sys_func == sys_ipc) {
decode_ipc_subcall(tcp);
break;
}
# endif
break;
}
-#endif /* SYS_socket_subcall || SYS_ipc_subcall */
+#endif
if (need_fork_exec_workarounds)
syscall_fixup_for_fork_exec(tcp);
- if ((SCNO_IS_VALID(tcp->scno) &&
- !(qual_flags[tcp->scno] & QUAL_TRACE)) ||
- (tracing_paths && !pathtrace_match(tcp))) {
+ if (!(tcp->qual_flg & QUAL_TRACE)
+ || (tracing_paths && !pathtrace_match(tcp))
+ ) {
tcp->flags |= TCB_INSYSCALL | TCB_FILTERED;
return 0;
}
}
printleader(tcp);
- if (!SCNO_IS_VALID(tcp->scno))
+ if (tcp->qual_flg & UNDEFINED_SCNO)
tprintf("%s(", undefined_scno_name(tcp));
else
- tprintf("%s(", sysent[tcp->scno].sys_name);
- if (!SCNO_IS_VALID(tcp->scno) ||
- ((qual_flags[tcp->scno] & QUAL_RAW) &&
- sysent[tcp->scno].sys_func != sys_exit))
+ tprintf("%s(", tcp->s_ent->sys_name);
+ if ((tcp->qual_flg & QUAL_RAW) && tcp->s_ent->sys_func != sys_exit)
res = printargs(tcp);
else
- res = (*sysent[tcp->scno].sys_func)(tcp);
+ res = tcp->s_ent->sys_func(tcp);
fflush(tcp->outf);
ret:
{
int u_error = 0;
int check_errno = 1;
- if (SCNO_IN_RANGE(tcp->scno)
- && (sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS)
- ) {
+ if (tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS) {
check_errno = 0;
}
#if defined(S390) || defined(S390X)
static void
dumpio(struct tcb *tcp)
{
+ int (*func)();
+
if (syserror(tcp))
return;
- if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
- return;
- if (!SCNO_IS_VALID(tcp->scno))
+ if ((unsigned long) tcp->u_arg[0] >= MAX_QUALS)
return;
- if (sysent[tcp->scno].sys_func == printargs)
+ func = tcp->s_ent->sys_func;
+ if (func == printargs)
return;
if (qual_flags[tcp->u_arg[0]] & QUAL_READ) {
- if (sysent[tcp->scno].sys_func == sys_read ||
- sysent[tcp->scno].sys_func == sys_pread ||
- sysent[tcp->scno].sys_func == sys_recv ||
- sysent[tcp->scno].sys_func == sys_recvfrom)
+ if (func == sys_read ||
+ func == sys_pread ||
+ func == sys_recv ||
+ func == sys_recvfrom)
dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
- else if (sysent[tcp->scno].sys_func == sys_readv)
+ else if (func == sys_readv)
dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
return;
}
if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE) {
- if (sysent[tcp->scno].sys_func == sys_write ||
- sysent[tcp->scno].sys_func == sys_pwrite ||
- sysent[tcp->scno].sys_func == sys_send ||
- sysent[tcp->scno].sys_func == sys_sendto)
+ if (func == sys_write ||
+ func == sys_pwrite ||
+ func == sys_send ||
+ func == sys_sendto)
dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
- else if (sysent[tcp->scno].sys_func == sys_writev)
+ else if (func == sys_writev)
dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
return;
}
if ((followfork < 2 && printing_tcp != tcp) || (tcp->flags & TCB_REPRINT)) {
tcp->flags &= ~TCB_REPRINT;
printleader(tcp);
- if (!SCNO_IS_VALID(tcp->scno))
+ if (tcp->qual_flg & UNDEFINED_SCNO)
tprintf("<... %s resumed> ", undefined_scno_name(tcp));
else
- tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name);
+ tprintf("<... %s resumed> ", tcp->s_ent->sys_name);
}
printing_tcp = tcp;
}
sys_res = 0;
- if (!SCNO_IS_VALID(tcp->scno)
- || (qual_flags[tcp->scno] & QUAL_RAW)) {
+ if (tcp->qual_flg & QUAL_RAW) {
/* sys_res = printargs(tcp); - but it's nop on sysexit */
} else {
/* FIXME: not_failing_only (IOW, option -z) is broken:
*/
if (not_failing_only && tcp->u_error)
goto ret; /* ignore failed syscalls */
- sys_res = (*sysent[tcp->scno].sys_func)(tcp);
+ sys_res = tcp->s_ent->sys_func(tcp);
}
tprints(") ");
tabto();
u_error = tcp->u_error;
- if (!SCNO_IS_VALID(tcp->scno) ||
- qual_flags[tcp->scno] & QUAL_RAW) {
+ if (tcp->qual_flg & QUAL_RAW) {
if (u_error)
tprintf("= -1 (errno %ld)", u_error);
else