Interpreter fixes for accessing 'ctx'.

This allow all cbcs in unit_tests/input to pass.
Not yet working on bytecode.cvd though.
0.96
Török Edvin 15 years ago
parent bdd9aeaeeb
commit 74f5816c58
  1. 70
      clambc/bcrun.c
  2. 84
      libclamav/bytecode.c
  3. 62
      libclamav/bytecode_vm.c
  4. 13
      unit_tests/check_bytecode.c

@ -161,7 +161,72 @@ static void print_src(const char *file)
} while (nread > 0);
fclose(f);
}
static uint32_t deadbeefcounts[64] = {
0xdeadbeef,
0,
0xbeefdead,
0,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
0xdeadbeef,
};
int main(int argc, char *argv[])
{
FILE *f;
@ -315,7 +380,8 @@ int main(int argc, char *argv[])
}
funmap(map);
}
/* for testing */
ctx->hooks.match_counts = deadbeefcounts;
rc = cli_bytecode_run(&bcs, bc, ctx);
if (rc != CL_SUCCESS) {
fprintf(stderr,"Unable to run bytecode: %s\n", cl_strerror(rc));

@ -36,9 +36,35 @@
#include "bytecode_api_impl.h"
#include <string.h>
/* TODO: we should make sure lsigcnt is never NULL, and has at least as many
* elements as the bytecode needs */
static const uint32_t nomatch[64];
/* dummy values */
static const uint32_t nomatch[64] = {
0xdeadbeef, 0xdeaddead, 0xbeefdead, 0xdeaddead, 0xdeadbeef, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
static const uint16_t nokind;
static const uint32_t nofilesize;
static const struct cli_pe_hook_data nopedata;
static void context_safe(struct cli_bc_ctx *ctx)
{
/* make sure these are never NULL */
if (!ctx->hooks.kind)
ctx->hooks.kind = &nokind;
if (!ctx->hooks.match_counts)
ctx->hooks.match_counts = nomatch;
if (!ctx->hooks.filesize)
ctx->hooks.filesize = &nofilesize;
if (!ctx->hooks.pedata)
ctx->hooks.pedata = &nopedata;
}
struct cli_bc_ctx *cli_bytecode_context_alloc(void)
{
struct cli_bc_ctx *ctx = cli_calloc(1, sizeof(*ctx));
@ -1146,8 +1172,11 @@ static int parseBB(struct cli_bc *bc, unsigned func, unsigned bb, unsigned char
inst.interp_op += 2;
else if (inst.type <= 32)
inst.interp_op += 3;
else if (inst.type <= 64)
else if (inst.type <= 65)
inst.interp_op += 4;
else {
cli_dbgmsg("unknown inst type: %d\n", inst.type);
}
}
BB->insts[BB->numInsts++] = inst;
}
@ -1359,6 +1388,7 @@ int cli_bytecode_run(const struct cli_all_bc *bcs, const struct cli_bc *bc, stru
cli_errmsg("bytecode has to be prepared either for interpreter or JIT!\n");
return CL_EARG;
}
context_safe(ctx);
if (bc->state == bc_interp) {
memset(&func, 0, sizeof(func));
func.numInsts = 1;
@ -1473,6 +1503,7 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
{
unsigned i, j, k;
uint64_t *gmap;
unsigned bcglobalid = cli_apicall_maxglobal - _FIRST_GLOBAL+2;
bc->numGlobalBytes = 0;
gmap = cli_malloc(bc->num_globals*sizeof(*gmap));
if (!gmap)
@ -1499,10 +1530,47 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc)
ty = &bc->types[bc->globaltys[j]-65];
switch (ty->kind) {
case DPointerType:
*(uint64_t*)&bc->globalBytes[gmap[j]] =
ptr_compose(bc->globals[j][1] - _FIRST_GLOBAL + 1,
bc->globals[j][0]);
break;
{
uint64_t ptr;
if (bc->globals[j][1] >= _FIRST_GLOBAL) {
ptr = ptr_compose(bc->globals[j][1] - _FIRST_GLOBAL + 1,
bc->globals[j][0]);
} else {
if (bc->globals[j][1] > bc->num_globals)
continue;
ptr = ptr_compose(bcglobalid,
gmap[bc->globals[j][1]] + bc->globals[j][0]);
}
*(uint64_t*)&bc->globalBytes[gmap[j]] = ptr;
break;
}
case DArrayType:
{
unsigned elsize, i, off = gmap[j];
/* TODO: support other than ints in arrays */
elsize = typesize(bc, ty->containedTypes[0]);
switch (elsize) {
case 1:
for(i=0;i<ty->numElements;i++)
bc->globalBytes[off+i] = bc->globals[j][i];
break;
case 2:
for(i=0;i<ty->numElements;i++)
*(uint16_t*)&bc->globalBytes[off+i*2] = bc->globals[j][i];
break;
case 4:
for(i=0;i<ty->numElements;i++)
*(uint32_t*)&bc->globalBytes[off+i*4] = bc->globals[j][i];
break;
case 8:
for(i=0;i<ty->numElements;i++)
*(uint64_t*)&bc->globalBytes[off+i*8] = bc->globals[j][i];
break;
default:
cli_dbgmsg("interpreter: unsupported elsize: %u\n", elsize);
}
break;
}
default:
/*TODO*/
if (!bc->globals[j][1])

@ -491,8 +491,12 @@ static inline int64_t ptr_register_glob_fixedid(struct ptr_infos *infos,
infos->nglobs = n;
}
sinfos = &infos->glob_infos[n-1];
if (!values)
size = 0;
sinfos->base = values;
sinfos->size = size;
cli_dbgmsg("bytecode: registered ctx variable at %p (+%u) id %u\n", values,
size, n);
return ptr_compose(n, 0);
}
@ -584,18 +588,39 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
char *values = ctx->values;
char *old_values;
struct ptr_infos ptrinfos;
struct timeval tv0, tv1, timeout;
memset(&ptrinfos, 0, sizeof(ptrinfos));
memset(&stack, 0, sizeof(stack));
for (i=0;i < cli_apicall_maxglobal - _FIRST_GLOBAL; i++) {
const struct cli_apiglobal *g = &cli_globals[i];
void *apiglobal = (void*)(((char*)&ctx->hooks) + g->offset);
void **apiglobal = (void**)(((char*)ctx) + g->offset);
if (!apiglobal)
continue;
void *apiptr = *apiglobal;
uint32_t size = globaltypesize(g->type);
ptr_register_glob_fixedid(&ptrinfos, apiglobal, size, g->globalid - _FIRST_GLOBAL+1);
ptr_register_glob_fixedid(&ptrinfos, apiptr, size, g->globalid - _FIRST_GLOBAL+1);
}
ptr_register_glob_fixedid(&ptrinfos, bc->globalBytes, bc->numGlobalBytes,
cli_apicall_maxglobal - _FIRST_GLOBAL + 2);
gettimeofday(&tv0, NULL);
timeout.tv_usec = tv0.tv_usec + ctx->bytecode_timeout*1000;
timeout.tv_sec = tv0.tv_sec + timeout.tv_usec/1000000;
timeout.tv_usec %= 1000000;
do {
pc++;
if (!(pc % 5000)) {
gettimeofday(&tv1, NULL);
if (tv1.tv_sec > timeout.tv_sec ||
(tv1.tv_sec == timeout.tv_sec &&
tv1.tv_usec > timeout.tv_usec)) {
cli_errmsg("Bytecode run timed out in interpreter\n");
stop = CL_ETIMEOUT;
break;
}
}
switch (inst->interp_op) {
DEFINE_BINOP(OP_BC_ADD, res = op0 + op1);
DEFINE_BINOP(OP_BC_SUB, res = op0 - op1);
@ -730,14 +755,13 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
break;
}
case 1: {
cli_errmsg("bytecode: type 1 apicalls not yet implemented!\n");
stop = CL_EBYTECODE;
/* void *p;
uint32_t u;
p = ...;
u = READ32(v, inst->u.ops.ops[1]);
res = cli_apicalls1[api->idx](p, u);
break;*/
void* arg1;
unsigned arg2;
/* check that arg2 is size of arg1 */
READ32(arg2, inst->u.ops.ops[1]);
READP(arg1, inst->u.ops.ops[0], arg2);
res = cli_apicalls1[api->idx](ctx, arg1, arg2);
break;
}
case 2: {
int32_t a;
@ -745,16 +769,9 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
res = cli_apicalls2[api->idx](ctx, a);
break;
}
case 3: {
cli_errmsg("bytecode: type 3 apicalls not yet implemented!\n");
default:
cli_errmsg("bytecode: type %u apicalls not yet implemented!\n", api->kind);
stop = CL_EBYTECODE;
/* void *p;
uint32_t u;
p = ...;
u = READ32(v, inst->u.ops.ops[1]);
res = cli_apicalls1[api->idx](p, u);
break;*/
}
}
WRITE32(inst->dest, res);
break;
@ -951,6 +968,13 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct
CHECK_GT(bb->numInsts, bb_inst);
}
} while (stop == CL_SUCCESS);
if (cli_debug_flag) {
gettimeofday(&tv1, NULL);
tv1.tv_sec -= tv0.tv_sec;
tv1.tv_usec -= tv0.tv_usec;
cli_dbgmsg("intepreter bytecode run finished in %dus\n",
tv1.tv_sec*1000000 + tv1.tv_usec);
}
cli_stack_destroy(&stack);
return stop == CL_BREAK ? CL_SUCCESS : stop;

@ -120,9 +120,8 @@ END_TEST
START_TEST (test_apicalls2)
{
cl_init(CL_INIT_DEFAULT);
if (have_clamjit)/*FIXME: should work with both */
runtest("input/apicalls2.cbc", 0xf00d, CL_SUCCESS, 0);
/* runtest("input/apicalls2.cbc", 0xf00d, CL_SUCCESS, 1); */
runtest("input/apicalls2.cbc", 0xf00d, CL_SUCCESS, 1);
}
END_TEST
@ -138,20 +137,16 @@ END_TEST
START_TEST (test_lsig)
{
cl_init(CL_INIT_DEFAULT);
#if 0
FIXME: match_counts should be initialized in clambc mode
if (have_clamjit)/* FIXME: should work with both */
runtest("input/lsig.cbc", 0, 0, 0);
//runtest("input/lsig.cbc", 0, CL_EBYTECODE, 1);
#endif
runtest("input/lsig.cbc", 0, 0, 1);
}
END_TEST
START_TEST (test_inf)
{
cl_init(CL_INIT_DEFAULT);
if (have_clamjit)
runtest("input/inf.cbc", 0, CL_ETIMEOUT, 0);
runtest("input/inf.cbc", 0, CL_ETIMEOUT, 0);
runtest("input/inf.cbc", 0, CL_ETIMEOUT, 1);
}
END_TEST

Loading…
Cancel
Save