rbx-trepanning 0.0.7-universal-rubinius-1.2 → 0.0.8-universal-rubinius-1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +236 -0
- data/NEWS +16 -0
- data/Rakefile +60 -11
- data/app/breakpoint.rb +5 -1
- data/app/brkptmgr.rb +5 -0
- data/app/cmd_parse.kpeg +225 -0
- data/app/cmd_parse.rb +209 -0
- data/app/cmd_parser.rb +1894 -0
- data/app/default.rb +0 -1
- data/app/method.rb +12 -8
- data/app/options.rb +2 -9
- data/app/validate.rb +2 -2
- data/bin/trepanx +3 -3
- data/lib/trepanning.rb +9 -6
- data/processor/breakpoint.rb +5 -19
- data/processor/command/alias.rb +4 -5
- data/processor/command/base/submgr.rb +2 -2
- data/processor/command/break.rb +44 -66
- data/processor/command/condition.rb +2 -0
- data/processor/command/continue.rb +11 -41
- data/processor/command/disassemble.rb +2 -0
- data/processor/command/eval.rb +20 -8
- data/processor/command/exit.rb +3 -2
- data/{doc → processor/command/help}/.gitignore +0 -0
- data/processor/command/help/command.txt +48 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/help.rb +52 -73
- data/processor/command/info_subcmd/breakpoints.rb +35 -13
- data/processor/command/info_subcmd/files.rb +34 -25
- data/processor/command/info_subcmd/frame.rb +67 -0
- data/processor/command/kill.rb +0 -1
- data/processor/command/restart.rb +8 -8
- data/processor/command/save.rb +58 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +1 -1
- data/processor/command/set_subcmd/trace_subcmd/print.rb +1 -1
- data/processor/command/show.rb +7 -6
- data/processor/command/step.rb +16 -3
- data/processor/command/tbreak.rb +1 -1
- data/processor/disassemble.rb +1 -1
- data/processor/help.rb +20 -0
- data/processor/load_cmds.rb +53 -4
- data/processor/location.rb +47 -1
- data/processor/main.rb +4 -9
- data/processor/mock.rb +3 -3
- data/processor/running.rb +16 -17
- data/processor/validate.rb +171 -159
- data/rbx-trepanning.gemspec +1 -1
- data/test/example/debugger-stop.rb +16 -0
- data/test/functional/test-break-name.rb +1 -1
- data/test/functional/test-eval.rb +115 -0
- data/test/functional/test-tbreak.rb +1 -1
- data/test/integration/helper.rb +5 -2
- data/test/unit/cmd-helper.rb +1 -1
- data/test/unit/test-app-cmd_parse.rb +97 -0
- data/test/unit/test-app-cmd_parser.rb +22 -0
- data/test/unit/test-app-options.rb +1 -0
- data/test/unit/test-app-validate.rb +2 -2
- data/test/unit/test-cmd-break.rb +47 -5
- data/test/unit/test-completion.rb +2 -1
- data/test/unit/test-proc-location.rb +11 -0
- data/test/unit/test-proc-validate.rb +68 -30
- metadata +26 -11
- data/doc/debugger.html +0 -108
data/processor/command/show.rb
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
3
|
require 'rubygems'; require 'require_relative'
|
4
4
|
require_relative 'base/submgr'
|
5
5
|
|
6
6
|
class Trepan::Command::ShowCommand < Trepan::SubcommandMgr
|
7
7
|
unless defined?(HELP)
|
8
|
-
|
9
|
-
|
8
|
+
NAME = File.basename(__FILE__, '.rb')
|
9
|
+
HELP = <<-HELP
|
10
|
+
Generic command for showing things about the debugger. You can
|
10
11
|
give unique prefix of the name of a subcommand to get information
|
11
12
|
about just that subcommand.
|
12
13
|
|
13
|
-
Type "
|
14
|
-
Type "help
|
14
|
+
Type "#{NAME}" for a list of "show" subcommands and what they do.
|
15
|
+
Type "help #{NAME} *" for just a list of "show" subcommands.
|
16
|
+
HELP
|
15
17
|
|
16
18
|
CATEGORY = 'status'
|
17
|
-
NAME = File.basename(__FILE__, '.rb')
|
18
19
|
NEED_STACK = false
|
19
20
|
SHORT_HELP = 'Show parts of the debugger environment'
|
20
21
|
end
|
data/processor/command/step.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'; require 'require_relative'
|
2
2
|
require_relative 'base/cmd'
|
3
|
+
require_relative '../../app/condition'
|
3
4
|
require_relative '../stepping'
|
4
5
|
|
5
6
|
class Trepan::Command::StepCommand < Trepan::Command
|
@@ -9,6 +10,7 @@ class Trepan::Command::StepCommand < Trepan::Command
|
|
9
10
|
NAME = File.basename(__FILE__, '.rb')
|
10
11
|
HELP = <<-HELP
|
11
12
|
#{NAME}[+|-] [into] [count]
|
13
|
+
#{NAME} until EXPRESSION
|
12
14
|
#{NAME} over [args..]
|
13
15
|
#{NAME} out [args..]
|
14
16
|
|
@@ -26,6 +28,7 @@ Examples:
|
|
26
28
|
#{NAME} 5/5+0 # same as above
|
27
29
|
#{NAME}+ # same but force stopping on a new line
|
28
30
|
#{NAME}- # same but force stopping on a new line a new frame added
|
31
|
+
#{NAME} until a > b
|
29
32
|
#{NAME} over # same as 'next'
|
30
33
|
#{NAME} out # same as 'finish'
|
31
34
|
|
@@ -44,15 +47,25 @@ See also the commands:
|
|
44
47
|
'into' => 'step',
|
45
48
|
}
|
46
49
|
|
47
|
-
|
50
|
+
include Trepan::Condition
|
51
|
+
# This method runs the command
|
52
|
+
def run(args) # :nodoc
|
53
|
+
condition = nil
|
54
|
+
opts = {}
|
48
55
|
if args.size == 1
|
49
56
|
step_count = 1
|
50
|
-
opts = {}
|
51
57
|
else
|
52
58
|
replace_cmd = Keyword_to_related_cmd[args[1]]
|
53
59
|
if replace_cmd
|
54
60
|
cmd = @proc.commands[replace_cmd]
|
55
61
|
return cmd.run([replace_cmd] + args[2..-1])
|
62
|
+
elsif 'until' == args[1]
|
63
|
+
try_condition = args[2..-1].join(' ')
|
64
|
+
if valid_condition?(try_condition)
|
65
|
+
condition = try_condition
|
66
|
+
opts[:different_pos] = false
|
67
|
+
step_count = 0
|
68
|
+
end
|
56
69
|
else
|
57
70
|
step_str = args[1]
|
58
71
|
opts = @proc.parse_next_step_suffix(args[0])
|
@@ -67,7 +80,7 @@ See also the commands:
|
|
67
80
|
end
|
68
81
|
end
|
69
82
|
|
70
|
-
@proc.step('step', step_count, opts)
|
83
|
+
@proc.step('step', step_count, opts, condition)
|
71
84
|
end
|
72
85
|
end
|
73
86
|
|
data/processor/command/tbreak.rb
CHANGED
@@ -3,7 +3,7 @@ require_relative './base/cmd'
|
|
3
3
|
require_relative 'break'
|
4
4
|
|
5
5
|
class Trepan::Command::SetTempBreakpointCommand <
|
6
|
-
Trepan::Command::
|
6
|
+
Trepan::Command::BreakCommand
|
7
7
|
ALIASES = %w(tb tbrk)
|
8
8
|
CATEGORY = 'breakpoints'
|
9
9
|
NAME = File.basename(__FILE__, '.rb')
|
data/processor/disassemble.rb
CHANGED
data/processor/help.rb
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
2
|
class Trepan
|
3
|
+
# class SubHelp
|
4
|
+
# def initialize(name, dir)
|
5
|
+
# @name = name
|
6
|
+
# @dir = dir
|
7
|
+
# load_sub_help_files(dir)
|
8
|
+
# end
|
9
|
+
|
10
|
+
# def load_sub_help_files(dir)
|
11
|
+
# Dir.glob(dir, '*.txt').each do |txt|
|
12
|
+
# basename = File.basename(txt, '.txt')
|
13
|
+
# @list << basename
|
14
|
+
# end
|
15
|
+
# end if File.directory?(dir)
|
16
|
+
|
17
|
+
# def summary_help
|
18
|
+
# section "List of #{@name} help"
|
19
|
+
# msg @list
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
|
3
23
|
module Help
|
4
24
|
|
5
25
|
def abbrev_stringify(name, min_abbrev)
|
data/processor/load_cmds.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
3
|
+
require 'tmpdir'
|
3
4
|
|
4
5
|
# Part of Trepan::CmdProcess that loads up debugger commands from
|
5
6
|
# builtin and user directories.
|
@@ -62,6 +63,23 @@ class Trepan
|
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
66
|
+
# Instantiate a Trepan::Command and extract info: the NAME, ALIASES
|
67
|
+
# and store the command in @commands.
|
68
|
+
def setup_command(command)
|
69
|
+
# Note: there is probably a non-eval way to instantiate the
|
70
|
+
# command, but I don't know it. And eval works.
|
71
|
+
klass = self.instance_eval("Trepan::Command::#{command}")
|
72
|
+
cmd = klass.send(:new, self)
|
73
|
+
|
74
|
+
# Add to list of commands and aliases.
|
75
|
+
cmd_name = klass.const_get(:NAME)
|
76
|
+
if klass.constants.member?(:ALIASES)
|
77
|
+
aliases= klass.const_get(:ALIASES)
|
78
|
+
aliases.each {|a| @aliases[a] = cmd_name}
|
79
|
+
end
|
80
|
+
@commands[cmd_name] = cmd
|
81
|
+
end
|
82
|
+
|
65
83
|
# Looks up cmd_array[0] in @commands and runs that. We do lots of
|
66
84
|
# validity testing on cmd_array.
|
67
85
|
def run_cmd(cmd_array)
|
@@ -85,6 +103,37 @@ class Trepan
|
|
85
103
|
end
|
86
104
|
end
|
87
105
|
|
106
|
+
def save_commands(opts)
|
107
|
+
save_filename = opts[:filename] ||
|
108
|
+
File.join(Dir.tmpdir, "trepanning-save-#{$$}.txt")
|
109
|
+
begin
|
110
|
+
save_file = File.open(save_filename, 'w')
|
111
|
+
rescue => exc
|
112
|
+
errmsg("Can't open #{save_filename} for writing.")
|
113
|
+
errmsg("System reports: #{exc.inspect}")
|
114
|
+
return nil
|
115
|
+
end
|
116
|
+
save_file.puts "#\n# Commands to restore trepanning environment\n#\n"
|
117
|
+
@commands.each do |cmd_name, cmd_obj|
|
118
|
+
cmd_obj.save_command if cmd_obj.respond_to?(:save_command)
|
119
|
+
next unless cmd_obj.is_a?(Trepan::SubcommandMgr)
|
120
|
+
cmd_obj.subcmds.subcmds.each do |subcmd_name, subcmd_obj|
|
121
|
+
save_file.puts subcmd_obj.save_command if
|
122
|
+
subcmd_obj.respond_to?(:save_command)
|
123
|
+
next unless subcmd_obj.is_a?(Trepan::SubSubcommandMgr)
|
124
|
+
subcmd_obj.subcmds.subcmds.each do |subsubcmd_name, subsubcmd_obj|
|
125
|
+
save_file.puts subsubcmd_obj.save_command if
|
126
|
+
subsubcmd_obj.respond_to?(:save_command)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
save_file.puts "!FileUtils.rm #{save_filename.inspect}" if
|
131
|
+
opts[:erase]
|
132
|
+
save_file.close
|
133
|
+
|
134
|
+
return save_filename
|
135
|
+
end
|
136
|
+
|
88
137
|
# Handle initial completion. We draw from the commands, aliases,
|
89
138
|
# and macros for completion. However we won't include aliases which
|
90
139
|
# are prefixes of other commands.
|
@@ -117,7 +166,7 @@ class Trepan
|
|
117
166
|
# ["#{name} #{args[1..-1].join(' ')}"]
|
118
167
|
# end
|
119
168
|
end
|
120
|
-
# match_pairs.size
|
169
|
+
# match_pairs.size <= 1
|
121
170
|
next_complete(str, next_blank_pos, match_pairs[0][1], last_token)
|
122
171
|
end
|
123
172
|
|
@@ -187,7 +236,7 @@ if __FILE__ == $0
|
|
187
236
|
cmdproc.run_cmd('foo') # Invalid - not an Array
|
188
237
|
cmdproc.run_cmd([]) # Invalid - empty Array
|
189
238
|
cmdproc.run_cmd(['list', 5]) # Invalid - nonstring arg
|
190
|
-
p cmdproc.complete("d")
|
191
|
-
p cmdproc.complete("sho d")
|
192
|
-
p cmdproc.complete('')
|
239
|
+
p cmdproc.complete("d", 'd')
|
240
|
+
p cmdproc.complete("sho d", 'd')
|
241
|
+
p cmdproc.complete('', '')
|
193
242
|
end
|
data/processor/location.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
+
require 'pathname' # For cleanpath
|
3
|
+
require 'rubygems';
|
2
4
|
require 'linecache'
|
3
|
-
require '
|
5
|
+
require 'require_relative'
|
4
6
|
require_relative 'disassemble'
|
5
7
|
require_relative 'msg'
|
6
8
|
require_relative 'frame'
|
@@ -12,6 +14,13 @@ class Trepan
|
|
12
14
|
@reload_on_change = nil
|
13
15
|
end
|
14
16
|
|
17
|
+
def canonic_file(filename)
|
18
|
+
# For now we want resolved filenames
|
19
|
+
@settings[:basename] ? File.basename(filename) :
|
20
|
+
# Cache this?
|
21
|
+
File.expand_path(Pathname.new(filename).cleanpath.to_s)
|
22
|
+
end
|
23
|
+
|
15
24
|
# Return the text to the current source line.
|
16
25
|
# FIXME: loc_and_text should call this rather than the other
|
17
26
|
# way around.
|
@@ -66,10 +75,12 @@ class Trepan
|
|
66
75
|
{:reload_on_change => @reload_on_change,
|
67
76
|
:output => @settings[:highlight]
|
68
77
|
})
|
78
|
+
|
69
79
|
vm_location = @frame.vm_location
|
70
80
|
filename = vm_location.method.active_path
|
71
81
|
line_no = vm_location.line
|
72
82
|
static = vm_location.static_scope
|
83
|
+
opts[:compiled_method] = top_scope(@frame.method)
|
73
84
|
|
74
85
|
if @frame.eval?
|
75
86
|
file = LineCache::map_script(static.script)
|
@@ -175,3 +186,38 @@ class Trepan
|
|
175
186
|
|
176
187
|
end
|
177
188
|
end
|
189
|
+
|
190
|
+
if __FILE__ == $0 && caller.size == 0 && ARGV.size > 0
|
191
|
+
# Demo it.
|
192
|
+
require 'thread_frame'
|
193
|
+
require_relative 'frame'
|
194
|
+
require_relative '../app/mock'
|
195
|
+
require_relative 'main' # Have to include before defining CmdProcessor!
|
196
|
+
# FIXME
|
197
|
+
class Trepan::CmdProcessor
|
198
|
+
def errmsg(msg)
|
199
|
+
puts msg
|
200
|
+
end
|
201
|
+
def print_location
|
202
|
+
puts "#{@frame.source_container} #{frame.source_location[0]}"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
proc = Trepan::CmdProcessor.new(Trepan::MockCore.new())
|
207
|
+
proc.instance_variable_set('@settings', {})
|
208
|
+
proc.frame_initialize
|
209
|
+
#proc.frame_setup(RubyVM::ThreadFrame.current)
|
210
|
+
proc.frame_initialize
|
211
|
+
|
212
|
+
proc.location_initialize
|
213
|
+
puts proc.canonic_file(__FILE__)
|
214
|
+
proc.instance_variable_set('@settings', {:basename => true})
|
215
|
+
puts proc.canonic_file(__FILE__)
|
216
|
+
puts proc.current_source_text
|
217
|
+
xx = eval <<-END
|
218
|
+
proc.frame_initialize
|
219
|
+
##proc.frame_setup(RubyVM::ThreadFrame.current)
|
220
|
+
proc.location_initialize
|
221
|
+
proc.current_source_text
|
222
|
+
END
|
223
|
+
end
|
data/processor/main.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
# command class and debugger command objects are pulled in from here.
|
4
4
|
|
5
5
|
require 'set'
|
6
|
-
require 'pathname' # For cleanpath
|
7
6
|
|
8
7
|
require 'rubygems'; require 'require_relative'
|
9
8
|
## %w(default display eventbuf eval load_cmds location frame hook msg
|
@@ -137,13 +136,6 @@ class Trepan
|
|
137
136
|
[container[0], canonic_file(container[1])]
|
138
137
|
end
|
139
138
|
|
140
|
-
def canonic_file(filename)
|
141
|
-
# For now we want resolved filenames
|
142
|
-
@settings[:basename] ? File.basename(filename) :
|
143
|
-
# Cache this?
|
144
|
-
Pathname.new(filename).cleanpath.to_s
|
145
|
-
end
|
146
|
-
|
147
139
|
def compute_prompt
|
148
140
|
"(#{@settings[:prompt]}): "
|
149
141
|
end
|
@@ -213,6 +205,9 @@ class Trepan
|
|
213
205
|
quit('exit!')
|
214
206
|
return true
|
215
207
|
end
|
208
|
+
rescue Exception => exc
|
209
|
+
errmsg("Internal debugger error in read: #{exc.inspect}")
|
210
|
+
exception_dump(exc, @settings[:debugexcept], $!.backtrace)
|
216
211
|
end
|
217
212
|
end
|
218
213
|
run_command(@current_command)
|
@@ -235,7 +230,7 @@ class Trepan
|
|
235
230
|
@last_pos = [@frame.vm_location, @stack_size, @current_thread, @event]
|
236
231
|
else
|
237
232
|
if stepping_skip? # || @stack_size <= @hide_level
|
238
|
-
step(@return_to_program, @step_count)
|
233
|
+
step(@return_to_program, @step_count, {}, @stop_condition)
|
239
234
|
return true
|
240
235
|
elsif @event == 'start'
|
241
236
|
step('step', 0)
|
data/processor/mock.rb
CHANGED
@@ -28,12 +28,12 @@ module MockDebugger
|
|
28
28
|
attr_reader :cmd_argstr, :cmd_name, :vm_locations, :current_frame,
|
29
29
|
:debugee_thread, :completion_proc
|
30
30
|
|
31
|
-
def initialize(settings={})
|
31
|
+
def initialize(settings={:start_frame=>1})
|
32
32
|
@before_cmdloop_hooks = []
|
33
33
|
@settings = Trepan::DEFAULT_SETTINGS.merge(settings)
|
34
34
|
@intf = [Trepan::UserInterface.new(nil, nil,
|
35
35
|
:history_save=>false)]
|
36
|
-
@vm_locations = Rubinius::VM.backtrace(
|
36
|
+
@vm_locations = Rubinius::VM.backtrace(settings[:start_frame], true)
|
37
37
|
@current_frame = Trepan::Frame.new(self, 0, @vm_locations[0])
|
38
38
|
@debugee_thread = Thread.current
|
39
39
|
@frames = []
|
@@ -66,7 +66,7 @@ module MockDebugger
|
|
66
66
|
dbgr = Trepan.new
|
67
67
|
dbgr.debugger
|
68
68
|
else
|
69
|
-
dbgr = MockDebugger.new
|
69
|
+
dbgr = MockDebugger.new(:start_frame=>2)
|
70
70
|
end
|
71
71
|
|
72
72
|
cmdproc = Trepan::CmdProcessor.new(dbgr)
|
data/processor/running.rb
CHANGED
@@ -193,24 +193,23 @@ class Trepan
|
|
193
193
|
end
|
194
194
|
|
195
195
|
@last_pos[2] = new_pos[2] if 'nostack' == @different_pos
|
196
|
-
condition_met =
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
# end
|
196
|
+
condition_met =
|
197
|
+
if @stop_condition
|
198
|
+
puts "stop_cond #{@stop_condition}" if @settings[:'debugskip']
|
199
|
+
debug_eval_no_errmsg(@stop_condition)
|
200
|
+
elsif @to_method
|
201
|
+
puts "method #{@frame.method} #{@to_method}" if
|
202
|
+
@settings[:'debugskip']
|
203
|
+
@frame.method == @to_method
|
204
|
+
else
|
205
|
+
puts 'uncond' if @settings[:'debugskip']
|
206
|
+
@step_count == 0
|
207
|
+
end
|
209
208
|
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
209
|
+
msg("condition_met: #{condition_met}, last: #{@last_pos}, " +
|
210
|
+
"new: #{new_pos}, different #{@different_pos.inspect}") if
|
211
|
+
@settings[:'debugskip']
|
212
|
+
|
214
213
|
should_skip = ((@last_pos[0..3] == new_pos[0..3] && @different_pos) ||
|
215
214
|
!condition_met)
|
216
215
|
|