support multiple filename in irep

This commit is contained in:
take_cheeze
2013-09-01 22:43:17 +09:00
parent bc131350d4
commit 3d1fffbd6b
13 changed files with 647 additions and 45 deletions
+4 -1
View File
@@ -38,6 +38,7 @@ void mrbc_partial_hook(mrb_state *mrb, mrbc_context *c, int (*partial_hook)(stru
typedef struct mrb_ast_node {
struct mrb_ast_node *car, *cdr;
short lineno;
char const* filename;
} mrb_ast_node;
/* lexer states */
@@ -110,7 +111,7 @@ struct mrb_parser_state {
FILE *f;
#endif
mrbc_context *cxt;
char *filename;
char const *filename;
int lineno;
int column;
@@ -150,6 +151,8 @@ struct mrb_parser_state* mrb_parser_new(mrb_state*);
void mrb_parser_free(struct mrb_parser_state*);
void mrb_parser_parse(struct mrb_parser_state*,mrbc_context*);
void mrb_parser_set_filename(struct mrb_parser_state*, char const*);
/* utility functions */
#ifdef ENABLE_STDIO
struct mrb_parser_state* mrb_parse_file(mrb_state*,FILE*,mrbc_context*);
+57
View File
@@ -0,0 +1,57 @@
#ifndef MRUBY_DEBUG_H
#define MRUBY_DEBUG_H
#include <stdint.h>
#include "mruby/value.h"
typedef enum mrb_debug_line_type {
mrb_debug_line_ary = 0,
mrb_debug_line_flat_map = 1
} mrb_debug_line_type;
typedef struct mrb_irep_debug_info_line {
uint32_t start_pos;
uint16_t line;
} mrb_irep_debug_info_line;
typedef struct mrb_irep_debug_info_file {
uint32_t start_pos;
char const* filename;
mrb_sym filename_sym;
uint32_t line_entry_count;
mrb_debug_line_type line_type;
union {
void* line_ptr;
mrb_irep_debug_info_line* line_flat_map;
uint16_t* line_ary;
};
} mrb_irep_debug_info_file;
typedef struct mrb_irep_debug_info {
uint32_t pc_count;
uint16_t flen;
mrb_irep_debug_info_file** files;
} mrb_irep_debug_info;
struct mrb_irep;
struct mrb_state;
/*
* get line from irep's debug info and program counter
* @return returns NULL if not found
*/
char const* mrb_get_filename(struct mrb_irep* irep, uint32_t pc);
/*
* get line from irep's debug info and program counter
* @return returns -1 if not found
*/
int32_t mrb_get_line(struct mrb_irep* irep, uint32_t pc);
mrb_irep_debug_info_file* mrb_debug_info_append_file(
struct mrb_state* mrb, struct mrb_irep* irep,
uint32_t start_pos, uint32_t end_pos);
mrb_irep_debug_info* mrb_debug_info_alloc(struct mrb_state* mrb, struct mrb_irep* irep);
void mrb_debug_info_free(struct mrb_state* mrb, mrb_irep_debug_info* d);
#endif /* MRUBY_DEBUG_H */
+10 -2
View File
@@ -52,6 +52,7 @@ mrb_value mrb_load_irep_file(mrb_state*,FILE*);
#define RITE_BINARY_EOF "END\0"
#define RITE_SECTION_IREP_IDENTIFIER "IREP"
#define RITE_SECTION_LINENO_IDENTIFIER "LINE"
#define RITE_SECTION_DEBUG_IDENTIFIER "DBG\0"
#define MRB_DUMP_DEFAULT_STR_LEN 128
@@ -79,14 +80,21 @@ struct rite_section_irep_header {
uint8_t rite_version[4]; // Rite Instruction Specification Version
uint8_t nirep[2]; // Number of ireps
uint8_t sirep[2]; // Start index
uint8_t sirep[2]; // Start index
};
struct rite_section_lineno_header {
RITE_SECTION_HEADER;
uint8_t nirep[2]; // Number of ireps
uint8_t sirep[2]; // Start index
uint8_t sirep[2]; // Start index
};
struct rite_section_debug_header {
RITE_SECTION_HEADER;
uint8_t nirep[2]; // Number of ireps
uint8_t sirep[2]; // Start index
};
struct rite_binary_footer {
+1
View File
@@ -25,6 +25,7 @@ typedef struct mrb_irep {
/* debug info */
const char *filename;
uint16_t *lines;
struct mrb_irep_debug_info* debug_info;
size_t ilen, plen, slen;
} mrb_irep;
+14 -14
View File
@@ -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;
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];
}
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);
+31 -5
View File
@@ -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);
+192
View File
@@ -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);
}
+206 -15
View File
@@ -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);
+6 -3
View File
@@ -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;
}
}
+113 -1
View File
@@ -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);
+8
View File
@@ -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)
+3
View File
@@ -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
+2 -4
View File
@@ -145,7 +145,7 @@ parse_args(mrb_state *mrb, int argc, char **argv, struct mrbc_args *args)
}
}
else {
break;
break;
}
}
return i;
@@ -177,9 +177,7 @@ partial_hook(struct mrb_parser_state *p)
fprintf(stderr, "%s: cannot open program file. (%s)\n", args->prog, fn);
return -1;
}
mrbc_filename(p->mrb, c, fn);
p->filename = c->filename;
p->lineno = 1;
mrb_parser_set_filename(p, fn);
return 0;
}