summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2011-08-25 01:13:43 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2011-08-25 01:13:43 +0200
commitcb6f056004a10d5c3ed0341366e3ddeb53cac5e6 (patch)
treeda1ecf272317cc684ee64062bbe25153630e6f24
parent1a5b5a7aff28a5c8bdafc6104508f553f50977a4 (diff)
downloadstrace-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.c2
-rw-r--r--defs.h2
-rw-r--r--syscall.c47
3 files changed, 27 insertions, 24 deletions
diff --git a/count.c b/count.c
index 86b1953..77fc919 100644
--- 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 a6b2da7..d0cb058 100644
--- 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,
diff --git a/syscall.c b/syscall.c
index 5a09b31..a04b004 100644
--- 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);