Class: Debugger::Context

Inherits:
Object
  • Object
show all
Defined in:
lib/ruby-debug-base.rb,
ext/ruby_debug/ruby_debug.c

Instance Method Summary collapse

Instance Method Details

#__c_frame_bindingObject



20
# File 'lib/ruby-debug-base.rb', line 20

alias __c_frame_binding frame_binding

#breakpointObject

Returns a context-specific temporary Breakpoint object.



267
268
269
270
271
272
273
274
275
276
# File 'ext/ruby_debug/breakpoint.c', line 267

VALUE
context_breakpoint(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return debug_context->breakpoint;
}

#dead?Boolean

Returns true if context doesn’t represent a live context and is created during post-mortem exception handling.

Returns:

  • (Boolean)


2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
# File 'ext/ruby_debug/ruby_debug.c', line 2265

static VALUE
context_dead(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_DEAD) ? Qtrue : Qfalse;
}

#frame_args(frame_position = 0) ⇒ Object

Returns frame’s argument parameters



2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
# File 'ext/ruby_debug/ruby_debug.c', line 2000

static VALUE
context_frame_args(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;
    if (debug_frame->dead)
        return debug_frame->info.copy.args;
    else
        return context_copy_args(debug_frame);
}

#frame_args_info(frame_position = 0) ⇒ Object #track_frame_argsObject

Returns info saved about call arguments (if any saved).



1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
# File 'ext/ruby_debug/ruby_debug.c', line 1742

static VALUE
context_frame_args_info(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    return RTEST(track_frame_args) ? GET_FRAME->arg_ary : Qnil;
}

#frame_binding(frame_position = 0) ⇒ Binding

Returns frame’s binding.

Returns:

  • (Binding)


1761
1762
1763
# File 'ext/ruby_debug/ruby_debug.c', line 1761

def frame_binding(frame)
  __c_frame_binding(frame) || hbinding(frame)
end

#frame_class(frame_position) ⇒ Object

Returns the real class of the frame. It could be different than context.frame_self(frame).class

Returns:

  • (Object)


2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
# File 'ext/ruby_debug/ruby_debug.c', line 2046

static VALUE
context_frame_class(int argc, VALUE *argv, VALUE self)
{
    VALUE klass;
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    rb_control_frame_t *cfp;
    
    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;

    cfp = debug_frame->info.runtime.cfp;

    klass = real_class(cfp->iseq->klass);
    if(TYPE(klass) == T_CLASS || TYPE(klass) == T_MODULE)
        return klass;
    return Qnil;
}

#frame_file(frame_position) ⇒ String

Returns the name of the file.

Returns:

  • (String)


1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
# File 'ext/ruby_debug/ruby_debug.c', line 1832

static VALUE
context_frame_file(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    return(GET_FRAME->info.runtime.cfp->iseq->filename);
}

#frame_method(frame_position = 0) ⇒ Object

Returns the sym of the called method.



1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
# File 'ext/ruby_debug/ruby_debug.c', line 1779

static VALUE
context_frame_id(int argc, VALUE *argv, VALUE self)
{
    ID id;
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    id = GET_FRAME->info.runtime.cfp->iseq->defined_method_id;
    return id ? ID2SYM(id): Qnil;
}

#frame_line(frame_position) ⇒ Integer

Returns the line number in the file.

Returns:

  • (Integer)


1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
# File 'ext/ruby_debug/ruby_debug.c', line 1800

static VALUE
context_frame_line(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    rb_thread_t *th;
    rb_control_frame_t *cfp;
    VALUE *pc;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);
    GetThreadPtr(context_thread_0(debug_context), th);

    pc = GET_FRAME->info.runtime.last_pc;
    cfp = GET_FRAME->info.runtime.cfp;
    while (cfp >= th->cfp)
    {
        if ((cfp->iseq != NULL) && (pc >= cfp->iseq->iseq_encoded) && (pc < cfp->iseq->iseq_encoded + cfp->iseq->iseq_size))
            return(INT2FIX(rb_vm_get_sourceline(cfp)));
        cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp);
    }

    return(INT2FIX(0));
}

