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 */ |
sewardj | 9578a8b | 2004-11-04 19:44:48 +0000 | [diff] [blame^] | 51 | static IRBB* ac_instrument ( IRBB*, VexGuestLayout*, IRType ); |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 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 | 9578a8b | 2004-11-04 19:44:48 +0000 | [diff] [blame^] | 126 | False, /* cleanup after instrument */ |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 127 | NULL, /* access checker */ |
| 128 | TEST_FLAGS |
| 129 | ); |
| 130 | |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 131 | if (tres != TransOK) |
| 132 | printf("\ntres = %d\n", (Int)tres); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 133 | assert(tres == TransOK); |
| 134 | assert(orig_used == orig_nbytes); |
sewardj | abe017e | 2004-10-29 23:42:36 +0000 | [diff] [blame] | 135 | |
sewardj | 4459baa | 2004-09-10 20:00:46 +0000 | [diff] [blame] | 136 | sum = 0; |
| 137 | for (i = 0; i < trans_used; i++) |
| 138 | sum += (UInt)transbuf[i]; |
| 139 | printf ( " %6.2f ... %d\n", (double)trans_used / (double)orig_used, sum ); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 140 | } |
| 141 | |
| 142 | fclose(f); |
sewardj | f05537e | 2004-10-14 01:08:12 +0000 | [diff] [blame] | 143 | printf("\n"); |
sewardj | 1f40a0a | 2004-07-21 12:28:07 +0000 | [diff] [blame] | 144 | LibVEX_ClearTemporary(True); |
sewardj | ced9fe5 | 2004-07-07 11:55:36 +0000 | [diff] [blame] | 145 | |
sewardj | ce605f9 | 2004-07-05 14:39:15 +0000 | [diff] [blame] | 146 | return 0; |
| 147 | } |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 148 | |
| 149 | ////////////////////////////////////////////////////////////////////// |
| 150 | |
| 151 | static |
| 152 | void panic ( Char* s ) |
| 153 | { |
| 154 | printf("\npanic: %s\n", s); |
| 155 | failure_exit(); |
| 156 | } |
| 157 | |
| 158 | static |
sewardj | 9578a8b | 2004-11-04 19:44:48 +0000 | [diff] [blame^] | 159 | IRBB* ac_instrument (IRBB* bb_in, VexGuestLayout* layout, IRType hWordTy ) |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 160 | { |
| 161 | /* Use this rather than eg. -1 because it's a UInt. */ |
| 162 | #define INVALID_DATA_SIZE 999999 |
| 163 | |
| 164 | Int i; |
| 165 | Int sz; |
| 166 | IRCallee* helper; |
| 167 | IRStmt* st; |
| 168 | IRExpr* data; |
| 169 | IRExpr* addr; |
| 170 | Bool needSz; |
| 171 | |
| 172 | /* Set up BB */ |
| 173 | IRBB* bb = emptyIRBB(); |
| 174 | bb->tyenv = dopyIRTypeEnv(bb_in->tyenv); |
| 175 | bb->next = dopyIRExpr(bb_in->next); |
| 176 | bb->jumpkind = bb_in->jumpkind; |
| 177 | |
| 178 | /* No loads to consider in ->next. */ |
| 179 | assert(isAtom(bb_in->next)); |
| 180 | |
| 181 | for (i = 0; i < bb_in->stmts_used; i++) { |
| 182 | st = bb_in->stmts[i]; |
| 183 | if (!st) continue; |
| 184 | |
| 185 | switch (st->tag) { |
| 186 | |
| 187 | case Ist_Tmp: |
| 188 | data = st->Ist.Tmp.data; |
| 189 | if (data->tag == Iex_LDle) { |
| 190 | addr = data->Iex.LDle.addr; |
| 191 | sz = sizeofIRType(data->Iex.LDle.ty); |
| 192 | needSz = False; |
| 193 | switch (sz) { |
| 194 | case 4: helper = mkIRCallee(1, "ac_helperc_LOAD4", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 195 | (void*)0x12345601); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 196 | case 2: helper = mkIRCallee(0, "ac_helperc_LOAD2", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 197 | (void*)0x12345602); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 198 | case 1: helper = mkIRCallee(1, "ac_helperc_LOAD1", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 199 | (void*)0x12345603); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 200 | default: helper = mkIRCallee(0, "ac_helperc_LOADN", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 201 | (void*)0x12345604); |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 202 | needSz = True; break; |
| 203 | } |
| 204 | if (needSz) { |
| 205 | addStmtToIRBB( |
| 206 | bb, |
| 207 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 208 | unsafeIRDirty_0_N( helper->regparms, |
| 209 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 210 | mkIRExprVec_2(addr, mkIRExpr_HWord(sz))) |
| 211 | )); |
| 212 | } else { |
| 213 | addStmtToIRBB( |
| 214 | bb, |
| 215 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 216 | unsafeIRDirty_0_N( helper->regparms, |
| 217 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 218 | mkIRExprVec_1(addr) ) |
| 219 | )); |
| 220 | } |
| 221 | } |
| 222 | break; |
| 223 | |
| 224 | case Ist_STle: |
| 225 | data = st->Ist.STle.data; |
| 226 | addr = st->Ist.STle.addr; |
| 227 | assert(isAtom(data)); |
| 228 | assert(isAtom(addr)); |
| 229 | sz = sizeofIRType(typeOfIRExpr(bb_in->tyenv, data)); |
| 230 | needSz = False; |
| 231 | switch (sz) { |
| 232 | case 4: helper = mkIRCallee(1, "ac_helperc_STORE4", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 233 | (void*)0x12345605); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 234 | case 2: helper = mkIRCallee(0, "ac_helperc_STORE2", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 235 | (void*)0x12345606); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 236 | case 1: helper = mkIRCallee(1, "ac_helperc_STORE1", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 237 | (void*)0x12345607); break; |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 238 | default: helper = mkIRCallee(0, "ac_helperc_STOREN", |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 239 | (void*)0x12345608); |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 240 | needSz = True; break; |
| 241 | } |
| 242 | if (needSz) { |
| 243 | addStmtToIRBB( |
| 244 | bb, |
| 245 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 246 | unsafeIRDirty_0_N( helper->regparms, |
| 247 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 248 | mkIRExprVec_2(addr, mkIRExpr_HWord(sz))) |
| 249 | )); |
| 250 | } else { |
| 251 | addStmtToIRBB( |
| 252 | bb, |
| 253 | IRStmt_Dirty( |
sewardj | f543586 | 2004-10-31 20:04:05 +0000 | [diff] [blame] | 254 | unsafeIRDirty_0_N( helper->regparms, |
| 255 | helper->name, helper->addr, |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 256 | mkIRExprVec_1(addr) ) |
| 257 | )); |
| 258 | } |
| 259 | break; |
| 260 | |
| 261 | case Ist_Put: |
| 262 | assert(isAtom(st->Ist.Put.data)); |
| 263 | break; |
| 264 | |
| 265 | case Ist_PutI: |
sewardj | eeac841 | 2004-11-02 00:26:55 +0000 | [diff] [blame] | 266 | assert(isAtom(st->Ist.PutI.ix)); |
sewardj | 9b1004e | 2004-10-30 22:25:40 +0000 | [diff] [blame] | 267 | assert(isAtom(st->Ist.PutI.data)); |
| 268 | break; |
| 269 | |
| 270 | case Ist_Exit: |
| 271 | assert(isAtom(st->Ist.Exit.cond)); |
| 272 | break; |
| 273 | |
| 274 | case Ist_Dirty: |
| 275 | /* If the call doesn't interact with memory, we ain't |
| 276 | interested. */ |
| 277 | if (st->Ist.Dirty.details->mFx == Ifx_None) |
| 278 | break; |
| 279 | goto unhandled; |
| 280 | |
| 281 | default: |
| 282 | unhandled: |
| 283 | printf("\n"); |
| 284 | ppIRStmt(st); |
| 285 | printf("\n"); |
| 286 | panic("addrcheck: unhandled IRStmt"); |
| 287 | } |
| 288 | |
| 289 | addStmtToIRBB( bb, dopyIRStmt(st)); |
| 290 | } |
| 291 | |
| 292 | return bb; |
| 293 | } |