blob: 6aa4368e3413f717fe7ec8a470109186c3ab0cbe [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 ) { }
sewardj3598ef92004-11-11 02:13:30 +0000330void MC_helperc_LOADV8 ( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000331void MC_helperc_LOADV4 ( void ) { }
332void MC_helperc_LOADV2 ( void ) { }
333void MC_helperc_LOADV1 ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000334void MC_helperc_STOREV8( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000335void MC_helperc_STOREV4( void ) { }
336void MC_helperc_STOREV2( void ) { }
337void MC_helperc_STOREV1( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000338void MC_helperc_value_check0_fail( void ) { }
339void MC_helperc_value_check1_fail( void ) { }
340void MC_helperc_value_check4_fail( void ) { }
341
342
343
344/*--------------------------------------------------------------------*/
345/*--- Instrument IR to perform memory checking operations. ---*/
346/*--- mc_translate.c ---*/
347/*--------------------------------------------------------------------*/
348
349/*
350 This file is part of MemCheck, a heavyweight Valgrind tool for
351 detecting memory errors.
352
353 Copyright (C) 2000-2004 Julian Seward
354 jseward@acm.org
355
356 This program is free software; you can redistribute it and/or
357 modify it under the terms of the GNU General Public License as
358 published by the Free Software Foundation; either version 2 of the
359 License, or (at your option) any later version.
360
361 This program is distributed in the hope that it will be useful, but
362 WITHOUT ANY WARRANTY; without even the implied warranty of
363 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
364 General Public License for more details.
365
366 You should have received a copy of the GNU General Public License
367 along with this program; if not, write to the Free Software
368 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
369 02111-1307, USA.
370
371 The GNU General Public License is contained in the file COPYING.
372*/
373
374//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000375
376
377/*------------------------------------------------------------*/
378/*--- Forward decls ---*/
379/*------------------------------------------------------------*/
380
381struct _MCEnv;
382
383static IRType shadowType ( IRType ty );
384static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
385
386
387/*------------------------------------------------------------*/
388/*--- Memcheck running state, and tmp management. ---*/
389/*------------------------------------------------------------*/
390
391/* Carries around state during memcheck instrumentation. */
392typedef
393 struct _MCEnv {
394 /* MODIFIED: the bb being constructed. IRStmts are added. */
395 IRBB* bb;
396
397 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
398 original temps to their current their current shadow temp.
399 Initially all entries are IRTemp_INVALID. Entries are added
400 lazily since many original temps are not used due to
401 optimisation prior to instrumentation. Note that floating
402 point original tmps are shadowed by integer tmps of the same
403 size, and Bit-typed original tmps are shadowed by the type
404 Ity_I8. See comment below. */
405 IRTemp* tmpMap;
406 Int n_originalTmps; /* for range checking */
407
408 /* READONLY: the guest layout. This indicates which parts of
409 the guest state should be regarded as 'always defined'. */
410 VexGuestLayout* layout;
411 /* READONLY: the host word type. Needed for constructing
412 arguments of type 'HWord' to be passed to helper functions.
413 Ity_I32 or Ity_I64 only. */
414 IRType hWordTy;
415 }
416 MCEnv;
417
418/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
419 demand), as they are encountered. This is for two reasons.
420
421 (1) (less important reason): Many original tmps are unused due to
422 initial IR optimisation, and we do not want to spaces in tables
423 tracking them.
424
425 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
426 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj92d168d2004-11-15 14:22:12 +0000427 each original tmp, or IRTemp_INVALID if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000428 It is necessary to support making multiple assignments to a shadow
429 -- specifically, after testing a shadow for definedness, it needs
430 to be made defined. But IR's SSA property disallows this.
431
432 (2) (more important reason): Therefore, when a shadow needs to get
433 a new value, a new temporary is created, the value is assigned to
434 that, and the tmpMap is updated to reflect the new binding.
435
436 A corollary is that if the tmpMap maps a given tmp to
sewardj92d168d2004-11-15 14:22:12 +0000437 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000438 there's a read-before-write error in the original tmps. The IR
439 sanity checker should catch all such anomalies, however.
440*/
441
442/* Find the tmp currently shadowing the given original tmp. If none
443 so far exists, allocate one. */
444static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
445{
446 sk_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000447 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000448 mce->tmpMap[orig]
449 = newIRTemp(mce->bb->tyenv,
450 shadowType(mce->bb->tyenv->types[orig]));
451 }
452 return mce->tmpMap[orig];
453}
454
455/* Allocate a new shadow for the given original tmp. This means any
456 previous shadow is abandoned. This is needed because it is
457 necessary to give a new value to a shadow once it has been tested
458 for undefinedness, but unfortunately IR's SSA property disallows
459 this. Instead we must abandon the old shadow, allocate a new one
460 and use that instead. */
461static void newShadowTmp ( MCEnv* mce, IRTemp orig )
462{
463 sk_assert(orig < mce->n_originalTmps);
464 mce->tmpMap[orig]
465 = newIRTemp(mce->bb->tyenv,
466 shadowType(mce->bb->tyenv->types[orig]));
467}
468
469
470/*------------------------------------------------------------*/
471/*--- IRAtoms -- a subset of IRExprs ---*/
472/*------------------------------------------------------------*/
473
474/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
475 isAtom() in libvex_ir.h. Because this instrumenter expects flat
476 input, most of this code deals in atoms. Usefully, a value atom
477 always has a V-value which is also an atom: constants are shadowed
478 by constants, and temps are shadowed by the corresponding shadow
479 temporary. */
480
481typedef IRExpr IRAtom;
482
483/* (used for sanity checks only): is this an atom which looks
484 like it's from original code? */
485static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
486{
487 if (a1->tag == Iex_Const)
488 return True;
489 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
490 return True;
491 return False;
492}
493
494/* (used for sanity checks only): is this an atom which looks
495 like it's from shadow code? */
496static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
497{
498 if (a1->tag == Iex_Const)
499 return True;
500 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
501 return True;
502 return False;
503}
504
505/* (used for sanity checks only): check that both args are atoms and
506 are identically-kinded. */
507static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
508{
509 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
510 return True;
511 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
512 return True;
513 return False;
514}
515
516
517/*------------------------------------------------------------*/
518/*--- Type management ---*/
519/*------------------------------------------------------------*/
520
521/* Shadow state is always accessed using integer types. This returns
522 an integer type with the same size (as per sizeofIRType) as the
523 given type. The only valid shadow types are Bit, I8, I16, I32,
524 I64. */
525
526static IRType shadowType ( IRType ty )
527{
528 switch (ty) {
529 case Ity_Bit:
530 case Ity_I8:
531 case Ity_I16:
532 case Ity_I32:
533 case Ity_I64: return ty;
534 case Ity_F32: return Ity_I32;
535 case Ity_F64: return Ity_I64;
536 default: ppIRType(ty);
537 VG_(skin_panic)("memcheck:shadowType");
538 }
539}
540
541/* Produce a 'defined' value of the given shadow type. Should only be
542 supplied shadow types (Bit/I8/I16/I32/UI64). */
543static IRExpr* definedOfType ( IRType ty ) {
544 switch (ty) {
545 case Ity_Bit: return IRExpr_Const(IRConst_Bit(False));
546 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
547 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
548 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
549 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
550 default: VG_(skin_panic)("memcheck:definedOfType");
551 }
552}
553
554
555/*------------------------------------------------------------*/
556/*--- Constructing IR fragments ---*/
557/*------------------------------------------------------------*/
558
559/* assign value to tmp */
560#define assign(_bb,_tmp,_expr) \
561 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
562
563/* add stmt to a bb */
564#define stmt(_bb,_stmt) \
565 addStmtToIRBB((_bb), (_stmt))
566
567/* build various kinds of expressions */
568#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
569#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
570#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
571#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
572#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
573#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
574#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
575
576/* bind the given expression to a new temporary, and return the
577 temporary. This effectively converts an arbitrary expression into
578 an atom. */
579static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
580 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
581 assign(mce->bb, t, e);
582 return mkexpr(t);
583}
584
585
586/*------------------------------------------------------------*/
587/*--- Constructing definedness primitive ops ---*/
588/*------------------------------------------------------------*/
589
590/* --------- Defined-if-either-defined --------- */
591
592static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
593 sk_assert(isShadowAtom(mce,a1));
594 sk_assert(isShadowAtom(mce,a2));
595 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
596}
597
598static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
599 sk_assert(isShadowAtom(mce,a1));
600 sk_assert(isShadowAtom(mce,a2));
601 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
602}
603
604static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
605 sk_assert(isShadowAtom(mce,a1));
606 sk_assert(isShadowAtom(mce,a2));
607 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
608}
609
610/* --------- Undefined-if-either-undefined --------- */
611
612static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
613 sk_assert(isShadowAtom(mce,a1));
614 sk_assert(isShadowAtom(mce,a2));
615 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
616}
617
618static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
619 sk_assert(isShadowAtom(mce,a1));
620 sk_assert(isShadowAtom(mce,a2));
621 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
622}
623
624static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
625 sk_assert(isShadowAtom(mce,a1));
626 sk_assert(isShadowAtom(mce,a2));
627 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
628}
629
630static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
631 sk_assert(isShadowAtom(mce,a1));
632 sk_assert(isShadowAtom(mce,a2));
633 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
634}
635
636static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
637 switch (vty) {
sewardj3598ef92004-11-11 02:13:30 +0000638 case Ity_I16: return mkUifU16(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000639 case Ity_I32: return mkUifU32(mce, a1, a2);
640 case Ity_I64: return mkUifU64(mce, a1, a2);
641 default:
642 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
643 VG_(skin_panic)("memcheck:mkUifU");
644 }
645}
646
647/* --------- The Left-family of operations. --------- */
648
649static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
650 sk_assert(isShadowAtom(mce,a1));
651 /* It's safe to duplicate a1 since it's only an atom */
652 return assignNew(mce, Ity_I8,
653 binop(Iop_Or8, a1,
654 assignNew(mce, Ity_I8,
655 /* unop(Iop_Neg8, a1)))); */
656 binop(Iop_Sub8, mkU8(0), a1) )));
657}
658
659static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
660 sk_assert(isShadowAtom(mce,a1));
661 /* It's safe to duplicate a1 since it's only an atom */
662 return assignNew(mce, Ity_I16,
663 binop(Iop_Or16, a1,
664 assignNew(mce, Ity_I16,
665 /* unop(Iop_Neg16, a1)))); */
666 binop(Iop_Sub16, mkU16(0), a1) )));
667}
668
669static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
670 sk_assert(isShadowAtom(mce,a1));
671 /* It's safe to duplicate a1 since it's only an atom */
672 return assignNew(mce, Ity_I32,
673 binop(Iop_Or32, a1,
674 assignNew(mce, Ity_I32,
675 /* unop(Iop_Neg32, a1)))); */
676 binop(Iop_Sub32, mkU32(0), a1) )));
677}
678
679/* --------- 'Improvement' functions for AND/OR. --------- */
680
681/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
682 defined (0); all other -> undefined (1).
683*/
684static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
685{
686 sk_assert(isOriginalAtom(mce, data));
687 sk_assert(isShadowAtom(mce, vbits));
688 sk_assert(sameKindedAtoms(data, vbits));
689 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
690}
691
sewardj3598ef92004-11-11 02:13:30 +0000692static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
693{
694 sk_assert(isOriginalAtom(mce, data));
695 sk_assert(isShadowAtom(mce, vbits));
696 sk_assert(sameKindedAtoms(data, vbits));
697 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
698}
699
sewardjde8a5ae2004-11-06 14:20:54 +0000700static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
701{
702 sk_assert(isOriginalAtom(mce, data));
703 sk_assert(isShadowAtom(mce, vbits));
704 sk_assert(sameKindedAtoms(data, vbits));
705 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
706}
707
708/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
709 defined (0); all other -> undefined (1).
710*/
711static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
712{
713 sk_assert(isOriginalAtom(mce, data));
714 sk_assert(isShadowAtom(mce, vbits));
715 sk_assert(sameKindedAtoms(data, vbits));
716 return assignNew(
717 mce, Ity_I8,
718 binop(Iop_Or8,
719 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
720 vbits) );
721}
722
723static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
724{
725 sk_assert(isOriginalAtom(mce, data));
726 sk_assert(isShadowAtom(mce, vbits));
727 sk_assert(sameKindedAtoms(data, vbits));
728 return assignNew(
729 mce, Ity_I16,
730 binop(Iop_Or16,
731 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
732 vbits) );
733}
734
735static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
736{
737 sk_assert(isOriginalAtom(mce, data));
738 sk_assert(isShadowAtom(mce, vbits));
739 sk_assert(sameKindedAtoms(data, vbits));
740 return assignNew(
741 mce, Ity_I32,
742 binop(Iop_Or32,
743 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
744 vbits) );
745}
746
747/* --------- Pessimising casts. --------- */
748
749static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
750{
751 /* Note, dst_ty is a shadow type, not an original type. */
752 /* First of all, collapse vbits down to a single bit. */
753 sk_assert(isShadowAtom(mce,vbits));
754 IRType ty = typeOfIRExpr(mce->bb->tyenv, vbits);
755 IRAtom* tmp1 = NULL;
756 switch (ty) {
757 case Ity_Bit:
758 tmp1 = vbits;
759 break;
760 case Ity_I8:
761 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE8, vbits, mkU8(0)));
762 break;
763 case Ity_I16:
764 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE16, vbits, mkU16(0)));
765 break;
766 case Ity_I32:
767 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE32, vbits, mkU32(0)));
768 break;
769 case Ity_I64:
770 tmp1 = assignNew(mce, Ity_Bit, binop(Iop_CmpNE64, vbits, mkU64(0)));
771 break;
772 default:
773 VG_(skin_panic)("mkPCastTo(1)");
774 }
775 sk_assert(tmp1);
776 /* Now widen up to the dst type. */
777 switch (dst_ty) {
778 case Ity_Bit:
779 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000780 case Ity_I8:
781 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000782 case Ity_I16:
783 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
784 case Ity_I32:
785 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
786 case Ity_I64:
787 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
788 default:
789 ppIRType(dst_ty);
790 VG_(skin_panic)("mkPCastTo(2)");
791 }
792}
793
794
795/*------------------------------------------------------------*/
796/*--- Emit a test and complaint if something is undefined. ---*/
797/*------------------------------------------------------------*/
798
799/* Set the annotations on a dirty helper to indicate that the stack
800 pointer and instruction pointers might be read. This is the
801 behaviour of all 'emit-a-complaint' style functions we might
802 call. */
803
804static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
805 di->nFxState = 2;
806 di->fxState[0].fx = Ifx_Read;
807 di->fxState[0].offset = mce->layout->offset_SP;
808 di->fxState[0].size = mce->layout->sizeof_SP;
809 di->fxState[1].fx = Ifx_Read;
810 di->fxState[1].offset = mce->layout->offset_IP;
811 di->fxState[1].size = mce->layout->sizeof_IP;
812}
813
814
815/* Check the supplied **original** atom for undefinedness, and emit a
816 complaint if so. Once that happens, mark it as defined. This is
817 possible because the atom is either a tmp or literal. If it's a
818 tmp, it will be shadowed by a tmp, and so we can set the shadow to
819 be defined. In fact as mentioned above, we will have to allocate a
820 new tmp to carry the new 'defined' shadow value, and update the
821 original->tmp mapping accordingly; we cannot simply assign a new
822 value to an existing shadow tmp as this breaks SSAness -- resulting
823 in the post-instrumentation sanity checker spluttering in disapproval.
824*/
825static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
826{
sewardjde8a5ae2004-11-06 14:20:54 +0000827 /* Since the original expression is atomic, there's no duplicated
828 work generated by making multiple V-expressions for it. So we
829 don't really care about the possibility that someone else may
830 also create a V-interpretion for it. */
831 sk_assert(isOriginalAtom(mce, atom));
832 IRAtom* vatom = expr2vbits( mce, atom );
833 sk_assert(isShadowAtom(mce, vatom));
834 sk_assert(sameKindedAtoms(atom, vatom));
835
836 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
837
838 /* sz is only used for constructing the error message */
839 Int sz = ty==Ity_Bit ? 0 : sizeofIRType(ty);
840
841 IRAtom* cond = mkPCastTo( mce, Ity_Bit, vatom );
842 /* cond will be 0 if all defined, and 1 if any not defined. */
843
sewardj3598ef92004-11-11 02:13:30 +0000844 IRDirty* di;
845 switch (sz) {
846 case 0:
847 di = unsafeIRDirty_0_N( 0/*regparms*/,
848 "MC_(helperc_value_check0_fail)",
849 &MC_(helperc_value_check0_fail),
850 mkIRExprVec_0()
851 );
852 break;
853 case 1:
854 di = unsafeIRDirty_0_N( 0/*regparms*/,
855 "MC_(helperc_value_check1_fail)",
856 &MC_(helperc_value_check1_fail),
857 mkIRExprVec_0()
858 );
859 break;
860 case 4:
861 di = unsafeIRDirty_0_N( 0/*regparms*/,
862 "MC_(helperc_value_check4_fail)",
863 &MC_(helperc_value_check4_fail),
864 mkIRExprVec_0()
865 );
866 break;
867 default:
868 di = unsafeIRDirty_0_N( 1/*regparms*/,
869 "MC_(helperc_complain_undef)",
870 &MC_(helperc_complain_undef),
871 mkIRExprVec_1( mkIRExpr_HWord( sz ))
872 );
873 break;
874 }
sewardjde8a5ae2004-11-06 14:20:54 +0000875 di->guard = cond;
876 setHelperAnns( mce, di );
877 stmt( mce->bb, IRStmt_Dirty(di));
878
879 /* Set the shadow tmp to be defined. First, update the
880 orig->shadow tmp mapping to reflect the fact that this shadow is
881 getting a new value. */
882 sk_assert(isAtom(vatom));
883 /* sameKindedAtoms ... */
884 if (vatom->tag == Iex_Tmp) {
885 sk_assert(atom->tag == Iex_Tmp);
886 newShadowTmp(mce, atom->Iex.Tmp.tmp);
887 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
888 definedOfType(ty));
889 }
890}
891
892
893/*------------------------------------------------------------*/
894/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
895/*------------------------------------------------------------*/
896
897/* Examine the always-defined sections declared in layout to see if
898 the (offset,size) section is within one. Note, is is an error to
899 partially fall into such a region: (offset,size) should either be
900 completely in such a region or completely not-in such a region.
901*/
902static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
903{
904 Int minoffD, maxoffD, i;
905 Int minoff = offset;
906 Int maxoff = minoff + size - 1;
907 sk_assert((minoff & ~0xFFFF) == 0);
908 sk_assert((maxoff & ~0xFFFF) == 0);
909
910 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
911 minoffD = mce->layout->alwaysDefd[i].offset;
912 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
913 sk_assert((minoffD & ~0xFFFF) == 0);
914 sk_assert((maxoffD & ~0xFFFF) == 0);
915
916 if (maxoff < minoffD || maxoffD < minoff)
917 continue; /* no overlap */
918 if (minoff >= minoffD && maxoff <= maxoffD)
919 return True; /* completely contained in an always-defd section */
920
921 VG_(skin_panic)("memcheck:isAlwaysDefd:partial overlap");
922 }
923 return False; /* could not find any containing section */
924}
925
926
927/* Generate into bb suitable actions to shadow this Put. If the state
928 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +0000929 supplied V bits to the shadow state. We can pass in either an
930 original atom or a V-atom, but not both. In the former case the
931 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +0000932*/
933static
sewardj3598ef92004-11-11 02:13:30 +0000934void do_shadow_PUT ( MCEnv* mce, Int offset,
935 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +0000936{
sewardj3598ef92004-11-11 02:13:30 +0000937 if (atom) {
938 sk_assert(!vatom);
939 sk_assert(isOriginalAtom(mce, atom));
940 vatom = expr2vbits( mce, atom );
941 } else {
942 sk_assert(vatom);
943 sk_assert(isShadowAtom(mce, vatom));
944 }
945
sewardjde8a5ae2004-11-06 14:20:54 +0000946 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
947 sk_assert(ty != Ity_Bit);
948 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
949 /* later: no ... */
950 /* emit code to emit a complaint if any of the vbits are 1. */
951 /* complainIfUndefined(mce, atom); */
952 } else {
953 /* Do a plain shadow Put. */
954 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
955 }
956}
957
958
959/* Return an expression which contains the V bits corresponding to the
960 given GETI (passed in in pieces).
961*/
962static
963void do_shadow_PUTI ( MCEnv* mce,
964 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
965{
966 sk_assert(isOriginalAtom(mce,atom));
967 IRAtom* vatom = expr2vbits( mce, atom );
968 sk_assert(sameKindedAtoms(atom, vatom));
969 IRType ty = descr->elemTy;
970 IRType tyS = shadowType(ty);
971 Int arrSize = descr->nElems * sizeofIRType(ty);
972 sk_assert(ty != Ity_Bit);
973 sk_assert(isOriginalAtom(mce,ix));
974 complainIfUndefined(mce,ix);
975 if (isAlwaysDefd(mce, descr->base, arrSize)) {
976 /* later: no ... */
977 /* emit code to emit a complaint if any of the vbits are 1. */
978 /* complainIfUndefined(mce, atom); */
979 } else {
980 /* Do a cloned version of the Put that refers to the shadow
981 area. */
982 IRArray* new_descr
983 = mkIRArray( descr->base + mce->layout->total_sizeB,
984 tyS, descr->nElems);
985 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
986 }
987}
988
989
990/* Return an expression which contains the V bits corresponding to the
991 given GET (passed in in pieces).
992*/
993static
994IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
995{
996 IRType tyS = shadowType(ty);
997 sk_assert(ty != Ity_Bit);
998 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
999 /* Always defined, return all zeroes of the relevant type */
1000 return definedOfType(tyS);
1001 } else {
1002 /* return a cloned version of the Get that refers to the shadow
1003 area. */
1004 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1005 }
1006}
1007
1008
1009/* Return an expression which contains the V bits corresponding to the
1010 given GETI (passed in in pieces).
1011*/
1012static
1013IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1014{
1015 IRType ty = descr->elemTy;
1016 IRType tyS = shadowType(ty);
1017 Int arrSize = descr->nElems * sizeofIRType(ty);
1018 sk_assert(ty != Ity_Bit);
1019 sk_assert(isOriginalAtom(mce,ix));
1020 complainIfUndefined(mce,ix);
1021 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1022 /* Always defined, return all zeroes of the relevant type */
1023 return definedOfType(tyS);
1024 } else {
1025 /* return a cloned version of the Get that refers to the shadow
1026 area. */
1027 IRArray* new_descr
1028 = mkIRArray( descr->base + mce->layout->total_sizeB,
1029 tyS, descr->nElems);
1030 return IRExpr_GetI( new_descr, ix, bias );
1031 }
1032}
1033
1034
1035/*------------------------------------------------------------*/
1036/*--- Generating approximations for unknown operations, ---*/
1037/*--- using lazy-propagate semantics ---*/
1038/*------------------------------------------------------------*/
1039
1040/* Lazy propagation of undefinedness from two values, resulting in the
1041 specified shadow type.
1042*/
1043static
1044IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1045{
1046 /* force everything via 32-bit intermediaries. */
1047 IRAtom* at;
1048 sk_assert(isShadowAtom(mce,va1));
1049 sk_assert(isShadowAtom(mce,va2));
1050 at = mkPCastTo(mce, Ity_I32, va1);
1051 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1052 at = mkPCastTo(mce, finalVty, at);
1053 return at;
1054}
1055
1056
1057/* Do the lazy propagation game from a null-terminated vector of
1058 atoms. This is presumably the arguments to a helper call, so the
1059 IRCallee info is also supplied in order that we can know which
1060 arguments should be ignored (via the .mcx_mask field).
1061*/
1062static
1063IRAtom* mkLazyN ( MCEnv* mce,
1064 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1065{
1066 Int i;
1067 IRAtom* here;
1068 IRAtom* curr = definedOfType(Ity_I32);
1069 for (i = 0; exprvec[i]; i++) {
1070 sk_assert(i < 32);
1071 sk_assert(isOriginalAtom(mce, exprvec[i]));
1072 /* Only take notice of this arg if the callee's mc-exclusion
1073 mask does not say it is to be excluded. */
1074 if (cee->mcx_mask & (1<<i)) {
1075 /* the arg is to be excluded from definedness checking. Do
1076 nothing. */
1077 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1078 } else {
1079 /* calculate the arg's definedness, and pessimistically merge
1080 it in. */
1081 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1082 curr = mkUifU32(mce, here, curr);
1083 }
1084 }
1085 return mkPCastTo(mce, finalVtype, curr );
1086}
1087
1088
1089/*------------------------------------------------------------*/
1090/*--- Generating expensive sequences for exact carry-chain ---*/
1091/*--- propagation in add/sub and related operations. ---*/
1092/*------------------------------------------------------------*/
1093
1094static
1095IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1096 IRAtom* aa, IRAtom* bb )
1097{
1098 sk_assert(isShadowAtom(mce,qaa));
1099 sk_assert(isShadowAtom(mce,qbb));
1100 sk_assert(isOriginalAtom(mce,aa));
1101 sk_assert(isOriginalAtom(mce,bb));
1102 sk_assert(sameKindedAtoms(qaa,aa));
1103 sk_assert(sameKindedAtoms(qbb,bb));
1104
1105 IRType ty = Ity_I32;
1106 IROp opAND = Iop_And32;
1107 IROp opOR = Iop_Or32;
1108 IROp opXOR = Iop_Xor32;
1109 IROp opNOT = Iop_Not32;
1110 IROp opADD = Iop_Add32;
1111
1112 IRAtom *a_min, *b_min, *a_max, *b_max;
1113
1114 // a_min = aa & ~qaa
1115 a_min = assignNew(mce,ty,
1116 binop(opAND, aa,
1117 assignNew(mce,ty, unop(opNOT, qaa))));
1118
1119 // b_min = bb & ~qbb
1120 b_min = assignNew(mce,ty,
1121 binop(opAND, bb,
1122 assignNew(mce,ty, unop(opNOT, qbb))));
1123
1124 // a_max = aa | qaa
1125 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1126
1127 // b_max = bb | qbb
1128 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1129
1130 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1131 return
1132 assignNew(mce,ty,
1133 binop( opOR,
1134 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1135 assignNew(mce,ty,
1136 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1137 assignNew(mce,ty, binop(opADD, a_max, b_max))
1138 )
1139 )
1140 )
1141 );
1142}
1143
1144
1145/*------------------------------------------------------------*/
1146/*--- Generate shadow values from all kinds of IRExprs. ---*/
1147/*------------------------------------------------------------*/
1148
1149static
1150IRAtom* expr2vbits_Binop ( MCEnv* mce,
1151 IROp op,
1152 IRAtom* atom1, IRAtom* atom2 )
1153{
1154 IRType and_or_ty;
1155 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1156 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1157 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1158
1159 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1160 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1161
1162 sk_assert(isOriginalAtom(mce,atom1));
1163 sk_assert(isOriginalAtom(mce,atom2));
1164 sk_assert(isShadowAtom(mce,vatom1));
1165 sk_assert(isShadowAtom(mce,vatom2));
1166 sk_assert(sameKindedAtoms(atom1,vatom1));
1167 sk_assert(sameKindedAtoms(atom2,vatom2));
1168 switch (op) {
1169
sewardj3598ef92004-11-11 02:13:30 +00001170 case Iop_RoundF64:
1171 case Iop_F64toI64:
1172 /* First arg is I32 (rounding mode), second is F64 (data). */
1173 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1174
1175 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1176 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001177 case Iop_F64toI32:
1178 /* First arg is I32 (rounding mode), second is F64 (data). */
1179 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1180
1181 case Iop_F64toI16:
1182 /* First arg is I32 (rounding mode), second is F64 (data). */
1183 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1184
sewardj3598ef92004-11-11 02:13:30 +00001185 case Iop_ScaleF64:
1186 case Iop_Yl2xF64:
1187 case Iop_Yl2xp1F64:
1188 case Iop_PRemF64:
1189 case Iop_AtanF64:
1190 case Iop_AddF64:
1191 case Iop_DivF64:
1192 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001193 case Iop_MulF64:
1194 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1195
sewardj3598ef92004-11-11 02:13:30 +00001196 case Iop_CmpF64:
1197 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1198
sewardjde8a5ae2004-11-06 14:20:54 +00001199 /* non-FP after here */
1200
1201 case Iop_DivModU64to32:
1202 case Iop_DivModS64to32:
1203 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1204
sewardj3598ef92004-11-11 02:13:30 +00001205 case Iop_16HLto32:
1206 return assignNew(mce, Ity_I32,
1207 binop(Iop_16HLto32, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001208 case Iop_32HLto64:
1209 return assignNew(mce, Ity_I64,
sewardj3598ef92004-11-11 02:13:30 +00001210 binop(Iop_32HLto64, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001211
1212 case Iop_MullS32:
1213 case Iop_MullU32: {
1214 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1215 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1216 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1217 }
1218
sewardj3598ef92004-11-11 02:13:30 +00001219 case Iop_MullS16:
1220 case Iop_MullU16: {
1221 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1222 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1223 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1224 }
1225
1226 case Iop_MullS8:
1227 case Iop_MullU8: {
1228 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1229 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1230 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1231 }
1232
sewardjde8a5ae2004-11-06 14:20:54 +00001233 case Iop_Add32:
1234# if 0
1235 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1236# endif
1237 case Iop_Sub32:
1238 case Iop_Mul32:
1239 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1240
sewardj3598ef92004-11-11 02:13:30 +00001241 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001242 case Iop_Add16:
1243 case Iop_Sub16:
1244 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1245
1246 case Iop_Sub8:
1247 case Iop_Add8:
1248 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1249
1250 case Iop_CmpLE32S: case Iop_CmpLE32U:
1251 case Iop_CmpLT32U: case Iop_CmpLT32S:
1252 case Iop_CmpEQ32: case Iop_CmpNE32:
1253 return mkPCastTo(mce, Ity_Bit, mkUifU32(mce, vatom1,vatom2));
1254
sewardj3598ef92004-11-11 02:13:30 +00001255 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjde8a5ae2004-11-06 14:20:54 +00001256 return mkPCastTo(mce, Ity_Bit, mkUifU16(mce, vatom1,vatom2));
1257
1258 case Iop_CmpEQ8: case Iop_CmpNE8:
1259 return mkPCastTo(mce, Ity_Bit, mkUifU8(mce, vatom1,vatom2));
1260
1261 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1262 /* Complain if the shift amount is undefined. Then simply
1263 shift the first arg's V bits by the real shift amount. */
1264 complainIfUndefined(mce, atom2);
1265 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1266
1267 case Iop_Shl16: case Iop_Shr16:
1268 /* Same scheme as with 32-bit shifts. */
1269 complainIfUndefined(mce, atom2);
1270 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1271
sewardj3598ef92004-11-11 02:13:30 +00001272 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001273 /* Same scheme as with 32-bit shifts. */
1274 complainIfUndefined(mce, atom2);
1275 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1276
1277 case Iop_Shl64: case Iop_Shr64:
1278 /* Same scheme as with 32-bit shifts. */
1279 complainIfUndefined(mce, atom2);
1280 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1281
1282 case Iop_And32:
1283 uifu = mkUifU32; difd = mkDifD32;
1284 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001285 case Iop_And16:
1286 uifu = mkUifU16; difd = mkDifD16;
1287 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001288 case Iop_And8:
1289 uifu = mkUifU8; difd = mkDifD8;
1290 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1291
1292 case Iop_Or32:
1293 uifu = mkUifU32; difd = mkDifD32;
1294 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1295 case Iop_Or16:
1296 uifu = mkUifU16; difd = mkDifD16;
1297 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1298 case Iop_Or8:
1299 uifu = mkUifU8; difd = mkDifD8;
1300 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1301
1302 do_And_Or:
1303 return
1304 assignNew(
1305 mce,
1306 and_or_ty,
1307 difd(mce, uifu(mce, vatom1, vatom2),
1308 difd(mce, improve(mce, atom1, vatom1),
1309 improve(mce, atom2, vatom2) ) ) );
1310
1311 case Iop_Xor8:
1312 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001313 case Iop_Xor16:
1314 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001315 case Iop_Xor32:
1316 return mkUifU32(mce, vatom1, vatom2);
1317
1318 default:
1319 ppIROp(op);
1320 VG_(skin_panic)("memcheck:expr2vbits_Binop");
1321 }
1322}
1323
1324
1325static
1326IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1327{
1328 IRAtom* vatom = expr2vbits( mce, atom );
1329 sk_assert(isOriginalAtom(mce,atom));
1330 switch (op) {
1331
1332 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001333 case Iop_I32toF64:
1334 case Iop_I64toF64:
1335 case Iop_NegF64:
1336 case Iop_SinF64:
1337 case Iop_CosF64:
1338 case Iop_TanF64:
1339 case Iop_SqrtF64:
1340 case Iop_AbsF64:
1341 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001342 return mkPCastTo(mce, Ity_I64, vatom);
1343
sewardj3598ef92004-11-11 02:13:30 +00001344 case Iop_F64toF32:
1345 case Iop_Clz32:
1346 case Iop_Ctz32:
1347 return mkPCastTo(mce, Ity_I32, vatom);
1348
1349 case Iop_32Sto64:
1350 case Iop_32Uto64:
1351 return assignNew(mce, Ity_I64, unop(op, vatom));
1352
sewardjde8a5ae2004-11-06 14:20:54 +00001353 case Iop_64to32:
1354 case Iop_64HIto32:
1355 case Iop_1Uto32:
1356 case Iop_8Uto32:
1357 case Iop_16Uto32:
1358 case Iop_16Sto32:
1359 case Iop_8Sto32:
1360 return assignNew(mce, Ity_I32, unop(op, vatom));
1361
1362 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001363 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001364 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001365 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001366 return assignNew(mce, Ity_I16, unop(op, vatom));
1367
1368 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001369 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001370 case Iop_32to8:
1371 return assignNew(mce, Ity_I8, unop(op, vatom));
1372
1373 case Iop_32to1:
1374 return assignNew(mce, Ity_Bit, unop(Iop_32to1, vatom));
1375
sewardj3598ef92004-11-11 02:13:30 +00001376 case Iop_ReinterpF64asI64:
1377 case Iop_ReinterpI64asF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001378 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001379 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001380 case Iop_Not8:
1381 case Iop_Not1:
1382 return vatom;
1383 default:
1384 ppIROp(op);
1385 VG_(skin_panic)("memcheck:expr2vbits_Unop");
1386 }
1387}
1388
1389
1390static
sewardj3598ef92004-11-11 02:13:30 +00001391IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001392{
1393 void* helper;
1394 Char* hname;
1395 IRDirty* di;
1396 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001397 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001398
1399 sk_assert(isOriginalAtom(mce,addr));
1400
1401 /* First, emit a definedness test for the address. This also sets
1402 the address (shadow) to 'defined' following the test. */
1403 complainIfUndefined( mce, addr );
1404
1405 /* Now cook up a call to the relevant helper function, to read the
1406 data V bits from shadow memory. */
1407 ty = shadowType(ty);
1408 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001409 case Ity_I64: helper = &MC_(helperc_LOADV8);
1410 hname = "MC_(helperc_LOADV8)";
1411 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001412 case Ity_I32: helper = &MC_(helperc_LOADV4);
1413 hname = "MC_(helperc_LOADV4)";
1414 break;
1415 case Ity_I16: helper = &MC_(helperc_LOADV2);
1416 hname = "MC_(helperc_LOADV2)";
1417 break;
1418 case Ity_I8: helper = &MC_(helperc_LOADV1);
1419 hname = "MC_(helperc_LOADV1)";
1420 break;
1421 default: ppIRType(ty);
1422 VG_(skin_panic)("memcheck:do_shadow_LDle");
1423 }
1424
sewardj3598ef92004-11-11 02:13:30 +00001425 /* Generate the actual address into addrAct. */
1426 if (bias == 0) {
1427 addrAct = addr;
1428 } else {
1429 IRType tyAddr = mce->hWordTy;
1430 sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1431 IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1432 IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
1433 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1434 }
1435
sewardjde8a5ae2004-11-06 14:20:54 +00001436 /* We need to have a place to park the V bits we're just about to
1437 read. */
1438 datavbits = newIRTemp(mce->bb->tyenv, ty);
1439 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001440 1/*regparms*/, hname, helper,
1441 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001442 setHelperAnns( mce, di );
1443 stmt( mce->bb, IRStmt_Dirty(di) );
1444
1445 return mkexpr(datavbits);
1446}
1447
1448
1449static
1450IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00001451 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00001452{
1453 IRAtom *vbitsC, *vbits0, *vbitsX;
1454 IRType ty;
1455 /* Given Mux0X(cond,expr0,exprX), generate
1456 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1457 That is, steer the V bits like the originals, but trash the
1458 result if the steering value is undefined. This gives
1459 lazy propagation. */
1460 sk_assert(isOriginalAtom(mce, cond));
1461 sk_assert(isOriginalAtom(mce, expr0));
1462 sk_assert(isOriginalAtom(mce, exprX));
1463
1464 vbitsC = expr2vbits(mce, cond);
1465 vbits0 = expr2vbits(mce, expr0);
1466 vbitsX = expr2vbits(mce, exprX);
1467 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1468
1469 return
1470 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1471 mkPCastTo(mce, ty, vbitsC) );
1472}
1473
1474/* --------- This is the main expression-handling function. --------- */
1475
1476static
1477IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1478{
1479 switch (e->tag) {
1480
1481 case Iex_Get:
1482 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1483
1484 case Iex_GetI:
1485 return shadow_GETI( mce, e->Iex.GetI.descr,
1486 e->Iex.GetI.ix, e->Iex.GetI.bias );
1487
1488 case Iex_Tmp:
1489 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
1490
1491 case Iex_Const:
1492 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
1493
1494 case Iex_Binop:
1495 return expr2vbits_Binop(
1496 mce,
1497 e->Iex.Binop.op,
1498 e->Iex.Binop.arg1, e->Iex.Binop.arg2
1499 );
1500
1501 case Iex_Unop:
1502 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
1503
1504 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00001505 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
1506 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00001507
1508 case Iex_CCall:
1509 return mkLazyN( mce, e->Iex.CCall.args,
1510 e->Iex.CCall.retty,
1511 e->Iex.CCall.cee );
1512
1513 case Iex_Mux0X:
1514 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
1515 e->Iex.Mux0X.exprX);
1516
1517 default:
1518 VG_(printf)("\n");
1519 ppIRExpr(e);
1520 VG_(printf)("\n");
1521 VG_(skin_panic)("memcheck: expr2vbits");
1522 }
1523}
1524
1525/*------------------------------------------------------------*/
1526/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
1527/*------------------------------------------------------------*/
1528
1529/* Widen a value to the host word size. */
1530
1531static
1532IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
1533{
1534 /* vatom is vbits-value and as such can only have a shadow type. */
1535 sk_assert(isShadowAtom(mce,vatom));
1536
1537 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
1538 IRType tyH = mce->hWordTy;
1539
1540 if (tyH == Ity_I32) {
1541 switch (ty) {
1542 case Ity_I32: return vatom;
1543 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
1544 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
1545 default: goto unhandled;
1546 }
1547 } else {
1548 goto unhandled;
1549 }
1550 unhandled:
1551 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
1552 VG_(skin_panic)("zwidenToHostWord");
1553}
1554
1555
sewardj3598ef92004-11-11 02:13:30 +00001556/* Generate a shadow store. addr is always the original address atom.
1557 You can pass in either originals or V-bits for the data atom, but
1558 obviously not both. */
1559
sewardjde8a5ae2004-11-06 14:20:54 +00001560static
sewardj3598ef92004-11-11 02:13:30 +00001561void do_shadow_STle ( MCEnv* mce,
1562 IRAtom* addr, UInt bias,
1563 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00001564{
1565 IRType ty;
1566 IRDirty* di;
sewardjde8a5ae2004-11-06 14:20:54 +00001567 void* helper = NULL;
1568 Char* hname = NULL;
sewardj3598ef92004-11-11 02:13:30 +00001569 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001570
sewardj3598ef92004-11-11 02:13:30 +00001571 if (data) {
1572 sk_assert(!vdata);
1573 sk_assert(isOriginalAtom(mce, data));
1574 sk_assert(bias == 0);
1575 vdata = expr2vbits( mce, data );
1576 } else {
1577 sk_assert(vdata);
1578 }
sewardjde8a5ae2004-11-06 14:20:54 +00001579
1580 sk_assert(isOriginalAtom(mce,addr));
sewardj3598ef92004-11-11 02:13:30 +00001581 sk_assert(isShadowAtom(mce,vdata));
1582
1583 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00001584
1585 /* First, emit a definedness test for the address. This also sets
1586 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00001587 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00001588
1589 /* Now cook up a call to the relevant helper function, to write the
1590 data V bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00001591 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001592 case Ity_I64: helper = &MC_(helperc_STOREV8);
1593 hname = "MC_(helperc_STOREV8)";
1594 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001595 case Ity_I32: helper = &MC_(helperc_STOREV4);
1596 hname = "MC_(helperc_STOREV4)";
1597 break;
1598 case Ity_I16: helper = &MC_(helperc_STOREV2);
1599 hname = "MC_(helperc_STOREV2)";
1600 break;
1601 case Ity_I8: helper = &MC_(helperc_STOREV1);
1602 hname = "MC_(helperc_STOREV1)";
1603 break;
1604 default: VG_(skin_panic)("memcheck:do_shadow_STle");
1605 }
1606
sewardj3598ef92004-11-11 02:13:30 +00001607 /* Generate the actual address into addrAct. */
1608 if (bias == 0) {
1609 addrAct = addr;
1610 } else {
1611 IRType tyAddr = mce->hWordTy;
1612 sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
1613 IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1614 IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
1615 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1616 }
1617
1618 if (ty == Ity_I64) {
1619 /* We can't do this with regparm 2 on 32-bit platforms, since
1620 the back ends aren't clever enough to handle 64-bit regparm
1621 args. Therefore be different. */
1622 di = unsafeIRDirty_0_N(
1623 1/*regparms*/, hname, helper,
1624 mkIRExprVec_2( addrAct, vdata ));
1625 } else {
1626 di = unsafeIRDirty_0_N(
1627 2/*regparms*/, hname, helper,
1628 mkIRExprVec_2( addrAct,
1629 zwidenToHostWord( mce, vdata )));
1630 }
sewardjde8a5ae2004-11-06 14:20:54 +00001631 setHelperAnns( mce, di );
1632 stmt( mce->bb, IRStmt_Dirty(di) );
1633}
1634
1635
sewardj3598ef92004-11-11 02:13:30 +00001636/* Do lazy pessimistic propagation through a dirty helper call, by
1637 looking at the annotations on it. This is the most complex part of
1638 Memcheck. */
1639
1640static IRType szToITy ( Int n )
1641{
1642 switch (n) {
1643 case 1: return Ity_I8;
1644 case 2: return Ity_I16;
1645 case 4: return Ity_I32;
1646 case 8: return Ity_I64;
1647 default: VG_(skin_panic)("szToITy(memcheck)");
1648 }
1649}
1650
1651static
1652void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
1653{
1654 Int i, offset, toDo;
1655 IRAtom* src;
1656 IRType tyAddr, tySrc, tyDst;
1657 IRTemp dst;
1658
1659 /* First check the guard. */
1660 complainIfUndefined(mce, d->guard);
1661
1662 /* Now round up all inputs and PCast over them. */
1663 IRAtom* here;
1664 IRAtom* curr = definedOfType(Ity_I32);
1665
1666 /* Inputs: unmasked args */
1667 for (i = 0; d->args[i]; i++) {
1668 if (d->cee->mcx_mask & (1<<i)) {
1669 /* ignore this arg */
1670 } else {
1671 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
1672 curr = mkUifU32(mce, here, curr);
1673 }
1674 }
1675
1676 /* Inputs: guest state that we read. */
1677 for (i = 0; i < d->nFxState; i++) {
1678 sk_assert(d->fxState[i].fx != Ifx_None);
1679 if (d->fxState[i].fx == Ifx_Write)
1680 continue;
1681 /* This state element is read or modified. So we need to
1682 consider it. */
1683 tySrc = szToITy( d->fxState[i].size );
1684 src = assignNew( mce, tySrc,
1685 shadow_GET(mce, d->fxState[i].offset, tySrc ) );
1686 here = mkPCastTo( mce, Ity_I32, src );
1687 curr = mkUifU32(mce, here, curr);
1688 }
1689
1690 /* Inputs: memory. First set up some info needed regardless of
1691 whether we're doing reads or writes. */
1692 tyAddr = Ity_INVALID;
1693
1694 if (d->mFx != Ifx_None) {
1695 /* Because we may do multiple shadow loads/stores from the same
1696 base address, it's best to do a single test of its
1697 definedness right now. Post-instrumentation optimisation
1698 should remove all but this test. */
1699 sk_assert(d->mAddr);
1700 complainIfUndefined(mce, d->mAddr);
1701
1702 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
1703 sk_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
1704 sk_assert(tyAddr == mce->hWordTy); /* not really right */
1705 }
1706
1707 /* Deal with memory inputs (reads or modifies) */
1708 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
1709 offset = 0;
1710 toDo = d->mSize;
1711 /* chew off 32-bit chunks */
1712 while (toDo >= 4) {
1713 here = mkPCastTo(
1714 mce, Ity_I32,
1715 expr2vbits_LDle ( mce, Ity_I32,
1716 d->mAddr, d->mSize - toDo )
1717 );
1718 curr = mkUifU32(mce, here, curr);
1719 toDo -= 4;
1720 }
1721 /* chew off 16-bit chunks */
1722 while (toDo >= 2) {
1723 here = mkPCastTo(
1724 mce, Ity_I32,
1725 expr2vbits_LDle ( mce, Ity_I16,
1726 d->mAddr, d->mSize - toDo )
1727 );
1728 curr = mkUifU32(mce, here, curr);
1729 toDo -= 2;
1730 }
1731 sk_assert(toDo == 0); /* also need to handle 1-byte excess */
1732 }
1733
1734 /* Whew! So curr is a 32-bit V-value summarising pessimistically
1735 all the inputs to the helper. Now we need to re-distribute the
1736 results to all destinations. */
1737
1738 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00001739 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00001740 dst = findShadowTmp(mce, d->tmp);
1741 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
1742 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
1743 }
1744
1745 /* Outputs: guest state that we write or modify. */
1746 for (i = 0; i < d->nFxState; i++) {
1747 sk_assert(d->fxState[i].fx != Ifx_None);
1748 if (d->fxState[i].fx == Ifx_Read)
1749 continue;
1750 /* this state element is written or modified. So we need to
1751 consider it. */
1752 tyDst = szToITy( d->fxState[i].size );
1753 do_shadow_PUT( mce, d->fxState[i].offset,
1754 NULL, /* original atom */
1755 mkPCastTo( mce, tyDst, curr ) );
1756 }
1757
1758 /* Outputs: memory that we write or modify. */
1759 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
1760 offset = 0;
1761 toDo = d->mSize;
1762 /* chew off 32-bit chunks */
1763 while (toDo >= 4) {
1764 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1765 NULL, /* original data */
1766 mkPCastTo( mce, Ity_I32, curr ) );
1767 toDo -= 4;
1768 }
1769 /* chew off 16-bit chunks */
1770 while (toDo >= 2) {
1771 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1772 NULL, /* original data */
1773 mkPCastTo( mce, Ity_I16, curr ) );
1774 toDo -= 2;
1775 }
1776 sk_assert(toDo == 0); /* also need to handle 1-byte excess */
1777 }
1778
1779}
1780
1781
sewardjde8a5ae2004-11-06 14:20:54 +00001782/*------------------------------------------------------------*/
1783/*--- Memcheck main ---*/
1784/*------------------------------------------------------------*/
1785
sewardj3598ef92004-11-11 02:13:30 +00001786#if 0 /* UNUSED */
1787static Bool isBogusAtom ( IRAtom* at )
1788{
1789 ULong n = 0;
1790 IRConst* con;
1791 sk_assert(isAtom(at));
1792 if (at->tag == Iex_Tmp)
1793 return False;
1794 sk_assert(at->tag == Iex_Const);
1795 con = at->Iex.Const.con;
1796 switch (con->tag) {
1797 case Ico_U8: n = (ULong)con->Ico.U8; break;
1798 case Ico_U16: n = (ULong)con->Ico.U16; break;
1799 case Ico_U32: n = (ULong)con->Ico.U32; break;
1800 case Ico_U64: n = (ULong)con->Ico.U64; break;
1801 default: ppIRExpr(at); sk_assert(0);
1802 }
1803 /* VG_(printf)("%llx\n", n); */
1804 return (n == 0xFEFEFEFF
1805 || n == 0x80808080
1806 || n == 0x1010101
1807 || n == 1010100);
1808}
1809
1810static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
1811{
1812 Int i;
1813 IRExpr* e;
1814 switch (st->tag) {
1815 case Ist_Tmp:
1816 e = st->Ist.Tmp.data;
1817 switch (e->tag) {
1818 case Iex_Get:
1819 case Iex_Tmp:
1820 return False;
1821 case Iex_Unop:
1822 return isBogusAtom(e->Iex.Unop.arg);
1823 case Iex_Binop:
1824 return isBogusAtom(e->Iex.Binop.arg1)
1825 || isBogusAtom(e->Iex.Binop.arg2);
1826 case Iex_Mux0X:
1827 return isBogusAtom(e->Iex.Mux0X.cond)
1828 || isBogusAtom(e->Iex.Mux0X.expr0)
1829 || isBogusAtom(e->Iex.Mux0X.exprX);
1830 case Iex_LDle:
1831 return isBogusAtom(e->Iex.LDle.addr);
1832 case Iex_CCall:
1833 for (i = 0; e->Iex.CCall.args[i]; i++)
1834 if (isBogusAtom(e->Iex.CCall.args[i]))
1835 return True;
1836 return False;
1837 default:
1838 goto unhandled;
1839 }
1840 case Ist_Put:
1841 return isBogusAtom(st->Ist.Put.data);
1842 case Ist_STle:
1843 return isBogusAtom(st->Ist.STle.addr)
1844 || isBogusAtom(st->Ist.STle.data);
1845 case Ist_Exit:
1846 return isBogusAtom(st->Ist.Exit.cond);
1847 default:
1848 unhandled:
1849 ppIRStmt(st);
1850 VG_(skin_panic)("hasBogusLiterals");
1851 }
1852}
1853#endif /* UNUSED */
1854
1855
sewardjde8a5ae2004-11-06 14:20:54 +00001856IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
1857{
sewardj3598ef92004-11-11 02:13:30 +00001858 Bool verboze = False; //True;
1859
1860 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00001861
1862 Int i, j, first_stmt;
1863 IRStmt* st;
1864 MCEnv mce;
1865
1866 /* Set up BB */
1867 IRBB* bb = emptyIRBB();
1868 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1869 bb->next = dopyIRExpr(bb_in->next);
1870 bb->jumpkind = bb_in->jumpkind;
1871
1872 /* Set up the running environment. Only .bb is modified as we go
1873 along. */
1874 mce.bb = bb;
1875 mce.layout = layout;
1876 mce.n_originalTmps = bb->tyenv->types_used;
1877 mce.hWordTy = hWordTy;
1878 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
1879 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00001880 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00001881
1882 /* Iterate over the stmts. */
1883
1884 for (i = 0; i < bb_in->stmts_used; i++) {
1885 st = bb_in->stmts[i];
1886 if (!st) continue;
1887
1888 sk_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00001889
1890 /*
1891 if (!hasBogusLiterals) {
1892 hasBogusLiterals = checkForBogusLiterals(st);
1893 if (hasBogusLiterals) {
1894 VG_(printf)("bogus: ");
1895 ppIRStmt(st);
1896 VG_(printf)("\n");
1897 }
1898 }
1899 */
sewardjde8a5ae2004-11-06 14:20:54 +00001900 first_stmt = bb->stmts_used;
1901
1902 if (verboze) {
1903 ppIRStmt(st);
1904 VG_(printf)("\n\n");
1905 }
1906
1907 switch (st->tag) {
1908
1909 case Ist_Tmp:
1910 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
1911 expr2vbits( &mce, st->Ist.Tmp.data) );
1912 break;
1913
1914 case Ist_Put:
1915 do_shadow_PUT( &mce,
1916 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00001917 st->Ist.Put.data,
1918 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00001919 break;
1920
1921 case Ist_PutI:
1922 do_shadow_PUTI( &mce,
1923 st->Ist.PutI.descr,
1924 st->Ist.PutI.ix,
1925 st->Ist.PutI.bias,
1926 st->Ist.PutI.data );
1927 break;
1928
1929 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00001930 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
1931 st->Ist.STle.data,
1932 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00001933 break;
1934
1935 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00001936 /* if (!hasBogusLiterals) */
1937 complainIfUndefined( &mce, st->Ist.Exit.cond );
1938 break;
1939
1940 case Ist_Dirty:
1941 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00001942 break;
1943
1944 default:
1945 VG_(printf)("\n");
1946 ppIRStmt(st);
1947 VG_(printf)("\n");
1948 VG_(skin_panic)("memcheck: unhandled IRStmt");
1949
1950 } /* switch (st->tag) */
1951
1952 if (verboze) {
1953 for (j = first_stmt; j < bb->stmts_used; j++) {
1954 VG_(printf)(" ");
1955 ppIRStmt(bb->stmts[j]);
1956 VG_(printf)("\n");
1957 }
1958 VG_(printf)("\n");
1959 }
1960
1961 addStmtToIRBB(bb, st);
1962
1963 }
1964
1965 /* Now we need to complain if the jump target is undefined. */
1966 first_stmt = bb->stmts_used;
1967
1968 if (verboze) {
1969 VG_(printf)("bb->next = ");
1970 ppIRExpr(bb->next);
1971 VG_(printf)("\n\n");
1972 }
1973
1974 complainIfUndefined( &mce, bb->next );
1975
1976 if (verboze) {
1977 for (j = first_stmt; j < bb->stmts_used; j++) {
1978 VG_(printf)(" ");
1979 ppIRStmt(bb->stmts[j]);
1980 VG_(printf)("\n");
1981 }
1982 VG_(printf)("\n");
1983 }
1984
1985 return bb;
1986}
1987
1988/*--------------------------------------------------------------------*/
1989/*--- end mc_translate.c ---*/
1990/*--------------------------------------------------------------------*/