byebug 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,8 +4,6 @@
4
4
  #include <ruby.h>
5
5
  #include <ruby/debug.h>
6
6
 
7
- typedef struct rb_trace_arg_struct rb_trace_point_t;
8
-
9
7
  /* flags */
10
8
  #define CTX_FL_SUSPEND (1<<1)
11
9
  #define CTX_FL_TRACING (1<<2)
@@ -28,44 +26,46 @@ typedef enum {
28
26
  CTX_STOP_CATCHPOINT
29
27
  } ctx_stop_reason;
30
28
 
31
- typedef struct debug_frame_t {
32
- struct debug_frame_t *prev;
33
- char *file;
34
- int line;
35
- VALUE method_id;
36
- VALUE defined_class;
37
- VALUE binding;
38
- VALUE self;
39
- } debug_frame_t;
40
-
41
29
  typedef struct {
42
- debug_frame_t *stack;
43
30
  int stack_size;
44
31
  int flags;
45
32
  ctx_stop_reason stop_reason;
33
+
46
34
  int dest_frame;
47
35
  int lines; /* # of lines in dest_frame before stopping */
48
36
  int steps; /* # of steps before stopping */
49
37
  int stop_frame; /* frame number after which we must stop */
50
- char *last_file;
51
- int last_line;
38
+
39
+ VALUE last_file;
40
+ VALUE last_line;
41
+
42
+ VALUE backtrace; /* [[loc, self, klass, binding], ...] */
52
43
  } debug_context_t;
53
44
 
45
+ enum frame_component { LOCATION, SELF, CLASS, BINDING };
46
+
47
+ struct call_with_inspection_data {
48
+ debug_context_t *dc;
49
+ VALUE context_obj;
50
+ ID id;
51
+ int argc;
52
+ VALUE *argv;
53
+ };
54
+
55
+
54
56
  /* functions */
55
57
  extern VALUE Init_context(VALUE mByebug);
56
- extern VALUE Context_create();
57
- extern VALUE Context_dup(debug_context_t *context);
58
- extern void reset_stepping_stop_points(debug_context_t *context);
59
58
 
60
- extern void push_frame(debug_context_t *context, char* file, int lineno,
61
- VALUE method_id, VALUE defined_class, VALUE binding,
62
- VALUE self);
59
+ extern VALUE context_create();
63
60
 
64
- extern void pop_frame(debug_context_t *context);
61
+ extern VALUE context_dup(debug_context_t *context);
62
+
63
+ extern void reset_stepping_stop_points(debug_context_t *context);
65
64
 
66
- extern void update_frame(debug_frame_t *context, char* file, int lineno,
67
- VALUE method_id, VALUE defined_class, VALUE binding,
68
- VALUE self);
65
+ extern VALUE call_with_debug_inspector(struct call_with_inspection_data *data);
66
+
67
+ extern VALUE context_backtrace_set(const rb_debug_inspector_t *inspector,
68
+ void *data);
69
69
 
70
70
  /* utility functions */
71
71
  static inline int
@@ -79,8 +79,9 @@ classname_cmp(VALUE name, VALUE klass)
79
79
  }
80
80
 
81
81
  /* breakpoints & catchpoints */
82
- enum bp_type {BP_POS_TYPE, BP_METHOD_TYPE};
83
- enum hit_condition {HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD};
82
+ enum bp_type { BP_POS_TYPE, BP_METHOD_TYPE };
83
+
84
+ enum hit_condition { HIT_COND_NONE, HIT_COND_GE, HIT_COND_EQ, HIT_COND_MOD };
84
85
 
