rb8-trepanning 0.1.3
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/.gitignore +3 -0
- data/CHANGES +34 -0
- data/ChangeLog +875 -0
- data/README.textile +59 -0
- data/Rakefile +215 -0
- data/app/.gitignore +1 -0
- data/app/cmd_parse.kpeg +241 -0
- data/app/cmd_parse.rb +212 -0
- data/app/cmd_parser.rb +1948 -0
- data/app/complete.rb +79 -0
- data/app/default.rb +90 -0
- data/app/display.rb +148 -0
- data/app/eventbuffer.rb +147 -0
- data/app/frame.rb +166 -0
- data/app/irb.rb +114 -0
- data/app/options.rb +200 -0
- data/app/run.rb +74 -0
- data/app/util.rb +65 -0
- data/bin/.gitignore +1 -0
- data/bin/trepan8 +115 -0
- data/data/.gitignore +1 -0
- data/data/irbrc +41 -0
- data/interface/.gitignore +1 -0
- data/interface/base_intf.rb +109 -0
- data/interface/client.rb +82 -0
- data/interface/comcodes.rb +20 -0
- data/interface/script.rb +110 -0
- data/interface/server.rb +147 -0
- data/interface/user.rb +165 -0
- data/io/base_io.rb +148 -0
- data/io/input.rb +158 -0
- data/io/null_output.rb +46 -0
- data/io/string_array.rb +156 -0
- data/io/tcpclient.rb +129 -0
- data/io/tcpfns.rb +33 -0
- data/io/tcpserver.rb +141 -0
- data/lib/debugger.rb +8 -0
- data/lib/trepanning.rb +283 -0
- data/processor/.gitignore +1 -0
- data/processor/command-ruby-debug/breakpoints.rb +155 -0
- data/processor/command-ruby-debug/catchpoint.rb +55 -0
- data/processor/command-ruby-debug/condition.rb +49 -0
- data/processor/command-ruby-debug/control.rb +31 -0
- data/processor/command-ruby-debug/display.rb +120 -0
- data/processor/command-ruby-debug/enable.rb +202 -0
- data/processor/command-ruby-debug/frame.rb +199 -0
- data/processor/command-ruby-debug/help.rb +63 -0
- data/processor/command-ruby-debug/info.rb +359 -0
- data/processor/command-ruby-debug/method.rb +84 -0
- data/processor/command-ruby-debug/reload.rb +40 -0
- data/processor/command-ruby-debug/save.rb +90 -0
- data/processor/command-ruby-debug/set.rb +237 -0
- data/processor/command-ruby-debug/show.rb +251 -0
- data/processor/command-ruby-debug/source.rb +36 -0
- data/processor/command-ruby-debug/threads.rb +189 -0
- data/processor/command-ruby-debug/trace.rb +57 -0
- data/processor/command-ruby-debug/variables.rb +199 -0
- data/processor/command.rb +270 -0
- data/processor/command/.gitignore +1 -0
- data/processor/command/alias.rb +54 -0
- data/processor/command/backtrace.rb +123 -0
- data/processor/command/base/cmd.rb +177 -0
- data/processor/command/base/subcmd.rb +230 -0
- data/processor/command/base/submgr.rb +188 -0
- data/processor/command/base/subsubcmd.rb +128 -0
- data/processor/command/base/subsubmgr.rb +199 -0
- data/processor/command/break.rb +114 -0
- data/processor/command/catch.rb +71 -0
- data/processor/command/complete.rb +39 -0
- data/processor/command/continue.rb +57 -0
- data/processor/command/directory.rb +50 -0
- data/processor/command/disable.rb +85 -0
- data/processor/command/display.rb +78 -0
- data/processor/command/down.rb +54 -0
- data/processor/command/edit.rb +79 -0
- data/processor/command/enable.rb +48 -0
- data/processor/command/eval.rb +90 -0
- data/processor/command/exit.rb +66 -0
- data/processor/command/finish.rb +59 -0
- data/processor/command/frame.rb +97 -0
- data/processor/command/help.rb +230 -0
- data/processor/command/help/.gitignore +1 -0
- data/processor/command/help/README +10 -0
- data/processor/command/help/command.txt +58 -0
- data/processor/command/help/examples.txt +16 -0
- data/processor/command/help/filename.txt +40 -0
- data/processor/command/help/location.txt +37 -0
- data/processor/command/help/suffixes.txt +17 -0
- data/processor/command/info.rb +28 -0
- data/processor/command/info_subcmd/.gitignore +1 -0
- data/processor/command/info_subcmd/args.rb +39 -0
- data/processor/command/info_subcmd/breakpoints.rb +80 -0
- data/processor/command/info_subcmd/catch.rb +36 -0
- data/processor/command/info_subcmd/files.rb +39 -0
- data/processor/command/info_subcmd/globals.rb +64 -0
- data/processor/command/info_subcmd/line.rb +30 -0
- data/processor/command/info_subcmd/locals.rb +69 -0
- data/processor/command/info_subcmd/macro.rb +62 -0
- data/processor/command/info_subcmd/program.rb +51 -0
- data/processor/command/info_subcmd/ruby.rb +57 -0
- data/processor/command/info_subcmd/source.rb +74 -0
- data/processor/command/info_subcmd/stack.rb +25 -0
- data/processor/command/info_subcmd/threads.rb +75 -0
- data/processor/command/kill.rb +78 -0
- data/processor/command/list.rb +117 -0
- data/processor/command/macro.rb +68 -0
- data/processor/command/next.rb +79 -0
- data/processor/command/parsetree.rb +56 -0
- data/processor/command/pp.rb +40 -0
- data/processor/command/pr.rb +37 -0
- data/processor/command/ps.rb +40 -0
- data/processor/command/restart.rb +86 -0
- data/processor/command/save.rb +58 -0
- data/processor/command/set.rb +47 -0
- data/processor/command/set_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/abbrev.rb +25 -0
- data/processor/command/set_subcmd/auto.rb +27 -0
- data/processor/command/set_subcmd/auto_subcmd/.gitignore +1 -0
- data/processor/command/set_subcmd/auto_subcmd/eval.rb +53 -0
- data/processor/command/set_subcmd/auto_subcmd/irb.rb +33 -0
- data/processor/command/set_subcmd/auto_subcmd/list.rb +33 -0
- data/processor/command/set_subcmd/basename.rb +25 -0
- data/processor/command/set_subcmd/callstyle.rb +46 -0
- data/processor/command/set_subcmd/confirm.rb +24 -0
- data/processor/command/set_subcmd/debug.rb +47 -0
- data/processor/command/set_subcmd/different.rb +61 -0
- data/processor/command/set_subcmd/highlight.rb +43 -0
- data/processor/command/set_subcmd/max.rb +26 -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 +76 -0
- data/processor/command/set_subcmd/max_subcmd/width.rb +49 -0
- data/processor/command/set_subcmd/reload.rb +42 -0
- data/processor/command/set_subcmd/timer.rb +58 -0
- data/processor/command/set_subcmd/trace.rb +37 -0
- data/processor/command/set_subcmd/trace_subcmd/buffer.rb +42 -0
- data/processor/command/set_subcmd/trace_subcmd/print.rb +41 -0
- data/processor/command/shell.rb +139 -0
- data/processor/command/show.rb +39 -0
- data/processor/command/show_subcmd/.gitignore +1 -0
- data/processor/command/show_subcmd/abbrev.rb +20 -0
- data/processor/command/show_subcmd/alias.rb +46 -0
- data/processor/command/show_subcmd/args.rb +34 -0
- data/processor/command/show_subcmd/auto.rb +28 -0
- data/processor/command/show_subcmd/auto_subcmd/eval.rb +27 -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 +20 -0
- data/processor/command/show_subcmd/callstyle.rb +22 -0
- data/processor/command/show_subcmd/confirm.rb +18 -0
- data/processor/command/show_subcmd/debug.rb +26 -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 +26 -0
- data/processor/command/show_subcmd/directories.rb +22 -0
- data/processor/command/show_subcmd/highlight.rb +24 -0
- data/processor/command/show_subcmd/max.rb +27 -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/reload.rb +18 -0
- data/processor/command/show_subcmd/timer.rb +18 -0
- data/processor/command/show_subcmd/trace.rb +29 -0
- data/processor/command/show_subcmd/trace_subcmd/buffer.rb +65 -0
- data/processor/command/show_subcmd/trace_subcmd/print.rb +23 -0
- data/processor/command/show_subcmd/version.rb +23 -0
- data/processor/command/source.rb +134 -0
- data/processor/command/step.rb +81 -0
- data/processor/command/tbreak.rb +19 -0
- data/processor/command/unalias.rb +44 -0
- data/processor/command/undisplay.rb +59 -0
- data/processor/command/up.rb +72 -0
- data/processor/default.rb +56 -0
- data/processor/display.rb +17 -0
- data/processor/eval.rb +113 -0
- data/processor/eventbuf.rb +105 -0
- data/processor/frame.rb +172 -0
- data/processor/help.rb +92 -0
- data/processor/helper.rb +76 -0
- data/processor/hook.rb +134 -0
- data/processor/load_cmds.rb +258 -0
- data/processor/location.rb +174 -0
- data/processor/main.rb +455 -0
- data/processor/mock.rb +136 -0
- data/processor/msg.rb +61 -0
- data/processor/processor.rb +674 -0
- data/processor/running.rb +168 -0
- data/processor/stepping.rb +18 -0
- data/processor/subcmd.rb +161 -0
- data/processor/validate.rb +355 -0
- data/processor/virtual.rb +34 -0
- data/test/data/.gitignore +1 -0
- data/test/data/break_bad.cmd +19 -0
- data/test/data/break_bad.right +29 -0
- data/test/data/break_loop_bug.cmd +5 -0
- data/test/data/break_loop_bug.right +15 -0
- data/test/data/dollar-0.right +2 -0
- data/test/data/dollar-0a.right +2 -0
- data/test/data/dollar-0b.right +2 -0
- data/test/data/edit.cmd +14 -0
- data/test/data/edit.right +24 -0
- data/test/data/file-with-space.cmd +6 -0
- data/test/data/file-with-space.right +4 -0
- data/test/data/printvar.cmd +17 -0
- data/test/data/printvar.right +31 -0
- data/test/data/raise.cmd +11 -0
- data/test/data/raise.right +19 -0
- data/test/data/source.cmd +5 -0
- data/test/data/source.right +18 -0
- data/test/data/stepping-1.9.right +50 -0
- data/test/data/stepping.cmd +21 -0
- data/test/data/stepping.right +48 -0
- data/test/data/trepan8-save.1 +6 -0
- data/test/example/bp_loop_issue.rb +3 -0
- data/test/example/break-bug.rb +7 -0
- data/test/example/brkpt-class-bug.rb +8 -0
- data/test/example/classes.rb +11 -0
- data/test/example/dollar-0.rb +5 -0
- data/test/example/except-bug1.rb +4 -0
- data/test/example/except-bug2.rb +7 -0
- data/test/example/file with space.rb +1 -0
- data/test/example/gcd.rb +18 -0
- data/test/example/info-var-bug.rb +47 -0
- data/test/example/info-var-bug2.rb +2 -0
- data/test/example/null.rb +1 -0
- data/test/example/pm-bug.rb +3 -0
- data/test/example/pm.rb +11 -0
- data/test/example/raise.rb +3 -0
- data/test/integration/.gitignore +4 -0
- data/test/integration/config.yaml +8 -0
- data/test/integration/helper.rb +154 -0
- data/test/integration/test-break_bad.rb +26 -0
- data/test/integration/test-dollar-0.rb +31 -0
- data/test/integration/test-edit.rb +17 -0
- data/test/integration/test-file-with-space.rb +26 -0
- data/test/integration/test-printvar.rb +17 -0
- data/test/integration/test-raise.rb +21 -0
- data/test/integration/test-source.rb +16 -0
- data/test/integration/test-stepping.rb +24 -0
- data/test/unit/.gitignore +1 -0
- data/test/unit/cmd-helper.rb +52 -0
- data/test/unit/mock-helper.rb +12 -0
- data/test/unit/test-app-cmd_parse.rb +97 -0
- data/test/unit/test-app-cmd_parser.rb +23 -0
- data/test/unit/test-app-complete.rb +39 -0
- data/test/unit/test-app-frame.rb +32 -0
- data/test/unit/test-app-options.rb +92 -0
- data/test/unit/test-app-run.rb +14 -0
- data/test/unit/test-app-util.rb +44 -0
- data/test/unit/test-base-cmd.rb +45 -0
- data/test/unit/test-base-subcmd.rb +57 -0
- data/test/unit/test-base-submgr.rb +23 -0
- data/test/unit/test-base-subsubcmd.rb +17 -0
- data/test/unit/test-cmd-alias.rb +48 -0
- data/test/unit/test-cmd-exit.rb +27 -0
- data/test/unit/test-cmd-help.rb +104 -0
- data/test/unit/test-cmd-kill.rb +46 -0
- data/test/unit/test-cmd-source.rb +34 -0
- data/test/unit/test-completion.rb +42 -0
- data/test/unit/test-intf-user.rb +46 -0
- data/test/unit/test-io-input.rb +27 -0
- data/test/unit/test-io-tcp.rb +33 -0
- data/test/unit/test-io-tcpclient.rb +54 -0
- data/test/unit/test-io-tcpfns.rb +17 -0
- data/test/unit/test-io-tcpserver.rb +50 -0
- data/test/unit/test-proc-eval.rb +36 -0
- data/test/unit/test-proc-hook.rb +30 -0
- data/test/unit/test-proc-load_cmds.rb +50 -0
- data/test/unit/test-proc-location.rb +79 -0
- data/test/unit/test-subcmd-help.rb +44 -0
- data/trepan8.gemspec +52 -0
- metadata +391 -0
data/app/run.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
require 'rbconfig'
|
|
4
|
+
require 'rubygems'; require 'require_relative'
|
|
5
|
+
module Trepan
|
|
6
|
+
|
|
7
|
+
module_function # All functions below are easily publically accessible
|
|
8
|
+
|
|
9
|
+
# Given a Ruby interpreter and program we are to debug, debug it.
|
|
10
|
+
# The caller must ensure that ARGV is set up to remove any debugger
|
|
11
|
+
# arguments or things that the debugged program isn't supposed to
|
|
12
|
+
# see. FIXME: Should we make ARGV an explicit parameter?
|
|
13
|
+
|
|
14
|
+
def debug_program(ruby_path, options)
|
|
15
|
+
# Make sure Ruby script syntax checks okay.
|
|
16
|
+
# Otherwise we get a load message that looks like trepan8 has
|
|
17
|
+
# a problem.
|
|
18
|
+
output = `#{ruby_path} -c #{Trepan::PROG_SCRIPT.inspect} 2>&1`
|
|
19
|
+
if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/
|
|
20
|
+
puts output
|
|
21
|
+
exit $?.exitstatus
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
%w(highlight basename).each do |opt|
|
|
25
|
+
opt = opt.to_sym
|
|
26
|
+
Debugger.handler.cmdproc.settings[opt] = options[opt]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Record where we are we can know if the call stack has been
|
|
30
|
+
# truncated or not.
|
|
31
|
+
Trepan.start_sentinal=caller(0)[1]
|
|
32
|
+
|
|
33
|
+
bt = Debugger.debug_load(Trepan::PROG_SCRIPT, options[:stop], false)
|
|
34
|
+
if bt
|
|
35
|
+
if options[:post_mortem]
|
|
36
|
+
Debugger.handle_post_mortem(bt)
|
|
37
|
+
else
|
|
38
|
+
print bt.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n"
|
|
39
|
+
print "Uncaught exception: #{bt}\n"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Do a shell-like path lookup for prog_script and return the results.
|
|
45
|
+
# If we can't find anything return prog_script.
|
|
46
|
+
def whence_file(prog_script)
|
|
47
|
+
if prog_script.index(File::SEPARATOR)
|
|
48
|
+
# Don't search since this name has path separator components
|
|
49
|
+
return prog_script
|
|
50
|
+
end
|
|
51
|
+
for dirname in ENV['PATH'].split(File::PATH_SEPARATOR) do
|
|
52
|
+
prog_script_try = File.join(dirname, prog_script)
|
|
53
|
+
return prog_script_try if File.readable?(prog_script_try)
|
|
54
|
+
end
|
|
55
|
+
# Failure
|
|
56
|
+
return prog_script
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Path name of Ruby interpreter we were invoked with. Is part of
|
|
61
|
+
# 1.9 but not necessarily 1.8.
|
|
62
|
+
def RbConfig.ruby
|
|
63
|
+
File.join(RbConfig::CONFIG['bindir'],
|
|
64
|
+
RbConfig::CONFIG['RUBY_INSTALL_NAME'] +
|
|
65
|
+
RbConfig::CONFIG['EXEEXT'])
|
|
66
|
+
end unless defined? RbConfig.ruby
|
|
67
|
+
|
|
68
|
+
if __FILE__ == $0
|
|
69
|
+
# Demo it.
|
|
70
|
+
include Trepan
|
|
71
|
+
puts whence_file('irb')
|
|
72
|
+
puts whence_file('probably-does-not-exist')
|
|
73
|
+
puts RbConfig.ruby
|
|
74
|
+
end
|
data/app/util.rb
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
2
|
+
|
|
3
|
+
module Trepan
|
|
4
|
+
module Util
|
|
5
|
+
|
|
6
|
+
module_function
|
|
7
|
+
def safe_repr(str, max, elipsis='... ')
|
|
8
|
+
if str.is_a?(String) && max > 0 && str.size > max && !str.index("\n")
|
|
9
|
+
"%s%s%s" % [ str[0...max/2], elipsis, str[str.size-max/2..str.size]]
|
|
10
|
+
else
|
|
11
|
+
str
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# name is String and list is an Array of String.
|
|
16
|
+
# If name is a unique leading prefix of one of the entries of list,
|
|
17
|
+
# then return that. Otherwise return name.
|
|
18
|
+
def uniq_abbrev(list, name)
|
|
19
|
+
candidates = list.select do |try_name|
|
|
20
|
+
try_name.start_with?(name)
|
|
21
|
+
end
|
|
22
|
+
candidates.size == 1 ? candidates.first : name
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# extract the "expression" part of a line of source code.
|
|
26
|
+
#
|
|
27
|
+
def extract_expression(text)
|
|
28
|
+
if text =~ /^\s*(?:if|elsif|unless)\s+/
|
|
29
|
+
text.gsub!(/^\s*(?:if|elsif|unless)\s+/,'')
|
|
30
|
+
text.gsub!(/\s+then\s*$/, '')
|
|
31
|
+
elsif text =~ /^\s*(?:until|while)\s+/
|
|
32
|
+
text.gsub!(/^\s*(?:until|while)\s+/,'')
|
|
33
|
+
text.gsub!(/\s+do\s*$/, '')
|
|
34
|
+
elsif text =~ /^\s*return\s+/
|
|
35
|
+
# EXPRESION in: return EXPRESSION
|
|
36
|
+
text.gsub!(/^\s*return\s+/,'')
|
|
37
|
+
elsif text =~ /^\s*case\s+/
|
|
38
|
+
# EXPRESSION in: case EXPESSION
|
|
39
|
+
text.gsub!(/^\s*case\s*/,'')
|
|
40
|
+
elsif text =~ /^\s*def\s*.*\(.+\)/
|
|
41
|
+
text.gsub!(/^\s*def\s*.*\((.*)\)/,'[\1]')
|
|
42
|
+
elsif text =~ /^\s*[A-Za-z_][A-Za-z0-9_\[\]]*\s*=[^=>]/
|
|
43
|
+
# RHS of an assignment statement.
|
|
44
|
+
text.gsub!(/^\s*[A-Za-z_][A-Za-z0-9_\[\]]*\s*=/,'')
|
|
45
|
+
end
|
|
46
|
+
return text
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if __FILE__ == $0
|
|
52
|
+
include Trepan::Util
|
|
53
|
+
string = 'The time has come to talk of many things.'
|
|
54
|
+
puts safe_repr(string, 50)
|
|
55
|
+
puts safe_repr(string, 17)
|
|
56
|
+
puts safe_repr(string.inspect, 17)
|
|
57
|
+
puts safe_repr(string.inspect, 17, '')
|
|
58
|
+
## puts "main script in above is #{locs.size() - 1 - find_main_script(locs)}"
|
|
59
|
+
|
|
60
|
+
list = %w(disassemble disable distance up)
|
|
61
|
+
p list
|
|
62
|
+
%w(dis disa u upper foo).each do |name|
|
|
63
|
+
puts "uniq_abbrev of #{name} is #{uniq_abbrev(list, name)}"
|
|
64
|
+
end
|
|
65
|
+
end
|
data/bin/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*~
|
data/bin/trepan8
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
require 'rubygems'
|
|
5
|
+
require 'ruby-debug-base'
|
|
6
|
+
require 'optparse'
|
|
7
|
+
require 'require_relative'
|
|
8
|
+
require_relative '../app/run'
|
|
9
|
+
require_relative '../app/options'
|
|
10
|
+
require_relative '../interface/user'
|
|
11
|
+
require_relative '../lib/trepanning'
|
|
12
|
+
|
|
13
|
+
begin
|
|
14
|
+
eval(File.read(Trepan::CMD_INITFILE)) if File.exist?(Trepan::CMD_INITFILE)
|
|
15
|
+
rescue
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
options = Trepan.copy_default_options
|
|
19
|
+
opts = Trepan.setup_options(options)
|
|
20
|
+
|
|
21
|
+
begin
|
|
22
|
+
if not defined? Trepan::ARGV
|
|
23
|
+
Trepan::ARGV = ARGV.clone
|
|
24
|
+
end
|
|
25
|
+
trepan8_path = File.expand_path($0)
|
|
26
|
+
if RUBY_PLATFORM =~ /mswin/
|
|
27
|
+
trepan8_path += '.cmd' unless trepan8_path =~ /\.cmd$/i
|
|
28
|
+
end
|
|
29
|
+
Trepan::PROG_UNRESOLVED_SCRIPT = trepan8_path
|
|
30
|
+
Trepan::TREPAN8_FILE = __FILE__
|
|
31
|
+
Trepan::INITIAL_DIR = Dir.pwd
|
|
32
|
+
opts.parse! ARGV
|
|
33
|
+
rescue StandardError => e
|
|
34
|
+
puts opts
|
|
35
|
+
puts
|
|
36
|
+
puts e.message
|
|
37
|
+
exit(-1)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
if options[:client]
|
|
41
|
+
Debugger.start_client(options[:host], options[:port])
|
|
42
|
+
else
|
|
43
|
+
if ARGV.empty?
|
|
44
|
+
exit if $VERBOSE and not options[:verbose_long]
|
|
45
|
+
puts opts
|
|
46
|
+
puts
|
|
47
|
+
puts 'Must specify a script to run'
|
|
48
|
+
exit(-1)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# save script name
|
|
52
|
+
prog_script = ARGV.shift
|
|
53
|
+
prog_script = Trepan::whence_file(prog_script) unless
|
|
54
|
+
File.exist?(prog_script)
|
|
55
|
+
Trepan::PROG_SCRIPT = File.expand_path prog_script
|
|
56
|
+
|
|
57
|
+
# install interruption handler
|
|
58
|
+
trap('INT') { Debugger.interrupt_last }
|
|
59
|
+
|
|
60
|
+
# set options
|
|
61
|
+
Trepan.wait_connection = options[:wait]
|
|
62
|
+
Debugger.keep_frame_binding = options[:frame_bind]
|
|
63
|
+
|
|
64
|
+
if options[:server]
|
|
65
|
+
# start remote mode
|
|
66
|
+
Debugger.start_remote(options[:host], [options[:port], options[:cport]],
|
|
67
|
+
options[:post_mortem]) do
|
|
68
|
+
# load initrc script
|
|
69
|
+
Trepan.add_startup_files unless options[:nx]
|
|
70
|
+
end
|
|
71
|
+
debug_program(RbConfig.ruby, options)
|
|
72
|
+
else
|
|
73
|
+
# Set up trace hook for debugger
|
|
74
|
+
Trepan.start
|
|
75
|
+
# start control thread
|
|
76
|
+
Trepan.start_control(options[:host], options[:cport]) if options[:control]
|
|
77
|
+
|
|
78
|
+
# load initrc script (e.g. .trepan8rc)
|
|
79
|
+
Trepan.add_startup_files unless options[:nx]
|
|
80
|
+
|
|
81
|
+
# run startup script if specified
|
|
82
|
+
Trepan.add_command_file(options[:script]) if options[:script]
|
|
83
|
+
|
|
84
|
+
# activate post-mortem
|
|
85
|
+
Trepan.post_mortem if options[:post_mortem]
|
|
86
|
+
options[:stop] = false if options[:tracing]
|
|
87
|
+
Debugger.tracing = options[:tracing]
|
|
88
|
+
|
|
89
|
+
if !options[:quit]
|
|
90
|
+
if Debugger.started?
|
|
91
|
+
until Debugger.stop do end
|
|
92
|
+
end
|
|
93
|
+
begin
|
|
94
|
+
debug_program(RbConfig.ruby, options)
|
|
95
|
+
rescue SyntaxError
|
|
96
|
+
puts $!.backtrace.map{|l| "\t#{l}"}.join("\n")
|
|
97
|
+
puts "Uncaught Syntax Error\n"
|
|
98
|
+
rescue
|
|
99
|
+
print $!.backtrace.map{|l| "\t#{l}"}.join("\n"), "\n"
|
|
100
|
+
print "Uncaught exception: #{$!}\n"
|
|
101
|
+
end
|
|
102
|
+
print "The program finished.\n" unless
|
|
103
|
+
Debugger.annotate.to_i > 1 # annotate has its own way
|
|
104
|
+
## interface = Debugger::LocalInterface.new
|
|
105
|
+
interface = Trepan::UserInterface.new
|
|
106
|
+
|
|
107
|
+
# Not sure if ControlCommandProcessor is really the right
|
|
108
|
+
# thing to use. CommandProcessor requires a state.
|
|
109
|
+
processor = Debugger::ControlCommandProcessor.new(interface)
|
|
110
|
+
processor.process_commands
|
|
111
|
+
else
|
|
112
|
+
Trepan::debug_program(RbConfig.ruby, options)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
data/data/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*~
|
data/data/irbrc
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- Ruby -*-
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
# We use this as the default startup file for irb inside trepan
|
|
4
|
+
# Down the line we will have a way for folks to add/override this
|
|
5
|
+
# with their own file.
|
|
6
|
+
IRB.conf[:PROMPT_MODE] = :SIMPLE
|
|
7
|
+
IRB.conf[:PROMPT][:SIMPLE] =
|
|
8
|
+
{:PROMPT_C=>"trepan8 ?> ",
|
|
9
|
+
:PROMPT_I=>"trepan8 >> ",
|
|
10
|
+
:PROMPT_N=>"trepan8 >> ",
|
|
11
|
+
:PROMPT_S=>nil,
|
|
12
|
+
:RETURN=>"=> %s\n"}
|
|
13
|
+
|
|
14
|
+
# Using dbgr to issue a debugger statement inside irb:
|
|
15
|
+
# dbgr %w(info program)
|
|
16
|
+
# dbgr 'info program' # also works
|
|
17
|
+
# But...
|
|
18
|
+
# dbgr info program # wrong!
|
|
19
|
+
#
|
|
20
|
+
puts "You are in a trepan session. You should have access to program scope."
|
|
21
|
+
puts "'dbgr', 'step', 'ne', 'q', 'cont' commands have been added."
|
|
22
|
+
|
|
23
|
+
if defined?($trepan) && $trepan
|
|
24
|
+
puts 'You should have access to debugger state via global variable $trepan'
|
|
25
|
+
end
|
|
26
|
+
if defined?($trepan_frame) && $trepan_frame
|
|
27
|
+
puts 'You should have access to the program frame via global variable $trepan_frame'
|
|
28
|
+
end
|
|
29
|
+
if defined?($trepan_cmdproc) && $trepan_cmdproc
|
|
30
|
+
puts 'You should have access to the command processor via global variable $trepan_cmdproc'
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Monkeypatch to save the current IRB statement to be run.
|
|
34
|
+
class IRB::Context
|
|
35
|
+
alias_method :_trepan_original_evaluate, :evaluate
|
|
36
|
+
def evaluate(line, line_no)
|
|
37
|
+
$trepan_irb_statements = line
|
|
38
|
+
_trepan_original_evaluate(line, line_no)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/*~
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# A base class for a debugger interface.
|
|
5
|
+
|
|
6
|
+
module Trepan
|
|
7
|
+
|
|
8
|
+
unless defined?(NotImplementedMessage)
|
|
9
|
+
NotImplementedMessage = 'This method must be overriden in a subclass'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# A debugger interface handles the communication or interaction with between
|
|
13
|
+
# the program and the outside portion which could be
|
|
14
|
+
# - a user,
|
|
15
|
+
# - a front-end that talks to a user, or
|
|
16
|
+
# - another interface in another process or computer
|
|
17
|
+
class Interface
|
|
18
|
+
|
|
19
|
+
attr_accessor :interactive, :history_io, :history_save, :input, :output
|
|
20
|
+
|
|
21
|
+
unless defined?(YES)
|
|
22
|
+
YES = %w(y yes oui si yep ja)
|
|
23
|
+
NO = %w(n no non nope nein)
|
|
24
|
+
YES_OR_NO = YES + NO
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def initialize(inp=nil, out=nil, opts={})
|
|
28
|
+
@histfile = nil
|
|
29
|
+
@history_io = nil
|
|
30
|
+
@history_save = false
|
|
31
|
+
@histsize = nil
|
|
32
|
+
@input = inp || STDIN
|
|
33
|
+
@interactive = false
|
|
34
|
+
@opts = opts
|
|
35
|
+
@output = out || STDOUT
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Closes all input and/or output.
|
|
39
|
+
def close
|
|
40
|
+
@input.close unless !@input || @input.closed?
|
|
41
|
+
@output.close unless !@output || @output.closed?
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Called when a dangerous action is about to be done to make sure
|
|
45
|
+
# it's okay. `prompt' is printed; user response is returned.
|
|
46
|
+
def confirm(prompt, default=false)
|
|
47
|
+
raise RuntimeError, Trepan::NotImplementedMessage
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Common routine for reporting debugger error messages.
|
|
51
|
+
def errmsg(str, prefix='** ')
|
|
52
|
+
if str.is_a?(Array)
|
|
53
|
+
str.each{|s| errmsg(s)}
|
|
54
|
+
else
|
|
55
|
+
str.split("\n").each do |s|
|
|
56
|
+
msg("%s%s" % [prefix, s])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def finalize(last_wishes=nil)
|
|
62
|
+
if @output && !@output.closed?
|
|
63
|
+
msg "%sThat's all, folks..." %
|
|
64
|
+
(defined?(Trepan::PROGRAM) ? "#{Trepan::PROGRAM}: " : '')
|
|
65
|
+
end
|
|
66
|
+
close
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def input_eof?
|
|
70
|
+
@input.eof?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Return true if interface is interactive.
|
|
74
|
+
def interactive?
|
|
75
|
+
# Default false and making subclasses figure out how to determine
|
|
76
|
+
# interactiveness.
|
|
77
|
+
false
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# used to write to a debugger that is connected to this
|
|
81
|
+
# server; `str' written will have a newline added to it.
|
|
82
|
+
def msg(message)
|
|
83
|
+
if message.is_a?(Array)
|
|
84
|
+
message.each{|s| msg(s)}
|
|
85
|
+
else
|
|
86
|
+
message = message ? message.to_s + "\n" : ''
|
|
87
|
+
@output.write(message)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# used to write to a debugger that is connected to this
|
|
92
|
+
# server; `str' written will not have a newline added to it
|
|
93
|
+
def msg_nocr(msg)
|
|
94
|
+
@output.write(msg)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def read_command(prompt='')
|
|
98
|
+
line = readline(prompt)
|
|
99
|
+
# FIXME: Do something with history?
|
|
100
|
+
return line
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def readline(prompt='')
|
|
104
|
+
@output.flush
|
|
105
|
+
@output.write(prompt) if prompt and prompt.size > 0
|
|
106
|
+
@input.readline
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
data/interface/client.rb
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
|
|
3
|
+
|
|
4
|
+
# Interface for client (i.e. user to communication-device) interaction.
|
|
5
|
+
# The debugged program is at the other end of the communcation.
|
|
6
|
+
|
|
7
|
+
require 'rubygems'; require 'require_relative'
|
|
8
|
+
require_relative 'user'
|
|
9
|
+
require_relative '../io/tcpclient'
|
|
10
|
+
require_relative 'comcodes'
|
|
11
|
+
|
|
12
|
+
# Interface for a user which is attached to a debugged process via
|
|
13
|
+
# some sort of communication medium (e.g. socket, tty, FIFOs). This
|
|
14
|
+
# could be on the same computer in a different process or on a remote
|
|
15
|
+
# computer.
|
|
16
|
+
class Trepan::ClientInterface < Trepan::Interface
|
|
17
|
+
|
|
18
|
+
DEFAULT_INIT_CONNECTION_OPTS = {
|
|
19
|
+
:open => true,
|
|
20
|
+
:io => :tcp
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def initialize(inp=nil, out=nil, inout=nil, user_opts={},
|
|
24
|
+
connection_opts={})
|
|
25
|
+
|
|
26
|
+
@connection_opts = DEFAULT_INIT_CONNECTION_OPTS.merge(connection_opts)
|
|
27
|
+
|
|
28
|
+
@user = Trepan::UserInterface.new(inp, out, user_opts)
|
|
29
|
+
|
|
30
|
+
@inout =
|
|
31
|
+
if inout
|
|
32
|
+
inout
|
|
33
|
+
else
|
|
34
|
+
# @server_type = @connection_opts[:io]
|
|
35
|
+
# if 'FIFO' == self.server_type
|
|
36
|
+
# Mfifoclient.FIFOClient(opts=@connection_opts)
|
|
37
|
+
# elsif :tcp == self.server_type
|
|
38
|
+
Trepan::TCPDbgClient.new(@connection_opts)
|
|
39
|
+
# else
|
|
40
|
+
# errmsg("Expecting server type TCP or FIFO. Got: %s." %
|
|
41
|
+
# self.server_type)
|
|
42
|
+
# return
|
|
43
|
+
# end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def closed?
|
|
48
|
+
@inout.closed?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def confirm(prompt, default)
|
|
52
|
+
@user.confirm(prompt, default)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def read_command(prompt='')
|
|
56
|
+
@user.read_command(prompt)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Send a message back to the server (in contrast to the local user
|
|
60
|
+
# output channel).
|
|
61
|
+
def read_remote
|
|
62
|
+
coded_line = nil
|
|
63
|
+
until coded_line
|
|
64
|
+
coded_line = @inout.read_msg
|
|
65
|
+
end
|
|
66
|
+
control = coded_line[0..0]
|
|
67
|
+
remote_line = coded_line[1..-1]
|
|
68
|
+
[control, remote_line]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# Send a message back to the server (in contrast to the local user
|
|
72
|
+
# output channel).
|
|
73
|
+
def write_remote(code, msg)
|
|
74
|
+
# FIXME change into write_xxx
|
|
75
|
+
@inout.writeline(code + msg)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Demo
|
|
80
|
+
if __FILE__ == $0
|
|
81
|
+
intf = Trepan::ClientInterface.new
|
|
82
|
+
end
|