ruby-debug-base19 0.11.18 → 0.11.19
Sign up to get free protection for your applications and to get access to all the features.
- 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
|