byebug 1.3.1 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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);