diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2011-08-25 01:13:43 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2011-08-25 01:13:43 +0200 |
commit | cb6f056004a10d5c3ed0341366e3ddeb53cac5e6 (patch) | |
tree | da1ecf272317cc684ee64062bbe25153630e6f24 | |
parent | 1a5b5a7aff28a5c8bdafc6104508f553f50977a4 (diff) | |
download | strace-cb6f056004a10d5c3ed0341366e3ddeb53cac5e6.tar.gz strace-cb6f056004a10d5c3ed0341366e3ddeb53cac5e6.tar.bz2 strace-cb6f056004a10d5c3ed0341366e3ddeb53cac5e6.tar.xz |
Opotimize "scno >= 0 && scno < nsyscalls" check
gcc can't figure out on its own that this check can be done with
single compare, and does two compares. We can help it by casting
scno to unsigned long: ((unsigned long)(scno) < nsyscalls)
* defs.h: New macro SCNO_IN_RANGE(long_var).
* count.c (count_syscall): Use SCNO_IN_RANGE() instead of open-coded check.
* syscall.c (getrval2): Use SCNO_IN_RANGE() instead of open-coded check.
This fixes a bug: missing check for scno < 0 and scno > nsyscalls
instead of scno >= nsyscalls.
(get_scno): Use SCNO_IN_RANGE() instead of open-coded check.
This fixes a bug: scno > nsyscalls instead of scno >= nsyscalls.
(known_scno): Use SCNO_IN_RANGE() instead of open-coded check.
(internal_syscall): Likewise.
(syscall_enter): Likewise.
(trace_syscall_entering): Likewise.
(get_error): Likewise.
(trace_syscall_exiting): Likewise.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | count.c | 2 | ||||
-rw-r--r-- | defs.h | 2 | ||||
-rw-r--r-- | syscall.c | 47 |
3 files changed, 27 insertions, 24 deletions
@@ -50,7 +50,7 @@ static struct timeval shortest = { 1000000, 0 }; void count_syscall(struct tcb *tcp, struct timeval *tv) { - if (tcp->scno < 0 || tcp->scno >= nsyscalls) + if (!SCNO_IN_RANGE(tcp->scno)) return; if (!counts) { @@ -728,6 +728,8 @@ extern unsigned nioctlents; extern const char *const *signalent; extern unsigned nsignals; +#define SCNO_IN_RANGE(scno) ((unsigned long)(scno) < nsyscalls) + #if HAVE_LONG_LONG /* _l refers to the lower numbered u_arg, @@ -675,11 +675,12 @@ getrval2(struct tcb *tcp) int sys_indir(struct tcb *tcp) { - int i, scno, nargs; + int i, nargs; + long scno; if (entering(tcp)) { scno = tcp->u_arg[0]; - if (scno > nsyscalls) { + if (!SCNO_IN_RANGE(scno)) { fprintf(stderr, "Bogus syscall: %u\n", scno); return 0; } @@ -1045,7 +1046,7 @@ get_scno(struct tcb *tcp) r2 = regs[REG_V0]; scno = r2; - if (scno < 0 || scno > nsyscalls) { + if (!SCNO_IN_RANGE(scno)) { if (a3 == 0 || a3 == -1) { if (debug) fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno); @@ -1058,7 +1059,7 @@ get_scno(struct tcb *tcp) if (upeek(tcp, REG_V0, &scno) < 0) return -1; - if (scno < 0 || scno > nsyscalls) { + if (!SCNO_IN_RANGE(scno)) { if (a3 == 0 || a3 == -1) { if (debug) fprintf(stderr, "stray syscall exit: v0 = %ld\n", scno); @@ -1075,7 +1076,7 @@ get_scno(struct tcb *tcp) * Do some sanity checks to figure out if it's * really a syscall entry */ - if (scno < 0 || scno > nsyscalls) { + if (!SCNO_IN_RANGE(scno)) { if (a3 == 0 || a3 == -1) { if (debug) fprintf(stderr, "stray syscall exit: r0 = %ld\n", scno); @@ -1228,7 +1229,7 @@ known_scno(struct tcb *tcp) { long scno = tcp->scno; #if SUPPORTED_PERSONALITIES > 1 - if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0) + if (SCNO_IN_RANGE(scno) && sysent[scno].native_scno != 0) scno = sysent[scno].native_scno; else #endif @@ -1425,7 +1426,7 @@ internal_syscall(struct tcb *tcp) */ int (*func)(); - if (tcp->scno < 0 || tcp->scno >= nsyscalls) + if (!SCNO_IN_RANGE(tcp->scno)) return 0; func = sysent[tcp->scno].sys_func; @@ -1464,7 +1465,7 @@ syscall_enter(struct tcb *tcp) #ifdef LINUX int i, nargs; - if (tcp->scno >= 0 && tcp->scno < nsyscalls) + if (SCNO_IN_RANGE(tcp->scno)) nargs = tcp->u_nargs = sysent[tcp->scno].nargs; else nargs = tcp->u_nargs = MAX_ARGS; @@ -1635,7 +1636,7 @@ syscall_enter(struct tcb *tcp) #endif /* LINUX */ #ifdef SUNOS4 int i, nargs; - if (tcp->scno >= 0 && tcp->scno < nsyscalls) + if (SCNO_IN_RANGE(tcp->scno)) nargs = tcp->u_nargs = sysent[tcp->scno].nargs; else nargs = tcp->u_nargs = MAX_ARGS; @@ -1653,7 +1654,7 @@ syscall_enter(struct tcb *tcp) * SGI is broken: even though it has pr_sysarg, it doesn't * set them on system call entry. Get a clue. */ - if (tcp->scno >= 0 && tcp->scno < nsyscalls) + if (SCNO_IN_RANGE(tcp->scno)) tcp->u_nargs = sysent[tcp->scno].nargs; else tcp->u_nargs = tcp->status.pr_nsysarg; @@ -1671,7 +1672,7 @@ syscall_enter(struct tcb *tcp) /* * Like SGI, UnixWare doesn't set pr_sysarg until system call exit */ - if (tcp->scno >= 0 && tcp->scno < nsyscalls) + if (SCNO_IN_RANGE(tcp->scno)) tcp->u_nargs = sysent[tcp->scno].nargs; else tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg; @@ -1679,14 +1680,14 @@ syscall_enter(struct tcb *tcp) tcp->u_nargs * sizeof(tcp->u_arg[0]), (char *) tcp->u_arg); # elif defined(HAVE_PR_SYSCALL) int i; - if (tcp->scno >= 0 && tcp->scno < nsyscalls) + if (SCNO_IN_RANGE(tcp->scno)) tcp->u_nargs = sysent[tcp->scno].nargs; else tcp->u_nargs = tcp->status.pr_nsysarg; for (i = 0; i < tcp->u_nargs; i++) tcp->u_arg[i] = tcp->status.pr_sysarg[i]; # elif defined(I386) - if (tcp->scno >= 0 && tcp->scno < nsyscalls) + if (SCNO_IN_RANGE(tcp->scno)) tcp->u_nargs = sysent[tcp->scno].nargs; else tcp->u_nargs = 5; @@ -1698,7 +1699,7 @@ syscall_enter(struct tcb *tcp) # endif #endif /* SVR4 */ #ifdef FREEBSD - if (tcp->scno >= 0 && tcp->scno < nsyscalls && + if (SCNO_IN_RANGE(tcp->scno) && sysent[tcp->scno].nargs > tcp->status.val) tcp->u_nargs = sysent[tcp->scno].nargs; else @@ -1756,7 +1757,7 @@ trace_syscall_entering(struct tcb *tcp) tcp_last = tcp; if (scno_good != 1) tprintf("????" /* anti-trigraph gap */ "("); - else if (tcp->scno >= nsyscalls || tcp->scno < 0) + else if (!SCNO_IN_RANGE(tcp->scno)) tprintf("syscall_%lu(", tcp->scno); else tprintf("%s(", sysent[tcp->scno].sys_name); @@ -1857,7 +1858,7 @@ trace_syscall_entering(struct tcb *tcp) internal_syscall(tcp); - if ((tcp->scno >= 0 && tcp->scno < nsyscalls && + if ((SCNO_IN_RANGE(tcp->scno) && !(qual_flags[tcp->scno] & QUAL_TRACE)) || (tracing_paths && !pathtrace_match(tcp))) { tcp->flags |= TCB_INSYSCALL | TCB_FILTERED; @@ -1874,11 +1875,11 @@ trace_syscall_entering(struct tcb *tcp) printleader(tcp); tcp->flags &= ~TCB_REPRINT; tcp_last = tcp; - if (tcp->scno >= nsyscalls || tcp->scno < 0) + if (!SCNO_IN_RANGE(tcp->scno)) tprintf("syscall_%lu(", tcp->scno); else tprintf("%s(", sysent[tcp->scno].sys_name); - if (tcp->scno >= nsyscalls || tcp->scno < 0 || + if (!SCNO_IN_RANGE(tcp->scno) || ((qual_flags[tcp->scno] & QUAL_RAW) && sysent[tcp->scno].sys_func != sys_exit)) res = printargs(tcp); @@ -2011,7 +2012,7 @@ get_error(struct tcb *tcp) int u_error = 0; #ifdef LINUX int check_errno = 1; - if (tcp->scno >= 0 && tcp->scno < nsyscalls && + if (SCNO_IN_RANGE(tcp->scno) && sysent[tcp->scno].sys_flags & SYSCALL_NEVER_FAILS) { check_errno = 0; } @@ -2257,7 +2258,7 @@ dumpio(struct tcb *tcp) return; if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS) return; - if (tcp->scno < 0 || tcp->scno >= nsyscalls) + if (!SCNO_IN_RANGE(tcp->scno)) return; if (sysent[tcp->scno].sys_func == printargs) return; @@ -2317,7 +2318,7 @@ trace_syscall_exiting(struct tcb *tcp) if (tcp->flags & TCB_REPRINT) { printleader(tcp); - if (tcp->scno >= nsyscalls || tcp->scno < 0) + if (!SCNO_IN_RANGE(tcp->scno)) tprintf("<... syscall_%lu resumed> ", tcp->scno); else tprintf("<... %s resumed> ", sysent[tcp->scno].sys_name); @@ -2340,7 +2341,7 @@ trace_syscall_exiting(struct tcb *tcp) return res; } - if (tcp->scno >= nsyscalls || tcp->scno < 0 + if (!SCNO_IN_RANGE(tcp->scno) || (qual_flags[tcp->scno] & QUAL_RAW)) sys_res = printargs(tcp); else { @@ -2360,7 +2361,7 @@ trace_syscall_exiting(struct tcb *tcp) tprintf(") "); tabto(acolumn); u_error = tcp->u_error; - if (tcp->scno >= nsyscalls || tcp->scno < 0 || + if (!SCNO_IN_RANGE(tcp->scno) || qual_flags[tcp->scno] & QUAL_RAW) { if (u_error) tprintf("= -1 (errno %ld)", u_error); |