Handle serialization endianness transparently (#152)
Change JS_WriteObject() and JS_WriteObject2() to write little-endian data and update JS_ReadObject() to byte-swap data when running on a big-endian system. Obsoletes the JS_WRITE_OBJ_BSWAP flag, it is now a no-op. Fixes: https://github.com/quickjs-ng/quickjs/issues/125
This commit is contained in:
parent
0ecb2c86b5
commit
a6e73ca73c
4 changed files with 18 additions and 36 deletions
|
@ -167,9 +167,6 @@ find the name of the dynamically loaded modules.
|
||||||
Add initialization code for an external C module. See the
|
Add initialization code for an external C module. See the
|
||||||
@code{c_module} example.
|
@code{c_module} example.
|
||||||
|
|
||||||
@item -x
|
|
||||||
Byte swapped output (only used for cross compilation).
|
|
||||||
|
|
||||||
@item -flto
|
@item -flto
|
||||||
Use link time optimization. The compilation is slower but the
|
Use link time optimization. The compilation is slower but the
|
||||||
executable is smaller and faster. This option is automatically set
|
executable is smaller and faster. This option is automatically set
|
||||||
|
|
13
qjsc.c
13
qjsc.c
|
@ -51,7 +51,6 @@ static namelist_t cname_list;
|
||||||
static namelist_t cmodule_list;
|
static namelist_t cmodule_list;
|
||||||
static namelist_t init_module_list;
|
static namelist_t init_module_list;
|
||||||
static FILE *outfile;
|
static FILE *outfile;
|
||||||
static BOOL byte_swap;
|
|
||||||
static const char *c_ident_prefix = "qjsc_";
|
static const char *c_ident_prefix = "qjsc_";
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,11 +151,8 @@ static void output_object_code(JSContext *ctx,
|
||||||
{
|
{
|
||||||
uint8_t *out_buf;
|
uint8_t *out_buf;
|
||||||
size_t out_buf_len;
|
size_t out_buf_len;
|
||||||
int flags;
|
|
||||||
flags = JS_WRITE_OBJ_BYTECODE;
|
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, JS_WRITE_OBJ_BYTECODE);
|
||||||
if (byte_swap)
|
|
||||||
flags |= JS_WRITE_OBJ_BSWAP;
|
|
||||||
out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags);
|
|
||||||
if (!out_buf) {
|
if (!out_buf) {
|
||||||
js_std_dump_error(ctx);
|
js_std_dump_error(ctx);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -322,7 +318,6 @@ void help(void)
|
||||||
"-m compile as Javascript module (default=autodetect)\n"
|
"-m compile as Javascript module (default=autodetect)\n"
|
||||||
"-D module_name compile a dynamically loaded module or worker\n"
|
"-D module_name compile a dynamically loaded module or worker\n"
|
||||||
"-M module_name[,cname] add initialization code for an external C module\n"
|
"-M module_name[,cname] add initialization code for an external C module\n"
|
||||||
"-x byte swapped output\n"
|
|
||||||
"-p prefix set the prefix of the generated C names\n"
|
"-p prefix set the prefix of the generated C names\n"
|
||||||
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
|
"-S n set the maximum stack size to 'n' bytes (default=%d)\n",
|
||||||
JS_GetVersion(),
|
JS_GetVersion(),
|
||||||
|
@ -352,7 +347,6 @@ int main(int argc, char **argv)
|
||||||
output_type = OUTPUT_C;
|
output_type = OUTPUT_C;
|
||||||
cname = NULL;
|
cname = NULL;
|
||||||
module = -1;
|
module = -1;
|
||||||
byte_swap = FALSE;
|
|
||||||
verbose = 0;
|
verbose = 0;
|
||||||
stack_size = 0;
|
stack_size = 0;
|
||||||
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
|
memset(&dynamic_module_list, 0, sizeof(dynamic_module_list));
|
||||||
|
@ -399,9 +393,6 @@ int main(int argc, char **argv)
|
||||||
case 'D':
|
case 'D':
|
||||||
namelist_add(&dynamic_module_list, optarg, NULL, 0);
|
namelist_add(&dynamic_module_list, optarg, NULL, 0);
|
||||||
break;
|
break;
|
||||||
case 'x':
|
|
||||||
byte_swap = TRUE;
|
|
||||||
break;
|
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
|
|
36
quickjs.c
36
quickjs.c
|
@ -31664,18 +31664,11 @@ typedef enum BCTagEnum {
|
||||||
BC_TAG_OBJECT_REFERENCE,
|
BC_TAG_OBJECT_REFERENCE,
|
||||||
} BCTagEnum;
|
} BCTagEnum;
|
||||||
|
|
||||||
#define BC_BASE_VERSION 2
|
#define BC_VERSION 3
|
||||||
#define BC_BE_VERSION 0x40
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
|
||||||
#define BC_VERSION (BC_BASE_VERSION | BC_BE_VERSION)
|
|
||||||
#else
|
|
||||||
#define BC_VERSION BC_BASE_VERSION
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct BCWriterState {
|
typedef struct BCWriterState {
|
||||||
JSContext *ctx;
|
JSContext *ctx;
|
||||||
DynBuf dbuf;
|
DynBuf dbuf;
|
||||||
BOOL byte_swap : 8;
|
|
||||||
BOOL allow_bytecode : 8;
|
BOOL allow_bytecode : 8;
|
||||||
BOOL allow_sab : 8;
|
BOOL allow_sab : 8;
|
||||||
BOOL allow_reference : 8;
|
BOOL allow_reference : 8;
|
||||||
|
@ -31717,6 +31710,15 @@ static const char * const bc_tag_str[] = {
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline BOOL is_be(void)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
uint16_t a;
|
||||||
|
uint8_t b;
|
||||||
|
} u = {0x100};
|
||||||
|
return u.b;
|
||||||
|
}
|
||||||
|
|
||||||
static void bc_put_u8(BCWriterState *s, uint8_t v)
|
static void bc_put_u8(BCWriterState *s, uint8_t v)
|
||||||
{
|
{
|
||||||
dbuf_putc(&s->dbuf, v);
|
dbuf_putc(&s->dbuf, v);
|
||||||
|
@ -31724,21 +31726,21 @@ static void bc_put_u8(BCWriterState *s, uint8_t v)
|
||||||
|
|
||||||
static void bc_put_u16(BCWriterState *s, uint16_t v)
|
static void bc_put_u16(BCWriterState *s, uint16_t v)
|
||||||
{
|
{
|
||||||
if (s->byte_swap)
|
if (is_be())
|
||||||
v = bswap16(v);
|
v = bswap16(v);
|
||||||
dbuf_put_u16(&s->dbuf, v);
|
dbuf_put_u16(&s->dbuf, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)
|
static __maybe_unused void bc_put_u32(BCWriterState *s, uint32_t v)
|
||||||
{
|
{
|
||||||
if (s->byte_swap)
|
if (is_be())
|
||||||
v = bswap32(v);
|
v = bswap32(v);
|
||||||
dbuf_put_u32(&s->dbuf, v);
|
dbuf_put_u32(&s->dbuf, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bc_put_u64(BCWriterState *s, uint64_t v)
|
static void bc_put_u64(BCWriterState *s, uint64_t v)
|
||||||
{
|
{
|
||||||
if (s->byte_swap)
|
if (is_be())
|
||||||
v = bswap64(v);
|
v = bswap64(v);
|
||||||
dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v));
|
dbuf_put(&s->dbuf, (uint8_t *)&v, sizeof(v));
|
||||||
}
|
}
|
||||||
|
@ -31908,7 +31910,7 @@ static int JS_WriteFunctionBytecode(BCWriterState *s,
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s->byte_swap)
|
if (is_be())
|
||||||
bc_byte_swap(bc_buf, bc_len);
|
bc_byte_swap(bc_buf, bc_len);
|
||||||
|
|
||||||
dbuf_put(&s->dbuf, bc_buf, bc_len);
|
dbuf_put(&s->dbuf, bc_buf, bc_len);
|
||||||
|
@ -32405,15 +32407,10 @@ static int JS_WriteObjectAtoms(BCWriterState *s)
|
||||||
JSRuntime *rt = s->ctx->rt;
|
JSRuntime *rt = s->ctx->rt;
|
||||||
DynBuf dbuf1;
|
DynBuf dbuf1;
|
||||||
int i, atoms_size;
|
int i, atoms_size;
|
||||||
uint8_t version;
|
|
||||||
|
|
||||||
dbuf1 = s->dbuf;
|
dbuf1 = s->dbuf;
|
||||||
js_dbuf_init(s->ctx, &s->dbuf);
|
js_dbuf_init(s->ctx, &s->dbuf);
|
||||||
|
bc_put_u8(s, BC_VERSION);
|
||||||
version = BC_VERSION;
|
|
||||||
if (s->byte_swap)
|
|
||||||
version ^= BC_BE_VERSION;
|
|
||||||
bc_put_u8(s, version);
|
|
||||||
|
|
||||||
bc_put_leb128(s, s->idx_to_atom_count);
|
bc_put_leb128(s, s->idx_to_atom_count);
|
||||||
for(i = 0; i < s->idx_to_atom_count; i++) {
|
for(i = 0; i < s->idx_to_atom_count; i++) {
|
||||||
|
@ -32446,8 +32443,6 @@ uint8_t *JS_WriteObject2(JSContext *ctx, size_t *psize, JSValueConst obj,
|
||||||
|
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
s->ctx = ctx;
|
s->ctx = ctx;
|
||||||
/* XXX: byte swapped output is untested */
|
|
||||||
s->byte_swap = ((flags & JS_WRITE_OBJ_BSWAP) != 0);
|
|
||||||
s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);
|
s->allow_bytecode = ((flags & JS_WRITE_OBJ_BYTECODE) != 0);
|
||||||
s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);
|
s->allow_sab = ((flags & JS_WRITE_OBJ_SAB) != 0);
|
||||||
s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);
|
s->allow_reference = ((flags & JS_WRITE_OBJ_REFERENCE) != 0);
|
||||||
|
@ -33531,7 +33526,6 @@ static int JS_ReadObjectAtoms(BCReaderState *s)
|
||||||
|
|
||||||
if (bc_get_u8(s, &v8))
|
if (bc_get_u8(s, &v8))
|
||||||
return -1;
|
return -1;
|
||||||
/* XXX: could support byte swapped input */
|
|
||||||
if (v8 != BC_VERSION) {
|
if (v8 != BC_VERSION) {
|
||||||
JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)",
|
JS_ThrowSyntaxError(s->ctx, "invalid version (%d expected=%d)",
|
||||||
v8, BC_VERSION);
|
v8, BC_VERSION);
|
||||||
|
|
|
@ -838,7 +838,7 @@ JS_EXTERN int JS_ExecutePendingJob(JSRuntime *rt, JSContext **pctx);
|
||||||
|
|
||||||
/* Object Writer/Reader (currently only used to handle precompiled code) */
|
/* Object Writer/Reader (currently only used to handle precompiled code) */
|
||||||
#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
|
#define JS_WRITE_OBJ_BYTECODE (1 << 0) /* allow function/module */
|
||||||
#define JS_WRITE_OBJ_BSWAP (1 << 1) /* byte swapped output */
|
#define JS_WRITE_OBJ_BSWAP (0) /* byte swapped output (obsolete, handled transparently) */
|
||||||
#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
|
#define JS_WRITE_OBJ_SAB (1 << 2) /* allow SharedArrayBuffer */
|
||||||
#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to
|
#define JS_WRITE_OBJ_REFERENCE (1 << 3) /* allow object references to
|
||||||
encode arbitrary object
|
encode arbitrary object
|
||||||
|
|
Loading…
Reference in a new issue