diff options
| author | take_cheeze <[email protected]> | 2013-09-01 22:43:17 +0900 |
|---|---|---|
| committer | take_cheeze <[email protected]> | 2013-09-02 00:48:06 +0900 |
| commit | 3d1fffbd6bce3a6f9a77af3116078574ce8d5fe9 (patch) | |
| tree | 35d6c58a23442ca055671c3b9e34f736153bc4ec /src | |
| parent | bc131350d416409220fd3294d2ffcea3ae73027d (diff) | |
| download | mruby-3d1fffbd6bce3a6f9a77af3116078574ce8d5fe9.tar.gz mruby-3d1fffbd6bce3a6f9a77af3116078574ce8d5fe9.zip | |
support multiple filename in irep
Diffstat (limited to 'src')
| -rw-r--r-- | src/backtrace.c | 30 | ||||
| -rw-r--r-- | src/codegen.c | 36 | ||||
| -rw-r--r-- | src/debug.c | 192 | ||||
| -rw-r--r-- | src/dump.c | 221 | ||||
| -rw-r--r-- | src/error.c | 9 | ||||
| -rw-r--r-- | src/load.c | 114 | ||||
| -rw-r--r-- | src/parse.y | 8 | ||||
| -rw-r--r-- | src/state.c | 3 |
8 files changed, 574 insertions, 39 deletions
diff --git a/src/backtrace.c b/src/backtrace.c index d7881dce1..a1c35d09f 100644 --- a/src/backtrace.c +++ b/src/backtrace.c @@ -10,6 +10,7 @@ #include "mruby/array.h" #include "mruby/string.h" #include "mruby/class.h" +#include "mruby/debug.h" #include <stdarg.h> typedef void (*output_stream_func)(mrb_state*, void*, int, const char*, ...); @@ -70,7 +71,7 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun for (i = ciidx; i >= 0; i--) { ci = &mrb->c->cibase[i]; - filename = "(unknown)"; + filename = NULL; line = -1; if (!verbose && MRB_PROC_CFUNC_P(ci->proc)) { @@ -78,21 +79,16 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun } if(!MRB_PROC_CFUNC_P(ci->proc)) { mrb_irep *irep = ci->proc->body.irep; - if (irep->filename != NULL) - filename = irep->filename; - if (irep->lines != NULL) { - mrb_code *pc; - - if (i+1 <= ciidx) { - pc = mrb->c->cibase[i+1].pc; - } - else { - pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "lastpc", 6))); - } - if (irep->iseq <= pc && pc < irep->iseq + irep->ilen) { - line = irep->lines[pc - irep->iseq - 1]; - } + mrb_code *pc; + + if (i+1 <= ciidx) { + pc = mrb->c->cibase[i+1].pc; + } + else { + pc = (mrb_code*)mrb_voidp(mrb_obj_iv_get(mrb, exc, mrb_intern2(mrb, "lastpc", 6))); } + filename = mrb_get_filename(irep, pc - irep->iseq - 1); + line = mrb_get_line(irep, pc - irep->iseq - 1); } if (!verbose && line == -1) continue; if (ci->target_class == ci->proc->target_class) @@ -100,6 +96,10 @@ mrb_output_backtrace(mrb_state *mrb, struct RObject *exc, output_stream_func fun else sep = "#"; + if (!filename) { + filename = "(unknown)"; + } + method = mrb_sym2name(mrb, ci->mid); if (verbose && !method && ci->proc->env) { method = mrb_sym2name(mrb, ci->proc->env->mid); diff --git a/src/codegen.c b/src/codegen.c index 50916a473..5ba5e4f03 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -12,6 +12,7 @@ #include "mruby/irep.h" #include "mruby/numeric.h" #include "mruby/string.h" +#include "mruby/debug.h" #include "node.h" #include "opcode.h" #include "re.h" @@ -51,7 +52,7 @@ typedef struct scope { struct loopinfo *loop; int ensure_level; - char *filename; + char const *filename; short lineno; mrb_code *iseq; @@ -67,6 +68,8 @@ typedef struct scope { int ai; int idx; + + int debug_start_pos; } codegen_scope; static codegen_scope* scope_new(mrb_state *mrb, codegen_scope *prev, node *lv); @@ -142,6 +145,7 @@ genop(codegen_scope *s, mrb_code i) s->iseq = (mrb_code *)codegen_realloc(s, s->iseq, sizeof(mrb_code)*s->icapa); if (s->lines) { s->lines = (short*)codegen_realloc(s, s->lines, sizeof(short)*s->icapa); + s->irep->lines = s->lines; } } s->iseq[s->pc] = i; @@ -1107,6 +1111,17 @@ codegen(codegen_scope *s, node *tree, int val) int nt; if (!tree) return; + + if (s->irep) { + if (s->pc > 0 && strcmp(s->filename, tree->filename) != 0) { + mrb_debug_info_append_file(s->mrb, s->irep, s->debug_start_pos, s->pc); + s->debug_start_pos = s->pc; + // fprintf(stderr, "%s\n", s->filename); + } + s->irep->filename = tree->filename; + s->filename = tree->filename; + } + nt = (intptr_t)tree->car; s->lineno = tree->lineno; tree = tree->cdr; @@ -2395,6 +2410,18 @@ scope_new(mrb_state *mrb, codegen_scope *prev, node *lv) p->lines = (short*)mrb_malloc(mrb, sizeof(short)*p->icapa); } p->lineno = prev->lineno; + + // debug setting + p->debug_start_pos = 0; + if(p->filename) { + mrb_debug_info_alloc(mrb, p->irep); + p->irep->filename = p->filename; + p->irep->lines = p->lines; + } + else { + p->irep->debug_info = NULL; + } + return p; } @@ -2420,6 +2447,8 @@ scope_finish(codegen_scope *s) irep->pool = (mrb_value *)codegen_realloc(s, irep->pool, sizeof(mrb_value)*irep->plen); irep->syms = (mrb_sym *)codegen_realloc(s, irep->syms, sizeof(mrb_sym)*irep->slen); if (s->filename) { + mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc); + fname_len = strlen(s->filename); fname = codegen_malloc(s, fname_len + 1); memcpy(fname, s->filename, fname_len); @@ -2831,7 +2860,6 @@ codedump_all(mrb_state *mrb, int start) codedump(mrb, i); } } - static int codegen_start(mrb_state *mrb, parser_state *p) { @@ -2841,9 +2869,7 @@ codegen_start(mrb_state *mrb, parser_state *p) return -1; } scope->mrb = mrb; - if (p->filename) { - scope->filename = p->filename; - } + scope->filename = p->filename; if (setjmp(scope->jmp) == 0) { // prepare irep codegen(scope, p->tree, NOVAL); diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 000000000..637d39bcc --- /dev/null +++ b/src/debug.c @@ -0,0 +1,192 @@ +#include "mruby/debug.h" + +#include "mruby.h" +#include "mruby/irep.h" + +#include <string.h> + +static mrb_irep_debug_info_file* +get_file(mrb_irep_debug_info* info, uint32_t const pc) +{ + if(pc >= info->pc_count) { return NULL; } + + // get upper bound + mrb_irep_debug_info_file** ret = info->files; + int32_t count = info->flen; + while (count > 0) { + int32_t const step = count / 2; + mrb_irep_debug_info_file** const it = ret + step; + if (!(pc < (*it)->start_pos)) { + ret = it + 1; + count -= step + 1; + } else { count = step; } + } + + --ret; + + mrb_assert(ret < (info->files + info->flen)); + mrb_assert((*ret)->start_pos <= pc && + pc < (((ret + 1 - info->files) < info->flen) + ? (*(ret+1))->start_pos : info->pc_count)); + + return *ret; +} + +static mrb_debug_line_type +select_line_type(uint32_t pc_count, uint16_t line_count) +{ + return (sizeof(uint16_t) * pc_count) < (sizeof(mrb_irep_debug_info_line) * line_count) + ? mrb_debug_line_ary : mrb_debug_line_flat_map; +} + +char const* +mrb_get_filename(mrb_irep* irep, uint32_t pc) +{ + mrb_irep_debug_info_file* f = NULL; + if (irep) { + if (!irep->debug_info) { return irep->filename; } + else if ((f = get_file(irep->debug_info, pc))) { + return f->filename; + } + } + return NULL; +} + +int32_t +mrb_get_line(mrb_irep* irep, uint32_t const pc) +{ + mrb_irep_debug_info_file* f = NULL; + if (irep) { + if (!irep->debug_info) { + return irep->lines? irep->lines[pc] : -1; + } + else if ((f = get_file(irep->debug_info, pc))) { + switch(f->line_type) { + case mrb_debug_line_ary: + mrb_assert(pc < (f->start_pos + f->line_entry_count)); + return f->line_ary[pc]; + + case mrb_debug_line_flat_map: { + // get upper bound + mrb_irep_debug_info_line* ret = f->line_flat_map; + int32_t count = f->line_entry_count; + while (count > 0) { + int32_t const step = count / 2; + mrb_irep_debug_info_line* const it = ret + step; + if (!(pc < it->start_pos)) { + ret = it + 1; + count -= step + 1; + } else { count = step; } + } + + --ret; + + mrb_assert((ret - f->line_flat_map) < f->line_entry_count); + mrb_assert(ret->start_pos <= pc && + pc < (((ret + 1 - f->line_flat_map) < f->line_entry_count) + ? (ret+1)->start_pos : irep->debug_info->pc_count)); + + return ret->line; + } + } + } + } + return -1; +} + +mrb_irep_debug_info* +mrb_debug_info_alloc(mrb_state* mrb, mrb_irep* irep) +{ + static mrb_irep_debug_info const initial = { 0, 0, NULL }; + mrb_assert(!irep->debug_info); + + mrb_irep_debug_info* const ret = (mrb_irep_debug_info*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info)); + *ret = initial; + irep->debug_info = ret; + return ret; +} + +mrb_irep_debug_info_file* +mrb_debug_info_append_file(mrb_state* mrb, mrb_irep* irep, + uint32_t const start_pos, uint32_t const end_pos) +{ + if (!irep->debug_info) { return NULL; } + + mrb_assert(irep->filename); + mrb_assert(irep->lines); + + mrb_irep_debug_info* info = irep->debug_info; + + if (info->flen > 0 && strcmp(irep->filename, info->files[info->flen - 1]->filename) == 0) { + return NULL; + } + + mrb_irep_debug_info_file* const ret = + (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file)); + info->files = + (mrb_irep_debug_info_file*)info->files + ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1)) + : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*)); + info->files[info->flen++] = ret; + + uint32_t const file_pc_count = end_pos - start_pos; + + ret->start_pos = start_pos; + info->pc_count = end_pos; + + size_t const fn_len = strlen(irep->filename); + ret->filename_sym = mrb_intern2(mrb, irep->filename, fn_len); + size_t len = 0; + ret->filename = mrb_sym2name_len(mrb, ret->filename_sym, &len); + + ret->line_type = select_line_type( + file_pc_count, irep->lines[end_pos - 1] - irep->lines[0] + 1); + ret->line_ptr = NULL; + + switch(ret->line_type) { + case mrb_debug_line_ary: + ret->line_entry_count = file_pc_count; + ret->line_ary = mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count); + for(uint32_t i = 0; i < file_pc_count; ++i) { + ret->line_ary[i] = irep->lines[start_pos + i]; + } + break; + + case mrb_debug_line_flat_map: { + ret->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1); + ret->line_entry_count = 0; + uint16_t prev_line = 0; + for(uint32_t i = 0; i < file_pc_count; ++i) { + if(irep->lines[start_pos + i] == prev_line) { continue; } + + ret->line_flat_map = mrb_realloc( + mrb, ret->line_flat_map, + sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1)); + mrb_irep_debug_info_line const m = { start_pos + i, irep->lines[start_pos + i] }; + ret->line_flat_map[ret->line_entry_count] = m; + + // update + ++ret->line_entry_count; + prev_line = irep->lines[start_pos + i]; + } + } break; + + default: mrb_assert(0); break; + } + + return ret; +} + +void +mrb_debug_info_free(mrb_state* mrb, mrb_irep_debug_info* d) +{ + if(!d) { return; } + + for(uint32_t i = 0; i < d->flen; ++i) { + mrb_assert(d->files[i]); + mrb_free(mrb, d->files[i]->line_ptr); + mrb_free(mrb, d->files[i]); + } + mrb_free(mrb, d->files); + mrb_free(mrb, d); +} diff --git a/src/dump.c b/src/dump.c index 72ca9e0c3..92b1b011a 100644 --- a/src/dump.c +++ b/src/dump.c @@ -11,6 +11,8 @@ #include "mruby/string.h" #include "mruby/irep.h" #include "mruby/numeric.h" +#include "mruby/debug.h" +#include "mruby/array.h" static size_t get_irep_record_size(mrb_state *mrb, mrb_irep *irep); @@ -257,7 +259,7 @@ 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) -{ +{ struct rite_section_irep_header *header = (struct rite_section_irep_header*)bin; memcpy(header->section_identify, RITE_SECTION_IREP_IDENTIFIER, sizeof(header->section_identify)); @@ -300,7 +302,7 @@ mrb_write_section_irep(mrb_state *mrb, size_t start_index, uint8_t *bin) static int mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t nirep, uint16_t sirep, uint8_t *bin) -{ +{ struct rite_section_lineno_header *header = (struct rite_section_lineno_header*)bin; // TODO @@ -313,7 +315,7 @@ mrb_write_section_lineno_header(mrb_state *mrb, uint32_t section_size, uint16_t } 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; @@ -388,9 +390,152 @@ mrb_write_section_lineno(mrb_state *mrb, size_t start_index, uint8_t *bin) return MRB_DUMP_OK; } +static size_t +get_debug_record_size(mrb_state* mrb, mrb_irep *irep) { + (void)mrb; + size_t ret = 0; + + ret += sizeof(uint32_t); // record size + ret += sizeof(uint16_t); // file count + + for(uint32_t 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) * file->line_entry_count; + break; + + case mrb_debug_line_flat_map: + ret += (sizeof(uint32_t) + sizeof(uint16_t)) * file->line_entry_count; + break; + + default: mrb_assert(0); break; + } + } + + return ret; +} + +static int +find_filename_index(mrb_value const ary, mrb_sym s) { + for(mrb_int i = 0; i < RARRAY_LEN(ary); ++i) { + mrb_assert(mrb_symbol_p(RARRAY_PTR(ary)[i])); + if(mrb_symbol(RARRAY_PTR(ary)[i]) == s) { return i; } + } + return -1; +} + +static int +write_debug_record(mrb_state* mrb, mrb_irep *irep, uint8_t * const bin, mrb_value filenames) +{ + uint8_t *cur = bin + sizeof(uint32_t); // skip record size + + cur += uint16_to_bin(irep->debug_info->flen, cur); // file count + for(uint32_t f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + mrb_irep_debug_info_file const* file = irep->debug_info->files[f_idx]; + + // position + cur += uint32_to_bin(file->start_pos, cur); + + // filename index + int const filename_idx = find_filename_index(filenames, file->filename_sym); + mrb_assert(filename_idx != -1); + cur += uint16_to_bin(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: { + for(size_t l = 0; l < file->line_entry_count; ++l) { + cur += uint16_to_bin(file->line_ary[l], cur); + } + } break; + + case mrb_debug_line_flat_map: + for(uint32_t line = 0; line < file->line_entry_count; ++line) { + cur += uint32_to_bin(file->line_flat_map[line].start_pos, cur); + cur += uint16_to_bin(file->line_flat_map[line].line, cur); + } + break; + + default: mrb_assert(0); break; + } + } + + size_t const ret = cur - bin; + uint32_to_bin(ret, bin); + + mrb_assert((cur - bin) == (int)get_debug_record_size(mrb, irep)); + + return ret; +} + +static int +mrb_write_section_debug(mrb_state* mrb, size_t start_index, uint8_t *cur) +{ + uint32_t section_size = 0; + uint8_t* const bin = cur; + + if (mrb == NULL || start_index >= mrb->irep_len || cur == NULL) { + return MRB_DUMP_INVALID_ARGUMENT; + } + + struct rite_section_debug_header* header = (struct rite_section_debug_header*)bin; + cur += sizeof(struct rite_section_debug_header); + section_size += sizeof(struct rite_section_debug_header); + + // filename table + mrb_value const filenames = mrb_ary_new(mrb); + uint8_t* const filenames_len = cur; + cur += sizeof(uint16_t); + section_size += sizeof(uint16_t); + for (size_t irep_i = start_index; irep_i < mrb->irep_len; ++irep_i) { + mrb_irep_debug_info const* debug_info = mrb->irep[irep_i]->debug_info; + + for(size_t file_i = 0; file_i < debug_info->flen; ++file_i) { + mrb_irep_debug_info_file const* file = debug_info->files[file_i]; + if(find_filename_index(filenames, file->filename_sym) != -1) continue; + + // register filename + mrb_ary_push(mrb, filenames, mrb_symbol_value(file->filename_sym)); + + // filename + uint16_t const fn_len = strlen(file->filename); + cur += uint16_to_bin(fn_len, cur); + memcpy(cur, file->filename, fn_len); + cur += fn_len; + + section_size += sizeof(uint16_t) + fn_len; + } + } + uint16_to_bin(RARRAY_LEN(filenames), filenames_len); + + // records + for (size_t i = start_index; i < mrb->irep_len; ++i) { + uint32_t rlen = write_debug_record(mrb, mrb->irep[i], cur, filenames); + cur += rlen; + section_size += rlen; + } + + memcpy(header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(header->section_identify)); + uint32_to_bin(section_size, header->section_size); + uint16_to_bin(mrb->irep_len - start_index, header->nirep); + uint16_to_bin(start_index, header->sirep); + + 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; uint16_t crc; size_t offset; @@ -400,7 +545,7 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin) 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); - + 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,6 +553,13 @@ write_rite_binary_header(mrb_state *mrb, size_t binary_size, uint8_t* bin) return MRB_DUMP_OK; } +mrb_bool is_debug_info_defined(mrb_state* mrb, size_t const start_index) { + for (size_t i = start_index; i < mrb->irep_len; ++i) { + if (!mrb->irep[i]->debug_info) { 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) { @@ -418,6 +570,8 @@ mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, size_t irep_no; uint8_t *cur = NULL; + mrb_bool const debug_info_defined = is_debug_info_defined(mrb, start_index); + if (mrb == NULL || start_index >= mrb->irep_len) { *bin = NULL; return MRB_DUMP_GENERAL_FAILURE; @@ -431,11 +585,39 @@ mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, /* 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) { + section_lineno_size += sizeof(struct rite_section_debug_header); + + // filename table + mrb_value const filenames = mrb_ary_new(mrb); + // filename table size + section_lineno_size += sizeof(uint16_t); + for (size_t irep_i = start_index; irep_i < mrb->irep_len; ++irep_i) { + mrb_irep_debug_info const* di = mrb->irep[irep_i]->debug_info; + + for(size_t file_i = 0; file_i < di->flen; ++file_i) { + mrb_irep_debug_info_file const* file = di->files[file_i]; + if(find_filename_index(filenames, file->filename_sym) != -1) continue; + + // register filename + mrb_ary_push(mrb, filenames, mrb_symbol_value(file->filename_sym)); + // filename + section_lineno_size += sizeof(uint16_t) + strlen(file->filename); + } + } + + for(irep_no = start_index; irep_no < mrb->irep_len; ++irep_no) { + section_lineno_size += get_debug_record_size(mrb, mrb->irep[irep_no]); + } + section_size += section_lineno_size; + } + else { + 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_lineno_record_size(mrb, mrb->irep[irep_no]); + } + section_size += section_lineno_size; } - section_size += section_lineno_size; } *bin_size += sizeof(struct rite_binary_header) + section_size + sizeof(struct rite_binary_footer); @@ -450,16 +632,25 @@ mrb_dump_irep(mrb_state *mrb, size_t start_index, int debug_info, uint8_t **bin, 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 (result != MRB_DUMP_OK) { - goto error_exit; + if(debug_info_defined) { + result = mrb_write_section_debug(mrb, start_index, cur); + if(result != MRB_DUMP_OK) { + goto error_exit; + } + cur += section_lineno_size; + } + else { + result = mrb_write_section_lineno(mrb, start_index, cur); + if (result != MRB_DUMP_OK) { + goto error_exit; + } + cur += section_lineno_size; } - cur += section_lineno_size; } mrb_write_eof(mrb, cur); diff --git a/src/error.c b/src/error.c index f7d41c2e2..4b5eab397 100644 --- a/src/error.c +++ b/src/error.c @@ -15,6 +15,7 @@ #include "mruby/proc.h" #include "mruby/string.h" #include "mruby/variable.h" +#include "mruby/debug.h" #include "error.h" mrb_value @@ -198,9 +199,11 @@ exc_debug_info(mrb_state *mrb, struct RObject *exc) if (ci->proc && !MRB_PROC_CFUNC_P(ci->proc)) { mrb_irep *irep = ci->proc->body.irep; - if (irep->filename && irep->lines && irep->iseq <= pc && pc < irep->iseq + irep->ilen) { - mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, irep->filename)); - mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(irep->lines[pc - irep->iseq - 1])); + int32_t const line = mrb_get_line(irep, pc - irep->iseq - 1); + char const* file = mrb_get_filename(irep, pc - irep->iseq - 1); + if(line != -1 && file) { + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "file", 4), mrb_str_new_cstr(mrb, file)); + mrb_obj_iv_set(mrb, exc, mrb_intern2(mrb, "line", 4), mrb_fixnum_value(line)); return; } } diff --git a/src/load.c b/src/load.c index 092ddbde8..3bdf39e73 100644 --- a/src/load.c +++ b/src/load.c @@ -16,6 +16,8 @@ #include "mruby/irep.h" #include "mruby/proc.h" #include "mruby/string.h" +#include "mruby/debug.h" +#include "mruby/array.h" #if !defined(_WIN32) && SIZE_MAX < UINT32_MAX # define SIZE_ERROR_MUL(x, y) ((x) > SIZE_MAX / (y)) @@ -299,6 +301,97 @@ error_exit: return result; } +static int read_rite_debug_record(mrb_state* mrb, uint8_t const *start, size_t irepno, uint32_t *len, mrb_value const filenames) { + uint8_t const* bin = start; + + mrb_irep* const irep = mrb->irep[irepno]; + + 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 = irep->ilen; + + size_t const record_size = 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); + bin += sizeof(uint16_t); + + for (uint16_t f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) { + mrb_irep_debug_info_file* const file = (mrb_irep_debug_info_file*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file)); + irep->debug_info->files[f_idx] = file; + + file->start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); + + // filename + file->filename_sym = mrb_symbol(RARRAY_PTR(filenames)[bin_to_uint16(bin)]); + size_t len = 0; + file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len); + bin += sizeof(uint16_t); + + file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t); + file->line_type = bin_to_uint8(bin); bin += sizeof(uint8_t); + switch(file->line_type) { + case mrb_debug_line_ary: + file->line_ary = mrb_malloc(mrb, sizeof(uint16_t) * file->line_entry_count); + for(size_t l = 0; l < file->line_entry_count; ++l) { + file->line_ary[l] = bin_to_uint16(bin); bin += sizeof(uint16_t); + } + break; + + case mrb_debug_line_flat_map: + file->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * file->line_entry_count); + for(size_t l = 0; l < file->line_entry_count; ++l) { + file->line_flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t); + file->line_flat_map[l].line = bin_to_uint16(bin); bin += sizeof(uint16_t); + } + break; + + default: return MRB_DUMP_GENERAL_FAILURE; + } + } + + if((long)record_size != (bin - start)) { + return MRB_DUMP_GENERAL_FAILURE; + } + + *len = bin - start; + + return MRB_DUMP_OK; +} + +static int +read_rite_section_debug(mrb_state* mrb, const uint8_t* start, size_t sirep) +{ + uint8_t const* bin = start; + struct rite_section_debug_header const* header = (struct rite_section_debug_header const*)bin; + bin += sizeof(struct rite_section_debug_header); + + uint16_t const nirep = bin_to_uint16(header->nirep); + + uint16_t const filenames_len = bin_to_uint16(bin); + mrb_value const filenames = mrb_ary_new_capa(mrb, filenames_len); + bin += sizeof(uint16_t); + for(uint16_t i = 0; i < filenames_len; ++i) { + uint16_t const f_len = bin_to_uint16(bin); + bin += sizeof(uint16_t); + mrb_ary_push(mrb, filenames, mrb_symbol_value(mrb_intern2(mrb, (char const*)bin, f_len))); + bin += f_len; + } + + for(uint16_t i = sirep; i < (sirep + nirep); ++i) { + uint32_t len = 0; + int result = read_rite_debug_record(mrb, bin, i, &len, filenames); + if (result != MRB_DUMP_OK) { return result; } + bin += len; + } + + if ((bin - start) != bin_to_uint32(header->section_size)) { + return MRB_DUMP_GENERAL_FAILURE; + } + + return sirep + bin_to_uint16(header->sirep); +} static int read_rite_binary_header(const uint8_t *bin, size_t *bin_size, uint16_t *crc) @@ -364,6 +457,12 @@ mrb_read_irep(mrb_state *mrb, const uint8_t *bin) return result; } } + else if (memcmp(section_header->section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header->section_identify)) == 0) { + result = read_rite_section_debug(mrb, bin, sirep); + if (result < MRB_DUMP_OK) { + return result; + } + } bin += bin_to_uint32(section_header->section_size); } while (memcmp(section_header->section_identify, RITE_BINARY_EOF, sizeof(section_header->section_identify)) != 0); @@ -566,7 +665,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) /* You don't need use SIZE_ERROR as block_size is enough small. */ for (i = 0; i < block_fallback_count; i++,block_size >>= 1){ buf = mrb_malloc_simple(mrb, block_size); - if (buf) break; + if (buf) break; } if (!buf) { return MRB_DUMP_GENERAL_FAILURE; @@ -608,6 +707,19 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp) return result; } } + else if (memcmp(section_header.section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header.section_identify)) == 0) { + uint8_t* const bin = mrb_malloc(mrb, section_size); + fseek(fp, fpos, SEEK_SET); + if(fread((char*)bin, section_size, 1, fp) != section_size) { + mrb_free(mrb, bin); + return MRB_DUMP_READ_FAULT; + } + result = read_rite_section_debug(mrb, bin, sirep); + mrb_free(mrb, bin); + if (result < MRB_DUMP_OK) { + return result; + } + } fseek(fp, fpos + section_size, SEEK_SET); } while (memcmp(section_header.section_identify, RITE_BINARY_EOF, sizeof(section_header.section_identify)) != 0); diff --git a/src/parse.y b/src/parse.y index bbad88949..9ebcd5d98 100644 --- a/src/parse.y +++ b/src/parse.y @@ -120,6 +120,7 @@ cons_gen(parser_state *p, node *car, node *cdr) c->car = car; c->cdr = cdr; c->lineno = p->lineno; + c->filename = p->filename; return c; } #define cons(a,b) cons_gen(p,(a),(b)) @@ -5179,6 +5180,13 @@ mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*func)(struct mrb_parser c->partial_data = data; } +void +mrb_parser_set_filename(struct mrb_parser_state* p, char const* f) +{ + p->filename = mrbc_filename(p->mrb, p->cxt, f); + p->lineno = 1; +} + #ifdef ENABLE_STDIO parser_state* mrb_parse_file(mrb_state *mrb, FILE *f, mrbc_context *c) diff --git a/src/state.c b/src/state.c index 5dcc4a40a..9a9f07787 100644 --- a/src/state.c +++ b/src/state.c @@ -10,6 +10,7 @@ #include "mruby/class.h" #include "mruby/irep.h" #include "mruby/variable.h" +#include "mruby/debug.h" void mrb_init_heap(mrb_state*); void mrb_init_core(mrb_state*); @@ -115,6 +116,8 @@ mrb_irep_free(mrb_state *mrb, struct mrb_irep *irep) mrb_free(mrb, (void *)irep->filename); mrb_free(mrb, irep->lines); mrb_free(mrb, irep); + + mrb_debug_info_free(mrb, irep->debug_info); } void |
