]> granicus.if.org Git - strace/commitdiff
Opotimize "scno >= 0 && scno < nsyscalls" check
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 24 Aug 2011 23:13:43 +0000 (01:13 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Wed, 24 Aug 2011 23:13:43 +0000 (01:13 +0200)
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>
count.c
defs.h
syscall.c

diff --git a/count.c b/count.c
index 86b1953169adadf171e7185953da53e2621e55ad..77fc919d6f44ff2eec586ab454050999cc03c24b 100644 (file)
--- a/count.c
+++ b/count.c
@@ -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) {
diff --git a/defs.h b/defs.h
index a6b2da71f7940165d26674f7004e7aa1939256d2..d0cb058f010f45712eeff79e54fa7e80b96051f3 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -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,
index 5a09b31549cdcce81c1d53cbe1c0bc20a74fcb03..a04b0041b1089ca0f6945fbdf1928cfaa5b02cb5 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -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);