blob: 39412412f018099844ff3a19702cd661d497d8bf [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 (
sewardjcb7a96f2004-11-25 13:08:26 +0000124 InsnSetARM, 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,
sewardj9e7448b2004-11-18 13:44:15 +0000128#if 1 /* no instrumentation */
129 NULL, /* instrument1 */
130 NULL, /* instrument2 */
131 False, /* cleanup after instrument */
132#endif
sewardjde8a5ae2004-11-06 14:20:54 +0000133#if 0 /* addrcheck */
134 ac_instrument, /* instrument1 */
135 NULL, /* instrument2 */
136 False, /* cleanup after instrument */
137#endif
sewardj9e7448b2004-11-18 13:44:15 +0000138#if 0 /* memcheck */
sewardjde8a5ae2004-11-06 14:20:54 +0000139 mc_instrument, /* instrument1 */
140 NULL, /* instrument2 */
141 False, /* cleanup after instrument */
142#endif
sewardjabe017e2004-10-29 23:42:36 +0000143 NULL, /* access checker */
144 TEST_FLAGS
145 );
146
sewardj4459baa2004-09-10 20:00:46 +0000147 if (tres != TransOK)
148 printf("\ntres = %d\n", (Int)tres);
sewardjced9fe52004-07-07 11:55:36 +0000149 assert(tres == TransOK);
150 assert(orig_used == orig_nbytes);
sewardjabe017e2004-10-29 23:42:36 +0000151
sewardj4459baa2004-09-10 20:00:46 +0000152 sum = 0;
153 for (i = 0; i < trans_used; i++)
154 sum += (UInt)transbuf[i];
155 printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
sewardjced9fe52004-07-07 11:55:36 +0000156 }
157
158 fclose(f);
sewardjf05537e2004-10-14 01:08:12 +0000159 printf("\n");
sewardj1f40a0a2004-07-21 12:28:07 +0000160 LibVEX_ClearTemporary(True);
sewardjced9fe52004-07-07 11:55:36 +0000161
sewardjce605f92004-07-05 14:39:15 +0000162 return 0;
163}
sewardj9b1004e2004-10-30 22:25:40 +0000164
165//////////////////////////////////////////////////////////////////////
sewardjde8a5ae2004-11-06 14:20:54 +0000166//////////////////////////////////////////////////////////////////////
167//////////////////////////////////////////////////////////////////////
168//////////////////////////////////////////////////////////////////////
169//////////////////////////////////////////////////////////////////////
170//////////////////////////////////////////////////////////////////////
171//////////////////////////////////////////////////////////////////////
172//////////////////////////////////////////////////////////////////////
sewardj9b1004e2004-10-30 22:25:40 +0000173
174static
sewardjde8a5ae2004-11-06 14:20:54 +0000175__attribute((noreturn))
sewardj9b1004e2004-10-30 22:25:40 +0000176void panic ( Char* s )
177{
178 printf("\npanic: %s\n", s);
179 failure_exit();
180}
181
182static
sewardj9578a8b2004-11-04 19:44:48 +0000183IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
sewardj9b1004e2004-10-30 22:25:40 +0000184{
185/* Use this rather than eg. -1 because it's a UInt. */
186#define INVALID_DATA_SIZE 999999
187
188 Int i;
189 Int sz;
190 IRCallee* helper;
191 IRStmt* st;
192 IRExpr* data;
193 IRExpr* addr;
194 Bool needSz;
195
196 /* Set up BB */
197 IRBB* bb = emptyIRBB();
198 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
199 bb->next = dopyIRExpr(bb_in->next);
200 bb->jumpkind = bb_in->jumpkind;
201
202 /* No loads to consider in ->next. */
203 assert(isAtom(bb_in->next));
204
205 for (i = 0; i < bb_in->stmts_used; i++) {
206 st = bb_in->stmts[i];
207 if (!st) continue;
208
209 switch (st->tag) {
210
211 case Ist_Tmp:
212 data = st->Ist.Tmp.data;
213 if (data->tag == Iex_LDle) {
214 addr = data->Iex.LDle.addr;
215 sz = sizeofIRType(data->Iex.LDle.ty);
216 needSz = False;
217 switch (sz) {
218 case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
sewardjf5435862004-10-31 20:04:05 +0000219 (void*)0x12345601); break;
sewardj9b1004e2004-10-30 22:25:40 +0000220 case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
sewardjf5435862004-10-31 20:04:05 +0000221 (void*)0x12345602); break;
sewardj9b1004e2004-10-30 22:25:40 +0000222 case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
sewardjf5435862004-10-31 20:04:05 +0000223 (void*)0x12345603); break;
sewardj9b1004e2004-10-30 22:25:40 +0000224 default: helper = mkIRCallee(0, "ac_helperc_LOADN",
sewardjf5435862004-10-31 20:04:05 +0000225 (void*)0x12345604);
sewardj9b1004e2004-10-30 22:25:40 +0000226 needSz = True; break;
227 }
228 if (needSz) {
229 addStmtToIRBB(
230 bb,
231 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000232 unsafeIRDirty_0_N( helper->regparms,
233 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000234 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
235 ));
236 } else {
237 addStmtToIRBB(
238 bb,
239 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000240 unsafeIRDirty_0_N( helper->regparms,
241 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000242 mkIRExprVec_1(addr) )
243 ));
244 }
245 }
246 break;
247
248 case Ist_STle:
249 data = st->Ist.STle.data;
250 addr = st->Ist.STle.addr;
251 assert(isAtom(data));
252 assert(isAtom(addr));
253 sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
254 needSz = False;
255 switch (sz) {
256 case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
sewardjf5435862004-10-31 20:04:05 +0000257 (void*)0x12345605); break;
sewardj9b1004e2004-10-30 22:25:40 +0000258 case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
sewardjf5435862004-10-31 20:04:05 +0000259 (void*)0x12345606); break;
sewardj9b1004e2004-10-30 22:25:40 +0000260 case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
sewardjf5435862004-10-31 20:04:05 +0000261 (void*)0x12345607); break;
sewardj9b1004e2004-10-30 22:25:40 +0000262 default: helper = mkIRCallee(0, "ac_helperc_STOREN",
sewardjf5435862004-10-31 20:04:05 +0000263 (void*)0x12345608);
sewardj9b1004e2004-10-30 22:25:40 +0000264 needSz = True; break;
265 }
266 if (needSz) {
267 addStmtToIRBB(
268 bb,
269 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000270 unsafeIRDirty_0_N( helper->regparms,
271 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000272 mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
273 ));
274 } else {
275 addStmtToIRBB(
276 bb,
277 IRStmt_Dirty(
sewardjf5435862004-10-31 20:04:05 +0000278 unsafeIRDirty_0_N( helper->regparms,
279 helper->name, helper->addr,
sewardj9b1004e2004-10-30 22:25:40 +0000280 mkIRExprVec_1(addr) )
281 ));
282 }
283 break;
284
285 case Ist_Put:
286 assert(isAtom(st->Ist.Put.data));
287 break;
288
289 case Ist_PutI:
sewardjeeac8412004-11-02 00:26:55 +0000290 assert(isAtom(st->Ist.PutI.ix));
sewardj9b1004e2004-10-30 22:25:40 +0000291 assert(isAtom(st->Ist.PutI.data));
292 break;
293
294 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +0000295 assert(isAtom(st->Ist.Exit.guard));
sewardj9b1004e2004-10-30 22:25:40 +0000296 break;
297
298 case Ist_Dirty:
299 /* If the call doesn't interact with memory, we ain't
300 interested. */
301 if (st->Ist.Dirty.details->mFx == Ifx_None)
302 break;
303 goto unhandled;
304
305 default:
306 unhandled:
307 printf("\n");
308 ppIRStmt(st);
309 printf("\n");
310 panic("addrcheck: unhandled IRStmt");
311 }
312
313 addStmtToIRBB( bb, dopyIRStmt(st));
314 }
315
316 return bb;
317}
sewardjde8a5ae2004-11-06 14:20:54 +0000318
319//////////////////////////////////////////////////////////////////////
320//////////////////////////////////////////////////////////////////////
321//////////////////////////////////////////////////////////////////////
322//////////////////////////////////////////////////////////////////////
323//////////////////////////////////////////////////////////////////////
324//////////////////////////////////////////////////////////////////////
325//////////////////////////////////////////////////////////////////////
326//////////////////////////////////////////////////////////////////////
327
328#define sk_assert(xxx) assert(xxx)
329#define VG_(xxxx) xxxx
330#define skin_panic(zzz) panic(zzz)
331#define MC_(zzzz) MC_##zzzz
332#define SK_(zzzz) SK_##zzzz
333
334void MC_helperc_complain_undef ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000335void MC_helperc_LOADV8 ( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000336void MC_helperc_LOADV4 ( void ) { }
337void MC_helperc_LOADV2 ( void ) { }
338void MC_helperc_LOADV1 ( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000339void MC_helperc_STOREV8( void ) { }
sewardjde8a5ae2004-11-06 14:20:54 +0000340void MC_helperc_STOREV4( void ) { }
341void MC_helperc_STOREV2( void ) { }
342void MC_helperc_STOREV1( void ) { }
sewardj3598ef92004-11-11 02:13:30 +0000343void MC_helperc_value_check0_fail( void ) { }
344void MC_helperc_value_check1_fail( void ) { }
345void MC_helperc_value_check4_fail( void ) { }
346
347
348
349/*--------------------------------------------------------------------*/
350/*--- Instrument IR to perform memory checking operations. ---*/
351/*--- mc_translate.c ---*/
352/*--------------------------------------------------------------------*/
353
354/*
355 This file is part of MemCheck, a heavyweight Valgrind tool for
356 detecting memory errors.
357
358 Copyright (C) 2000-2004 Julian Seward
359 jseward@acm.org
360
361 This program is free software; you can redistribute it and/or
362 modify it under the terms of the GNU General Public License as
363 published by the Free Software Foundation; either version 2 of the
364 License, or (at your option) any later version.
365
366 This program is distributed in the hope that it will be useful, but
367 WITHOUT ANY WARRANTY; without even the implied warranty of
368 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
369 General Public License for more details.
370
371 You should have received a copy of the GNU General Public License
372 along with this program; if not, write to the Free Software
373 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
374 02111-1307, USA.
375
376 The GNU General Public License is contained in the file COPYING.
377*/
378
379//#include "mc_include.h"
sewardjde8a5ae2004-11-06 14:20:54 +0000380
381
382/*------------------------------------------------------------*/
383/*--- Forward decls ---*/
384/*------------------------------------------------------------*/
385
386struct _MCEnv;
387
388static IRType shadowType ( IRType ty );
389static IRExpr* expr2vbits ( struct _MCEnv* mce, IRExpr* e );
390
391
392/*------------------------------------------------------------*/
393/*--- Memcheck running state, and tmp management. ---*/
394/*------------------------------------------------------------*/
395
396/* Carries around state during memcheck instrumentation. */
397typedef
398 struct _MCEnv {
399 /* MODIFIED: the bb being constructed. IRStmts are added. */
400 IRBB* bb;
401
402 /* MODIFIED: a table [0 .. #temps_in_original_bb-1] which maps
403 original temps to their current their current shadow temp.
404 Initially all entries are IRTemp_INVALID. Entries are added
405 lazily since many original temps are not used due to
406 optimisation prior to instrumentation. Note that floating
407 point original tmps are shadowed by integer tmps of the same
408 size, and Bit-typed original tmps are shadowed by the type
409 Ity_I8. See comment below. */
410 IRTemp* tmpMap;
411 Int n_originalTmps; /* for range checking */
412
413 /* READONLY: the guest layout. This indicates which parts of
414 the guest state should be regarded as 'always defined'. */
415 VexGuestLayout* layout;
416 /* READONLY: the host word type. Needed for constructing
417 arguments of type 'HWord' to be passed to helper functions.
418 Ity_I32 or Ity_I64 only. */
419 IRType hWordTy;
420 }
421 MCEnv;
422
423/* SHADOW TMP MANAGEMENT. Shadow tmps are allocated lazily (on
424 demand), as they are encountered. This is for two reasons.
425
426 (1) (less important reason): Many original tmps are unused due to
427 initial IR optimisation, and we do not want to spaces in tables
428 tracking them.
429
430 Shadow IRTemps are therefore allocated on demand. mce.tmpMap is a
431 table indexed [0 .. n_types-1], which gives the current shadow for
sewardj92d168d2004-11-15 14:22:12 +0000432 each original tmp, or IRTemp_INVALID if none is so far assigned.
sewardjde8a5ae2004-11-06 14:20:54 +0000433 It is necessary to support making multiple assignments to a shadow
434 -- specifically, after testing a shadow for definedness, it needs
435 to be made defined. But IR's SSA property disallows this.
436
437 (2) (more important reason): Therefore, when a shadow needs to get
438 a new value, a new temporary is created, the value is assigned to
439 that, and the tmpMap is updated to reflect the new binding.
440
441 A corollary is that if the tmpMap maps a given tmp to
sewardj92d168d2004-11-15 14:22:12 +0000442 IRTemp_INVALID and we are hoping to read that shadow tmp, it means
sewardjde8a5ae2004-11-06 14:20:54 +0000443 there's a read-before-write error in the original tmps. The IR
444 sanity checker should catch all such anomalies, however.
445*/
446
447/* Find the tmp currently shadowing the given original tmp. If none
448 so far exists, allocate one. */
449static IRTemp findShadowTmp ( MCEnv* mce, IRTemp orig )
450{
451 sk_assert(orig < mce->n_originalTmps);
sewardj92d168d2004-11-15 14:22:12 +0000452 if (mce->tmpMap[orig] == IRTemp_INVALID) {
sewardjde8a5ae2004-11-06 14:20:54 +0000453 mce->tmpMap[orig]
454 = newIRTemp(mce->bb->tyenv,
455 shadowType(mce->bb->tyenv->types[orig]));
456 }
457 return mce->tmpMap[orig];
458}
459
460/* Allocate a new shadow for the given original tmp. This means any
461 previous shadow is abandoned. This is needed because it is
462 necessary to give a new value to a shadow once it has been tested
463 for undefinedness, but unfortunately IR's SSA property disallows
464 this. Instead we must abandon the old shadow, allocate a new one
465 and use that instead. */
466static void newShadowTmp ( MCEnv* mce, IRTemp orig )
467{
468 sk_assert(orig < mce->n_originalTmps);
469 mce->tmpMap[orig]
470 = newIRTemp(mce->bb->tyenv,
471 shadowType(mce->bb->tyenv->types[orig]));
472}
473
474
475/*------------------------------------------------------------*/
476/*--- IRAtoms -- a subset of IRExprs ---*/
477/*------------------------------------------------------------*/
478
479/* An atom is either an IRExpr_Const or an IRExpr_Tmp, as defined by
480 isAtom() in libvex_ir.h. Because this instrumenter expects flat
481 input, most of this code deals in atoms. Usefully, a value atom
482 always has a V-value which is also an atom: constants are shadowed
483 by constants, and temps are shadowed by the corresponding shadow
484 temporary. */
485
486typedef IRExpr IRAtom;
487
488/* (used for sanity checks only): is this an atom which looks
489 like it's from original code? */
490static Bool isOriginalAtom ( MCEnv* mce, IRAtom* a1 )
491{
492 if (a1->tag == Iex_Const)
493 return True;
494 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp < mce->n_originalTmps)
495 return True;
496 return False;
497}
498
499/* (used for sanity checks only): is this an atom which looks
500 like it's from shadow code? */
501static Bool isShadowAtom ( MCEnv* mce, IRAtom* a1 )
502{
503 if (a1->tag == Iex_Const)
504 return True;
505 if (a1->tag == Iex_Tmp && a1->Iex.Tmp.tmp >= mce->n_originalTmps)
506 return True;
507 return False;
508}
509
510/* (used for sanity checks only): check that both args are atoms and
511 are identically-kinded. */
512static Bool sameKindedAtoms ( IRAtom* a1, IRAtom* a2 )
513{
514 if (a1->tag == Iex_Tmp && a1->tag == Iex_Tmp)
515 return True;
516 if (a1->tag == Iex_Const && a1->tag == Iex_Const)
517 return True;
518 return False;
519}
520
521
522/*------------------------------------------------------------*/
523/*--- Type management ---*/
524/*------------------------------------------------------------*/
525
526/* Shadow state is always accessed using integer types. This returns
527 an integer type with the same size (as per sizeofIRType) as the
528 given type. The only valid shadow types are Bit, I8, I16, I32,
529 I64. */
530
531static IRType shadowType ( IRType ty )
532{
533 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000534 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000535 case Ity_I8:
536 case Ity_I16:
537 case Ity_I32:
538 case Ity_I64: return ty;
539 case Ity_F32: return Ity_I32;
540 case Ity_F64: return Ity_I64;
541 default: ppIRType(ty);
542 VG_(skin_panic)("memcheck:shadowType");
543 }
544}
545
546/* Produce a 'defined' value of the given shadow type. Should only be
547 supplied shadow types (Bit/I8/I16/I32/UI64). */
548static IRExpr* definedOfType ( IRType ty ) {
549 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000550 case Ity_I1: return IRExpr_Const(IRConst_U1(False));
sewardjde8a5ae2004-11-06 14:20:54 +0000551 case Ity_I8: return IRExpr_Const(IRConst_U8(0));
552 case Ity_I16: return IRExpr_Const(IRConst_U16(0));
553 case Ity_I32: return IRExpr_Const(IRConst_U32(0));
554 case Ity_I64: return IRExpr_Const(IRConst_U64(0));
555 default: VG_(skin_panic)("memcheck:definedOfType");
556 }
557}
558
559
560/*------------------------------------------------------------*/
561/*--- Constructing IR fragments ---*/
562/*------------------------------------------------------------*/
563
564/* assign value to tmp */
565#define assign(_bb,_tmp,_expr) \
566 addStmtToIRBB((_bb), IRStmt_Tmp((_tmp),(_expr)))
567
568/* add stmt to a bb */
569#define stmt(_bb,_stmt) \
570 addStmtToIRBB((_bb), (_stmt))
571
572/* build various kinds of expressions */
573#define binop(_op, _arg1, _arg2) IRExpr_Binop((_op),(_arg1),(_arg2))
574#define unop(_op, _arg) IRExpr_Unop((_op),(_arg))
575#define mkU8(_n) IRExpr_Const(IRConst_U8(_n))
576#define mkU16(_n) IRExpr_Const(IRConst_U16(_n))
577#define mkU32(_n) IRExpr_Const(IRConst_U32(_n))
578#define mkU64(_n) IRExpr_Const(IRConst_U64(_n))
579#define mkexpr(_tmp) IRExpr_Tmp((_tmp))
580
581/* bind the given expression to a new temporary, and return the
582 temporary. This effectively converts an arbitrary expression into
583 an atom. */
584static IRAtom* assignNew ( MCEnv* mce, IRType ty, IRExpr* e ) {
585 IRTemp t = newIRTemp(mce->bb->tyenv, ty);
586 assign(mce->bb, t, e);
587 return mkexpr(t);
588}
589
590
591/*------------------------------------------------------------*/
592/*--- Constructing definedness primitive ops ---*/
593/*------------------------------------------------------------*/
594
595/* --------- Defined-if-either-defined --------- */
596
597static IRAtom* mkDifD8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
598 sk_assert(isShadowAtom(mce,a1));
599 sk_assert(isShadowAtom(mce,a2));
600 return assignNew(mce, Ity_I8, binop(Iop_And8, a1, a2));
601}
602
603static IRAtom* mkDifD16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
604 sk_assert(isShadowAtom(mce,a1));
605 sk_assert(isShadowAtom(mce,a2));
606 return assignNew(mce, Ity_I16, binop(Iop_And16, a1, a2));
607}
608
609static IRAtom* mkDifD32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
610 sk_assert(isShadowAtom(mce,a1));
611 sk_assert(isShadowAtom(mce,a2));
612 return assignNew(mce, Ity_I32, binop(Iop_And32, a1, a2));
613}
614
615/* --------- Undefined-if-either-undefined --------- */
616
617static IRAtom* mkUifU8 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
618 sk_assert(isShadowAtom(mce,a1));
619 sk_assert(isShadowAtom(mce,a2));
620 return assignNew(mce, Ity_I8, binop(Iop_Or8, a1, a2));
621}
622
623static IRAtom* mkUifU16 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
624 sk_assert(isShadowAtom(mce,a1));
625 sk_assert(isShadowAtom(mce,a2));
626 return assignNew(mce, Ity_I16, binop(Iop_Or16, a1, a2));
627}
628
629static IRAtom* mkUifU32 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
630 sk_assert(isShadowAtom(mce,a1));
631 sk_assert(isShadowAtom(mce,a2));
632 return assignNew(mce, Ity_I32, binop(Iop_Or32, a1, a2));
633}
634
635static IRAtom* mkUifU64 ( MCEnv* mce, IRAtom* a1, IRAtom* a2 ) {
636 sk_assert(isShadowAtom(mce,a1));
637 sk_assert(isShadowAtom(mce,a2));
638 return assignNew(mce, Ity_I64, binop(Iop_Or64, a1, a2));
639}
640
641static IRAtom* mkUifU ( MCEnv* mce, IRType vty, IRAtom* a1, IRAtom* a2 ) {
642 switch (vty) {
sewardj3598ef92004-11-11 02:13:30 +0000643 case Ity_I16: return mkUifU16(mce, a1, a2);
sewardjde8a5ae2004-11-06 14:20:54 +0000644 case Ity_I32: return mkUifU32(mce, a1, a2);
645 case Ity_I64: return mkUifU64(mce, a1, a2);
646 default:
647 VG_(printf)("\n"); ppIRType(vty); VG_(printf)("\n");
648 VG_(skin_panic)("memcheck:mkUifU");
649 }
650}
651
652/* --------- The Left-family of operations. --------- */
653
654static IRAtom* mkLeft8 ( MCEnv* mce, IRAtom* a1 ) {
655 sk_assert(isShadowAtom(mce,a1));
656 /* It's safe to duplicate a1 since it's only an atom */
657 return assignNew(mce, Ity_I8,
658 binop(Iop_Or8, a1,
659 assignNew(mce, Ity_I8,
660 /* unop(Iop_Neg8, a1)))); */
661 binop(Iop_Sub8, mkU8(0), a1) )));
662}
663
664static IRAtom* mkLeft16 ( MCEnv* mce, IRAtom* a1 ) {
665 sk_assert(isShadowAtom(mce,a1));
666 /* It's safe to duplicate a1 since it's only an atom */
667 return assignNew(mce, Ity_I16,
668 binop(Iop_Or16, a1,
669 assignNew(mce, Ity_I16,
670 /* unop(Iop_Neg16, a1)))); */
671 binop(Iop_Sub16, mkU16(0), a1) )));
672}
673
674static IRAtom* mkLeft32 ( MCEnv* mce, IRAtom* a1 ) {
675 sk_assert(isShadowAtom(mce,a1));
676 /* It's safe to duplicate a1 since it's only an atom */
677 return assignNew(mce, Ity_I32,
678 binop(Iop_Or32, a1,
679 assignNew(mce, Ity_I32,
680 /* unop(Iop_Neg32, a1)))); */
681 binop(Iop_Sub32, mkU32(0), a1) )));
682}
683
684/* --------- 'Improvement' functions for AND/OR. --------- */
685
686/* ImproveAND(data, vbits) = data OR vbits. Defined (0) data 0s give
687 defined (0); all other -> undefined (1).
688*/
689static IRAtom* mkImproveAND8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
690{
691 sk_assert(isOriginalAtom(mce, data));
692 sk_assert(isShadowAtom(mce, vbits));
693 sk_assert(sameKindedAtoms(data, vbits));
694 return assignNew(mce, Ity_I8, binop(Iop_Or8, data, vbits));
695}
696
sewardj3598ef92004-11-11 02:13:30 +0000697static IRAtom* mkImproveAND16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
698{
699 sk_assert(isOriginalAtom(mce, data));
700 sk_assert(isShadowAtom(mce, vbits));
701 sk_assert(sameKindedAtoms(data, vbits));
702 return assignNew(mce, Ity_I16, binop(Iop_Or16, data, vbits));
703}
704
sewardjde8a5ae2004-11-06 14:20:54 +0000705static IRAtom* mkImproveAND32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
706{
707 sk_assert(isOriginalAtom(mce, data));
708 sk_assert(isShadowAtom(mce, vbits));
709 sk_assert(sameKindedAtoms(data, vbits));
710 return assignNew(mce, Ity_I32, binop(Iop_Or32, data, vbits));
711}
712
713/* ImproveOR(data, vbits) = ~data OR vbits. Defined (0) data 1s give
714 defined (0); all other -> undefined (1).
715*/
716static IRAtom* mkImproveOR8 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
717{
718 sk_assert(isOriginalAtom(mce, data));
719 sk_assert(isShadowAtom(mce, vbits));
720 sk_assert(sameKindedAtoms(data, vbits));
721 return assignNew(
722 mce, Ity_I8,
723 binop(Iop_Or8,
724 assignNew(mce, Ity_I8, unop(Iop_Not8, data)),
725 vbits) );
726}
727
728static IRAtom* mkImproveOR16 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
729{
730 sk_assert(isOriginalAtom(mce, data));
731 sk_assert(isShadowAtom(mce, vbits));
732 sk_assert(sameKindedAtoms(data, vbits));
733 return assignNew(
734 mce, Ity_I16,
735 binop(Iop_Or16,
736 assignNew(mce, Ity_I16, unop(Iop_Not16, data)),
737 vbits) );
738}
739
740static IRAtom* mkImproveOR32 ( MCEnv* mce, IRAtom* data, IRAtom* vbits )
741{
742 sk_assert(isOriginalAtom(mce, data));
743 sk_assert(isShadowAtom(mce, vbits));
744 sk_assert(sameKindedAtoms(data, vbits));
745 return assignNew(
746 mce, Ity_I32,
747 binop(Iop_Or32,
748 assignNew(mce, Ity_I32, unop(Iop_Not32, data)),
749 vbits) );
750}
751
752/* --------- Pessimising casts. --------- */
753
754static IRAtom* mkPCastTo( MCEnv* mce, IRType dst_ty, IRAtom* vbits )
755{
sewardj8fc93742004-11-22 11:29:33 +0000756 IRType ty;
757 IRAtom* tmp1;
sewardjde8a5ae2004-11-06 14:20:54 +0000758 /* Note, dst_ty is a shadow type, not an original type. */
759 /* First of all, collapse vbits down to a single bit. */
760 sk_assert(isShadowAtom(mce,vbits));
sewardj8fc93742004-11-22 11:29:33 +0000761 ty = typeOfIRExpr(mce->bb->tyenv, vbits);
762 tmp1 = NULL;
sewardjde8a5ae2004-11-06 14:20:54 +0000763 switch (ty) {
sewardjba999312004-11-15 15:21:17 +0000764 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000765 tmp1 = vbits;
766 break;
767 case Ity_I8:
sewardjba999312004-11-15 15:21:17 +0000768 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE8, vbits, mkU8(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000769 break;
770 case Ity_I16:
sewardjba999312004-11-15 15:21:17 +0000771 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE16, vbits, mkU16(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000772 break;
773 case Ity_I32:
sewardjba999312004-11-15 15:21:17 +0000774 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE32, vbits, mkU32(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000775 break;
776 case Ity_I64:
sewardjba999312004-11-15 15:21:17 +0000777 tmp1 = assignNew(mce, Ity_I1, binop(Iop_CmpNE64, vbits, mkU64(0)));
sewardjde8a5ae2004-11-06 14:20:54 +0000778 break;
779 default:
780 VG_(skin_panic)("mkPCastTo(1)");
781 }
782 sk_assert(tmp1);
783 /* Now widen up to the dst type. */
784 switch (dst_ty) {
sewardjba999312004-11-15 15:21:17 +0000785 case Ity_I1:
sewardjde8a5ae2004-11-06 14:20:54 +0000786 return tmp1;
sewardj3598ef92004-11-11 02:13:30 +0000787 case Ity_I8:
788 return assignNew(mce, Ity_I8, unop(Iop_1Sto8, tmp1));
sewardjde8a5ae2004-11-06 14:20:54 +0000789 case Ity_I16:
790 return assignNew(mce, Ity_I16, unop(Iop_1Sto16, tmp1));
791 case Ity_I32:
792 return assignNew(mce, Ity_I32, unop(Iop_1Sto32, tmp1));
793 case Ity_I64:
794 return assignNew(mce, Ity_I64, unop(Iop_1Sto64, tmp1));
795 default:
796 ppIRType(dst_ty);
797 VG_(skin_panic)("mkPCastTo(2)");
798 }
799}
800
801
802/*------------------------------------------------------------*/
803/*--- Emit a test and complaint if something is undefined. ---*/
804/*------------------------------------------------------------*/
805
806/* Set the annotations on a dirty helper to indicate that the stack
807 pointer and instruction pointers might be read. This is the
808 behaviour of all 'emit-a-complaint' style functions we might
809 call. */
810
811static void setHelperAnns ( MCEnv* mce, IRDirty* di ) {
812 di->nFxState = 2;
813 di->fxState[0].fx = Ifx_Read;
814 di->fxState[0].offset = mce->layout->offset_SP;
815 di->fxState[0].size = mce->layout->sizeof_SP;
816 di->fxState[1].fx = Ifx_Read;
817 di->fxState[1].offset = mce->layout->offset_IP;
818 di->fxState[1].size = mce->layout->sizeof_IP;
819}
820
821
822/* Check the supplied **original** atom for undefinedness, and emit a
823 complaint if so. Once that happens, mark it as defined. This is
824 possible because the atom is either a tmp or literal. If it's a
825 tmp, it will be shadowed by a tmp, and so we can set the shadow to
826 be defined. In fact as mentioned above, we will have to allocate a
827 new tmp to carry the new 'defined' shadow value, and update the
828 original->tmp mapping accordingly; we cannot simply assign a new
829 value to an existing shadow tmp as this breaks SSAness -- resulting
830 in the post-instrumentation sanity checker spluttering in disapproval.
831*/
832static void complainIfUndefined ( MCEnv* mce, IRAtom* atom )
833{
sewardj8fc93742004-11-22 11:29:33 +0000834 Int sz;
835 IRType ty;
836 IRAtom* vatom;
837 IRAtom* cond;
838 IRDirty* di;
839
sewardjde8a5ae2004-11-06 14:20:54 +0000840 /* Since the original expression is atomic, there's no duplicated
841 work generated by making multiple V-expressions for it. So we
842 don't really care about the possibility that someone else may
843 also create a V-interpretion for it. */
844 sk_assert(isOriginalAtom(mce, atom));
sewardj8fc93742004-11-22 11:29:33 +0000845 vatom = expr2vbits( mce, atom );
sewardjde8a5ae2004-11-06 14:20:54 +0000846 sk_assert(isShadowAtom(mce, vatom));
847 sk_assert(sameKindedAtoms(atom, vatom));
848
sewardj8fc93742004-11-22 11:29:33 +0000849 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjde8a5ae2004-11-06 14:20:54 +0000850
851 /* sz is only used for constructing the error message */
sewardj8fc93742004-11-22 11:29:33 +0000852 sz = ty==Ity_I1 ? 0 : sizeofIRType(ty);
sewardjde8a5ae2004-11-06 14:20:54 +0000853
sewardj8fc93742004-11-22 11:29:33 +0000854 cond = mkPCastTo( mce, Ity_I1, vatom );
sewardjde8a5ae2004-11-06 14:20:54 +0000855 /* cond will be 0 if all defined, and 1 if any not defined. */
856
sewardj3598ef92004-11-11 02:13:30 +0000857 switch (sz) {
858 case 0:
859 di = unsafeIRDirty_0_N( 0/*regparms*/,
860 "MC_(helperc_value_check0_fail)",
861 &MC_(helperc_value_check0_fail),
862 mkIRExprVec_0()
863 );
864 break;
865 case 1:
866 di = unsafeIRDirty_0_N( 0/*regparms*/,
867 "MC_(helperc_value_check1_fail)",
868 &MC_(helperc_value_check1_fail),
869 mkIRExprVec_0()
870 );
871 break;
872 case 4:
873 di = unsafeIRDirty_0_N( 0/*regparms*/,
874 "MC_(helperc_value_check4_fail)",
875 &MC_(helperc_value_check4_fail),
876 mkIRExprVec_0()
877 );
878 break;
879 default:
880 di = unsafeIRDirty_0_N( 1/*regparms*/,
881 "MC_(helperc_complain_undef)",
882 &MC_(helperc_complain_undef),
883 mkIRExprVec_1( mkIRExpr_HWord( sz ))
884 );
885 break;
886 }
sewardjde8a5ae2004-11-06 14:20:54 +0000887 di->guard = cond;
888 setHelperAnns( mce, di );
889 stmt( mce->bb, IRStmt_Dirty(di));
890
891 /* Set the shadow tmp to be defined. First, update the
892 orig->shadow tmp mapping to reflect the fact that this shadow is
893 getting a new value. */
894 sk_assert(isAtom(vatom));
895 /* sameKindedAtoms ... */
896 if (vatom->tag == Iex_Tmp) {
897 sk_assert(atom->tag == Iex_Tmp);
898 newShadowTmp(mce, atom->Iex.Tmp.tmp);
899 assign(mce->bb, findShadowTmp(mce, atom->Iex.Tmp.tmp),
900 definedOfType(ty));
901 }
902}
903
904
905/*------------------------------------------------------------*/
906/*--- Shadowing PUTs/GETs, and indexed variants thereof ---*/
907/*------------------------------------------------------------*/
908
909/* Examine the always-defined sections declared in layout to see if
910 the (offset,size) section is within one. Note, is is an error to
911 partially fall into such a region: (offset,size) should either be
912 completely in such a region or completely not-in such a region.
913*/
914static Bool isAlwaysDefd ( MCEnv* mce, Int offset, Int size )
915{
916 Int minoffD, maxoffD, i;
917 Int minoff = offset;
918 Int maxoff = minoff + size - 1;
919 sk_assert((minoff & ~0xFFFF) == 0);
920 sk_assert((maxoff & ~0xFFFF) == 0);
921
922 for (i = 0; i < mce->layout->n_alwaysDefd; i++) {
923 minoffD = mce->layout->alwaysDefd[i].offset;
924 maxoffD = minoffD + mce->layout->alwaysDefd[i].size - 1;
925 sk_assert((minoffD & ~0xFFFF) == 0);
926 sk_assert((maxoffD & ~0xFFFF) == 0);
927
928 if (maxoff < minoffD || maxoffD < minoff)
929 continue; /* no overlap */
930 if (minoff >= minoffD && maxoff <= maxoffD)
931 return True; /* completely contained in an always-defd section */
932
933 VG_(skin_panic)("memcheck:isAlwaysDefd:partial overlap");
934 }
935 return False; /* could not find any containing section */
936}
937
938
939/* Generate into bb suitable actions to shadow this Put. If the state
940 slice is marked 'always defined', do nothing. Otherwise, write the
sewardj3598ef92004-11-11 02:13:30 +0000941 supplied V bits to the shadow state. We can pass in either an
942 original atom or a V-atom, but not both. In the former case the
943 relevant V-bits are then generated from the original.
sewardjde8a5ae2004-11-06 14:20:54 +0000944*/
945static
sewardj3598ef92004-11-11 02:13:30 +0000946void do_shadow_PUT ( MCEnv* mce, Int offset,
947 IRAtom* atom, IRAtom* vatom )
sewardjde8a5ae2004-11-06 14:20:54 +0000948{
sewardj8fc93742004-11-22 11:29:33 +0000949 IRType ty;
sewardj3598ef92004-11-11 02:13:30 +0000950 if (atom) {
951 sk_assert(!vatom);
952 sk_assert(isOriginalAtom(mce, atom));
953 vatom = expr2vbits( mce, atom );
954 } else {
955 sk_assert(vatom);
956 sk_assert(isShadowAtom(mce, vatom));
957 }
958
sewardj8fc93742004-11-22 11:29:33 +0000959 ty = typeOfIRExpr(mce->bb->tyenv, vatom);
sewardjba999312004-11-15 15:21:17 +0000960 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +0000961 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
962 /* later: no ... */
963 /* emit code to emit a complaint if any of the vbits are 1. */
964 /* complainIfUndefined(mce, atom); */
965 } else {
966 /* Do a plain shadow Put. */
967 stmt( mce->bb, IRStmt_Put( offset + mce->layout->total_sizeB, vatom ) );
968 }
969}
970
971
972/* Return an expression which contains the V bits corresponding to the
973 given GETI (passed in in pieces).
974*/
975static
976void do_shadow_PUTI ( MCEnv* mce,
977 IRArray* descr, IRAtom* ix, Int bias, IRAtom* atom )
978{
sewardj8fc93742004-11-22 11:29:33 +0000979 IRAtom* vatom;
980 IRType ty, tyS;
981 Int arrSize;
982
sewardjde8a5ae2004-11-06 14:20:54 +0000983 sk_assert(isOriginalAtom(mce,atom));
sewardj8fc93742004-11-22 11:29:33 +0000984 vatom = expr2vbits( mce, atom );
sewardjde8a5ae2004-11-06 14:20:54 +0000985 sk_assert(sameKindedAtoms(atom, vatom));
sewardj8fc93742004-11-22 11:29:33 +0000986 ty = descr->elemTy;
987 tyS = shadowType(ty);
988 arrSize = descr->nElems * sizeofIRType(ty);
sewardjba999312004-11-15 15:21:17 +0000989 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +0000990 sk_assert(isOriginalAtom(mce,ix));
991 complainIfUndefined(mce,ix);
992 if (isAlwaysDefd(mce, descr->base, arrSize)) {
993 /* later: no ... */
994 /* emit code to emit a complaint if any of the vbits are 1. */
995 /* complainIfUndefined(mce, atom); */
996 } else {
997 /* Do a cloned version of the Put that refers to the shadow
998 area. */
999 IRArray* new_descr
1000 = mkIRArray( descr->base + mce->layout->total_sizeB,
1001 tyS, descr->nElems);
1002 stmt( mce->bb, IRStmt_PutI( new_descr, ix, bias, vatom ));
1003 }
1004}
1005
1006
1007/* Return an expression which contains the V bits corresponding to the
1008 given GET (passed in in pieces).
1009*/
1010static
1011IRExpr* shadow_GET ( MCEnv* mce, Int offset, IRType ty )
1012{
1013 IRType tyS = shadowType(ty);
sewardjba999312004-11-15 15:21:17 +00001014 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001015 if (isAlwaysDefd(mce, offset, sizeofIRType(ty))) {
1016 /* Always defined, return all zeroes of the relevant type */
1017 return definedOfType(tyS);
1018 } else {
1019 /* return a cloned version of the Get that refers to the shadow
1020 area. */
1021 return IRExpr_Get( offset + mce->layout->total_sizeB, tyS );
1022 }
1023}
1024
1025
1026/* Return an expression which contains the V bits corresponding to the
1027 given GETI (passed in in pieces).
1028*/
1029static
1030IRExpr* shadow_GETI ( MCEnv* mce, IRArray* descr, IRAtom* ix, Int bias )
1031{
1032 IRType ty = descr->elemTy;
1033 IRType tyS = shadowType(ty);
1034 Int arrSize = descr->nElems * sizeofIRType(ty);
sewardjba999312004-11-15 15:21:17 +00001035 sk_assert(ty != Ity_I1);
sewardjde8a5ae2004-11-06 14:20:54 +00001036 sk_assert(isOriginalAtom(mce,ix));
1037 complainIfUndefined(mce,ix);
1038 if (isAlwaysDefd(mce, descr->base, arrSize)) {
1039 /* Always defined, return all zeroes of the relevant type */
1040 return definedOfType(tyS);
1041 } else {
1042 /* return a cloned version of the Get that refers to the shadow
1043 area. */
1044 IRArray* new_descr
1045 = mkIRArray( descr->base + mce->layout->total_sizeB,
1046 tyS, descr->nElems);
1047 return IRExpr_GetI( new_descr, ix, bias );
1048 }
1049}
1050
1051
1052/*------------------------------------------------------------*/
1053/*--- Generating approximations for unknown operations, ---*/
1054/*--- using lazy-propagate semantics ---*/
1055/*------------------------------------------------------------*/
1056
1057/* Lazy propagation of undefinedness from two values, resulting in the
1058 specified shadow type.
1059*/
1060static
1061IRAtom* mkLazy2 ( MCEnv* mce, IRType finalVty, IRAtom* va1, IRAtom* va2 )
1062{
1063 /* force everything via 32-bit intermediaries. */
1064 IRAtom* at;
1065 sk_assert(isShadowAtom(mce,va1));
1066 sk_assert(isShadowAtom(mce,va2));
1067 at = mkPCastTo(mce, Ity_I32, va1);
1068 at = mkUifU(mce, Ity_I32, at, mkPCastTo(mce, Ity_I32, va2));
1069 at = mkPCastTo(mce, finalVty, at);
1070 return at;
1071}
1072
1073
1074/* Do the lazy propagation game from a null-terminated vector of
1075 atoms. This is presumably the arguments to a helper call, so the
1076 IRCallee info is also supplied in order that we can know which
1077 arguments should be ignored (via the .mcx_mask field).
1078*/
1079static
1080IRAtom* mkLazyN ( MCEnv* mce,
1081 IRAtom** exprvec, IRType finalVtype, IRCallee* cee )
1082{
1083 Int i;
1084 IRAtom* here;
1085 IRAtom* curr = definedOfType(Ity_I32);
1086 for (i = 0; exprvec[i]; i++) {
1087 sk_assert(i < 32);
1088 sk_assert(isOriginalAtom(mce, exprvec[i]));
1089 /* Only take notice of this arg if the callee's mc-exclusion
1090 mask does not say it is to be excluded. */
1091 if (cee->mcx_mask & (1<<i)) {
1092 /* the arg is to be excluded from definedness checking. Do
1093 nothing. */
1094 if (0) VG_(printf)("excluding %s(%d)\n", cee->name, i);
1095 } else {
1096 /* calculate the arg's definedness, and pessimistically merge
1097 it in. */
1098 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, exprvec[i]) );
1099 curr = mkUifU32(mce, here, curr);
1100 }
1101 }
1102 return mkPCastTo(mce, finalVtype, curr );
1103}
1104
1105
1106/*------------------------------------------------------------*/
1107/*--- Generating expensive sequences for exact carry-chain ---*/
1108/*--- propagation in add/sub and related operations. ---*/
1109/*------------------------------------------------------------*/
1110
1111static
1112IRAtom* expensiveAdd32 ( MCEnv* mce, IRAtom* qaa, IRAtom* qbb,
1113 IRAtom* aa, IRAtom* bb )
1114{
sewardj8fc93742004-11-22 11:29:33 +00001115 IRType ty;
1116 IROp opAND, opOR, opXOR, opNOT, opADD;
1117 IRAtom *a_min, *b_min, *a_max, *b_max;
1118
sewardjde8a5ae2004-11-06 14:20:54 +00001119 sk_assert(isShadowAtom(mce,qaa));
1120 sk_assert(isShadowAtom(mce,qbb));
1121 sk_assert(isOriginalAtom(mce,aa));
1122 sk_assert(isOriginalAtom(mce,bb));
1123 sk_assert(sameKindedAtoms(qaa,aa));
1124 sk_assert(sameKindedAtoms(qbb,bb));
1125
sewardj8fc93742004-11-22 11:29:33 +00001126 ty = Ity_I32;
1127 opAND = Iop_And32;
1128 opOR = Iop_Or32;
1129 opXOR = Iop_Xor32;
1130 opNOT = Iop_Not32;
1131 opADD = Iop_Add32;
sewardjde8a5ae2004-11-06 14:20:54 +00001132
1133 // a_min = aa & ~qaa
1134 a_min = assignNew(mce,ty,
1135 binop(opAND, aa,
1136 assignNew(mce,ty, unop(opNOT, qaa))));
1137
1138 // b_min = bb & ~qbb
1139 b_min = assignNew(mce,ty,
1140 binop(opAND, bb,
1141 assignNew(mce,ty, unop(opNOT, qbb))));
1142
1143 // a_max = aa | qaa
1144 a_max = assignNew(mce,ty, binop(opOR, aa, qaa));
1145
1146 // b_max = bb | qbb
1147 b_max = assignNew(mce,ty, binop(opOR, bb, qbb));
1148
1149 // result = (qaa | qbb) | ((a_min + b_min) ^ (a_max + b_max))
1150 return
1151 assignNew(mce,ty,
1152 binop( opOR,
1153 assignNew(mce,ty, binop(opOR, qaa, qbb)),
1154 assignNew(mce,ty,
1155 binop(opXOR, assignNew(mce,ty, binop(opADD, a_min, b_min)),
1156 assignNew(mce,ty, binop(opADD, a_max, b_max))
1157 )
1158 )
1159 )
1160 );
1161}
1162
1163
1164/*------------------------------------------------------------*/
1165/*--- Generate shadow values from all kinds of IRExprs. ---*/
1166/*------------------------------------------------------------*/
1167
1168static
1169IRAtom* expr2vbits_Binop ( MCEnv* mce,
1170 IROp op,
1171 IRAtom* atom1, IRAtom* atom2 )
1172{
1173 IRType and_or_ty;
1174 IRAtom* (*uifu) (MCEnv*, IRAtom*, IRAtom*);
1175 IRAtom* (*difd) (MCEnv*, IRAtom*, IRAtom*);
1176 IRAtom* (*improve) (MCEnv*, IRAtom*, IRAtom*);
1177
1178 IRAtom* vatom1 = expr2vbits( mce, atom1 );
1179 IRAtom* vatom2 = expr2vbits( mce, atom2 );
1180
1181 sk_assert(isOriginalAtom(mce,atom1));
1182 sk_assert(isOriginalAtom(mce,atom2));
1183 sk_assert(isShadowAtom(mce,vatom1));
1184 sk_assert(isShadowAtom(mce,vatom2));
1185 sk_assert(sameKindedAtoms(atom1,vatom1));
1186 sk_assert(sameKindedAtoms(atom2,vatom2));
1187 switch (op) {
1188
sewardj3598ef92004-11-11 02:13:30 +00001189 case Iop_RoundF64:
1190 case Iop_F64toI64:
1191 /* First arg is I32 (rounding mode), second is F64 (data). */
1192 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1193
1194 case Iop_PRemC3210F64: case Iop_PRem1C3210F64:
1195 /* Takes two F64 args. */
sewardjde8a5ae2004-11-06 14:20:54 +00001196 case Iop_F64toI32:
1197 /* First arg is I32 (rounding mode), second is F64 (data). */
1198 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1199
1200 case Iop_F64toI16:
1201 /* First arg is I32 (rounding mode), second is F64 (data). */
1202 return mkLazy2(mce, Ity_I16, vatom1, vatom2);
1203
sewardj3598ef92004-11-11 02:13:30 +00001204 case Iop_ScaleF64:
1205 case Iop_Yl2xF64:
1206 case Iop_Yl2xp1F64:
1207 case Iop_PRemF64:
1208 case Iop_AtanF64:
1209 case Iop_AddF64:
1210 case Iop_DivF64:
1211 case Iop_SubF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001212 case Iop_MulF64:
1213 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1214
sewardj3598ef92004-11-11 02:13:30 +00001215 case Iop_CmpF64:
1216 return mkLazy2(mce, Ity_I32, vatom1, vatom2);
1217
sewardjde8a5ae2004-11-06 14:20:54 +00001218 /* non-FP after here */
1219
1220 case Iop_DivModU64to32:
1221 case Iop_DivModS64to32:
1222 return mkLazy2(mce, Ity_I64, vatom1, vatom2);
1223
sewardj3598ef92004-11-11 02:13:30 +00001224 case Iop_16HLto32:
1225 return assignNew(mce, Ity_I32,
1226 binop(Iop_16HLto32, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001227 case Iop_32HLto64:
1228 return assignNew(mce, Ity_I64,
sewardj3598ef92004-11-11 02:13:30 +00001229 binop(Iop_32HLto64, vatom1, vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001230
1231 case Iop_MullS32:
1232 case Iop_MullU32: {
1233 IRAtom* vLo32 = mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1234 IRAtom* vHi32 = mkPCastTo(mce, Ity_I32, vLo32);
1235 return assignNew(mce, Ity_I64, binop(Iop_32HLto64, vHi32, vLo32));
1236 }
1237
sewardj3598ef92004-11-11 02:13:30 +00001238 case Iop_MullS16:
1239 case Iop_MullU16: {
1240 IRAtom* vLo16 = mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1241 IRAtom* vHi16 = mkPCastTo(mce, Ity_I16, vLo16);
1242 return assignNew(mce, Ity_I32, binop(Iop_16HLto32, vHi16, vLo16));
1243 }
1244
1245 case Iop_MullS8:
1246 case Iop_MullU8: {
1247 IRAtom* vLo8 = mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1248 IRAtom* vHi8 = mkPCastTo(mce, Ity_I8, vLo8);
1249 return assignNew(mce, Ity_I16, binop(Iop_8HLto16, vHi8, vLo8));
1250 }
1251
sewardjde8a5ae2004-11-06 14:20:54 +00001252 case Iop_Add32:
1253# if 0
1254 return expensiveAdd32(mce, vatom1,vatom2, atom1,atom2);
1255# endif
1256 case Iop_Sub32:
1257 case Iop_Mul32:
1258 return mkLeft32(mce, mkUifU32(mce, vatom1,vatom2));
1259
sewardj3598ef92004-11-11 02:13:30 +00001260 case Iop_Mul16:
sewardjde8a5ae2004-11-06 14:20:54 +00001261 case Iop_Add16:
1262 case Iop_Sub16:
1263 return mkLeft16(mce, mkUifU16(mce, vatom1,vatom2));
1264
1265 case Iop_Sub8:
1266 case Iop_Add8:
1267 return mkLeft8(mce, mkUifU8(mce, vatom1,vatom2));
1268
1269 case Iop_CmpLE32S: case Iop_CmpLE32U:
1270 case Iop_CmpLT32U: case Iop_CmpLT32S:
1271 case Iop_CmpEQ32: case Iop_CmpNE32:
sewardjba999312004-11-15 15:21:17 +00001272 return mkPCastTo(mce, Ity_I1, mkUifU32(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001273
sewardj3598ef92004-11-11 02:13:30 +00001274 case Iop_CmpEQ16: case Iop_CmpNE16:
sewardjba999312004-11-15 15:21:17 +00001275 return mkPCastTo(mce, Ity_I1, mkUifU16(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001276
1277 case Iop_CmpEQ8: case Iop_CmpNE8:
sewardjba999312004-11-15 15:21:17 +00001278 return mkPCastTo(mce, Ity_I1, mkUifU8(mce, vatom1,vatom2));
sewardjde8a5ae2004-11-06 14:20:54 +00001279
1280 case Iop_Shl32: case Iop_Shr32: case Iop_Sar32:
1281 /* Complain if the shift amount is undefined. Then simply
1282 shift the first arg's V bits by the real shift amount. */
1283 complainIfUndefined(mce, atom2);
1284 return assignNew(mce, Ity_I32, binop(op, vatom1, atom2));
1285
1286 case Iop_Shl16: case Iop_Shr16:
1287 /* Same scheme as with 32-bit shifts. */
1288 complainIfUndefined(mce, atom2);
1289 return assignNew(mce, Ity_I16, binop(op, vatom1, atom2));
1290
sewardj3598ef92004-11-11 02:13:30 +00001291 case Iop_Shl8: case Iop_Shr8:
sewardjde8a5ae2004-11-06 14:20:54 +00001292 /* Same scheme as with 32-bit shifts. */
1293 complainIfUndefined(mce, atom2);
1294 return assignNew(mce, Ity_I8, binop(op, vatom1, atom2));
1295
1296 case Iop_Shl64: case Iop_Shr64:
1297 /* Same scheme as with 32-bit shifts. */
1298 complainIfUndefined(mce, atom2);
1299 return assignNew(mce, Ity_I64, binop(op, vatom1, atom2));
1300
1301 case Iop_And32:
1302 uifu = mkUifU32; difd = mkDifD32;
1303 and_or_ty = Ity_I32; improve = mkImproveAND32; goto do_And_Or;
sewardj3598ef92004-11-11 02:13:30 +00001304 case Iop_And16:
1305 uifu = mkUifU16; difd = mkDifD16;
1306 and_or_ty = Ity_I16; improve = mkImproveAND16; goto do_And_Or;
sewardjde8a5ae2004-11-06 14:20:54 +00001307 case Iop_And8:
1308 uifu = mkUifU8; difd = mkDifD8;
1309 and_or_ty = Ity_I8; improve = mkImproveAND8; goto do_And_Or;
1310
1311 case Iop_Or32:
1312 uifu = mkUifU32; difd = mkDifD32;
1313 and_or_ty = Ity_I32; improve = mkImproveOR32; goto do_And_Or;
1314 case Iop_Or16:
1315 uifu = mkUifU16; difd = mkDifD16;
1316 and_or_ty = Ity_I16; improve = mkImproveOR16; goto do_And_Or;
1317 case Iop_Or8:
1318 uifu = mkUifU8; difd = mkDifD8;
1319 and_or_ty = Ity_I8; improve = mkImproveOR8; goto do_And_Or;
1320
1321 do_And_Or:
1322 return
1323 assignNew(
1324 mce,
1325 and_or_ty,
1326 difd(mce, uifu(mce, vatom1, vatom2),
1327 difd(mce, improve(mce, atom1, vatom1),
1328 improve(mce, atom2, vatom2) ) ) );
1329
1330 case Iop_Xor8:
1331 return mkUifU8(mce, vatom1, vatom2);
sewardj3598ef92004-11-11 02:13:30 +00001332 case Iop_Xor16:
1333 return mkUifU16(mce, vatom1, vatom2);
sewardjde8a5ae2004-11-06 14:20:54 +00001334 case Iop_Xor32:
1335 return mkUifU32(mce, vatom1, vatom2);
1336
1337 default:
1338 ppIROp(op);
1339 VG_(skin_panic)("memcheck:expr2vbits_Binop");
1340 }
1341}
1342
1343
1344static
1345IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
1346{
1347 IRAtom* vatom = expr2vbits( mce, atom );
1348 sk_assert(isOriginalAtom(mce,atom));
1349 switch (op) {
1350
1351 case Iop_F32toF64:
sewardj3598ef92004-11-11 02:13:30 +00001352 case Iop_I32toF64:
1353 case Iop_I64toF64:
1354 case Iop_NegF64:
1355 case Iop_SinF64:
1356 case Iop_CosF64:
1357 case Iop_TanF64:
1358 case Iop_SqrtF64:
1359 case Iop_AbsF64:
1360 case Iop_2xm1F64:
sewardjde8a5ae2004-11-06 14:20:54 +00001361 return mkPCastTo(mce, Ity_I64, vatom);
1362
sewardj3598ef92004-11-11 02:13:30 +00001363 case Iop_F64toF32:
1364 case Iop_Clz32:
1365 case Iop_Ctz32:
1366 return mkPCastTo(mce, Ity_I32, vatom);
1367
1368 case Iop_32Sto64:
1369 case Iop_32Uto64:
1370 return assignNew(mce, Ity_I64, unop(op, vatom));
1371
sewardjde8a5ae2004-11-06 14:20:54 +00001372 case Iop_64to32:
1373 case Iop_64HIto32:
1374 case Iop_1Uto32:
1375 case Iop_8Uto32:
1376 case Iop_16Uto32:
1377 case Iop_16Sto32:
1378 case Iop_8Sto32:
1379 return assignNew(mce, Ity_I32, unop(op, vatom));
1380
1381 case Iop_8Sto16:
sewardj3598ef92004-11-11 02:13:30 +00001382 case Iop_8Uto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001383 case Iop_32to16:
sewardj3598ef92004-11-11 02:13:30 +00001384 case Iop_32HIto16:
sewardjde8a5ae2004-11-06 14:20:54 +00001385 return assignNew(mce, Ity_I16, unop(op, vatom));
1386
1387 case Iop_1Uto8:
sewardj3598ef92004-11-11 02:13:30 +00001388 case Iop_16to8:
sewardjde8a5ae2004-11-06 14:20:54 +00001389 case Iop_32to8:
1390 return assignNew(mce, Ity_I8, unop(op, vatom));
1391
1392 case Iop_32to1:
sewardjba999312004-11-15 15:21:17 +00001393 return assignNew(mce, Ity_I1, unop(Iop_32to1, vatom));
sewardjde8a5ae2004-11-06 14:20:54 +00001394
sewardj3598ef92004-11-11 02:13:30 +00001395 case Iop_ReinterpF64asI64:
1396 case Iop_ReinterpI64asF64:
sewardjde8a5ae2004-11-06 14:20:54 +00001397 case Iop_Not32:
sewardj3598ef92004-11-11 02:13:30 +00001398 case Iop_Not16:
sewardjde8a5ae2004-11-06 14:20:54 +00001399 case Iop_Not8:
1400 case Iop_Not1:
1401 return vatom;
1402 default:
1403 ppIROp(op);
1404 VG_(skin_panic)("memcheck:expr2vbits_Unop");
1405 }
1406}
1407
1408
1409static
sewardj3598ef92004-11-11 02:13:30 +00001410IRAtom* expr2vbits_LDle ( MCEnv* mce, IRType ty, IRAtom* addr, UInt bias )
sewardjde8a5ae2004-11-06 14:20:54 +00001411{
1412 void* helper;
1413 Char* hname;
1414 IRDirty* di;
1415 IRTemp datavbits;
sewardj3598ef92004-11-11 02:13:30 +00001416 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001417
1418 sk_assert(isOriginalAtom(mce,addr));
1419
1420 /* First, emit a definedness test for the address. This also sets
1421 the address (shadow) to 'defined' following the test. */
1422 complainIfUndefined( mce, addr );
1423
1424 /* Now cook up a call to the relevant helper function, to read the
1425 data V bits from shadow memory. */
1426 ty = shadowType(ty);
1427 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001428 case Ity_I64: helper = &MC_(helperc_LOADV8);
1429 hname = "MC_(helperc_LOADV8)";
1430 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001431 case Ity_I32: helper = &MC_(helperc_LOADV4);
1432 hname = "MC_(helperc_LOADV4)";
1433 break;
1434 case Ity_I16: helper = &MC_(helperc_LOADV2);
1435 hname = "MC_(helperc_LOADV2)";
1436 break;
1437 case Ity_I8: helper = &MC_(helperc_LOADV1);
1438 hname = "MC_(helperc_LOADV1)";
1439 break;
1440 default: ppIRType(ty);
1441 VG_(skin_panic)("memcheck:do_shadow_LDle");
1442 }
1443
sewardj3598ef92004-11-11 02:13:30 +00001444 /* Generate the actual address into addrAct. */
1445 if (bias == 0) {
1446 addrAct = addr;
1447 } else {
1448 IRType tyAddr = mce->hWordTy;
sewardj3598ef92004-11-11 02:13:30 +00001449 IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1450 IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj8fc93742004-11-22 11:29:33 +00001451 sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj3598ef92004-11-11 02:13:30 +00001452 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1453 }
1454
sewardjde8a5ae2004-11-06 14:20:54 +00001455 /* We need to have a place to park the V bits we're just about to
1456 read. */
1457 datavbits = newIRTemp(mce->bb->tyenv, ty);
1458 di = unsafeIRDirty_1_N( datavbits,
sewardj3598ef92004-11-11 02:13:30 +00001459 1/*regparms*/, hname, helper,
1460 mkIRExprVec_1( addrAct ));
sewardjde8a5ae2004-11-06 14:20:54 +00001461 setHelperAnns( mce, di );
1462 stmt( mce->bb, IRStmt_Dirty(di) );
1463
1464 return mkexpr(datavbits);
1465}
1466
1467
1468static
1469IRAtom* expr2vbits_Mux0X ( MCEnv* mce,
sewardj3598ef92004-11-11 02:13:30 +00001470 IRAtom* cond, IRAtom* expr0, IRAtom* exprX )
sewardjde8a5ae2004-11-06 14:20:54 +00001471{
1472 IRAtom *vbitsC, *vbits0, *vbitsX;
1473 IRType ty;
1474 /* Given Mux0X(cond,expr0,exprX), generate
1475 Mux0X(cond,expr0#,exprX#) `UifU` PCast(cond#)
1476 That is, steer the V bits like the originals, but trash the
1477 result if the steering value is undefined. This gives
1478 lazy propagation. */
1479 sk_assert(isOriginalAtom(mce, cond));
1480 sk_assert(isOriginalAtom(mce, expr0));
1481 sk_assert(isOriginalAtom(mce, exprX));
1482
1483 vbitsC = expr2vbits(mce, cond);
1484 vbits0 = expr2vbits(mce, expr0);
1485 vbitsX = expr2vbits(mce, exprX);
1486 ty = typeOfIRExpr(mce->bb->tyenv, vbits0);
1487
1488 return
1489 mkUifU(mce, ty, assignNew(mce, ty, IRExpr_Mux0X(cond, vbits0, vbitsX)),
1490 mkPCastTo(mce, ty, vbitsC) );
1491}
1492
1493/* --------- This is the main expression-handling function. --------- */
1494
1495static
1496IRExpr* expr2vbits ( MCEnv* mce, IRExpr* e )
1497{
1498 switch (e->tag) {
1499
1500 case Iex_Get:
1501 return shadow_GET( mce, e->Iex.Get.offset, e->Iex.Get.ty );
1502
1503 case Iex_GetI:
1504 return shadow_GETI( mce, e->Iex.GetI.descr,
1505 e->Iex.GetI.ix, e->Iex.GetI.bias );
1506
1507 case Iex_Tmp:
1508 return IRExpr_Tmp( findShadowTmp(mce, e->Iex.Tmp.tmp) );
1509
1510 case Iex_Const:
1511 return definedOfType(shadowType(typeOfIRExpr(mce->bb->tyenv, e)));
1512
1513 case Iex_Binop:
1514 return expr2vbits_Binop(
1515 mce,
1516 e->Iex.Binop.op,
1517 e->Iex.Binop.arg1, e->Iex.Binop.arg2
1518 );
1519
1520 case Iex_Unop:
1521 return expr2vbits_Unop( mce, e->Iex.Unop.op, e->Iex.Unop.arg );
1522
1523 case Iex_LDle:
sewardj3598ef92004-11-11 02:13:30 +00001524 return expr2vbits_LDle( mce, e->Iex.LDle.ty,
1525 e->Iex.LDle.addr, 0/*addr bias*/ );
sewardjde8a5ae2004-11-06 14:20:54 +00001526
1527 case Iex_CCall:
1528 return mkLazyN( mce, e->Iex.CCall.args,
1529 e->Iex.CCall.retty,
1530 e->Iex.CCall.cee );
1531
1532 case Iex_Mux0X:
1533 return expr2vbits_Mux0X( mce, e->Iex.Mux0X.cond, e->Iex.Mux0X.expr0,
1534 e->Iex.Mux0X.exprX);
1535
1536 default:
1537 VG_(printf)("\n");
1538 ppIRExpr(e);
1539 VG_(printf)("\n");
1540 VG_(skin_panic)("memcheck: expr2vbits");
1541 }
1542}
1543
1544/*------------------------------------------------------------*/
1545/*--- Generate shadow stmts from all kinds of IRStmts. ---*/
1546/*------------------------------------------------------------*/
1547
1548/* Widen a value to the host word size. */
1549
1550static
1551IRExpr* zwidenToHostWord ( MCEnv* mce, IRAtom* vatom )
1552{
sewardjde8a5ae2004-11-06 14:20:54 +00001553 IRType ty = typeOfIRExpr(mce->bb->tyenv, vatom);
1554 IRType tyH = mce->hWordTy;
1555
sewardj8fc93742004-11-22 11:29:33 +00001556 /* vatom is vbits-value and as such can only have a shadow type. */
1557 sk_assert(isShadowAtom(mce,vatom));
1558
sewardjde8a5ae2004-11-06 14:20:54 +00001559 if (tyH == Ity_I32) {
1560 switch (ty) {
1561 case Ity_I32: return vatom;
1562 case Ity_I16: return assignNew(mce, tyH, unop(Iop_16Uto32, vatom));
1563 case Ity_I8: return assignNew(mce, tyH, unop(Iop_8Uto32, vatom));
1564 default: goto unhandled;
1565 }
1566 } else {
1567 goto unhandled;
1568 }
1569 unhandled:
1570 VG_(printf)("\nty = "); ppIRType(ty); VG_(printf)("\n");
1571 VG_(skin_panic)("zwidenToHostWord");
1572}
1573
1574
sewardj3598ef92004-11-11 02:13:30 +00001575/* Generate a shadow store. addr is always the original address atom.
1576 You can pass in either originals or V-bits for the data atom, but
1577 obviously not both. */
1578
sewardjde8a5ae2004-11-06 14:20:54 +00001579static
sewardj3598ef92004-11-11 02:13:30 +00001580void do_shadow_STle ( MCEnv* mce,
1581 IRAtom* addr, UInt bias,
1582 IRAtom* data, IRAtom* vdata )
sewardjde8a5ae2004-11-06 14:20:54 +00001583{
1584 IRType ty;
1585 IRDirty* di;
sewardjde8a5ae2004-11-06 14:20:54 +00001586 void* helper = NULL;
1587 Char* hname = NULL;
sewardj3598ef92004-11-11 02:13:30 +00001588 IRAtom* addrAct;
sewardjde8a5ae2004-11-06 14:20:54 +00001589
sewardj3598ef92004-11-11 02:13:30 +00001590 if (data) {
1591 sk_assert(!vdata);
1592 sk_assert(isOriginalAtom(mce, data));
1593 sk_assert(bias == 0);
1594 vdata = expr2vbits( mce, data );
1595 } else {
1596 sk_assert(vdata);
1597 }
sewardjde8a5ae2004-11-06 14:20:54 +00001598
1599 sk_assert(isOriginalAtom(mce,addr));
sewardj3598ef92004-11-11 02:13:30 +00001600 sk_assert(isShadowAtom(mce,vdata));
1601
1602 ty = typeOfIRExpr(mce->bb->tyenv, vdata);
sewardjde8a5ae2004-11-06 14:20:54 +00001603
1604 /* First, emit a definedness test for the address. This also sets
1605 the address (shadow) to 'defined' following the test. */
sewardj3598ef92004-11-11 02:13:30 +00001606 complainIfUndefined( mce, addr );
sewardjde8a5ae2004-11-06 14:20:54 +00001607
1608 /* Now cook up a call to the relevant helper function, to write the
1609 data V bits into shadow memory. */
sewardjde8a5ae2004-11-06 14:20:54 +00001610 switch (ty) {
sewardj3598ef92004-11-11 02:13:30 +00001611 case Ity_I64: helper = &MC_(helperc_STOREV8);
1612 hname = "MC_(helperc_STOREV8)";
1613 break;
sewardjde8a5ae2004-11-06 14:20:54 +00001614 case Ity_I32: helper = &MC_(helperc_STOREV4);
1615 hname = "MC_(helperc_STOREV4)";
1616 break;
1617 case Ity_I16: helper = &MC_(helperc_STOREV2);
1618 hname = "MC_(helperc_STOREV2)";
1619 break;
1620 case Ity_I8: helper = &MC_(helperc_STOREV1);
1621 hname = "MC_(helperc_STOREV1)";
1622 break;
1623 default: VG_(skin_panic)("memcheck:do_shadow_STle");
1624 }
1625
sewardj3598ef92004-11-11 02:13:30 +00001626 /* Generate the actual address into addrAct. */
1627 if (bias == 0) {
1628 addrAct = addr;
1629 } else {
1630 IRType tyAddr = mce->hWordTy;
sewardj3598ef92004-11-11 02:13:30 +00001631 IROp mkAdd = tyAddr==Ity_I32 ? Iop_Add32 : Iop_Add64;
1632 IRAtom* eBias = tyAddr==Ity_I32 ? mkU32(bias) : mkU64(bias);
sewardj8fc93742004-11-22 11:29:33 +00001633 sk_assert( tyAddr == Ity_I32 || tyAddr == Ity_I64 );
sewardj3598ef92004-11-11 02:13:30 +00001634 addrAct = assignNew(mce, tyAddr, binop(mkAdd, addr, eBias) );
1635 }
1636
1637 if (ty == Ity_I64) {
1638 /* We can't do this with regparm 2 on 32-bit platforms, since
1639 the back ends aren't clever enough to handle 64-bit regparm
1640 args. Therefore be different. */
1641 di = unsafeIRDirty_0_N(
1642 1/*regparms*/, hname, helper,
1643 mkIRExprVec_2( addrAct, vdata ));
1644 } else {
1645 di = unsafeIRDirty_0_N(
1646 2/*regparms*/, hname, helper,
1647 mkIRExprVec_2( addrAct,
1648 zwidenToHostWord( mce, vdata )));
1649 }
sewardjde8a5ae2004-11-06 14:20:54 +00001650 setHelperAnns( mce, di );
1651 stmt( mce->bb, IRStmt_Dirty(di) );
1652}
1653
1654
sewardj3598ef92004-11-11 02:13:30 +00001655/* Do lazy pessimistic propagation through a dirty helper call, by
1656 looking at the annotations on it. This is the most complex part of
1657 Memcheck. */
1658
1659static IRType szToITy ( Int n )
1660{
1661 switch (n) {
1662 case 1: return Ity_I8;
1663 case 2: return Ity_I16;
1664 case 4: return Ity_I32;
1665 case 8: return Ity_I64;
1666 default: VG_(skin_panic)("szToITy(memcheck)");
1667 }
1668}
1669
1670static
1671void do_shadow_Dirty ( MCEnv* mce, IRDirty* d )
1672{
1673 Int i, offset, toDo;
1674 IRAtom* src;
1675 IRType tyAddr, tySrc, tyDst;
1676 IRTemp dst;
sewardj8fc93742004-11-22 11:29:33 +00001677 IRAtom *here, *curr;
sewardj3598ef92004-11-11 02:13:30 +00001678
1679 /* First check the guard. */
1680 complainIfUndefined(mce, d->guard);
1681
1682 /* Now round up all inputs and PCast over them. */
sewardj8fc93742004-11-22 11:29:33 +00001683 curr = definedOfType(Ity_I32);
sewardj3598ef92004-11-11 02:13:30 +00001684
1685 /* Inputs: unmasked args */
1686 for (i = 0; d->args[i]; i++) {
1687 if (d->cee->mcx_mask & (1<<i)) {
1688 /* ignore this arg */
1689 } else {
1690 here = mkPCastTo( mce, Ity_I32, expr2vbits(mce, d->args[i]) );
1691 curr = mkUifU32(mce, here, curr);
1692 }
1693 }
1694
1695 /* Inputs: guest state that we read. */
1696 for (i = 0; i < d->nFxState; i++) {
1697 sk_assert(d->fxState[i].fx != Ifx_None);
1698 if (d->fxState[i].fx == Ifx_Write)
1699 continue;
1700 /* This state element is read or modified. So we need to
1701 consider it. */
1702 tySrc = szToITy( d->fxState[i].size );
1703 src = assignNew( mce, tySrc,
1704 shadow_GET(mce, d->fxState[i].offset, tySrc ) );
1705 here = mkPCastTo( mce, Ity_I32, src );
1706 curr = mkUifU32(mce, here, curr);
1707 }
1708
1709 /* Inputs: memory. First set up some info needed regardless of
1710 whether we're doing reads or writes. */
1711 tyAddr = Ity_INVALID;
1712
1713 if (d->mFx != Ifx_None) {
1714 /* Because we may do multiple shadow loads/stores from the same
1715 base address, it's best to do a single test of its
1716 definedness right now. Post-instrumentation optimisation
1717 should remove all but this test. */
1718 sk_assert(d->mAddr);
1719 complainIfUndefined(mce, d->mAddr);
1720
1721 tyAddr = typeOfIRExpr(mce->bb->tyenv, d->mAddr);
1722 sk_assert(tyAddr == Ity_I32 || tyAddr == Ity_I64);
1723 sk_assert(tyAddr == mce->hWordTy); /* not really right */
1724 }
1725
1726 /* Deal with memory inputs (reads or modifies) */
1727 if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify) {
1728 offset = 0;
1729 toDo = d->mSize;
1730 /* chew off 32-bit chunks */
1731 while (toDo >= 4) {
1732 here = mkPCastTo(
1733 mce, Ity_I32,
1734 expr2vbits_LDle ( mce, Ity_I32,
1735 d->mAddr, d->mSize - toDo )
1736 );
1737 curr = mkUifU32(mce, here, curr);
1738 toDo -= 4;
1739 }
1740 /* chew off 16-bit chunks */
1741 while (toDo >= 2) {
1742 here = mkPCastTo(
1743 mce, Ity_I32,
1744 expr2vbits_LDle ( mce, Ity_I16,
1745 d->mAddr, d->mSize - toDo )
1746 );
1747 curr = mkUifU32(mce, here, curr);
1748 toDo -= 2;
1749 }
1750 sk_assert(toDo == 0); /* also need to handle 1-byte excess */
1751 }
1752
1753 /* Whew! So curr is a 32-bit V-value summarising pessimistically
1754 all the inputs to the helper. Now we need to re-distribute the
1755 results to all destinations. */
1756
1757 /* Outputs: the destination temporary, if there is one. */
sewardj92d168d2004-11-15 14:22:12 +00001758 if (d->tmp != IRTemp_INVALID) {
sewardj3598ef92004-11-11 02:13:30 +00001759 dst = findShadowTmp(mce, d->tmp);
1760 tyDst = typeOfIRTemp(mce->bb->tyenv, d->tmp);
1761 assign( mce->bb, dst, mkPCastTo( mce, tyDst, curr) );
1762 }
1763
1764 /* Outputs: guest state that we write or modify. */
1765 for (i = 0; i < d->nFxState; i++) {
1766 sk_assert(d->fxState[i].fx != Ifx_None);
1767 if (d->fxState[i].fx == Ifx_Read)
1768 continue;
1769 /* this state element is written or modified. So we need to
1770 consider it. */
1771 tyDst = szToITy( d->fxState[i].size );
1772 do_shadow_PUT( mce, d->fxState[i].offset,
1773 NULL, /* original atom */
1774 mkPCastTo( mce, tyDst, curr ) );
1775 }
1776
1777 /* Outputs: memory that we write or modify. */
1778 if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify) {
1779 offset = 0;
1780 toDo = d->mSize;
1781 /* chew off 32-bit chunks */
1782 while (toDo >= 4) {
1783 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1784 NULL, /* original data */
1785 mkPCastTo( mce, Ity_I32, curr ) );
1786 toDo -= 4;
1787 }
1788 /* chew off 16-bit chunks */
1789 while (toDo >= 2) {
1790 do_shadow_STle( mce, d->mAddr, d->mSize - toDo,
1791 NULL, /* original data */
1792 mkPCastTo( mce, Ity_I16, curr ) );
1793 toDo -= 2;
1794 }
1795 sk_assert(toDo == 0); /* also need to handle 1-byte excess */
1796 }
1797
1798}
1799
1800
sewardjde8a5ae2004-11-06 14:20:54 +00001801/*------------------------------------------------------------*/
1802/*--- Memcheck main ---*/
1803/*------------------------------------------------------------*/
1804
sewardj3598ef92004-11-11 02:13:30 +00001805#if 0 /* UNUSED */
1806static Bool isBogusAtom ( IRAtom* at )
1807{
1808 ULong n = 0;
1809 IRConst* con;
1810 sk_assert(isAtom(at));
1811 if (at->tag == Iex_Tmp)
1812 return False;
1813 sk_assert(at->tag == Iex_Const);
1814 con = at->Iex.Const.con;
1815 switch (con->tag) {
1816 case Ico_U8: n = (ULong)con->Ico.U8; break;
1817 case Ico_U16: n = (ULong)con->Ico.U16; break;
1818 case Ico_U32: n = (ULong)con->Ico.U32; break;
1819 case Ico_U64: n = (ULong)con->Ico.U64; break;
1820 default: ppIRExpr(at); sk_assert(0);
1821 }
1822 /* VG_(printf)("%llx\n", n); */
1823 return (n == 0xFEFEFEFF
1824 || n == 0x80808080
1825 || n == 0x1010101
1826 || n == 1010100);
1827}
1828
1829static Bool checkForBogusLiterals ( /*FLAT*/ IRStmt* st )
1830{
1831 Int i;
1832 IRExpr* e;
1833 switch (st->tag) {
1834 case Ist_Tmp:
1835 e = st->Ist.Tmp.data;
1836 switch (e->tag) {
1837 case Iex_Get:
1838 case Iex_Tmp:
1839 return False;
1840 case Iex_Unop:
1841 return isBogusAtom(e->Iex.Unop.arg);
1842 case Iex_Binop:
1843 return isBogusAtom(e->Iex.Binop.arg1)
1844 || isBogusAtom(e->Iex.Binop.arg2);
1845 case Iex_Mux0X:
1846 return isBogusAtom(e->Iex.Mux0X.cond)
1847 || isBogusAtom(e->Iex.Mux0X.expr0)
1848 || isBogusAtom(e->Iex.Mux0X.exprX);
1849 case Iex_LDle:
1850 return isBogusAtom(e->Iex.LDle.addr);
1851 case Iex_CCall:
1852 for (i = 0; e->Iex.CCall.args[i]; i++)
1853 if (isBogusAtom(e->Iex.CCall.args[i]))
1854 return True;
1855 return False;
1856 default:
1857 goto unhandled;
1858 }
1859 case Ist_Put:
1860 return isBogusAtom(st->Ist.Put.data);
1861 case Ist_STle:
1862 return isBogusAtom(st->Ist.STle.addr)
1863 || isBogusAtom(st->Ist.STle.data);
1864 case Ist_Exit:
sewardj0276d4b2004-11-15 15:30:21 +00001865 return isBogusAtom(st->Ist.Exit.guard);
sewardj3598ef92004-11-11 02:13:30 +00001866 default:
1867 unhandled:
1868 ppIRStmt(st);
1869 VG_(skin_panic)("hasBogusLiterals");
1870 }
1871}
1872#endif /* UNUSED */
1873
1874
sewardjde8a5ae2004-11-06 14:20:54 +00001875IRBB* mc_instrument ( IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
1876{
sewardj3598ef92004-11-11 02:13:30 +00001877 Bool verboze = False; //True;
1878
1879 /* Bool hasBogusLiterals = False; */
sewardjde8a5ae2004-11-06 14:20:54 +00001880
1881 Int i, j, first_stmt;
1882 IRStmt* st;
1883 MCEnv mce;
1884
1885 /* Set up BB */
1886 IRBB* bb = emptyIRBB();
1887 bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
1888 bb->next = dopyIRExpr(bb_in->next);
1889 bb->jumpkind = bb_in->jumpkind;
1890
1891 /* Set up the running environment. Only .bb is modified as we go
1892 along. */
1893 mce.bb = bb;
1894 mce.layout = layout;
1895 mce.n_originalTmps = bb->tyenv->types_used;
1896 mce.hWordTy = hWordTy;
1897 mce.tmpMap = LibVEX_Alloc(mce.n_originalTmps * sizeof(IRTemp));
1898 for (i = 0; i < mce.n_originalTmps; i++)
sewardj92d168d2004-11-15 14:22:12 +00001899 mce.tmpMap[i] = IRTemp_INVALID;
sewardjde8a5ae2004-11-06 14:20:54 +00001900
1901 /* Iterate over the stmts. */
1902
1903 for (i = 0; i < bb_in->stmts_used; i++) {
1904 st = bb_in->stmts[i];
1905 if (!st) continue;
1906
1907 sk_assert(isFlatIRStmt(st));
sewardj3598ef92004-11-11 02:13:30 +00001908
1909 /*
1910 if (!hasBogusLiterals) {
1911 hasBogusLiterals = checkForBogusLiterals(st);
1912 if (hasBogusLiterals) {
1913 VG_(printf)("bogus: ");
1914 ppIRStmt(st);
1915 VG_(printf)("\n");
1916 }
1917 }
1918 */
sewardjde8a5ae2004-11-06 14:20:54 +00001919 first_stmt = bb->stmts_used;
1920
1921 if (verboze) {
1922 ppIRStmt(st);
1923 VG_(printf)("\n\n");
1924 }
1925
1926 switch (st->tag) {
1927
1928 case Ist_Tmp:
1929 assign( bb, findShadowTmp(&mce, st->Ist.Tmp.tmp),
1930 expr2vbits( &mce, st->Ist.Tmp.data) );
1931 break;
1932
1933 case Ist_Put:
1934 do_shadow_PUT( &mce,
1935 st->Ist.Put.offset,
sewardj3598ef92004-11-11 02:13:30 +00001936 st->Ist.Put.data,
1937 NULL /* shadow atom */ );
sewardjde8a5ae2004-11-06 14:20:54 +00001938 break;
1939
1940 case Ist_PutI:
1941 do_shadow_PUTI( &mce,
1942 st->Ist.PutI.descr,
1943 st->Ist.PutI.ix,
1944 st->Ist.PutI.bias,
1945 st->Ist.PutI.data );
1946 break;
1947
1948 case Ist_STle:
sewardj3598ef92004-11-11 02:13:30 +00001949 do_shadow_STle( &mce, st->Ist.STle.addr, 0/* addr bias */,
1950 st->Ist.STle.data,
1951 NULL /* shadow data */ );
sewardjde8a5ae2004-11-06 14:20:54 +00001952 break;
1953
1954 case Ist_Exit:
sewardj3598ef92004-11-11 02:13:30 +00001955 /* if (!hasBogusLiterals) */
sewardj0276d4b2004-11-15 15:30:21 +00001956 complainIfUndefined( &mce, st->Ist.Exit.guard );
sewardj3598ef92004-11-11 02:13:30 +00001957 break;
1958
1959 case Ist_Dirty:
1960 do_shadow_Dirty( &mce, st->Ist.Dirty.details );
sewardjde8a5ae2004-11-06 14:20:54 +00001961 break;
1962
1963 default:
1964 VG_(printf)("\n");
1965 ppIRStmt(st);
1966 VG_(printf)("\n");
1967 VG_(skin_panic)("memcheck: unhandled IRStmt");
1968
1969 } /* switch (st->tag) */
1970
1971 if (verboze) {
1972 for (j = first_stmt; j < bb->stmts_used; j++) {
1973 VG_(printf)(" ");
1974 ppIRStmt(bb->stmts[j]);
1975 VG_(printf)("\n");
1976 }
1977 VG_(printf)("\n");
1978 }
1979
1980 addStmtToIRBB(bb, st);
1981
1982 }
1983
1984 /* Now we need to complain if the jump target is undefined. */
1985 first_stmt = bb->stmts_used;
1986
1987 if (verboze) {
1988 VG_(printf)("bb->next = ");
1989 ppIRExpr(bb->next);
1990 VG_(printf)("\n\n");
1991 }
1992
1993 complainIfUndefined( &mce, bb->next );
1994
1995 if (verboze) {
1996 for (j = first_stmt; j < bb->stmts_used; j++) {
1997 VG_(printf)(" ");
1998 ppIRStmt(bb->stmts[j]);
1999 VG_(printf)("\n");
2000 }
2001 VG_(printf)("\n");
2002 }
2003
2004 return bb;
2005}
2006
2007/*--------------------------------------------------------------------*/
2008/*--- end mc_translate.c ---*/
2009/*--------------------------------------------------------------------*/