#frame_locals(frame) ⇒ Hash

Returns frame’s local variables.

Returns:

  • (Hash)


1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
# File 'ext/ruby_debug/ruby_debug.c', line 1976

static VALUE
context_frame_locals(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    
    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;
    if (debug_frame->dead)
        return debug_frame->info.copy.locals;
    else
        return context_copy_locals(debug_context, debug_frame, self);
}

#frame_method(frame_position = 0) ⇒ Object

Returns the sym of the called method.



1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
# File 'ext/ruby_debug/ruby_debug.c', line 1779

static VALUE
context_frame_id(int argc, VALUE *argv, VALUE self)
{
    ID id;
    VALUE frame;
    debug_context_t *debug_context;

    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    id = GET_FRAME->info.runtime.cfp->iseq->defined_method_id;
    return id ? ID2SYM(id): Qnil;
}

#frame_self(frame_postion = 0) ⇒ Object

Returns self object of the frame.

Returns:

  • (Object)


2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
# File 'ext/ruby_debug/ruby_debug.c', line 2024

static VALUE
context_frame_self(int argc, VALUE *argv, VALUE self)
{
    VALUE frame;
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    
    debug_check_started();
    frame = optional_frame_position(argc, argv);
    Data_Get_Struct(self, debug_context_t, debug_context);

    debug_frame = GET_FRAME;
    return(debug_frame->self);
}

#ignored?Boolean

Returns the ignore flag for the current context.

Returns:

  • (Boolean)


2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
# File 'ext/ruby_debug/ruby_debug.c', line 2247

static VALUE
context_ignored(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_IGNORE) ? Qtrue : Qfalse;
}

#interruptObject



16
17
18
# File 'lib/ruby-debug-base.rb', line 16

def interrupt
  self.stop_next = 1
end

#jump(line, file) ⇒ Boolean

Returns true if jump to line in filename file was successful.

Returns:

  • (Boolean)


2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
# File 'ext/ruby_debug/ruby_debug.c', line 2385

static VALUE
context_jump(VALUE self, VALUE line, VALUE file)
{
    debug_context_t *debug_context;
    debug_frame_t *debug_frame;
    int i;
    rb_thread_t *th;
    rb_control_frame_t *cfp;
    rb_control_frame_t *cfp_end;
    rb_control_frame_t *cfp_start = NULL;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    GetThreadPtr(context_thread_0(debug_context), th);
    debug_frame = get_top_frame(debug_context);
    if (debug_frame == NULL)
        rb_raise(rb_eRuntimeError, "No frames collected.");

    line = FIX2INT(line);

    /* find topmost frame of the debugged code */
    cfp = th->cfp;
    cfp_end = RUBY_VM_END_CONTROL_FRAME(th);
    while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, cfp_end))
    {
        if (cfp->pc == debug_frame->info.runtime.last_pc)
        {
            cfp_start = cfp;
            if ((cfp->pc - cfp->iseq->iseq_encoded) >= (cfp->iseq->iseq_size - 1))
                return(INT2FIX(1)); /* no space for opt_call_c_function hijack */
            break;
        }
        cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
    }
    if (cfp_start == NULL)
        return(INT2FIX(2)); /* couldn't find frame; should never happen */

    /* find target frame to jump to */
    while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, cfp_end))
    {
        if ((cfp->iseq != NULL) && (rb_str_cmp(file, cfp->iseq->filename) == 0))
        {
            for (i = 0; i < cfp->iseq->insn_info_size; i++)
            {
                if (cfp->iseq->insn_info_table[i].line_no != line)
                    continue;

                /* hijack the currently running code so that we can change the frame PC */
                debug_context->saved_jump_ins[0] = cfp_start->pc[0];
                debug_context->saved_jump_ins[1] = cfp_start->pc[1];
                cfp_start->pc[0] = opt_call_c_function;
                cfp_start->pc[1] = (VALUE)do_jump;

                debug_context->jump_cfp = cfp;
                debug_context->jump_pc =
                    cfp->iseq->iseq_encoded + cfp->iseq->insn_info_table[i].position;

                return(INT2FIX(0)); /* success */
            }
        }

        cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
    }

    return(INT2FIX(3)); /* couldn't find a line and file frame match */
}

