~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/bytecode_vm.c

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  Execute ClamAV bytecode.
3
 
 *
4
 
 *  Copyright (C) 2009-2010 Sourcefire, Inc.
5
 
 *
6
 
 *  Authors: Tƶrƶk Edvin
7
 
 *
8
 
 *  This program is free software; you can redistribute it and/or modify
9
 
 *  it under the terms of the GNU General Public License version 2 as
10
 
 *  published by the Free Software Foundation.
11
 
 *
12
 
 *  This program is distributed in the hope that it will be useful,
13
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 *  GNU General Public License for more details.
16
 
 *
17
 
 *  You should have received a copy of the GNU General Public License
18
 
 *  along with this program; if not, write to the Free Software
19
 
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20
 
 *  MA 02110-1301, USA.
21
 
 */
22
 
#if HAVE_CONFIG_H
23
 
#include "clamav-config.h"
24
 
#endif
25
 
#include "clamav.h"
26
 
#include "others.h"
27
 
#include "bytecode.h"
28
 
#include "bytecode_priv.h"
29
 
#include "type_desc.h"
30
 
#include "readdb.h"
31
 
#include <string.h>
32
 
#ifndef _WIN32
33
 
#include <sys/time.h>
34
 
#endif
35
 
#include "bytecode_api_impl.h"
36
 
#include "disasm-common.h"
37
 
 
38
 
/* Enable this to catch more bugs in the RC phase */
39
 
#define CL_BYTECODE_SAFE
40
 
 
41
 
#ifdef CL_BYTECODE_SAFE
42
 
/* These checks will also be done by the bytecode verifier, but for
43
 
 * debugging purposes we have explicit checks, these should never fail! */
44
 
#ifdef CL_DEBUG
45
 
static int never_inline bcfail(const char *msg, long a, long b,
46
 
                  const char *file, unsigned line)
47
 
{
48
 
    cli_warnmsg("bytecode: check failed %s (%lx and %lx) at %s:%u\n", msg, a, b, file, line);
49
 
    return CL_EARG;
50
 
}
51
 
#else
52
 
#define bcfail(msg,a,b,f,l) CL_EBYTECODE
53
 
#endif
54
 
 
55
 
#define CHECK_FUNCID(funcid) do { if (funcid >= bc->num_func) return \
56
 
    bcfail("funcid out of bounds!",funcid, bc->num_func,__FILE__,__LINE__); } while(0)
57
 
#define CHECK_APIID(funcid) do { if (funcid >= cli_apicall_maxapi) return \
58
 
    bcfail("APIid out of bounds!",funcid, cli_apicall_maxapi,__FILE__,__LINE__); } while(0)
59
 
