blob: 87903c9f42ae3bd875bc3fd3118aa37612c7de5a [file] [log] [blame]
sewardjc97096c2004-06-30 09:28:04 +00001
2/*---------------------------------------------------------------*/
3/*--- ---*/
4/*--- This file (test_main.c) is ---*/
5/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
6/*--- ---*/
7/*---------------------------------------------------------------*/
8
9#include <stdio.h>
10#include <stdlib.h>
sewardjced9fe52004-07-07 11:55:36 +000011#include <assert.h>
sewardj9b1004e2004-10-30 22:25:40 +000012#include <string.h>
sewardjc97096c2004-06-30 09:28:04 +000013
sewardjced9fe52004-07-07 11:55:36 +000014#include "libvex_basictypes.h"
15#include "libvex.h"
sewardjc97096c2004-06-30 09:28:04 +000016
sewardjabe017e2004-10-29 23:42:36 +000017#include "test_main.h"
18
19
sewardjc97096c2004-06-30 09:28:04 +000020/*---------------------------------------------------------------*/
21/*--- Test ---*/
22/*---------------------------------------------------------------*/
23
sewardjce605f92004-07-05 14:39:15 +000024
sewardj2b515872004-07-05 20:50:45 +000025__attribute__ ((noreturn))
sewardj41f43bc2004-07-08 14:23:22 +000026static
sewardjce605f92004-07-05 14:39:15 +000027void failure_exit ( void )
28{
29 fprintf(stdout, "VEX did failure_exit. Bye.\n");
30 exit(1);
31}
32
sewardj41f43bc2004-07-08 14:23:22 +000033static
sewardjce605f92004-07-05 14:39:15 +000034void log_bytes ( Char* bytes, Int nbytes )
35{
36 fwrite ( bytes, 1, nbytes, stdout );
37}
38
sewardjced9fe52004-07-07 11:55:36 +000039#define N_LINEBUF 10000
sewardj41f43bc2004-07-08 14:23:22 +000040static Char linebuf[N_LINEBUF];
sewardjced9fe52004-07-07 11:55:36 +000041
sewardjf05537e2004-10-14 01:08:12 +000042#define N_ORIGBUF 1000
sewardj4459baa2004-09-10 20:00:46 +000043#define N_TRANSBUF 5000
sewardjced9fe52004-07-07 11:55:36 +000044
sewardj4459baa2004-09-10 20:00:46 +000045static UChar origbuf[N_ORIGBUF];
46static UChar transbuf[N_TRANSBUF];
sewardjced9fe52004-07-07 11:55:36 +000047
sewardj1f40a0a2004-07-21 12:28:07 +000048static Bool verbose = True;
sewardjced9fe52004-07-07 11:55:36 +000049
sewardj9b1004e2004-10-30 22:25:40 +000050/* Forwards */
sewardj9578a8b2004-11-04 19:44:48 +000051static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardjde8a5ae2004-11-06 14:20:54 +000052static IRBB* mc_instrument ( IRBB*, VexGuestLayout*, IRType );
sewardj9b1004e2004-10-30 22:25:40 +000053
sewardj5bd4d162004-11-10 13:02:48 +000054static Bool chase_into_not_ok ( Addr64 dst ) { return False; }
sewardj9b1004e2004-10-30 22:25:40 +000055
sewardjced9fe52004-07-07 11:55:36 +000056int main ( int argc, char** argv )
sewardjce605f92004-07-05 14:39:15 +000057{
sewardjced9fe52004-07-07 11:55:36 +000058 FILE* f;
59 Int i;
sewardj4459baa2004-09-10 20:00:46 +000060 UInt u, sum;
sewardjced9fe52004-07-07 11:55:36 +000061 Addr32 orig_addr;
sewardjabe017e2004-10-29 23:42:36 +000062 Int bb_number, n_bbs_done = 0;
sewardjced9fe52004-07-07 11:55:36 +000063 Int orig_nbytes, trans_used, orig_used;
64 TranslateResult tres;
sewardjb5bf2e02004-10-25 13:06:17 +000065 VexControl vcon;
sewardjced9fe52004-07-07 11:55:36 +000066
67 if (argc != 2) {
68 fprintf(stderr, "usage: vex file.org\n");
69 exit(1);
70 }
71 f = fopen(argv[1], "r");
72 if (!f) {
73 fprintf(stderr, "can't open `%s'\n", argv[1]);
74 exit(1);
75 }
76
sewardjb5bf2e02004-10-25 13:06:17 +000077 /* Run with default params. However, we can't allow bb chasing
78 since that causes the front end to get segfaults when it tries
sewardj5bd4d162004-11-10 13:02:48 +000079 to read code outside the initial BB we hand it. So when calling
80 LibVEX_Translate, send in a chase-into predicate that always
81 returns False. */
sewardjb5bf2e02004-10-25 13:06:17 +000082 LibVEX_default_VexControl ( &vcon );
sewardjb4952402004-10-26 13:24:50 +000083 vcon.iropt_level = 2;
sewardjb5bf2e02004-10-25 13:06:17 +000084
sewardjced9fe52004-07-07 11:55:36 +000085 LibVEX_Init ( &failure_exit, &log_bytes,
sewardj1f40a0a2004-07-21 12:28:07 +000086 1, /* debug_paranoia */
sewardjabe017e2004-10-29 23:42:36 +000087 TEST_VSUPPORT, /* valgrind support */
sewardjb5bf2e02004-10-25 13:06:17 +000088 &vcon );
sewardjced9fe52004-07-07 11:55:36 +000089
sewardjea64e142004-07-22 16:47:21 +000090
sewardjced9fe52004-07-07 11:55:36 +000091 while (!feof(f)) {
sewardjabe017e2004-10-29 23:42:36 +000092
sewardjced9fe52004-07-07 11:55:36 +000093 fgets(linebuf, N_LINEBUF,f);
sewardjabe017e2004-10-29 23:42:36 +000094 if (linebuf[0] == 0) continue;
sewardjced9fe52004-07-07 11:55:36 +000095 if (linebuf[0] != '.') continue;
sewardjabe017e2004-10-29 23:42:36 +000096
97 if (n_bbs_done == TEST_N_BBS) break;
98 n_bbs_done++;
99
sewardjced9fe52004-07-07 11:55:36 +0000100 /* first line is: . bb-number bb-addr n-bytes */
101 assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
102 & bb_number,
sewardjabe017e2004-10-29 23:42:36 +0000103 & orig_addr, & orig_nbytes ));
sewardjced9fe52004-07-07 11:55:36 +0000104 assert(orig_nbytes >= 1);
105 assert(!feof(f));
106 fgets(linebuf, N_LINEBUF,f);
107 assert(linebuf[0] == '.');
sewardjabe017e2004-10-29 23:42:36 +0000108
sewardjced9fe52004-07-07 11:55:36 +0000109 /* second line is: . byte byte byte etc */
sewardj1f40a0a2004-07-21 12:28:07 +0000110 if (verbose)
sewardj4459baa2004-09-10 20:00:46 +0000111 printf("============ Basic Block %d, "
112 "Start %x, nbytes %2d ============",
sewardjabe017e2004-10-29 23:42:36 +0000113 n_bbs_done-1, orig_addr, orig_nbytes);
114
sewardjced9fe52004-07-07 11:55:36 +0000115 assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
116 for (i = 0; i < orig_nbytes; i++) {
sewardjabe017e2004-10-29 23:42:36 +0000117 assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
118 origbuf[i] = (UChar)u;
sewardjced9fe52004-07-07 11:55:36 +0000119 }
120
sewardjabe017e2004-10-29 23:42:36 +0000121 for (i = 0; i < TEST_N_ITERS; i++)
122 tres
123 = LibVEX_Translate (
124 InsnSetX86, InsnSetX86,
sewardj5bd4d162004-11-10 13:02:48 +0000125 origbuf, (Addr64)orig_addr, chase_into_not_ok,
126 &orig_used,
sewardjabe017e2004-10-29 23:42:36 +0000127 transbuf, N_TRANSBUF, &trans_used,
sewardjde8a5ae2004-11-06 14:20:54 +0000128#if 0 /* addrcheck */
129 ac_instrument, /* instrument1 */
130 NULL, /* instrument2 */
131 False, /* cleanup after instrument */
132#endif
133#if 1 /* memcheck */
134 mc_instrument, /* instrument1 */
135 NULL, /* instrument2 */
136 False, /* cleanup after instrument */
137#endif
sewardjabe017e2004-10-29 23:42:36 +0000138 NULL, /* access checker */
139 TEST_FLAGS
140 );
141
sewardj4459baa2004-09-10 20:00:46 +0000142 if (tres != TransOK)
143 printf("\ntres = %d\n", (Int)tres);
sewardjced9fe52004-07-07 11:55:36 +0000144 assert(tres == TransOK);
145 assert(orig_used == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000146
sewardj4459baa2004-09-10 20:00:46 +0000147 sum = 0;
148 for (i = 0; i < trans_used; i++)
149 sum += (UInt)transbuf[i];
150 printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
sewardjced9fe52004-07-07 11:55:36 +0000151 }
152
153 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000154 printf("\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000155 LibVEX_ClearTemporary(True);
sewardjced9fe52004-07-07 11:55:36 +0000156
sewardjce605f92004-07-05 14:39:15 +0000157 return 0;
158}
sewardj9b1004e2004-10-30 22:25:40 +0000159
160//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000161//////////////////////////////////////////////////////////////////////
162//////////////////////////////////////////////////////////////////////
163//////////////////////////////////////////////////////////////////////
164//////////////////////////////////////////////////////////////////////
165//////////////////////////////////////////////////////////////////////
166//////////////////////////////////////////////////////////////////////
167//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000168
169static
sewardjde8a5ae2004-11-06 14:20:54 +0000170__attribute((noreturn))
sewardj9b1004e2004-10-30 22:25:40 +0000171void panic ( Char* s )
172{
173 printf("\npanic: %s\n", s);
174 failure_exit();
175}
176
177static
sewardj9578a8b2004-11-04 19:44:48 +0000178IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000179{
180/* Use this rather than eg. -1 because it's a UInt. */
181#define INVALID_DATA_SIZE 999999
182
183 Int i;
184 Int sz;
185 IRCallee* helper;
186 IRStmt* st;
187 IRExpr* data;
188 IRExpr* addr;
189 Bool needSz;
190
191 /* Set up BB */
192 IRBB* bb = emptyIRBB();
193 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
194 bb->next = dopyIRExpr(bb_in->next);
195 bb->jumpkind = bb_in->jumpkind;
196
197 /* No loads to consider in ->next. */
198 assert(isAtom(bb_in->next));
199
200 for (i = 0; i < bb_in->stmts_used; i++) {
201 st = bb_in->stmts[i];
202 if (!st) continue;
203
204 switch (st->tag) {
205
206 case Ist_Tmp:
207 data = st->Ist.Tmp.data;
208 if (data->tag == Iex_LDle) {
209 addr = data->Iex.LDle.addr;
210 sz = sizeofIRType(data->Iex.LDle.ty);
211 needSz = False;
212 switch (sz) {
213 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000214 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000215 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000216 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000217 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000218 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000219 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000220 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000221 needSz = True; break;
222 }
223 if (needSz) {
224 addStmtToIRBB(
225 bb,
226 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000227 unsafeIRDirty_0_N( helper->regparms,
228 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000229 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
230 ));
231 } else {
232 addStmtToIRBB(
233 bb,
234 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000235 unsafeIRDirty_0_N( helper->regparms,
236 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000237 mkIRExprVec_1(addr) )
238 ));
239 }
240 }
241 break;
242
243 case Ist_STle:
244 data = st->Ist.STle.data;
245 addr = st->Ist.STle.addr;
246 assert(isAtom(data));
247 assert(isAtom(addr));
248 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
249 needSz = False;
250 switch (sz) {
251 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000252 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000253 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000254 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000255 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000256 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000257 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000258 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000259 needSz = True; break;
260 }
261 if (needSz) {
262 addStmtToIRBB(
263 bb,
264 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000265 unsafeIRDirty_0_N( helper->regparms,
266 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000267 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
268 ));
269 } else {
270 addStmtToIRBB(
271 bb,
272 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000273 unsafeIRDirty_0_N( helper->regparms,
274 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000275 mkIRExprVec_1(addr) )
276 ));
277 }
278 break;
279
280 case Ist_Put:
281 assert(isAtom(st->Ist.Put.data));
282 break;
283
284 case Ist_PutI:
sewardjeeac8412004-11-02 00:26:55 +0000285 assert(isAtom(st->Ist.PutI.ix));
sewardj9b1004e2004-10-30 22:25:40 +0000286 assert(isAtom(st->Ist.PutI.data));
287 break;
288
289 case Ist_Exit:
290 assert(isAtom(st->Ist.Exit.cond));
291 break;
292
293 case Ist_Dirty:
294 /* If the call doesn't interact with memory, we ain't
295 interested. */
296 if (st->Ist.Dirty.details->mFx == Ifx_None)
297 break;
298 goto unhandled;
299
300 default:
301 unhandled:
302 printf("\n");
303 ppIRStmt(st);
304 printf("\n");
305 panic("addrcheck: unhandled IRStmt");
306 }
307
308 addStmtToIRBB( bb, dopyIRStmt(st));
309 }
310
311 return bb;
312}
sewardjde8a5ae2004-11-06 14:20:54 +0000313
314//////////////////////////////////////////////////////////////////////
315//////////////////////////////////////////////////////////////////////
316//////////////////////////////////////////////////////////////////////
317//////////////////////////////////////////////////////////////////////
318//////////////////////////////////////////////////////////////////////
319//////////////////////////////////////////////////////////////////////
320//////////////////////////////////////////////////////////////////////
321//////////////////////////////////////////////////////////////////////
322
323#define sk_assert(xxx) assert(xxx)
324#define VG_(xxxx) xxxx
325#define skin_panic(zzz) panic(zzz)
326#define MC_(zzzz) MC_##zzzz
327#define SK_(zzzz) SK_##zzzz
328
329void MC_helperc_complain_undef ( void ) { }
330void MC_helperc_LOADV4 ( void ) { }
331void MC_helperc_LOADV2 ( void ) { }
332void MC_helperc_LOADV1 ( void ) { }
333void MC_helperc_STOREV4( void ) { }
334void MC_helperc_STOREV2( void ) { }
335void MC_helperc_STOREV1( void ) { }
336
337
338/*------------------------------------------------------------*/
339/*--- Forward decls ---*/
340/*------------------------------------------------------------*/
341
342struct _MCEnv;
343
344static IRType shadowType ( IRType ty );
345static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
346
347
348/*------------------------------------------------------------*/
349/*--- Memcheck running state, and tmp management. ---*/
350/*------------------------------------------------------------*/
351
352/* Carries around state during memcheck instrumentation. */
353typedef
354 struct _MCEnv {
355 /* MODIFIED: the bb being constructed. IRStmts are added. */
356 IRBB* bb;
357
358 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
359 original temps to their current their current shadow temp.
360 Initially all entries are IRTemp_INVALID. Entries are added
361 lazily since many original temps are not used due to
362 optimisation prior to instrumentation. Note that floating
363 point original tmps are shadowed by integer tmps of the same
364 size, and Bit-typed original tmps are shadowed by the type
365 Ity_I8. See comment below. */
366 IRTemp* tmpMap;
367 Int n_originalTmps; /* for range checking */
368
369 /* READONLY: the guest layout. This indicates which parts of
370 the guest state should be regarded as 'always defined'. */
371 VexGuestLayout* layout;
372 /* READONLY: the host word type. Needed for constructing
373 arguments of type 'HWord' to be passed to helper functions.
374 Ity_I32 or Ity_I64 only. */
375 IRType hWordTy;
376 }
377 MCEnv;
378
379/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
380 demand), as they are encountered. This is for two reasons.
381
382 (1) (less important reason): Many original tmps are unused due to
383 initial IR optimisation, and we do not want to spaces in tables
384 tracking them.
385
386 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
387 table indexed [0 .. n_types-1], which gives the current shadow for
388 each original tmp, or INVALID_IRTEMP if none is so far assigned.
389 It is necessary to support making multiple assignments to a shadow
390 -- specifically, after testing a shadow for definedness, it needs
391 to be made defined. But IR's SSA property disallows this.
392
393 (2) (more important reason): Therefore, when a shadow needs to get
394 a new value, a new temporary is created, the value is assigned to
395 that, and the tmpMap is updated to reflect the new binding.
396
397 A corollary is that if the tmpMap maps a given tmp to
398 INVALID_IRTEMP and we are hoping to read that shadow tmp, it means
399 there's a read-before-write error in the original tmps. The IR
400 sanity checker should catch all such anomalies, however.
401*/
402
403/* Find the tmp currently shadowing the given original tmp. If none
404 so far exists, allocate one. */
405static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
406{
407 sk_assert(orig < mce->n_originalTmps);
408 if (mce->tmpMap[orig] == INVALID_IRTEMP) {
409 mce->tmpMap[orig]
410 = newIRTemp(mce->bb->tyenv,
411 shadowType(mce->bb->tyenv->types[orig]));
412 }
413 return mce->tmpMap[orig];
414}
415
416/* Allocate a new shadow for the given original tmp. This means any
417 previous shadow is abandoned. This is needed because it is
418 necessary to give a new value to a shadow once it has been tested
419 for undefinedness, but unfortunately IR's SSA property disallows
420 this. Instead we must abandon the old shadow, allocate a new one
421 and use that instead. */
422static void newShadowTmp ( MCEnv* mce, IRTemp orig )
423{
424 sk_assert(orig < mce->n_originalTmps);
425 mce->tmpMap[orig]
426 = newIRTemp(mce->bb->tyenv,
427 shadowType(mce->bb->tyenv->types[orig]));
428}
429
430
431/*------------------------------------------------------------*/
432/*--- IRAtoms -- a subset of IRExprs ---*/
433/*------------------------------------------------------------*/
434
435/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
436 isAtom() in libvex_ir.h. Because this instrumenter expects flat
437 input, most of this code deals in atoms. Usefully, a value atom
438 always has a V-value which is also an atom: constants are shadowed
439 by constants, and temps are shadowed by the corresponding shadow
440 temporary. */
441
442typedef IRExpr IRAtom;
443
444/* (used for sanity checks only): is this an atom which looks
445 like it's from original code? */
446static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
447{
448 if (a1->tag == Iex_Const)
449 return True;
450 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
451 return True;
452 return False;
453}
454
455/* (used for sanity checks only): is this an atom which looks
456 like it's from shadow code? */
457static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
458{
459 if (a1->tag == Iex_Const)
460 return True;
461 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
462 return True;
463 return False;
464}
465
466/* (used for sanity checks only): check that both args are atoms and
467 are identically-kinded. */
468static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
469{
470 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
471 return True;
472 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
473 return True;
474 return False;
475}
476
477
478/*------------------------------------------------------------*/
479/*--- Type management ---*/
480/*------------------------------------------------------------*/
481
482/* Shadow state is always accessed using integer types. This returns
483 an integer type with the same size (as per sizeofIRType) as the
484 given type. The only valid shadow types are Bit, I8, I16, I32,
485 I64. */
486
487static IRType shadowType ( IRType ty )
488{
489 switch (ty) {
490 case Ity_Bit:
491 case Ity_I8:
492 case Ity_I16:
493 case Ity_I32:
494 case Ity_I64: return ty;
495 case Ity_F32: return Ity_I32;
496 case Ity_F64: return Ity_I64;
497 default: ppIRType(ty);
498 VG_(skin_panic)("memcheck:shadowType");
499 }
500}
501
502/* Produce a 'defined' value of the given shadow type. Should only be
503 supplied shadow types (Bit/I8/I16/I32/UI64). */
504static IRExpr* definedOfType ( IRType ty ) {
505 switch (ty) {
506 case Ity_Bit: return IRExpr_Const(IRConst_Bit(False));
507 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
508 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
509 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
510 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
511 default: VG_(skin_panic)("memcheck:definedOfType");
512 }
513}
514
515
516/*------------------------------------------------------------*/
517/*--- Constructing IR fragments ---*/
518/*------------------------------------------------------------*/
519
520/* assign value to tmp */
521#define assign(_bb,_tmp,_expr) \
522 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
523
524/* add stmt to a bb */
525#define stmt(_bb,_stmt) \
526 addStmtToIRBB((_bb), (_stmt))
527
528/* build various kinds of expressions */
529#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
530#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
531#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
532#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
533#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
534#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
535#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
536
537/* bind the given expression to a new temporary, and return the
538 temporary. This effectively converts an arbitrary expression into
539 an atom. */
540static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
541 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
542 assign(mce->bb, t, e);
543 return mkexpr(t);
544}
545
546
547/*------------------------------------------------------------*/
548/*--- Constructing definedness primitive ops ---*/
549/*------------------------------------------------------------*/
550
551/* --------- Defined-if-either-defined --------- */
552
553static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
554 sk_assert(isShadowAtom(mce,a1));
555 sk_assert(isShadowAtom(mce,a2));
556 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
557}
558
559static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
560 sk_assert(isShadowAtom(mce,a1));
561 sk_assert(isShadowAtom(mce,a2));
562 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
563}
564
565static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
566 sk_assert(isShadowAtom(mce,a1));
567 sk_assert(isShadowAtom(mce,a2));
568 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
569}
570
571/* --------- Undefined-if-either-undefined --------- */
572
573static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
574 sk_assert(isShadowAtom(mce,a1));
575 sk_assert(isShadowAtom(mce,a2));
576 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
577}
578
579static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
580 sk_assert(isShadowAtom(mce,a1));
581 sk_assert(isShadowAtom(mce,a2));
582 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
583}
584
585static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
586 sk_assert(isShadowAtom(mce,a1));
587 sk_assert(isShadowAtom(mce,a2));
588 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
589}
590
591static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
592 sk_assert(isShadowAtom(mce,a1));
593 sk_assert(isShadowAtom(mce,a2));
594 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
595}
596
597static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
598 switch (vty) {
599 case Ity_I32: return mkUifU32(mce, a1, a2);
600 case Ity_I64: return mkUifU64(mce, a1, a2);
601 default:
602 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
603 VG_(skin_panic)("memcheck:mkUifU");
604 }
605}
606
607/* --------- The Left-family of operations. --------- */
608
609static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
610 sk_assert(isShadowAtom(mce,a1));
611 /* It's safe to duplicate a1 since it's only an atom */
612 return assignNew(mce, Ity_I8,
613 binop(Iop_Or8, a1,
614 assignNew(mce, Ity_I8,
615 /* unop(Iop_Neg8, a1)))); */
616 binop(Iop_Sub8, mkU8(0), a1) )));
617}
618
619static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
620 sk_assert(isShadowAtom(mce,a1));
621 /* It's safe to duplicate a1 since it's only an atom */
622 return assignNew(mce, Ity_I16,
623 binop(Iop_Or16, a1,
624 assignNew(mce, Ity_I16,
625 /* unop(Iop_Neg16, a1)))); */
626 binop(Iop_Sub16, mkU16(0), a1) )));
627}
628
629static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
630 sk_assert(isShadowAtom(mce,a1));
631 /* It's safe to duplicate a1 since it's only an atom */
632 return assignNew(mce, Ity_I32,
633 binop(Iop_Or32, a1,
634 assignNew(mce, Ity_I32,
635 /* unop(Iop_Neg32, a1)))); */
636 binop(Iop_Sub32, mkU32(0), a1) )));
637}
638
639/* --------- 'Improvement' functions for AND/OR. --------- */
640
641/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
642 defined (0); all other -> undefined (1).
643*/
644static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
645{
646 sk_assert(isOriginalAtom(mce, data));
647 sk_assert(isShadowAtom(mce, vbits));
648 sk_assert(sameKindedAtoms(data, vbits));
649 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
650}
651
652static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
653{
654 sk_assert(isOriginalAtom(mce, data));
655 sk_assert(isShadowAtom(mce, vbits));
656 sk_assert(sameKindedAtoms(data, vbits));
657 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
658}
659
660/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
661 defined (0); all other -> undefined (1).
662*/
663static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
664{
665 sk_assert(isOriginalAtom(mce, data));
666 sk_assert(isShadowAtom(mce, vbits));
667 sk_assert(sameKindedAtoms(data, vbits));
668 return assignNew(
669 mce, Ity_I8,
670 binop(Iop_Or8,
671 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
672 vbits) );
673}
674
675static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
676{
677 sk_assert(isOriginalAtom(mce, data));
678 sk_assert(isShadowAtom(mce, vbits));
679 sk_assert(sameKindedAtoms(data, vbits));
680 return assignNew(
681 mce, Ity_I16,
682 binop(Iop_Or16,
683 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
684 vbits) );
685}
686
687static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
688{
689 sk_assert(isOriginalAtom(mce, data));
690 sk_assert(isShadowAtom(mce, vbits));
691 sk_assert(sameKindedAtoms(data, vbits));
692 return assignNew(
693 mce, Ity_I32,
694 binop(Iop_Or32,
695 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
696 vbits) );
697}
698
699/* --------- Pessimising casts. --------- */
700
701static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
702{
703 /* Note, dst_ty is a shadow type, not an original type. */
704 /* First of all, collapse vbits down to a single bit. */
705 sk_assert(isShadowAtom(mce,vbits));
706 IRType ty = typeOfIRExpr(mce->bb->tyenv, vbits);
707 IRAtom* tmp1 = NULL;
708 switch (ty) {
709 case Ity_Bit:
710 tmp1 = vbits;
711 break;
712 case Ity_I8:
713 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE8, vbits, mkU8(0)));
714 break;
715 case Ity_I16:
716 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE16, vbits, mkU16(0)));
717 break;
718 case Ity_I32:
719 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE32, vbits, mkU32(0)));
720 break;
721 case Ity_I64:
722 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE64, vbits, mkU64(0)));
723 break;
724 default:
725 VG_(skin_panic)("mkPCastTo(1)");
726 }
727 sk_assert(tmp1);
728 /* Now widen up to the dst type. */
729 switch (dst_ty) {
730 case Ity_Bit:
731 return tmp1;
732 case Ity_I16:
733 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
734 case Ity_I32:
735 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
736 case Ity_I64:
737 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
738 default:
739 ppIRType(dst_ty);
740 VG_(skin_panic)("mkPCastTo(2)");
741 }
742}
743
744
745/*------------------------------------------------------------*/
746/*--- Emit a test and complaint if something is undefined. ---*/
747/*------------------------------------------------------------*/
748
749/* Set the annotations on a dirty helper to indicate that the stack
750 pointer and instruction pointers might be read. This is the
751 behaviour of all 'emit-a-complaint' style functions we might
752 call. */
753
754static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
755 di->nFxState = 2;
756 di->fxState[0].fx = Ifx_Read;
757 di->fxState[0].offset = mce->layout->offset_SP;
758 di->fxState[0].size = mce->layout->sizeof_SP;
759 di->fxState[1].fx = Ifx_Read;
760 di->fxState[1].offset = mce->layout->offset_IP;
761 di->fxState[1].size = mce->layout->sizeof_IP;
762}
763
764
765/* Check the supplied **original** atom for undefinedness, and emit a
766 complaint if so. Once that happens, mark it as defined. This is
767 possible because the atom is either a tmp or literal. If it's a
768 tmp, it will be shadowed by a tmp, and so we can set the shadow to
769 be defined. In fact as mentioned above, we will have to allocate a
770 new tmp to carry the new 'defined' shadow value, and update the
771 original->tmp mapping accordingly; we cannot simply assign a new
772 value to an existing shadow tmp as this breaks SSAness -- resulting
773 in the post-instrumentation sanity checker spluttering in disapproval.
774*/
775static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
776{
777 //static Int zzz=0;
778
779 /* Since the original expression is atomic, there's no duplicated
780 work generated by making multiple V-expressions for it. So we
781 don't really care about the possibility that someone else may
782 also create a V-interpretion for it. */
783 sk_assert(isOriginalAtom(mce, atom));
784 IRAtom* vatom = expr2vbits( mce, atom );
785 sk_assert(isShadowAtom(mce, vatom));
786 sk_assert(sameKindedAtoms(atom, vatom));
787
788 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
789
790 /* sz is only used for constructing the error message */
791 Int sz = ty==Ity_Bit ? 0 : sizeofIRType(ty);
792
793 IRAtom* cond = mkPCastTo( mce, Ity_Bit, vatom );
794 /* cond will be 0 if all defined, and 1 if any not defined. */
795
796 IRDirty* di
797 = unsafeIRDirty_0_N( 1/*regparms*/,
798 "MC_(helperc_complain_undef)",
799 &MC_(helperc_complain_undef),
800 mkIRExprVec_1( mkIRExpr_HWord( sz
801 // zzz++
802 ) ));
803 di->guard = cond;
804 setHelperAnns( mce, di );
805 stmt( mce->bb, IRStmt_Dirty(di));
806
807 /* Set the shadow tmp to be defined. First, update the
808 orig->shadow tmp mapping to reflect the fact that this shadow is
809 getting a new value. */
810 sk_assert(isAtom(vatom));
811 /* sameKindedAtoms ... */
812 if (vatom->tag == Iex_Tmp) {
813 sk_assert(atom->tag == Iex_Tmp);
814 newShadowTmp(mce, atom->Iex.Tmp.tmp);
815 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
816 definedOfType(ty));
817 }
818}
819
820
821/*------------------------------------------------------------*/
822/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
823/*------------------------------------------------------------*/
824
825/* Examine the always-defined sections declared in layout to see if
826 the (offset,size) section is within one. Note, is is an error to
827 partially fall into such a region: (offset,size) should either be
828 completely in such a region or completely not-in such a region.
829*/
830static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
831{
832 Int minoffD, maxoffD, i;
833 Int minoff = offset;
834 Int maxoff = minoff + size - 1;
835 sk_assert((minoff & ~0xFFFF) == 0);
836 sk_assert((maxoff & ~0xFFFF) == 0);
837
838 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
839 minoffD = mce->layout->alwaysDefd[i].offset;
840 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
841 sk_assert((minoffD & ~0xFFFF) == 0);
842 sk_assert((maxoffD & ~0xFFFF) == 0);
843
844 if (maxoff < minoffD || maxoffD < minoff)
845 continue; /* no overlap */
846 if (minoff >= minoffD && maxoff <= maxoffD)
847 return True; /* completely contained in an always-defd section */
848
849 VG_(skin_panic)("memcheck:isAlwaysDefd:partial overlap");
850 }
851 return False; /* could not find any containing section */
852}
853
854
855/* Generate into bb suitable actions to shadow this Put. If the state
856 slice is marked 'always defined', do nothing. Otherwise, write the
857 supplied V bits to the shadow state.
858*/
859static
860void do_shadow_PUT ( MCEnv* mce, Int offset, IRAtom* atom )
861{
862 sk_assert(isOriginalAtom(mce, atom));
863 IRAtom* vatom = expr2vbits( mce, atom );
864 sk_assert(isShadowAtom(mce, vatom));
865 sk_assert(sameKindedAtoms(atom, vatom));
866 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
867 sk_assert(ty != Ity_Bit);
868 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
869 /* later: no ... */
870 /* emit code to emit a complaint if any of the vbits are 1. */
871 /* complainIfUndefined(mce, atom); */
872 } else {
873 /* Do a plain shadow Put. */
874 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
875 }
876}
877
878
879/* Return an expression which contains the V bits corresponding to the
880 given GETI (passed in in pieces).
881*/
882static
883void do_shadow_PUTI ( MCEnv* mce,
884 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
885{
886 sk_assert(isOriginalAtom(mce,atom));
887 IRAtom* vatom = expr2vbits( mce, atom );
888 sk_assert(sameKindedAtoms(atom, vatom));
889 IRType ty = descr->elemTy;
890 IRType tyS = shadowType(ty);
891 Int arrSize = descr->nElems * sizeofIRType(ty);
892 sk_assert(ty != Ity_Bit);
893 sk_assert(isOriginalAtom(mce,ix));
894 complainIfUndefined(mce,ix);
895 if (isAlwaysDefd(mce, descr->base, arrSize)) {
896 /* later: no ... */
897 /* emit code to emit a complaint if any of the vbits are 1. */
898 /* complainIfUndefined(mce, atom); */
899 } else {
900 /* Do a cloned version of the Put that refers to the shadow
901 area. */
902 IRArray* new_descr
903 = mkIRArray( descr->base + mce->layout->total_sizeB,
904 tyS, descr->nElems);
905 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
906 }
907}
908
909
910/* Return an expression which contains the V bits corresponding to the
911 given GET (passed in in pieces).
912*/
913static
914IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
915{
916 IRType tyS = shadowType(ty);
917 sk_assert(ty != Ity_Bit);
918 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
919 /* Always defined, return all zeroes of the relevant type */
920 return definedOfType(tyS);
921 } else {
922 /* return a cloned version of the Get that refers to the shadow
923 area. */
924 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
925 }
926}
927
928
929/* Return an expression which contains the V bits corresponding to the
930 given GETI (passed in in pieces).
931*/
932static
933IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
934{
935 IRType ty = descr->elemTy;
936 IRType tyS = shadowType(ty);
937 Int arrSize = descr->nElems * sizeofIRType(ty);
938 sk_assert(ty != Ity_Bit);
939 sk_assert(isOriginalAtom(mce,ix));
940 complainIfUndefined(mce,ix);
941 if (isAlwaysDefd(mce, descr->base, arrSize)) {
942 /* Always defined, return all zeroes of the relevant type */
943 return definedOfType(tyS);
944 } else {
945 /* return a cloned version of the Get that refers to the shadow
946 area. */
947 IRArray* new_descr
948 = mkIRArray( descr->base + mce->layout->total_sizeB,
949 tyS, descr->nElems);
950 return IRExpr_GetI( new_descr, ix, bias );
951 }
952}
953
954
955/*------------------------------------------------------------*/
956/*--- Generating approximations for unknown operations, ---*/
957/*--- using lazy-propagate semantics ---*/
958/*------------------------------------------------------------*/
959
960/* Lazy propagation of undefinedness from two values, resulting in the
961 specified shadow type.
962*/
963static
964IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
965{
966 /* force everything via 32-bit intermediaries. */
967 IRAtom* at;
968 sk_assert(isShadowAtom(mce,va1));
969 sk_assert(isShadowAtom(mce,va2));
970 at = mkPCastTo(mce, Ity_I32, va1);
971 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
972 at = mkPCastTo(mce, finalVty, at);
973 return at;
974}
975
976
977/* Do the lazy propagation game from a null-terminated vector of
978 atoms. This is presumably the arguments to a helper call, so the
979 IRCallee info is also supplied in order that we can know which
980 arguments should be ignored (via the .mcx_mask field).
981*/
982static
983IRAtom* mkLazyN ( MCEnv* mce,
984 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
985{
986 Int i;
987 IRAtom* here;
988 IRAtom* curr = definedOfType(Ity_I32);
989 for (i = 0; exprvec[i]; i++) {
990 sk_assert(i < 32);
991 sk_assert(isOriginalAtom(mce, exprvec[i]));
992 /* Only take notice of this arg if the callee's mc-exclusion
993 mask does not say it is to be excluded. */
994 if (cee->mcx_mask & (1<<i)) {
995 /* the arg is to be excluded from definedness checking. Do
996 nothing. */
997 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
998 } else {
999 /* calculate the arg's definedness, and pessimistically merge
1000 it in. */
1001 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1002 curr = mkUifU32(mce, here, curr);
1003 }
1004 }
1005 return mkPCastTo(mce, finalVtype, curr );
1006}
1007
1008
1009/*------------------------------------------------------------*/
1010/*--- Generating expensive sequences for exact carry-chain ---*/
1011/*--- propagation in add/sub and related operations. ---*/
1012/*------------------------------------------------------------*/
1013
1014static
1015IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1016 IRAtom* aa, IRAtom* bb )
1017{
1018 sk_assert(isShadowAtom(mce,qaa));
1019 sk_assert(isShadowAtom(mce,qbb));
1020 sk_assert(isOriginalAtom(mce,aa));
1021 sk_assert(isOriginalAtom(mce,bb));
1022 sk_assert(sameKindedAtoms(qaa,aa));
1023 sk_assert(sameKindedAtoms(qbb,bb));
1024
1025 IRType ty = Ity_I32;
1026 IROp opAND = Iop_And32;
1027 IROp opOR = Iop_Or32;
1028 IROp opXOR = Iop_Xor32;
1029 IROp opNOT = Iop_Not32;
1030 IROp opADD = Iop_Add32;
1031
1032 IRAtom *a_min, *b_min, *a_max, *b_max;
1033
1034 // a_min = aa & ~qaa
1035 a_min = assignNew(mce,ty,
1036 binop(opAND, aa,
1037 assignNew(mce,ty, unop(opNOT, qaa))));
1038
1039 // b_min = bb & ~qbb
1040 b_min = assignNew(mce,ty,
1041 binop(opAND, bb,
1042 assignNew(mce,ty, unop(opNOT, qbb))));
1043
1044 // a_max = aa | qaa
1045 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1046
1047 // b_max = bb | qbb
1048 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1049
1050 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1051 return
1052 assignNew(mce,ty,
1053 binop( opOR,
1054 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1055 assignNew(mce,ty,
1056 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1057 assignNew(mce,ty, binop(opADD, a_max, b_max))
1058 )
1059 )
1060 )
1061 );
1062}
1063
1064
1065/*------------------------------------------------------------*/
1066/*--- Generate shadow values from all kinds of IRExprs. ---*/
1067/*------------------------------------------------------------*/
1068
1069static
1070IRAtom* expr2vbits_Binop ( MCEnv* mce,
1071 IROp op,
1072 IRAtom* atom1, IRAtom* atom2 )
1073{
1074 IRType and_or_ty;
1075 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1076 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1077 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1078
1079 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1080 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1081
1082 sk_assert(isOriginalAtom(mce,atom1));
1083 sk_assert(isOriginalAtom(mce,atom2));
1084 sk_assert(isShadowAtom(mce,vatom1));
1085 sk_assert(isShadowAtom(mce,vatom2));
1086 sk_assert(sameKindedAtoms(atom1,vatom1));
1087 sk_assert(sameKindedAtoms(atom2,vatom2));
1088 switch (op) {
1089
1090 case Iop_F64toI32:
1091 /* First arg is I32 (rounding mode), second is F64 (data). */
1092 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1093
1094 case Iop_F64toI16:
1095 /* First arg is I32 (rounding mode), second is F64 (data). */
1096 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1097
1098 case Iop_MulF64:
1099 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1100
1101 /* non-FP after here */
1102
1103 case Iop_DivModU64to32:
1104 case Iop_DivModS64to32:
1105 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1106
1107 case Iop_32HLto64:
1108 return assignNew(mce, Ity_I64,
1109 binop(Iop_32HLto64, atom1, atom2));
1110
1111 case Iop_MullS32:
1112 case Iop_MullU32: {
1113 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1114 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1115 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1116 }
1117
1118 case Iop_Add32:
1119# if 0
1120 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1121# endif
1122 case Iop_Sub32:
1123 case Iop_Mul32:
1124 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1125
1126 case Iop_Add16:
1127 case Iop_Sub16:
1128 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1129
1130 case Iop_Sub8:
1131 case Iop_Add8:
1132 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1133
1134 case Iop_CmpLE32S: case Iop_CmpLE32U:
1135 case Iop_CmpLT32U: case Iop_CmpLT32S:
1136 case Iop_CmpEQ32: case Iop_CmpNE32:
1137 return mkPCastTo(mce, Ity_Bit, mkUifU32(mce, vatom1,vatom2));
1138
1139 case Iop_CmpEQ16:
1140 return mkPCastTo(mce, Ity_Bit, mkUifU16(mce, vatom1,vatom2));
1141
1142 case Iop_CmpEQ8: case Iop_CmpNE8:
1143 return mkPCastTo(mce, Ity_Bit, mkUifU8(mce, vatom1,vatom2));
1144
1145 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1146 /* Complain if the shift amount is undefined. Then simply
1147 shift the first arg's V bits by the real shift amount. */
1148 complainIfUndefined(mce, atom2);
1149 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1150
1151 case Iop_Shl16: case Iop_Shr16:
1152 /* Same scheme as with 32-bit shifts. */
1153 complainIfUndefined(mce, atom2);
1154 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1155
1156 case Iop_Shl8:
1157 /* Same scheme as with 32-bit shifts. */
1158 complainIfUndefined(mce, atom2);
1159 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1160
1161 case Iop_Shl64: case Iop_Shr64:
1162 /* Same scheme as with 32-bit shifts. */
1163 complainIfUndefined(mce, atom2);
1164 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1165
1166 case Iop_And32:
1167 uifu = mkUifU32; difd = mkDifD32;
1168 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
1169 case Iop_And8:
1170 uifu = mkUifU8; difd = mkDifD8;
1171 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1172
1173 case Iop_Or32:
1174 uifu = mkUifU32; difd = mkDifD32;
1175 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1176 case Iop_Or16:
1177 uifu = mkUifU16; difd = mkDifD16;
1178 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1179 case Iop_Or8:
1180 uifu = mkUifU8; difd = mkDifD8;
1181 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1182
1183 do_And_Or:
1184 return
1185 assignNew(
1186 mce,
1187 and_or_ty,
1188 difd(mce, uifu(mce, vatom1, vatom2),
1189 difd(mce, improve(mce, atom1, vatom1),
1190 improve(mce, atom2, vatom2) ) ) );
1191
1192 case Iop_Xor8:
1193 return mkUifU8(mce, vatom1, vatom2);
1194 case Iop_Xor32:
1195 return mkUifU32(mce, vatom1, vatom2);
1196
1197 default:
1198 ppIROp(op);
1199 VG_(skin_panic)("memcheck:expr2vbits_Binop");
1200 }
1201}
1202
1203
1204static
1205IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1206{
1207 IRAtom* vatom = expr2vbits( mce, atom );
1208 sk_assert(isOriginalAtom(mce,atom));
1209 switch (op) {
1210
1211 case Iop_F32toF64:
1212 case Iop_I32toF64:
1213 return mkPCastTo(mce, Ity_I64, vatom);
1214
1215 case Iop_64to32:
1216 case Iop_64HIto32:
1217 case Iop_1Uto32:
1218 case Iop_8Uto32:
1219 case Iop_16Uto32:
1220 case Iop_16Sto32:
1221 case Iop_8Sto32:
1222 return assignNew(mce, Ity_I32, unop(op, vatom));
1223
1224 case Iop_8Sto16:
1225 case Iop_32to16:
1226 return assignNew(mce, Ity_I16, unop(op, vatom));
1227
1228 case Iop_1Uto8:
1229 case Iop_32to8:
1230 return assignNew(mce, Ity_I8, unop(op, vatom));
1231
1232 case Iop_32to1:
1233 return assignNew(mce, Ity_Bit, unop(Iop_32to1, vatom));
1234
1235 case Iop_Not32:
1236 case Iop_Not8:
1237 case Iop_Not1:
1238 return vatom;
1239 default:
1240 ppIROp(op);
1241 VG_(skin_panic)("memcheck:expr2vbits_Unop");
1242 }
1243}
1244
1245
1246static
1247IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr )
1248{
1249 void* helper;
1250 Char* hname;
1251 IRDirty* di;
1252 IRTemp datavbits;
1253
1254 sk_assert(isOriginalAtom(mce,addr));
1255
1256 /* First, emit a definedness test for the address. This also sets
1257 the address (shadow) to 'defined' following the test. */
1258 complainIfUndefined( mce, addr );
1259
1260 /* Now cook up a call to the relevant helper function, to read the
1261 data V bits from shadow memory. */
1262 ty = shadowType(ty);
1263 switch (ty) {
1264 case Ity_I32: helper = &MC_(helperc_LOADV4);
1265 hname = "MC_(helperc_LOADV4)";
1266 break;
1267 case Ity_I16: helper = &MC_(helperc_LOADV2);
1268 hname = "MC_(helperc_LOADV2)";
1269 break;
1270 case Ity_I8: helper = &MC_(helperc_LOADV1);
1271 hname = "MC_(helperc_LOADV1)";
1272 break;
1273 default: ppIRType(ty);
1274 VG_(skin_panic)("memcheck:do_shadow_LDle");
1275 }
1276
1277 /* We need to have a place to park the V bits we're just about to
1278 read. */
1279 datavbits = newIRTemp(mce->bb->tyenv, ty);
1280 di = unsafeIRDirty_1_N( datavbits,
1281 1/*regparms*/, hname, helper, mkIRExprVec_1( addr ));
1282 setHelperAnns( mce, di );
1283 stmt( mce->bb, IRStmt_Dirty(di) );
1284
1285 return mkexpr(datavbits);
1286}
1287
1288
1289static
1290IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
1291 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
1292{
1293 IRAtom *vbitsC, *vbits0, *vbitsX;
1294 IRType ty;
1295 /* Given Mux0X(cond,expr0,exprX), generate
1296 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1297 That is, steer the V bits like the originals, but trash the
1298 result if the steering value is undefined. This gives
1299 lazy propagation. */
1300 sk_assert(isOriginalAtom(mce, cond));
1301 sk_assert(isOriginalAtom(mce, expr0));
1302 sk_assert(isOriginalAtom(mce, exprX));
1303
1304 vbitsC = expr2vbits(mce, cond);
1305 vbits0 = expr2vbits(mce, expr0);
1306 vbitsX = expr2vbits(mce, exprX);
1307 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1308
1309 return
1310 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1311 mkPCastTo(mce, ty, vbitsC) );
1312}
1313
1314/* --------- This is the main expression-handling function. --------- */
1315
1316static
1317IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1318{
1319 switch (e->tag) {
1320
1321 case Iex_Get:
1322 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1323
1324 case Iex_GetI:
1325 return shadow_GETI( mce, e->Iex.GetI.descr,
1326 e->Iex.GetI.ix, e->Iex.GetI.bias );
1327
1328 case Iex_Tmp:
1329 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
1330
1331 case Iex_Const:
1332 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
1333
1334 case Iex_Binop:
1335 return expr2vbits_Binop(
1336 mce,
1337 e->Iex.Binop.op,
1338 e->Iex.Binop.arg1, e->Iex.Binop.arg2
1339 );
1340
1341 case Iex_Unop:
1342 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
1343
1344 case Iex_LDle:
1345 return expr2vbits_LDle( mce, e->Iex.LDle.ty, e->Iex.LDle.addr );
1346
1347 case Iex_CCall:
1348 return mkLazyN( mce, e->Iex.CCall.args,
1349 e->Iex.CCall.retty,
1350 e->Iex.CCall.cee );
1351
1352 case Iex_Mux0X:
1353 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
1354 e->Iex.Mux0X.exprX);
1355
1356 default:
1357 VG_(printf)("\n");
1358 ppIRExpr(e);
1359 VG_(printf)("\n");
1360 VG_(skin_panic)("memcheck: expr2vbits");
1361 }
1362}
1363
1364/*------------------------------------------------------------*/
1365/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
1366/*------------------------------------------------------------*/
1367
1368/* Widen a value to the host word size. */
1369
1370static
1371IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
1372{
1373 /* vatom is vbits-value and as such can only have a shadow type. */
1374 sk_assert(isShadowAtom(mce,vatom));
1375
1376 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
1377 IRType tyH = mce->hWordTy;
1378
1379 if (tyH == Ity_I32) {
1380 switch (ty) {
1381 case Ity_I32: return vatom;
1382 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
1383 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
1384 default: goto unhandled;
1385 }
1386 } else {
1387 goto unhandled;
1388 }
1389 unhandled:
1390 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
1391 VG_(skin_panic)("zwidenToHostWord");
1392}
1393
1394
1395static
1396void do_shadow_STle ( MCEnv* mce, IRAtom* addr, IRAtom* data )
1397{
1398 IRType ty;
1399 IRDirty* di;
1400 IRExpr* datavbits;
1401 void* helper = NULL;
1402 Char* hname = NULL;
1403
1404 ty = shadowType(typeOfIRExpr(mce->bb->tyenv, data));
1405
1406 sk_assert(isOriginalAtom(mce,addr));
1407 sk_assert(isOriginalAtom(mce,data));
1408
1409 /* First, emit a definedness test for the address. This also sets
1410 the address (shadow) to 'defined' following the test. */
1411 complainIfUndefined( mce, addr);
1412
1413 /* Now cook up a call to the relevant helper function, to write the
1414 data V bits into shadow memory. */
1415 datavbits = expr2vbits( mce, data );
1416 switch (ty) {
1417 case Ity_I32: helper = &MC_(helperc_STOREV4);
1418 hname = "MC_(helperc_STOREV4)";
1419 break;
1420 case Ity_I16: helper = &MC_(helperc_STOREV2);
1421 hname = "MC_(helperc_STOREV2)";
1422 break;
1423 case Ity_I8: helper = &MC_(helperc_STOREV1);
1424 hname = "MC_(helperc_STOREV1)";
1425 break;
1426 default: VG_(skin_panic)("memcheck:do_shadow_STle");
1427 }
1428
1429 di = unsafeIRDirty_0_N(
1430 2/*regparms*/, hname, helper,
1431 mkIRExprVec_2( addr,
1432 zwidenToHostWord( mce, datavbits )));
1433 setHelperAnns( mce, di );
1434 stmt( mce->bb, IRStmt_Dirty(di) );
1435}
1436
1437
1438/*------------------------------------------------------------*/
1439/*--- Memcheck main ---*/
1440/*------------------------------------------------------------*/
1441
1442IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
1443{
1444 Bool verboze = False;
1445 //True;
1446
1447 Int i, j, first_stmt;
1448 IRStmt* st;
1449 MCEnv mce;
1450
1451 /* Set up BB */
1452 IRBB* bb = emptyIRBB();
1453 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1454 bb->next = dopyIRExpr(bb_in->next);
1455 bb->jumpkind = bb_in->jumpkind;
1456
1457 /* Set up the running environment. Only .bb is modified as we go
1458 along. */
1459 mce.bb = bb;
1460 mce.layout = layout;
1461 mce.n_originalTmps = bb->tyenv->types_used;
1462 mce.hWordTy = hWordTy;
1463 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
1464 for (i = 0; i < mce.n_originalTmps; i++)
1465 mce.tmpMap[i] = INVALID_IRTEMP;
1466
1467 /* Iterate over the stmts. */
1468
1469 for (i = 0; i < bb_in->stmts_used; i++) {
1470 st = bb_in->stmts[i];
1471 if (!st) continue;
1472
1473 sk_assert(isFlatIRStmt(st));
1474 first_stmt = bb->stmts_used;
1475
1476 if (verboze) {
1477 ppIRStmt(st);
1478 VG_(printf)("\n\n");
1479 }
1480
1481 switch (st->tag) {
1482
1483 case Ist_Tmp:
1484 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
1485 expr2vbits( &mce, st->Ist.Tmp.data) );
1486 break;
1487
1488 case Ist_Put:
1489 do_shadow_PUT( &mce,
1490 st->Ist.Put.offset,
1491 st->Ist.Put.data );
1492 break;
1493
1494 case Ist_PutI:
1495 do_shadow_PUTI( &mce,
1496 st->Ist.PutI.descr,
1497 st->Ist.PutI.ix,
1498 st->Ist.PutI.bias,
1499 st->Ist.PutI.data );
1500 break;
1501
1502 case Ist_STle:
1503 do_shadow_STle( &mce, st->Ist.STle.addr, st->Ist.STle.data );
1504 break;
1505
1506 case Ist_Exit:
1507 complainIfUndefined( &mce, st->Ist.Exit.cond );
1508 break;
1509
1510 default:
1511 VG_(printf)("\n");
1512 ppIRStmt(st);
1513 VG_(printf)("\n");
1514 VG_(skin_panic)("memcheck: unhandled IRStmt");
1515
1516 } /* switch (st->tag) */
1517
1518 if (verboze) {
1519 for (j = first_stmt; j < bb->stmts_used; j++) {
1520 VG_(printf)(" ");
1521 ppIRStmt(bb->stmts[j]);
1522 VG_(printf)("\n");
1523 }
1524 VG_(printf)("\n");
1525 }
1526
1527 addStmtToIRBB(bb, st);
1528
1529 }
1530
1531 /* Now we need to complain if the jump target is undefined. */
1532 first_stmt = bb->stmts_used;
1533
1534 if (verboze) {
1535 VG_(printf)("bb->next = ");
1536 ppIRExpr(bb->next);
1537 VG_(printf)("\n\n");
1538 }
1539
1540 complainIfUndefined( &mce, bb->next );
1541
1542 if (verboze) {
1543 for (j = first_stmt; j < bb->stmts_used; j++) {
1544 VG_(printf)(" ");
1545 ppIRStmt(bb->stmts[j]);
1546 VG_(printf)("\n");
1547 }
1548 VG_(printf)("\n");
1549 }
1550
1551 return bb;
1552}
1553
1554/*--------------------------------------------------------------------*/
1555/*--- end mc_translate.c ---*/
1556/*--------------------------------------------------------------------*/