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;