85
86
  typedef struct {
86
87
  int id;
@@ -88,8 +89,8 @@ typedef struct {
88
89
  VALUE source;
89
90
  union
90
91
  {
91
- int line;
92
- ID mid;
92
+ int line;
93
+ ID mid;
93
94
  } pos;
94
95
  VALUE expr;
95
96
  VALUE enabled;
@@ -13,29 +13,6 @@ reset_stepping_stop_points(debug_context_t *context)
13
13
  context->stop_frame = -1;
14
14
  }
15
15
 
16
- static inline void
17
- delete_frame(debug_context_t *context)
18
- {
19
- debug_frame_t *frame;
20
-
21
- frame = context->stack;
22
- context->stack = frame->prev;
23
- context->stack_size--;
24
- xfree(frame);
25
- }
26
-
27
- extern void
28
- update_frame(debug_frame_t *frame, char* file, int lineno, VALUE method_id,
29
- VALUE defined_class, VALUE binding, VALUE self)
30
- {
31
- frame->file = file;
32
- frame->line = lineno;
33
- frame->method_id = method_id;
34
- frame->defined_class = defined_class;
35
- frame->binding = binding;
36
- frame->self = self;
37
- }
38
-
39
16
  static inline VALUE
40
17
  Context_stack_size(VALUE self)
41
18
  {
@@ -52,199 +29,220 @@ Context_dead(VALUE self)
52
29
  return CTX_FL_TEST(context, CTX_FL_DEAD) ? Qtrue : Qfalse;
53
30
  }
54
31
 
55
- extern void
56
- push_frame(debug_context_t *context, char* file, int lineno, VALUE method_id,
57
- VALUE defined_class, VALUE binding, VALUE self)
32
+ static void
33
+ context_mark(void *data)
34
+ {
35
+ debug_context_t *context = (debug_context_t *)data;
36
+ rb_gc_mark(context->backtrace);
37
+ }
38
+
39
+ static void
40
+ context_free(void *data)
58
41
  {
59
- debug_frame_t *frame;
60
42
 
61
- frame = ALLOC(debug_frame_t);
62
- update_frame(frame, file, lineno, method_id, defined_class, binding, self);
63
- frame->prev = context->stack;
64
- context->stack = frame;
65
- context->stack_size++;
66
43
  }
67
44
 
68
- extern void
69
- pop_frame(debug_context_t *context)
45
+ extern VALUE
46
+ context_create()
70
47
  {
71
- if (context->stack_size > 0) {
72
- delete_frame(context);
73
- }
48
+ debug_context_t *context = ALLOC(debug_context_t);
49
+
50
+ context->last_file = Qnil;
51
+ context->last_line = Qnil;
52
+ context->flags = 0;
53
+ context->stack_size = 0;
54
+ reset_stepping_stop_points(context);
55
+ context->stop_reason = CTX_STOP_NONE;
56
+ context->backtrace = Qnil;
57
+
58
+ return Data_Wrap_Struct(cContext, context_mark, context_free, context);
74
59
  }
75
60
 
76
- static void
77
- Context_mark(debug_context_t *context)
61
+ extern VALUE
62
+ context_dup(debug_context_t *context)
78
63
  {
79
- debug_frame_t *frame;
64
+ debug_context_t *new_context = ALLOC(debug_context_t);
80
65
 
81
- frame = context->stack;
82
- while (frame != NULL) {
83
- rb_gc_mark(frame->self);
84
- rb_gc_mark(frame->binding);
85
- frame = frame->prev;
86
- }
66
+ memcpy(new_context, context, sizeof(debug_context_t));
67
+ reset_stepping_stop_points(new_context);
68
+ new_context->backtrace = context->backtrace;
69
+ CTX_FL_SET(new_context, CTX_FL_DEAD);
70
+
71
+ return Data_Wrap_Struct(cContext, context_mark, context_free, new_context);
87
72
  }
88
73
 
89
- static void
90
- Context_free(debug_context_t *context) {
91
- while (context->stack_size > 0) {
92
- delete_frame(context);
93
- }
94
- xfree(context);
74
+ static VALUE
75
+ dc_backtrace(const debug_context_t *context)
76
+ {
77
+ if (NIL_P(context->backtrace))
78
+ rb_raise(rb_eRuntimeError, "Backtrace information is not available");
79
+
80
+ return context->backtrace;
95
81
  }
96
82
 
97
- extern VALUE
98
- Context_create()
83
+ static VALUE
84
+ dc_frame_get(const debug_context_t *context, int frame_index,
85
+ enum frame_component type)
99
86
  {
100
- debug_context_t *context;
87
+ if (frame_index >= RARRAY_LEN(dc_backtrace(context)))
88
+ rb_raise(rb_eRuntimeError, "That frame doesn't exist!");
101
89
 
102
- context = ALLOC(debug_context_t);
103
- context->stack_size = 0;
104
- context->stack = NULL;
105
- context->flags = 0;
106
- context->last_file = NULL;
107
- context->last_line = -1;
108
- reset_stepping_stop_points(context);
109
- return Data_Wrap_Struct(cContext, Context_mark, Context_free, context);
90
+ VALUE frame = rb_ary_entry(dc_backtrace(context), frame_index);
91
+ return rb_ary_entry(frame, type);
110
92
  }
111
93
 
112
- static void
113
- frame_copy(debug_frame_t *new_frame, debug_frame_t *old_frame)
94
+ static VALUE
95
+ dc_frame_location(const debug_context_t *context, int frame_index)
114
96
  {
115
- new_frame->file = old_frame->file;
116
- new_frame->line = old_frame->line;
117
- new_frame->method_id = old_frame->method_id;
118
- new_frame->defined_class = old_frame->defined_class;
119
- new_frame->binding = old_frame->binding;
120
- new_frame->self = old_frame->self;
97
+ return dc_frame_get(context, frame_index, LOCATION);
121
98
  }
122
99
 
123
- extern VALUE
124
- Context_dup(debug_context_t *context)
125
- {
126
- debug_context_t *new_context;
127
- debug_frame_t *source_frame = context->stack, *dest_frame, *new_frame;
128
-
129
- new_context = ALLOC(debug_context_t);
130
- memcpy(new_context, context, sizeof(debug_context_t));
131
- reset_stepping_stop_points(new_context);
132
- new_context->stack_size = context->stack_size;
133
- CTX_FL_SET(new_context, CTX_FL_DEAD);
134
- new_context->stack = ALLOC(debug_frame_t);
135
- frame_copy(new_context->stack, context->stack);
136
-
137
- new_frame = new_context->stack;
138
- while ((source_frame = source_frame->prev))
139
- {
140
- dest_frame = new_frame;
141
- new_frame = ALLOC(debug_frame_t);
142
- frame_copy(new_frame, source_frame);
143
- dest_frame->prev = new_frame;
144
- }
145
- return Data_Wrap_Struct(cContext, 0, Context_free, new_context);
100
+ static VALUE
101
+ dc_frame_self(const debug_context_t *context, int frame_index)
102
+ {
103
+ return dc_frame_get(context, frame_index, SELF);
146
104
  }
147
105
 
148
- static debug_frame_t*
149
- get_frame_no(debug_context_t *context, int frame_n)
106
+ static VALUE
107
+ dc_frame_class(const debug_context_t *context, int frame_index)
150
108
  {
151
- debug_frame_t *frame;
109
+ return dc_frame_get(context, frame_index, CLASS);
110
+ }
111
+
112
+ static VALUE
113
+ dc_frame_binding(const debug_context_t *context, int frame_index)
114
+ {
115
+ return dc_frame_get(context, frame_index, BINDING);
116
+ }
117
+
118
+ static VALUE
119
+ load_backtrace(const rb_debug_inspector_t *inspector)
120
+ {
121
+ VALUE backtrace = rb_ary_new();
122
+ VALUE locs = rb_debug_inspector_backtrace_locations(inspector);
152
123
  int i;
153
124
 
154
- if (frame_n < 0 || frame_n >= context->stack_size) {
155
- rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)",
156
- frame_n, context->stack_size);
157
- }
125
+ for (i=0; i<RARRAY_LEN(locs); i++)
126
+ {
127
+ VALUE frame = rb_ary_new();
128
+ rb_ary_push(frame, rb_ary_entry(locs, i));
129
+ rb_ary_push(frame, rb_debug_inspector_frame_self_get(inspector, i));
130
+ rb_ary_push(frame, rb_debug_inspector_frame_class_get(inspector, i));
131
+ rb_ary_push(frame, rb_debug_inspector_frame_binding_get(inspector, i));
158
132
 
159
- frame = context->stack;
160
- for (i = 0; i < frame_n; i++) {
161
- frame = frame->prev;
133
+ rb_ary_push(backtrace, frame);
162
134
  }
163
- return frame;
135
+
136
+ return backtrace;
137
+ }
138
+
139
+ extern VALUE
140
+ context_backtrace_set(const rb_debug_inspector_t *inspector, void *data)
141
+ {
142
+ debug_context_t *dc = (debug_context_t *)data;
143
+ dc->backtrace = load_backtrace(inspector);
144
+
145
+ return Qnil;
146
+ }
147
+
148
+ static VALUE
149
+ open_debug_inspector_i(const rb_debug_inspector_t *inspector, void *data)
150
+ {
151
+ struct call_with_inspection_data *cwi =
152
+ (struct call_with_inspection_data *)data;
153
+ cwi->dc->backtrace = load_backtrace(inspector);
154
+
155
+ return rb_funcall2(cwi->context_obj, cwi->id, cwi->argc, cwi->argv);
156
+ }
157
+
158
+ static VALUE
159
+ open_debug_inspector(struct call_with_inspection_data *cwi)
160
+ {
161
+ return rb_debug_inspector_open(open_debug_inspector_i, cwi);
162
+ }
163
+
164
+ static VALUE
165
+ close_debug_inspector(struct call_with_inspection_data *cwi)
166
+ {
167
+ cwi->dc->backtrace = Qnil;
168
+ return Qnil;
164
169
  }
165
170
 
171
+ extern VALUE
172
+ call_with_debug_inspector(struct call_with_inspection_data *data)
173
+ {
174
+ return rb_ensure(open_debug_inspector, (VALUE)data,
175
+ close_debug_inspector, (VALUE)data);
176
+ }
177
+
178
+ #define FRAME_SETUP \
179
+ debug_context_t *context; \
180
+ VALUE frame_no; \
181
+ int frame_n; \
182
+ Data_Get_Struct(self, debug_context_t, context); \
183
+ if (!rb_scan_args(argc, argv, "01", &frame_no)) \
184
+ frame_n = 0; \
185
+ else \
186
+ frame_n = FIX2INT(frame_no); \
187
+ if (frame_n < 0 || frame_n >= context->stack_size) \
188
+ { \
189
+ rb_raise(rb_eArgError, "Invalid frame number %d, stack (0...%d)", \
190
+ frame_n, context->stack_size-1); \
191
+ } \
192
+
166
193
  static VALUE
167
194
  Context_frame_file(int argc, VALUE *argv, VALUE self)
168
195
  {
169
- debug_context_t *context;
170
- debug_frame_t *frame;
171
- VALUE frame_no;
172
- int frame_n;
196
+ FRAME_SETUP;
197
+ VALUE loc;
173
198
 
174
- Data_Get_Struct(self, debug_context_t, context);
175
- frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
176
- frame = get_frame_no(context, frame_n);
177
- return rb_str_new2(frame->file);
199
+ loc = dc_frame_location(context, frame_n);
200
+ return rb_funcall(loc, rb_intern("absolute_path"), 0);
178
201
  }
179
202
 
180
203
  static VALUE
181
204
  Context_frame_line(int argc, VALUE *argv, VALUE self)
182
205
  {
183
- debug_context_t *context;
184
- debug_frame_t *frame;
185
- VALUE frame_no;
186
- int frame_n;
206
+ FRAME_SETUP;
207
+ VALUE loc;
187
208
 
188
- Data_Get_Struct(self, debug_context_t, context);
189
- frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
190
- frame = get_frame_no(context, frame_n);
191
- return INT2FIX(frame->line);
209
+ loc = dc_frame_location(context, frame_n);
210
+ return rb_funcall(loc, rb_intern("lineno"), 0);
192
211
  }
193
212
 
194
213
  static VALUE
195
214
  Context_frame_method(int argc, VALUE *argv, VALUE self)
196
215
  {
197
- debug_context_t *context;
198
- debug_frame_t *frame;
199
- VALUE frame_no;
200
- int frame_n;
216
+ FRAME_SETUP;
217
+ VALUE loc;
218
+
219
+ loc = dc_frame_location(context, frame_n);
220
+ return rb_str_intern(rb_funcall(loc, rb_intern("label"), 0));
201
221
 
202
- Data_Get_Struct(self, debug_context_t, context);
203
- frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
204
- frame = get_frame_no(context, frame_n);
205
- return frame->method_id;
206
222
  }
207
223
 
208
224
  static VALUE
209
225
  Context_frame_binding(int argc, VALUE *argv, VALUE self)
210
226
  {
211
- debug_context_t *context;
212
- debug_frame_t *frame;
213
- VALUE frame_no;
214
- int frame_n;
227
+ FRAME_SETUP;
215
228
 
216
- Data_Get_Struct(self, debug_context_t, context);
217
- frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
218
- frame = get_frame_no(context, frame_n);
219
- return frame->binding;
229
+ return dc_frame_binding(context, frame_n);
220
230
  }
221
231
 
222
232
  static VALUE
223
233
  Context_frame_self(int argc, VALUE *argv, VALUE self)
224
234
  {
225
- debug_context_t *context;
226
- debug_frame_t *frame;
227
- VALUE frame_no;
228
- int frame_n;
235
+ FRAME_SETUP;
229
236
 
230
- Data_Get_Struct(self, debug_context_t, context);
231
- frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
232
- frame = get_frame_no(context, frame_n);
233
- return frame->self;
237
+ return dc_frame_self(context, frame_n);
234
238
  }
235
239
 
236
240
  static VALUE
237
241
  Context_frame_class(int argc, VALUE *argv, VALUE self)
238
242
  {
239
- debug_context_t *context;
240
- debug_frame_t *frame;
241
- VALUE frame_no;
242
- int frame_n;
243
+ FRAME_SETUP;
243
244
 
244
- Data_Get_Struct(self, debug_context_t, context);
245
- frame_n = rb_scan_args(argc, argv, "01", &frame_no) == 0 ? 0 : FIX2INT(frame_no);
246
- frame = get_frame_no(context, frame_n);
247
- return frame->defined_class;
245
+ return dc_frame_class(context, frame_n);
248
246
  }
249
247
 
250
248
  static VALUE
@@ -336,7 +334,7 @@ Context_step_into(int argc, VALUE *argv, VALUE self)
336
334
  Data_Get_Struct(self, debug_context_t, context);
337
335
  context->steps = FIX2INT(steps);
338
336
 
339
- if(RTEST(force))
337
+ if (RTEST(force))
340
338
  CTX_FL_SET(context, CTX_FL_FORCE_MOVE);
341
339
  else
342
340
  CTX_FL_UNSET(context, CTX_FL_FORCE_MOVE);