8 #include <mruby/irep.h>
10 #include <mruby/debug.h>
11 #include <mruby/opcode.h>
12 #include <mruby/class.h>
13 #include <mruby/proc.h>
14 #include <mruby/variable.h>
15 #include "mrdberror.h"
18 #define MAX_BREAKPOINTNO (MAX_BREAKPOINT * 1024)
19 #define MRB_DEBUG_BP_FILE_OK (0x0001)
20 #define MRB_DEBUG_BP_LINENO_OK (0x0002)
23 check_lineno(mrb_irep_debug_info_file *info_file, uint16_t lineno)
25 uint32_t count = info_file->line_entry_count;
28 if (info_file->line_type == mrb_debug_line_ary) {
29 for (l_idx = 0; l_idx < count; ++l_idx) {
30 if (lineno == info_file->lines.ary[l_idx]) {
36 for (l_idx = 0; l_idx < count; ++l_idx) {
37 if (lineno == info_file->lines.flat_map[l_idx].line) {
47 get_break_index(mrb_debug_context *dbg, uint32_t bpno)
53 for(i = 0 ; i < dbg->bpnum; i++) {
54 if (dbg->bp[i].bpno == bpno) {
62 return MRB_DEBUG_BREAK_INVALID_NO;
69 free_breakpoint(mrb_state *mrb, mrb_debug_breakpoint *bp)
72 case MRB_DEBUG_BPTYPE_LINE:
73 mrb_free(mrb, (void*)bp->point.linepoint.file);
75 case MRB_DEBUG_BPTYPE_METHOD:
76 mrb_free(mrb, (void*)bp->point.methodpoint.method_name);
77 if (bp->point.methodpoint.class_name != NULL) {
78 mrb_free(mrb, (void*)bp->point.methodpoint.class_name);
87 check_file_lineno(mrb_state *mrb, struct mrb_irep *irep, const char *file, uint16_t lineno)
89 mrb_irep_debug_info_file *info_file;
95 for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
97 info_file = irep->debug_info->files[f_idx];
98 filename = mrb_sym_name_len(mrb, info_file->filename_sym, NULL);
99 if (!strcmp(filename, file)) {
100 result = MRB_DEBUG_BP_FILE_OK;
102 fix_lineno = check_lineno(info_file, lineno);
103 if (fix_lineno != 0) {
104 return result | MRB_DEBUG_BP_LINENO_OK;
107 for (i=0; i < irep->rlen; ++i) {
108 result |= check_file_lineno(mrb, irep->reps[i], file, lineno);
109 if (result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
118 compare_break_method(mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
120 const char* class_name;
121 const char* method_name;
126 mrb_debug_methodpoint *method_p;
129 method_name = mrb_sym_name(mrb, method_sym);
131 method_p = &bp->point.methodpoint;
132 if (strcmp(method_p->method_name, method_name) == 0) {
133 class_name = mrb_class_name(mrb, class_obj);
134 if (class_name == NULL) {
135 if (method_p->class_name == NULL) {
139 else if (method_p->class_name != NULL) {
140 m = mrb_method_search_vm(mrb, &class_obj, method_sym);
141 if (MRB_METHOD_UNDEF_P(m)) {
144 if (MRB_METHOD_CFUNC_P(m)) {
148 is_defined = mrb_class_defined(mrb, method_p->class_name);
149 if (is_defined == FALSE) {
153 sc = mrb_class_get(mrb, method_p->class_name);
154 ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
155 m = mrb_method_search_vm(mrb, &sc, ssym);
156 if (MRB_METHOD_UNDEF_P(m)) {
160 class_name = mrb_class_name(mrb, class_obj);
161 sn = mrb_class_name(mrb, sc);
162 if (strcmp(sn, class_name) == 0) {
171 mrb_debug_set_break_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t lineno)
177 if ((mrb == NULL)||(dbg == NULL)||(file == NULL)) {
178 return MRB_DEBUG_INVALID_ARGUMENT;
181 if (dbg->bpnum >= MAX_BREAKPOINT) {
182 return MRB_DEBUG_BREAK_NUM_OVER;
185 if (dbg->next_bpno > MAX_BREAKPOINTNO) {
186 return MRB_DEBUG_BREAK_NO_OVER;
189 /* file and lineno check (line type mrb_debug_line_ary only.) */
190 result = check_file_lineno(mrb, dbg->root_irep, file, lineno);
192 return MRB_DEBUG_BREAK_INVALID_FILE;
194 else if (result == MRB_DEBUG_BP_FILE_OK) {
195 return MRB_DEBUG_BREAK_INVALID_LINENO;
198 set_file = (char*)mrb_malloc(mrb, strlen(file) + 1);
201 dbg->bp[index].bpno = dbg->next_bpno;
203 dbg->bp[index].enable = TRUE;
204 dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE;
205 dbg->bp[index].point.linepoint.lineno = lineno;
208 strncpy(set_file, file, strlen(file) + 1);
210 dbg->bp[index].point.linepoint.file = set_file;
212 return dbg->bp[index].bpno;
216 mrb_debug_set_break_method(mrb_state *mrb, mrb_debug_context *dbg, const char *class_name, const char *method_name)
222 if ((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) {
223 return MRB_DEBUG_INVALID_ARGUMENT;
226 if (dbg->bpnum >= MAX_BREAKPOINT) {
227 return MRB_DEBUG_BREAK_NUM_OVER;
230 if (dbg->next_bpno > MAX_BREAKPOINTNO) {
231 return MRB_DEBUG_BREAK_NO_OVER;
234 if (class_name != NULL) {
235 set_class = (char*)mrb_malloc(mrb, strlen(class_name) + 1);
236 strncpy(set_class, class_name, strlen(class_name) + 1);
242 set_method = (char*)mrb_malloc(mrb, strlen(method_name) + 1);
244 strncpy(set_method, method_name, strlen(method_name) + 1);
247 dbg->bp[index].bpno = dbg->next_bpno;
249 dbg->bp[index].enable = TRUE;
250 dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD;
251 dbg->bp[index].point.methodpoint.method_name = set_method;
252 dbg->bp[index].point.methodpoint.class_name = set_class;
255 return dbg->bp[index].bpno;
259 mrb_debug_get_breaknum(mrb_state *mrb, mrb_debug_context *dbg)
261 if ((mrb == NULL) || (dbg == NULL)) {
262 return MRB_DEBUG_INVALID_ARGUMENT;
269 mrb_debug_get_break_all(mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint *bp)
271 uint32_t get_size = 0;
273 if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
274 return MRB_DEBUG_INVALID_ARGUMENT;
277 if (dbg->bpnum >= size) {
281 get_size = dbg->bpnum;
284 memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size);
290 mrb_debug_get_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno, mrb_debug_breakpoint *bp)
294 if ((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
295 return MRB_DEBUG_INVALID_ARGUMENT;
298 index = get_break_index(dbg, bpno);
299 if (index == MRB_DEBUG_BREAK_INVALID_NO) {
300 return MRB_DEBUG_BREAK_INVALID_NO;
303 bp->bpno = dbg->bp[index].bpno;
304 bp->enable = dbg->bp[index].enable;
305 bp->point = dbg->bp[index].point;
306 bp->type = dbg->bp[index].type;
312 mrb_debug_delete_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
317 if ((mrb == NULL) ||(dbg == NULL)) {
318 return MRB_DEBUG_INVALID_ARGUMENT;
321 index = get_break_index(dbg, bpno);
322 if (index == MRB_DEBUG_BREAK_INVALID_NO) {
323 return MRB_DEBUG_BREAK_INVALID_NO;
326 free_breakpoint(mrb, &dbg->bp[index]);
328 for(i = index ; i < dbg->bpnum; i++) {
329 if ((i + 1) == dbg->bpnum) {
330 memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint));
333 memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint));
343 mrb_debug_delete_break_all(mrb_state *mrb, mrb_debug_context *dbg)
347 if ((mrb == NULL) || (dbg == NULL)) {
348 return MRB_DEBUG_INVALID_ARGUMENT;
351 for(i = 0 ; i < dbg->bpnum ; i++) {
352 free_breakpoint(mrb, &dbg->bp[i]);
361 mrb_debug_enable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
365 if ((mrb == NULL) || (dbg == NULL)) {
366 return MRB_DEBUG_INVALID_ARGUMENT;
369 index = get_break_index(dbg, bpno);
370 if (index == MRB_DEBUG_BREAK_INVALID_NO) {
371 return MRB_DEBUG_BREAK_INVALID_NO;
374 dbg->bp[index].enable = TRUE;
380 mrb_debug_enable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
384 if ((mrb == NULL) || (dbg == NULL)) {
385 return MRB_DEBUG_INVALID_ARGUMENT;
388 for(i = 0 ; i < dbg->bpnum; i++) {
389 dbg->bp[i].enable = TRUE;
396 mrb_debug_disable_break(mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno)
400 if ((mrb == NULL) || (dbg == NULL)) {
401 return MRB_DEBUG_INVALID_ARGUMENT;
404 index = get_break_index(dbg, bpno);
405 if (index == MRB_DEBUG_BREAK_INVALID_NO) {
406 return MRB_DEBUG_BREAK_INVALID_NO;
409 dbg->bp[index].enable = FALSE;
415 mrb_debug_disable_break_all(mrb_state *mrb, mrb_debug_context *dbg)
419 if ((mrb == NULL) || (dbg == NULL)) {
420 return MRB_DEBUG_INVALID_ARGUMENT;
423 for(i = 0 ; i < dbg->bpnum; i++) {
424 dbg->bp[i].enable = FALSE;
431 check_start_pc_for_line(mrb_state *mrb, mrb_irep *irep, const mrb_code *pc, uint16_t line)
433 if (pc > irep->iseq) {
434 if (line == mrb_debug_get_line(mrb, irep, pc - irep->iseq - 1)) {
442 mrb_debug_check_breakpoint_line(mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t line)
444 mrb_debug_breakpoint *bp;
445 mrb_debug_linepoint *line_p;
448 if ((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) {
449 return MRB_DEBUG_INVALID_ARGUMENT;
452 if (!check_start_pc_for_line(mrb, dbg->irep, dbg->pc, line)) {
457 for(i=0; i<dbg->bpnum; i++) {
459 case MRB_DEBUG_BPTYPE_LINE:
460 if (bp->enable == TRUE) {
461 line_p = &bp->point.linepoint;
462 if ((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) {
467 case MRB_DEBUG_BPTYPE_METHOD:
469 case MRB_DEBUG_BPTYPE_NONE:
480 mrb_debug_check_breakpoint_method(mrb_state *mrb, mrb_debug_context *dbg, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc)
482 mrb_debug_breakpoint *bp;
486 if ((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) {
487 return MRB_DEBUG_INVALID_ARGUMENT;
491 for(i=0; i<dbg->bpnum; i++) {
492 if (bp->type == MRB_DEBUG_BPTYPE_METHOD) {
493 if (bp->enable == TRUE) {
494 bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc);
500 else if (bp->type == MRB_DEBUG_BPTYPE_NONE) {