rbx-trepanning 0.0.1-universal-rubinius
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 +376 -0
- data/LICENSE +25 -0
- data/NEWS +2 -0
- data/README.textile +28 -0
- data/Rakefile +165 -0
- data/THANKS +14 -0
- data/app/breakpoint.rb +218 -0
- data/app/breakpoint.rbc +3564 -0
- data/app/brkptmgr.rb +138 -0
- data/app/brkptmgr.rbc +2827 -0
- data/app/default.rb +61 -0
- data/app/default.rbc +1011 -0
- data/app/display.rb +35 -0
- data/app/display.rbc +968 -0
- data/app/frame.rb +98 -0
- data/app/frame.rbc +1808 -0
- data/app/irb.rb +112 -0
- data/app/irb.rbc +2111 -0
- data/app/iseq.rb +95 -0
- data/app/iseq.rbc +1801 -0
- data/app/method.rb +173 -0
- data/app/method.rbc +2492 -0
- data/app/mock.rb +13 -0
- data/app/mock.rbc +398 -0
- data/app/options.rb +123 -0
- data/app/options.rbc +2183 -0
- data/app/run.rb +86 -0
- data/app/run.rbc +1244 -0
- data/app/util.rb +49 -0
- data/app/util.rbc +1144 -0
- data/app/validate.rb +30 -0
- data/app/validate.rbc +676 -0
- data/bin/trepan.compiled.rbc +1043 -0
- data/bin/trepanx +63 -0
- data/bin/trepanx.compiled.rbc +985 -0
- data/interface/base_intf.rb +95 -0
- data/interface/base_intf.rbc +1742 -0
- data/interface/script.rb +104 -0
- data/interface/script.rbc +1642 -0
- data/interface/user.rb +91 -0
- data/interface/user.rbc +1418 -0
- data/io/base_io.rb +94 -0
- data/io/base_io.rbc +1404 -0
- data/io/input.rb +112 -0
- data/io/input.rbc +1979 -0
- data/io/null_output.rb +42 -0
- data/io/null_output.rbc +730 -0
- data/io/string_array.rb +156 -0
- data/io/string_array.rbc +2466 -0
- data/lib/trepanning.rb +398 -0
- data/lib/trepanning.rbc +6661 -0
- data/processor/breakpoint.rb +161 -0
- data/processor/command/alias.rb +55 -0
- data/processor/command/backtrace.rb +46 -0
- data/processor/command/base/cmd.rb +124 -0
- data/processor/command/base/subcmd.rb +213 -0
- data/processor/command/base/submgr.rb +179 -0
- data/processor/command/base/subsubcmd.rb +103 -0
- data/processor/command/base/subsubmgr.rb +184 -0
- data/processor/command/break.rb +100 -0
- data/processor/command/continue.rb +82 -0
- data/processor/command/delete.rb +30 -0
- data/processor/command/directory.rb +43 -0
- data/processor/command/disassemble.rb +103 -0
- data/processor/command/down.rb +54 -0
- data/processor/command/eval.rb +31 -0
- data/processor/command/exit.rb +58 -0
- data/processor/command/finish.rb +78 -0
- data/processor/command/frame.rb +89 -0
- data/processor/command/help.rb +146 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/breakpoints.rb +75 -0
- data/processor/command/info_subcmd/file.rb +153 -0
- data/processor/command/info_subcmd/method.rb +71 -0
- data/processor/command/info_subcmd/program.rb +59 -0
- data/processor/command/info_subcmd/variables.rb +40 -0
- data/processor/command/irb.rb +96 -0
- data/processor/command/kill.rb +70 -0
- data/processor/command/list.rb +296 -0
- data/processor/command/next.rb +66 -0
- data/processor/command/nexti.rb +59 -0
- data/processor/command/pr.rb +38 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/restart.rb +60 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/auto.rb +28 -0
- data/processor/command/set_subcmd/auto_subcmd/dis.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +54 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +34 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +34 -0
- data/processor/command/set_subcmd/basename.rb +26 -0
- data/processor/command/set_subcmd/debug.rb +27 -0
- data/processor/command/set_subcmd/debug_subcmd/dbgr.rb +36 -0
- data/processor/command/set_subcmd/debug_subcmd/skip.rb +23 -0
- data/processor/command/set_subcmd/debug_subcmd/step.rb +23 -0
- data/processor/command/set_subcmd/different.rb +60 -0
- data/processor/command/set_subcmd/hidelevel.rb +63 -0
- data/processor/command/set_subcmd/kernelstep.rb +61 -0
- data/processor/command/set_subcmd/max.rb +29 -0
- data/processor/command/set_subcmd/max_subcmd/list.rb +49 -0
- data/processor/command/set_subcmd/max_subcmd/stack.rb +50 -0
- data/processor/command/set_subcmd/max_subcmd/string.rb +54 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
- data/processor/command/set_subcmd/substitute.rb +25 -0
- data/processor/command/set_subcmd/substitute_subcmd/path.rb +56 -0
- data/processor/command/set_subcmd/trace.rb +37 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +57 -0
- data/processor/command/show.rb +27 -0
- data/processor/command/show_subcmd/alias.rb +43 -0
- data/processor/command/show_subcmd/args.rb +26 -0
- data/processor/command/show_subcmd/auto.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/dis.rb +37 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/irb.rb +23 -0
- data/processor/command/show_subcmd/auto_subcmd/list.rb +22 -0
- data/processor/command/show_subcmd/basename.rb +22 -0
- data/processor/command/show_subcmd/debug.rb +27 -0
- data/processor/command/show_subcmd/debug_subcmd/dbgr.rb +21 -0
- data/processor/command/show_subcmd/debug_subcmd/skip.rb +22 -0
- data/processor/command/show_subcmd/debug_subcmd/step.rb +22 -0
- data/processor/command/show_subcmd/different.rb +27 -0
- data/processor/command/show_subcmd/hidelevel.rb +42 -0
- data/processor/command/show_subcmd/kernelstep.rb +37 -0
- data/processor/command/show_subcmd/max.rb +30 -0
- data/processor/command/show_subcmd/max_subcmd/list.rb +38 -0
- data/processor/command/show_subcmd/max_subcmd/stack.rb +36 -0
- data/processor/command/show_subcmd/max_subcmd/string.rb +42 -0
- data/processor/command/show_subcmd/max_subcmd/width.rb +37 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +38 -0
- data/processor/command/source.rb +83 -0
- data/processor/command/step.rb +41 -0
- data/processor/command/tbreak.rb +19 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/up.rb +87 -0
- data/processor/default.rb +56 -0
- data/processor/disassemble.rb +32 -0
- data/processor/eval.rb +96 -0
- data/processor/frame.rb +211 -0
- data/processor/help.rb +72 -0
- data/processor/hook.rb +133 -0
- data/processor/load_cmds.rb +101 -0
- data/processor/location.rb +128 -0
- data/processor/main.rb +394 -0
- data/processor/mock.rb +137 -0
- data/processor/msg.rb +28 -0
- data/processor/running.rb +230 -0
- data/processor/stepping.rb +115 -0
- data/processor/subcmd.rb +160 -0
- data/processor/validate.rb +355 -0
- data/test/data/enable.right +36 -0
- data/test/data/fname-with-blank.cmd +6 -0
- data/test/data/fname-with-blank.right +1 -0
- data/test/data/quit-Xdebug.right +3 -0
- data/test/data/quit.cmd +5 -0
- data/test/data/quit.right +0 -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 +112 -0
- data/test/functional/test-break-name.rb +52 -0
- data/test/functional/test-break.rb +51 -0
- data/test/functional/test-finish.rb +70 -0
- data/test/functional/test-fn_helper.rb +43 -0
- data/test/functional/test-list.rb +55 -0
- data/test/functional/test-next-bug.rb +49 -0
- data/test/functional/test-next.rb +101 -0
- data/test/functional/test-step.rb +272 -0
- data/test/functional/test-step2.rb +35 -0
- data/test/functional/test-tbreak.rb +41 -0
- data/test/integration/file-diff.rb +89 -0
- data/test/integration/helper.rb +78 -0
- data/test/integration/test-fname-with-blank.rb +12 -0
- data/test/integration/test-quit.rb +25 -0
- data/test/unit/cmd-helper.rb +46 -0
- data/test/unit/test-app-brkpt.rb +30 -0
- data/test/unit/test-app-brkptmgr.rb +51 -0
- data/test/unit/test-app-iseq.rb +49 -0
- data/test/unit/test-app-method.rb +54 -0
- data/test/unit/test-app-options.rb +61 -0
- data/test/unit/test-app-run.rb +16 -0
- data/test/unit/test-app-util.rb +28 -0
- data/test/unit/test-app-validate.rb +18 -0
- data/test/unit/test-base-subcmd.rb +61 -0
- data/test/unit/test-bin-trepanx.rb +48 -0
- data/test/unit/test-cmd-alias.rb +49 -0
- data/test/unit/test-cmd-break.rb +23 -0
- data/test/unit/test-cmd-exit.rb +27 -0
- data/test/unit/test-cmd-help.rb +101 -0
- data/test/unit/test-cmd-kill.rb +48 -0
- data/test/unit/test-intf-user.rb +46 -0
- data/test/unit/test-io-input.rb +27 -0
- data/test/unit/test-proc-eval.rb +37 -0
- data/test/unit/test-proc-frame.rb +79 -0
- data/test/unit/test-proc-help.rb +16 -0
- data/test/unit/test-proc-hook.rb +30 -0
- data/test/unit/test-proc-load_cmds.rb +41 -0
- data/test/unit/test-proc-location.rb +48 -0
- data/test/unit/test-proc-main.rb +96 -0
- data/test/unit/test-proc-validate.rb +91 -0
- data/test/unit/test-subcmd-help.rb +51 -0
- metadata +337 -0
data/lib/trepanning.rb
ADDED
@@ -0,0 +1,398 @@
|
|
1
|
+
require 'readline'
|
2
|
+
require 'compiler/iseq'
|
3
|
+
|
4
|
+
require 'rubygems'; require 'require_relative'
|
5
|
+
require_relative '../app/frame'
|
6
|
+
require_relative '../app/util' # get_dollar_0
|
7
|
+
require_relative '../processor/main'
|
8
|
+
require_relative '../app/breakpoint'
|
9
|
+
require_relative '../app/default' # default debugger settings
|
10
|
+
require_relative '../app/breakpoint'
|
11
|
+
require_relative '../app/display' # FIXME: remove
|
12
|
+
require_relative '../interface/user' # user interface (includes I/O)
|
13
|
+
require_relative '../io/null_output'
|
14
|
+
|
15
|
+
#
|
16
|
+
# The Rubinius Trepan debugger.
|
17
|
+
#
|
18
|
+
# This debugger is wired into the debugging APIs provided by Rubinius.
|
19
|
+
#
|
20
|
+
|
21
|
+
class Trepan
|
22
|
+
VERSION = '0.0.1'
|
23
|
+
|
24
|
+
attr_accessor :breakpoint # Breakpoint. The current breakpoint we are
|
25
|
+
# stopped at or nil if none.
|
26
|
+
attr_accessor :intf # Array. The way the outside world
|
27
|
+
# interfaces with us. An array, so that
|
28
|
+
# interfaces with us. An array, so that
|
29
|
+
# interfaces can be stacked.
|
30
|
+
attr_accessor :restart_argv # How to restart us, empty or nil.
|
31
|
+
# Note: restart_argv is typically C's
|
32
|
+
# **argv, not Ruby's ARGV. So
|
33
|
+
# restart_argv[0] is $0.
|
34
|
+
attr_reader :settings # Hash[:symbol] of things you can configure
|
35
|
+
attr_reader :deferred_breakpoints
|
36
|
+
attr_reader :processor
|
37
|
+
|
38
|
+
# Used to try and show the source for the kernel. Should
|
39
|
+
# mostly work, but it's a hack.
|
40
|
+
DBGR_DIR = File.dirname(RequireRelative.abs_file)
|
41
|
+
ROOT_DIR = File.expand_path(File.join(DBGR_DIR, "/.."))
|
42
|
+
|
43
|
+
include Trepan::Display # FIXME: remove
|
44
|
+
|
45
|
+
# Create a new debugger object. The debugger starts up a thread
|
46
|
+
# which is where the command line interface executes from. Other
|
47
|
+
# threads that you wish to debug are told that their debugging
|
48
|
+
# thread is the debugger thread. This is how the debugger is handed
|
49
|
+
# control of execution.
|
50
|
+
#
|
51
|
+
def initialize(settings={})
|
52
|
+
@breakpoint = nil
|
53
|
+
@settings = Trepanning::DEFAULT_SETTINGS.merge(settings)
|
54
|
+
@input ||= @settings[:input]
|
55
|
+
@output ||= @settings[:output]
|
56
|
+
|
57
|
+
@processor = CmdProcessor.new(self)
|
58
|
+
|
59
|
+
@intf = [Trepan::UserInterface.new(@input, @output)]
|
60
|
+
@settings[:cmdfiles].each do |cmdfile|
|
61
|
+
add_command_file(cmdfile)
|
62
|
+
end if @settings.member?(:cmdfiles)
|
63
|
+
Dir.chdir(@settings[:initial_dir]) if @settings[:initial_dir]
|
64
|
+
@restart_argv = @settings[:restart_argv]
|
65
|
+
|
66
|
+
## FIXME: put in fn
|
67
|
+
@processor.dbgr = self
|
68
|
+
## m = Rubinius::Loader.method(:debugger).executable.inspect
|
69
|
+
meth = Rubinius::VM.backtrace(0)[0].method
|
70
|
+
@processor.ignore_methods[meth] = 'next'
|
71
|
+
@processor.ignore_methods[method(:debugger)] = 'step'
|
72
|
+
|
73
|
+
@thread = nil
|
74
|
+
@frames = []
|
75
|
+
## FIXME: Delete these and use the ones in processor/default instead.
|
76
|
+
@variables = {
|
77
|
+
:show_bytecode => false,
|
78
|
+
:highlight => false
|
79
|
+
}
|
80
|
+
|
81
|
+
@loaded_hook = proc { |file|
|
82
|
+
check_deferred_breakpoints
|
83
|
+
}
|
84
|
+
|
85
|
+
@added_hook = proc { |mod, name, exec|
|
86
|
+
check_deferred_breakpoints
|
87
|
+
}
|
88
|
+
|
89
|
+
# Use a few Rubinius specific hooks to trigger checking
|
90
|
+
# for deferred breakpoints.
|
91
|
+
|
92
|
+
Rubinius::CodeLoader.loaded_hook.add @loaded_hook
|
93
|
+
Rubinius.add_method_hook.add @added_hook
|
94
|
+
|
95
|
+
@deferred_breakpoints = []
|
96
|
+
|
97
|
+
@history_path = File.expand_path("~/.trepanx")
|
98
|
+
|
99
|
+
if File.exists?(@history_path)
|
100
|
+
File.readlines(@history_path).each do |line|
|
101
|
+
Readline::HISTORY << line.strip
|
102
|
+
end
|
103
|
+
@history_io = File.new(@history_path, "a")
|
104
|
+
else
|
105
|
+
@history_io = File.new(@history_path, "w")
|
106
|
+
end
|
107
|
+
|
108
|
+
@history_io.sync = true
|
109
|
+
|
110
|
+
@root_dir = ROOT_DIR
|
111
|
+
|
112
|
+
# Run user debugger command startup files.
|
113
|
+
add_startup_files unless @settings[:nx]
|
114
|
+
add_command_file(@settings[:restore_profile]) if
|
115
|
+
@settings[:restore_profile] && File.readable?(@settings[:restore_profile])
|
116
|
+
end
|
117
|
+
|
118
|
+
## HACK to skip over loader code. Until I find something better...
|
119
|
+
def skip_loader
|
120
|
+
cmds =
|
121
|
+
if @settings[:skip_loader] == :Xdebug
|
122
|
+
['continue Rubinius::CodeLoader#load_script',
|
123
|
+
'continue 67',
|
124
|
+
# 'set kernelstep off', # eventually would like 'on'
|
125
|
+
'step', 'set hidelevel -1'
|
126
|
+
]
|
127
|
+
else
|
128
|
+
['next', 'next',
|
129
|
+
# 'set kernelstep off', # eventually would like 'on'
|
130
|
+
'set hidelevel -1',
|
131
|
+
'step', ]
|
132
|
+
end
|
133
|
+
|
134
|
+
input = Trepan::StringArrayInput.open(cmds)
|
135
|
+
startup = Trepan::ScriptInterface.new('startup',
|
136
|
+
Trepan::OutputNull.new(nil),
|
137
|
+
:input => input)
|
138
|
+
@intf << startup
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
attr_reader :variables, :current_frame, :breakpoints
|
143
|
+
attr_reader :vm_locations, :history_io, :debugee_thread
|
144
|
+
|
145
|
+
def self.global(settings={})
|
146
|
+
@global ||= new(settings)
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.start(settings={})
|
150
|
+
settings = {:immediate => false, :offset => 1}.merge(settings)
|
151
|
+
global(settings).start(settings)
|
152
|
+
end
|
153
|
+
|
154
|
+
# This is simplest API point. This starts up the debugger in the caller
|
155
|
+
# of this method to begin debugging.
|
156
|
+
#
|
157
|
+
def self.here(settings={})
|
158
|
+
global(settings).start(:offset => 1)
|
159
|
+
end
|
160
|
+
|
161
|
+
# Startup the debugger, skipping back +offset+ frames. This lets you start
|
162
|
+
# the debugger straight into callers method.
|
163
|
+
#
|
164
|
+
def start(settings = {:immediate => false})
|
165
|
+
@settings = @settings.merge(settings)
|
166
|
+
skip_loader if @settings[:skip_loader]
|
167
|
+
spinup_thread
|
168
|
+
@debugee_thread = @thread
|
169
|
+
if @settings[:hide_level]
|
170
|
+
@processor.hidelevels[@thread] = @settings[:hide_level]
|
171
|
+
end
|
172
|
+
|
173
|
+
# Feed info to the debugger thread!
|
174
|
+
locs = Rubinius::VM.backtrace(@settings[:offset] + 1, true)
|
175
|
+
|
176
|
+
method = Rubinius::CompiledMethod.of_sender
|
177
|
+
|
178
|
+
event = settings[:immediate] ? 'debugger-call' : 'start'
|
179
|
+
bp = Trepanning::Breakpoint.new('<start>', method, 0, 0, 0,
|
180
|
+
{:event => event}
|
181
|
+
)
|
182
|
+
channel = Rubinius::Channel.new
|
183
|
+
|
184
|
+
@local_channel.send Rubinius::Tuple[bp, Thread.current, channel, locs]
|
185
|
+
|
186
|
+
# wait for the debugger to release us
|
187
|
+
channel.receive
|
188
|
+
|
189
|
+
Thread.current.set_debugger_thread @thread
|
190
|
+
self
|
191
|
+
end
|
192
|
+
|
193
|
+
def stop(settings = {})
|
194
|
+
# Nothing for now...
|
195
|
+
end
|
196
|
+
|
197
|
+
def add_command_file(cmdfile, stderr=$stderr)
|
198
|
+
unless File.readable?(cmdfile)
|
199
|
+
if File.exists?(cmdfile)
|
200
|
+
stderr.puts "Command file '#{cmdfile}' is not readable."
|
201
|
+
return
|
202
|
+
else
|
203
|
+
stderr.puts "Command file '#{cmdfile}' does not exist."
|
204
|
+
stderr.puts caller
|
205
|
+
return
|
206
|
+
end
|
207
|
+
end
|
208
|
+
@intf << Trepan::ScriptInterface.new(cmdfile, @output)
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_startup_files()
|
212
|
+
seen = {}
|
213
|
+
cwd_initfile = File.join('.', Trepanning::CMD_INITFILE_BASE)
|
214
|
+
[cwd_initfile, Trepanning::CMD_INITFILE].each do |initfile|
|
215
|
+
full_initfile_path = File.expand_path(initfile)
|
216
|
+
next if seen[full_initfile_path]
|
217
|
+
add_command_file(full_initfile_path) if File.readable?(full_initfile_path)
|
218
|
+
seen[full_initfile_path] = true
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Stop and wait for a debuggee thread to send us info about
|
223
|
+
# stopping at a breakpoint.
|
224
|
+
#
|
225
|
+
def listen(step_into=false)
|
226
|
+
@breakpoint = nil
|
227
|
+
while true
|
228
|
+
if @channel
|
229
|
+
if step_into
|
230
|
+
@channel << :step
|
231
|
+
else
|
232
|
+
@channel << true
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
# Wait for someone to stop
|
237
|
+
@breakpoint, @debugee_thread, @channel, @vm_locations =
|
238
|
+
@local_channel.receive
|
239
|
+
|
240
|
+
# Uncache all frames since we stopped at a new place
|
241
|
+
@frames = []
|
242
|
+
|
243
|
+
set_frame(0)
|
244
|
+
|
245
|
+
if @breakpoint
|
246
|
+
# Some breakpoints are frame specific. Check for this. hit!
|
247
|
+
# also removes the breakpoint if it was temporary and hit.
|
248
|
+
break if @breakpoint.hit!(@vm_locations.first.variables)
|
249
|
+
else
|
250
|
+
@processor.step_bp.remove! if @processor.step_bp
|
251
|
+
break
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
event =
|
256
|
+
if @breakpoint
|
257
|
+
@breakpoint.event || 'brkpt'
|
258
|
+
else
|
259
|
+
# Evan assures me that the only way the breakpoint can be nil
|
260
|
+
# is if we are stepping and enter a function.
|
261
|
+
'step-call'
|
262
|
+
end
|
263
|
+
@processor.instance_variable_set('@event', event)
|
264
|
+
|
265
|
+
if @variables[:show_bytecode]
|
266
|
+
decode_one
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|
270
|
+
|
271
|
+
def frame(num)
|
272
|
+
@frames[num] ||= Frame.new(self, num, @vm_locations[num])
|
273
|
+
end
|
274
|
+
|
275
|
+
def set_frame(num)
|
276
|
+
@current_frame = frame(num)
|
277
|
+
end
|
278
|
+
|
279
|
+
def each_frame(start=0)
|
280
|
+
start = start.number if start.kind_of?(Frame)
|
281
|
+
|
282
|
+
start.upto(@vm_locations.size-1) do |idx|
|
283
|
+
yield frame(idx)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
def add_deferred_breakpoint(klass_name, which, name, line)
|
288
|
+
dbp = Trepanning::DeferredBreakpoint.new(self, @current_frame, klass_name, which, name,
|
289
|
+
line, @deferred_breakpoints)
|
290
|
+
@deferred_breakpoints << dbp
|
291
|
+
# @processor.brkpts << dbp
|
292
|
+
end
|
293
|
+
|
294
|
+
def check_deferred_breakpoints
|
295
|
+
@deferred_breakpoints.delete_if do |bp|
|
296
|
+
bp.resolve!
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
def send_between(exec, start, fin)
|
301
|
+
ss = Rubinius::InstructionSet.opcodes_map[:send_stack]
|
302
|
+
sm = Rubinius::InstructionSet.opcodes_map[:send_method]
|
303
|
+
sb = Rubinius::InstructionSet.opcodes_map[:send_stack_with_block]
|
304
|
+
|
305
|
+
iseq = exec.iseq
|
306
|
+
|
307
|
+
fin = iseq.size if fin < 0
|
308
|
+
|
309
|
+
i = start
|
310
|
+
while i < fin
|
311
|
+
op = iseq[i]
|
312
|
+
case op
|
313
|
+
when ss, sm, sb
|
314
|
+
return exec.literals[iseq[i + 1]]
|
315
|
+
else
|
316
|
+
op = Rubinius::InstructionSet[op]
|
317
|
+
i += (op.arg_count + 1)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
return nil
|
322
|
+
end
|
323
|
+
|
324
|
+
def show_code(line=@current_frame.line)
|
325
|
+
path = @current_frame.method.active_path
|
326
|
+
str = @processor.line_at(path, line)
|
327
|
+
unless str.nil?
|
328
|
+
# if @variables[:highlight]
|
329
|
+
# fin = @current_frame.method.first_ip_on_line(line + 1)
|
330
|
+
# name = send_between(@current_frame.method, @current_frame.ip, fin)
|
331
|
+
|
332
|
+
# if name
|
333
|
+
# str = str.gsub name.to_s, "\033[0;4m#{name}\033[0m"
|
334
|
+
# end
|
335
|
+
# end
|
336
|
+
# info "#{line}: #{str}"
|
337
|
+
else
|
338
|
+
show_bytecode(line)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
def decode_one
|
343
|
+
ip = @current_frame.next_ip
|
344
|
+
|
345
|
+
meth = @current_frame.method
|
346
|
+
decoder = Rubinius::InstructionDecoder.new(meth.iseq)
|
347
|
+
partial = decoder.decode_between(ip, ip+1)
|
348
|
+
|
349
|
+
partial.each do |ins|
|
350
|
+
op = ins.shift
|
351
|
+
|
352
|
+
ins.each_index do |i|
|
353
|
+
case op.args[i]
|
354
|
+
when :literal
|
355
|
+
ins[i] = meth.literals[ins[i]].inspect
|
356
|
+
when :local
|
357
|
+
if meth.local_names
|
358
|
+
ins[i] = meth.local_names[ins[i]]
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
display "ip #{ip} = #{op.opcode} #{ins.join(', ')}"
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def spinup_thread
|
368
|
+
return if @thread
|
369
|
+
|
370
|
+
@local_channel = Rubinius::Channel.new
|
371
|
+
|
372
|
+
@thread = Thread.new do
|
373
|
+
begin
|
374
|
+
listen
|
375
|
+
rescue Exception => e
|
376
|
+
e.render("Listening")
|
377
|
+
break
|
378
|
+
end
|
379
|
+
|
380
|
+
@processor.process_commands
|
381
|
+
|
382
|
+
end
|
383
|
+
|
384
|
+
@thread.setup_control!(@local_channel)
|
385
|
+
end
|
386
|
+
|
387
|
+
private :spinup_thread
|
388
|
+
|
389
|
+
end
|
390
|
+
|
391
|
+
module Kernel
|
392
|
+
# A simpler way of calling Trepan.start
|
393
|
+
def debugger(settings = {})
|
394
|
+
settings = {:immediate => false, :offset => 2}.merge(settings)
|
395
|
+
Trepan.start(settings)
|
396
|
+
end
|
397
|
+
alias breakpoint debugger unless respond_to?(:breakpoint)
|
398
|
+
end
|