|
From: Stephen M.
|
Consider a program like the following:
#include <sys/select.h>
int main(int argc, char **argv) {
int y;
fd_set *set = (fd_set *)&y;
int which = 4;
FD_SET(which, set);
return 0;
}
"FD_SET" is a macro defined to inline to a "bts" instruction:
# define __FD_SET(fd, fdsp) \
__asm__ __volatile__ ("btsl %1,%0" \
: "=m" (__FDS_BITS (fdsp)[__FDELT (fd)]) \
: "r" (((int) (fd)) % __NFDBITS) \
: "cc","memory")
For instance, when I compile with -O (Debian gcc 3.3.5), I get an
instruction like this:
8048362: 0f ab 45 fc bts %eax,0xfffffffc(%ebp)
If I run the program under Valgrind 3, I get warnings like this from
Vex:
==27349== Memcheck, a memory error detector.
==27349== Using LibVEX rev 1139, a library for dynamic binary translation.
==27349== Using valgrind-3.0.0.SVN, a dynamic binary instrumentation framework.
==27349==
vex iropt: fold_Expr: no rule for: Shl8(0x1:I8,0x4:I8)
vex iropt: fold_Expr: no rule for: Shl8(0x0:I8,0x4:I8)
vex iropt: fold_Expr: no rule for: Shl8(0x1:I8,0x4:I8)
We of course first noticed this running a larger example, a server for
the FreeCiv game that uses select() for network connections. In fact,
there appear to be no constant folding rules at all for Shl8 (which
makes a certain amount of sense because GCC doesn't normally seem to
generate 8-bit shifts).
One potential fix would be to add such a case to the constant folding,
as in the attached patch.
Hope this helps,
-- Stephen
Index: priv/ir/iropt.c
===================================================================
--- priv/ir/iropt.c (revision 1139)
+++ priv/ir/iropt.c (working copy)
@@ -1080,6 +1080,14 @@
}
/* -- Shl -- */
+ case Iop_Shl8:
+ vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
+ shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
+ if (shift >= 0 && shift <= 7)
+ e2 = IRExpr_Const(IRConst_U8(
+ (e->Iex.Binop.arg1->Iex.Const.con->Ico.U8
+ << shift)));
+ break;
case Iop_Shl32:
vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
shift = (Int)(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8);
|