diff options
Diffstat (limited to 'src/dump.c')
| -rw-r--r-- | src/dump.c | 789 |
1 files changed, 425 insertions, 364 deletions
diff --git a/src/dump.c b/src/dump.c index beaed7e7d..0b4200795 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1,19 +1,22 @@ /* -** dump.c - mruby binary dumper (mrbc binary format) +** cdump.c - mruby binary dumper (in C) ** ** See Copyright Notice in mruby.h */ -#include <ctype.h> #include <string.h> #include <limits.h> -#include "mruby/dump.h" -#include "mruby/string.h" -#include "mruby/irep.h" -#include "mruby/numeric.h" -#include "mruby/debug.h" +#include <math.h> +#include <mruby/dump.h> +#include <mruby/string.h> +#include <mruby/irep.h> +#include <mruby/debug.h> + +#ifndef MRB_NO_FLOAT +#include <mruby/endian.h> +#endif -static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); +static size_t get_irep_record_size_1(mrb_state *mrb, const mrb_irep *irep); #if UINT32_MAX > SIZE_MAX # error This code cannot be built on your environment. @@ -31,11 +34,11 @@ get_irep_header_size(mrb_state *mrb) } static ptrdiff_t -write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_irep_header(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; - cur += uint32_to_bin(get_irep_record_size_1(mrb, irep), cur); /* record size */ + cur += uint32_to_bin((uint32_t)get_irep_record_size_1(mrb, irep), cur); /* record size */ cur += uint16_to_bin((uint16_t)irep->nlocals, cur); /* number of local variable */ cur += uint16_to_bin((uint16_t)irep->nregs, cur); /* number of register variable */ cur += uint16_to_bin((uint16_t)irep->rlen, cur); /* number of child irep */ @@ -43,75 +46,112 @@ write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) return cur - buf; } - static size_t -get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) +get_iseq_block_size(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; - size += sizeof(uint32_t); /* ilen */ - size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ + size += sizeof(uint16_t); /* clen */ + size += sizeof(uint16_t); /* ilen */ + size += irep->ilen * sizeof(mrb_code); /* iseq(n) */ + size += irep->clen * sizeof(struct mrb_irep_catch_handler); return size; } static ptrdiff_t -write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_iseq_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf, uint8_t flags) { uint8_t *cur = buf; - uint32_t iseq_no; + size_t seqlen = irep->ilen * sizeof(mrb_code) + + irep->clen * sizeof(struct mrb_irep_catch_handler); - cur += uint32_to_bin(irep->ilen, cur); /* number of opcode */ - for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { - cur += uint32_to_bin(irep->iseq[iseq_no], cur); /* opcode */ - } + cur += uint16_to_bin(irep->clen, cur); /* number of catch handlers */ + cur += uint16_to_bin(irep->ilen, cur); /* number of opcode */ + memcpy(cur, irep->iseq, seqlen); + cur += seqlen; return cur - buf; } +#ifndef MRB_NO_FLOAT +static void +dump_float(mrb_state *mrb, uint8_t *buf, mrb_float f) +{ + /* dump IEEE754 binary in little endian */ + union { + double f; + char s[sizeof(double)]; + } u = {.f = (double)f}; + + if (littleendian) { + memcpy(buf, u.s, sizeof(double)); + } + else { + size_t i; + + for (i=0; i<sizeof(double); i++) { + buf[i] = u.s[sizeof(double)-i-1]; + } + } +} +#endif static size_t -get_pool_block_size(mrb_state *mrb, mrb_irep *irep) +get_pool_block_size(mrb_state *mrb, const mrb_irep *irep) { + int pool_no; size_t size = 0; - size_t pool_no; - mrb_value str; - char buf[32]; - size += sizeof(uint32_t); /* plen */ - size += irep->plen * (sizeof(uint8_t) + sizeof(uint16_t)); /* len(n) */ + size += sizeof(uint16_t); /* plen */ + size += irep->plen * sizeof(uint8_t); /* len(n) */ for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - switch (mrb_type(irep->pool[pool_no])) { - case MRB_TT_FIXNUM: - str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); + switch (irep->pool[pool_no].tt) { + case IREP_TT_INT64: +#ifdef MRB_64BIT { - mrb_int len = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; + int64_t i = irep->pool[pool_no].u.i64; + + if (i < INT32_MIN || INT32_MAX < i) + size += 8; + else + size += 4; } break; +#else + /* fall through */ +#endif + case IREP_TT_INT32: + size += 4; /* 32bits = 4bytes */ + break; - case MRB_TT_FLOAT: + case IREP_TT_BIGINT: { - int len; - len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); + mrb_int len = irep->pool[pool_no].u.str[0]; mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; + size += sizeof(uint8_t); + size += (size_t)len+2; } break; - case MRB_TT_STRING: + case IREP_TT_FLOAT: +#ifndef MRB_NO_FLOAT { - mrb_int len = RSTRING_LEN(irep->pool[pool_no]); - mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); - size += (size_t)len; + size += sizeof(double); } +#endif break; - default: + default: /* packed IREP_TT_STRING */ + { + mrb_int len = irep->pool[pool_no].tt >> 2; /* unpack length */ + mrb_assert_int_fit(mrb_int, len, size_t, SIZE_MAX); + size += sizeof(uint16_t); + size += (size_t)len+1; + } break; } mrb_gc_arena_restore(mrb, ai); @@ -121,84 +161,89 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) } static ptrdiff_t -write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_pool_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) { - size_t pool_no; + int pool_no; uint8_t *cur = buf; - uint16_t len; - mrb_value str; - const char *char_ptr; - char char_buf[30]; + mrb_int len; + const char *ptr; - cur += uint32_to_bin(irep->plen, cur); /* number of pool */ + cur += uint16_to_bin(irep->plen, cur); /* number of pool */ for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - switch (mrb_type(irep->pool[pool_no])) { - case MRB_TT_FIXNUM: - cur += uint8_to_bin(IREP_TT_FIXNUM, cur); /* data type */ - str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); - char_ptr = RSTRING_PTR(str); + switch (irep->pool[pool_no].tt) { +#ifdef MRB_64BIT + case IREP_TT_INT64: { - mrb_int tlen; - - tlen = RSTRING_LEN(str); - mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX); - len = (uint16_t)tlen; + int64_t i = irep->pool[pool_no].u.i64; + if (i < INT32_MIN || INT32_MAX < i) { + cur += uint8_to_bin(IREP_TT_INT64, cur); /* data type */ + cur += uint32_to_bin((uint32_t)((i>>32) & 0xffffffff), cur); /* i64 hi */ + cur += uint32_to_bin((uint32_t)((i ) & 0xffffffff), cur); /* i64 lo */ + } + else { + cur += uint8_to_bin(IREP_TT_INT32, cur); /* data type */ + cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */ + } } break; +#endif + case IREP_TT_INT32: + cur += uint8_to_bin(IREP_TT_INT32, cur); /* data type */ + cur += uint32_to_bin(irep->pool[pool_no].u.i32, cur); /* i32 */ + break; - case MRB_TT_FLOAT: - cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ - { - int tlen; - tlen = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); - mrb_assert_int_fit(int, tlen, uint16_t, UINT16_MAX); - len = (uint16_t)tlen; - } - char_ptr = &char_buf[0]; + case IREP_TT_BIGINT: + cur += uint8_to_bin(IREP_TT_BIGINT, cur); /* data type */ + len = irep->pool[pool_no].u.str[0]; + memcpy(cur, irep->pool[pool_no].u.str, (size_t)len+2); + cur += len+2; + *cur++ = '\0'; break; - case MRB_TT_STRING: - cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ - char_ptr = RSTRING_PTR(irep->pool[pool_no]); + case IREP_TT_FLOAT: + cur += uint8_to_bin(IREP_TT_FLOAT, cur); /* data type */ +#ifndef MRB_NO_FLOAT { - mrb_int tlen; - - tlen = RSTRING_LEN(irep->pool[pool_no]); - mrb_assert_int_fit(mrb_int, tlen, uint16_t, UINT16_MAX); - len = (uint16_t)tlen; + dump_float(mrb, cur,irep->pool[pool_no].u.f); + cur += sizeof(double); } +#else + cur += uint16_to_bin(0, cur); /* zero length */ +#endif break; - default: - continue; + default: /* string */ + cur += uint8_to_bin(IREP_TT_STR, cur); /* data type */ + ptr = irep->pool[pool_no].u.str; + len = irep->pool[pool_no].tt>>2; + mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX); + cur += uint16_to_bin((uint16_t)len, cur); /* data length */ + memcpy(cur, ptr, (size_t)len); + cur += len; + *cur++ = '\0'; + break; } - - cur += uint16_to_bin(len, cur); /* data length */ - memcpy(cur, char_ptr, (size_t)len); - cur += len; - mrb_gc_arena_restore(mrb, ai); } return cur - buf; } - static size_t -get_syms_block_size(mrb_state *mrb, mrb_irep *irep) +get_syms_block_size(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; - uint32_t sym_no; + int sym_no; mrb_int len; - size += sizeof(uint32_t); /* slen */ + size += sizeof(uint16_t); /* slen */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { size += sizeof(uint16_t); /* snl(n) */ if (irep->syms[sym_no] != 0) { - mrb_sym2name_len(mrb, irep->syms[sym_no], &len); + mrb_sym_name_len(mrb, irep->syms[sym_no], &len); size += len + 1; /* sn(n) + null char */ } } @@ -207,19 +252,19 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep) } static ptrdiff_t -write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) +write_syms_block(mrb_state *mrb, const mrb_irep *irep, uint8_t *buf) { - uint32_t sym_no; + int sym_no; uint8_t *cur = buf; const char *name; - cur += uint32_to_bin(irep->slen, cur); /* number of symbol */ + cur += uint16_to_bin(irep->slen, cur); /* number of symbol */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { if (irep->syms[sym_no] != 0) { mrb_int len; - name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); + name = mrb_sym_name_len(mrb, irep->syms[sym_no], &len); mrb_assert_int_fit(mrb_int, len, uint16_t, UINT16_MAX); cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */ @@ -236,7 +281,7 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } static size_t -get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) +get_irep_record_size_1(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; @@ -248,11 +293,11 @@ get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) } static size_t -get_irep_record_size(mrb_state *mrb, mrb_irep *irep) +get_irep_record_size(mrb_state *mrb, const mrb_irep *irep) { size_t size = 0; - size_t irep_no; - + int irep_no; + size = get_irep_record_size_1(mrb, irep); for (irep_no = 0; irep_no < irep->rlen; irep_no++) { size += get_irep_record_size(mrb, irep->reps[irep_no]); @@ -261,23 +306,17 @@ get_irep_record_size(mrb_state *mrb, mrb_irep *irep) } static int -write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, size_t *irep_record_size) +write_irep_record(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, size_t *irep_record_size, uint8_t flags) { - uint32_t i; + int i; + uint8_t *src = bin; if (irep == NULL) { return MRB_DUMP_INVALID_IREP; } - *irep_record_size = get_irep_record_size_1(mrb, irep); - if (*irep_record_size == 0) { - return MRB_DUMP_GENERAL_FAILURE; - } - - memset(bin, 0, *irep_record_size); - bin += write_irep_header(mrb, irep, bin); - bin += write_iseq_block(mrb, irep, bin); + bin += write_iseq_block(mrb, irep, bin, flags); bin += write_pool_block(mrb, irep, bin); bin += write_syms_block(mrb, irep, bin); @@ -285,13 +324,13 @@ write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, size_t *irep_rec int result; size_t rsize; - result = write_irep_record(mrb, irep->reps[i], bin, &rsize); + result = write_irep_record(mrb, irep->reps[i], bin, &rsize, flags); if (result != MRB_DUMP_OK) { return result; } - *irep_record_size += rsize; bin += rsize; } + *irep_record_size = bin - src; return MRB_DUMP_OK; } @@ -300,7 +339,7 @@ write_footer(mrb_state *mrb, uint8_t *bin) { struct rite_binary_footer footer; - memcpy(footer.section_identify, RITE_BINARY_EOF, sizeof(footer.section_identify)); + memcpy(footer.section_ident, RITE_BINARY_EOF, sizeof(footer.section_ident)); uint32_to_bin(sizeof(struct rite_binary_footer), footer.section_size); memcpy(bin, &footer, sizeof(struct rite_binary_footer)); @@ -313,7 +352,7 @@ write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) { struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin; - memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify)); + memcpy(header->section_ident, RITE_SECTION_IREP_IDENT, sizeof(header->section_ident)); mrb_assert_int_fit(size_t, section_size, uint32_t, UINT32_MAX); uint32_to_bin((uint32_t)section_size, header->section_size); @@ -323,10 +362,9 @@ write_section_irep_header(mrb_state *mrb, size_t section_size, uint8_t *bin) } static int -write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) +write_section_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, size_t *len_p, uint8_t flags) { int result; - size_t section_size = 0; /* size of irep record */ size_t rsize = 0; uint8_t *cur = bin; @@ -335,136 +373,24 @@ write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) } cur += sizeof(struct rite_section_irep_header); - section_size += sizeof(struct rite_section_irep_header); - result = write_irep_record(mrb, irep, cur, &rsize); + result = write_irep_record(mrb, irep, cur, &rsize, flags); if (result != MRB_DUMP_OK) { return result; } - cur += rsize; - section_size += rsize; - write_section_irep_header(mrb, section_size, bin); - - return MRB_DUMP_OK; -} - -static int -write_section_lineno_header(mrb_state *mrb, size_t section_size, uint8_t *bin) -{ - struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; - - memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify)); - uint32_to_bin((uint32_t)section_size, header->section_size); + mrb_assert(rsize == get_irep_record_size(mrb, irep)); + *len_p = cur - bin + rsize; + write_section_irep_header(mrb, *len_p, bin); return MRB_DUMP_OK; } static size_t -get_lineno_record_size(mrb_state *mrb, mrb_irep *irep) -{ - size_t size = 0; - - size += sizeof(uint32_t); /* record size */ - size += sizeof(uint16_t); /* filename size */ - if (irep->filename) { - size += strlen(irep->filename); /* filename */ - } - size += sizeof(uint32_t); /* niseq */ - if (irep->lines) { - size += sizeof(uint16_t) * irep->ilen; /* lineno */ - } - - return size; -} - -static size_t -write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) -{ - uint8_t *cur = bin; - size_t iseq_no; - size_t filename_len; - ptrdiff_t diff; - - cur += sizeof(uint32_t); /* record size */ - - if (irep->filename) { - filename_len = strlen(irep->filename); - } else { - filename_len = 0; - } - mrb_assert_int_fit(size_t, filename_len, uint16_t, UINT16_MAX); - cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ - - if (filename_len) { - memcpy(cur, irep->filename, filename_len); - cur += filename_len; /* filename */ - } - - if (irep->lines) { - mrb_assert_int_fit(size_t, irep->ilen, uint32_t, UINT32_MAX); - cur += uint32_to_bin((uint32_t)(irep->ilen), cur); /* niseq */ - for (iseq_no = 0; iseq_no < irep->ilen; iseq_no++) { - cur += uint16_to_bin(irep->lines[iseq_no], cur); /* opcode */ - } - } - else { - cur += uint32_to_bin(0, cur); /* niseq */ - } - - diff = cur - bin; - mrb_assert_int_fit(ptrdiff_t, diff, uint32_t, UINT32_MAX); - - uint32_to_bin((uint32_t)diff, bin); /* record size */ - - mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); - return (size_t)diff; -} - -static size_t -write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) -{ - size_t i; - size_t rlen, size = 0; - - rlen = write_lineno_record_1(mrb, irep, bin); - bin += rlen; - size += rlen; - for (i=0; i<irep->rlen; i++) { - rlen = write_lineno_record(mrb, irep, bin); - bin += rlen; - size += rlen; - } - return size; -} - -static int -write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) -{ - size_t section_size = 0; - size_t rlen = 0; /* size of irep record */ - uint8_t *cur = bin; - - if (mrb == NULL || bin == NULL) { - return MRB_DUMP_INVALID_ARGUMENT; - } - - cur += sizeof(struct rite_section_lineno_header); - section_size += sizeof(struct rite_section_lineno_header); - - rlen = write_lineno_record(mrb, irep, cur); - section_size += rlen; - - write_section_lineno_header(mrb, section_size, bin); - - return MRB_DUMP_OK; -} - -static size_t -get_debug_record_size(mrb_state *mrb, mrb_irep *irep) +get_debug_record_size(mrb_state *mrb, const mrb_irep *irep) { size_t ret = 0; uint16_t f_idx; - size_t i; + int i; ret += sizeof(uint32_t); /* record size */ ret += sizeof(uint16_t); /* file count */ @@ -498,7 +424,7 @@ get_debug_record_size(mrb_state *mrb, mrb_irep *irep) } static int -find_filename_index(const mrb_sym *ary, uint16_t ary_len, mrb_sym s) +find_filename_index(const mrb_sym *ary, int ary_len, mrb_sym s) { int i; @@ -509,23 +435,19 @@ find_filename_index(const mrb_sym *ary, uint16_t ary_len, mrb_sym s) } static size_t -get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t *lp) +get_filename_table_size(mrb_state *mrb, const mrb_irep *irep, mrb_sym **fp, uint16_t *lp) { mrb_sym *filenames = *fp; - uint16_t tsize = 0; - uint32_t file_i; size_t size = 0; - mrb_irep_debug_info *di = irep->debug_info; + const mrb_irep_debug_info *di = irep->debug_info; + int i; - if (lp == NULL) { - lp = &tsize; - } - for (file_i = 0; file_i < di->flen; ++file_i) { + mrb_assert(lp); + for (i = 0; i < di->flen; ++i) { mrb_irep_debug_info_file *file; mrb_int filename_len; - size_t i; - file = di->files[file_i]; + file = di->files[i]; if (find_filename_index(filenames, *lp, file->filename_sym) == -1) { /* register filename */ *lp += 1; @@ -533,19 +455,18 @@ get_filename_table_size(mrb_state *mrb, mrb_irep *irep, mrb_sym **fp, uint16_t * filenames[*lp - 1] = file->filename_sym; /* filename */ - mrb_sym2name_len(mrb, file->filename_sym, &filename_len); + mrb_sym_name_len(mrb, file->filename_sym, &filename_len); size += sizeof(uint16_t) + (size_t)filename_len; } - for (i=0; i<irep->rlen; i++) { - size += get_filename_table_size(mrb, irep->reps[i], fp, lp); - filenames = *fp; - } + } + for (i=0; i<irep->rlen; i++) { + size += get_filename_table_size(mrb, irep->reps[i], fp, lp); } return size; } static size_t -write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) +write_debug_record_1(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { uint8_t *cur; uint16_t f_idx; @@ -592,18 +513,18 @@ write_debug_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const ret = cur - bin; mrb_assert_int_fit(ptrdiff_t, ret, uint32_t, UINT32_MAX); - uint32_to_bin(ret, bin); + uint32_to_bin((uint32_t)ret, bin); mrb_assert_int_fit(ptrdiff_t, ret, size_t, SIZE_MAX); return (size_t)ret; } static size_t -write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) +write_debug_record(mrb_state *mrb, const mrb_irep *irep, uint8_t *bin, mrb_sym const* filenames, uint16_t filenames_len) { size_t size, len; - size_t irep_no; - + int irep_no; + size = len = write_debug_record_1(mrb, irep, bin, filenames, filenames_len); bin += len; for (irep_no = 0; irep_no < irep->rlen; irep_no++) { @@ -616,50 +537,15 @@ write_debug_record(mrb_state *mrb, mrb_irep *irep, uint8_t *bin, mrb_sym const* return size; } -static size_t -write_filename_table(mrb_state *mrb, mrb_irep *irep, uint8_t **cp, mrb_sym **fp, uint16_t *lp) -{ - uint8_t *cur = *cp; - mrb_sym *filenames = *fp; - uint32_t file_i; - uint16_t fn_len; - size_t size = 0; - mrb_irep_debug_info *debug_info = irep->debug_info; - - for (file_i = 0; file_i < debug_info->flen; ++file_i) { - mrb_irep_debug_info_file *file = debug_info->files[file_i]; - if (find_filename_index(filenames, *lp, file->filename_sym) != -1) continue; - - /* register filename */ - *lp += 1; - *fp = filenames = (mrb_sym*)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp)); - filenames[*lp - 1] = file->filename_sym; - - /* filename */ - fn_len = (uint16_t)strlen(file->filename); - cur += uint16_to_bin(fn_len, cur); - memcpy(cur, file->filename, fn_len); - cur += fn_len; - - size += sizeof(uint16_t) + fn_len; - } - for (file_i=0; file_i<irep->rlen; file_i++) { - size += write_filename_table(mrb, irep->reps[file_i], &cur, fp, lp); - } - *cp = cur; - return size; -} - static int -write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) +write_section_debug(mrb_state *mrb, const mrb_irep *irep, uint8_t *cur, mrb_sym const *filenames, uint16_t filenames_len) { size_t section_size = 0; const uint8_t *bin = cur; struct rite_section_debug_header *header; - mrb_sym *filenames; - uint16_t filenames_len = 0; - uint8_t *filenames_len_out; size_t dlen; + uint16_t i; + char const *sym; mrb_int sym_len; if (mrb == NULL || cur == NULL) { return MRB_DUMP_INVALID_ARGUMENT; @@ -670,67 +556,222 @@ write_section_debug(mrb_state *mrb, mrb_irep *irep, uint8_t *cur) section_size += sizeof(struct rite_section_debug_header); /* filename table */ - filenames = (mrb_sym *)mrb_malloc(mrb, sizeof(mrb_sym) * 1); - filenames_len_out = cur; - cur += sizeof(uint16_t); + cur += uint16_to_bin(filenames_len, cur); section_size += sizeof(uint16_t); - section_size += write_filename_table(mrb, irep, &cur, &filenames, &filenames_len); - uint16_to_bin(filenames_len, filenames_len_out); + for (i = 0; i < filenames_len; ++i) { + sym = mrb_sym_name_len(mrb, filenames[i], &sym_len); + mrb_assert(sym); + cur += uint16_to_bin((uint16_t)sym_len, cur); + memcpy(cur, sym, sym_len); + cur += sym_len; + section_size += sizeof(uint16_t) + sym_len; + } /* debug records */ dlen = write_debug_record(mrb, irep, cur, filenames, filenames_len); section_size += dlen; - memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify)); + memcpy(header->section_ident, RITE_SECTION_DEBUG_IDENT, sizeof(header->section_ident)); mrb_assert(section_size <= INT32_MAX); - uint32_to_bin(section_size, header->section_size); + uint32_to_bin((uint32_t)section_size, header->section_size); - mrb_free(mrb, filenames); + return MRB_DUMP_OK; +} + +static void +create_lv_sym_table(mrb_state *mrb, const mrb_irep *irep, mrb_sym **syms, uint32_t *syms_len) +{ + int i; + + if (*syms == NULL) { + *syms = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) * 1); + } + + for (i = 0; i + 1 < irep->nlocals; ++i) { + mrb_sym const name = irep->lv[i]; + if (name == 0) continue; + if (find_filename_index(*syms, *syms_len, name) != -1) continue; + + ++(*syms_len); + *syms = (mrb_sym*)mrb_realloc(mrb, *syms, sizeof(mrb_sym) * (*syms_len)); + (*syms)[*syms_len - 1] = name; + } + + for (i = 0; i < irep->rlen; ++i) { + create_lv_sym_table(mrb, irep->reps[i], syms, syms_len); + } +} + +static int +write_lv_sym_table(mrb_state *mrb, uint8_t **start, mrb_sym const *syms, uint32_t syms_len) +{ + uint8_t *cur = *start; + uint32_t i; + const char *str; + mrb_int str_len; + + cur += uint32_to_bin(syms_len, cur); + + for (i = 0; i < syms_len; ++i) { + str = mrb_sym_name_len(mrb, syms[i], &str_len); + cur += uint16_to_bin((uint16_t)str_len, cur); + memcpy(cur, str, str_len); + cur += str_len; + } + + *start = cur; + + return MRB_DUMP_OK; +} + +static int +write_lv_record(mrb_state *mrb, const mrb_irep *irep, uint8_t **start, mrb_sym const *syms, uint32_t syms_len) +{ + uint8_t *cur = *start; + int i; + + for (i = 0; i + 1 < irep->nlocals; ++i) { + if (irep->lv[i] == 0) { + cur += uint16_to_bin(RITE_LV_NULL_MARK, cur); + } + else { + int const sym_idx = find_filename_index(syms, syms_len, irep->lv[i]); + mrb_assert(sym_idx != -1); /* local variable name must be in syms */ + + cur += uint16_to_bin(sym_idx, cur); + } + } + + for (i = 0; i < irep->rlen; ++i) { + write_lv_record(mrb, irep->reps[i], &cur, syms, syms_len); + } + + *start = cur; return MRB_DUMP_OK; } +static size_t +get_lv_record_size(mrb_state *mrb, const mrb_irep *irep) +{ + size_t ret = 0; + int i; + + ret += sizeof(uint16_t) * (irep->nlocals - 1); + + for (i = 0; i < irep->rlen; ++i) { + ret += get_lv_record_size(mrb, irep->reps[i]); + } + + return ret; +} + +static size_t +get_lv_section_size(mrb_state *mrb, const mrb_irep *irep, mrb_sym const *syms, uint32_t syms_len) +{ + size_t ret = 0, i; + + ret += sizeof(uint32_t); /* syms_len */ + ret += sizeof(uint16_t) * syms_len; /* symbol name lengths */ + for (i = 0; i < syms_len; ++i) { + mrb_int str_len; + mrb_sym_name_len(mrb, syms[i], &str_len); + ret += str_len; + } + + ret += get_lv_record_size(mrb, irep); + + return ret; +} + +static int +write_section_lv(mrb_state *mrb, const mrb_irep *irep, uint8_t *start, mrb_sym const *syms, uint32_t const syms_len) +{ + uint8_t *cur = start; + struct rite_section_lv_header *header; + ptrdiff_t diff; + int result = MRB_DUMP_OK; + + if (mrb == NULL || cur == NULL) { + return MRB_DUMP_INVALID_ARGUMENT; + } + + header = (struct rite_section_lv_header*)cur; + cur += sizeof(struct rite_section_lv_header); + + result = write_lv_sym_table(mrb, &cur, syms, syms_len); + if (result != MRB_DUMP_OK) { + goto lv_section_exit; + } + + result = write_lv_record(mrb, irep, &cur, syms, syms_len); + if (result != MRB_DUMP_OK) { + goto lv_section_exit; + } + + memcpy(header->section_ident, RITE_SECTION_LV_IDENT, sizeof(header->section_ident)); + + diff = cur - start; + mrb_assert_int_fit(ptrdiff_t, diff, size_t, SIZE_MAX); + uint32_to_bin((uint32_t)diff, header->section_size); + +lv_section_exit: + return result; +} + static int -write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin) +write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin, uint8_t flags) { struct rite_binary_header *header = (struct rite_binary_header *)bin; - uint16_t crc; - uint32_t offset; - memcpy(header->binary_identify, RITE_BINARY_IDENTIFIER, sizeof(header->binary_identify)); - memcpy(header->binary_version, RITE_BINARY_FORMAT_VER, sizeof(header->binary_version)); + memcpy(header->binary_ident, RITE_BINARY_IDENT, sizeof(header->binary_ident)); + memcpy(header->major_version, RITE_BINARY_MAJOR_VER, sizeof(header->major_version)); + memcpy(header->minor_version, RITE_BINARY_MINOR_VER, sizeof(header->minor_version)); memcpy(header->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); mrb_assert(binary_size <= UINT32_MAX); uint32_to_bin((uint32_t)binary_size, header->binary_size); - offset = (&(header->binary_crc[0]) - bin) + sizeof(uint16_t); - crc = calc_crc_16_ccitt(bin + offset, binary_size - offset, 0); - uint16_to_bin(crc, header->binary_crc); - return MRB_DUMP_OK; } static mrb_bool -is_debug_info_defined(mrb_irep *irep) +debug_info_defined_p(const mrb_irep *irep) { - size_t i; + int i; if (!irep->debug_info) return FALSE; for (i=0; i<irep->rlen; i++) { - if (!is_debug_info_defined(irep->reps[i])) return FALSE; + if (!debug_info_defined_p(irep->reps[i])) return FALSE; } return TRUE; } +static mrb_bool +lv_defined_p(const mrb_irep *irep) +{ + int i; + + if (irep->lv) { return TRUE; } + + for (i = 0; i < irep->rlen; ++i) { + if (lv_defined_p(irep->reps[i])) { return TRUE; } + } + + return FALSE; +} + static int -dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size) +dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) { int result = MRB_DUMP_GENERAL_FAILURE; + size_t malloc_size; size_t section_irep_size; - size_t section_lineno_size = 0; + size_t section_lineno_size = 0, section_lv_size = 0; uint8_t *cur = NULL; - mrb_bool const debug_info_defined = is_debug_info_defined(irep); + mrb_bool const debug_info_defined = debug_info_defined_p(irep), lv_defined = lv_defined_p(irep); + mrb_sym *lv_syms = NULL; uint32_t lv_syms_len = 0; + mrb_sym *filenames = NULL; uint16_t filenames_len = 0; if (mrb == NULL) { *bin = NULL; @@ -741,72 +782,83 @@ dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t section_irep_size += get_irep_record_size(mrb, irep); /* DEBUG section size */ - if (debug_info) { + if (flags & MRB_DUMP_DEBUG_INFO) { if (debug_info_defined) { - mrb_sym *filenames; - section_lineno_size += sizeof(struct rite_section_debug_header); /* filename table */ filenames = (mrb_sym*)mrb_malloc(mrb, sizeof(mrb_sym) + 1); /* filename table size */ section_lineno_size += sizeof(uint16_t); - section_lineno_size += get_filename_table_size(mrb, irep, &filenames, NULL); - mrb_free(mrb, filenames); + section_lineno_size += get_filename_table_size(mrb, irep, &filenames, &filenames_len); section_lineno_size += get_debug_record_size(mrb, irep); } - else { - section_lineno_size += sizeof(struct rite_section_lineno_header); - section_lineno_size += get_lineno_record_size(mrb, irep); - } } - *bin_size = sizeof(struct rite_binary_header) + - section_irep_size + section_lineno_size + - sizeof(struct rite_binary_footer); - cur = *bin = (uint8_t*)mrb_malloc(mrb, *bin_size); - if (cur == NULL) { - goto error_exit; + if (lv_defined) { + section_lv_size += sizeof(struct rite_section_lv_header); + create_lv_sym_table(mrb, irep, &lv_syms, &lv_syms_len); + section_lv_size += get_lv_section_size(mrb, irep, lv_syms, lv_syms_len); } + + malloc_size = sizeof(struct rite_binary_header) + + section_irep_size + section_lineno_size + section_lv_size + + sizeof(struct rite_binary_footer); + cur = *bin = (uint8_t*)mrb_malloc(mrb, malloc_size); cur += sizeof(struct rite_binary_header); - result = write_section_irep(mrb, irep, cur); + result = write_section_irep(mrb, irep, cur, §ion_irep_size, flags); if (result != MRB_DUMP_OK) { goto error_exit; } cur += section_irep_size; + *bin_size = sizeof(struct rite_binary_header) + + section_irep_size + section_lineno_size + section_lv_size + + sizeof(struct rite_binary_footer); /* write DEBUG section */ - if (debug_info) { + if (flags & MRB_DUMP_DEBUG_INFO) { if (debug_info_defined) { - result = write_section_debug(mrb, irep, cur); - } - else { - result = write_section_lineno(mrb, irep, cur); + result = write_section_debug(mrb, irep, cur, filenames, filenames_len); + if (result != MRB_DUMP_OK) { + goto error_exit; + } } + cur += section_lineno_size; + } + + if (lv_defined) { + result = write_section_lv(mrb, irep, cur, lv_syms, lv_syms_len); if (result != MRB_DUMP_OK) { goto error_exit; } - cur += section_lineno_size; + cur += section_lv_size; } write_footer(mrb, cur); - write_rite_binary_header(mrb, *bin_size, *bin); + write_rite_binary_header(mrb, *bin_size, *bin, flags); error_exit: if (result != MRB_DUMP_OK) { mrb_free(mrb, *bin); *bin = NULL; } + mrb_free(mrb, lv_syms); + mrb_free(mrb, filenames); return result; } +int +mrb_dump_irep(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, uint8_t **bin, size_t *bin_size) +{ + return dump_irep(mrb, irep, flags, bin, bin_size); +} -#ifdef ENABLE_STDIO +#ifndef MRB_NO_STDIO int -mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp) +mrb_dump_irep_binary(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE* fp) { uint8_t *bin = NULL; size_t bin_size = 0; @@ -816,55 +868,64 @@ mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp) return MRB_DUMP_INVALID_ARGUMENT; } - result = dump_irep(mrb, irep, debug_info, &bin, &bin_size); + result = dump_irep(mrb, irep, flags, &bin, &bin_size); if (result == MRB_DUMP_OK) { - fwrite(bin, bin_size, 1, fp); + if (fwrite(bin, sizeof(bin[0]), bin_size, fp) != bin_size) { + result = MRB_DUMP_WRITE_FAULT; + } } mrb_free(mrb, bin); return result; } -static mrb_bool -is_valid_c_symbol_name(const char *name) -{ - const char *c = NULL; - - if (name == NULL || name[0] == '\0') return FALSE; - if (!ISALPHA(name[0]) && name[0] != '_') return FALSE; - - c = &name[1]; - for (; *c != '\0'; ++c) { - if (!ISALNUM(*c) && *c != '_') return FALSE; - } - - return TRUE; -} - int -mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, const char *initname) +mrb_dump_irep_cfunc(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname) { uint8_t *bin = NULL; size_t bin_size = 0, bin_idx = 0; int result; - if (fp == NULL || initname == NULL || !is_valid_c_symbol_name(initname)) { + if (fp == NULL || initname == NULL || initname[0] == '\0') { return MRB_DUMP_INVALID_ARGUMENT; } - - result = dump_irep(mrb, irep, debug_info, &bin, &bin_size); + result = dump_irep(mrb, irep, flags, &bin, &bin_size); if (result == MRB_DUMP_OK) { - fprintf(fp, "#include <stdint.h>\n"); /* for uint8_t under at least Darwin */ - fprintf(fp, "const uint8_t %s[] = {", initname); + if (fprintf(fp, "#include <stdint.h>\n") < 0) { /* for uint8_t under at least Darwin */ + mrb_free(mrb, bin); + return MRB_DUMP_WRITE_FAULT; + } + if (fprintf(fp, + "%s\n" + "const uint8_t %s[] = {", + (flags & MRB_DUMP_STATIC) ? "static" + : "#ifdef __cplusplus\n" + "extern\n" + "#endif", + initname) < 0) { + mrb_free(mrb, bin); + return MRB_DUMP_WRITE_FAULT; + } while (bin_idx < bin_size) { - if (bin_idx % 16 == 0) fputs("\n", fp); - fprintf(fp, "0x%02x,", bin[bin_idx++]); + if (bin_idx % 16 == 0) { + if (fputs("\n", fp) == EOF) { + mrb_free(mrb, bin); + return MRB_DUMP_WRITE_FAULT; + } + } + if (fprintf(fp, "0x%02x,", bin[bin_idx++]) < 0) { + mrb_free(mrb, bin); + return MRB_DUMP_WRITE_FAULT; + } + } + if (fputs("\n};\n", fp) == EOF) { + mrb_free(mrb, bin); + return MRB_DUMP_WRITE_FAULT; } - fputs("\n};\n", fp); } mrb_free(mrb, bin); return result; } -#endif /* ENABLE_STDIO */ +#endif /* MRB_NO_STDIO */ |
