blob: 5c2d3005905576c741fd06574967629b6d1941ea [file] [log] [blame]
/*---------------------------------------------------------------*/
/*--- ---*/
/*--- This file (test_main.c) is ---*/
/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/
/*--- ---*/
/*---------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "libvex_basictypes.h"
#include "libvex.h"
#include "test_main.h"
/*---------------------------------------------------------------*/
/*--- Test ---*/
/*---------------------------------------------------------------*/
__attribute__ ((noreturn))
static
void failure_exit ( void )
{
fprintf(stdout, "VEX did failure_exit. Bye.\n");
exit(1);
}
static
void log_bytes ( Char* bytes, Int nbytes )
{
fwrite ( bytes, 1, nbytes, stdout );
}
#define N_LINEBUF 10000
static Char linebuf[N_LINEBUF];
#define N_ORIGBUF 1000
#define N_TRANSBUF 5000
static UChar origbuf[N_ORIGBUF];
static UChar transbuf[N_TRANSBUF];
static Bool verbose = True;
/* Forwards */
static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType );
int main ( int argc, char** argv )
{
FILE* f;
Int i;
UInt u, sum;
Addr32 orig_addr;
Int bb_number, n_bbs_done = 0;
Int orig_nbytes, trans_used, orig_used;
TranslateResult tres;
VexControl vcon;
if (argc != 2) {
fprintf(stderr, "usage: vex file.org\n");
exit(1);
}
f = fopen(argv[1], "r");
if (!f) {
fprintf(stderr, "can't open `%s'\n", argv[1]);
exit(1);
}
/* Run with default params. However, we can't allow bb chasing
since that causes the front end to get segfaults when it tries
to read code outside the initial BB we hand it. */
LibVEX_default_VexControl ( &vcon );
vcon.guest_chase_thresh = 0;
vcon.iropt_level = 2;
LibVEX_Init ( &failure_exit, &log_bytes,
1, /* debug_paranoia */
TEST_VSUPPORT, /* valgrind support */
&vcon );
while (!feof(f)) {
fgets(linebuf, N_LINEBUF,f);
if (linebuf[0] == 0) continue;
if (linebuf[0] != '.') continue;
if (n_bbs_done == TEST_N_BBS) break;
n_bbs_done++;
/* first line is: . bb-number bb-addr n-bytes */
assert(3 == sscanf(&linebuf[1], " %d %x %d\n",
& bb_number,
& orig_addr, & orig_nbytes ));
assert(orig_nbytes >= 1);
assert(!feof(f));
fgets(linebuf, N_LINEBUF,f);
assert(linebuf[0] == '.');
/* second line is: . byte byte byte etc */
if (verbose)
printf("============ Basic Block %d, "
"Start %x, nbytes %2d ============",
n_bbs_done-1, orig_addr, orig_nbytes);
assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF);
for (i = 0; i < orig_nbytes; i++) {
assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u));
origbuf[i] = (UChar)u;
}
for (i = 0; i < TEST_N_ITERS; i++)
tres
= LibVEX_Translate (
InsnSetX86, InsnSetX86,
origbuf, (Addr64)orig_addr, &orig_used,
transbuf, N_TRANSBUF, &trans_used,
ac_instrument, //NULL, /* instrument1 */
NULL, /* instrument2 */
False, /* cleanup after instrument */
NULL, /* access checker */
TEST_FLAGS
);
if (tres != TransOK)
printf("\ntres = %d\n", (Int)tres);
assert(tres == TransOK);
assert(orig_used == orig_nbytes);
sum = 0;
for (i = 0; i < trans_used; i++)
sum += (UInt)transbuf[i];
printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum );
}
fclose(f);
printf("\n");
LibVEX_ClearTemporary(True);
return 0;
}
//////////////////////////////////////////////////////////////////////
static
void panic ( Char* s )
{
printf("\npanic: %s\n", s);
failure_exit();
}
static
IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy )
{
/* Use this rather than eg. -1 because it's a UInt. */
#define INVALID_DATA_SIZE 999999
Int i;
Int sz;
IRCallee* helper;
IRStmt* st;
IRExpr* data;
IRExpr* addr;
Bool needSz;
/* Set up BB */
IRBB* bb = emptyIRBB();
bb->tyenv = dopyIRTypeEnv(bb_in->tyenv);
bb->next = dopyIRExpr(bb_in->next);
bb->jumpkind = bb_in->jumpkind;
/* No loads to consider in ->next. */
assert(isAtom(bb_in->next));
for (i = 0; i < bb_in->stmts_used; i++) {
st = bb_in->stmts[i];
if (!st) continue;
switch (st->tag) {
case Ist_Tmp:
data = st->Ist.Tmp.data;
if (data->tag == Iex_LDle) {
addr = data->Iex.LDle.addr;
sz = sizeofIRType(data->Iex.LDle.ty);
needSz = False;
switch (sz) {
case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4",
(void*)0x12345601); break;
case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2",
(void*)0x12345602); break;
case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1",
(void*)0x12345603); break;
default: helper = mkIRCallee(0, "ac_helperc_LOADN",
(void*)0x12345604);
needSz = True; break;
}
if (needSz) {
addStmtToIRBB(
bb,
IRStmt_Dirty(
unsafeIRDirty_0_N( helper->regparms,
helper->name, helper->addr,
mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
));
} else {
addStmtToIRBB(
bb,
IRStmt_Dirty(
unsafeIRDirty_0_N( helper->regparms,
helper->name, helper->addr,
mkIRExprVec_1(addr) )
));
}
}
break;
case Ist_STle:
data = st->Ist.STle.data;
addr = st->Ist.STle.addr;
assert(isAtom(data));
assert(isAtom(addr));
sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data));
needSz = False;
switch (sz) {
case 4: helper = mkIRCallee(1, "ac_helperc_STORE4",
(void*)0x12345605); break;
case 2: helper = mkIRCallee(0, "ac_helperc_STORE2",
(void*)0x12345606); break;
case 1: helper = mkIRCallee(1, "ac_helperc_STORE1",
(void*)0x12345607); break;
default: helper = mkIRCallee(0, "ac_helperc_STOREN",
(void*)0x12345608);
needSz = True; break;
}
if (needSz) {
addStmtToIRBB(
bb,
IRStmt_Dirty(
unsafeIRDirty_0_N( helper->regparms,
helper->name, helper->addr,
mkIRExprVec_2(addr, mkIRExpr_HWord(sz)))
));
} else {
addStmtToIRBB(
bb,
IRStmt_Dirty(
unsafeIRDirty_0_N( helper->regparms,
helper->name, helper->addr,
mkIRExprVec_1(addr) )
));
}
break;
case Ist_Put:
assert(isAtom(st->Ist.Put.data));
break;
case Ist_PutI:
assert(isAtom(st->Ist.PutI.ix));
assert(isAtom(st->Ist.PutI.data));
break;
case Ist_Exit:
assert(isAtom(st->Ist.Exit.cond));
break;
case Ist_Dirty:
/* If the call doesn't interact with memory, we ain't
interested. */
if (st->Ist.Dirty.details->mFx == Ifx_None)
break;
goto unhandled;
default:
unhandled:
printf("\n");
ppIRStmt(st);
printf("\n");
panic("addrcheck: unhandled IRStmt");
}
addStmtToIRBB( bb, dopyIRStmt(st));
}
return bb;
}