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)


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

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



1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
# File 'ext/ruby_debug/ruby_debug.c', line 1981

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).



1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
# File 'ext/ruby_debug/ruby_debug.c', line 1723

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)


1742
1743
1744
# File 'ext/ruby_debug/ruby_debug.c', line 1742

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)


2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
# File 'ext/ruby_debug/ruby_debug.c', line 2027

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)


1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
# File 'ext/ruby_debug/ruby_debug.c', line 1813

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.



1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
# File 'ext/ruby_debug/ruby_debug.c', line 1760

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)


1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
# File 'ext/ruby_debug/ruby_debug.c', line 1781

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)


1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
# File 'ext/ruby_debug/ruby_debug.c', line 1957

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.



1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
# File 'ext/ruby_debug/ruby_debug.c', line 1760

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)


2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
# File 'ext/ruby_debug/ruby_debug.c', line 2005

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)


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

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)


2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
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
# File 'ext/ruby_debug/ruby_debug.c', line 2366

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 */
}

#resumenil

Resumes the thread from the suspended mode.

Returns:

  • (nil)


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

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.



2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
# File 'ext/ruby_debug/ruby_debug.c', line 2057

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.



1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
# File 'ext/ruby_debug/ruby_debug.c', line 1608

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.



1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
# File 'ext/ruby_debug/ruby_debug.c', line 1638

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.



1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
# File 'ext/ruby_debug/ruby_debug.c', line 1676

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.



1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
# File 'ext/ruby_debug/ruby_debug.c', line 1608

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



2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
# File 'ext/ruby_debug/ruby_debug.c', line 2264

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)


2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
# File 'ext/ruby_debug/ruby_debug.c', line 2133

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)


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

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)


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

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.



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

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)


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

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.



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

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;
}