trepanning 0.0.8 → 0.0.9
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 +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
|