#define CHECK_EQ(a, b) do { if ((a) != (b)) return \
60
 
    bcfail("Values "#a" and "#b" don't match!",(a),(b),__FILE__,__LINE__); } while(0)
61
 
#define CHECK_GT(a, b) do {if ((a) <= (b)) return \
62
 
    bcfail("Condition failed "#a" > "#b,(a),(b), __FILE__, __LINE__); } while(0)
63
 
 
64
 
#else
65
 
static inline int bcfail(const char *msg, long a, long b,
66
 
                         const char *file, unsigned line) {}
67
 
#define CHECK_FUNCID(x);
68
 
#define CHECK_APIID(x);
69
 
#define CHECK_EQ(a,b)
70
 
#define CHECK_GT(a,b)
71
 
#endif
72
 
#ifdef CL_DEBUG
73
 
#define CHECK_UNREACHABLE do { cli_dbgmsg("bytecode: unreachable executed!\n"); return CL_EBYTECODE; } while(0)
74
 
#define TRACE_PTR(ptr, s) cli_dbgmsg("bytecode trace: ptr %llx, +%x\n", ptr, s);
75
 
#define TRACE_R(x) cli_dbgmsg("bytecode trace: %u, read %llx\n", pc, (long long)x);
76
 
#define TRACE_W(x, w, p) cli_dbgmsg("bytecode trace: %u, write%d @%u %llx\n", pc, p, w, (long long)(x));
77
 
#define TRACE_EXEC(id, dest, ty, stack) cli_dbgmsg("bytecode trace: executing %d, -> %u (%u); %u\n", id, dest, ty, stack)
78
 
#define TRACE_API(s, dest, ty, stack) cli_dbgmsg("bytecode trace: executing %s, -> %u (%u); %u\n", s, dest, ty, stack)
79
 
#else
80
 
#define CHECK_UNREACHABLE return CL_EBYTECODE
81
 
#define TRACE_PTR(ptr, s)
82
 
#define TRACE_R(x)
83
 
#define TRACE_W(x, w, p)
84
 
#define TRACE_EXEC(id, dest, ty, stack)
85
 
#define TRACE_API(s, dest, ty, stack)
86
 
#endif
87
 
 
88
 
#define SIGNEXT(a, from) CLI_SRS(((int64_t)(a)) << (64-(from)), (64-(from)))
89
 
 
90
 
#ifdef CL_DEBUG
91
 
#undef always_inline
92
 
#define always_inline
93
 
#endif
94
 
 
95
 
static always_inline int jump(const struct cli_bc_func *func, uint16_t bbid, struct cli_bc_bb **bb, const struct cli_bc_inst **inst,
96
 
                unsigned *bb_inst)
97
 
{
98
 
    CHECK_GT(func->numBB, bbid);
99
 
    *bb = &func->BB[bbid];
100
 
    *inst = (*bb)->insts;
101
 
    *bb_inst = 0;
102
 
    return 0;
103
 
}
104
 
 
105
 
#define STACK_CHUNKSIZE 65536
106
 
 
107
 
struct stack_chunk {
108
 
    struct stack_chunk *prev;
109
 
    unsigned used;
110
 
    union {
111
 
        void *align;
112
 
        char data[STACK_CHUNKSIZE];
113
 
    } u;
114
 
};
115
 
 
116
 
struct stack {
117
 
    struct stack_chunk* chunk;
118
 
    uint16_t last_size;
119
 
};
120
 
 
121
 
/* type with largest alignment that we use (in general it is a long double, but
122
 
 * thats too big alignment for us) */
123
 
typedef uint64_t align_t;
124
 
 
125
 
static always_inline void* cli_stack_alloc(struct stack *stack, unsigned bytes)
126
 
{
127
 
    struct stack_chunk *chunk = stack->chunk;
128
 
    uint16_t last_size_off;
129
 
 
130
 
    /* last_size is stored after data */
131
 
    /* align bytes to pointer size */
132
 
    bytes = (bytes + sizeof(uint16_t) + sizeof(align_t)) & ~(sizeof(align_t)-1);
133
 
    last_size_off = bytes - 2;
134
 
 
135
 
    if (chunk && (chunk->used + bytes <= STACK_CHUNKSIZE)) {
136
 
        /* there is still room in this chunk */
137
 
        void *ret;
138
 
 
139
 
        *(uint16_t*)&chunk->u.data[chunk->used + last_size_off] = stack->last_size;
140
 
        stack->last_size = bytes/sizeof(align_t);
141
 
 
142
 
        ret = chunk->u.data + chunk->used;
143
 
        chunk->used += bytes;
144
 
        return ret;
145
 
    }
146
 
 
147
 
    if(bytes >= STACK_CHUNKSIZE) {
148
 
        cli_warnmsg("cli_stack_alloc: Attempt to allocate more than STACK_CHUNKSIZE bytes: %u!\n", bytes);
149
 
        return NULL;
150
 
    }
151
 
    /* not enough room here, allocate new chunk */
152
 
    chunk = cli_malloc(sizeof(*stack->chunk));
153
 
    if (!chunk)
154
 
        return NULL;
155
 
 
156
 
    *(uint16_t*)&chunk->u.data[last_size_off] = stack->last_size;
157
 
    stack->last_size = bytes/sizeof(align_t);
158
 
 
159
 
    chunk->used = bytes;
160
 
    chunk->prev = stack->chunk;
161
 
    stack->chunk = chunk;
162
 
    return chunk->u.data;
163
 
}
164
 
 
165
 
static always_inline void cli_stack_free(struct stack *stack, void *data)
166
 
{
167
 
    uint16_t last_size;
168
 
    struct stack_chunk *chunk = stack->chunk;
169
 
    if (!chunk) {
170
 
        cli_warnmsg("cli_stack_free: stack empty!\n");
171
 
        return;
172
 
    }
173
 
    if ((chunk->u.data + chunk->used) != ((char*)data + stack->last_size*sizeof(align_t))) {
174
 
        cli_warnmsg("cli_stack_free: wrong free order: %p, expected %p\n",
175
 
                   data, chunk->u.data + chunk->used - stack->last_size*sizeof(align_t));
176
 
        return;
177
 
    }
178
 
    last_size = *(uint16_t*)&chunk->u.data[chunk->used-2];
179
 
    if (chunk->used < stack->last_size*sizeof(align_t)) {
180
 
        cli_warnmsg("cli_stack_free: last_size is corrupt!\n");
181
 
        return;
182
 
    }
183
 
    chunk->used -= stack->last_size*sizeof(align_t);
184
 
    stack->last_size = last_size;
185
 
    if (!chunk->used) {
186
 
        stack->chunk = chunk->prev;
187
 
        free(chunk);
188
 
    }
189
 
}
190
 
 
191
 
static void cli_stack_destroy(struct stack *stack)
192
 
{
193
 
    struct stack_chunk *chunk = stack->chunk;
194
 
    while (chunk) {
195
 
        stack->chunk = chunk->prev;
196
 
        free(chunk);
197
 
        chunk = stack->chunk;
198
 
    }
199
 
}
200
 
 
201
 
struct stack_entry {
202
 
    struct stack_entry *prev;
203
 
    const struct cli_bc_func *func;
204
 
    operand_t ret;
205
 
    unsigned bb_inst;
206
 
    struct cli_bc_bb *bb;
207
 
    char *values;
208
 
};
209
 
 
210
 
static always_inline struct stack_entry *allocate_stack(struct stack *stack,
211
 
                                                        struct stack_entry *prev,
212
 
                                                        const struct cli_bc_func *func,
213
 
                                                        const struct cli_bc_func *func_old,
214
 
                                                        operand_t ret,
215
 
                                                        struct cli_bc_bb *bb,
216
 
                                                        unsigned bb_inst)
217
 
{
218
 
    char *values;
219
 
    struct stack_entry *entry = cli_stack_alloc(stack, sizeof(*entry) + sizeof(*values)*func->numBytes);
220
 
    if (!entry)
221
 
        return NULL;
222
 
    entry->prev = prev;
223
 
    entry->func = func_old;
224
 
    entry->ret = ret;
225
 
    entry->bb = bb;
226
 
    entry->bb_inst = bb_inst;
227
 
    /* we allocated room for values right after stack_entry! */
228
 
    entry->values = values = (char*)&entry[1];
229
 
    memcpy(&values[func->numBytes - func->numConstants*8], func->constants,
230
 
           sizeof(*values)*func->numConstants*8);
231
 
    return entry;
232
 
}
233
 
 
234
 
static always_inline struct stack_entry *pop_stack(struct stack *stack,
235
 
                                                   struct stack_entry *stack_entry,
236
 
                                                   const struct cli_bc_func **func,
237
 
                                                   operand_t *ret,
238
 
                                                   struct cli_bc_bb **bb,
239
 
                                                   unsigned *bb_inst)
240
 
{
241
 
    void *data;
242
 
    *func = stack_entry->func;
243
 
    *ret = stack_entry->ret;
244
 
    *bb = stack_entry->bb;
245
 
    *bb_inst = stack_entry->bb_inst;
246
 
    data = stack_entry;
247
 
    stack_entry = stack_entry->prev;
248
 
    cli_stack_free(stack, data);
249
 
    return stack_entry;
250
 
}
251
 
 
252
 
 
253
 
/*
254
 
 *
255
 
 * p, p+1, p+2, p+3 <- gt
256
 
    CHECK_EQ((p)&1, 0); 
257
 
    CHECK_EQ((p)&3, 0); 
258
 
    CHECK_EQ((p)&7, 0); 
259
 
*/
260
 
#define WRITE8(p, x) CHECK_GT(func->numBytes, p);\
261
 
    TRACE_W(x, p, 8);\
262
 
    *(uint8_t*)&values[p] = x
263
 
#define WRITE16(p, x) CHECK_GT(func->numBytes, p+1);\
264
 
    CHECK_EQ((p)&1, 0);\
265
 
    TRACE_W(x, p, 16);\
266
 
    *(uint16_t*)&values[p] = x
267
 
#define WRITE32(p, x) CHECK_GT(func->numBytes, p+3);\
268
 
    CHECK_EQ((p)&3, 0);\
269
 
    TRACE_W(x, p, 32);\
270
 
    *(uint32_t*)&values[p] = x
271
 
#define WRITE64(p, x) CHECK_GT(func->numBytes, p+7);\
272
 
    CHECK_EQ((p)&7, 0);\
273
 
    TRACE_W(x, p, 64);\
274
 
    *(uint64_t*)&values[p] = x
275
 
#define WRITEP(x, p) CHECK_GT(func->numBytes, p+PSIZE-1);\
276
 
    CHECK_EQ((p)&(PSIZE-1), 0);\
277
 
    TRACE_W(x, p, PSIZE*8);\
278
 
    *(void**)&values[p] = x
279
 
 
280
 
#define uint_type(n) uint##n##_t
281
 
#define READNfrom(maxBytes, from, x, n, p)\
282
 
    CHECK_GT((maxBytes), (p)+(n/8)-1);\
283
 
    CHECK_EQ((p)&(n/8-1), 0);\
284
 
    x = *(uint_type(n)*)&(from)[(p)];\
285
 
    TRACE_R(x)
286
 
 
287
 
#define READN(x, n, p)\
288
 
 do {\
289
 
     if (p&0x80000000) {\
290
 
         uint32_t pg = p&0x7fffffff;\
291
 
         if (!pg) {\
292
 
         x = 0;\
293
 
         } else {\
294
 
         READNfrom(bc->numGlobalBytes, bc->globalBytes, x, n, pg);\
295
 
         }\
296
 
     } else {\
297
 
         READNfrom(func->numBytes, values, x, n, p);\
298
 
     }\
299
 
 } while (0)
300
 
 
301
 
#define READ1(x, p) READN(x, 8, p);\
302
 
    x = x&1
303
 
#define READ8(x, p) READN(x, 8, p)
304
 
#define READ16(x, p) READN(x, 16, p)
305
 
#define READ32(x, p) READN(x, 32, p)
306
 
#define READ64(x, p) READN(x, 64, p)
307
 
 
308
 
#define PSIZE sizeof(int64_t)
309
 
#define READP(x, p, asize) { int64_t iptr__;\
310
 
    READN(iptr__, 64, p);\
311
 
    x = ptr_torealptr(&ptrinfos, iptr__, (asize));\
312
 
    if (!x) {\
313
 
        stop = CL_EBYTECODE;\
314
 
        break;\
315
 
    }\
316
 
    TRACE_R(x)\
317
 
}
318
 
#define READPOP(x, p, asize) {\
319
 
    if ((p)&0x40000000) {\
320
 
        unsigned ptr__ = (p)&0xbfffffff;\
321
 
        CHECK_GT(func->numBytes, ptr__);\
322
 
        TRACE_PTR(ptr__, asize);\
323
 
        x = (void*)&values[ptr__];\
324
 
    } else {\
325
 
        READP(x, p, asize)\
326
 
    }\
327
 
}
328
 
 
329
 
