diff options
Diffstat (limited to 'src/load.c')
| -rw-r--r-- | src/load.c | 504 |
1 files changed, 266 insertions, 238 deletions
diff --git a/src/load.c b/src/load.c index 54b50b14d..bd0811743 100644 --- a/src/load.c +++ b/src/load.c @@ -7,50 +7,74 @@ #include <limits.h> #include <stdlib.h> #include <string.h> +#include <math.h> #include <mruby/dump.h> #include <mruby/irep.h> #include <mruby/proc.h> #include <mruby/string.h> #include <mruby/debug.h> #include <mruby/error.h> +#include <mruby/data.h> +#include <mruby/endian.h> #if SIZE_MAX < UINT32_MAX # error size_t must be at least 32 bits wide #endif -#define FLAG_BYTEORDER_BIG 2 -#define FLAG_BYTEORDER_LIL 4 -#define FLAG_BYTEORDER_NATIVE 8 #define FLAG_SRC_MALLOC 1 #define FLAG_SRC_STATIC 0 #define SIZE_ERROR_MUL(nmemb, size) ((size_t)(nmemb) > SIZE_MAX / (size)) -static size_t -skip_padding(const uint8_t *buf) -{ - const size_t align = MRB_DUMP_ALIGNMENT; - return -(intptr_t)buf & (align-1); -} +#define DEFINE_READ_IREP_FUNC(funcdecl, basecall) \ + funcdecl \ + { \ + int ai = mrb_gc_arena_save(mrb); \ + struct RProc *proc = basecall; \ + struct mrb_irep *irep = (mrb_irep*)(proc ? proc->body.irep : NULL); \ + if (irep) proc->body.irep = NULL; \ + mrb_gc_arena_restore(mrb, ai); \ + return irep; \ + } -static size_t -offset_crc_body(void) +#ifndef MRB_NO_FLOAT +static double +str_to_double(mrb_state *mrb, const char *p) { - struct rite_binary_header header; - return ((uint8_t *)header.binary_crc - (uint8_t *)&header) + sizeof(header.binary_crc); + /* dump IEEE754 little endian binary */ + union { + char s[sizeof(double)]; + double f; + } u; + + if (littleendian) { + memcpy(u.s, p, sizeof(double)); + } + else { + size_t i; + for (i=0; i<sizeof(double); i++) { + u.s[i] = p[sizeof(double)-i-1]; + } + } + return u.f; } +#endif -static mrb_irep* -read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) +static mrb_bool +read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags, mrb_irep **irepp) { int i; const uint8_t *src = bin; ptrdiff_t diff; uint16_t tt, pool_data_len, snl; int plen; + mrb_pool_value *pool; + mrb_sym *syms; int ai = mrb_gc_arena_save(mrb); mrb_irep *irep = mrb_add_irep(mrb); + *irepp = irep; + /* skip record size */ src += sizeof(uint32_t); @@ -63,237 +87,213 @@ read_irep_record_1(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flag src += sizeof(uint16_t); /* number of child irep */ - irep->rlen = (size_t)bin_to_uint16(src); + irep->rlen = (uint8_t)bin_to_uint16(src); src += sizeof(uint16_t); /* Binary Data Section */ - /* ISEQ BLOCK */ - irep->ilen = (uint16_t)bin_to_uint32(src); - src += sizeof(uint32_t); - src += skip_padding(src); + /* ISEQ BLOCK (and CATCH HANDLER TABLE BLOCK) */ + irep->clen = bin_to_uint16(src); /* number of catch handler */ + src += sizeof(uint16_t); + irep->ilen = bin_to_uint16(src); + src += sizeof(uint16_t); if (irep->ilen > 0) { + size_t data_len = sizeof(mrb_code) * irep->ilen + + sizeof(struct mrb_irep_catch_handler) * irep->clen; + mrb_static_assert1(sizeof(struct mrb_irep_catch_handler) == 13); if (SIZE_ERROR_MUL(irep->ilen, sizeof(mrb_code))) { - return NULL; + return FALSE; } - if ((flags & FLAG_SRC_MALLOC) == 0 && - (flags & FLAG_BYTEORDER_NATIVE)) { + if ((flags & FLAG_SRC_MALLOC) == 0) { irep->iseq = (mrb_code*)src; - src += sizeof(mrb_code) * irep->ilen; irep->flags |= MRB_ISEQ_NO_FREE; } else { - irep->iseq = (mrb_code *)mrb_malloc(mrb, sizeof(mrb_code) * irep->ilen); - if (flags & FLAG_BYTEORDER_NATIVE) { - memcpy(irep->iseq, src, sizeof(uint32_t) * irep->ilen); - src += sizeof(uint32_t) * irep->ilen; - } - else if (flags & FLAG_BYTEORDER_BIG) { - for (i = 0; i < irep->ilen; i++) { - irep->iseq[i] = (mrb_code)bin_to_uint32(src); /* iseq */ - src += sizeof(uint32_t); - } - } - else { - for (i = 0; i < irep->ilen; i++) { - irep->iseq[i] = (mrb_code)bin_to_uint32l(src); /* iseq */ - src += sizeof(uint32_t); - } - } + void *buf = mrb_malloc(mrb, data_len); + irep->iseq = (mrb_code *)buf; + memcpy(buf, src, data_len); } + src += data_len; } /* POOL BLOCK */ - plen = bin_to_uint32(src); /* number of pool */ - src += sizeof(uint32_t); + plen = bin_to_uint16(src); /* number of pool */ + src += sizeof(uint16_t); if (plen > 0) { if (SIZE_ERROR_MUL(plen, sizeof(mrb_value))) { - return NULL; + return FALSE; } - irep->pool = (mrb_value*)mrb_malloc(mrb, sizeof(mrb_value) * plen); + irep->pool = pool = (mrb_pool_value*)mrb_calloc(mrb, sizeof(mrb_pool_value), plen); for (i = 0; i < plen; i++) { - mrb_value s; + mrb_bool st = (flags & FLAG_SRC_MALLOC)==0; tt = *src++; /* pool TT */ - pool_data_len = bin_to_uint16(src); /* pool data length */ - src += sizeof(uint16_t); - if (flags & FLAG_SRC_MALLOC) { - s = mrb_str_new(mrb, (char *)src, pool_data_len); - } - else { - s = mrb_str_new_static(mrb, (char *)src, pool_data_len); - } - src += pool_data_len; switch (tt) { /* pool data */ - case IREP_TT_FIXNUM: { - mrb_value num = mrb_str_to_inum(mrb, s, 10, FALSE); -#ifdef MRB_WITHOUT_FLOAT - irep->pool[i] = num; + case IREP_TT_INT32: + { + mrb_int v = (int32_t)bin_to_uint32(src); + src += sizeof(uint32_t); +#ifdef MRB_64BIT + pool[i].tt = IREP_TT_INT64; + pool[i].u.i64 = (int64_t)v; #else - irep->pool[i] = mrb_float_p(num)? mrb_float_pool(mrb, mrb_float(num)) : num; + pool[i].tt = IREP_TT_INT32; + pool[i].u.i32 = v; #endif } break; + case IREP_TT_INT64: +#ifdef MRB_INT64 + { + uint64_t i64 = bin_to_uint32(src); + src += sizeof(uint32_t); + i64 <<= 32; + i64 |= bin_to_uint32(src); + src += sizeof(uint32_t); + pool[i].tt = tt; + pool[i].u.i64 = (int64_t)i64; + } + break; +#else + return FALSE; +#endif + + case IREP_TT_BIGINT: + pool_data_len = bin_to_uint8(src); /* pool data length */ + src += sizeof(uint8_t); + { + char *p; + pool[i].tt = IREP_TT_BIGINT; + p = (char*)mrb_malloc(mrb, pool_data_len+2); + memcpy(p, src, pool_data_len+2); + pool[i].u.str = (const char*)p; + } + src += pool_data_len + 2; + break; -#ifndef MRB_WITHOUT_FLOAT case IREP_TT_FLOAT: - irep->pool[i] = mrb_float_pool(mrb, mrb_str_to_dbl(mrb, s, FALSE)); +#ifndef MRB_NO_FLOAT + pool[i].tt = tt; + pool[i].u.f = str_to_double(mrb, (const char*)src); + src += sizeof(double); break; +#else + return FALSE; /* MRB_NO_FLOAT */ #endif - case IREP_TT_STRING: - irep->pool[i] = mrb_str_pool(mrb, s); + case IREP_TT_STR: + pool_data_len = bin_to_uint16(src); /* pool data length */ + src += sizeof(uint16_t); + if (st) { + pool[i].tt = (pool_data_len<<2) | IREP_TT_SSTR; + pool[i].u.str = (const char*)src; + } + else { + char *p; + pool[i].tt = (pool_data_len<<2) | IREP_TT_STR; + p = (char*)mrb_malloc(mrb, pool_data_len+1); + memcpy(p, src, pool_data_len+1); + pool[i].u.str = (const char*)p; + } + src += pool_data_len + 1; break; default: /* should not happen */ - irep->pool[i] = mrb_nil_value(); - break; + return FALSE; } - irep->plen++; - mrb_gc_arena_restore(mrb, ai); + irep->plen = i+1; } } /* SYMS BLOCK */ - irep->slen = (uint16_t)bin_to_uint32(src); /* syms length */ - src += sizeof(uint32_t); + irep->slen = bin_to_uint16(src); /* syms length */ + src += sizeof(uint16_t); if (irep->slen > 0) { if (SIZE_ERROR_MUL(irep->slen, sizeof(mrb_sym))) { - return NULL; + return FALSE; } - irep->syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen); + irep->syms = syms = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * irep->slen); for (i = 0; i < irep->slen; i++) { snl = bin_to_uint16(src); /* symbol name length */ src += sizeof(uint16_t); if (snl == MRB_DUMP_NULL_SYM_LEN) { - irep->syms[i] = 0; + syms[i] = 0; continue; } if (flags & FLAG_SRC_MALLOC) { - irep->syms[i] = mrb_intern(mrb, (char *)src, snl); + syms[i] = mrb_intern(mrb, (char *)src, snl); } else { - irep->syms[i] = mrb_intern_static(mrb, (char *)src, snl); + syms[i] = mrb_intern_static(mrb, (char *)src, snl); } src += snl + 1; - mrb_gc_arena_restore(mrb, ai); } } - irep->reps = (mrb_irep**)mrb_malloc(mrb, sizeof(mrb_irep*)*irep->rlen); - diff = src - bin; mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); *len = (size_t)diff; - return irep; + return TRUE; } -static mrb_irep* -read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags) +static mrb_bool +read_irep_record(mrb_state *mrb, const uint8_t *bin, size_t *len, uint8_t flags, mrb_irep **irepp) { - mrb_irep *irep = read_irep_record_1(mrb, bin, len, flags); + int ai = mrb_gc_arena_save(mrb); + mrb_bool readsuccess = read_irep_record_1(mrb, bin, len, flags, irepp); + mrb_irep **reps; int i; - if (irep == NULL) { - return NULL; + mrb_gc_arena_restore(mrb, ai); + if (!readsuccess) { + return FALSE; } + reps = (mrb_irep**)mrb_calloc(mrb, (*irepp)->rlen, sizeof(mrb_irep*)); + (*irepp)->reps = (const mrb_irep**)reps; + bin += *len; - for (i=0; i<irep->rlen; i++) { + for (i=0; i<(*irepp)->rlen; i++) { size_t rlen; - irep->reps[i] = read_irep_record(mrb, bin, &rlen, flags); - if (irep->reps[i] == NULL) { - return NULL; + readsuccess = read_irep_record(mrb, bin, &rlen, flags, &reps[i]); + mrb_gc_arena_restore(mrb, ai); + if (!readsuccess) { + return FALSE; } bin += rlen; *len += rlen; } - return irep; + + return TRUE; } static mrb_irep* -read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags) +read_section_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags, struct RProc **proc) { size_t len; - bin += sizeof(struct rite_section_irep_header); - return read_irep_record(mrb, bin, &len, flags); -} + /* + * This proc object keeps all the data in progress to avoid memory leaks + * if something goes wrong while reading irep. + */ + *proc = mrb_proc_new(mrb, NULL); -static int -read_lineno_record_1(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *len) -{ - size_t i, fname_len, niseq; - char *fname; - uint16_t *lines; - - *len = 0; - bin += sizeof(uint32_t); /* record size */ - *len += sizeof(uint32_t); - fname_len = bin_to_uint16(bin); - bin += sizeof(uint16_t); - *len += sizeof(uint16_t); - fname = (char *)mrb_malloc(mrb, fname_len + 1); - memcpy(fname, bin, fname_len); - fname[fname_len] = '\0'; - bin += fname_len; - *len += fname_len; - - niseq = (size_t)bin_to_uint32(bin); - bin += sizeof(uint32_t); /* niseq */ - *len += sizeof(uint32_t); - - if (SIZE_ERROR_MUL(niseq, sizeof(uint16_t))) { - return MRB_DUMP_GENERAL_FAILURE; - } - lines = (uint16_t *)mrb_malloc(mrb, niseq * sizeof(uint16_t)); - for (i = 0; i < niseq; i++) { - lines[i] = bin_to_uint16(bin); - bin += sizeof(uint16_t); /* niseq */ - *len += sizeof(uint16_t); + mrb_irep **irepp = (mrb_irep**)&(*proc)->body.irep; + bin += sizeof(struct rite_section_irep_header); + if (read_irep_record(mrb, bin, &len, flags, irepp)) { + return *irepp; } - - irep->filename = fname; - irep->lines = lines; - return MRB_DUMP_OK; -} - -static int -read_lineno_record(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep, size_t *lenp) -{ - int result = read_lineno_record_1(mrb, bin, irep, lenp); - int i; - - if (result != MRB_DUMP_OK) return result; - for (i = 0; i < irep->rlen; i++) { - size_t len; - - result = read_lineno_record(mrb, bin, irep->reps[i], &len); - if (result != MRB_DUMP_OK) break; - bin += len; - *lenp += len; + else { + return NULL; } - return result; -} - -static int -read_section_lineno(mrb_state *mrb, const uint8_t *bin, mrb_irep *irep) -{ - size_t len; - - len = 0; - bin += sizeof(struct rite_section_lineno_header); - - /* Read Binary Data Section */ - return read_lineno_record(mrb, bin, irep, &len); } static int @@ -304,26 +304,26 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * size_t record_size; uint16_t f_idx; int i; + mrb_irep_debug_info *debug; if (irep->debug_info) { return MRB_DUMP_INVALID_IREP; } - irep->debug_info = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); - irep->debug_info->pc_count = (uint32_t)irep->ilen; + irep->debug_info = debug = (mrb_irep_debug_info*)mrb_calloc(mrb, 1, sizeof(mrb_irep_debug_info)); + debug->pc_count = (uint32_t)irep->ilen; record_size = (size_t)bin_to_uint32(bin); bin += sizeof(uint32_t); - irep->debug_info->flen = bin_to_uint16(bin); - irep->debug_info->files = (mrb_irep_debug_info_file**)mrb_malloc(mrb, sizeof(mrb_irep_debug_info*) * irep->debug_info->flen); + debug->flen = bin_to_uint16(bin); + debug->files = (mrb_irep_debug_info_file**)mrb_calloc(mrb, irep->debug_info->flen, sizeof(mrb_irep_debug_info*)); bin += sizeof(uint16_t); - for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + for (f_idx = 0; f_idx < debug->flen; ++f_idx) { mrb_irep_debug_info_file *file; uint16_t filename_idx; - mrb_int len; - file = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*file)); - irep->debug_info->files[f_idx] = file; + file = (mrb_irep_debug_info_file *)mrb_calloc(mrb, 1, sizeof(*file)); + debug->files[f_idx] = file; file->start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); @@ -333,8 +333,6 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * bin += sizeof(uint16_t); mrb_assert(filename_idx < filenames_len); file->filename_sym = filenames[filename_idx]; - len = 0; - file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len); file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t); @@ -354,8 +352,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * case mrb_debug_line_flat_map: { uint32_t l; - file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_malloc( - mrb, sizeof(mrb_irep_debug_info_line) * (size_t)(file->line_entry_count)); + file->lines.flat_map = (mrb_irep_debug_info_line*)mrb_calloc( + mrb, (size_t)(file->line_entry_count), sizeof(mrb_irep_debug_info_line)); for (l = 0; l < file->line_entry_count; ++l) { file->lines.flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); @@ -364,6 +362,12 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * } } break; + case mrb_debug_line_packed_map: { + file->lines.packed_map = (uint8_t*)mrb_calloc(mrb, 1, (size_t)file->line_entry_count); + memcpy(file->lines.packed_map, bin, file->line_entry_count); + bin += file->line_entry_count; + } break; + default: return MRB_DUMP_GENERAL_FAILURE; } } @@ -379,7 +383,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, size_t * size_t len; int ret; - ret = read_debug_record(mrb, bin, irep->reps[i], &len, filenames, filenames_len); + ret = read_debug_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, filenames, filenames_len); if (ret != MRB_DUMP_OK) return ret; bin += len; } @@ -402,6 +406,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t int result; uint16_t filenames_len; mrb_sym *filenames; + mrb_value filenames_obj; bin = start; header = (struct rite_section_debug_header *)bin; @@ -409,7 +414,8 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t filenames_len = bin_to_uint16(bin); bin += sizeof(uint16_t); - filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)filenames_len); + filenames_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)filenames_len); + filenames = (mrb_sym*)RSTRING_PTR(filenames_obj); for (i = 0; i < filenames_len; ++i) { uint16_t f_len = bin_to_uint16(bin); bin += sizeof(uint16_t); @@ -433,7 +439,7 @@ read_section_debug(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t } debug_exit: - mrb_free(mrb, filenames); + mrb_str_resize(mrb, filenames_obj, 0); return result; } @@ -441,34 +447,31 @@ static int read_lv_record(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, size_t *record_len, mrb_sym const *syms, uint32_t syms_len) { const uint8_t *bin = start; + mrb_sym *lv; ptrdiff_t diff; int i; - irep->lv = (struct mrb_locals*)mrb_malloc(mrb, sizeof(struct mrb_locals) * (irep->nlocals - 1)); + irep->lv = lv = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (irep->nlocals - 1)); - for (i = 0; i + 1< irep->nlocals; ++i) { + for (i = 0; i + 1 < irep->nlocals; ++i) { uint16_t const sym_idx = bin_to_uint16(bin); bin += sizeof(uint16_t); if (sym_idx == RITE_LV_NULL_MARK) { - irep->lv[i].name = 0; - irep->lv[i].r = 0; + lv[i] = 0; } else { if (sym_idx >= syms_len) { return MRB_DUMP_GENERAL_FAILURE; } - irep->lv[i].name = syms[sym_idx]; - - irep->lv[i].r = bin_to_uint16(bin); + lv[i] = syms[sym_idx]; } - bin += sizeof(uint16_t); } for (i = 0; i < irep->rlen; ++i) { size_t len; int ret; - ret = read_lv_record(mrb, bin, irep->reps[i], &len, syms, syms_len); + ret = read_lv_record(mrb, bin, (mrb_irep*)irep->reps[i], &len, syms, syms_len); if (ret != MRB_DUMP_OK) return ret; bin += len; } @@ -491,6 +494,7 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl int result; uint32_t syms_len; mrb_sym *syms; + mrb_value syms_obj; mrb_sym (*intern_func)(mrb_state*, const char*, size_t) = (flags & FLAG_SRC_MALLOC)? mrb_intern : mrb_intern_static; @@ -500,7 +504,8 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl syms_len = bin_to_uint32(bin); bin += sizeof(uint32_t); - syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * (size_t)syms_len); + syms_obj = mrb_str_new(mrb, NULL, sizeof(mrb_sym) * (size_t)syms_len); + syms = (mrb_sym*)RSTRING_PTR(syms_obj); for (i = 0; i < syms_len; ++i) { uint16_t const str_len = bin_to_uint16(bin); bin += sizeof(uint16_t); @@ -520,77 +525,66 @@ read_section_lv(mrb_state *mrb, const uint8_t *start, mrb_irep *irep, uint8_t fl } lv_exit: - mrb_free(mrb, syms); + mrb_str_resize(mrb, syms_obj, 0); return result; } static int -read_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc, uint8_t *flags) +read_binary_header(const uint8_t *bin, size_t bufsize, size_t *bin_size, uint8_t *flags) { const struct rite_binary_header *header = (const struct rite_binary_header *)bin; - if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) == 0) { - if (bigendian_p()) - *flags |= FLAG_BYTEORDER_NATIVE; - else - *flags |= FLAG_BYTEORDER_BIG; + if (bufsize < sizeof(struct rite_binary_header)) { + return MRB_DUMP_READ_FAULT; } - else if (memcmp(header->binary_ident, RITE_BINARY_IDENT_LIL, sizeof(header->binary_ident)) == 0) { - if (bigendian_p()) - *flags |= FLAG_BYTEORDER_LIL; - else - *flags |= FLAG_BYTEORDER_NATIVE; - } - else { + + if (memcmp(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)) != 0) { return MRB_DUMP_INVALID_FILE_HEADER; } - if (crc) { - *crc = bin_to_uint16(header->binary_crc); + /* if major version is different, they are incompatible */ + if (memcmp(header->major_version, RITE_BINARY_MAJOR_VER, sizeof(header->major_version)) != 0) { + return MRB_DUMP_INVALID_FILE_HEADER; } + /* if minor version is different, we can accept the older version */ + if (memcmp(header->minor_version, RITE_BINARY_MINOR_VER, sizeof(header->minor_version)) > 0) { + return MRB_DUMP_INVALID_FILE_HEADER; + } + *bin_size = (size_t)bin_to_uint32(header->binary_size); + if (bufsize < *bin_size) { + return MRB_DUMP_READ_FAULT; + } + return MRB_DUMP_OK; } -static mrb_irep* -read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags) +static struct RProc* +read_irep(mrb_state *mrb, const uint8_t *bin, size_t bufsize, uint8_t flags) { int result; + struct RProc *proc = NULL; mrb_irep *irep = NULL; const struct rite_section_header *section_header; - uint16_t crc; size_t bin_size = 0; - size_t n; if ((mrb == NULL) || (bin == NULL)) { return NULL; } - result = read_binary_header(bin, &bin_size, &crc, &flags); + result = read_binary_header(bin, bufsize, &bin_size, &flags); if (result != MRB_DUMP_OK) { return NULL; } - n = offset_crc_body(); - if (crc != calc_crc_16_ccitt(bin + n, bin_size - n, 0)) { - return NULL; - } - bin += sizeof(struct rite_binary_header); do { section_header = (const struct rite_section_header *)bin; if (memcmp(section_header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(section_header->section_ident)) == 0) { - irep = read_section_irep(mrb, bin, flags); + irep = read_section_irep(mrb, bin, flags, &proc); if (!irep) return NULL; } - else if (memcmp(section_header->section_ident, RITE_SECTION_LINENO_IDENT, sizeof(section_header->section_ident)) == 0) { - if (!irep) return NULL; /* corrupted data */ - result = read_section_lineno(mrb, bin, irep); - if (result < MRB_DUMP_OK) { - return NULL; - } - } else if (memcmp(section_header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(section_header->section_ident)) == 0) { if (!irep) return NULL; /* corrupted data */ result = read_section_debug(mrb, bin, irep, flags); @@ -608,43 +602,53 @@ read_irep(mrb_state *mrb, const uint8_t *bin, uint8_t flags) bin += bin_to_uint32(section_header->section_size); } while (memcmp(section_header->section_ident, RITE_BINARY_EOF, sizeof(section_header->section_ident)) != 0); - return irep; + return proc; } -mrb_irep* -mrb_read_irep(mrb_state *mrb, const uint8_t *bin) +static struct RProc* +mrb_proc_read_irep(mrb_state *mrb, const uint8_t *bin) { -#ifdef MRB_USE_ETEXT_EDATA +#if defined(MRB_USE_LINK_TIME_RO_DATA_P) || defined(MRB_USE_CUSTOM_RO_DATA_P) uint8_t flags = mrb_ro_data_p((char*)bin) ? FLAG_SRC_STATIC : FLAG_SRC_MALLOC; #else uint8_t flags = FLAG_SRC_STATIC; #endif - return read_irep(mrb, bin, flags); + return read_irep(mrb, bin, (size_t)-1, flags); +} + +DEFINE_READ_IREP_FUNC( + mrb_irep *mrb_read_irep(mrb_state *mrb, const uint8_t *bin), + mrb_proc_read_irep(mrb, bin)) + +static struct RProc* +mrb_proc_read_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize) +{ + return read_irep(mrb, (const uint8_t *)buf, bufsize, FLAG_SRC_MALLOC); } +DEFINE_READ_IREP_FUNC( + MRB_API mrb_irep *mrb_read_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize), + mrb_proc_read_irep_buf(mrb, buf, bufsize)) + void mrb_exc_set(mrb_state *mrb, mrb_value exc); static void irep_error(mrb_state *mrb) { - mrb_exc_set(mrb, mrb_exc_new_str_lit(mrb, E_SCRIPT_ERROR, "irep load error")); + mrb_exc_set(mrb, mrb_exc_new_lit(mrb, E_SCRIPT_ERROR, "irep load error")); } void mrb_codedump_all(mrb_state*, struct RProc*); static mrb_value -load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c) +load_irep(mrb_state *mrb, struct RProc *proc, mrbc_context *c) { - struct RProc *proc; - - if (!irep) { + if (!proc || !proc->body.irep) { irep_error(mrb); return mrb_nil_value(); } - proc = mrb_proc_new(mrb, irep); proc->c = NULL; - mrb_irep_decref(mrb, irep); if (c && c->dump_result) mrb_codedump_all(mrb, proc); if (c && c->no_exec) return mrb_obj_value(proc); return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0); @@ -653,7 +657,15 @@ load_irep(mrb_state *mrb, mrb_irep *irep, mrbc_context *c) MRB_API mrb_value mrb_load_irep_cxt(mrb_state *mrb, const uint8_t *bin, mrbc_context *c) { - return load_irep(mrb, mrb_read_irep(mrb, bin), c); + struct RProc *proc = mrb_proc_read_irep(mrb, bin); + if (!proc) return mrb_undef_value(); + return load_irep(mrb, proc, c); +} + +MRB_API mrb_value +mrb_load_irep_buf_cxt(mrb_state *mrb, const void *buf, size_t bufsize, mrbc_context *c) +{ + return load_irep(mrb, mrb_proc_read_irep_buf(mrb, buf, bufsize), c); } MRB_API mrb_value @@ -662,12 +674,24 @@ mrb_load_irep(mrb_state *mrb, const uint8_t *bin) return mrb_load_irep_cxt(mrb, bin, NULL); } -#ifndef MRB_DISABLE_STDIO +MRB_API mrb_value +mrb_load_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize) +{ + return mrb_load_irep_buf_cxt(mrb, buf, bufsize, NULL); +} -mrb_irep* -mrb_read_irep_file(mrb_state *mrb, FILE* fp) +MRB_API mrb_value +mrb_load_proc(mrb_state *mrb, const struct RProc *proc) { - mrb_irep *irep = NULL; + return mrb_top_run(mrb, proc, mrb_top_self(mrb), 0); +} + +#ifndef MRB_NO_STDIO + +static struct RProc* +mrb_proc_read_irep_file(mrb_state *mrb, FILE *fp) +{ + struct RProc *proc = NULL; uint8_t *buf; const size_t header_size = sizeof(struct rite_binary_header); size_t buf_size = 0; @@ -682,7 +706,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) if (fread(buf, header_size, 1, fp) == 0) { goto irep_exit; } - result = read_binary_header(buf, &buf_size, NULL, &flags); + result = read_binary_header(buf, (size_t)-1, &buf_size, &flags); if (result != MRB_DUMP_OK || buf_size <= header_size) { goto irep_exit; } @@ -691,17 +715,21 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) if (fread(buf+header_size, buf_size-header_size, 1, fp) == 0) { goto irep_exit; } - irep = read_irep(mrb, buf, FLAG_SRC_MALLOC); + proc = read_irep(mrb, buf, (size_t)-1, FLAG_SRC_MALLOC); irep_exit: mrb_free(mrb, buf); - return irep; + return proc; } +DEFINE_READ_IREP_FUNC( + mrb_irep *mrb_read_irep_file(mrb_state *mrb, FILE *fp), + mrb_proc_read_irep_file(mrb, fp)) + MRB_API mrb_value mrb_load_irep_file_cxt(mrb_state *mrb, FILE* fp, mrbc_context *c) { - return load_irep(mrb, mrb_read_irep_file(mrb, fp), c); + return load_irep(mrb, mrb_proc_read_irep_file(mrb, fp), c); } MRB_API mrb_value @@ -709,4 +737,4 @@ mrb_load_irep_file(mrb_state *mrb, FILE* fp) { return mrb_load_irep_file_cxt(mrb, fp, NULL); } -#endif /* MRB_DISABLE_STDIO */ +#endif /* MRB_NO_STDIO */ |
