const char *auxstr; /* Auxiliary info from syscall (see RVAL_STR) */
void *_priv_data; /* Private data for syscall decoding functions */
void (*_free_priv_data)(void *); /* Callback for freeing priv_data */
- const struct_sysent *s_ent; /* sysent[scno] or dummy struct for bad scno */
+ const struct_sysent *s_ent; /* sysent[scno] or a stub struct for bad
+ * scno. Use tcp_sysent() macro for access.
+ */
const struct_sysent *s_prev_ent; /* for "resuming interrupted SYSCALL" msg */
struct inject_opts *inject_vec[SUPPORTED_PERSONALITIES];
struct timespec stime; /* System time usage as of last process wait */
# define syscall_delayed(tcp) ((tcp)->flags & TCB_DELAYED)
# define syscall_tampered_nofail(tcp) ((tcp)->flags & TCB_TAMPERED_NO_FAIL)
+extern const struct_sysent stub_sysent;
+# define tcp_sysent(tcp) (tcp->s_ent ?: &stub_sysent)
+# define n_args(tcp) (tcp_sysent(tcp)->nargs)
+
# include "xlat.h"
extern const struct xlat addrfams[];
# define IOCTL_NUMBER_HANDLED 1
# define IOCTL_NUMBER_STOP_LOOKUP 010
-# define indirect_ipccall(tcp) (tcp->s_ent->sys_flags & TRACE_INDIRECT_SUBCALL)
+# define indirect_ipccall(tcp) (tcp_sysent(tcp)->sys_flags & TRACE_INDIRECT_SUBCALL)
enum sock_proto {
SOCK_PROTO_UNKNOWN,
printxval_u(ipccalls, call, NULL);
unsigned int i;
- for (i = 1; i < tcp->s_ent->nargs; ++i)
+ for (i = 1; i < n_args(tcp); ++i)
tprintf(", %#" PRI_klx, tcp->u_arg[i]);
return RVAL_DECODED;
{
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
return -1;
return 1;
};
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
return -1;
return 1;
{
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
return -1;
return 1;
unsigned long *out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i) {
+ for (i = 0; i < n_args(tcp); ++i) {
if (umove(tcp,
(unsigned long) ia64_rse_skip_regs(out0, i),
&tcp->u_arg[i]) < 0) {
{
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
return -1;
return 1;
tcp->u_arg[1] = mips_REG_A1;
tcp->u_arg[2] = mips_REG_A2;
tcp->u_arg[3] = mips_REG_A3;
- if (tcp->s_ent->nargs > 4
+ if (n_args(tcp) > 4
&& umoven(tcp, mips_REG_SP + 4 * sizeof(tcp->u_arg[0]),
- (tcp->s_ent->nargs - 4) * sizeof(tcp->u_arg[0]),
+ (n_args(tcp) - 4) * sizeof(tcp->u_arg[0]),
&tcp->u_arg[4]) < 0) {
/*
* Let's proceed with the first 4 arguments
* instead of reporting the failure.
*/
memset(&tcp->u_arg[4], 0,
- (tcp->s_ent->nargs - 4) * sizeof(tcp->u_arg[0]));
+ (n_args(tcp) - 4) * sizeof(tcp->u_arg[0]));
}
#else
# error unsupported mips abi
* and sync_file_range) requires additional code,
* see linux/mips/get_syscall_args.c
*/
- if (tcp->s_ent->nargs == MAX_ARGS) {
+ if (n_args(tcp) == MAX_ARGS) {
if (umoven(tcp,
mips_REG_SP + MAX_ARGS * sizeof(tcp->u_arg[0]),
sizeof(tcp->u_arg[0]),
};
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, syscall_regs[i], &tcp->u_arg[i]) < 0)
return -1;
return 1;
static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, REG_GENERAL(syscall_regs[i]),
&tcp->u_arg[i]) < 0)
return -1;
{
if (x86_io.iov_len != sizeof(i386_regs)) {
/* x86-64 or x32 ABI */
- if (tcp->s_ent->sys_flags & COMPAT_SYSCALL_TYPES) {
+ if (tcp_sysent(tcp)->sys_flags & COMPAT_SYSCALL_TYPES) {
/*
* X32 compat syscall: zero-extend from 32 bits.
* Use truncate_klong_to_current_wordsize(tcp->u_arg[N])
};
unsigned int i;
- for (i = 0; i < tcp->s_ent->nargs; ++i)
+ for (i = 0; i < n_args(tcp); ++i)
if (upeek(tcp, xtensaregs[i], &tcp->u_arg[i]) < 0)
return -1;
return 1;
{
const struct_sysent *s;
- s = tcp->s_ent;
+ s = tcp_sysent(tcp);
if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK)))
return false;
{
unsigned int i;
- for (i = first; i < tcp->s_ent->nargs; ++i)
+ for (i = first; i < n_args(tcp); ++i)
tprintf(", %#" PRI_klx, tcp->u_arg[i]);
}
SYS_FUNC(sigsuspend)
{
#ifdef MIPS
- print_sigset_addr_len(tcp, tcp->u_arg[tcp->s_ent->nargs - 1],
+ print_sigset_addr_len(tcp, tcp->u_arg[n_args(tcp) - 1],
current_wordsize);
#else
- tprint_old_sigmask_val("", tcp->u_arg[tcp->s_ent->nargs - 1]);
+ tprint_old_sigmask_val("", tcp->u_arg[n_args(tcp) - 1]);
#endif
return RVAL_DECODED;
tcp->qual_flg = qual_flags(tcp->scno);
tcp->s_ent = &sysent[tcp->scno];
- const unsigned int n = tcp->s_ent->nargs;
+ const unsigned int n = n_args(tcp);
unsigned int i;
for (i = 0; i < n; i++)
tcp->u_arg[i] = tcp->u_arg[i + 1];
return;
if (is_number_in_set(fd, write_set)) {
- switch (tcp->s_ent->sen) {
+ switch (tcp_sysent(tcp)->sen) {
case SEN_write:
case SEN_pwrite:
case SEN_send:
return;
if (is_number_in_set(fd, read_set)) {
- switch (tcp->s_ent->sen) {
+ switch (tcp_sysent(tcp)->sen) {
case SEN_read:
case SEN_pread:
case SEN_recv:
int res = get_scno(tcp);
if (res == 0)
return res;
- int scno_good = res;
if (res != 1 || (res = get_syscall_args(tcp)) != 1) {
printleader(tcp);
- tprintf("%s(", scno_good == 1 ? tcp->s_ent->sys_name : "????");
+ tprintf("%s(", tcp_sysent(tcp)->sys_name);
/*
* " <unavailable>" will be added later by the code which
* detects ptrace errors.
|| defined SYS_socket_subcall \
|| defined SYS_syscall_subcall
for (;;) {
- switch (tcp->s_ent->sen) {
+ switch (tcp_sysent(tcp)->sen) {
# ifdef SYS_ipc_subcall
case SEN_ipc:
decode_ipc_subcall(tcp);
# ifdef SYS_syscall_subcall
case SEN_syscall:
decode_syscall_subcall(tcp);
- if (tcp->s_ent->sen != SEN_syscall)
+ if (tcp_sysent(tcp)->sen != SEN_syscall)
continue;
break;
# endif
*/
tcp->qual_flg &= ~QUAL_INJECT;
- switch (tcp->s_ent->sen) {
+ switch (tcp_sysent(tcp)->sen) {
case SEN_execve:
case SEN_execveat:
case SEN_execv:
#ifdef ENABLE_STACKTRACE
if (stack_trace_enabled) {
- if (tcp->s_ent->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
+ if (tcp_sysent(tcp)->sys_flags & STACKTRACE_CAPTURE_ON_ENTER)
unwind_tcb_capture(tcp);
}
#endif
printleader(tcp);
- tprintf("%s(", tcp->s_ent->sys_name);
- int res = raw(tcp) ? printargs(tcp) : tcp->s_ent->sys_func(tcp);
+ tprintf("%s(", tcp_sysent(tcp)->sys_name);
+ int res = raw(tcp) ? printargs(tcp) : tcp_sysent(tcp)->sys_func(tcp);
fflush(tcp->outf);
return res;
}
if ((Tflag || cflag) && !filtered(tcp))
clock_gettime(CLOCK_MONOTONIC, pts);
- if (tcp->s_ent->sys_flags & MEMORY_MAPPING_CHANGE)
+ if (tcp_sysent(tcp)->sys_flags & MEMORY_MAPPING_CHANGE)
mmap_notify_report(tcp);
if (filtered(tcp))
|| (tcp->flags & TCB_REPRINT)) {
tcp->flags &= ~TCB_REPRINT;
printleader(tcp);
- tprintf("<... %s resumed>", tcp->s_ent->sys_name);
+ tprintf("<... %s resumed>", tcp_sysent(tcp)->sys_name);
}
}
if (tcp->sys_func_rval & RVAL_DECODED)
sys_res = tcp->sys_func_rval;
else
- sys_res = tcp->s_ent->sys_func(tcp);
+ sys_res = tcp_sysent(tcp)->sys_func(tcp);
}
tprints(") ");
return get_regs(tcp);
}
+const struct_sysent stub_sysent = {
+ .nargs = MAX_ARGS,
+ .sen = SEN_printargs,
+ .sys_func = printargs,
+ .sys_name = "????",
+};
+
/*
* Returns:
* 0: "ignore this ptrace stop", syscall_entering_decode() should return a "bail
int
get_scno(struct tcb *tcp)
{
+ tcp->scno = -1;
+ tcp->s_ent = NULL;
+ tcp->qual_flg = QUAL_RAW | DEFAULT_QUAL_FLAGS;
+
if (get_syscall_regs(tcp) < 0)
return -1;
struct sysent_buf *s = xcalloc(1, sizeof(*s));
s->tcp = tcp;
- s->ent.nargs = MAX_ARGS;
- s->ent.sen = SEN_printargs;
- s->ent.sys_func = printargs;
+ s->ent = stub_sysent;
s->ent.sys_name = s->buf;
xsprintf(s->buf, "syscall_%#" PRI_klx, shuffle_scno(tcp->scno));
tcp->s_ent = &s->ent;
- tcp->qual_flg = QUAL_RAW | DEFAULT_QUAL_FLAGS;
set_tcb_priv_data(tcp, s, free_sysent_buf);
for (unsigned int i = 0; i < ARRAY_SIZE(tcp->u_arg); ++i)
tcp->u_arg[i] = ptrace_sci.entry.args[i];
#if SUPPORTED_PERSONALITIES > 1
- if (tcp->s_ent->sys_flags & COMPAT_SYSCALL_TYPES) {
+ if (tcp_sysent(tcp)->sys_flags & COMPAT_SYSCALL_TYPES) {
for (unsigned int i = 0; i < ARRAY_SIZE(tcp->u_arg); ++i)
tcp->u_arg[i] = (uint32_t) tcp->u_arg[i];
}
if (get_syscall_result_regs(tcp) < 0)
return -1;
get_error(tcp,
- (!(tcp->s_ent->sys_flags & SYSCALL_NEVER_FAILS)
+ (!(tcp_sysent(tcp)->sys_flags & SYSCALL_NEVER_FAILS)
|| syscall_tampered(tcp))
&& !syscall_tampered_nofail(tcp));
if (ptrace_syscall_info_is_valid())
tcp->u_rval = -1;
else
- get_error(tcp, !(tcp->s_ent->sys_flags &
+ get_error(tcp, !(tcp_sysent(tcp)->sys_flags &
SYSCALL_NEVER_FAILS));
}
}
if (ptrace_syscall_info_is_valid())
tcp->u_error = 0;
else
- get_error(tcp, !(tcp->s_ent->sys_flags &
+ get_error(tcp, !(tcp_sysent(tcp)->sys_flags &
SYSCALL_NEVER_FAILS));
}
}
int
printargs(struct tcb *tcp)
{
- const int n = tcp->s_ent->nargs;
+ const int n = n_args(tcp);
int i;
for (i = 0; i < n; ++i)
tprintf("%s%#" PRI_klx, i ? ", " : "", tcp->u_arg[i]);
int
printargs_u(struct tcb *tcp)
{
- const int n = tcp->s_ent->nargs;
+ const int n = n_args(tcp);
int i;
for (i = 0; i < n; ++i)
tprintf("%s%u", i ? ", " : "",
int
printargs_d(struct tcb *tcp)
{
- const int n = tcp->s_ent->nargs;
+ const int n = n_args(tcp);
int i;
for (i = 0; i < n; ++i)
tprintf("%s%d", i ? ", " : "",