diff options
Diffstat (limited to 'src/dump.c')
| -rw-r--r-- | src/dump.c | 596 |
1 files changed, 465 insertions, 131 deletions
diff --git a/src/dump.c b/src/dump.c index 72ca9e0c3..bdfa0787f 100644 --- a/src/dump.c +++ b/src/dump.c @@ -4,61 +4,69 @@ ** See Copyright Notice in mruby.h */ +#include <ctype.h> #include <string.h> +#include <limits.h> #include "mruby/dump.h" -#include <ctype.h> - #include "mruby/string.h" #include "mruby/irep.h" #include "mruby/numeric.h" +#include "mruby/debug.h" -static size_t get_irep_record_size(mrb_state *mrb, mrb_irep *irep); +static size_t get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep); -static uint32_t +#if UINT32_MAX > SIZE_MAX +# error This code cannot be built on your environment. +#endif + +static size_t get_irep_header_size(mrb_state *mrb) { - uint32_t size = 0; + size_t size = 0; size += sizeof(uint32_t) * 1; - size += sizeof(uint16_t) * 2; + size += sizeof(uint16_t) * 3; return size; } -static size_t +static ptrdiff_t write_irep_header(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; - cur += uint32_to_bin(get_irep_record_size(mrb, irep), cur); /* record size */ + cur += uint32_to_bin(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 */ - return (cur - buf); + return cur - buf; } -static uint32_t +static size_t get_iseq_block_size(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; + size += sizeof(uint32_t); /* ilen */ size += sizeof(uint32_t) * irep->ilen; /* iseq(n) */ + return size; } -static int +static ptrdiff_t write_iseq_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { uint8_t *cur = buf; - size_t iseq_no; + uint32_t iseq_no; 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 */ } - return (cur - buf); + return cur - buf; } @@ -67,7 +75,6 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) { size_t size = 0; size_t pool_no; - int len; mrb_value str; char buf[32]; @@ -80,35 +87,48 @@ get_pool_block_size(mrb_state *mrb, mrb_irep *irep) switch (mrb_type(irep->pool[pool_no])) { case MRB_TT_FIXNUM: str = mrb_fixnum_to_str(mrb, irep->pool[pool_no], 10); - size += RSTRING_LEN(str); + { + mrb_int len = RSTRING_LEN(str); + mrb_assert(len >= 0); + mrb_assert(len <= SIZE_MAX); + size += (size_t)len; + } break; case MRB_TT_FLOAT: - len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); - size += len; + { + int len; + len = mrb_float_to_str(buf, mrb_float(irep->pool[pool_no])); + mrb_assert(len >= 0); + mrb_assert(len <= SIZE_MAX); + size += (size_t)len; + } break; case MRB_TT_STRING: - str = mrb_str_to_str(mrb, irep->pool[pool_no]); - size += RSTRING_LEN(str); + { + mrb_int len = RSTRING_LEN(irep->pool[pool_no]); + mrb_assert(len >= 0); + mrb_assert(len <= SIZE_MAX); + size += (size_t)len; + } break; default: break; } - mrb_gc_arena_restore(mrb, ai); } return size; } -static int +static ptrdiff_t write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { size_t pool_no; uint8_t *cur = buf; - size_t len; + uint16_t len; mrb_value str; const char *char_ptr; char char_buf[30]; @@ -118,24 +138,42 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) for (pool_no = 0; pool_no < irep->plen; pool_no++) { int ai = mrb_gc_arena_save(mrb); - cur += uint8_to_bin(mrb_type(irep->pool[pool_no]), cur); /* data type */ - 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); - len = RSTRING_LEN(str); + { + mrb_int tlen; + tlen = RSTRING_LEN(str); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } break; case MRB_TT_FLOAT: - len = mrb_float_to_str(char_buf, mrb_float(irep->pool[pool_no])); + 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(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } char_ptr = &char_buf[0]; break; case MRB_TT_STRING: - str = irep->pool[pool_no]; - char_ptr = RSTRING_PTR(str); - len = RSTRING_LEN(str); + cur += uint8_to_bin(IREP_TT_STRING, cur); /* data type */ + char_ptr = RSTRING_PTR(irep->pool[pool_no]); + { + mrb_int tlen; + tlen = RSTRING_LEN(irep->pool[pool_no]); + mrb_assert(tlen >= 0); + mrb_assert(tlen <= INT16_MAX); + len = (uint16_t)tlen; + } break; default: @@ -143,13 +181,13 @@ write_pool_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } cur += uint16_to_bin(len, cur); /* data length */ - memcpy(cur, char_ptr, len); + memcpy(cur, char_ptr, (size_t)len); cur += len; mrb_gc_arena_restore(mrb, ai); } - return (int)(cur - buf); + return cur - buf; } @@ -157,8 +195,8 @@ static size_t get_syms_block_size(mrb_state *mrb, mrb_irep *irep) { size_t size = 0; - size_t sym_no; - size_t len; + uint32_t sym_no; + mrb_int len; size += sizeof(uint32_t); /* slen */ for (sym_no = 0; sym_no < irep->slen; sym_no++) { @@ -172,10 +210,10 @@ get_syms_block_size(mrb_state *mrb, mrb_irep *irep) return size; } -static int +static ptrdiff_t write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) { - size_t sym_no; + uint32_t sym_no; uint8_t *cur = buf; const char *name; @@ -183,13 +221,11 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) for (sym_no = 0; sym_no < irep->slen; sym_no++) { if (irep->syms[sym_no] != 0) { - size_t len; + mrb_int len; name = mrb_sym2name_len(mrb, irep->syms[sym_no], &len); - if (len > UINT16_MAX) { - return MRB_DUMP_GENERAL_FAILURE; - } + mrb_assert(len <= UINT16_MAX); cur += uint16_to_bin((uint16_t)len, cur); /* length of symbol name */ memcpy(cur, name, len); /* symbol name */ cur += (uint16_t)len; @@ -200,50 +236,71 @@ write_syms_block(mrb_state *mrb, mrb_irep *irep, uint8_t *buf) } } - return (int)(cur - buf); + return cur - buf; } - - static size_t -get_irep_record_size(mrb_state *mrb, mrb_irep *irep) +get_irep_record_size_1(mrb_state *mrb, mrb_irep *irep) { - uint32_t size = 0; + size_t size = 0; - //size += sizeof(uint16_t); /* rlen */ size += get_irep_header_size(mrb); size += get_iseq_block_size(mrb, irep); size += get_pool_block_size(mrb, irep); size += get_syms_block_size(mrb, irep); + return size; +} +static size_t +get_irep_record_size(mrb_state *mrb, mrb_irep *irep) +{ + size_t size = 0; + size_t 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]); + } return size; } static int -write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, uint32_t *irep_record_size) +write_irep_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin, size_t *irep_record_size) { + uint32_t i; + if (irep == NULL) { return MRB_DUMP_INVALID_IREP; } - *irep_record_size = get_irep_record_size(mrb, 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 += uint16_to_bin(*irep_record_size, bin); bin += write_irep_header(mrb, irep, bin); bin += write_iseq_block(mrb, irep, bin); bin += write_pool_block(mrb, irep, bin); bin += write_syms_block(mrb, irep, bin); + for (i = 0; i < irep->rlen; i++) { + int result; + size_t rsize; + + result = write_irep_record(mrb, irep->reps[i], bin, &rsize); + if (result != MRB_DUMP_OK) { + return result; + } + *irep_record_size += rsize; + bin += rsize; + } return MRB_DUMP_OK; } -static size_t -mrb_write_eof(mrb_state *mrb, uint8_t *bin) +static uint32_t +write_footer(mrb_state *mrb, uint8_t *bin) { struct rite_binary_footer footer; @@ -256,92 +313,90 @@ mrb_write_eof(mrb_state *mrb, uint8_t *bin) static int -mrb_write_section_irep_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin) -{ +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)); - uint32_to_bin(section_size, header->section_size); + mrb_assert(section_size <= UINT32_MAX); + uint32_to_bin((uint32_t)section_size, header->section_size); memcpy(header->rite_version, RITE_VM_VER, sizeof(header->rite_version)); - uint16_to_bin(nirep, header->nirep); - uint16_to_bin(sirep, header->sirep); return MRB_DUMP_OK; } static int -mrb_write_section_irep(mrb_state *mrb, size_t start_index, uint8_t *bin) +write_section_irep(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) { int result; - size_t irep_no; - uint32_t section_size = 0, rlen = 0; /* size of irep record */ + size_t section_size = 0; /* size of irep record */ + size_t rsize = 0; uint8_t *cur = bin; - if (mrb == NULL || start_index >= mrb->irep_len || bin == NULL) { + if (mrb == NULL || bin == NULL) { return MRB_DUMP_INVALID_ARGUMENT; } cur += sizeof(struct rite_section_irep_header); section_size += sizeof(struct rite_section_irep_header); - for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) { - result = write_irep_record(mrb, mrb->irep[irep_no], cur, &rlen); - if (result != MRB_DUMP_OK) { - return result; - } - cur += rlen; - section_size += rlen; + result = write_irep_record(mrb, irep, cur, &rsize); + if (result != MRB_DUMP_OK) { + return result; } - - mrb_write_section_irep_header(mrb, section_size, mrb->irep_len - start_index, start_index, bin); + cur += rsize; + section_size += rsize; + write_section_irep_header(mrb, section_size, bin); return MRB_DUMP_OK; } static int -mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin) -{ +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; - // TODO memcpy(header->section_identify, RITE_SECTION_LINENO_IDENTIFIER, sizeof(header->section_identify)); - uint32_to_bin(section_size, header->section_size); - uint16_to_bin(nirep, header->nirep); - uint16_to_bin(sirep, header->sirep); + uint32_to_bin((uint32_t)section_size, header->section_size); return MRB_DUMP_OK; } static size_t -get_debug_record_size(mrb_state *mrb, mrb_irep *irep) +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 + size += sizeof(uint32_t); /* record size */ + size += sizeof(uint16_t); /* filename size */ if (irep->filename) { - size += strlen(irep->filename); // filename + size += strlen(irep->filename); /* filename */ } - size += sizeof(uint32_t); // niseq + size += sizeof(uint32_t); /* niseq */ if (irep->lines) { - size += sizeof(uint16_t) * irep->ilen; // lineno + size += sizeof(uint16_t) * irep->ilen; /* lineno */ } return size; } -static int -write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) +static size_t +write_lineno_record_1(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) { uint8_t *cur = bin; - size_t filename_len = 0, iseq_no; + 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; } - cur += uint16_to_bin(filename_len, cur); /* filename size */ + mrb_assert(filename_len <= UINT16_MAX); + cur += uint16_to_bin((uint16_t)filename_len, cur); /* filename size */ if (filename_len) { memcpy(cur, irep->filename, filename_len); @@ -349,7 +404,8 @@ write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) } if (irep->lines) { - cur += uint32_to_bin(irep->ilen, cur); /* niseq */ + mrb_assert(irep->ilen <= 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 */ } @@ -358,49 +414,302 @@ write_lineno_record(mrb_state *mrb, mrb_irep *irep, uint8_t* bin) cur += uint32_to_bin(0, cur); /* niseq */ } - uint32_to_bin(cur - bin, bin); /* record size */ + diff = cur - bin; + mrb_assert(diff >= 0); + mrb_assert(diff <= UINT32_MAX); - return (cur - bin); + uint32_to_bin((uint32_t)diff, bin); /* record size */ + + mrb_assert(diff <= 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 -mrb_write_section_lineno(mrb_state *mrb, size_t start_index, uint8_t *bin) +write_section_lineno(mrb_state *mrb, mrb_irep *irep, uint8_t *bin) { - size_t irep_no; - uint32_t section_size = 0, rlen = 0; /* size of irep record */ + size_t section_size = 0; + size_t rlen = 0; /* size of irep record */ uint8_t *cur = bin; - if (mrb == NULL || start_index >= mrb->irep_len || bin == NULL) { + 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); - for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) { - rlen = write_lineno_record(mrb, mrb->irep[irep_no], cur); - cur += rlen; - section_size += rlen; + 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) +{ + size_t ret = 0; + uint16_t f_idx; + size_t i; + + ret += sizeof(uint32_t); /* record size */ + ret += sizeof(uint16_t); /* file count */ + + for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx]; + + ret += sizeof(uint32_t); /* position */ + ret += sizeof(uint16_t); /* filename index */ + + /* lines */ + ret += sizeof(uint32_t); /* entry count */ + ret += sizeof(uint8_t); /* line type */ + switch (file->line_type) { + case mrb_debug_line_ary: + ret += sizeof(uint16_t) * (size_t)(file->line_entry_count); + break; + + case mrb_debug_line_flat_map: + ret += (sizeof(uint32_t) + sizeof(uint16_t)) * (size_t)(file->line_entry_count); + break; + + default: mrb_assert(0); break; + } + } + for (i=0; i<irep->rlen; i++) { + ret += get_debug_record_size(mrb, irep->reps[i]); + } + + return ret; +} + +static int +find_filename_index(const mrb_sym *ary, uint16_t ary_len, mrb_sym s) +{ + int i; + + for (i = 0; i < ary_len; ++i) { + if (ary[i] == s) { return i; } + } + return -1; +} + +static size_t +get_filename_table_size(mrb_state *mrb, 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; + + if (lp == NULL) { + lp = &tsize; + } + for (file_i = 0; file_i < di->flen; ++file_i) { + mrb_irep_debug_info_file *file; + mrb_int filename_len; + size_t i; + + file = di->files[file_i]; + if (find_filename_index(filenames, *lp, file->filename_sym) == -1) { + /* register filename */ + *lp += 1; + *fp = filenames = (mrb_sym *)mrb_realloc(mrb, filenames, sizeof(mrb_sym) * (*lp)); + filenames[*lp - 1] = file->filename_sym; + + /* filename */ + mrb_sym2name_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; + } + } + 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) +{ + uint8_t *cur; + uint16_t f_idx; + ptrdiff_t ret; + + cur = bin + sizeof(uint32_t); /* skip record size */ + cur += uint16_to_bin(irep->debug_info->flen, cur); /* file count */ + + for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + int filename_idx; + const mrb_irep_debug_info_file *file = irep->debug_info->files[f_idx]; + + /* position */ + cur += uint32_to_bin(file->start_pos, cur); + + /* filename index */ + filename_idx = find_filename_index(filenames, filenames_len, + file->filename_sym); + mrb_assert(filename_idx >= 0); + mrb_assert(filename_idx <= UINT16_MAX); + cur += uint16_to_bin((uint16_t)filename_idx, cur); + + /* lines */ + cur += uint32_to_bin(file->line_entry_count, cur); + cur += uint8_to_bin(file->line_type, cur); + switch (file->line_type) { + case mrb_debug_line_ary: { + uint32_t l; + for (l = 0; l < file->line_entry_count; ++l) { + cur += uint16_to_bin(file->lines.ary[l], cur); + } + } break; + + case mrb_debug_line_flat_map: { + uint32_t line; + for (line = 0; line < file->line_entry_count; ++line) { + cur += uint32_to_bin(file->lines.flat_map[line].start_pos, cur); + cur += uint16_to_bin(file->lines.flat_map[line].line, cur); + } + } break; + + default: mrb_assert(0); break; + } + } + + ret = cur - bin; + mrb_assert(ret >= 0); + mrb_assert(ret <= UINT32_MAX); + uint32_to_bin(ret, bin); + + mrb_assert(ret <= 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) +{ + size_t size, len; + size_t 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++) { + len = write_debug_record(mrb, irep->reps[irep_no], bin, filenames, filenames_len); + bin += len; + size += len; + } + + mrb_assert(size == get_debug_record_size(mrb, irep)); + 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) +{ + 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; + + if (mrb == NULL || cur == NULL) { + return MRB_DUMP_INVALID_ARGUMENT; } - mrb_write_section_lineno_header(mrb, section_size, mrb->irep_len - start_index, start_index, bin); + header = (struct rite_section_debug_header *)bin; + cur += sizeof(struct rite_section_debug_header); + 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); + section_size += sizeof(uint16_t); + section_size += write_filename_table(mrb, irep, &cur, &filenames, &filenames_len); + uint16_to_bin(filenames_len, filenames_len_out); + + /* 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)); + mrb_assert(section_size <= INT32_MAX); + uint32_to_bin(section_size, header->section_size); + + mrb_free(mrb, filenames); return MRB_DUMP_OK; } static int -write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin) -{ - struct rite_binary_header *header = (struct rite_binary_header*)bin; +write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t *bin) +{ + struct rite_binary_header *header = (struct rite_binary_header *)bin; uint16_t crc; - size_t offset; + 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->compiler_name, RITE_COMPILER_NAME, sizeof(header->compiler_name)); memcpy(header->compiler_version, RITE_COMPILER_VERSION, sizeof(header->compiler_version)); - uint32_to_bin(binary_size, header->binary_size); - + 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); @@ -408,63 +717,88 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin) return MRB_DUMP_OK; } +static mrb_bool +is_debug_info_defined(mrb_irep *irep) +{ + size_t i; + + if (!irep->debug_info) return 0; + for (i=0; i<irep->rlen; i++) { + if (!is_debug_info_defined(irep->reps[i])) return 0; + } + return 1; +} + static int -mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, size_t *bin_size) +dump_irep(mrb_state *mrb, mrb_irep *irep, int debug_info, uint8_t **bin, size_t *bin_size) { int result = MRB_DUMP_GENERAL_FAILURE; - size_t section_size = 0; size_t section_irep_size; size_t section_lineno_size = 0; - size_t irep_no; uint8_t *cur = NULL; + mrb_bool const debug_info_defined = is_debug_info_defined(irep); - if (mrb == NULL || start_index >= mrb->irep_len) { + if (mrb == NULL) { *bin = NULL; return MRB_DUMP_GENERAL_FAILURE; } section_irep_size = sizeof(struct rite_section_irep_header); - for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) { - section_irep_size += get_irep_record_size(mrb, mrb->irep[irep_no]); - } - section_size += section_irep_size; + section_irep_size += get_irep_record_size(mrb, irep); /* DEBUG section size */ if (debug_info) { - section_lineno_size += sizeof(struct rite_section_lineno_header); - for (irep_no = start_index; irep_no < mrb->irep_len; irep_no++) { - section_lineno_size += get_debug_record_size(mrb, mrb->irep[irep_no]); + 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_debug_record_size(mrb, irep); + } + else { + section_lineno_size += sizeof(struct rite_section_lineno_header); + section_lineno_size += get_lineno_record_size(mrb, irep); } - section_size += section_lineno_size; } - *bin_size += sizeof(struct rite_binary_header) + section_size + sizeof(struct rite_binary_footer); - cur = *bin = (uint8_t *)mrb_malloc(mrb, *bin_size); + *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; } - cur += sizeof(struct rite_binary_header); - result = mrb_write_section_irep(mrb, start_index, cur); + result = write_section_irep(mrb, irep, cur); if (result != MRB_DUMP_OK) { goto error_exit; } - cur += section_irep_size; - + /* write DEBUG section */ if (debug_info) { - result = mrb_write_section_lineno(mrb, start_index, cur); + if (debug_info_defined) { + result = write_section_debug(mrb, irep, cur); + } + else { + result = write_section_lineno(mrb, irep, cur); + } if (result != MRB_DUMP_OK) { goto error_exit; } cur += section_lineno_size; } - mrb_write_eof(mrb, cur); - - result = write_rite_binary_header(mrb, *bin_size, *bin); + write_footer(mrb, cur); + write_rite_binary_header(mrb, *bin_size, *bin); error_exit: if (result != MRB_DUMP_OK) { @@ -478,7 +812,7 @@ error_exit: #ifdef ENABLE_STDIO int -mrb_dump_irep_binary(mrb_state *mrb, size_t start_index, int debug_info, FILE* fp) +mrb_dump_irep_binary(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE* fp) { uint8_t *bin = NULL; size_t bin_size = 0; @@ -488,7 +822,7 @@ mrb_dump_irep_binary(mrb_state *mrb, size_t start_index, int debug_info, FILE* f return MRB_DUMP_INVALID_ARGUMENT; } - result = mrb_dump_irep(mrb, start_index, debug_info, &bin, &bin_size); + result = dump_irep(mrb, irep, debug_info, &bin, &bin_size); if (result == MRB_DUMP_OK) { fwrite(bin, bin_size, 1, fp); } @@ -514,7 +848,7 @@ is_valid_c_symbol_name(const char *name) } int -mrb_dump_irep_cfunc(mrb_state *mrb, size_t start_index, int debug_info, FILE *fp, const char *initname) +mrb_dump_irep_cfunc(mrb_state *mrb, mrb_irep *irep, int debug_info, FILE *fp, const char *initname) { uint8_t *bin = NULL; size_t bin_size = 0, bin_idx = 0; @@ -524,12 +858,12 @@ mrb_dump_irep_cfunc(mrb_state *mrb, size_t start_index, int debug_info, FILE *fp return MRB_DUMP_INVALID_ARGUMENT; } - result = mrb_dump_irep(mrb, start_index, debug_info, &bin, &bin_size); + result = dump_irep(mrb, irep, debug_info, &bin, &bin_size); if (result == MRB_DUMP_OK) { - fprintf(fp, "#include <stdint.h>\n"); // for uint8_t under at least Darwin + fprintf(fp, "#include <stdint.h>\n"); /* for uint8_t under at least Darwin */ fprintf(fp, "const uint8_t %s[] = {", initname); while (bin_idx < bin_size) { - if (bin_idx % 16 == 0 ) fputs("\n", fp); + if (bin_idx % 16 == 0) fputs("\n", fp); fprintf(fp, "0x%02x,", bin[bin_idx++]); } fputs("\n};\n", fp); |
