source: EcnlProtoTool/trunk/mruby-1.2.0/mrbgems/mruby-bin-debugger/tools/mrdb/apibreak.c@ 321

Last change on this file since 321 was 321, checked in by coas-nagasima, 7 years ago

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 11.4 KB
Line 
1/*
2** apibreak.c
3**
4*/
5
6#include <string.h>
7#include "mruby.h"
8#include "mruby/irep.h"
9#include "mrdb.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"
16#include "apibreak.h"
17
18#define MAX_BREAKPOINTNO (MAX_BREAKPOINT * 1024)
19#define MRB_DEBUG_BP_FILE_OK (0x0001)
20#define MRB_DEBUG_BP_LINENO_OK (0x0002)
21
22static uint16_t
23check_lineno( mrb_irep_debug_info_file *info_file, uint16_t lineno )
24{
25 uint32_t count = info_file->line_entry_count;
26 uint16_t l_idx;
27
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]) {
31 return lineno;
32 }
33 }
34 } else {
35 for (l_idx = 0; l_idx < count; ++l_idx) {
36 if(lineno == info_file->lines.flat_map[l_idx].line) {
37 return lineno;
38 }
39 }
40 }
41
42 return 0;
43}
44
45static int32_t
46get_break_index( mrb_debug_context *dbg, int32_t bpno )
47{
48 uint32_t i;
49 int32_t index;
50 char hit = FALSE;
51
52 for(i = 0 ; i < dbg->bpnum; i++) {
53 if(dbg->bp[i].bpno == bpno) {
54 hit = TRUE;
55 index = i;
56 break;
57 }
58 }
59
60 if(hit == FALSE) {
61 return MRB_DEBUG_BREAK_INVALID_NO;
62 }
63
64 return index;
65}
66
67static void
68free_breakpoint( mrb_state *mrb, mrb_debug_breakpoint *bp )
69{
70 switch(bp->type) {
71 case MRB_DEBUG_BPTYPE_LINE:
72 mrb_free(mrb, (void*)bp->point.linepoint.file);
73 break;
74 case MRB_DEBUG_BPTYPE_METHOD:
75 mrb_free(mrb, (void*)bp->point.methodpoint.method_name);
76 if(bp->point.methodpoint.class_name != NULL) {
77 mrb_free(mrb, (void*)bp->point.methodpoint.class_name);
78 }
79 break;
80 default:
81 break;
82 }
83}
84
85static uint16_t
86check_file_lineno( struct mrb_irep *irep, const char *file, uint16_t lineno )
87{
88 mrb_irep_debug_info_file *info_file;
89 uint16_t result = 0;
90 uint16_t f_idx;
91 uint16_t fix_lineno;
92 uint16_t i;
93
94 for (f_idx = 0; f_idx < irep->debug_info->flen; ++f_idx) {
95 info_file = irep->debug_info->files[f_idx];
96 if(!strcmp(info_file->filename, file)) {
97 result = MRB_DEBUG_BP_FILE_OK;
98
99 fix_lineno = check_lineno( info_file, lineno );
100 if(fix_lineno != 0) {
101 return result | MRB_DEBUG_BP_LINENO_OK;
102 }
103 }
104 for ( i=0; i < irep->rlen; ++i ) {
105 result |= check_file_lineno(irep->reps[i], file, lineno);
106 if(result == (MRB_DEBUG_BP_FILE_OK | MRB_DEBUG_BP_LINENO_OK)) {
107 return result;
108 }
109 }
110 }
111 return result;
112}
113
114static const char*
115get_class_name( mrb_state *mrb, struct RClass *class_obj )
116{
117 struct RClass *outer;
118 mrb_sym class_sym;
119
120 outer = mrb_class_outer_module(mrb, class_obj);
121 class_sym = mrb_class_sym(mrb, class_obj, outer);
122 return mrb_sym2name(mrb, class_sym);
123}
124
125static int32_t
126compare_break_method( mrb_state *mrb, mrb_debug_breakpoint *bp, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc )
127{
128 const char* class_name;
129 const char* method_name;
130 struct RProc* m;
131 struct RClass* sc;
132 const char* sn;
133 mrb_sym ssym;
134 mrb_debug_methodpoint *method_p;
135 mrb_bool is_defined;
136
137 method_name = mrb_sym2name(mrb, method_sym);
138
139 method_p = &bp->point.methodpoint;
140 if(strcmp(method_p->method_name, method_name) == 0) {
141 class_name = get_class_name(mrb, class_obj);
142 if(class_name == NULL) {
143 if(method_p->class_name == NULL) {
144 return bp->bpno;
145 }
146 }
147 else if(method_p->class_name != NULL) {
148 m = mrb_method_search_vm(mrb, &class_obj, method_sym);
149 if(m == NULL) {
150 return MRB_DEBUG_OK;
151 }
152 if(MRB_PROC_CFUNC_P(m)) {
153 *isCfunc = TRUE;
154 }
155
156 is_defined = mrb_class_defined(mrb, method_p->class_name);
157 if(is_defined == FALSE) {
158 return MRB_DEBUG_OK;
159 }
160
161 sc = mrb_class_get(mrb, method_p->class_name);
162 ssym = mrb_symbol(mrb_check_intern_cstr(mrb, method_p->method_name));
163 m = mrb_method_search_vm(mrb, &sc, ssym);
164 if(m == NULL) {
165 return MRB_DEBUG_OK;
166 }
167
168 class_name = get_class_name(mrb, class_obj);
169 sn = get_class_name(mrb, sc);
170 if(strcmp(sn, class_name) == 0) {
171 return bp->bpno;
172 }
173 }
174 }
175 return MRB_DEBUG_OK;
176}
177
178int32_t
179mrb_debug_set_break_line( mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t lineno)
180{
181 int32_t index;
182 char* set_file;
183 uint16_t result;
184
185 if((mrb == NULL)||(dbg == NULL)||(file == NULL)) {
186 return MRB_DEBUG_INVALID_ARGUMENT;
187 }
188
189 if(dbg->bpnum >= MAX_BREAKPOINT) {
190 return MRB_DEBUG_BREAK_NUM_OVER;
191 }
192
193 if(dbg->next_bpno > MAX_BREAKPOINTNO) {
194 return MRB_DEBUG_BREAK_NO_OVER;
195 }
196
197 /* file and lineno check (line type mrb_debug_line_ary only.) */
198 result = check_file_lineno( dbg->root_irep, file, lineno );
199 if(result == 0) {
200 return MRB_DEBUG_BREAK_INVALID_FILE;
201 }else if(result == MRB_DEBUG_BP_FILE_OK) {
202 return MRB_DEBUG_BREAK_INVALID_LINENO;
203 }
204
205 set_file = mrb_malloc(mrb, strlen(file) + 1);
206
207 index = dbg->bpnum;
208 dbg->bp[index].bpno = dbg->next_bpno;
209 dbg->next_bpno++;
210 dbg->bp[index].enable = TRUE;
211 dbg->bp[index].type = MRB_DEBUG_BPTYPE_LINE;
212 dbg->bp[index].point.linepoint.lineno = lineno;
213 dbg->bpnum++;
214
215 strncpy(set_file, file, strlen(file) + 1);
216
217 dbg->bp[index].point.linepoint.file = set_file;
218
219 return dbg->bp[index].bpno;
220}
221
222int32_t
223mrb_debug_set_break_method( mrb_state *mrb, mrb_debug_context *dbg, const char *class_name, const char *method_name )
224{
225 int32_t index;
226 char* set_class;
227 char* set_method;
228
229 if((mrb == NULL) || (dbg == NULL) || (method_name == NULL)) {
230 return MRB_DEBUG_INVALID_ARGUMENT;
231 }
232
233 if(dbg->bpnum >= MAX_BREAKPOINT) {
234 return MRB_DEBUG_BREAK_NUM_OVER;
235 }
236
237 if(dbg->next_bpno > MAX_BREAKPOINTNO) {
238 return MRB_DEBUG_BREAK_NO_OVER;
239 }
240
241 if(class_name != NULL) {
242 set_class = mrb_malloc(mrb, strlen(class_name) + 1);
243 strncpy(set_class, class_name, strlen(class_name) + 1);
244 }
245 else {
246 set_class = NULL;
247 }
248
249 set_method = mrb_malloc(mrb, strlen(method_name) + 1);
250
251 strncpy(set_method, method_name, strlen(method_name) + 1);
252
253 index = dbg->bpnum;
254 dbg->bp[index].bpno = dbg->next_bpno;
255 dbg->next_bpno++;
256 dbg->bp[index].enable = TRUE;
257 dbg->bp[index].type = MRB_DEBUG_BPTYPE_METHOD;
258 dbg->bp[index].point.methodpoint.method_name = set_method;
259 dbg->bp[index].point.methodpoint.class_name = set_class;
260 dbg->bpnum++;
261
262 return dbg->bp[index].bpno;
263}
264
265int32_t
266mrb_debug_get_breaknum( mrb_state *mrb, mrb_debug_context *dbg )
267{
268 if((mrb == NULL) || (dbg == NULL)) {
269 return MRB_DEBUG_INVALID_ARGUMENT;
270 }
271
272 return dbg->bpnum;
273}
274
275int32_t
276mrb_debug_get_break_all( mrb_state *mrb, mrb_debug_context *dbg, uint32_t size, mrb_debug_breakpoint *bp )
277{
278 uint32_t get_size = 0;
279
280 if((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
281 return MRB_DEBUG_INVALID_ARGUMENT;
282 }
283
284 if(dbg->bpnum >= size) {
285 get_size = size;
286 }
287 else {
288 get_size = dbg->bpnum;
289 }
290
291 memcpy(bp, dbg->bp, sizeof(mrb_debug_breakpoint) * get_size);
292
293 return get_size;
294}
295
296int32_t
297mrb_debug_get_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno, mrb_debug_breakpoint *bp )
298{
299 uint32_t index;
300
301 if((mrb == NULL) || (dbg == NULL) || (bp == NULL)) {
302 return MRB_DEBUG_INVALID_ARGUMENT;
303 }
304
305 index = get_break_index(dbg, bpno);
306 if(index == MRB_DEBUG_BREAK_INVALID_NO) {
307 return MRB_DEBUG_BREAK_INVALID_NO;
308 }
309
310 bp->bpno = dbg->bp[index].bpno;
311 bp->enable = dbg->bp[index].enable;
312 bp->point = dbg->bp[index].point;
313 bp->type = dbg->bp[index].type;
314
315 return 0;
316}
317
318int32_t
319mrb_debug_delete_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno )
320{
321 uint32_t i;
322 int32_t index;
323
324 if((mrb == NULL) ||(dbg == NULL)) {
325 return MRB_DEBUG_INVALID_ARGUMENT;
326 }
327
328 index = get_break_index(dbg, bpno);
329 if(index == MRB_DEBUG_BREAK_INVALID_NO) {
330 return MRB_DEBUG_BREAK_INVALID_NO;
331 }
332
333 free_breakpoint(mrb, &dbg->bp[index]);
334
335 for(i = index ; i < dbg->bpnum; i++) {
336 if((i + 1) == dbg->bpnum) {
337 memset(&dbg->bp[i], 0, sizeof(mrb_debug_breakpoint));
338 }
339 else {
340 memcpy(&dbg->bp[i], &dbg->bp[i + 1], sizeof(mrb_debug_breakpoint));
341 }
342 }
343
344 dbg->bpnum--;
345
346 return MRB_DEBUG_OK;
347}
348
349int32_t
350mrb_debug_delete_break_all( mrb_state *mrb, mrb_debug_context *dbg )
351{
352 uint32_t i;
353
354 if((mrb == NULL) || (dbg == NULL)) {
355 return MRB_DEBUG_INVALID_ARGUMENT;
356 }
357
358 for(i = 0 ; i < dbg->bpnum ; i++) {
359 free_breakpoint(mrb, &dbg->bp[i]);
360 }
361
362 dbg->bpnum = 0;
363
364 return MRB_DEBUG_OK;
365}
366
367int32_t
368mrb_debug_enable_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno )
369{
370 int32_t index = 0;
371
372 if((mrb == NULL) || (dbg == NULL)) {
373 return MRB_DEBUG_INVALID_ARGUMENT;
374 }
375
376 index = get_break_index(dbg, bpno);
377 if(index == MRB_DEBUG_BREAK_INVALID_NO) {
378 return MRB_DEBUG_BREAK_INVALID_NO;
379 }
380
381 dbg->bp[index].enable = TRUE;
382
383 return MRB_DEBUG_OK;
384}
385
386int32_t
387mrb_debug_enable_break_all( mrb_state *mrb, mrb_debug_context *dbg )
388{
389 uint32_t i;
390
391 if((mrb == NULL) || (dbg == NULL)) {
392 return MRB_DEBUG_INVALID_ARGUMENT;
393 }
394
395 for(i = 0 ; i < dbg->bpnum; i++) {
396 dbg->bp[i].enable = TRUE;
397 }
398
399 return MRB_DEBUG_OK;
400}
401
402int32_t
403mrb_debug_disable_break( mrb_state *mrb, mrb_debug_context *dbg, uint32_t bpno )
404{
405 int32_t index = 0;
406
407 if((mrb == NULL) || (dbg == NULL)) {
408 return MRB_DEBUG_INVALID_ARGUMENT;
409 }
410
411 index = get_break_index(dbg, bpno);
412 if(index == MRB_DEBUG_BREAK_INVALID_NO) {
413 return MRB_DEBUG_BREAK_INVALID_NO;
414 }
415
416 dbg->bp[index].enable = FALSE;
417
418 return MRB_DEBUG_OK;
419}
420
421int32_t
422mrb_debug_disable_break_all( mrb_state *mrb, mrb_debug_context *dbg )
423{
424 uint32_t i;
425
426 if((mrb == NULL) || (dbg == NULL)) {
427 return MRB_DEBUG_INVALID_ARGUMENT;
428 }
429
430 for(i = 0 ; i < dbg->bpnum; i++) {
431 dbg->bp[i].enable = FALSE;
432 }
433
434 return MRB_DEBUG_OK;
435}
436
437static mrb_bool
438check_start_pc_for_line( mrb_irep *irep, mrb_code *pc, uint16_t line )
439{
440 if( pc > irep->iseq ) {
441 if( line == mrb_debug_get_line(irep, (uint32_t)(pc - irep->iseq - 1))) {
442 return FALSE;
443 }
444 }
445 return TRUE;
446}
447
448int32_t
449mrb_debug_check_breakpoint_line( mrb_state *mrb, mrb_debug_context *dbg, const char *file, uint16_t line )
450{
451 mrb_debug_breakpoint *bp;
452 mrb_debug_linepoint *line_p;
453 int i;
454
455 if((mrb == NULL) || (dbg == NULL) || (file == NULL) || (line <= 0)) {
456 return MRB_DEBUG_INVALID_ARGUMENT;
457 }
458
459 if(!check_start_pc_for_line(dbg->irep, dbg->pc, line)) {
460 return MRB_DEBUG_OK;
461 }
462
463 bp = dbg->bp;
464 for(i=0; i<dbg->bpnum; i++) {
465 switch (bp->type) {
466 case MRB_DEBUG_BPTYPE_LINE:
467 if(bp->enable == TRUE) {
468 line_p = &bp->point.linepoint;
469 if((strcmp(line_p->file, file) == 0) && (line_p->lineno == line)) {
470 return bp->bpno;
471 }
472 }
473 break;
474 case MRB_DEBUG_BPTYPE_METHOD:
475 break;
476 case MRB_DEBUG_BPTYPE_NONE:
477 default:
478 return MRB_DEBUG_OK;
479 }
480 bp++;
481 }
482 return MRB_DEBUG_OK;
483}
484
485
486int32_t
487mrb_debug_check_breakpoint_method( mrb_state *mrb, mrb_debug_context *dbg, struct RClass *class_obj, mrb_sym method_sym, mrb_bool* isCfunc )
488{
489 mrb_debug_breakpoint *bp;
490 int32_t bpno;
491 int i;
492
493 if((mrb == NULL) || (dbg == NULL) || (class_obj == NULL)) {
494 return MRB_DEBUG_INVALID_ARGUMENT;
495 }
496
497 bp = dbg->bp;
498 for(i=0; i<dbg->bpnum; i++) {
499 if(bp->type == MRB_DEBUG_BPTYPE_METHOD) {
500 if(bp->enable == TRUE) {
501 bpno = compare_break_method(mrb, bp, class_obj, method_sym, isCfunc);
502 if(bpno > 0) {
503 return bpno;
504 }
505 }
506 }
507 else if(bp->type == MRB_DEBUG_BPTYPE_NONE) {
508 break;
509 }
510 bp++;
511 }
512
513 return 0;
514}
515
516
Note: See TracBrowser for help on using the repository browser.