#define READOLD8(x, p) CHECK_GT(func->numBytes, p);\
330
 
    x = *(uint8_t*)&old_values[p];\
331
 
    TRACE_R(x)
332
 
#define READOLD16(x, p) CHECK_GT(func->numBytes, p+1);\
333
 
    CHECK_EQ((p)&1, 0);\
334
 
    x = *(uint16_t*)&old_values[p];\
335
 
    TRACE_R(x)
336
 
#define READOLD32(x, p) CHECK_GT(func->numBytes, p+3);\
337
 
    CHECK_EQ((p)&3, 0);\
338
 
    x = *(uint32_t*)&old_values[p];\
339
 
    TRACE_R(x)
340
 
#define READOLD64(x, p) CHECK_GT(func->numBytes, p+7);\
341
 
    CHECK_EQ((p)&7, 0);\
342
 
    x = *(uint64_t*)&old_values[p];\
343
 
    TRACE_R(x)
344
 
 
345
 
#define BINOP(i) inst->u.binop[i]
346
 
 
347
 
#define DEFINE_BINOP_BC_HELPER(opc, OP, W0, W1, W2, W3, W4) \
348
 
    case opc*5: {\
349
 
                    uint8_t op0, op1, res;\
350
 
                    int8_t sop0, sop1;\
351
 
                    READ1(op0, BINOP(0));\
352
 
                    READ1(op1, BINOP(1));\
353
 
                    sop0 = op0; sop1 = op1;\
354
 
                    OP;\
355
 
                    W0(inst->dest, res);\
356
 
                    break;\
357
 
                }\
358
 
    case opc*5+1: {\
359
 
                    uint8_t op0, op1, res;\
360
 
                    int8_t sop0, sop1;\
361
 
                    READ8(op0, BINOP(0));\
362
 
                    READ8(op1, BINOP(1));\
363
 
                    sop0 = op0; sop1 = op1;\
364
 
                    OP;\
365
 
                    W1(inst->dest, res);\
366
 
                    break;\
367
 
                }\
368
 
    case opc*5+2: {\
369
 
                    uint16_t op0, op1, res;\
370
 
                    int16_t sop0, sop1;\
371
 
                    READ16(op0, BINOP(0));\
372
 
                    READ16(op1, BINOP(1));\
373
 
                    sop0 = op0; sop1 = op1;\
374
 
                    OP;\
375
 
                    W2(inst->dest, res);\
376
 
                    break;\
377
 
                }\
378
 
    case opc*5+3: {\
379
 
                    uint32_t op0, op1, res;\
380
 
                    int32_t sop0, sop1;\
381
 
                    READ32(op0, BINOP(0));\
382
 
                    READ32(op1, BINOP(1));\
383
 
                    sop0 = op0; sop1 = op1;\
384
 
                    OP;\
385
 
                    W3(inst->dest, res);\
386
 
                    break;\
387
 
                }\
388
 
    case opc*5+4: {\
389
 
                    uint64_t op0, op1, res;\
390
 
                    int64_t sop0, sop1;\
391
 
                    READ64(op0, BINOP(0));\
392
 
                    READ64(op1, BINOP(1));\
393
 
                    sop0 = op0; sop1 = op1;\
394
 
                    OP;\
395
 
                    W4(inst->dest, res);\
396
 
                    break;\
397
 
                }
398
 
 
399
 
#define DEFINE_BINOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE16, WRITE32, WRITE64)
400
 
#define DEFINE_ICMPOP(opc, OP) DEFINE_BINOP_BC_HELPER(opc, OP, WRITE8, WRITE8, WRITE8, WRITE8, WRITE8)
401
 
 
402
 
#define CHECK_OP(cond, msg) if((cond)) { cli_dbgmsg(msg); stop = CL_EBYTECODE; break;}
403
 
 
404
 
#define DEFINE_SCASTOP(opc, OP) \
405
 
    case opc*5: {\
406
 
                    uint8_t res;\
407
 
                    int8_t sres;\
408
 
                    OP;\
409
 
                    WRITE8(inst->dest, res);\
410
 
                    break;\
411
 
                }\
412
 
    case opc*5+1: {\
413
 
                    uint8_t res;\
414
 
                    int8_t sres;\
415
 
                    OP;\
416
 
                    WRITE8(inst->dest, res);\
417
 
                    break;\
418
 
                }\
419
 
    case opc*5+2: {\
420
 
                    uint16_t res;\
421
 
                    int16_t sres;\
422
 
                    OP;\
423
 
                    WRITE16(inst->dest, res);\
424
 
                    break;\
425
 
                }\
426
 
    case opc*5+3: {\
427
 
                    uint32_t res;\
428
 
                    int32_t sres;\
429
 
                    OP;\
430
 
                    WRITE32(inst->dest, res);\
431
 
                    break;\
432
 
                }\
433
 
    case opc*5+4: {\
434
 
                    uint64_t res;\
435
 
                    int64_t sres;\
436
 
                    OP;\
437
 
                    WRITE64(inst->dest, res);\
438
 
                    break;\
439
 
                }
440
 
#define DEFINE_CASTOP(opc, OP) DEFINE_SCASTOP(opc, OP; (void)sres)
441
 
 
442
 
#define DEFINE_OP(opc) \
443
 
    case opc*5: /* fall-through */\
444
 
    case opc*5+1: /* fall-through */\
445
 
    case opc*5+2: /* fall-through */\
446
 
    case opc*5+3: /* fall-through */\
447
 
    case opc*5+4:
448
 
 
449
 
#define CHOOSE(OP0, OP1, OP2, OP3, OP4) \
450
 
    switch (inst->u.cast.size) {\
451
 
        case 0: OP0; break;\
452
 
        case 1: OP1; break;\
453
 
        case 2: OP2; break;\
454
 
        case 3: OP3; break;\
455
 
        case 4: OP4; break;\
456
 
        default: CHECK_UNREACHABLE;\
457
 
    }
458
 
 
459
 
#define DEFINE_OP_BC_RET_N(OP, T, R0, W0) \
460
 
    case OP: {\
461
 
                T tmp;\
462
 
                R0(tmp, inst->u.unaryop);\
463
 
                CHECK_GT(stack_depth, 0);\
464
 
                stack_depth--;\
465
 
                stack_entry = pop_stack(&stack, stack_entry, &func, &i, &bb,\
466
 
                                        &bb_inst);\
467
 
                values = stack_entry ? stack_entry->values : ctx->values;\
468
 
                CHECK_GT(func->numBytes, i);\
469
 
                W0(i, tmp);\
470
 
                if (!bb) {\
471
 
                    stop = CL_BREAK;\
472
 
                    continue;\
473
 
                }\
474
 
                stackid = ptr_register_stack(&ptrinfos, values, 0, func->numBytes)>>32;\
475
 
                inst = &bb->insts[bb_inst];\
476
 
                break;\
477
 
            }
478
 
 
479
 
struct ptr_info {
480
 
    uint8_t *base;
481
 
    uint32_t size;
482
 
};
483
 
 
484
 
struct ptr_infos {
485
 
    struct ptr_info *stack_infos;
486
 
    struct ptr_info *glob_infos;
487
 
