... | ... |
@@ -1441,6 +1441,7 @@ void cli_bytecode_destroy(struct cli_bc *bc) |
1441 | 1441 |
if (bc->uses_apis) |
1442 | 1442 |
cli_bitset_free(bc->uses_apis); |
1443 | 1443 |
free(bc->lsig); |
1444 |
+ free(bc->globalBytes); |
|
1444 | 1445 |
} |
1445 | 1446 |
|
1446 | 1447 |
#define MAP(val) do { operand_t o = val; \ |
... | ... |
@@ -1476,6 +1477,9 @@ static int cli_bytecode_prepare_interpreter(struct cli_bc *bc) |
1476 | 1476 |
gmap[j] = bc->numGlobalBytes; |
1477 | 1477 |
bc->numGlobalBytes += typesize(bc, ty); |
1478 | 1478 |
} |
1479 |
+ bc->globalBytes = cli_calloc(1, bc->numGlobalBytes); |
|
1480 |
+ if (!bc->globalBytes) |
|
1481 |
+ return CL_EMEM; |
|
1479 | 1482 |
|
1480 | 1483 |
for (i=0;i<bc->num_func;i++) { |
1481 | 1484 |
struct cli_bc_func *bcfunc = &bc->funcs[i]; |
... | ... |
@@ -36,7 +36,7 @@ |
36 | 36 |
/* These checks will also be done by the bytecode verifier, but for |
37 | 37 |
* debugging purposes we have explicit checks, these should never fail! */ |
38 | 38 |
#ifdef CL_BYTECODE_DEBUG |
39 |
-static int bcfail(const char *msg, long a, long b, |
|
39 |
+static int never_inline bcfail(const char *msg, long a, long b, |
|
40 | 40 |
const char *file, unsigned line) |
41 | 41 |
{ |
42 | 42 |
cli_errmsg("bytecode: check failed %s (%lx and %lx) at %s:%u\n", msg, a, b, file, line); |
... | ... |
@@ -56,6 +56,8 @@ static int bcfail(const char *msg, long a, long b, |
56 | 56 |
#define TRACE_W(x, w, p) cli_dbgmsg("bytecode trace: %u, write%d @%u %llx\n", pc, p, w, (long long)x); |
57 | 57 |
#define TRACE_EXEC(id, dest, ty, stack) cli_dbgmsg("bytecode trace: executing %d, -> %u (%u); %u\n", id, dest, ty, stack) |
58 | 58 |
#else |
59 |
+static inline int bcfail(const char *msg, long a, long b, |
|
60 |
+ const char *file, unsigned line) {} |
|
59 | 61 |
#define TRACE_R(x) |
60 | 62 |
#define TRACE_W(x, w, p) |
61 | 63 |
#define TRACE_EXEC(id, dest, ty, stack) |
... | ... |
@@ -262,6 +264,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, |
262 | 262 |
#define uint_type(n) uint##n##_t |
263 | 263 |
#define READNfrom(maxBytes, from, x, n, p)\ |
264 | 264 |
CHECK_GT((maxBytes), (p)+(n/8)-1);\ |
265 |
+ CHECK_EQ((p)&(n-1), 0);\ |
|
265 | 266 |
x = *(uint_type(n)*)&(from)[(p)];\ |
266 | 267 |
TRACE_R(x) |
267 | 268 |
|
... | ... |
@@ -269,7 +272,7 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, |
269 | 269 |
do {\ |
270 | 270 |
if (p&0x80000000) {\ |
271 | 271 |
uint32_t pg = p&0x7fffffff;\ |
272 |
- READNfrom(ctx->numGlobals, ctx->globals, x, n, p);\ |
|
272 |
+ READNfrom(bc->numGlobalBytes, bc->globals, x, n, pg);\ |
|
273 | 273 |
} else {\ |
274 | 274 |
READNfrom(func->numBytes, values, x, n, p);\ |
275 | 275 |
}\ |
... | ... |
@@ -282,11 +285,16 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, |
282 | 282 |
#define READ32(x, p) READN(x, 32, p) |
283 | 283 |
#define READ64(x, p) READN(x, 64, p) |
284 | 284 |
|
285 |
-#define PSIZE sizeof(void*) |
|
286 |
-#define READP(x, p) CHECK_GT(func->numBytes, p+PSIZE-1);\ |
|
287 |
- CHECK_EQ((p)&(PSIZE-1), 0);\ |
|
288 |
- x = *(void**)&values[p];\ |
|
289 |
- TRACE_R(x) |
|
285 |
+#define PSIZE sizeof(int64_t) |
|
286 |
+#define READP(x, p, asize) { int64_t iptr__;\ |
|
287 |
+ READN(iptr__, 8, p);\ |
|
288 |
+ x = ptr_torealptr(&ptrinfos, iptr__, (asize));\ |
|
289 |
+ if (!x) {\ |
|
290 |
+ stop = CL_EBYTECODE;\ |
|
291 |
+ break;\ |
|
292 |
+ }\ |
|
293 |
+ TRACE_R(x)\ |
|
294 |
+} |
|
290 | 295 |
|
291 | 296 |
#define READOLD8(x, p) CHECK_GT(func->numBytes, p);\ |
292 | 297 |
x = *(uint8_t*)&old_values[p];\ |
... | ... |
@@ -436,6 +444,101 @@ static always_inline struct stack_entry *pop_stack(struct stack *stack, |
436 | 436 |
break;\ |
437 | 437 |
} |
438 | 438 |
|
439 |
+struct ptr_info { |
|
440 |
+ uint8_t *base; |
|
441 |
+ uint32_t size; |
|
442 |
+}; |
|
443 |
+ |
|
444 |
+struct ptr_infos { |
|
445 |
+ struct ptr_info *stack_infos; |
|
446 |
+ struct ptr_info *glob_infos; |
|
447 |
+ unsigned nstacks, nglobs; |
|
448 |
+}; |
|
449 |
+ |
|
450 |
+static inline int64_t ptr_compose(int32_t id, uint32_t offset) |
|
451 |
+{ |
|
452 |
+ uint64_t i = id; |
|
453 |
+ return (i << 32) | offset; |
|
454 |
+} |
|
455 |
+ |
|
456 |
+static inline int32_t ptr_register_stack(struct ptr_infos *infos, |
|
457 |
+ unsigned char *values, |
|
458 |
+ uint32_t off, uint32_t size) |
|
459 |
+{ |
|
460 |
+ int16_t id; |
|
461 |
+ unsigned n = infos->nstacks + 1; |
|
462 |
+ struct ptr_info *sinfos = cli_realloc(infos->stack_infos, |
|
463 |
+ sizeof(*sinfos)*n); |
|
464 |
+ if (!sinfos) |
|
465 |
+ return 0; |
|
466 |
+ infos->stack_infos = sinfos; |
|
467 |
+ infos->nstacks = n; |
|
468 |
+ sinfos = &sinfos[n-1]; |
|
469 |
+ sinfos->base = values + off; |
|
470 |
+ sinfos->size = size; |
|
471 |
+ return ptr_compose(-(n-1), 0); |
|
472 |
+} |
|
473 |
+ |
|
474 |
+static inline int64_t ptr_register_glob(struct ptr_infos *infos, |
|
475 |
+ void *values, uint32_t size) |
|
476 |
+{ |
|
477 |
+ unsigned n = infos->nstacks + 1; |
|
478 |
+ struct ptr_info *sinfos = cli_realloc(infos->stack_infos, |
|
479 |
+ sizeof(*sinfos)*n); |
|
480 |
+ if (!sinfos) |
|
481 |
+ return 0; |
|
482 |
+ infos->stack_infos = sinfos; |
|
483 |
+ infos->nstacks = n; |
|
484 |
+ sinfos = &sinfos[n-1]; |
|
485 |
+ sinfos->base = values; |
|
486 |
+ sinfos->size = size; |
|
487 |
+ return ptr_compose(n, 0); |
|
488 |
+} |
|
489 |
+ |
|
490 |
+static inline int64_t ptr_index(int64_t ptr, uint32_t off) |
|
491 |
+{ |
|
492 |
+ int32_t ptrid = ptr >> 32; |
|
493 |
+ uint32_t ptroff = (uint32_t)ptr; |
|
494 |
+ return ptr_compose(ptrid, ptroff+off); |
|
495 |
+} |
|
496 |
+ |
|
497 |
+static inline void* ptr_torealptr(const struct ptr_infos *infos, int64_t ptr, |
|
498 |
+ uint32_t read_size) |
|
499 |
+{ |
|
500 |
+ struct ptr_info *info; |
|
501 |
+ int32_t ptrid = ptr >> 32; |
|
502 |
+ uint32_t ptroff = (uint32_t)ptr; |
|
503 |
+ if (UNLIKELY(!ptrid)) { |
|
504 |
+ bcfail("nullptr", ptrid, 0, __FILE__, __LINE__); |
|
505 |
+ return NULL; |
|
506 |
+ } |
|
507 |
+ if (ptrid < 0) { |
|
508 |
+ ptrid = -ptrid; |
|
509 |
+ if (UNLIKELY(ptrid >= infos->nstacks)) { |
|
510 |
+ bcfail("ptr", ptrid, infos->nstacks, __FILE__, __LINE__); |
|
511 |
+ return NULL; |
|
512 |
+ } |
|
513 |
+ info = &infos->stack_infos[ptrid]; |
|
514 |
+ } else { |
|
515 |
+ ptrid--; |
|
516 |
+ if (UNLIKELY(ptrid >= infos->nglobs)) { |
|
517 |
+ bcfail("ptr", ptrid, infos->nglobs, __FILE__, __LINE__); |
|
518 |
+ return NULL; |
|
519 |
+ } |
|
520 |
+ info = &infos->glob_infos[ptrid]; |
|
521 |
+ } |
|
522 |
+ if (LIKELY(ptroff < info->size && |
|
523 |
+ read_size < info->size && |
|
524 |
+ ptroff + read_size <= info->size)) { |
|
525 |
+ return info->base+ptroff; |
|
526 |
+ } |
|
527 |
+ |
|
528 |
+ bcfail("ptr1", ptroff, info->size, __FILE__, __LINE__); |
|
529 |
+ bcfail("ptr2", read_size, info->size, __FILE__, __LINE__); |
|
530 |
+ bcfail("ptr3", ptroff+read_size, info->size, __FILE__, __LINE__); |
|
531 |
+ return NULL; |
|
532 |
+} |
|
533 |
+ |
|
439 | 534 |
static always_inline int check_sdivops(int64_t op0, int64_t op1) |
440 | 535 |
{ |
441 | 536 |
return op1 == 0 || (op0 == -1 && op1 == (-9223372036854775807LL-1LL)); |
... | ... |
@@ -450,7 +553,9 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
450 | 450 |
struct cli_bc_bb *bb = NULL; |
451 | 451 |
char *values = ctx->values; |
452 | 452 |
char *old_values; |
453 |
+ struct ptr_infos ptrinfos; |
|
453 | 454 |
|
455 |
+ memset(&ptrinfos, 0, sizeof(ptrinfos)); |
|
454 | 456 |
memset(&stack, 0, sizeof(stack)); |
455 | 457 |
do { |
456 | 458 |
pc++; |
... | ... |
@@ -721,32 +826,28 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
721 | 721 |
case OP_BC_LOAD*5+1: |
722 | 722 |
{ |
723 | 723 |
uint8_t *ptr; |
724 |
- READP(ptr, inst->u.unaryop); |
|
724 |
+ READP(ptr, inst->u.unaryop, 1); |
|
725 | 725 |
WRITE8(inst->dest, (*ptr)); |
726 | 726 |
break; |
727 | 727 |
} |
728 | 728 |
case OP_BC_LOAD*5+2: |
729 | 729 |
{ |
730 | 730 |
const union unaligned_16 *ptr; |
731 |
- READP(ptr, inst->u.unaryop); |
|
731 |
+ READP(ptr, inst->u.unaryop, 2); |
|
732 | 732 |
WRITE16(inst->dest, (ptr->una_u16)); |
733 | 733 |
break; |
734 | 734 |
} |
735 | 735 |
case OP_BC_LOAD*5+3: |
736 | 736 |
{ |
737 | 737 |
const union unaligned_32 *ptr; |
738 |
- READP(ptr, inst->u.unaryop); |
|
739 |
- if (!ptr) { |
|
740 |
- cli_dbgmsg("Bytecode attempted to load from null pointer!\n"); |
|
741 |
- return CL_EBYTECODE; |
|
742 |
- } |
|
738 |
+ READP(ptr, inst->u.unaryop, 4); |
|
743 | 739 |
WRITE32(inst->dest, (ptr->una_u32)); |
744 | 740 |
break; |
745 | 741 |
} |
746 | 742 |
case OP_BC_LOAD*5+4: |
747 | 743 |
{ |
748 | 744 |
const union unaligned_64 *ptr; |
749 |
- READP(ptr, inst->u.unaryop); |
|
745 |
+ READP(ptr, inst->u.unaryop, 8); |
|
750 | 746 |
WRITE64(inst->dest, (ptr->una_u64)); |
751 | 747 |
break; |
752 | 748 |
} |
... | ... |
@@ -755,7 +856,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
755 | 755 |
{ |
756 | 756 |
uint8_t *ptr; |
757 | 757 |
uint8_t v; |
758 |
- READP(ptr, BINOP(0)); |
|
758 |
+ READP(ptr, BINOP(0), 1); |
|
759 | 759 |
READ1(v, BINOP(1)); |
760 | 760 |
*ptr = v; |
761 | 761 |
break; |
... | ... |
@@ -764,7 +865,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
764 | 764 |
{ |
765 | 765 |
uint8_t *ptr; |
766 | 766 |
uint8_t v; |
767 |
- READP(ptr, BINOP(0)); |
|
767 |
+ READP(ptr, BINOP(0), 1); |
|
768 | 768 |
READ8(v, BINOP(1)); |
769 | 769 |
*ptr = v; |
770 | 770 |
break; |
... | ... |
@@ -773,7 +874,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
773 | 773 |
{ |
774 | 774 |
union unaligned_16 *ptr; |
775 | 775 |
uint16_t v; |
776 |
- READP(ptr, BINOP(0)); |
|
776 |
+ READP(ptr, BINOP(0), 2); |
|
777 | 777 |
READ16(v, BINOP(1)); |
778 | 778 |
ptr->una_s16 = v; |
779 | 779 |
break; |
... | ... |
@@ -782,7 +883,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
782 | 782 |
{ |
783 | 783 |
union unaligned_32 *ptr; |
784 | 784 |
uint32_t v; |
785 |
- READP(ptr, BINOP(0)); |
|
785 |
+ READP(ptr, BINOP(0), 4); |
|
786 | 786 |
READ32(v, BINOP(1)); |
787 | 787 |
ptr->una_u32 = v; |
788 | 788 |
break; |
... | ... |
@@ -791,7 +892,7 @@ int cli_vm_execute(const struct cli_bc *bc, struct cli_bc_ctx *ctx, const struct |
791 | 791 |
{ |
792 | 792 |
union unaligned_64 *ptr; |
793 | 793 |
uint64_t v; |
794 |
- READP(ptr, BINOP(0)); |
|
794 |
+ READP(ptr, BINOP(0), 8); |
|
795 | 795 |
READ64(v, BINOP(1)); |
796 | 796 |
ptr->una_u64 = v; |
797 | 797 |
break; |