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
data/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.org>
|
|
2
|
+
All rights reserved.
|
|
3
|
+
*
|
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
|
5
|
+
modification, are permitted provided that the following conditions
|
|
6
|
+
are met:
|
|
7
|
+
1. Redistributions of source code must retain the above copyright
|
|
8
|
+
notice, this list of conditions and the following disclaimer.
|
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright
|
|
10
|
+
notice, this list of conditions and the following disclaimer in the
|
|
11
|
+
documentation and/or other materials provided with the distribution.
|
|
12
|
+
*
|
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
14
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
15
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
16
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
17
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
18
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
19
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
20
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
21
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
22
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
23
|
+
SUCH DAMAGE.
|
data/NEWS
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Oct 8, 2010
|
|
2
|
+
First release under the name trepanning
|
|
3
|
+
|
|
4
|
+
* Add gdb-like "directory" command
|
|
5
|
+
* Add "set max list" to set number of lines to list by default.
|
|
6
|
+
* "break line" searches parent instruction sequences in the same file. This
|
|
7
|
+
should allow more line numbers to be breakpointable.
|
|
8
|
+
* Some small bug fixes
|
|
9
|
+
|
|
10
|
+
Sept 13, 2010
|
|
11
|
+
|
|
12
|
+
First public (gemcutter) release.
|
data/README.textile
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
A modular, testable debugger for Ruby 1.9.2. A total rewrite of _ruby-debug_.
|
|
2
|
+
|
|
3
|
+
__In order to use this debugger, you'll need a patched Ruby 1.9.2 and some additional packages. See the "installation instructions.":http://wiki.github.com/rocky/rb-trepanning/how-to-install-rbdbgr__
|
|
4
|
+
|
|
5
|
+
Right now this debugger is beta code.
|
|
6
|
+
|
|
7
|
+
There is a "google group mailing list":http://groups.google.com/group/ruby-debugger for Ruby debuggers.
|
|
8
|
+
|
|
9
|
+
If rb-trepanning is installed, here is how to run:
|
|
10
|
+
|
|
11
|
+
bc. trepan ruby-program [program]
|
|
12
|
+
|
|
13
|
+
If your program needs options of its own:
|
|
14
|
+
|
|
15
|
+
bc. trepan -- ruby-program [program args...]
|
|
16
|
+
|
|
17
|
+
If you want to run from the source tree you can do that too:
|
|
18
|
+
|
|
19
|
+
bc. cd place-where-trepan-is-installed:
|
|
20
|
+
./bin/trepan -- ruby-program [program args...]
|
|
21
|
+
|
|
22
|
+
Running from inside _irb_:
|
|
23
|
+
|
|
24
|
+
bc. require 'trepanning'
|
|
25
|
+
Trepan.debug { your code }
|
|
26
|
+
|
|
27
|
+
The return value from Trepan is the return value of the block, i.e. the final value in the block.
|
|
28
|
+
|
|
29
|
+
You can run the same thing inside your Ruby program, but probably you don't want to give a block. Instead, you may want to have debugging start on the next statement in the code:
|
|
30
|
+
|
|
31
|
+
bc. require 'trepan'
|
|
32
|
+
Trepan.debug # Don't stop here...
|
|
33
|
+
work # but stop here.
|
|
34
|
+
|
|
35
|
+
or if you haven't mucked around with $0 and ARGV, you might try:
|
|
36
|
+
|
|
37
|
+
bc. Trepan.debug(:set_restart=>true)
|
|
38
|
+
|
|
39
|
+
which informs the debugger on how to restart the program (via the restart command) using the values of ARGV and $0 at the time Trepan.debug was called.
|
|
40
|
+
|
|
41
|
+
The above is really shorthand for something like:
|
|
42
|
+
|
|
43
|
+
bc. $trepan = Trepan.new(:set_restart=>true)
|
|
44
|
+
$trepan.debugger
|
|
45
|
+
|
|
46
|
+
The global variable $trepan set holds debugger settings, such as "autolist" or "autoeval" settings and breakpoint information.
|
|
47
|
+
|
|
48
|
+
Due to the line-event orientation in ruby-debug, it occasionally it was convenient to add a synchronous stop in your program. I don't think that will as necessary here, but if you do call to the debugger at the point of the call rather than the subsequent stopping point, set opts[:immediate] to true. Example:
|
|
49
|
+
|
|
50
|
+
bc. # ... work, work, work
|
|
51
|
+
mydbg.debugger(:immediate=>true) # enter debugger here
|
|
52
|
+
# ... work, work, work
|
|
53
|
+
|
|
54
|
+
There is extensive on-line help. Run "help" inside the debugger.
|
|
55
|
+
|
|
56
|
+
|
data/Rakefile
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
#!/usr/bin/env rake
|
|
2
|
+
# -*- Ruby -*-
|
|
3
|
+
require 'rubygems'
|
|
4
|
+
require 'rake/gempackagetask'
|
|
5
|
+
require 'rake/rdoctask'
|
|
6
|
+
require 'rake/testtask'
|
|
7
|
+
|
|
8
|
+
ROOT_DIR = File.dirname(__FILE__)
|
|
9
|
+
require File.join %W(#{ROOT_DIR} app options)
|
|
10
|
+
|
|
11
|
+
def gemspec
|
|
12
|
+
@gemspec ||= eval(File.read('.gemspec'), binding, '.gemspec')
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc "Build the gem"
|
|
16
|
+
task :package=>:gem
|
|
17
|
+
task :gem=>:gemspec do
|
|
18
|
+
Dir.chdir(ROOT_DIR) do
|
|
19
|
+
sh "gem build .gemspec"
|
|
20
|
+
FileUtils.mkdir_p 'pkg'
|
|
21
|
+
FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", 'pkg'
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc "Install the gem locally"
|
|
26
|
+
task :install => :gem do
|
|
27
|
+
Dir.chdir(ROOT_DIR) do
|
|
28
|
+
sh %{gem install --local pkg/#{gemspec.name}-#{gemspec.version}}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
desc "Test everything."
|
|
33
|
+
Rake::TestTask.new(:test) do |t|
|
|
34
|
+
t.libs << './lib'
|
|
35
|
+
t.pattern = 'test/test-*.rb'
|
|
36
|
+
t.verbose = true
|
|
37
|
+
end
|
|
38
|
+
task :test => :lib
|
|
39
|
+
|
|
40
|
+
desc "same as test"
|
|
41
|
+
task :check => :test
|
|
42
|
+
|
|
43
|
+
require 'rbconfig'
|
|
44
|
+
RUBY_PATH = File.join(RbConfig::CONFIG['bindir'],
|
|
45
|
+
RbConfig::CONFIG['RUBY_INSTALL_NAME'])
|
|
46
|
+
|
|
47
|
+
def run_standalone_ruby_file(directory)
|
|
48
|
+
puts ('*' * 10) + ' ' + directory + ' ' + ('*' * 10)
|
|
49
|
+
Dir.chdir(directory) do
|
|
50
|
+
Dir.glob('*.rb').each do |ruby_file|
|
|
51
|
+
puts ('-' * 20) + ' ' + ruby_file + ' ' + ('-' * 20)
|
|
52
|
+
system(RUBY_PATH, ruby_file)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
desc 'Create a GNU-style ChangeLog via git2cl'
|
|
58
|
+
task :ChangeLog do
|
|
59
|
+
system('git log --pretty --numstat --summary | git2cl > ChangeLog')
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc 'Test units - the smaller tests'
|
|
63
|
+
task :'test:unit' do |t|
|
|
64
|
+
Rake::TestTask.new(:'test:unit') do |t|
|
|
65
|
+
t.test_files = FileList['test/unit/**/test-*.rb']
|
|
66
|
+
# t.pattern = 'test/**/*test-*.rb' # instead of above
|
|
67
|
+
t.verbose = true
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
desc 'Test functional - the medium-sized tests'
|
|
72
|
+
task :'test:functional' do |t|
|
|
73
|
+
Rake::TestTask.new(:'test:functional') do |t|
|
|
74
|
+
t.test_files = FileList['test/functional/**/test-*.rb']
|
|
75
|
+
t.verbose = true
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
desc 'Test integration - end-to-end blackbox tests'
|
|
80
|
+
task :'test:integration' do |t|
|
|
81
|
+
Rake::TestTask.new(:'test:integration') do |t|
|
|
82
|
+
t.test_files = FileList['test/integration/**/test-*.rb']
|
|
83
|
+
t.verbose = true
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
desc 'Test everything - unit tests for now.'
|
|
88
|
+
task :test do
|
|
89
|
+
exceptions = %w(test:unit test:functional test:integration).collect do |task|
|
|
90
|
+
begin
|
|
91
|
+
Rake::Task[task].invoke
|
|
92
|
+
nil
|
|
93
|
+
rescue => e
|
|
94
|
+
e
|
|
95
|
+
end
|
|
96
|
+
end.compact
|
|
97
|
+
|
|
98
|
+
exceptions.each {|e| puts e;puts e.backtrace }
|
|
99
|
+
raise "Test failures" unless exceptions.empty?
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
desc "Run each library Ruby file in standalone mode."
|
|
103
|
+
task :'check:app' do
|
|
104
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} app)))
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
desc "Run each command in standalone mode."
|
|
108
|
+
task :'check:commands' do
|
|
109
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} processor command)))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
desc "Run each processor Ruby file in standalone mode."
|
|
113
|
+
task :'check:lib' do
|
|
114
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} lib)))
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
desc "Run each processor Ruby file in standalone mode."
|
|
118
|
+
task :'check:processor' do
|
|
119
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} processor)))
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
desc "Run each processor Ruby file in standalone mode."
|
|
123
|
+
task :'check:unit' do
|
|
124
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} test unit)))
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
task :'check:functional' do
|
|
128
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} test functional)))
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
task :'check:integration' do
|
|
132
|
+
run_standalone_ruby_file(File.join(%W(#{ROOT_DIR} test integration)))
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
task :check => %w(check:lib check:processor check:commands).map{|c| c.to_sym}
|
|
136
|
+
|
|
137
|
+
desc "Test everything - same as test."
|
|
138
|
+
task :default => :test
|
|
139
|
+
|
|
140
|
+
desc "Generate the gemspec"
|
|
141
|
+
task :generate do
|
|
142
|
+
puts gemspec.to_ruby
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
desc "Validate the gemspec"
|
|
146
|
+
task :gemspec do
|
|
147
|
+
gemspec.validate
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# --------- RDoc Documentation ------
|
|
151
|
+
desc "Generate rdoc documentation"
|
|
152
|
+
Rake::RDocTask.new("rdoc") do |rdoc|
|
|
153
|
+
rdoc.rdoc_dir = 'doc'
|
|
154
|
+
rdoc.title = "Trepanning #{Trepanning::VERSION} Documentation"
|
|
155
|
+
|
|
156
|
+
rdoc.rdoc_files.include('lib/*.rb', 'app/*.rb', 'bin/trepan')
|
|
157
|
+
end
|
|
158
|
+
desc "Same as rdoc"
|
|
159
|
+
task :doc => :rdoc
|
|
160
|
+
|
|
161
|
+
desc "Remove built files"
|
|
162
|
+
task :clean => [:clobber_package, :clobber_rdoc]
|
|
163
|
+
|
|
164
|
+
task :clobber_package do
|
|
165
|
+
FileUtils.rm_rf File.join(ROOT_DIR, 'pkg')
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
task :clobber_rdoc do
|
|
169
|
+
FileUtils.rm_rf File.join(ROOT_DIR, 'doc')
|
|
170
|
+
end
|
|
171
|
+
|
data/app/Makefile
ADDED
data/app/breakpoint.rb
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require 'thread_frame'
|
|
4
|
+
|
|
5
|
+
# Breakpoint objects
|
|
6
|
+
module Trepanning
|
|
7
|
+
class Breakpoint
|
|
8
|
+
attr_accessor :condition # If non-nil, this is a String to be eval'd
|
|
9
|
+
# which must be true to enter the debugger
|
|
10
|
+
attr_accessor :hits # Fixnum. The number of timea a breakpoint
|
|
11
|
+
# has been hit (with a true condition). Do
|
|
12
|
+
# we want to (also) record hits independent
|
|
13
|
+
# of the condition?
|
|
14
|
+
attr_reader :id # Fixnum. Name of breakpoint
|
|
15
|
+
attr_reader :ignore # Fixnum. Number of times encountered to ignore
|
|
16
|
+
attr_reader :iseq # Instruction sequence associated with this
|
|
17
|
+
# breakpoint. From this we can derive
|
|
18
|
+
# information such as source location.
|
|
19
|
+
attr_reader :offset # Fixnum. Offset into an instruction
|
|
20
|
+
# sequence for the location of the
|
|
21
|
+
# breakpoint
|
|
22
|
+
attr_reader :type # String. 'line' if breakpoint requested
|
|
23
|
+
# at "line" boundary or 'offset'
|
|
24
|
+
# requested at a specific offset
|
|
25
|
+
@@next_id = 1
|
|
26
|
+
|
|
27
|
+
BRKPT_DEFAULT_SETTINGS = {
|
|
28
|
+
:condition => 'true',
|
|
29
|
+
:enabled => 'true',
|
|
30
|
+
:ignore => 0,
|
|
31
|
+
:temp => false,
|
|
32
|
+
:type => 'line',
|
|
33
|
+
} unless defined?(BRKPT_DEFAULT_SETTINGS)
|
|
34
|
+
|
|
35
|
+
def initialize(iseq, offset, opts = {})
|
|
36
|
+
raise TypeError,
|
|
37
|
+
"#{iseq} is not an instruction sequence" unless
|
|
38
|
+
iseq.is_a?(RubyVM::InstructionSequence)
|
|
39
|
+
@iseq = iseq
|
|
40
|
+
|
|
41
|
+
raise TypeError,
|
|
42
|
+
"offset #{offset.inspect} not found in instruction sequence" unless
|
|
43
|
+
iseq.offset2lines(offset)
|
|
44
|
+
@offset = iseq
|
|
45
|
+
|
|
46
|
+
raise TypeError,
|
|
47
|
+
"type mismatch: #{offset.class} given, Fixnum expected" unless
|
|
48
|
+
offset.is_a?(Fixnum)
|
|
49
|
+
@offset = offset
|
|
50
|
+
|
|
51
|
+
opts = BRKPT_DEFAULT_SETTINGS.merge(opts)
|
|
52
|
+
opts.keys.each do |key|
|
|
53
|
+
self.instance_variable_set('@'+key.to_s, opts[key])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
@hits = 0
|
|
57
|
+
|
|
58
|
+
unless @id
|
|
59
|
+
@id = @@next_id
|
|
60
|
+
@@next_id += 1
|
|
61
|
+
end
|
|
62
|
+
set
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def condition?(bind)
|
|
66
|
+
if eval(@condition, bind)
|
|
67
|
+
if @ignore > 0
|
|
68
|
+
@ignore -= 1
|
|
69
|
+
return false
|
|
70
|
+
else
|
|
71
|
+
@hits += 1
|
|
72
|
+
return true
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
return false
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def disable
|
|
80
|
+
@enabled = false
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def enabled
|
|
84
|
+
@enabled = true
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def enabled=(bool)
|
|
88
|
+
@enabled = bool
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def enabled?
|
|
92
|
+
@enabled
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Return a one-character "icon" giving the state of the breakpoint
|
|
96
|
+
# 't': temporary breakpoint
|
|
97
|
+
# 'B': enabled breakpoint
|
|
98
|
+
# 'b': disabled breakpoint
|
|
99
|
+
def icon_char
|
|
100
|
+
temp? ? 't' : (enabled? ? 'B' : 'b')
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def set
|
|
104
|
+
@iseq.brkpt_set(@offset)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def source_container
|
|
108
|
+
@iseq.source_container
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def source_location
|
|
112
|
+
@iseq.offset2lines(@offset)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def temp?
|
|
116
|
+
@temp
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def remove!
|
|
120
|
+
@iseq.brkpt_unset(@offset)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
# Really shouldn't need this after next_id is removed.
|
|
124
|
+
def self.reset
|
|
125
|
+
@@next_id = 1
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
if __FILE__ == $0
|
|
132
|
+
tf = RubyVM::ThreadFrame.current
|
|
133
|
+
iseq = tf.iseq
|
|
134
|
+
b1 = Trepanning::Breakpoint.new(iseq, 0)
|
|
135
|
+
p b1
|
|
136
|
+
p b1.source_location
|
|
137
|
+
p b1.source_container
|
|
138
|
+
b2 = Trepanning::Breakpoint.new(iseq, 0, :temp => true)
|
|
139
|
+
p b2
|
|
140
|
+
puts "b2 id: #{b2.id}"
|
|
141
|
+
puts "b2 hits: #{b2.hits}"
|
|
142
|
+
puts "b2.condition? #{b2.condition?(tf.binding)}"
|
|
143
|
+
puts "b2 hits: #{b2.hits}"
|
|
144
|
+
begin
|
|
145
|
+
b3 = Breakpoint.new(iseq, iseq.iseq_size)
|
|
146
|
+
rescue TypeError => e
|
|
147
|
+
puts "TypeError (expected): #{e}"
|
|
148
|
+
end
|
|
149
|
+
begin
|
|
150
|
+
b3 = Trepanning::Breakpoint.new(5, iseq.iseq_size)
|
|
151
|
+
rescue TypeError => e
|
|
152
|
+
puts "TypeError (expected): #{e}"
|
|
153
|
+
end
|
|
154
|
+
puts Trepanning::Breakpoint.class_variable_get('@@next_id')
|
|
155
|
+
Trepanning::Breakpoint.reset
|
|
156
|
+
puts Trepanning::Breakpoint.class_variable_get('@@next_id')
|
|
157
|
+
end
|
data/app/brkptmgr.rb
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
require 'set'
|
|
3
|
+
require_relative 'breakpoint'
|
|
4
|
+
class BreakpointMgr
|
|
5
|
+
|
|
6
|
+
attr_reader :list
|
|
7
|
+
attr_reader :set
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@list = []
|
|
11
|
+
@next_id = 1
|
|
12
|
+
@set = Set.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def <<(brkpt)
|
|
16
|
+
@list << brkpt
|
|
17
|
+
@set.add(set_key(brkpt))
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def [](index)
|
|
21
|
+
raise TypeError,
|
|
22
|
+
"index #{index} should be a Fixnum, is #{index.class}" unless
|
|
23
|
+
index.is_a?(Fixnum)
|
|
24
|
+
@list.detect {|bp| bp.id == index }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alias detect []
|
|
28
|
+
|
|
29
|
+
def delete(index)
|
|
30
|
+
bp = detect(index)
|
|
31
|
+
if bp
|
|
32
|
+
delete_by_brkpt(bp)
|
|
33
|
+
return bp
|
|
34
|
+
else
|
|
35
|
+
return nil
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete_by_brkpt(delete_bp)
|
|
40
|
+
@list = @list.reject{|candidate| candidate == delete_bp}
|
|
41
|
+
@set = Set.new(@list.map{|bp| set_key(bp)})
|
|
42
|
+
delete_bp.remove! unless @set.member?(set_key(delete_bp))
|
|
43
|
+
return delete_bp
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add(*args)
|
|
47
|
+
if args[2]
|
|
48
|
+
unless args[2].member?(:id)
|
|
49
|
+
args[2][:id] = @next_id
|
|
50
|
+
@next_id += 1
|
|
51
|
+
end
|
|
52
|
+
else
|
|
53
|
+
args[2] = {:id => @next_id}
|
|
54
|
+
@next_id += 1
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
brkpt = Trepanning::Breakpoint.new(*args)
|
|
58
|
+
@list << brkpt
|
|
59
|
+
@set.add(set_key(brkpt))
|
|
60
|
+
return brkpt
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def empty?
|
|
64
|
+
@list.empty?
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def line_breaks(container)
|
|
68
|
+
result = {}
|
|
69
|
+
@list.each do |bp|
|
|
70
|
+
if bp.source_container == container
|
|
71
|
+
bp.source_location.each do |line|
|
|
72
|
+
result[line] = bp
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
result
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def find(iseq, offset, bind)
|
|
80
|
+
@list.detect do |bp|
|
|
81
|
+
if bp.enabled? && bp.iseq.equal?(iseq) && bp.offset == offset
|
|
82
|
+
begin
|
|
83
|
+
return bp if bp.condition?(bind)
|
|
84
|
+
rescue
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def max
|
|
91
|
+
@list.map{|bp| bp.id}.max
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Key used in @set to list unique instruction-sequence offsets.
|
|
95
|
+
def set_key(bp)
|
|
96
|
+
[bp.iseq, bp.offset]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def size
|
|
100
|
+
@list.size
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def reset
|
|
104
|
+
@list.each{|bp| bp.remove!}
|
|
105
|
+
@list = []
|
|
106
|
+
@set = Set.new
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
if __FILE__ == $0
|
|
111
|
+
def bp_status(brkpts, i)
|
|
112
|
+
puts "list size: #{brkpts.list.size}"
|
|
113
|
+
puts "set size: #{brkpts.set.size}"
|
|
114
|
+
puts "max: #{brkpts.max}"
|
|
115
|
+
p brkpts
|
|
116
|
+
puts "--- #{i} ---"
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
frame = RubyVM::ThreadFrame.current
|
|
120
|
+
iseq = frame.iseq
|
|
121
|
+
brkpts = BreakpointMgr.new
|
|
122
|
+
brkpts.add(iseq, 0)
|
|
123
|
+
p brkpts[2]
|
|
124
|
+
bp_status(brkpts, 1)
|
|
125
|
+
offset = frame.pc_offset
|
|
126
|
+
b2 = Trepanning::Breakpoint.new(iseq, offset)
|
|
127
|
+
brkpts << b2
|
|
128
|
+
p brkpts.find(b2.iseq, b2.offset, nil)
|
|
129
|
+
p brkpts[2]
|
|
130
|
+
puts '--- 2 ---'
|
|
131
|
+
p brkpts.line_breaks(iseq.source_container)
|
|
132
|
+
p brkpts.delete(2)
|
|
133
|
+
p brkpts[2]
|
|
134
|
+
bp_status(brkpts, 3)
|
|
135
|
+
|
|
136
|
+
# Two of the same breakpoints but delete 1 and see that the
|
|
137
|
+
# other still stays
|
|
138
|
+
offset = frame.pc_offset
|
|
139
|
+
b2 = Trepanning::Breakpoint.new(iseq, offset)
|
|
140
|
+
brkpts << b2
|
|
141
|
+
bp_status(brkpts, 4)
|
|
142
|
+
b3 = Trepanning::Breakpoint.new(iseq, offset)
|
|
143
|
+
brkpts << b3
|
|
144
|
+
bp_status(brkpts, 5)
|
|
145
|
+
brkpts.delete_by_brkpt(b2)
|
|
146
|
+
bp_status(brkpts, 6)
|
|
147
|
+
brkpts.delete_by_brkpt(b3)
|
|
148
|
+
bp_status(brkpts, 7)
|
|
149
|
+
end
|
data/app/condition.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
class Trepan
|
|
3
|
+
module Condition
|
|
4
|
+
def valid_condition?(str)
|
|
5
|
+
begin
|
|
6
|
+
RubyVM::InstructionSequence.compile(str)
|
|
7
|
+
rescue SyntaxError
|
|
8
|
+
return nil
|
|
9
|
+
rescue
|
|
10
|
+
nil
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
module_function :valid_condition?
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
if __FILE__ == $0
|
|
17
|
+
include Trepan::Condition
|
|
18
|
+
p valid_condition?('a+2')
|
|
19
|
+
puts '-' * 20
|
|
20
|
+
p valid_condition?('1+')
|
|
21
|
+
puts '-' * 20
|
|
22
|
+
end
|