    unsigned nstacks, nglobs;
488
 
};
489
 
 
490
 
static inline int64_t ptr_compose(int32_t id, uint32_t offset)
491
 
{
492
 
    uint64_t i = id;
493
 
    return (i << 32) | offset;
494
 
}
495
 
 
496
 
static inline int32_t ptr_diff32(int64_t ptr1, int64_t ptr2)
497
 
{
498
 
    int32_t ptrid1 = ptr1 >> 32;
499
 
    int32_t ptrid2 = ptr2 >> 32;
500
 
    if (ptrid1 != ptrid2) {
501
 
        (void)bcfail("difference of pointers not pointing to same object!", ptrid1, ptrid2, __FILE__, __LINE__);
502
 
        /* invalid diff */
503
 
        return 0x40000000;
504
 
    }
505
 
    return (uint32_t)ptr1 - (uint32_t)ptr2;
506
 
}
507
 
 
508
 
static inline int64_t ptr_register_stack(struct ptr_infos *infos,
509
 
                                         char *values,
510
 
                                         uint32_t off, uint32_t size)
511
 
{
512
 
    unsigned n = infos->nstacks + 1;
513
 
    struct ptr_info *sinfos = cli_realloc(infos->stack_infos,
514
 
                                          sizeof(*sinfos)*n);
515
 
    if (!sinfos)
516
 
        return 0;
517
 
    infos->stack_infos = sinfos;
518
 
    infos->nstacks = n;
519
 
    sinfos = &sinfos[n-1];
520
 
    sinfos->base = (uint8_t*)values + off;
521
 
    sinfos->size = size;
522
 
    return ptr_compose(-n, 0);
523
 
}
524
 
 
525
 
static inline int64_t ptr_register_glob_fixedid(struct ptr_infos *infos,
526
 
                                                void *values, uint32_t size, unsigned n)
527
 
{
528
 
    struct ptr_info *sinfos;
529
 
    if (n > infos->nglobs) {
530
 
        sinfos = cli_realloc(infos->glob_infos, sizeof(*sinfos)*n);
531
 
        if (!sinfos)
532
 
            return 0;
533
 
        memset(sinfos + infos->nglobs, 0, (n - infos->nglobs)*sizeof(*sinfos));
534
 
        infos->glob_infos = sinfos;
535
 
        infos->nglobs = n;
536
 
    }
537
 
    sinfos = &infos->glob_infos[n-1];
538
 
    if (!values)
539
 
        size = 0;
540
 
    sinfos->base = values;
541
 
    sinfos->size = size;
542
 
    cli_dbgmsg("bytecode: registered ctx variable at %p (+%u) id %u\n", values,
543
 
               size, n);
544
 
    return ptr_compose(n, 0);
545
 
}
546
 
 
547
 
static inline int64_t ptr_register_glob(struct ptr_infos *infos,
548
 
                                        void *values, uint32_t size)
549
 
{
550
 
    if (!values)
551
 
        return 0;
552
 
    return ptr_register_glob_fixedid(infos, values, size, infos->nglobs+1);
553
 
}
554
 
 
555
 
static inline int64_t ptr_index(int64_t ptr, uint32_t off)
556
 
{
557
 
    int32_t ptrid = ptr >> 32;
558
 
    uint32_t ptroff = (uint32_t)ptr;
559
 
    return ptr_compose(ptrid, ptroff+off);
560
 
}
561
 
 
562
 
static inline void* ptr_torealptr(const struct ptr_infos *infos, int64_t ptr,
563
 
                                  uint32_t read_size)
564
 
{
565
 
    struct ptr_info *info;
566
 
    int32_t ptrid = ptr >> 32;
567
 
    uint32_t ptroff = (uint32_t)ptr;
568
 
    TRACE_PTR(ptr, read_size);
569
 
    if (UNLIKELY(!ptrid)) {
570
 
        (void)bcfail("nullptr", ptrid, 0, __FILE__, __LINE__);
571
 
        return NULL;
572
 
    }
573
 
    if (ptrid < 0) {
574
 
        ptrid = -ptrid-1;
575
 
        if (UNLIKELY(ptrid >= infos->nstacks)) {
576
 
            (void)bcfail("ptr", ptrid, infos->nstacks, __FILE__, __LINE__);
577
 
            return NULL;
578
 
        }
579
 
        info = &infos->stack_infos[ptrid];
580
 
    } else {
581
 
        ptrid--;
582
 
        if (UNLIKELY(ptrid >= infos->nglobs)) {
583
 
            (void)bcfail("ptr", ptrid, infos->nglobs, __FILE__, __LINE__);
584
 
            return NULL;
585
 
        }
586
 
        info = &infos->glob_infos[ptrid];
587
 
    }
588
 
    if (LIKELY(ptroff < info->size &&
589
 
        read_size <= info->size &&
590
 
        ptroff + read_size <= info->size)) {
591
 
        return info->base+ptroff;
592
 
    }
593
 
 
594
 
    (void)bcfail("ptr1", ptroff, info->size, __FILE__, __LINE__);
595
 
    (void)bcfail("ptr2", read_size, info->size, __FILE__, __LINE__);
596
 
    (void)bcfail("ptr3", ptroff+read_size, info->size, __FILE__, __LINE__);
597
 
    return NULL;
598
 
}
599
 
 
600
 
static always_inline int check_sdivops(int64_t op0, int64_t op1)
601
 
{
602
 
    return op1 == 0 || (op0 == -1 && op1 ==  (-9223372036854775807LL-1LL));
603
 
}
604
 
 
605
 
static unsigned globaltypesize(uint16_t id)
606
 
{
607
 
    const struct cli_bc_type *ty;
608
 
    if (id <= 64)
609
 
        return (id + 7)/8;
610
 
    if (id < 69)
611
 
        return 8; /* ptr */
612
 
    ty = &cli_apicall_types[id - 69];
613
 
    switch (ty->kind) {
614
 
        case DArrayType:
615
 
            return ty->numElements*globaltypesize(ty->containedTypes[0]);
616
 
        case DStructType:
617
 
        case DPackedStructType:
618
 
            {
619
 
                unsigned i, s = 0;
620
 
                for (i=0;i<ty->numElements;i++)
621
 
                    s += globaltypesize(ty->containedTypes[i]);
622
 
                return s;
623
 
            }
624
 
        default:
625
 
            return 0;
626
 
    }
627
 
}
628
 
 
629
 
/* TODO: fix the APIs too */
630
 
static struct {
631
 
    cli_apicall_pointer api;
632
 
    uint32_t override_size;
633
 
} apisize_override[] = {
634
 
    {(void*)cli_bcapi_disasm_x86, sizeof(struct DISASM_RESULT)},
635
 
    {(void*)cli_bcapi_get_pe_section, sizeof(struct cli_exe_section)},
636
 
};
637
 
 
638
 
int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct cli_bc_func *func, const struct cli_bc_inst *inst)
639
 
