source: EcnlProtoTool/trunk/prototool/src/apibreak.c@ 279

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

ファイルを追加、更新。

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