trepanning 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +289 -443
- data/NEWS +3 -0
- data/app/options.rb +1 -1
- data/app/run.rb +1 -2
- data/interface/script.rb +2 -2
- data/lib/trepanning.rb +1 -1
- data/processor/breakpoint.rb +5 -6
- data/processor/command/base/subcmd.rb +7 -5
- data/processor/command/base/submgr.rb +2 -2
- data/processor/command/disassemble.rb +10 -11
- data/processor/command/info_subcmd/file.rb +2 -2
- data/processor/command/irb.rb +1 -1
- data/processor/command/kill.rb +2 -2
- data/processor/command/list.rb +4 -4
- data/processor/command/nocache.rb +1 -1
- data/processor/command/set_subcmd/substitute_subcmd/eval.rb +1 -1
- data/processor/main.rb +1 -1
- data/processor/running.rb +0 -1
- data/test/data/enable.cmd +12 -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.cmd +5 -0
- data/test/data/quit.right +0 -0
- data/test/example/null.rb +1 -0
- data/test/integration/helper.rb +45 -26
- data/test/unit/test-app-file.rb +1 -0
- metadata +10 -7
- data/data/custom_require.rb +0 -44
- data/data/irbrc +0 -41
- data/data/prelude.rb +0 -38
data/NEWS
CHANGED
data/app/options.rb
CHANGED
@@ -65,7 +65,7 @@ EOB
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
opts.on('--nx',
|
68
|
-
"Do not run debugger initialization
|
68
|
+
"Do not run debugger initialization file #{CMD_INITFILE}") do
|
69
69
|
options[:nx] = true
|
70
70
|
end
|
71
71
|
# opts.on('--output FILE', String, "Name of file to record output") do |outfile|
|
data/app/run.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
require 'rbconfig'
|
4
4
|
module Trepanning
|
5
5
|
|
6
|
-
|
6
|
+
module_function # All functions below are easily publically accessible
|
7
7
|
|
8
8
|
# Given a Ruby interpreter and program we are to debug, debug it.
|
9
9
|
# The caller must ensure that ARGV is set up to remove any debugger
|
@@ -50,7 +50,6 @@ module Trepanning
|
|
50
50
|
def ruby_path
|
51
51
|
File.join(%w(bindir RUBY_INSTALL_NAME).map{|k| RbConfig::CONFIG[k]})
|
52
52
|
end
|
53
|
-
module_function :ruby_path
|
54
53
|
|
55
54
|
# Do a shell-like path lookup for prog_script and return the results.
|
56
55
|
# If we can't find anything return prog_script.
|
data/interface/script.rb
CHANGED
@@ -24,8 +24,8 @@ class Trepan::ScriptInterface < Trepan::Interface
|
|
24
24
|
at_exit { finalize }
|
25
25
|
@script_name = script_name
|
26
26
|
@input_lineno = 0
|
27
|
-
@input =
|
28
|
-
|
27
|
+
@input = opts[:input] ||
|
28
|
+
Trepan::UserInput.open(script_name, :line_edit => false)
|
29
29
|
@buffer_output = []
|
30
30
|
unless opts[:verbose] or out
|
31
31
|
out = Trepan::StringArrayOutput.open(@buffer_output)
|
data/lib/trepanning.rb
CHANGED
data/processor/breakpoint.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# Copyright (C) 2010 Rocky Bernstein <rockyb@rubyforge.net>
|
2
|
-
require_relative '../app/core'
|
3
2
|
class Trepan
|
4
3
|
|
5
4
|
class CmdProcessor
|
@@ -14,8 +13,8 @@ class Trepan
|
|
14
13
|
# If no breakpoint stop this is nil.
|
15
14
|
|
16
15
|
def breakpoint_initialize
|
17
|
-
@brkpts
|
18
|
-
@brkpt
|
16
|
+
@brkpts = BreakpointMgr.new
|
17
|
+
@brkpt = nil
|
19
18
|
end
|
20
19
|
|
21
20
|
def breakpoint?
|
@@ -44,13 +43,13 @@ class Trepan
|
|
44
43
|
end
|
45
44
|
|
46
45
|
# Does whatever needs to be done to set a breakpoint
|
47
|
-
def breakpoint_line(line_number,
|
46
|
+
def breakpoint_line(line_number, initial_iseq, temp=false)
|
48
47
|
# FIXME: handle breakpoint conditions.
|
49
|
-
found_iseq =
|
48
|
+
found_iseq = initial_iseq.child_iseqs.detect do |iseq|
|
50
49
|
iseq.lineoffsets.keys.member?(line_number)
|
51
50
|
end
|
52
51
|
unless found_iseq
|
53
|
-
found_iseq =
|
52
|
+
found_iseq = initial_iseq.parent
|
54
53
|
while found_iseq do
|
55
54
|
break if found_iseq.lineoffsets.keys.member?(line_number)
|
56
55
|
found_iseq = found_iseq.parent
|
@@ -27,6 +27,7 @@ class Trepan
|
|
27
27
|
# which append current settings to list output.
|
28
28
|
MIN_ABBREV = 1
|
29
29
|
NEED_STACK = false
|
30
|
+
NAME = 'your_command_name'
|
30
31
|
end
|
31
32
|
|
32
33
|
|
@@ -180,11 +181,12 @@ class Trepan
|
|
180
181
|
|
181
182
|
class ShowIntSubcommand < Subcommand
|
182
183
|
def run(args)
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
doc =
|
185
|
+
if self.respond_to?(:short_help)
|
186
|
+
short_help
|
187
|
+
else
|
188
|
+
my_const(:HELP)[5..-2].capitalize
|
189
|
+
end
|
188
190
|
run_show_int(doc)
|
189
191
|
end
|
190
192
|
end
|
@@ -28,7 +28,7 @@ class Trepan::SubcommandMgr < Trepan::Command
|
|
28
28
|
@name = obj_const(self, :NAME)
|
29
29
|
@subcmds = Trepan::Subcmd.new(self)
|
30
30
|
@proc = proc
|
31
|
-
load_debugger_subcommands(
|
31
|
+
load_debugger_subcommands(self)
|
32
32
|
end
|
33
33
|
|
34
34
|
# Create an instance of each of the debugger subcommands. Commands
|
@@ -38,7 +38,7 @@ class Trepan::SubcommandMgr < Trepan::Command
|
|
38
38
|
# inside those files and for each class name, we will create an
|
39
39
|
# instance of that class. The set of TrepanCommand class instances
|
40
40
|
# form set of possible debugger commands.
|
41
|
-
def load_debugger_subcommands(
|
41
|
+
def load_debugger_subcommands(parent)
|
42
42
|
|
43
43
|
# Initialization
|
44
44
|
cmd_names = []
|
@@ -10,7 +10,9 @@ class Trepan::Command::DisassembleCommand < Trepan::Command
|
|
10
10
|
|
11
11
|
unless defined?(HELP)
|
12
12
|
NAME = File.basename(__FILE__, '.rb')
|
13
|
-
|
13
|
+
ALIASES = %w(disas disassem) # Note we have disable
|
14
|
+
CATEGORY = 'data'
|
15
|
+
HELP = <<-HELP
|
14
16
|
#{NAME} [thing] [full]
|
15
17
|
|
16
18
|
With no argument, disassemble the current frame. With a method,
|
@@ -23,24 +25,21 @@ instruction sequence might have. If 'full' is given, all instruction
|
|
23
25
|
sequences are include.
|
24
26
|
|
25
27
|
Examples:
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
disas require_relative # disassemble method 'require_relative'
|
28
|
+
#{NAME}
|
29
|
+
#{NAME} . # Same as above
|
30
|
+
#{NAME} . full # At least the instruction sequence above but maybe more
|
31
|
+
#{NAME} require_relative # disassemble method 'require_relative'
|
31
32
|
HELP
|
32
33
|
|
33
|
-
ALIASES = %w(disas disassem) # Note we have disable
|
34
|
-
CATEGORY = 'data'
|
35
34
|
NEED_STACK = true
|
36
35
|
SHORT_HELP = 'Disassemble Ruby VM instructions'
|
37
36
|
end
|
38
37
|
|
39
38
|
# FIXME: put in processor/data.rb?
|
40
39
|
|
41
|
-
def marked_disassemble(
|
42
|
-
iseqs = include_children ?
|
43
|
-
|
40
|
+
def marked_disassemble(iseq_param, include_children)
|
41
|
+
iseqs = include_children ? iseq_param.child_iseqs : [iseq_param]
|
42
|
+
iseqs.each do |iseq|
|
44
43
|
ary = mark_disassembly(iseq.disasm_nochildren,
|
45
44
|
@proc.frame.iseq.equal?(iseq),
|
46
45
|
@proc.frame.pc_offset,
|
@@ -65,7 +65,7 @@ If no sub-options are given #{DEFAULT_FILE_ARGS.join(' ')} are assumed.
|
|
65
65
|
elsif !(matches = find_scripts(filename)).empty?
|
66
66
|
if (matches.size > 1)
|
67
67
|
msg("Multiple files found:")
|
68
|
-
matches.each { |
|
68
|
+
matches.each { |match_file| msg "\t%s" % match_file }
|
69
69
|
return
|
70
70
|
else
|
71
71
|
msg('File "%s" just now cached.' % filename)
|
@@ -135,7 +135,7 @@ If no sub-options are given #{DEFAULT_FILE_ARGS.join(' ')} are assumed.
|
|
135
135
|
end
|
136
136
|
|
137
137
|
if __FILE__ == $0
|
138
|
-
if
|
138
|
+
if !(ARGV.size == 1 && ARGV[0] == 'noload')
|
139
139
|
ISEQS__ = {}
|
140
140
|
SCRIPT_ISEQS__ = {}
|
141
141
|
ARGV[0..-1] = ['noload']
|
data/processor/command/irb.rb
CHANGED
data/processor/command/kill.rb
CHANGED
@@ -31,13 +31,13 @@ Examples:
|
|
31
31
|
end
|
32
32
|
|
33
33
|
# This method runs the command
|
34
|
-
def run(args)
|
34
|
+
def run(args) # :nodoc
|
35
35
|
if args.size > 1
|
36
36
|
sig = Integer(args[1]) rescue args[1]
|
37
37
|
unless sig.is_a?(Integer) || Signal.list.member?(sig.upcase)
|
38
38
|
errmsg("Signal name '#{sig}' is not a signal I know about.\n")
|
39
39
|
return false
|
40
|
-
|
40
|
+
end
|
41
41
|
# FIXME: reinstate
|
42
42
|
# if 'KILL' == sig || Signal['KILL'] == sig
|
43
43
|
# @proc.intf.finalize
|
data/processor/command/list.rb
CHANGED
@@ -257,13 +257,13 @@ disabled.
|
|
257
257
|
@proc.line_no = lineno
|
258
258
|
end
|
259
259
|
rescue => e
|
260
|
-
errmsg e if settings[:debugexcept]
|
260
|
+
errmsg e.to_s if settings[:debugexcept]
|
261
261
|
end
|
262
262
|
end
|
263
263
|
end
|
264
264
|
|
265
265
|
if __FILE__ == $0
|
266
|
-
if
|
266
|
+
if !(ARGV.size == 1 && ARGV[0] == 'noload')
|
267
267
|
ISEQS__ = {}
|
268
268
|
SCRIPT_ISEQS__ = {}
|
269
269
|
ARGV[0..-1] = ['noload']
|
@@ -275,8 +275,8 @@ if __FILE__ == $0
|
|
275
275
|
dbgr, cmd = MockDebugger::setup
|
276
276
|
cmd.proc.send('frame_initialize')
|
277
277
|
LineCache::cache(__FILE__)
|
278
|
-
cmd.run([
|
279
|
-
cmd.run([
|
278
|
+
cmd.run([cmd.name])
|
279
|
+
cmd.run([cmd.name, __FILE__ + ':10'])
|
280
280
|
|
281
281
|
def run_cmd(cmd, args)
|
282
282
|
seps = '--' * 10
|
@@ -19,7 +19,7 @@ class Trepan::Command::NoCacheCommand < Trepan::Command
|
|
19
19
|
if @proc.frame.iseq
|
20
20
|
puts @proc.frame.iseq.disassemble
|
21
21
|
count = @proc.frame.iseq.killcache
|
22
|
-
msg
|
22
|
+
msg "%d locations removed" % count
|
23
23
|
# puts @proc.frame.iseq.disassemble
|
24
24
|
end
|
25
25
|
end
|
data/processor/main.rb
CHANGED
@@ -113,7 +113,7 @@ class Trepan
|
|
113
113
|
|
114
114
|
# Run initialization routines for each of the "submodule"s.
|
115
115
|
# load_cmds has to come first.
|
116
|
-
%w(load_cmds breakpoint display eventbuf frame running validate
|
116
|
+
%w(load_cmds breakpoint display eventbuf frame location running validate
|
117
117
|
).each do |submod|
|
118
118
|
self.send("#{submod}_initialize")
|
119
119
|
end
|
data/processor/running.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
# ********************************************************
|
2
|
+
# This tests the enable command.
|
3
|
+
# ********************************************************
|
4
|
+
set basename off
|
5
|
+
break gcd
|
6
|
+
# Should have a breakpoint 1
|
7
|
+
enable 1
|
8
|
+
# An invalid enable command
|
9
|
+
enable foo
|
10
|
+
quit
|
11
|
+
|
12
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
gcd.rb:4
|
2
|
+
def gcd(a, b)
|
3
|
+
# # ********************************************************
|
4
|
+
# # This tests the enable command.
|
5
|
+
# # ********************************************************
|
6
|
+
# set debuggertesting on
|
7
|
+
Currently testing the debugger is on.
|
8
|
+
# set callstyle last
|
9
|
+
Frame call-display style is last.
|
10
|
+
# set autoeval off
|
11
|
+
autoeval is off.
|
12
|
+
# break Object.gcd
|
13
|
+
Breakpoint 1 at Object::gcd
|
14
|
+
# # Should have a breakpoint 1
|
15
|
+
# enable br 1
|
16
|
+
# # Get help on enable
|
17
|
+
# help enable
|
18
|
+
Enable some things.
|
19
|
+
This is used to cancel the effect of the "disable" command.
|
20
|
+
--
|
21
|
+
List of enable subcommands:
|
22
|
+
--
|
23
|
+
enable breakpoints -- Enable specified breakpoints
|
24
|
+
enable display -- Enable some expressions to be displayed when program stops
|
25
|
+
# # Get help on just enable break
|
26
|
+
# help enable break
|
27
|
+
Enable specified breakpoints.
|
28
|
+
Give breakpoint numbers (separated by spaces) as arguments.
|
29
|
+
This is used to cancel the effect of the "disable" command.
|
30
|
+
# # Plain enable should work
|
31
|
+
# enable
|
32
|
+
*** "enable" must be followed "display", "breakpoints" or breakpoint numbers.
|
33
|
+
# # An invalid enable command
|
34
|
+
# enable foo
|
35
|
+
Enable breakpoints argument 'foo' needs to be a number.
|
36
|
+
# quit
|
@@ -0,0 +1 @@
|
|
1
|
+
Ha!
|
data/test/data/quit.cmd
ADDED
File without changes
|
data/test/example/null.rb
CHANGED
data/test/integration/helper.rb
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
require 'diff/lcs'
|
2
2
|
require 'fileutils'
|
3
|
+
require_relative '../../app/run' # for ruby_path
|
3
4
|
|
4
|
-
|
5
|
+
DEFAULT_DEBUGGER_OPTS = {
|
6
|
+
:args => '',
|
7
|
+
:dbgr => '',
|
8
|
+
:outfile => nil,
|
9
|
+
:short_cmd => nil,
|
10
|
+
:short_right => nil,
|
11
|
+
:do_diff => true,
|
12
|
+
}
|
5
13
|
|
14
|
+
def run_debugger(testname, ruby_file, opts={})
|
15
|
+
opts = DEFAULT_DEBUGGER_OPTS.merge(opts)
|
6
16
|
srcdir = File.dirname(__FILE__)
|
7
17
|
datadir = File.join(srcdir, %w(.. data))
|
8
18
|
progdir = File.join(srcdir, %w(.. example))
|
@@ -11,40 +21,49 @@ def run_debugger(testname, ruby_file, dbgr_opts='', args='', outfile=nil)
|
|
11
21
|
dbgr_short = File.join(%w(bin trepan))
|
12
22
|
dbgr_path = File.join(dbgr_dir, dbgr_short)
|
13
23
|
|
14
|
-
|
24
|
+
short_right = "#{opts[:short_right] || testname}.right"
|
25
|
+
rightfile = File.join(datadir, short_right)
|
15
26
|
|
16
|
-
|
17
|
-
|
27
|
+
short_cmd = "#{opts[:short_cmd] || testname}.cmd"
|
28
|
+
cmdfile = File.join(datadir, short_cmd)
|
29
|
+
outfile = opts[:outfile] ||
|
30
|
+
File.join(srcdir, "#{testname}.out")
|
18
31
|
programfile = ruby_file ? File.join(progdir, ruby_file) : ''
|
19
32
|
|
20
33
|
FileUtils.rm(outfile) if File.exist?(outfile)
|
21
34
|
|
22
|
-
cmd = "%s --nx --command %s %s '%s' %s >%s" %
|
23
|
-
[dbgr_path, cmdfile,
|
35
|
+
cmd = "%s %s --nx --command %s %s '%s' %s >%s" %
|
36
|
+
[Trepanning::ruby_path, dbgr_path, cmdfile, opts[:dbgr],
|
37
|
+
programfile, opts[:args], outfile]
|
24
38
|
|
25
39
|
system(cmd)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
return false unless 0 == $?.exitstatus
|
41
|
+
if opts[:do_diff]
|
42
|
+
from_file = rightfile
|
43
|
+
# fromdate = time.ctime(os.stat(fromfile).st_mtime)
|
44
|
+
from_lines = File.open(from_file).readlines()
|
45
|
+
to_file = outfile
|
46
|
+
# todate = time.ctime(os.stat(tofile).st_mtime)
|
47
|
+
to_lines = File.open(to_file).readlines()
|
48
|
+
|
49
|
+
# Seems to be a bug in LCS in that it will return a diff even if two
|
50
|
+
# files are the same.
|
51
|
+
return true if from_lines == to_lines
|
52
|
+
|
53
|
+
sdiffs = Diff::LCS.sdiff(from_lines, to_lines)
|
54
|
+
|
55
|
+
if sdiffs.empty?
|
56
|
+
FileUtils.rm(outfile)
|
57
|
+
else
|
58
|
+
puts cmd
|
59
|
+
sdiffs.each do |diff|
|
60
|
+
p diff
|
61
|
+
end
|
45
62
|
end
|
63
|
+
return sdiffs.empty?
|
64
|
+
else
|
65
|
+
return true # We already tested for false above
|
46
66
|
end
|
47
|
-
return sdiffs.empty?
|
48
67
|
end
|
49
68
|
|
50
69
|
if __FILE__ == $0
|