{
640
 
    unsigned i, j, stack_depth=0, bb_inst=0, stop=0, pc=0;
641
 
    struct cli_bc_func *func2;
642
 
    struct stack stack;
643
 
    struct stack_entry *stack_entry = NULL;
644
 
    struct cli_bc_bb *bb = NULL;
645
 
    char *values = ctx->values;
646
 
    char *old_values;
647
 
    struct ptr_infos ptrinfos;
648
 
    struct timeval tv0, tv1, timeout;
649
 
    int stackid = 0;
650
 
 
651
 
    memset(&ptrinfos, 0, sizeof(ptrinfos));
652
 
    memset(&stack, 0, sizeof(stack));
653
 
    for (i=0;i < cli_apicall_maxglobal - _FIRST_GLOBAL; i++) {
654
 
        void *apiptr;
655
 
        uint32_t size;
656
 
        const struct cli_apiglobal *g = &cli_globals[i];
657
 
        void **apiglobal = (void**)(((char*)ctx) + g->offset);
658
 
        if (!apiglobal)
659
 
            continue;
660
 
        apiptr = *apiglobal;
661
 
        size = globaltypesize(g->type);
662
 
        ptr_register_glob_fixedid(&ptrinfos, apiptr, size, g->globalid - _FIRST_GLOBAL+1);
663
 
    }
664
 
    ptr_register_glob_fixedid(&ptrinfos, bc->globalBytes, bc->numGlobalBytes,
665
 
                              cli_apicall_maxglobal - _FIRST_GLOBAL + 2);
666
 
 
667
 
    gettimeofday(&tv0, NULL);
668
 
    timeout.tv_usec = tv0.tv_usec + ctx->bytecode_timeout*1000;
669
 
    timeout.tv_sec = tv0.tv_sec + timeout.tv_usec/1000000;
670
 
    timeout.tv_usec %= 1000000;
671
 
 
672
 
    do {
673
 
        pc++;
674
 
        if (!(pc % 5000)) {
675
 
            gettimeofday(&tv1, NULL);
676
 
            if (tv1.tv_sec > timeout.tv_sec ||
677
 
                (tv1.tv_sec == timeout.tv_sec &&
678
 
                 tv1.tv_usec > timeout.tv_usec)) {
679
 
                cli_warnmsg("Bytecode run timed out in interpreter after %u opcodes\n", pc);
680
 
                stop = CL_ETIMEOUT;
681
 
                break;
682
 
            }
683
 
        }
684
 
        switch (inst->interp_op) {
685
 
            DEFINE_BINOP(OP_BC_ADD, res = op0 + op1);
686
 
            DEFINE_BINOP(OP_BC_SUB, res = op0 - op1);
687
 
            DEFINE_BINOP(OP_BC_MUL, res = op0 * op1);
688
 
 
689
 
            DEFINE_BINOP(OP_BC_UDIV, CHECK_OP(op1 == 0, "bytecode attempted to execute udiv#0\n");
690
 
                         res=op0/op1);
691
 
            DEFINE_BINOP(OP_BC_SDIV, CHECK_OP(check_sdivops(sop0, sop1), "bytecode attempted to execute sdiv#0\n");
692
 
                         res=sop0/sop1);
693
 
            DEFINE_BINOP(OP_BC_UREM, CHECK_OP(op1 == 0, "bytecode attempted to execute urem#0\n");
694
 
                         res=op0 % op1);
695
 
            DEFINE_BINOP(OP_BC_SREM, CHECK_OP(check_sdivops(sop0,sop1), "bytecode attempted to execute urem#0\n");
696
 
                         res=sop0 % sop1);
697
 
 
698
 
            DEFINE_BINOP(OP_BC_SHL, CHECK_OP(op1 > inst->type, "bytecode attempted to execute shl greater than bitwidth\n");
699
 
                         res = op0 << op1);
700
 
            DEFINE_BINOP(OP_BC_LSHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute lshr greater than bitwidth\n");
701
 
                         res = op0 >> op1);
702
 
            DEFINE_BINOP(OP_BC_ASHR, CHECK_OP(op1 > inst->type, "bytecode attempted to execute ashr greater than bitwidth\n");
703
 
                         res = CLI_SRS(sop0, op1));
704
 
 
705
 
            DEFINE_BINOP(OP_BC_AND, res = op0 & op1);
706
 
            DEFINE_BINOP(OP_BC_OR, res = op0 | op1);
707
 
            DEFINE_BINOP(OP_BC_XOR, res = op0 ^ op1);
708
 
 
709
 
            DEFINE_SCASTOP(OP_BC_SEXT,
710
 
                          CHOOSE(READ1(sres, inst->u.cast.source); res = sres ? ~0ull : 0,
711
 
                                 READ8(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
712
 
                                 READ16(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
713
 
                                 READ32(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask),
714
 
                                 READ64(sres, inst->u.cast.source); res=sres=SIGNEXT(sres, inst->u.cast.mask)));
715
 
            DEFINE_CASTOP(OP_BC_ZEXT,
716
 
                          CHOOSE(READ1(res, inst->u.cast.source),
717
 
                                 READ8(res, inst->u.cast.source),
718
 
                                 READ16(res, inst->u.cast.source),
719
 
                                 READ32(res, inst->u.cast.source),
720
 
                                 READ64(res, inst->u.cast.source)));
721
 
            DEFINE_CASTOP(OP_BC_TRUNC,
722
 
                          CHOOSE(READ1(res, inst->u.cast.source),
723
 
                                 READ8(res, inst->u.cast.source),
724
 
                                 READ16(res, inst->u.cast.source),
725
 
                                 READ32(res, inst->u.cast.source),
726
 
                                 READ64(res, inst->u.cast.source)));
727
 
 
728
 
            DEFINE_OP(OP_BC_BRANCH)
729
 
                stop = jump(func, (values[inst->u.branch.condition]&1) ?
730
 
                          inst->u.branch.br_true : inst->u.branch.br_false,
731
 
                          &bb, &inst, &bb_inst);
732
 
                continue;
733
 
 
734
 
            DEFINE_OP(OP_BC_JMP)
735
 
                stop = jump(func, inst->u.jump, &bb, &inst, &bb_inst);
736
 
                continue;
737
 
 
738
 
            DEFINE_OP_BC_RET_N(OP_BC_RET*5, uint8_t, READ1, WRITE8);
739
 
            DEFINE_OP_BC_RET_N(OP_BC_RET*5+1, uint8_t, READ8, WRITE8);
740
 
            DEFINE_OP_BC_RET_N(OP_BC_RET*5+2, uint16_t, READ16, WRITE16);
741
 
            DEFINE_OP_BC_RET_N(OP_BC_RET*5+3, uint32_t, READ32, WRITE32);
742
 
            DEFINE_OP_BC_RET_N(OP_BC_RET*5+4, uint64_t, READ64, WRITE64);
743
 
 
744
 
            DEFINE_ICMPOP(OP_BC_ICMP_EQ, res = (op0 == op1));
745
 
            DEFINE_ICMPOP(OP_BC_ICMP_NE, res = (op0 != op1));
746
 
            DEFINE_ICMPOP(OP_BC_ICMP_UGT, res = (op0 > op1));
747
 
            DEFINE_ICMPOP(OP_BC_ICMP_UGE, res = (op0 >= op1));
748
 
            DEFINE_ICMPOP(OP_BC_ICMP_ULT, res = (op0 < op1));
749
 
            DEFINE_ICMPOP(OP_BC_ICMP_ULE, res = (op0 <= op1));
750
 
            DEFINE_ICMPOP(OP_BC_ICMP_SGT, res = (sop0 > sop1));
751
 
            DEFINE_ICMPOP(OP_BC_ICMP_SGE, res = (sop0 >= sop1));
752
 
            DEFINE_ICMPOP(OP_BC_ICMP_SLE, res = (sop0 <= sop1));
753
 
            DEFINE_ICMPOP(OP_BC_ICMP_SLT, res = (sop0 < sop1));
754
 
 
755
 
            case OP_BC_SELECT*5:
756
 
            {
757
 
                uint8_t t0, t1, t2;
758
 
                READ1(t0, inst->u.three[0]);
759
 
                READ1(t1, inst->u.three[1]);
760
 
                READ1(t2, inst->u.three[2]);
761
 
                WRITE8(inst->dest, t0 ? t1 : t2);
762
 
                break;
763
 
            }
764
 
            case OP_BC_SELECT*5+1:
765
 
            {
766
 
                uint8_t t0, t1, t2;
767
 
                READ1(t0, inst->u.three[0]);
768
 
                READ8(t1, inst->u.three[1]);
769
 
                READ8(t2, inst->u.three[2]);
770
 
                WRITE8(inst->dest, t0 ? t1 : t2);
771
 
                break;
772
 
            }
773
 
            case OP_BC_SELECT*5+2:
774
 
            {
775
 
                uint8_t t0;
776
 
                uint16_t t1, t2;
777
 
                READ1(t0, inst->u.three[0]);
778
 
                READ16(t1, inst->u.three[1]);
779
 
                READ16(t2, inst->u.three[2]);
780
 
                WRITE16(inst->dest, t0 ? t1 : t2);
781
 
                break;
782
 
            }
783
 
            case OP_BC_SELECT*5+3:
784
 
            {
785
 
                uint8_t t0;
786
 
                uint32_t t1, t2;
787
 
                READ1(t0, inst->u.three[0]);
788
 
                READ32(t1, inst->u.three[1]);
789
 
                READ32(t2, inst->u.three[2]);
790
 
                WRITE32(inst->dest, t0 ? t1 : t2);
791
 
                break;
792
 
            }
793
 
            case OP_BC_SELECT*5+4:
794
 
            {
795
 
                uint8_t t0;
796
 
                uint64_t t1, t2;
797
 
                READ1(t0, inst->u.three[0]);
798
 
                READ64(t1, inst->u.three[1]);
799
 
                READ64(t2, inst->u.three[2]);
800
 
                WRITE64(inst->dest, t0 ? t1 : t2);
801
 
                break;
802
 
            }
803
 
 
804
 
            DEFINE_OP(OP_BC_CALL_API) {
805
 
                const struct cli_apicall *api = &cli_apicalls[inst->u.ops.funcid];
806
 
                int32_t res32;
807
 
                int64_t res64;
808
 
                CHECK_APIID(inst->u.ops.funcid);
809
 
                TRACE_API(api->name, inst->dest, inst->type, stack_depth);
810
 
                switch (api->kind) {
811
 
                    case 0: {
812
 
                        int32_t a, b;
813
 
                        READ32(a, inst->u.ops.ops[0]);
814
 
                        READ32(b, inst->u.ops.ops[1]);
815
 
                        res32 = cli_apicalls0[api->idx](ctx, a, b);
816
 
                        WRITE32(inst->dest, res32);
817
 
                        break;
818
 
                    }
819
 
                    case 1: {
820
 
                        unsigned i;
821
 
                        void* arg1;
822
 
                        unsigned arg2, arg1size;
823
 
                        READ32(arg2, inst->u.ops.ops[1]);
824
 
                        /* check that arg2 is size of arg1 */
825
 
                        arg1size = arg2;
826
 
                        for (i=0;i<sizeof(apisize_override)/sizeof(apisize_override[0]);i++) {
827
 
                            if (cli_apicalls1[api->idx] == apisize_override[i].api) {
828
 
                                arg1size = apisize_override[i].override_size;
829
 
                                break;
830
 
                            }
831
 
                        }
832
 
                        READPOP(arg1, inst->u.ops.ops[0], arg1size);
833
 
                        res32 = cli_apicalls1[api->idx](ctx, arg1, arg2);
834
 
                        WRITE32(inst->dest, res32);
835
 
                        break;
836
 
                    }
837
 
                    case 2: {
838
 
                        int32_t a;
839
 
                        READ32(a, inst->u.ops.ops[0]);
840
 
                        res32 = cli_apicalls2[api->idx](ctx, a);
841
 
                        WRITE32(inst->dest, res32);
842
 
                        break;
843
 
                    }
844
 
                    case 3: {
845
 
                        int32_t a;
846
 
                        void *resp;
847
 
                        READ32(a, inst->u.ops.ops[0]);
848
 
                        resp = cli_apicalls3[api->idx](ctx, a);
849
 
                        res64 = ptr_register_glob(&ptrinfos, resp, a);
850
 
                        WRITE64(inst->dest, res64);
851
 
                        break;
852
 
                    }
853
 
                    case 4: {
854
 
                        int32_t arg2, arg3, arg4, arg5;
855
 
                        void *arg1;
856
 
                        READ32(arg2, inst->u.ops.ops[1]);
857
 
                        /* check that arg2 is size of arg1 */
858
 
                        READP(arg1, inst->u.ops.ops[0], arg2);
859
 
                        READ32(arg3, inst->u.ops.ops[2]);
860
 
                        READ32(arg4, inst->u.ops.ops[3]);
861
 
                        READ32(arg5, inst->u.ops.ops[4]);
862
 
                        res32 = cli_apicalls4[api->idx](ctx, arg1, arg2, arg3, arg4, arg5);
863
 
                        WRITE32(inst->dest, res32);
864
 
                        break;
865
 
                    }
866
 
                    case 5: {
867
 
                        res32 = cli_apicalls5[api->idx](ctx);
868
 
                        WRITE32(inst->dest, res32);
869
 
                        break;
870
 
                    }
871
 
                    case 6: {
872
 
                        int32_t arg1, arg2;
873
 
                        void *resp;
874
 
                        READ32(arg1, inst->u.ops.ops[0]);
875
 
                        READ32(arg2, inst->u.ops.ops[1]);
876
 
                        resp = cli_apicalls6[api->idx](ctx, arg1, arg2);
877
 
                        res64 = ptr_register_glob(&ptrinfos, resp, arg2);
878
 
                        WRITE64(inst->dest, res64);
879
 
                        break;
880
 
                    }
881
 
                    case 7: {
882
 
                        int32_t arg1,arg2,arg3;
883
 
                        READ32(arg1, inst->u.ops.ops[0]);
884
 
                        READ32(arg2, inst->u.ops.ops[1]);
885
 
                        READ32(arg3, inst->u.ops.ops[2]);
886
 
                        res32 = cli_apicalls7[api->idx](ctx, arg1, arg2, arg3);
887
 
                        WRITE32(inst->dest, res32);
888
 
                        break;
889
 
                    }
890
 
                    case 8: {
891
 
                        int32_t arg2, arg4;
892
 
                        void *arg1, *arg3;
893
 
                        int32_t resp;
894
 
                        READ32(arg2, inst->u.ops.ops[1]);
895
 
                        /* check that arg2 is size of arg1 */
896
 
                        READP(arg1, inst->u.ops.ops[0], arg2);
897
 
                        READ32(arg4, inst->u.ops.ops[3]);
898
 
                        READP(arg3, inst->u.ops.ops[2], arg4);
899
 
                        resp = cli_apicalls8[api->idx](ctx, arg1, arg2, arg3, arg4);
900
 
                        WRITE32(inst->dest, resp);
901
 
                        break;
902
 
                    }
903
 
                    case 9: {
904
 
                        int32_t arg2, arg3;
905
 
                        void *arg1;
906
 
                        int32_t resp;
907
 
                        READ32(arg2, inst->u.ops.ops[1]);
908
 
                        /* check that arg2 is size of arg1 */
909
 
                        READP(arg1, inst->u.ops.ops[0], arg2);
910
 
                        READ32(arg3, inst->u.ops.ops[2]);
911
 
                        resp = cli_apicalls9[api->idx](ctx, arg1, arg2, arg3);
912
 
                        WRITE32(inst->dest, resp);
913
 
                        break;
914
 
                    };
915
 
                    default:
916
 
                        cli_warnmsg("bytecode: type %u apicalls not yet implemented!\n", api->kind);
917
 
                        stop = CL_EBYTECODE;
918
 
                }
919
 
                break;
920
 
            }
921
 
 
922
 
            DEFINE_OP(OP_BC_CALL_DIRECT)
923
 
                CHECK_FUNCID(inst->u.ops.funcid);
924
 
                func2 = &bc->funcs[inst->u.ops.funcid];
925
 
                CHECK_EQ(func2->numArgs, inst->u.ops.numOps);
926
 
                old_values = values;
927
 
                stack_entry = allocate_stack(&stack, stack_entry, func2, func, inst->dest,
928
 
                                             bb, bb_inst);
929
 
                if (!stack_entry) {
930
 
                    stop = CL_EMEM;
931
 
                    break;
932
 
                }
933
 
                values = stack_entry->values;
934
 
                /* TODO: unregister on ret */
935
 
                TRACE_EXEC(inst->u.ops.funcid, inst->dest, inst->type, stack_depth);
936
 
                if (stack_depth > 10000) {
937
 
                    cli_warnmsg("bytecode: stack depth exceeded\n");
938
 
                    stop = CL_EBYTECODE;
939
 
                    break;
940
 
                }
941
 
                j = 0;
942
 
                for (i=0;i<func2->numArgs;i++) {
943
 
                    switch (inst->u.ops.opsizes[i]) {
944
 
                        case 1: {
945
 
                            uint8_t v;
946
 
                            READOLD8(v, inst->u.ops.ops[i]);
947
 
                            CHECK_GT(func2->numBytes, j);
948
 
                            values[j++] = v;
949
 
                            break;
950
 
                        }
951
 
                        case 2: {
952
 
                            uint16_t v;
953
 
                            READOLD16(v, inst->u.ops.ops[i]);
954
 
                            j = (j+1)&~1;
955
 
                            CHECK_GT(func2->numBytes, j);
956
 
                            *(uint16_t*)&values[j] = v;
957
 
                            j += 2;
958
 
                            break;
959
 
                        }
960
 
                        case 4: {
961
 
                            uint32_t v;
962
 
                            READOLD32(v, inst->u.ops.ops[i]);
963
 
                            j = (j+3)&~3;
964
 
                            CHECK_GT(func2->numBytes, j);
965
 
                            *(uint32_t*)&values[j] = v;
966
 
                            j += 4;
967
 
                            break;
968
 
                        }
969
 
                        case 8: {
970
 
                            uint64_t v;
971
 
                            READOLD64(v, inst->u.ops.ops[i]);
972
 
                            j = (j+7)&~7;
973
 
                            CHECK_GT(func2->numBytes, j);
974
 
                            *(uint64_t*)&values[j] = v;
975
 
                            j += 8;
976
 
                            break;
977
 
                        }
978
 
                    }
979
 
                }
980
 
                func = func2;
981
 
                stackid = ptr_register_stack(&ptrinfos, values, 0, func->numBytes)>>32;
982
 
                CHECK_GT(func->numBB, 0);
983
 
                stop = jump(func, 0, &bb, &inst, &bb_inst);
984
 
                stack_depth++;
985
 
                continue;
986
 
 
987
 
            case OP_BC_COPY*5:
988
 
            {
989
 
                uint8_t op;
990
 
                READ1(op, BINOP(0));
991
 
                WRITE8(BINOP(1), op);
992
 
                break;
993
 
            }
994
 
            case OP_BC_COPY*5+1:
995
 
            {
996
 
                uint8_t op;
997
 
                READ8(op, BINOP(0));
998
 
                WRITE8(BINOP(1), op);
999
 
                break;
1000
 
            }
1001
 
            case OP_BC_COPY*5+2:
1002
 
            {
1003
 
                uint16_t op;
1004
 
                READ16(op, BINOP(0));
1005
 
                WRITE16(BINOP(1), op);
1006
 
                break;
1007
 
            }
1008
 
            case OP_BC_COPY*5+3:
1009
 
            {
1010
 
                uint32_t op;
1011
 
                READ32(op, BINOP(0));
1012
 
                WRITE32(BINOP(1), op);
1013
 
                break;
1014
 
            }
1015
 
            case OP_BC_COPY*5+4:
1016
 
            {
1017
 
                uint64_t op;
1018
 
                READ64(op, BINOP(0));
1019
 
                WRITE64(BINOP(1), op);
1020
 
                break;
1021
 
            }
1022
 
 
1023
 
            case OP_BC_LOAD*5:
1024
 
            case OP_BC_LOAD*5+1:
1025
 
            {
1026
 
                uint8_t *ptr;
1027
 
                READPOP(ptr, inst->u.unaryop, 1);
1028
 
                WRITE8(inst->dest, (*ptr));
1029
 
                break;
1030
 
            }
1031
 
            case OP_BC_LOAD*5+2:
1032
 
            {
1033
 
                const union unaligned_16 *ptr;
1034
 
                READPOP(ptr, inst->u.unaryop, 2);
1035
 
                WRITE16(inst->dest, (ptr->una_u16));
1036
 
                break;
1037
 
            }
1038
 
            case OP_BC_LOAD*5+3:
1039
 
            {
1040
 
                const union unaligned_32 *ptr;
1041
 
                READPOP(ptr, inst->u.unaryop, 4);
1042
 
                WRITE32(inst->dest, (ptr->una_u32));
1043
 
                break;
1044
 
            }
1045
 
            case OP_BC_LOAD*5+4:
1046
 
            {
1047
 
                const union unaligned_64 *ptr;
1048
 
                READPOP(ptr, inst->u.unaryop, 8);
1049
 
                WRITE64(inst->dest, (ptr->una_u64));
1050
 
                break;
1051
 
            }
1052
 
 
1053
 
            case OP_BC_STORE*5:
1054
 
            {
1055
 
                uint8_t *ptr;
1056
 
                uint8_t v;
1057
 
                READP(ptr, BINOP(1), 1);
1058
 
                READ1(v, BINOP(0));
1059
 
                *ptr = v;
1060
 
                break;
1061
 
            }
1062
 
            case OP_BC_STORE*5+1:
1063
 
            {
1064
 
                uint8_t *ptr;
1065
 
                uint8_t v;
1066
 
                READP(ptr, BINOP(1), 1);
1067
 
                READ8(v, BINOP(0));
1068
 
                *ptr = v;
1069
 
                break;
1070
 
            }
1071
 
            case OP_BC_STORE*5+2:
1072
 
            {
1073
 
                union unaligned_16 *ptr;
1074
 
                uint16_t v;
1075
 
                READP(ptr, BINOP(1), 2);
1076
 
                READ16(v, BINOP(0));
1077
 
                ptr->una_s16 = v;
1078
 
                break;
1079
 
            }
1080
 
            case OP_BC_STORE*5+3:
1081
 
            {
1082
 
                union unaligned_32 *ptr;
1083
 
                uint32_t v;
1084
 
                READP(ptr, BINOP(1), 4);
1085
 
                READ32(v, BINOP(0));
1086
 
                ptr->una_u32 = v;
1087
 
                break;
1088
 
            }
1089
 
            case OP_BC_STORE*5+4:
1090
 
            {
1091
 
                union unaligned_64 *ptr;
1092
 
                uint64_t v;
1093
 
                READP(ptr, BINOP(1), 8);
1094
 
                READ64(v, BINOP(0));
1095
 
                ptr->una_u64 = v;
1096
 
                break;
1097
 
            }
1098
 
            DEFINE_OP(OP_BC_ISBIGENDIAN) {
1099
 
                WRITE8(inst->dest, WORDS_BIGENDIAN);
1100
 
                break;
1101
 
            }
1102
 
            DEFINE_OP(OP_BC_GEPZ) {
1103
 
                int64_t ptr;
1104
 
                if (!(inst->interp_op%5)) {
1105
 
                    int32_t off;
1106
 
                    READ32(off, inst->u.three[2]);
1107
 
                    WRITE64(inst->dest, ptr_compose(stackid,
1108
 
                                                    inst->u.three[1]+off));
1109
 
                } else {
1110
 
                    int32_t off;
1111
 
                    READ32(off, inst->u.three[2]);
1112
 
                    READ64(ptr, inst->u.three[1]);
1113
 
                    WRITE64(inst->dest, ptr+off);
1114
 
                }
1115
 
                break;
1116
 
            }
1117
 
            DEFINE_OP(OP_BC_MEMCMP) {
1118
 
                int32_t arg3;
1119
 
                void *arg1, *arg2;
1120
 
                READ32(arg3, inst->u.three[2]);
1121
 
                READPOP(arg1, inst->u.three[0], arg3);
1122
 
                READPOP(arg2, inst->u.three[1], arg3);
1123
 
                WRITE32(inst->dest, memcmp(arg1, arg2, arg3));
1124
 
                break;
1125
 
            }
1126
 
            DEFINE_OP(OP_BC_MEMCPY) {
1127
 
                int64_t arg3;
1128
 
                void *arg1, *arg2;
1129
 
                int64_t res=0;
1130
 
 
1131
 
                READ32(arg3, inst->u.three[2]);
1132
 
                READPOP(arg1, inst->u.three[0], arg3);
1133
 
                READPOP(arg2, inst->u.three[1], arg3);
1134
 
                memcpy(arg1, arg2, (int32_t)arg3);
1135
 
/*              READ64(res, inst->u.three[0]);*/
1136
 
                WRITE64(inst->dest, res);
1137
 
                break;
1138
 
            }
1139
 
            DEFINE_OP(OP_BC_MEMMOVE) {
1140
 
                int64_t arg3;
1141
 
                void *arg1, *arg2;
1142
 
                int64_t res=0;
1143
 
 
1144
 
                READ64(arg3, inst->u.three[2]);
1145
 
                READPOP(arg1, inst->u.three[0], arg3);
1146
 
                READPOP(arg2, inst->u.three[1], arg3);
1147
 
                memmove(arg1, arg2, (int32_t)arg3);
1148
 
/*              READ64(res, inst->u.three[0]);*/
1149
 
                WRITE64(inst->dest, res);
1150
 
                break;
1151
 
            }
1152
 
            DEFINE_OP(OP_BC_MEMSET) {
1153
 
                int64_t arg3;
1154
 
                int32_t arg2;
1155
 
                void *arg1;
1156
 
                int64_t res=0;
1157
 
 
1158
 
                READ64(arg3, inst->u.three[2]);
1159
 
                READPOP(arg1, inst->u.three[0], arg3);
1160
 
                READ32(arg2, inst->u.three[1]);
1161
 
                memset(arg1, arg2, (int32_t)arg3);
1162
 
/*              READ64(res, inst->u.three[0]);*/
1163
 
                WRITE64(inst->dest, res);
1164
 
                break;
1165
 
            }
1166
 
            DEFINE_OP(OP_BC_BSWAP16) {
1167
 
                int16_t arg1;
1168
 
                READ16(arg1, inst->u.unaryop);
1169
 
                WRITE16(inst->dest, cbswap16(arg1));
1170
 
                break;
1171
 
            }
1172
 
            DEFINE_OP(OP_BC_BSWAP32) {
1173
 
                int32_t arg1;
1174
 
                READ32(arg1, inst->u.unaryop);
1175
 
                WRITE32(inst->dest, cbswap32(arg1));
1176
 
                break;
1177
 
            }
1178
 
            DEFINE_OP(OP_BC_BSWAP64) {
1179
 
                int64_t arg1;
1180
 
                READ64(arg1, inst->u.unaryop);
1181
 
                WRITE64(inst->dest, cbswap64(arg1));
1182
 
                break;
1183
 
            }
1184
 
            DEFINE_OP(OP_BC_PTRDIFF32) {
1185
 
                int64_t ptr1, ptr2;
1186
 
                if (BINOP(0)&0x40000000)
1187
 
                    ptr1 = ptr_compose(stackid, BINOP(0)&0xbfffffff);
1188
 
                else
1189
 
                    READ64(ptr1, BINOP(0));
1190
 
                if (BINOP(1)&0x40000000)
1191
 
                    ptr2 = ptr_compose(stackid, BINOP(1)&0xbfffffff);
1192
 
                else
1193
 
                    READ64(ptr2, BINOP(1));
1194
 
                WRITE32(inst->dest, ptr_diff32(ptr1, ptr2));
1195
 
                break;
1196
 
            }
1197
 
            DEFINE_OP(OP_BC_PTRTOINT64) {
1198
 
                int64_t ptr;
1199
 
                if (inst->u.unaryop&0x40000000)
1200
 
                    ptr = ptr_compose(stackid, inst->u.unaryop&0xbfffffff);
1201
 
                else
1202
 
                    READ64(ptr, BINOP(0));
1203
 
                WRITE64(inst->dest, ptr);
1204
 
                break;
1205
 
            }
1206
 
            DEFINE_OP(OP_BC_GEP1) {
1207
 
                int64_t ptr;
1208
 
                if (!(inst->interp_op%5)) {
1209
 
                    int32_t off;
1210
 
                    READ32(off, inst->u.three[2]);
1211
 
                    WRITE64(inst->dest, ptr_compose(stackid,
1212
 
                                                    inst->u.three[1]+off*inst->u.three[0]));
1213
 
                } else {
1214
 
                    int32_t off;
1215
 
                    READ32(off, inst->u.three[2]);
1216
 
                    READ64(ptr, inst->u.three[1]);
1217
 
                    WRITE64(inst->dest, ptr+off*inst->u.three[0]);
1218
 
                }
1219
 
                break;
1220
 
            }
1221
 
            /* TODO: implement OP_BC_GEP1, OP_BC_GEP2, OP_BC_GEPN */
1222
 
            default:
1223
 
                cli_errmsg("Opcode %u of type %u is not implemented yet!\n",
1224
 
                           inst->interp_op/5, inst->interp_op%5);
1225
 
                stop = CL_EARG;
1226
 
                continue;
1227
 
        }
1228
 
        bb_inst++;
1229
 
        inst++;
1230
 
        if (bb) {
1231
 
            CHECK_GT(bb->numInsts, bb_inst);
1232
 
        }
1233
 
    } while (stop == CL_SUCCESS);
1234
 
    if (cli_debug_flag) {
1235
 
        gettimeofday(&tv1, NULL);
1236
 
        tv1.tv_sec -= tv0.tv_sec;
1237
 
        tv1.tv_usec -= tv0.tv_usec;
1238
 
        cli_dbgmsg("intepreter bytecode run finished in %luus, after executing %u opcodes\n",
1239
 
                   tv1.tv_sec*1000000 + tv1.tv_usec, pc);
1240
 
    }
1241
 
    if (stop == CL_EBYTECODE) {
1242
 
        cli_event_error_str(ctx->bc_events, "interpreter finished with error\n");
1243
 
        cli_dbgmsg("intepreter finished with error\n");
1244
 
    }
1245
 
 
1246
 
    cli_stack_destroy(&stack);
1247
 
    free(ptrinfos.stack_infos);
1248
 
    free(ptrinfos.glob_infos);
1249
 
    return stop == CL_BREAK ? CL_SUCCESS : stop;
1250
 
}