trepanning 0.0.4
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/ChangeLog +4422 -0
- data/LICENSE +23 -0
- data/NEWS +12 -0
- data/README.textile +56 -0
- data/Rakefile +171 -0
- data/app/Makefile +7 -0
- data/app/breakpoint.rb +157 -0
- data/app/brkptmgr.rb +149 -0
- data/app/condition.rb +22 -0
- data/app/core.rb +203 -0
- data/app/default.rb +54 -0
- data/app/disassemble.rb +61 -0
- data/app/display.rb +148 -0
- data/app/file.rb +135 -0
- data/app/frame.rb +275 -0
- data/app/irb.rb +112 -0
- data/app/mock.rb +22 -0
- data/app/options.rb +122 -0
- data/app/run.rb +95 -0
- data/app/thread.rb +24 -0
- data/app/util.rb +32 -0
- data/bin/trepan +63 -0
- data/data/custom_require.rb +44 -0
- data/data/irbrc +55 -0
- data/data/prelude.rb +38 -0
- data/interface/base_intf.rb +95 -0
- data/interface/script.rb +103 -0
- data/interface/user.rb +90 -0
- data/io/base_io.rb +92 -0
- data/io/input.rb +111 -0
- data/io/string_array.rb +155 -0
- data/lib/Makefile +7 -0
- data/lib/trepanning.rb +277 -0
- data/processor/breakpoint.rb +108 -0
- data/processor/command/alias.rb +55 -0
- data/processor/command/backtrace.rb +95 -0
- data/processor/command/base/cmd.rb +97 -0
- data/processor/command/base/subcmd.rb +207 -0
- data/processor/command/base/submgr.rb +178 -0
- data/processor/command/base/subsubcmd.rb +102 -0
- data/processor/command/base/subsubmgr.rb +182 -0
- data/processor/command/break.rb +85 -0
- data/processor/command/condition.rb +64 -0
- data/processor/command/continue.rb +61 -0
- data/processor/command/debug.rb +85 -0
- data/processor/command/delete.rb +54 -0
- data/processor/command/directory.rb +43 -0
- data/processor/command/disable.rb +65 -0
- data/processor/command/disassemble.rb +103 -0
- data/processor/command/display.rb +81 -0
- data/processor/command/down.rb +56 -0
- data/processor/command/enable.rb +43 -0
- data/processor/command/exit.rb +54 -0
- data/processor/command/finish.rb +81 -0
- data/processor/command/frame.rb +117 -0
- data/processor/command/help.rb +146 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/args.rb +56 -0
- data/processor/command/info_subcmd/breakpoints.rb +162 -0
- data/processor/command/info_subcmd/file.rb +162 -0
- data/processor/command/info_subcmd/frame.rb +39 -0
- data/processor/command/info_subcmd/iseq.rb +83 -0
- data/processor/command/info_subcmd/locals.rb +88 -0
- data/processor/command/info_subcmd/program.rb +54 -0
- data/processor/command/info_subcmd/registers.rb +72 -0
- data/processor/command/info_subcmd/registers_subcmd/dfp.rb +38 -0
- data/processor/command/info_subcmd/registers_subcmd/helper.rb +40 -0
- data/processor/command/info_subcmd/registers_subcmd/lfp.rb +54 -0
- data/processor/command/info_subcmd/registers_subcmd/pc.rb +44 -0
- data/processor/command/info_subcmd/registers_subcmd/sp.rb +75 -0
- data/processor/command/info_subcmd/return.rb +40 -0
- data/processor/command/info_subcmd/thread.rb +106 -0
- data/processor/command/irb.rb +106 -0
- data/processor/command/kill.rb +58 -0
- data/processor/command/list.rb +327 -0
- data/processor/command/macro.rb +65 -0
- data/processor/command/next.rb +89 -0
- data/processor/command/nocache.rb +33 -0
- data/processor/command/print.rb +37 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/quit.rb +62 -0
- data/processor/command/raise.rb +47 -0
- data/processor/command/reload.rb +28 -0
- data/processor/command/reload_subcmd/command.rb +34 -0
- data/processor/command/restart.rb +57 -0
- data/processor/command/save.rb +60 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/auto.rb +27 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +67 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +49 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +51 -0
- data/processor/command/set_subcmd/basename.rb +39 -0
- data/processor/command/set_subcmd/debug.rb +27 -0
- data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +49 -0
- data/processor/command/set_subcmd/debug_subcmd/except.rb +35 -0
- data/processor/command/set_subcmd/debug_subcmd/macro.rb +35 -0
- data/processor/command/set_subcmd/debug_subcmd/skip.rb +35 -0
- data/processor/command/set_subcmd/debug_subcmd/stack.rb +45 -0
- data/processor/command/set_subcmd/different.rb +67 -0
- data/processor/command/set_subcmd/events.rb +71 -0
- data/processor/command/set_subcmd/max.rb +35 -0
- data/processor/command/set_subcmd/max_subcmd/list.rb +50 -0
- data/processor/command/set_subcmd/max_subcmd/stack.rb +60 -0
- data/processor/command/set_subcmd/max_subcmd/string.rb +53 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +50 -0
- data/processor/command/set_subcmd/return.rb +66 -0
- data/processor/command/set_subcmd/sp.rb +62 -0
- data/processor/command/set_subcmd/substitute.rb +25 -0
- data/processor/command/set_subcmd/substitute_subcmd/eval.rb +98 -0
- data/processor/command/set_subcmd/substitute_subcmd/path.rb +55 -0
- data/processor/command/set_subcmd/substitute_subcmd/string.rb +72 -0
- data/processor/command/set_subcmd/timer.rb +68 -0
- data/processor/command/set_subcmd/trace.rb +43 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +56 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +54 -0
- data/processor/command/set_subcmd/trace_subcmd/var.rb +61 -0
- data/processor/command/show.rb +27 -0
- data/processor/command/show_subcmd/alias.rb +50 -0
- data/processor/command/show_subcmd/args.rb +50 -0
- data/processor/command/show_subcmd/auto.rb +27 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +38 -0
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +34 -0
- data/processor/command/show_subcmd/auto_subcmd/list.rb +36 -0
- data/processor/command/show_subcmd/basename.rb +28 -0
- data/processor/command/show_subcmd/debug.rb +27 -0
- data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +31 -0
- data/processor/command/show_subcmd/debug_subcmd/except.rb +33 -0
- data/processor/command/show_subcmd/debug_subcmd/macro.rb +32 -0
- data/processor/command/show_subcmd/debug_subcmd/skip.rb +33 -0
- data/processor/command/show_subcmd/debug_subcmd/stack.rb +32 -0
- data/processor/command/show_subcmd/different.rb +37 -0
- data/processor/command/show_subcmd/events.rb +40 -0
- data/processor/command/show_subcmd/macro.rb +45 -0
- data/processor/command/show_subcmd/max.rb +31 -0
- data/processor/command/show_subcmd/max_subcmd/list.rb +39 -0
- data/processor/command/show_subcmd/max_subcmd/stack.rb +35 -0
- data/processor/command/show_subcmd/max_subcmd/string.rb +41 -0
- data/processor/command/show_subcmd/max_subcmd/width.rb +36 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +84 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +38 -0
- data/processor/command/source.rb +74 -0
- data/processor/command/step.rb +139 -0
- data/processor/command/stepi.rb +63 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/undisplay.rb +63 -0
- data/processor/command/up.rb +92 -0
- data/processor/default.rb +45 -0
- data/processor/display.rb +17 -0
- data/processor/eval.rb +88 -0
- data/processor/eventbuf.rb +131 -0
- data/processor/frame.rb +230 -0
- data/processor/help.rb +72 -0
- data/processor/hook.rb +128 -0
- data/processor/load_cmds.rb +102 -0
- data/processor/location.rb +126 -0
- data/processor/main.rb +364 -0
- data/processor/mock.rb +100 -0
- data/processor/msg.rb +26 -0
- data/processor/running.rb +170 -0
- data/processor/subcmd.rb +159 -0
- data/processor/validate.rb +395 -0
- data/test/example/fname with blank.rb +1 -0
- data/test/example/gcd-xx.rb +18 -0
- data/test/example/gcd.rb +19 -0
- data/test/example/gcd1.rb +24 -0
- data/test/example/null.rb +1 -0
- data/test/example/thread1.rb +3 -0
- data/test/functional/fn_helper.rb +119 -0
- data/test/functional/test-break.rb +87 -0
- data/test/functional/test-condition.rb +59 -0
- data/test/functional/test-debugger-call-bug.rb +31 -0
- data/test/functional/test-delete.rb +71 -0
- data/test/functional/test-finish.rb +44 -0
- data/test/functional/test-immediate-step-bug.rb +35 -0
- data/test/functional/test-next.rb +77 -0
- data/test/functional/test-raise.rb +73 -0
- data/test/functional/test-return.rb +100 -0
- data/test/functional/test-step.rb +274 -0
- data/test/functional/test-stepbug.rb +40 -0
- data/test/functional/test-trace-var.rb +40 -0
- data/test/functional/tmp/b1.rb +5 -0
- data/test/functional/tmp/s1.rb +9 -0
- data/test/functional/tmp/t2.rb +6 -0
- data/test/integration/file-diff.rb +88 -0
- data/test/integration/helper.rb +52 -0
- data/test/integration/test-fname-with-blank.rb +11 -0
- data/test/integration/test-quit.rb +11 -0
- data/test/integration/try-test-enable.rb +11 -0
- data/test/unit/cmd-helper.rb +44 -0
- data/test/unit/test-app-brkpt.rb +30 -0
- data/test/unit/test-app-brkptmgr.rb +56 -0
- data/test/unit/test-app-disassemble.rb +60 -0
- data/test/unit/test-app-file.rb +46 -0
- data/test/unit/test-app-frame.rb +49 -0
- data/test/unit/test-app-options.rb +60 -0
- data/test/unit/test-app-run.rb +19 -0
- data/test/unit/test-app-thread.rb +25 -0
- data/test/unit/test-app-util.rb +17 -0
- data/test/unit/test-base-subcmd.rb +59 -0
- data/test/unit/test-bin-trepan.rb +48 -0
- data/test/unit/test-cmd-alias.rb +50 -0
- data/test/unit/test-cmd-break.rb +80 -0
- data/test/unit/test-cmd-endisable.rb +59 -0
- data/test/unit/test-cmd-help.rb +100 -0
- data/test/unit/test-cmd-kill.rb +47 -0
- data/test/unit/test-cmd-quit.rb +26 -0
- data/test/unit/test-cmd-step.rb +45 -0
- data/test/unit/test-intf-user.rb +45 -0
- data/test/unit/test-io-input.rb +26 -0
- data/test/unit/test-proc-eval.rb +26 -0
- data/test/unit/test-proc-frame.rb +77 -0
- data/test/unit/test-proc-help.rb +15 -0
- data/test/unit/test-proc-hook.rb +29 -0
- data/test/unit/test-proc-load_cmds.rb +40 -0
- data/test/unit/test-proc-main.rb +99 -0
- data/test/unit/test-proc-validate.rb +90 -0
- data/test/unit/test-subcmd-help.rb +48 -0
- metadata +358 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require_relative 'base/cmd'
|
|
4
|
+
require_relative '../../app/disassemble'
|
|
5
|
+
require_relative '../../app/file'
|
|
6
|
+
|
|
7
|
+
class Trepan::Command::DisassembleCommand < Trepan::Command
|
|
8
|
+
include Trepan::Disassemble
|
|
9
|
+
include Trepanning
|
|
10
|
+
|
|
11
|
+
unless defined?(HELP)
|
|
12
|
+
HELP =
|
|
13
|
+
"disassemble [thing] [full]
|
|
14
|
+
|
|
15
|
+
With no argument, disassemble the current frame. With a method,
|
|
16
|
+
disassemble that method. '.' can be used to indicate the instruction
|
|
17
|
+
sequence for the current frame.
|
|
18
|
+
|
|
19
|
+
By default, just this instruction sequence is disassembled, not others
|
|
20
|
+
which may be accessed off of this one, including any catch table the
|
|
21
|
+
instruction sequence might have. If 'full' is given, all instruction
|
|
22
|
+
sequences are include.
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
|
|
26
|
+
disassemble
|
|
27
|
+
disas . # Same as above
|
|
28
|
+
disas . full # At least the instruction sequence above but maybe more
|
|
29
|
+
disas require_relative # disassemble method 'require_relative'
|
|
30
|
+
"
|
|
31
|
+
|
|
32
|
+
ALIASES = %w(disas disassem) # Note we have disable
|
|
33
|
+
CATEGORY = 'data'
|
|
34
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
35
|
+
NEED_STACK = true
|
|
36
|
+
SHORT_HELP = 'Disassemble Ruby VM instructions'
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# FIXME: put in processor/data.rb?
|
|
40
|
+
|
|
41
|
+
def marked_disassemble(iseq, include_children)
|
|
42
|
+
iseqs = include_children ? iseq.child_iseqs : [iseq]
|
|
43
|
+
iseqs.each do |iseq|
|
|
44
|
+
ary = mark_disassembly(iseq.disasm_nochildren,
|
|
45
|
+
@proc.frame.iseq.equal?(iseq),
|
|
46
|
+
@proc.frame.pc_offset,
|
|
47
|
+
iseq.brkpts)
|
|
48
|
+
msg ary
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Run command.
|
|
53
|
+
def run(args)
|
|
54
|
+
|
|
55
|
+
obj = nil
|
|
56
|
+
include_children =
|
|
57
|
+
if args.size > 1 && args[-1] == 'full'
|
|
58
|
+
args.pop
|
|
59
|
+
true
|
|
60
|
+
else
|
|
61
|
+
false
|
|
62
|
+
end
|
|
63
|
+
if args.size == 1 || '.' == args[1]
|
|
64
|
+
# Form is: "disassemble" or "disassemble ."
|
|
65
|
+
if @proc.frame.type == 'CFUNC'
|
|
66
|
+
errmsg "Can't handle C functions yet."
|
|
67
|
+
return
|
|
68
|
+
elsif @proc.frame.iseq
|
|
69
|
+
marked_disassemble(@proc.frame.iseq, include_children)
|
|
70
|
+
return
|
|
71
|
+
end
|
|
72
|
+
else
|
|
73
|
+
if !(matches = find_iseqs(ISEQS__, args[1])).empty?
|
|
74
|
+
# FIXME: do something if there is more than one
|
|
75
|
+
iseq = matches[0]
|
|
76
|
+
else
|
|
77
|
+
iseq = @proc.object_iseq(args[1])
|
|
78
|
+
end
|
|
79
|
+
marked_disassemble(iseq, include_children) if iseq
|
|
80
|
+
return
|
|
81
|
+
end
|
|
82
|
+
errmsg("Sorry can't handle right now.")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if __FILE__ == $0
|
|
87
|
+
# Demo it.
|
|
88
|
+
require 'thread_frame'
|
|
89
|
+
|
|
90
|
+
require_relative '../mock'
|
|
91
|
+
name = File.basename(__FILE__, '.rb')
|
|
92
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
93
|
+
def small_fn(cmd, name)
|
|
94
|
+
cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
|
|
95
|
+
cmd.run [name]
|
|
96
|
+
end
|
|
97
|
+
small_fn(cmd, name)
|
|
98
|
+
p = Proc.new do
|
|
99
|
+
|x,y| x + y
|
|
100
|
+
end
|
|
101
|
+
cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
|
|
102
|
+
cmd.run([name, 'p'])
|
|
103
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require_relative 'base/cmd'
|
|
4
|
+
|
|
5
|
+
class Trepan::Command::DisplayCommand < Trepan::Command
|
|
6
|
+
|
|
7
|
+
unless defined?(HELP)
|
|
8
|
+
HELP = <<EOH
|
|
9
|
+
display [format] EXP
|
|
10
|
+
|
|
11
|
+
Print value of expression EXP each time the program stops. FMT may be
|
|
12
|
+
used before EXP and may be one of 'c' for char, 'x' for hex, 'o' for
|
|
13
|
+
octal, 'f' for float or 's' for string.
|
|
14
|
+
|
|
15
|
+
For now, display expressions are only evaluated when in the same
|
|
16
|
+
instruction sequence as the frame that was in effect when the display
|
|
17
|
+
expression was set. This is a departure from gdb and we may allow for
|
|
18
|
+
more flexibility in the future to specify whether this should be the
|
|
19
|
+
case or not.
|
|
20
|
+
|
|
21
|
+
With no argument, evaluate and display all currently requested
|
|
22
|
+
auto-display expressions. Use "undisplay" to cancel display
|
|
23
|
+
requests previously made.
|
|
24
|
+
EOH
|
|
25
|
+
|
|
26
|
+
CATEGORY = 'data'
|
|
27
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
28
|
+
NEED_STACK = false
|
|
29
|
+
SHORT_HELP = 'Display expressions when entering debugger'
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def run(args)
|
|
33
|
+
|
|
34
|
+
if args.size == 1
|
|
35
|
+
# Display anything active
|
|
36
|
+
@proc.run_eval_display
|
|
37
|
+
else
|
|
38
|
+
if %w(/c /x /o /f /s).member?(args[1])
|
|
39
|
+
if 2 == args.size
|
|
40
|
+
errmsg("Expecting an expression after the format")
|
|
41
|
+
return
|
|
42
|
+
end
|
|
43
|
+
format = args[1]
|
|
44
|
+
expr = args[2..-1].join(' ')
|
|
45
|
+
else
|
|
46
|
+
format = nil
|
|
47
|
+
expr = args[1..-1].join(' ')
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
dp = @proc.displays.add(@proc.frame, expr, format)
|
|
51
|
+
unless dp
|
|
52
|
+
errmsg('Error evaluating "%s" in the current frame' % expr)
|
|
53
|
+
return
|
|
54
|
+
end
|
|
55
|
+
msg(dp.to_s(@proc.frame))
|
|
56
|
+
@proc.cmdloop_prehooks.insert_if_new(5, *@proc.display_hook)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
if __FILE__ == $0
|
|
62
|
+
# Demo it.
|
|
63
|
+
require 'thread_frame'
|
|
64
|
+
require_relative '../mock'
|
|
65
|
+
name = File.basename(__FILE__, '.rb')
|
|
66
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
67
|
+
|
|
68
|
+
def run_cmd(cmd, args)
|
|
69
|
+
cmd.run(args)
|
|
70
|
+
puts '==' * 10
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
|
|
74
|
+
|
|
75
|
+
run_cmd(cmd, [name])
|
|
76
|
+
run_cmd(cmd, [name, '/x', '10'])
|
|
77
|
+
run_cmd(cmd, [name, 'd'])
|
|
78
|
+
run_cmd(cmd, [name])
|
|
79
|
+
e = 5
|
|
80
|
+
run_cmd(cmd, [name, 'e'])
|
|
81
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require_relative 'up'
|
|
4
|
+
|
|
5
|
+
# Debugger "down" command. Is the same as the "up" command with the
|
|
6
|
+
# direction (set by DIRECTION) reversed.
|
|
7
|
+
class Trepan::Command::DownCommand < Trepan::Command::UpCommand
|
|
8
|
+
|
|
9
|
+
# Silence already initialized constant .. warnings
|
|
10
|
+
old_verbose = $VERBOSE
|
|
11
|
+
$VERBOSE = nil
|
|
12
|
+
HELP =
|
|
13
|
+
"d(own) [count]
|
|
14
|
+
|
|
15
|
+
Move the current frame down in the stack trace (to a newer frame). 0
|
|
16
|
+
is the most recent frame. If no count is given, move down 1.
|
|
17
|
+
|
|
18
|
+
See also 'up' and 'frame'.
|
|
19
|
+
"
|
|
20
|
+
|
|
21
|
+
ALIASES = %w(d)
|
|
22
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
23
|
+
SHORT_HELP = 'Move frame in the direction of the caller of the last-selected frame'
|
|
24
|
+
$VERBOSE = old_verbose
|
|
25
|
+
|
|
26
|
+
def initialize(proc)
|
|
27
|
+
super
|
|
28
|
+
@direction = -1 # +1 for up.
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
if __FILE__ == $0
|
|
34
|
+
# Demo it.
|
|
35
|
+
require 'thread_frame'
|
|
36
|
+
require_relative '../mock'
|
|
37
|
+
name = File.basename(__FILE__, '.rb')
|
|
38
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
39
|
+
|
|
40
|
+
def sep ; puts '=' * 40 end
|
|
41
|
+
cmd.run [name]
|
|
42
|
+
%w(-1 0 1 -2).each do |count|
|
|
43
|
+
puts "#{name} #{count}"
|
|
44
|
+
cmd.run([name, count])
|
|
45
|
+
sep
|
|
46
|
+
end
|
|
47
|
+
def foo(cmd, name)
|
|
48
|
+
cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
|
|
49
|
+
puts "#{name}"
|
|
50
|
+
cmd.run([name])
|
|
51
|
+
sep
|
|
52
|
+
puts "#{name} -1"
|
|
53
|
+
cmd.run([name, '-1'])
|
|
54
|
+
end
|
|
55
|
+
foo(cmd, name)
|
|
56
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require_relative 'disable'
|
|
4
|
+
|
|
5
|
+
# enable breakpoint command. Is like disable but the parameter
|
|
6
|
+
# to @proc.en_disable_breakpoint_by_number is different (set as
|
|
7
|
+
# ENABLE_PARM below).
|
|
8
|
+
class Trepan::Command::EnableCommand < Trepan::Command::DisableCommand
|
|
9
|
+
|
|
10
|
+
# Silence already initialized constant .. warnings
|
|
11
|
+
old_verbose = $VERBOSE
|
|
12
|
+
$VERBOSE = nil
|
|
13
|
+
HELP =
|
|
14
|
+
'enable [display] bpnumber [bpnumber ...]
|
|
15
|
+
|
|
16
|
+
Enables the breakpoints given as a space separated list of breakpoint
|
|
17
|
+
numbers. See also "info break" to get a list.
|
|
18
|
+
'
|
|
19
|
+
|
|
20
|
+
ALIASES = %w(en)
|
|
21
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
22
|
+
SHORT_HELP = 'Enable some breakpoints'
|
|
23
|
+
$VERBOSE = old_verbose
|
|
24
|
+
|
|
25
|
+
def initialize(proc)
|
|
26
|
+
super
|
|
27
|
+
@enable_parm = true # true if enable
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
if __FILE__ == $0
|
|
33
|
+
require_relative '../mock'
|
|
34
|
+
name = File.basename(__FILE__, '.rb')
|
|
35
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
36
|
+
cmd.run([name])
|
|
37
|
+
cmd.run([name, '1'])
|
|
38
|
+
cmdproc = dbgr.core.processor
|
|
39
|
+
cmds = cmdproc.commands
|
|
40
|
+
break_cmd = cmds['break']
|
|
41
|
+
break_cmd.run(['break', cmdproc.frame.source_location[0].to_s])
|
|
42
|
+
cmd.run([name, '1'])
|
|
43
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
require_relative 'base/cmd'
|
|
3
|
+
class Trepan::Command::ExitCommand < Trepan::Command
|
|
4
|
+
|
|
5
|
+
unless defined?(HELP)
|
|
6
|
+
HELP =
|
|
7
|
+
'exit [exitcode] - hard exit of the debugged program.
|
|
8
|
+
|
|
9
|
+
The program being debugged is exited via exit!() which does not run
|
|
10
|
+
the Kernel at_exit finalizers. If a return code is given, that is the
|
|
11
|
+
return code passed to exit() - presumably the return code that will be
|
|
12
|
+
passed back to the OS. If no exit code is given, 0 is used.
|
|
13
|
+
|
|
14
|
+
See also the commands "quit" and "kill".'
|
|
15
|
+
|
|
16
|
+
CATEGORY = 'support'
|
|
17
|
+
MAX_ARGS = 2 # Need at most this many
|
|
18
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
19
|
+
SHORT_HELP = 'Exit program via "exit!"'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# FIXME: Combine 'quit' and 'exit'. The only difference is
|
|
23
|
+
# whether exit! or exit is used.
|
|
24
|
+
|
|
25
|
+
# This method runs the command
|
|
26
|
+
def run(args) # :nodoc
|
|
27
|
+
unconditional =
|
|
28
|
+
if args.size > 1 && args[1] == 'unconditionally'
|
|
29
|
+
args.shift
|
|
30
|
+
true
|
|
31
|
+
elsif args[0][-1..-1] == '!'
|
|
32
|
+
true
|
|
33
|
+
else
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
unless unconditional || confirm('Really quit?', false)
|
|
37
|
+
msg('Quit not confirmed.')
|
|
38
|
+
return
|
|
39
|
+
end
|
|
40
|
+
exitrc = (args.size > 1) ? exitrc = Integer(args[1]) rescue 0 : 0
|
|
41
|
+
# No graceful way to stop threads...
|
|
42
|
+
# A little harsh, but for now let's go with this.
|
|
43
|
+
exit! exitrc
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if __FILE__ == $0
|
|
48
|
+
require_relative '../mock'
|
|
49
|
+
name = File.basename(__FILE__, '.rb')
|
|
50
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
51
|
+
name = File.basename(__FILE__, '.rb')
|
|
52
|
+
fork { cmd.run([name]) }
|
|
53
|
+
cmd.run([name, '10'])
|
|
54
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require_relative 'base/cmd'
|
|
4
|
+
|
|
5
|
+
class Trepan::Command::FinishCommand < Trepan::Command
|
|
6
|
+
|
|
7
|
+
unless defined?(HELP)
|
|
8
|
+
HELP =
|
|
9
|
+
"finish [levels]
|
|
10
|
+
|
|
11
|
+
Continue execution until leaving the current function.
|
|
12
|
+
Sometimes this is called 'step out'.
|
|
13
|
+
|
|
14
|
+
When `levels' is specified, that many frame levels need to be
|
|
15
|
+
popped. The default is 1. Note that 'yield' and exceptions raised my
|
|
16
|
+
reduce the number of stack frames. Also, if a thread is switched, we
|
|
17
|
+
stop ignoring levels.
|
|
18
|
+
|
|
19
|
+
'next>' is similar in that it stops at a return, but it doesn't
|
|
20
|
+
guarentee the stack level is the same as or less than the current
|
|
21
|
+
one.
|
|
22
|
+
|
|
23
|
+
See the break command if you want to stop at a particular point in a
|
|
24
|
+
program. In general, 'finish', 'step' and 'next' may slow a program down
|
|
25
|
+
while 'break' will have less overhead.
|
|
26
|
+
"
|
|
27
|
+
ALIASES = %w(fin)
|
|
28
|
+
CATEGORY = 'running'
|
|
29
|
+
# execution_set = ['Running']
|
|
30
|
+
MAX_ARGS = 1 # Need at most this many.
|
|
31
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
32
|
+
NEED_STACK = true
|
|
33
|
+
SHORT_HELP = 'Step program without entering called functions'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# This method runs the command
|
|
37
|
+
def run(args) # :nodoc
|
|
38
|
+
opts = {}
|
|
39
|
+
if args.size == 1
|
|
40
|
+
# Form is: "finish" which means "finish 1"
|
|
41
|
+
level_count = 0
|
|
42
|
+
else
|
|
43
|
+
count_str = args[1]
|
|
44
|
+
opts = {
|
|
45
|
+
:msg_on_error =>
|
|
46
|
+
"The 'next' command argument must eval to an integer. Got: %s" %
|
|
47
|
+
count_str,
|
|
48
|
+
:min_value => 1
|
|
49
|
+
}
|
|
50
|
+
count = @proc.get_an_int(count_str, opts)
|
|
51
|
+
return unless count
|
|
52
|
+
# step 1 is core.level_count = 0 or "stop next event"
|
|
53
|
+
level_count = count - 1
|
|
54
|
+
end
|
|
55
|
+
if 0 == level_count and %w(return c-return).member?(@proc.event)
|
|
56
|
+
errmsg "You are already at the requested return event."
|
|
57
|
+
else
|
|
58
|
+
@proc.finish(level_count, opts)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
if __FILE__ == $0
|
|
64
|
+
require_relative '../mock'
|
|
65
|
+
name = File.basename(__FILE__, '.rb')
|
|
66
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
67
|
+
[%w(finish 1), %w(fin 2-1), %w(n foo)].each do |c|
|
|
68
|
+
cmd.proc.next_level = 0
|
|
69
|
+
cmd.proc.leave_cmd_loop = false
|
|
70
|
+
result = cmd.run(c)
|
|
71
|
+
puts 'Run result: %s' % result
|
|
72
|
+
puts 'level_count %d, leave_cmd_loop: %s' % [cmd.proc.next_level,
|
|
73
|
+
cmd.proc.leave_cmd_loop]
|
|
74
|
+
end
|
|
75
|
+
[%w(fin), %w(finish)].each do |c|
|
|
76
|
+
cmd.proc.next_level = 0
|
|
77
|
+
cmd.proc.leave_cmd_loop = false
|
|
78
|
+
result = cmd.run(c)
|
|
79
|
+
puts cmd.proc.different_pos
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
require_relative 'base/cmd'
|
|
3
|
+
require_relative '../../app/frame'
|
|
4
|
+
|
|
5
|
+
class Trepan::Command::FrameCommand < Trepan::Command
|
|
6
|
+
|
|
7
|
+
include Trepan::Frame
|
|
8
|
+
|
|
9
|
+
unless defined?(HELP)
|
|
10
|
+
HELP =
|
|
11
|
+
"frame [thread-Name] [frame-number]
|
|
12
|
+
|
|
13
|
+
Change the current frame to frame `frame-number' if specified, or the
|
|
14
|
+
most-recent frame, 0, if no frame number specified.
|
|
15
|
+
|
|
16
|
+
If a thread name or thread number is given, change the current frame
|
|
17
|
+
to a frame in that thread. Dot (.) can be used to indicate the name of
|
|
18
|
+
the current frame the debugger is stopped in.
|
|
19
|
+
|
|
20
|
+
A negative number indicates the position from the other or
|
|
21
|
+
least-recently-entered end. So 'frame -1' moves to the oldest frame.
|
|
22
|
+
Any variable or expression that evaluates to a number can be used as a
|
|
23
|
+
position, however due to parsing limitations, the position expression
|
|
24
|
+
has to be seen as a single blank-delimited parameter. That is, the
|
|
25
|
+
expression '(5*3)-1' is okay while '( (5 * 3) - 1 )' isn't.
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
frame # Set current frame at the current stopping point
|
|
29
|
+
frame 0 # Same as above
|
|
30
|
+
frame 5-5 # Same as above. Note: no spaces allowed in expression 5-5
|
|
31
|
+
frame . # Same as above. 'current thread' is explicit.
|
|
32
|
+
frame . 0 # Same as above.
|
|
33
|
+
frame 1 # Move to frame 1. Same as: frame 0; up
|
|
34
|
+
frame -1 # The least-recent frame
|
|
35
|
+
frame MainThread 0 # Switch to frame 0 of thread MainThread
|
|
36
|
+
frame MainThread # Same as above
|
|
37
|
+
frame -2434343 0 # Use a thread number instead of name
|
|
38
|
+
|
|
39
|
+
See also 'up', 'down' 'where' and 'info thread'.
|
|
40
|
+
"
|
|
41
|
+
|
|
42
|
+
CATEGORY = 'stack'
|
|
43
|
+
MAX_ARGS = 2 # Need at most this many
|
|
44
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
45
|
+
NEED_STACK = true
|
|
46
|
+
SHORT_HELP = 'Select and print a stack frame'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# The simple case: thread frame switching has been done or is
|
|
50
|
+
# not needed and we have an explicit position number as a string
|
|
51
|
+
def one_arg_run(position_str)
|
|
52
|
+
stack_size = @proc.top_frame.stack_size - @proc.hide_level
|
|
53
|
+
opts={
|
|
54
|
+
:msg_on_error =>
|
|
55
|
+
"The '#{NAME}' command requires a frame number. Got: #{position_str}",
|
|
56
|
+
:min_value => -stack_size,
|
|
57
|
+
:max_value => stack_size-1
|
|
58
|
+
}
|
|
59
|
+
frame_num = @proc.get_an_int(position_str, opts)
|
|
60
|
+
return false unless frame_num
|
|
61
|
+
|
|
62
|
+
# FIXME: move into @proc and test based on NEED_STACK.
|
|
63
|
+
if not @proc.top_frame
|
|
64
|
+
errmsg('No frames recorded.')
|
|
65
|
+
return false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
@proc.adjust_frame(frame_num, true)
|
|
69
|
+
return true
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Run a frame command. This routine is a little complex
|
|
73
|
+
# because we allow a number parameter variations.
|
|
74
|
+
def run(args)
|
|
75
|
+
if args.size == 1
|
|
76
|
+
# Form is: "frame" which means "frame 0"
|
|
77
|
+
position_str = '0'
|
|
78
|
+
elsif args.size == 2
|
|
79
|
+
# Form is: "frame position"
|
|
80
|
+
position_str = args[1]
|
|
81
|
+
elsif args.size == 3
|
|
82
|
+
# Form is: frame <position> <thread>
|
|
83
|
+
name_or_id = args[1]
|
|
84
|
+
thread_str = args[2]
|
|
85
|
+
th = @proc.get_thread_from_string(thread_str)
|
|
86
|
+
if th
|
|
87
|
+
@proc.frame_setup(th.threadframe)
|
|
88
|
+
return
|
|
89
|
+
else
|
|
90
|
+
# FIXME: Give suitable error message was given
|
|
91
|
+
end
|
|
92
|
+
else
|
|
93
|
+
# Form should be: "frame thread" which means
|
|
94
|
+
# "frame thread 0"
|
|
95
|
+
position_str = '0'
|
|
96
|
+
## FIXME:
|
|
97
|
+
## @proc.find_and_set_debugged_frame(frame, thread_id)
|
|
98
|
+
end
|
|
99
|
+
one_arg_run(position_str)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
if __FILE__ == $0
|
|
104
|
+
# Demo it.
|
|
105
|
+
require 'thread_frame'
|
|
106
|
+
require_relative '../mock'
|
|
107
|
+
name = File.basename(__FILE__, '.rb')
|
|
108
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
109
|
+
|
|
110
|
+
def sep ; puts '=' * 40 end
|
|
111
|
+
%w(0 1 -2).each {|count| cmd.run([name, count]); sep }
|
|
112
|
+
def foo(cmd, name)
|
|
113
|
+
cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
|
|
114
|
+
%w(0 -1).each {|count| cmd.run([name, count]); sep }
|
|
115
|
+
end
|
|
116
|
+
foo(cmd, name)
|
|
117
|
+
end
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
require_relative 'base/cmd'
|
|
3
|
+
class Trepan::Command::HelpCommand < Trepan::Command
|
|
4
|
+
|
|
5
|
+
unless defined?(HELP)
|
|
6
|
+
HELP =
|
|
7
|
+
"help [command [subcommand]|expression]
|
|
8
|
+
|
|
9
|
+
Without argument, print the list of available debugger commands.
|
|
10
|
+
|
|
11
|
+
When an argument is given, it is first checked to see if it is command
|
|
12
|
+
name. 'help where' gives help on the 'where' debugger command.
|
|
13
|
+
|
|
14
|
+
If the environment variable $PAGER is defined, the file is
|
|
15
|
+
piped through that command. You'll notice this only for long help
|
|
16
|
+
output.
|
|
17
|
+
|
|
18
|
+
Some commands like 'info', 'set', and 'show' can accept an
|
|
19
|
+
additional subcommand to give help just about that particular
|
|
20
|
+
subcommand. For example 'help info line' give help about the
|
|
21
|
+
info line command.
|
|
22
|
+
|
|
23
|
+
See also 'examine' and 'whatis'.
|
|
24
|
+
"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
ALIASES = %w(?)
|
|
28
|
+
CATEGORIES = {
|
|
29
|
+
'breakpoints' => 'Making the program stop at certain points',
|
|
30
|
+
'data' => 'Examining data',
|
|
31
|
+
'files' => 'Specifying and examining files',
|
|
32
|
+
'running' => 'Running the program',
|
|
33
|
+
'status' => 'Status inquiries',
|
|
34
|
+
'support' => 'Support facilities',
|
|
35
|
+
'stack' => 'Examining the call stack'
|
|
36
|
+
}
|
|
37
|
+
CATEGORY = 'support'
|
|
38
|
+
NAME = File.basename(__FILE__, '.rb')
|
|
39
|
+
NEED_STACK = false
|
|
40
|
+
SHORT_HELP = 'Print commands or give help for command(s)'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# List the command categories and a short description of each.
|
|
44
|
+
def list_categories
|
|
45
|
+
msg("Classes of commands:")
|
|
46
|
+
CATEGORIES.keys.sort.each do |cat|
|
|
47
|
+
msg("%-13s -- %s" % [cat, CATEGORIES[cat]])
|
|
48
|
+
end
|
|
49
|
+
final_msg = '
|
|
50
|
+
Type "help" followed by a class name for a list of commands in that class.
|
|
51
|
+
Type "help *" for the list of all commands.
|
|
52
|
+
Type "help REGEXP" for the list of commands matching /^#{REGEXP}/
|
|
53
|
+
Type "help CLASS *" for the list of all commands in class CLASS.
|
|
54
|
+
Type "help" followed by command name for full documentation.
|
|
55
|
+
'
|
|
56
|
+
msg(final_msg)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# This method runs the command
|
|
60
|
+
def run(args) # :nodoc
|
|
61
|
+
if args.size > 1
|
|
62
|
+
cmd_name = args[1]
|
|
63
|
+
if cmd_name == '*'
|
|
64
|
+
msg("All command names:")
|
|
65
|
+
msg columnize_commands(@proc.commands.keys.sort)
|
|
66
|
+
elsif CATEGORIES.member?(cmd_name)
|
|
67
|
+
show_category(args[1], args[2..-1])
|
|
68
|
+
elsif @proc.commands.member?(cmd_name) or @proc.aliases.member?(cmd_name)
|
|
69
|
+
real_name =
|
|
70
|
+
if @proc.commands.member?(cmd_name)
|
|
71
|
+
cmd_name
|
|
72
|
+
else
|
|
73
|
+
@proc.aliases[cmd_name]
|
|
74
|
+
end
|
|
75
|
+
cmd_obj = @proc.commands[real_name]
|
|
76
|
+
help_text =
|
|
77
|
+
cmd_obj.respond_to?(:help) ? cmd_obj.help(args) :
|
|
78
|
+
cmd_obj.class.const_get(:HELP)
|
|
79
|
+
if help_text
|
|
80
|
+
msg(help_text)
|
|
81
|
+
if cmd_obj.class.constants.member?(:ALIASES) and
|
|
82
|
+
args.size == 2
|
|
83
|
+
msg "Aliases: #{cmd_obj.class.const_get(:ALIASES).join(', ')}"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
else
|
|
87
|
+
matches = @proc.commands.keys.grep(/^#{cmd_name}/).sort rescue []
|
|
88
|
+
if matches.empty?
|
|
89
|
+
errmsg("No commands found matching /^#{cmd_name}/. Try \"help\".")
|
|
90
|
+
else
|
|
91
|
+
msg("Command names matching /^#{cmd_name}/:")
|
|
92
|
+
msg columnize_commands(matches.sort)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
else
|
|
96
|
+
list_categories
|
|
97
|
+
end
|
|
98
|
+
return false # Don't break out of cmd loop
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Show short help for all commands in `category'.
|
|
102
|
+
def show_category(category, args)
|
|
103
|
+
|
|
104
|
+
if args.size == 1 && args[0] == '*'
|
|
105
|
+
msg("Commands in class %s:" % category)
|
|
106
|
+
|
|
107
|
+
cmds = @proc.commands.keys.select do |cmd_name|
|
|
108
|
+
category == @proc.commands[cmd_name].category
|
|
109
|
+
end.sort
|
|
110
|
+
|
|
111
|
+
width = settings[:maxwidth]
|
|
112
|
+
return columnize_commands(cmds)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
msg("%s." % CATEGORIES[category])
|
|
116
|
+
msg("List of commands:\n")
|
|
117
|
+
@proc.commands.keys.sort.each do |name|
|
|
118
|
+
next if category != @proc.commands[name].category
|
|
119
|
+
msg("%-13s -- %s" % [name, @proc.commands[name].short_help])
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
if __FILE__ == $0
|
|
125
|
+
# Demo it.
|
|
126
|
+
require_relative '../mock'
|
|
127
|
+
name = File.basename(__FILE__, '.rb')
|
|
128
|
+
dbgr, cmd = MockDebugger::setup(name)
|
|
129
|
+
|
|
130
|
+
cmd.run %w(help help)
|
|
131
|
+
puts '=' * 40
|
|
132
|
+
cmd.run %w(help *)
|
|
133
|
+
puts '=' * 40
|
|
134
|
+
cmd.run %w(help fdafsasfda)
|
|
135
|
+
puts '=' * 40
|
|
136
|
+
cmd.run %w(help)
|
|
137
|
+
puts '=' * 40
|
|
138
|
+
cmd.run %w(help support)
|
|
139
|
+
puts '=' * 40
|
|
140
|
+
cmd.run %w(help support *)
|
|
141
|
+
|
|
142
|
+
puts '=' * 40
|
|
143
|
+
cmd.run %w(help s.*)
|
|
144
|
+
puts '=' * 40
|
|
145
|
+
cmd.run %w(help s<>)
|
|
146
|
+
end
|