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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/README.md +3 -2
- data/bin/byebug +1 -0
- data/byebug.gemspec +6 -5
- data/ext/byebug/breakpoint.c +29 -28
- data/ext/byebug/byebug.c +217 -184
- data/ext/byebug/byebug.h +30 -29
- data/ext/byebug/context.c +152 -154
- data/lib/byebug.rb +4 -0
- data/lib/byebug/command.rb +5 -7
- data/lib/byebug/commands/set.rb +1 -1
- data/lib/byebug/commands/show.rb +1 -1
- data/lib/byebug/context.rb +4 -9
- data/lib/byebug/processor.rb +2 -4
- data/lib/byebug/version.rb +1 -1
- data/test/display_test.rb +0 -2
- data/test/examples/list.rb +1 -1
- data/test/frame_test.rb +14 -18
- data/test/info_test.rb +3 -7
- metadata +9 -8
data/ext/byebug/byebug.h
CHANGED
@@ -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
|
-
|
51
|
-
|
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
|
61
|
-
VALUE method_id, VALUE defined_class, VALUE binding,
|
62
|
-
VALUE self);
|
59
|
+
extern VALUE context_create();
|
63
60
|
|
64
|
-
extern
|
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
|
67
|
-
|
68
|
-
|
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
|
-
|
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
|
-
|
92
|
-
|
92
|
+
int line;
|
93
|
+
ID mid;
|
93
94
|
} pos;
|
94
95
|
VALUE expr;
|
95
96
|
VALUE enabled;
|
data/ext/byebug/context.c
CHANGED
@@ -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
|
-
|
56
|
-
|
57
|
-
|
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
|
69
|
-
|
45
|
+
extern VALUE
|
46
|
+
context_create()
|
70
47
|
{
|
71
|
-
|
72
|
-
|
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
|
-
|
77
|
-
|
61
|
+
extern VALUE
|
62
|
+
context_dup(debug_context_t *context)
|
78
63
|
{
|
79
|
-
|
64
|
+
debug_context_t *new_context = ALLOC(debug_context_t);
|
80
65
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
98
|
-
|
83
|
+
static VALUE
|
84
|
+
dc_frame_get(const debug_context_t *context, int frame_index,
|
85
|
+
enum frame_component type)
|
99
86
|
{
|
100
|
-
|
87
|
+
if (frame_index >= RARRAY_LEN(dc_backtrace(context)))
|
88
|
+
rb_raise(rb_eRuntimeError, "That frame doesn't exist!");
|
101
89
|
|
102
|
-
|
103
|
-
|
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
|
113
|
-
|
94
|
+
static VALUE
|
95
|
+
dc_frame_location(const debug_context_t *context, int frame_index)
|
114
96
|
{
|
115
|
-
|
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
|
-
|
124
|
-
|
125
|
-
{
|
126
|
-
|
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
|
149
|
-
|
106
|
+
static VALUE
|
107
|
+
dc_frame_class(const debug_context_t *context, int frame_index)
|
150
108
|
{
|
151
|
-
|
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
|
-
|
155
|
-
|
156
|
-
|
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
|
-
|
160
|
-
for (i = 0; i < frame_n; i++) {
|
161
|
-
frame = frame->prev;
|
133
|
+
rb_ary_push(backtrace, frame);
|
162
134
|
}
|
163
|
-
|
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
|
-
|
170
|
-
|
171
|
-
VALUE frame_no;
|
172
|
-
int frame_n;
|
196
|
+
FRAME_SETUP;
|
197
|
+
VALUE loc;
|
173
198
|
|
174
|
-
|
175
|
-
|
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
|
-
|
184
|
-
|
185
|
-
VALUE frame_no;
|
186
|
-
int frame_n;
|
206
|
+
FRAME_SETUP;
|
207
|
+
VALUE loc;
|
187
208
|
|
188
|
-
|
189
|
-
|
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
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
-
|
212
|
-
debug_frame_t *frame;
|
213
|
-
VALUE frame_no;
|
214
|
-
int frame_n;
|
227
|
+
FRAME_SETUP;
|
215
228
|
|
216
|
-
|
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
|
-
|
226
|
-
debug_frame_t *frame;
|
227
|
-
VALUE frame_no;
|
228
|
-
int frame_n;
|
235
|
+
FRAME_SETUP;
|
229
236
|
|
230
|
-
|
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
|
-
|
240
|
-
debug_frame_t *frame;
|
241
|
-
VALUE frame_no;
|
242
|
-
int frame_n;
|
243
|
+
FRAME_SETUP;
|
243
244
|
|
244
|
-
|
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);
|