... | ... |
@@ -295,7 +295,7 @@ int main(int argc, char *argv[]) |
295 | 295 |
if (optget(opts, "force-interpreter")->enabled) { |
296 | 296 |
bcs.engine = NULL; |
297 | 297 |
} else { |
298 |
- rc = cli_bytecode_init(&bcs, BYTECODE_ENGINE_MASK); |
|
298 |
+ rc = cli_bytecode_init(&bcs); |
|
299 | 299 |
if (rc != CL_SUCCESS) { |
300 | 300 |
fprintf(stderr,"Unable to init bytecode engine: %s\n", cl_strerror(rc)); |
301 | 301 |
optfree(opts); |
... | ... |
@@ -339,7 +339,7 @@ int main(int argc, char *argv[]) |
339 | 339 |
optfree(opts); |
340 | 340 |
exit(4); |
341 | 341 |
} |
342 |
- rc = cli_bytecode_prepare(&bcs, BYTECODE_ENGINE_MASK); |
|
342 |
+ rc = cli_bytecode_prepare(engine, &bcs, BYTECODE_ENGINE_MASK); |
|
343 | 343 |
if (rc != CL_SUCCESS) { |
344 | 344 |
fprintf(stderr,"Unable to prepare bytecode: %s\n", cl_strerror(rc)); |
345 | 345 |
optfree(opts); |
... | ... |
@@ -1768,7 +1768,7 @@ static int updatedb(const char *dbname, const char *hostname, char *ip, int *sig |
1768 | 1768 |
cl_engine_free(engine); |
1769 | 1769 |
return 55; |
1770 | 1770 |
} |
1771 |
- if((ret = cli_bytecode_prepare(&engine->bcs, engine->dconf->bytecode/*FIXME: dconf has no sense here*/))) { |
|
1771 |
+ if((ret = cli_bytecode_prepare(engine, &engine->bcs, engine->dconf->bytecode/*FIXME: dconf has no sense here*/))) { |
|
1772 | 1772 |
logg("!Failed to compile/load bytecode: %s\n", cl_strerror(ret)); |
1773 | 1773 |
unlink(newfile); |
1774 | 1774 |
free(newfile); |
... | ... |
@@ -2090,7 +2090,7 @@ static int selfcheck(int jit, struct cli_bcengine *engine) |
2090 | 2090 |
return rc; |
2091 | 2091 |
} |
2092 | 2092 |
|
2093 |
-int cli_bytecode_prepare(struct cli_all_bc *bcs, unsigned dconfmask) |
|
2093 |
+int cli_bytecode_prepare(struct cl_engine *engine, struct cli_all_bc *bcs, unsigned dconfmask) |
|
2094 | 2094 |
{ |
2095 | 2095 |
unsigned i, interp = 0; |
2096 | 2096 |
int rc1, rc2, rc; |
... | ... |
@@ -2125,10 +2125,15 @@ int cli_bytecode_prepare(struct cli_all_bc *bcs, unsigned dconfmask) |
2125 | 2125 |
return CL_SUCCESS; |
2126 | 2126 |
} |
2127 | 2127 |
|
2128 |
-int cli_bytecode_init(struct cli_all_bc *allbc, unsigned dconfmask) |
|
2128 |
+int cli_bytecode_init(struct cli_all_bc *allbc) |
|
2129 | 2129 |
{ |
2130 |
+ int ret; |
|
2130 | 2131 |
memset(allbc, 0, sizeof(*allbc)); |
2131 |
- return cli_bytecode_init_jit(allbc, dconfmask); |
|
2132 |
+ ret = cli_bytecode_init_jit(allbc, 0/*XXX*/); |
|
2133 |
+ cli_dbgmsg("Bytecode initialized in %s mode\n", |
|
2134 |
+ allbc->engine ? "JIT" : "interpreter"); |
|
2135 |
+ allbc->inited = 1; |
|
2136 |
+ return ret; |
|
2132 | 2137 |
} |
2133 | 2138 |
|
2134 | 2139 |
int cli_bytecode_done(struct cli_all_bc *allbc) |
... | ... |
@@ -25,6 +25,7 @@ |
25 | 25 |
#include "clambc.h" |
26 | 26 |
#include <stdio.h> |
27 | 27 |
#include "fmap.h" |
28 |
+#include "bytecode_detect.h" |
|
28 | 29 |
|
29 | 30 |
struct cli_dbio; |
30 | 31 |
struct cli_bc_ctx; |
... | ... |
@@ -41,7 +42,8 @@ enum bc_state { |
41 | 41 |
bc_skip, |
42 | 42 |
bc_loaded, |
43 | 43 |
bc_jit, |
44 |
- bc_interp |
|
44 |
+ bc_interp, |
|
45 |
+ bc_disabled |
|
45 | 46 |
}; |
46 | 47 |
|
47 | 48 |
struct cli_bc { |
... | ... |
@@ -74,6 +76,8 @@ struct cli_all_bc { |
74 | 74 |
struct cli_bc *all_bcs; |
75 | 75 |
unsigned count; |
76 | 76 |
struct cli_bcengine *engine; |
77 |
+ struct cli_environment env; |
|
78 |
+ int inited; |
|
77 | 79 |
}; |
78 | 80 |
|
79 | 81 |
struct cli_pe_hook_data; |
... | ... |
@@ -100,9 +104,9 @@ extern int have_clamjit; |
100 | 100 |
#ifdef __cplusplus |
101 | 101 |
} |
102 | 102 |
#endif |
103 |
-int cli_bytecode_init(struct cli_all_bc *allbc, unsigned dconfmask); |
|
103 |
+int cli_bytecode_init(struct cli_all_bc *allbc); |
|
104 | 104 |
int cli_bytecode_load(struct cli_bc *bc, FILE *f, struct cli_dbio *dbio, int security); |
105 |
-int cli_bytecode_prepare(struct cli_all_bc *allbc, unsigned dconfmask); |
|
105 |
+int cli_bytecode_prepare(struct cl_engine *engine, struct cli_all_bc *allbc, unsigned dconfmask); |
|
106 | 106 |
int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, struct cli_bc_ctx *ctx); |
107 | 107 |
void cli_bytecode_destroy(struct cli_bc *bc); |
108 | 108 |
int cli_bytecode_done(struct cli_all_bc *allbc); |
... | ... |
@@ -66,8 +66,8 @@ typedef enum { |
66 | 66 |
CL_EMAXSIZE, |
67 | 67 |
CL_EMAXFILES, |
68 | 68 |
CL_EFORMAT, |
69 |
- CL_EBYTECODE, |
|
70 |
- |
|
69 |
+ CL_EBYTECODE,/* may be reported in testmode */ |
|
70 |
+ CL_EBYTECODE_TESTFAIL, /* may be reported in testmode */ |
|
71 | 71 |
|
72 | 72 |
/* no error codes below this line please */ |
73 | 73 |
CL_ELAST_ERROR |
... | ... |
@@ -147,8 +147,9 @@ enum cl_engine_field { |
147 | 147 |
CL_ENGINE_AC_MAXDEPTH, /* uint32_t */ |
148 | 148 |
CL_ENGINE_TMPDIR, /* (char *) */ |
149 | 149 |
CL_ENGINE_KEEPTMP, /* uint32_t */ |
150 |
- CL_ENGINE_BYTECODE_SECURITY, /* uint32_t */ |
|
151 |
- CL_ENGINE_BYTECODE_TIMEOUT /* uint32_t */ |
|
150 |
+ CL_ENGINE_BYTECODE_SECURITY, /* uint32_t */ |
|
151 |
+ CL_ENGINE_BYTECODE_TIMEOUT, /* uint32_t */ |
|
152 |
+ CL_ENGINE_BYTECODE_MODE /* uint32_t */ |
|
152 | 153 |
}; |
153 | 154 |
|
154 | 155 |
enum bytecode_security { |
... | ... |
@@ -157,6 +158,15 @@ enum bytecode_security { |
157 | 157 |
CL_BYTECODE_TRUST_NOTHING /* paranoid setting */ |
158 | 158 |
}; |
159 | 159 |
|
160 |
+enum bytecode_mode { |
|
161 |
+ CL_BYTECODE_MODE_AUTO=0, /* JIT if possible, fallback to interpreter */ |
|
162 |
+ CL_BYTECODE_MODE_JIT, /* force JIT */ |
|
163 |
+ CL_BYTECODE_MODE_INTERPRETER, /* force interpreter */ |
|
164 |
+ CL_BYTECODE_MODE_TEST, /* both JIT and interpreter, compare results, |
|
165 |
+ all failures are fatal */ |
|
166 |
+ CL_BYTECODE_MODE_OFF /* for query only, not settable */ |
|
167 |
+}; |
|
168 |
+ |
|
160 | 169 |
extern int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long long num); |
161 | 170 |
|
162 | 171 |
extern long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field field, int *err); |
... | ... |
@@ -248,6 +248,8 @@ const char *cl_strerror(int clerror) |
248 | 248 |
return "CL_EFORMAT: Bad format or broken data"; |
249 | 249 |
case CL_EBYTECODE: |
250 | 250 |
return "CL_EBYTECODE: error during bytecode execution"; |
251 |
+ case CL_EBYTECODE_TESTFAIL: |
|
252 |
+ return "CL_EBYTECODE_TESTFAIL: failure in bytecode testmode"; |
|
251 | 253 |
default: |
252 | 254 |
return "Unknown error code"; |
253 | 255 |
} |
... | ... |
@@ -301,6 +303,7 @@ struct cl_engine *cl_engine_new(void) |
301 | 301 |
new->bytecode_security = CL_BYTECODE_TRUST_SIGNED; |
302 | 302 |
/* 5 seconds timeout */ |
303 | 303 |
new->bytecode_timeout = 60000; |
304 |
+ new->bytecode_mode = CL_BYTECODE_MODE_AUTO; |
|
304 | 305 |
new->refcount = 1; |
305 | 306 |
new->ac_only = 0; |
306 | 307 |
new->ac_mindepth = CLI_DEFAULT_AC_MINDEPTH; |
... | ... |
@@ -394,11 +397,25 @@ int cl_engine_set_num(struct cl_engine *engine, enum cl_engine_field field, long |
394 | 394 |
return CL_EARG; |
395 | 395 |
} |
396 | 396 |
#endif |
397 |
+ if (engine->dboptions & CL_DB_COMPILED) { |
|
398 |
+ cli_errmsg("cl_engine_set_num: CL_ENGINE_BYTECODE_SECURITY cannot be set after engine was compiled\n"); |
|
399 |
+ return CL_EARG; |
|
400 |
+ } |
|
397 | 401 |
engine->bytecode_security = num; |
398 | 402 |
break; |
399 | 403 |
case CL_ENGINE_BYTECODE_TIMEOUT: |
400 | 404 |
engine->bytecode_timeout = num; |
401 | 405 |
break; |
406 |
+ case CL_ENGINE_BYTECODE_MODE: |
|
407 |
+ if (engine->dboptions & CL_DB_COMPILED) { |
|
408 |
+ cli_errmsg("cl_engine_set_num: CL_ENGINE_BYTECODE_MODE cannot be set after engine was compiled\n"); |
|
409 |
+ return CL_EARG; |
|
410 |
+ } |
|
411 |
+ if (num == CL_BYTECODE_MODE_OFF) { |
|
412 |
+ cli_errmsg("cl_engine_set_num: CL_BYTECODE_MODE_OFF is not settable, use dboptions to turn off!\n"); |
|
413 |
+ } |
|
414 |
+ engine->bytecode_mode = num; |
|
415 |
+ break; |
|
402 | 416 |
default: |
403 | 417 |
cli_errmsg("cl_engine_set_num: Incorrect field number\n"); |
404 | 418 |
return CL_EARG; |
... | ... |
@@ -446,6 +463,12 @@ long long cl_engine_get_num(const struct cl_engine *engine, enum cl_engine_field |
446 | 446 |
return engine->ac_maxdepth; |
447 | 447 |
case CL_ENGINE_KEEPTMP: |
448 | 448 |
return engine->keeptmp; |
449 |
+ case CL_ENGINE_BYTECODE_SECURITY: |
|
450 |
+ return engine->bytecode_security; |
|
451 |
+ case CL_ENGINE_BYTECODE_TIMEOUT: |
|
452 |
+ return engine->bytecode_timeout; |
|
453 |
+ case CL_ENGINE_BYTECODE_MODE: |
|
454 |
+ return engine->bytecode_mode; |
|
449 | 455 |
default: |
450 | 456 |
cli_errmsg("cl_engine_get: Incorrect field number\n"); |
451 | 457 |
if(err) |
... | ... |
@@ -2636,8 +2636,8 @@ int cl_load(const char *path, struct cl_engine *engine, unsigned int *signo, uns |
2636 | 2636 |
if((ret = phishing_init(engine))) |
2637 | 2637 |
return ret; |
2638 | 2638 |
|
2639 |
- if((dboptions & CL_DB_BYTECODE) && !engine->bcs.engine && (engine->dconf->bytecode & BYTECODE_ENGINE_MASK)) { |
|
2640 |
- if((ret = cli_bytecode_init(&engine->bcs, engine->dconf->bytecode))) |
|
2639 |
+ if((dboptions & CL_DB_BYTECODE) && !engine->bcs.inited) { |
|
2640 |
+ if((ret = cli_bytecode_init(&engine->bcs))) |
|
2641 | 2641 |
return ret; |
2642 | 2642 |
} else { |
2643 | 2643 |
cli_dbgmsg("Bytecode engine disabled\n"); |
... | ... |
@@ -3078,7 +3078,7 @@ int cl_engine_compile(struct cl_engine *engine) |
3078 | 3078 |
mpool_flush(engine->mempool); |
3079 | 3079 |
|
3080 | 3080 |
/* Compile bytecode */ |
3081 |
- if((ret = cli_bytecode_prepare(&engine->bcs, engine->dconf->bytecode))) { |
|
3081 |
+ if((ret = cli_bytecode_prepare(engine, &engine->bcs, engine->dconf->bytecode))) { |
|
3082 | 3082 |
cli_errmsg("Unable to compile/load bytecode: %s\n", cl_strerror(ret)); |
3083 | 3083 |
return ret; |
3084 | 3084 |
} |
... | ... |
@@ -70,7 +70,7 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit, |
70 | 70 |
cl_debug(); |
71 | 71 |
|
72 | 72 |
if (!nojit) { |
73 |
- rc = cli_bytecode_init(&bcs, BYTECODE_ENGINE_MASK); |
|
73 |
+ rc = cli_bytecode_init(&bcs); |
|
74 | 74 |
fail_unless(rc == CL_SUCCESS, "cli_bytecode_init failed"); |
75 | 75 |
} else { |
76 | 76 |
bcs.engine = NULL; |
... | ... |
@@ -83,7 +83,10 @@ static void runtest(const char *file, uint64_t expected, int fail, int nojit, |
83 | 83 |
fail_unless(rc == CL_SUCCESS, "cli_bytecode_load failed"); |
84 | 84 |
fclose(f); |
85 | 85 |
|
86 |
- rc = cli_bytecode_prepare(&bcs, BYTECODE_ENGINE_MASK); |
|
86 |
+ if (testmode) |
|
87 |
+ engine->bytecode_mode = CL_BYTECODE_MODE_TEST; |
|
88 |
+ |
|
89 |
+ rc = cli_bytecode_prepare(engine, &bcs, BYTECODE_ENGINE_MASK); |
|
87 | 90 |
fail_unless(rc == CL_SUCCESS, "cli_bytecode_prepare failed"); |
88 | 91 |
|
89 | 92 |
if (have_clamjit && !nojit && nojit != -1) { |