#breakBoolean

Returns true if context is currently running and set flag to break it at next line

Returns:

  • (Boolean)


2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
# File 'ext/ruby_debug/ruby_debug.c', line 2459

static VALUE
context_pause(VALUE self)
{
    debug_context_t *debug_context;
    rb_thread_t *th;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if (CTX_FL_TEST(debug_context, CTX_FL_DEAD))
        return(Qfalse);

    GetThreadPtr(context_thread_0(debug_context), th);
    if (th == GET_THREAD())
        return(Qfalse);

    debug_context->thread_pause = 1;
    return(Qtrue);
}

#resumenil

Resumes the thread from the suspended mode.

Returns:

  • (nil)


2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
# File 'ext/ruby_debug/ruby_debug.c', line 2189

static VALUE
context_resume(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if(!CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
        rb_raise(rb_eRuntimeError, "Thread is not suspended.");
    context_resume_0(debug_context);
    return Qnil;
}

#set_breakpoint(source, pos, condition = nil) ⇒ Object

Sets a context-specific temporary breakpoint, which can be used to implement ‘Run to Cursor’ debugger function. When this breakpoint is reached, it will be cleared out.

source is a name of a file or a class. pos is a line number or a method name if source is a class name. condition is a string which is evaluated to true when this breakpoint is activated.



291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'ext/ruby_debug/breakpoint.c', line 291

VALUE
context_set_breakpoint(int argc, VALUE *argv, VALUE self)
{
    VALUE result;
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    result = create_breakpoint_from_args(argc, argv, 0);
    debug_context->breakpoint = result;
    return result;
}

#stack_sizeObject

Returns the size of the context stack.



2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
# File 'ext/ruby_debug/ruby_debug.c', line 2076

static VALUE
context_stack_size(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);

    return INT2FIX(debug_context->stack_size);
}

#step(steps, force = false) ⇒ Object

Stops the current context after a number of steps are made. force parameter (if true) ensures that the cursor moves from the current line.



1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
# File 'ext/ruby_debug/ruby_debug.c', line 1627

static VALUE
context_stop_next(int argc, VALUE *argv, VALUE self)
{
    VALUE steps, force;
    debug_context_t *debug_context;

    debug_check_started();

    rb_scan_args(argc, argv, "11", &steps, &force);
    if(FIX2INT(steps) < 0)
        rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");

    Data_Get_Struct(self, debug_context_t, debug_context);
    debug_context->stop_next = FIX2INT(steps);
    if(RTEST(force))
        CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);

    return steps;
}

#step_over(steps, frame = nil, force = false) ⇒ Object

Steps over a steps number of times. Make step over operation on frame, by default the current frame. force parameter (if true) ensures that the cursor moves from the current line.



1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
# File 'ext/ruby_debug/ruby_debug.c', line 1657

static VALUE
context_step_over(int argc, VALUE *argv, VALUE self)
{
    VALUE lines, frame, force;
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);
    if(debug_context->stack_size == 0)
        rb_raise(rb_eRuntimeError, "No frames collected.");

    rb_scan_args(argc, argv, "12", &lines, &frame, &force);
    debug_context->stop_line = FIX2INT(lines);
    CTX_FL_UNSET(debug_context, CTX_FL_STEPPED);
    if(frame == Qnil)
    {
        debug_context->dest_frame = debug_context->stack_size;
    }
    else
    {
        if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
            rb_raise(rb_eRuntimeError, "Destination frame is out of range.");
        debug_context->dest_frame = debug_context->stack_size - FIX2INT(frame);
    }
    if(RTEST(force))
        CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);

    return Qnil;
}

#stop_frame(frame) ⇒ Object

Stops when a frame with number frame is activated. Implements finish and next commands.



1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
# File 'ext/ruby_debug/ruby_debug.c', line 1695

