sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 1 | |
| 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> |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 11 | #include <assert.h> |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 12 | #include <string.h> |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 13 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 14 | #include "libvex_basictypes.h" |
| 15 | #include "libvex.h" |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 16 | |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 17 | #include "test_main.h" |
| 18 | |
| 19 | |
sewardj | c97096c | 2004-06-30 09:28:04 +0000 | [diff] [blame] | 20 | /*---------------------------------------------------------------*/ |
| 21 | /*--- Test ---*/ |
| 22 | /*---------------------------------------------------------------*/ |
| 23 | |
sewardj | ce605f9 | 2004-07-05 14:39:15 +0000 | [diff] [blame] | 24 | |
sewardj | 2b51587 | 2004-07-05 20:50:45 +0000 | [diff] [blame] | 25 | __attribute__ ((noreturn)) |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 26 | static |
sewardj | ce605f9 | 2004-07-05 14:39:15 +0000 | [diff] [blame] | 27 | void failure_exit ( void ) |
| 28 | { |
| 29 | fprintf(stdout, "VEX did failure_exit. Bye.\n"); |
| 30 | exit(1); |
| 31 | } |
| 32 | |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 33 | static |
sewardj | ce605f9 | 2004-07-05 14:39:15 +0000 | [diff] [blame] | 34 | void log_bytes ( Char* bytes, Int nbytes ) |
| 35 | { |
| 36 | fwrite ( bytes, 1, nbytes, stdout ); |
| 37 | } |
| 38 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 39 | #define N_LINEBUF 10000 |
sewardj | 41f43bc | 2004-07-08 14:23:22 +0000 | [diff] [blame] | 40 | static Char linebuf[N_LINEBUF]; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 41 | |
sewardj | f05537e | 2004-10-14 01:08:12 +0000 | [diff] [blame] | 42 | #define N_ORIGBUF 1000 |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 43 | #define N_TRANSBUF 5000 |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 44 | |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 45 | static UChar origbuf[N_ORIGBUF]; |
| 46 | static UChar transbuf[N_TRANSBUF]; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 47 | |
sewardj | 1f40a0a | 2004-07-21 12:28:07 +0000 | [diff] [blame] | 48 | static Bool verbose = True; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 49 | |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 50 | /* Forwards */ |
| 51 | static IRBB* ac_instrument ( IRBB*, VexGuestLayoutInfo* ); |
| 52 | |
| 53 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 54 | int main ( int argc, char** argv ) |
sewardj | ce605f9 | 2004-07-05 14:39:15 +0000 | [diff] [blame] | 55 | { |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 56 | FILE* f; |
| 57 | Int i; |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 58 | UInt u, sum; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 59 | Addr32 orig_addr; |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 60 | Int bb_number, n_bbs_done = 0; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 61 | Int orig_nbytes, trans_used, orig_used; |
| 62 | TranslateResult tres; |
sewardj | b5bf2e0 | 2004-10-25 13:06:17 +0000 | [diff] [blame] | 63 | VexControl vcon; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 64 | |
| 65 | if (argc != 2) { |
| 66 | fprintf(stderr, "usage: vex file.org\n"); |
| 67 | exit(1); |
| 68 | } |
| 69 | f = fopen(argv[1], "r"); |
| 70 | if (!f) { |
| 71 | fprintf(stderr, "can't open `%s'\n", argv[1]); |
| 72 | exit(1); |
| 73 | } |
| 74 | |
sewardj | b5bf2e0 | 2004-10-25 13:06:17 +0000 | [diff] [blame] | 75 | /* Run with default params. However, we can't allow bb chasing |
| 76 | since that causes the front end to get segfaults when it tries |
| 77 | to read code outside the initial BB we hand it. */ |
| 78 | LibVEX_default_VexControl ( &vcon ); |
| 79 | vcon.guest_chase_thresh = 0; |
sewardj | b495240 | 2004-10-26 13:24:50 +0000 | [diff] [blame] | 80 | vcon.iropt_level = 2; |
sewardj | b5bf2e0 | 2004-10-25 13:06:17 +0000 | [diff] [blame] | 81 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 82 | LibVEX_Init ( &failure_exit, &log_bytes, |
sewardj | 1f40a0a | 2004-07-21 12:28:07 +0000 | [diff] [blame] | 83 | 1, /* debug_paranoia */ |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 84 | TEST_VSUPPORT, /* valgrind support */ |
sewardj | b5bf2e0 | 2004-10-25 13:06:17 +0000 | [diff] [blame] | 85 | &vcon ); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 86 | |
sewardj | ea64e14 | 2004-07-22 16:47:21 +0000 | [diff] [blame] | 87 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 88 | while (!feof(f)) { |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 89 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 90 | fgets(linebuf, N_LINEBUF,f); |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 91 | if (linebuf[0] == 0) continue; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 92 | if (linebuf[0] != '.') continue; |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 93 | |
| 94 | if (n_bbs_done == TEST_N_BBS) break; |
| 95 | n_bbs_done++; |
| 96 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 97 | /* first line is: . bb-number bb-addr n-bytes */ |
| 98 | assert(3 == sscanf(&linebuf[1], " %d %x %d\n", |
| 99 | & bb_number, |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 100 | & orig_addr, & orig_nbytes )); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 101 | assert(orig_nbytes >= 1); |
| 102 | assert(!feof(f)); |
| 103 | fgets(linebuf, N_LINEBUF,f); |
| 104 | assert(linebuf[0] == '.'); |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 105 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 106 | /* second line is: . byte byte byte etc */ |
sewardj | 1f40a0a | 2004-07-21 12:28:07 +0000 | [diff] [blame] | 107 | if (verbose) |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 108 | printf("============ Basic Block %d, " |
| 109 | "Start %x, nbytes %2d ============", |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 110 | n_bbs_done-1, orig_addr, orig_nbytes); |
| 111 | |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 112 | assert(orig_nbytes >= 1 && orig_nbytes <= N_ORIGBUF); |
| 113 | for (i = 0; i < orig_nbytes; i++) { |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 114 | assert(1 == sscanf(&linebuf[2 + 3*i], "%x", &u)); |
| 115 | origbuf[i] = (UChar)u; |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 116 | } |
| 117 | |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 118 | for (i = 0; i < TEST_N_ITERS; i++) |
| 119 | tres |
| 120 | = LibVEX_Translate ( |
| 121 | InsnSetX86, InsnSetX86, |
| 122 | origbuf, (Addr64)orig_addr, &orig_used, |
| 123 | transbuf, N_TRANSBUF, &trans_used, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 124 | ac_instrument, //NULL, /* instrument1 */ |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 125 | NULL, /* instrument2 */ |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 126 | NULL, /* access checker */ |
| 127 | TEST_FLAGS |
| 128 | ); |
| 129 | |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 130 | if (tres != TransOK) |
| 131 | printf("\ntres = %d\n", (Int)tres); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 132 | assert(tres == TransOK); |
| 133 | assert(orig_used == orig_nbytes); |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 134 | |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 135 | sum = 0; |
| 136 | for (i = 0; i < trans_used; i++) |
| 137 | sum += (UInt)transbuf[i]; |
| 138 | printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum ); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 139 | } |
| 140 | |
| 141 | fclose(f); |
sewardj | f05537e | 2004-10-14 01:08:12 +0000 | [diff] [blame] | 142 | printf("\n"); |
sewardj | 1f40a0a | 2004-07-21 12:28:07 +0000 | [diff] [blame] | 143 | LibVEX_ClearTemporary(True); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 144 | |
sewardj | ce605f9 | 2004-07-05 14:39:15 +0000 | [diff] [blame] | 145 | return 0; |
| 146 | } |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 147 | |
| 148 | ////////////////////////////////////////////////////////////////////// |
| 149 | |
| 150 | static |
| 151 | void panic ( Char* s ) |
| 152 | { |
| 153 | printf("\npanic: %s\n", s); |
| 154 | failure_exit(); |
| 155 | } |
| 156 | |
| 157 | static |
| 158 | IRBB* ac_instrument (IRBB* bb_in, VexGuestLayoutInfo* layout) |
| 159 | { |
| 160 | /* Use this rather than eg. -1 because it's a UInt. */ |
| 161 | #define INVALID_DATA_SIZE 999999 |
| 162 | |
| 163 | Int i; |
| 164 | Int sz; |
| 165 | IRCallee* helper; |
| 166 | IRStmt* st; |
| 167 | IRExpr* data; |
| 168 | IRExpr* addr; |
| 169 | Bool needSz; |
| 170 | |
| 171 | /* Set up BB */ |
| 172 | IRBB* bb = emptyIRBB(); |
| 173 | bb->tyenv = dopyIRTypeEnv(bb_in->tyenv); |
| 174 | bb->next = dopyIRExpr(bb_in->next); |
| 175 | bb->jumpkind = bb_in->jumpkind; |
| 176 | |
| 177 | /* No loads to consider in ->next. */ |
| 178 | assert(isAtom(bb_in->next)); |
| 179 | |
| 180 | for (i = 0; i < bb_in->stmts_used; i++) { |
| 181 | st = bb_in->stmts[i]; |
| 182 | if (!st) continue; |
| 183 | |
| 184 | switch (st->tag) { |
| 185 | |
| 186 | case Ist_Tmp: |
| 187 | data = st->Ist.Tmp.data; |
| 188 | if (data->tag == Iex_LDle) { |
| 189 | addr = data->Iex.LDle.addr; |
| 190 | sz = sizeofIRType(data->Iex.LDle.ty); |
| 191 | needSz = False; |
| 192 | switch (sz) { |
| 193 | case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 194 | (void*)0x12345601); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 195 | case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 196 | (void*)0x12345602); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 197 | case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 198 | (void*)0x12345603); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 199 | default: helper = mkIRCallee(0, "ac_helperc_LOADN", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 200 | (void*)0x12345604); |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 201 | needSz = True; break; |
| 202 | } |
| 203 | if (needSz) { |
| 204 | addStmtToIRBB( |
| 205 | bb, |
| 206 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 207 | unsafeIRDirty_0_N( helper->regparms, |
| 208 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 209 | mkIRExprVec_2(addr, mkIRExpr_HWord(sz))) |
| 210 | )); |
| 211 | } else { |
| 212 | addStmtToIRBB( |
| 213 | bb, |
| 214 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 215 | unsafeIRDirty_0_N( helper->regparms, |
| 216 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 217 | mkIRExprVec_1(addr) ) |
| 218 | )); |
| 219 | } |
| 220 | } |
| 221 | break; |
| 222 | |
| 223 | case Ist_STle: |
| 224 | data = st->Ist.STle.data; |
| 225 | addr = st->Ist.STle.addr; |
| 226 | assert(isAtom(data)); |
| 227 | assert(isAtom(addr)); |
| 228 | sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data)); |
| 229 | needSz = False; |
| 230 | switch (sz) { |
| 231 | case 4: helper = mkIRCallee(1, "ac_helperc_STORE4", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 232 | (void*)0x12345605); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 233 | case 2: helper = mkIRCallee(0, "ac_helperc_STORE2", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 234 | (void*)0x12345606); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 235 | case 1: helper = mkIRCallee(1, "ac_helperc_STORE1", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 236 | (void*)0x12345607); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 237 | default: helper = mkIRCallee(0, "ac_helperc_STOREN", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 238 | (void*)0x12345608); |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 239 | needSz = True; break; |
| 240 | } |
| 241 | if (needSz) { |
| 242 | addStmtToIRBB( |
| 243 | bb, |
| 244 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 245 | unsafeIRDirty_0_N( helper->regparms, |
| 246 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 247 | mkIRExprVec_2(addr, mkIRExpr_HWord(sz))) |
| 248 | )); |
| 249 | } else { |
| 250 | addStmtToIRBB( |
| 251 | bb, |
| 252 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 253 | unsafeIRDirty_0_N( helper->regparms, |
| 254 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 255 | mkIRExprVec_1(addr) ) |
| 256 | )); |
| 257 | } |
| 258 | break; |
| 259 | |
| 260 | case Ist_Put: |
| 261 | assert(isAtom(st->Ist.Put.data)); |
| 262 | break; |
| 263 | |
| 264 | case Ist_PutI: |
| 265 | assert(isAtom(st->Ist.PutI.off)); |
| 266 | assert(isAtom(st->Ist.PutI.data)); |
| 267 | break; |
| 268 | |
| 269 | case Ist_Exit: |
| 270 | assert(isAtom(st->Ist.Exit.cond)); |
| 271 | break; |
| 272 | |
| 273 | case Ist_Dirty: |
| 274 | /* If the call doesn't interact with memory, we ain't |
| 275 | interested. */ |
| 276 | if (st->Ist.Dirty.details->mFx == Ifx_None) |
| 277 | break; |
| 278 | goto unhandled; |
| 279 | |
| 280 | default: |
| 281 | unhandled: |
| 282 | printf("\n"); |
| 283 | ppIRStmt(st); |
| 284 | printf("\n"); |
| 285 | panic("addrcheck: unhandled IRStmt"); |
| 286 | } |
| 287 | |
| 288 | addStmtToIRBB( bb, dopyIRStmt(st)); |
| 289 | } |
| 290 | |
| 291 | return bb; |
| 292 | } |