~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to libclamav/bytecode_vm.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-07-15 01:08:10 UTC
  • mfrom: (0.35.47 sid)
  • Revision ID: package-import@ubuntu.com-20140715010810-ru66ek4fun2iseba
Tags: 0.98.4+dfsg-2~ubuntu13.10.1
No-change backport to saucy (LP: #1341962)

Show diffs side-by-side

added added

removed removed

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