ruby-debug-base19 0.11.18 → 0.11.19
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.
- data/ext/ruby_debug/ruby_debug.c +140 -38
- data/ext/ruby_debug/ruby_debug.h +3 -1
- data/lib/ruby-debug-base.rb +1 -1
- metadata +2 -2
data/ext/ruby_debug/ruby_debug.c
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <stdio.h>
|
3
|
+
#include <ctype.h>
|
3
4
|
#include <vm_core.h>
|
4
5
|
#include <iseq.h>
|
5
6
|
#include <version.h>
|
@@ -43,6 +44,7 @@ static debug_context_t *last_debug_context = NULL;
|
|
43
44
|
VALUE rdebug_threads_tbl = Qnil; /* Context for each of the threads */
|
44
45
|
VALUE mDebugger; /* Ruby Debugger Module object */
|
45
46
|
|
47
|
+
static VALUE opt_call_c_function;
|
46
48
|
static VALUE cThreadsTable;
|
47
49
|
static VALUE cContext;
|
48
50
|
static VALUE cDebugThread;
|
@@ -71,7 +73,6 @@ static VALUE context_copy_locals(debug_context_t *,debug_frame_t *, VALUE);
|
|
71
73
|
static void context_suspend_0(debug_context_t *);
|
72
74
|
static void context_resume_0(debug_context_t *);
|
73
75
|
static void copy_scalar_args(debug_frame_t *);
|
74
|
-
static void debug_event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE klass);
|
75
76
|
|
76
77
|
typedef struct locked_thread_t {
|
77
78
|
VALUE thread_id;
|
@@ -383,6 +384,8 @@ debug_context_create(VALUE thread)
|
|
383
384
|
debug_context->stack_size = 0;
|
384
385
|
debug_context->thread_id = ref2id(thread);
|
385
386
|
debug_context->breakpoint = Qnil;
|
387
|
+
debug_context->jump_pc = NULL;
|
388
|
+
debug_context->jump_cfp = NULL;
|
386
389
|
if(rb_obj_class(thread) == cDebugThread)
|
387
390
|
CTX_FL_SET(debug_context, CTX_FL_IGNORE);
|
388
391
|
return Data_Wrap_Struct(cContext, debug_context_mark, debug_context_free, debug_context);
|
@@ -418,7 +421,7 @@ debug_context_dup(debug_context_t *debug_context, VALUE self)
|
|
418
421
|
}
|
419
422
|
|
420
423
|
static void
|
421
|
-
thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_context)
|
424
|
+
thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_context, int create)
|
422
425
|
{
|
423
426
|
threads_table_t *threads_table;
|
424
427
|
VALUE thread_id;
|
@@ -437,8 +440,18 @@ thread_context_lookup(VALUE thread, VALUE *context, debug_context_t **debug_cont
|
|
437
440
|
Data_Get_Struct(rdebug_threads_tbl, threads_table_t, threads_table);
|
438
441
|
if(!st_lookup(threads_table->tbl, thread_id, context))
|
439
442
|
{
|
440
|
-
|
441
|
-
|
443
|
+
if (create)
|
444
|
+
{
|
445
|
+
*context = debug_context_create(thread);
|
446
|
+
st_insert(threads_table->tbl, thread_id, *context);
|
447
|
+
}
|
448
|
+
else
|
449
|
+
{
|
450
|
+
*context = 0;
|
451
|
+
if (debug_context)
|
452
|
+
*debug_context = NULL;
|
453
|
+
return;
|
454
|
+
}
|
442
455
|
}
|
443
456
|
|
444
457
|
Data_Get_Struct(*context, debug_context_t, l_debug_context);
|
@@ -709,7 +722,7 @@ debug_event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE kl
|
|
709
722
|
|
710
723
|
if ((iseq == NULL) && (event != RUBY_EVENT_RAISE))
|
711
724
|
return;
|
712
|
-
thread_context_lookup(thread->self, &context, &debug_context);
|
725
|
+
thread_context_lookup(thread->self, &context, &debug_context, 1);
|
713
726
|
|
714
727
|
if ((event == RUBY_EVENT_LINE) || (event == RUBY_EVENT_CALL))
|
715
728
|
{
|
@@ -803,12 +816,7 @@ debug_event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE kl
|
|
803
816
|
else
|
804
817
|
set_frame_source(event, debug_context, self, file, line, mid);
|
805
818
|
|
806
|
-
if (CTX_FL_TEST(debug_context,
|
807
|
-
{
|
808
|
-
CTX_FL_UNSET(debug_context, CTX_FL_JUMPING);
|
809
|
-
break;
|
810
|
-
}
|
811
|
-
else if (CTX_FL_TEST(debug_context, CTX_FL_CATCHING))
|
819
|
+
if (CTX_FL_TEST(debug_context, CTX_FL_CATCHING))
|
812
820
|
{
|
813
821
|
debug_frame_t *top_frame = get_top_frame(debug_context);
|
814
822
|
|
@@ -1195,7 +1203,7 @@ debug_current_context(VALUE self)
|
|
1195
1203
|
debug_check_started();
|
1196
1204
|
|
1197
1205
|
thread = rb_thread_current();
|
1198
|
-
thread_context_lookup(thread, &context, NULL);
|
1206
|
+
thread_context_lookup(thread, &context, NULL, 1);
|
1199
1207
|
|
1200
1208
|
return context;
|
1201
1209
|
}
|
@@ -1212,7 +1220,7 @@ debug_thread_context(VALUE self, VALUE thread)
|
|
1212
1220
|
VALUE context;
|
1213
1221
|
|
1214
1222
|
debug_check_started();
|
1215
|
-
thread_context_lookup(thread, &context, NULL);
|
1223
|
+
thread_context_lookup(thread, &context, NULL, 1);
|
1216
1224
|
return context;
|
1217
1225
|
}
|
1218
1226
|
|
@@ -1239,7 +1247,7 @@ debug_contexts(VALUE self)
|
|
1239
1247
|
for(i = 0; i < RARRAY_LEN(list); i++)
|
1240
1248
|
{
|
1241
1249
|
thread = rb_ary_entry(list, i);
|
1242
|
-
thread_context_lookup(thread, &context, NULL);
|
1250
|
+
thread_context_lookup(thread, &context, NULL, 1);
|
1243
1251
|
rb_ary_push(new_list, context);
|
1244
1252
|
}
|
1245
1253
|
threads_table_clear(rdebug_threads_tbl);
|
@@ -1271,7 +1279,7 @@ debug_suspend(VALUE self)
|
|
1271
1279
|
debug_check_started();
|
1272
1280
|
|
1273
1281
|
context_list = debug_contexts(self);
|
1274
|
-
thread_context_lookup(rb_thread_current(), ¤t, NULL);
|
1282
|
+
thread_context_lookup(rb_thread_current(), ¤t, NULL, 1);
|
1275
1283
|
|
1276
1284
|
for(i = 0; i < RARRAY_LEN(context_list); i++)
|
1277
1285
|
{
|
@@ -1303,7 +1311,7 @@ debug_resume(VALUE self)
|
|
1303
1311
|
|
1304
1312
|
context_list = debug_contexts(self);
|
1305
1313
|
|
1306
|
-
thread_context_lookup(rb_thread_current(), ¤t, NULL);
|
1314
|
+
thread_context_lookup(rb_thread_current(), ¤t, NULL, 1);
|
1307
1315
|
for(i = 0; i < RARRAY_LEN(context_list); i++)
|
1308
1316
|
{
|
1309
1317
|
context = rb_ary_entry(context_list, i);
|
@@ -1440,7 +1448,7 @@ debug_set_debug(VALUE self, VALUE value)
|
|
1440
1448
|
static VALUE
|
1441
1449
|
debug_thread_inherited(VALUE klass)
|
1442
1450
|
{
|
1443
|
-
|
1451
|
+
rb_raise(rb_eRuntimeError, "Can't inherit Debugger::DebugThread class");
|
1444
1452
|
}
|
1445
1453
|
|
1446
1454
|
/*
|
@@ -1755,12 +1763,32 @@ context_frame_line(int argc, VALUE *argv, VALUE self)
|
|
1755
1763
|
{
|
1756
1764
|
VALUE frame;
|
1757
1765
|
debug_context_t *debug_context;
|
1766
|
+
debug_frame_t *debug_frame;
|
1767
|
+
rb_control_frame_t *cfp;
|
1768
|
+
rb_control_frame_t *cfp_end;
|
1769
|
+
rb_thread_t *th;
|
1770
|
+
VALUE *pc;
|
1758
1771
|
|
1759
1772
|
debug_check_started();
|
1760
1773
|
frame = optional_frame_position(argc, argv);
|
1761
1774
|
Data_Get_Struct(self, debug_context_t, debug_context);
|
1775
|
+
GetThreadPtr(context_thread_0(debug_context), th);
|
1776
|
+
|
1777
|
+
debug_frame = get_top_frame(debug_context);
|
1778
|
+
if (debug_frame == NULL)
|
1779
|
+
return(INT2FIX(0));
|
1762
1780
|
|
1763
|
-
|
1781
|
+
pc = GET_FRAME->info.runtime.last_pc;
|
1782
|
+
cfp_end = RUBY_VM_END_CONTROL_FRAME(th);
|
1783
|
+
cfp = GET_FRAME->info.runtime.cfp;
|
1784
|
+
while (cfp > (rb_control_frame_t*)th->stack)
|
1785
|
+
{
|
1786
|
+
if ((cfp->iseq != NULL) && (pc >= cfp->iseq->iseq_encoded) && (pc < cfp->iseq->iseq_encoded + cfp->iseq->iseq_size))
|
1787
|
+
return(INT2FIX(rb_vm_get_sourceline(cfp)));
|
1788
|
+
cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
return(INT2FIX(0));
|
1764
1792
|
}
|
1765
1793
|
|
1766
1794
|
/*
|
@@ -1883,7 +1911,7 @@ context_copy_locals(debug_context_t *debug_context, debug_frame_t *debug_frame,
|
|
1883
1911
|
{
|
1884
1912
|
rb_thread_t *th;
|
1885
1913
|
rb_control_frame_t *block_frame = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
|
1886
|
-
|
1914
|
+
GetThreadPtr(context_thread_0(debug_context), th);
|
1887
1915
|
while (block_frame > (rb_control_frame_t*)th->stack)
|
1888
1916
|
{
|
1889
1917
|
if (block_frame->iseq == cfp->block_iseq)
|
@@ -2243,6 +2271,32 @@ context_stop_reason(VALUE self)
|
|
2243
2271
|
return ID2SYM(rb_intern(sym_name));
|
2244
2272
|
}
|
2245
2273
|
|
2274
|
+
static rb_control_frame_t *
|
2275
|
+
FUNC_FASTCALL(do_jump)(rb_thread_t *th, rb_control_frame_t *cfp)
|
2276
|
+
{
|
2277
|
+
VALUE context;
|
2278
|
+
debug_context_t *debug_context;
|
2279
|
+
|
2280
|
+
thread_context_lookup(th->self, &context, &debug_context, 0);
|
2281
|
+
if (debug_context == NULL)
|
2282
|
+
rb_raise(rb_eRuntimeError, "Lost context in jump");
|
2283
|
+
cfp->pc[-2] = debug_context->saved_jump_ins[0];
|
2284
|
+
cfp->pc[-1] = debug_context->saved_jump_ins[1];
|
2285
|
+
|
2286
|
+
cfp = debug_context->jump_cfp;
|
2287
|
+
if ((debug_context->jump_pc < cfp->iseq->iseq_encoded) || (debug_context->jump_pc >= cfp->iseq->iseq_encoded + cfp->iseq->iseq_size))
|
2288
|
+
rb_raise(rb_eRuntimeError, "Invalid jump PC target");
|
2289
|
+
cfp->pc = debug_context->jump_pc;
|
2290
|
+
|
2291
|
+
debug_context->jump_pc = NULL;
|
2292
|
+
debug_context->jump_cfp = NULL;
|
2293
|
+
debug_context->last_line = 0;
|
2294
|
+
debug_context->last_file = NULL;
|
2295
|
+
debug_context->stop_next = 1;
|
2296
|
+
th->cfp = cfp;
|
2297
|
+
return(cfp);
|
2298
|
+
}
|
2299
|
+
|
2246
2300
|
/*
|
2247
2301
|
* call-seq:
|
2248
2302
|
* context.jump(line, file) -> bool
|
@@ -2255,39 +2309,74 @@ context_jump(int argc, VALUE *argv, VALUE self)
|
|
2255
2309
|
debug_context_t *debug_context;
|
2256
2310
|
debug_frame_t *debug_frame;
|
2257
2311
|
VALUE line, file;
|
2258
|
-
const char *file_str;
|
2259
2312
|
int i;
|
2260
|
-
|
2313
|
+
rb_thread_t *th;
|
2314
|
+
rb_control_frame_t *cfp;
|
2315
|
+
rb_control_frame_t *cfp_end;
|
2316
|
+
rb_control_frame_t *cfp_start = NULL;
|
2317
|
+
|
2318
|
+
debug_check_started();
|
2261
2319
|
|
2262
2320
|
Data_Get_Struct(self, debug_context_t, debug_context);
|
2321
|
+
GetThreadPtr(context_thread_0(debug_context), th);
|
2263
2322
|
debug_frame = get_top_frame(debug_context);
|
2323
|
+
if (debug_frame == NULL)
|
2324
|
+
rb_raise(rb_eRuntimeError, "No frames collected.");
|
2264
2325
|
|
2265
|
-
if (
|
2266
|
-
rb_raise(rb_eArgError, "wrong number of arguments (%d for
|
2267
|
-
rb_scan_args(argc, argv, "
|
2326
|
+
if (argc != 2)
|
2327
|
+
rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc);
|
2328
|
+
rb_scan_args(argc, argv, "2", &line, &file);
|
2268
2329
|
|
2269
2330
|
line = FIX2INT(line);
|
2270
|
-
if (file == Qnil)
|
2271
|
-
file_str = debug_frame->file;
|
2272
|
-
else
|
2273
|
-
file_str = RSTRING_PTR(file);
|
2274
2331
|
|
2275
|
-
|
2276
|
-
|
2332
|
+
/* find topmost frame of the debugged code */
|
2333
|
+
cfp = th->cfp;
|
2334
|
+
cfp_end = RUBY_VM_END_CONTROL_FRAME(th);
|
2335
|
+
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, cfp_end))
|
2277
2336
|
{
|
2278
|
-
if (
|
2337
|
+
if (cfp->pc == debug_frame->info.runtime.last_pc)
|
2279
2338
|
{
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
CTX_FL_SET(debug_context, CTX_FL_JUMPING);
|
2285
|
-
return Qtrue;
|
2339
|
+
cfp_start = cfp;
|
2340
|
+
if ((cfp->pc - cfp->iseq->iseq_encoded) >= (cfp->iseq->iseq_size - 1))
|
2341
|
+
return(INT2FIX(1)); /* no space for opt_call_c_function hijack */
|
2342
|
+
break;
|
2286
2343
|
}
|
2344
|
+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
2287
2345
|
}
|
2288
|
-
|
2346
|
+
if (cfp_start == NULL)
|
2347
|
+
return(INT2FIX(2)); /* couldn't find frame; should never happen */
|
2348
|
+
|
2349
|
+
/* find target frame to jump to */
|
2350
|
+
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, cfp_end))
|
2351
|
+
{
|
2352
|
+
if ((cfp->iseq != NULL) && (rb_str_cmp(file, cfp->iseq->filename) == 0))
|
2353
|
+
{
|
2354
|
+
for (i = 0; i < cfp->iseq->insn_info_size; i++)
|
2355
|
+
{
|
2356
|
+
if (cfp->iseq->insn_info_table[i].line_no != line)
|
2357
|
+
continue;
|
2358
|
+
|
2359
|
+
/* hijack the currently running code so that we can change the frame PC(s) */
|
2360
|
+
debug_context->saved_jump_ins[0] = cfp_start->pc[0];
|
2361
|
+
debug_context->saved_jump_ins[1] = cfp_start->pc[1];
|
2362
|
+
cfp_start->pc[0] = opt_call_c_function;
|
2363
|
+
cfp_start->pc[1] = (VALUE)do_jump;
|
2364
|
+
|
2365
|
+
debug_context->jump_cfp = cfp;
|
2366
|
+
debug_context->jump_pc =
|
2367
|
+
cfp->iseq->iseq_encoded + cfp->iseq->insn_info_table[i].position;
|
2368
|
+
|
2369
|
+
return(INT2FIX(0)); /* success */
|
2370
|
+
}
|
2371
|
+
}
|
2372
|
+
|
2373
|
+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
|
2374
|
+
}
|
2375
|
+
|
2376
|
+
return(INT2FIX(3)); /* couldn't find a line and file frame match */
|
2289
2377
|
}
|
2290
2378
|
|
2379
|
+
|
2291
2380
|
/*
|
2292
2381
|
* Document-class: Context
|
2293
2382
|
*
|
@@ -2378,6 +2467,19 @@ debug_add_breakpoint(int argc, VALUE *argv, VALUE self)
|
|
2378
2467
|
void
|
2379
2468
|
Init_ruby_debug()
|
2380
2469
|
{
|
2470
|
+
rb_iseq_t iseq;
|
2471
|
+
iseq.iseq = &opt_call_c_function;
|
2472
|
+
iseq.iseq_size = 1;
|
2473
|
+
iseq.iseq_encoded = NULL;
|
2474
|
+
|
2475
|
+
opt_call_c_function = (VALUE)BIN(opt_call_c_function);
|
2476
|
+
rb_iseq_translate_threaded_code(&iseq);
|
2477
|
+
if (iseq.iseq_encoded != iseq.iseq)
|
2478
|
+
{
|
2479
|
+
opt_call_c_function = iseq.iseq_encoded[0];
|
2480
|
+
xfree(iseq.iseq_encoded);
|
2481
|
+
}
|
2482
|
+
|
2381
2483
|
mDebugger = rb_define_module("Debugger");
|
2382
2484
|
rb_define_const(mDebugger, "VERSION", rb_str_new2(DEBUG_VERSION));
|
2383
2485
|
rb_define_module_function(mDebugger, "start_", debug_start, 0);
|
data/ext/ruby_debug/ruby_debug.h
CHANGED
@@ -13,7 +13,6 @@ enum ctx_stop_reason {CTX_STOP_NONE, CTX_STOP_STEP, CTX_STOP_BREAKPOINT,
|
|
13
13
|
#define CTX_FL_STEPPED (1<<8)
|
14
14
|
#define CTX_FL_FORCE_MOVE (1<<9)
|
15
15
|
#define CTX_FL_CATCHING (1<<10)
|
16
|
-
#define CTX_FL_JUMPING (1<<11)
|
17
16
|
|
18
17
|
#define CTX_FL_TEST(c,f) ((c)->flags & (f))
|
19
18
|
#define CTX_FL_SET(c,f) do { (c)->flags |= (f); } while (0)
|
@@ -69,6 +68,9 @@ typedef struct {
|
|
69
68
|
int last_line;
|
70
69
|
VALUE breakpoint;
|
71
70
|
debug_catch_t catch_table;
|
71
|
+
VALUE saved_jump_ins[2];
|
72
|
+
rb_control_frame_t *jump_cfp;
|
73
|
+
VALUE *jump_pc;
|
72
74
|
} debug_context_t;
|
73
75
|
|
74
76
|
/* variables in ruby_debug.c */
|
data/lib/ruby-debug-base.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-debug-base19
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.19
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kent Sibilev
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-
|
13
|
+
date: 2009-09-01 00:00:00 -07:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|