Eliminate many SCNO_IS_VALID checks

By adding tcp->s_ent pointer tot syscall table entry,
we can replace sysent[tcp->scno] references by tcp->s_ent.
More importantly, we may ensure that tcp->s_ent is always valid,
regardless of tcp->scno value. This allows us to drop
SCNO_IS_VALID(tcp->scno) checks before we access syscall
table entry.

We can optimize (qual_flags[tcp->scno] & QUAL_foo) checks
with a similar technique.

Resulting code shrink:
   text    data     bss     dec     hex filename
 245975     700   19072  265747   40e13 strace.t3/strace
 245703     700   19072  265475   40d03 strace.t4/strace

* count.c (count_syscall): Use cheaper SCNO_IN_RANGE() check.
* defs.h: Add "int qual_flg" and "const struct sysent *s_ent"
to struct tcb. Remove "int u_nargs" from it.
Add UNDEFINED_SCNO constant which will mark undefined scnos
in tcp->qual_flg.
* pathtrace.c (pathtrace_match): Drop SCNO_IS_VALID check.
Use tcp->s_ent instead of sysent[tcp->scno].
* process.c (sys_prctl): Use tcp->s_ent->nargs instead of tcp->u_nargs.
(sys_waitid): Likewise.
* strace.c (init): Add compile-time check that DEFAULT_QUAL_FLAGS
constant is consistent with init code.
* syscall.c (decode_socket_subcall): Use tcp->s_ent->nargs
instead of tcp->u_nargs. Set tcp->qual_flg and tcp->s_ent.
(decode_ipc_subcall): Likewise.
(printargs): Use tcp->s_ent->nargs instead of tcp->u_nargs.
(printargs_lu): Likewise.
(printargs_ld): Likewise.
(get_scno): [MIPS,ALPHA] Use cheaper SCNO_IN_RANGE() check.
If !SCNO_IS_VALID, set tcp->s_ent and tcp->qual_flg to default values.
(internal_fork): Use tcp->s_ent instead of sysent[tcp->scno].
(syscall_fixup_for_fork_exec): Remove SCNO_IS_VALID check.
Use tcp->s_ent instead of sysent[tcp->scno].
(get_syscall_args): Likewise.
(get_error): Drop SCNO_IS_VALID check where it is redundant.
(dumpio): Drop SCNO_IS_VALID check where it is redundant.
Use tcp->s_ent instead of sysent[tcp->scno].
(trace_syscall_entering): Use (tcp->qual_flg & UNDEFINED_SCNO) instead
of SCNO_IS_VALID check. Use tcp->s_ent instead of sysent[tcp->scno].
Drop SCNO_IS_VALID check where it is redundant.
Print undefined syscall name with undefined_scno_name(tcp).
(trace_syscall_exiting): Likewise.
* util.c (setbpt): Use tcp->s_ent instead of sysent[tcp->scno].

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
diff --git a/defs.h b/defs.h
index fc8f8e7..855a312 100644
--- a/defs.h
+++ b/defs.h
@@ -366,11 +366,24 @@
 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 */
@@ -385,6 +398,7 @@
 	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 */
@@ -447,14 +461,17 @@
 #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)
@@ -728,19 +745,6 @@
 # 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;