static VALUE
context_stop_frame(VALUE self, VALUE frame)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);
    if(FIX2INT(frame) < 0 && FIX2INT(frame) >= debug_context->stack_size)
        rb_raise(rb_eRuntimeError, "Stop frame is out of range.");
    debug_context->stop_frame = debug_context->stack_size - FIX2INT(frame);

    return frame;
}

#step(steps, force = false) ⇒ Object

Stops the current context after a number of steps are made. force parameter (if true) ensures that the cursor moves from the current line.



1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
# File 'ext/ruby_debug/ruby_debug.c', line 1627

static VALUE
context_stop_next(int argc, VALUE *argv, VALUE self)
{
    VALUE steps, force;
    debug_context_t *debug_context;

    debug_check_started();

    rb_scan_args(argc, argv, "11", &steps, &force);
    if(FIX2INT(steps) < 0)
        rb_raise(rb_eRuntimeError, "Steps argument can't be negative.");

    Data_Get_Struct(self, debug_context_t, debug_context);
    debug_context->stop_next = FIX2INT(steps);
    if(RTEST(force))
        CTX_FL_SET(debug_context, CTX_FL_FORCE_MOVE);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_FORCE_MOVE);

    return steps;
}

#stop_reasonObject

Returns the reason for the stop. It maybe of the following values: :initial, :step, :breakpoint, :catchpoint, :post-mortem



2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
# File 'ext/ruby_debug/ruby_debug.c', line 2283

static VALUE
context_stop_reason(VALUE self)
{
    debug_context_t *debug_context;
    const char * sym_name;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    
    switch(debug_context->stop_reason)
    {
        case CTX_STOP_STEP:
            sym_name = "step";
            break;
        case CTX_STOP_BREAKPOINT:
            sym_name = "breakpoint";
            break;
        case CTX_STOP_CATCHPOINT:
            sym_name = "catchpoint";
            break;
        case CTX_STOP_NONE:
        default:
            sym_name = "none";
    }
    if(CTX_FL_TEST(debug_context, CTX_FL_DEAD))
        sym_name = "post-mortem";
    
    return ID2SYM(rb_intern(sym_name));
}

#suspendnil

Suspends the thread when it is running.

Returns:

  • (nil)


2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
# File 'ext/ruby_debug/ruby_debug.c', line 2152

static VALUE
context_suspend(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if(CTX_FL_TEST(debug_context, CTX_FL_SUSPEND))
        rb_raise(rb_eRuntimeError, "Already suspended.");
    context_suspend_0(debug_context);
    return Qnil;
}

#suspended?Boolean

Returns true if the thread is suspended by debugger.

Returns:

  • (Boolean)


2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
# File 'ext/ruby_debug/ruby_debug.c', line 2172

static VALUE
context_is_suspended(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_SUSPEND) ? Qtrue : Qfalse;
}

#thnumInteger

Returns the context’s number.

Returns:

  • (Integer)


2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
# File 'ext/ruby_debug/ruby_debug.c', line 2110

static VALUE
context_thnum(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);
    
    return INT2FIX(debug_context->thnum);
}

#threadObject

Returns a thread this context is associated with.



2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
# File 'ext/ruby_debug/ruby_debug.c', line 2093

static VALUE
context_thread(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();
    Data_Get_Struct(self, debug_context_t, debug_context);

    return(id2ref(debug_context->thread_id));
}

#tracingBoolean

Returns the tracing flag for the current context.

Returns:

  • (Boolean)


2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
# File 'ext/ruby_debug/ruby_debug.c', line 2209

static VALUE
context_tracing(VALUE self)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    return CTX_FL_TEST(debug_context, CTX_FL_TRACING) ? Qtrue : Qfalse;
}

#tracing=(bool) ⇒ Object

Controls the tracing for this context.



2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
# File 'ext/ruby_debug/ruby_debug.c', line 2226

static VALUE
context_set_tracing(VALUE self, VALUE value)
{
    debug_context_t *debug_context;

    debug_check_started();

    Data_Get_Struct(self, debug_context_t, debug_context);
    if(RTEST(value))
        CTX_FL_SET(debug_context, CTX_FL_TRACING);
    else
        CTX_FL_UNSET(debug_context, CTX_FL_TRACING);
    return value;
}