trepanning 0.1.4 → 0.1.6

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.
Files changed (79) hide show
  1. data/ChangeLog +188 -0
  2. data/Makefile +7 -0
  3. data/NEWS +9 -0
  4. data/README.textile +3 -3
  5. data/Rakefile +3 -3
  6. data/app/breakpoint.rb +1 -1
  7. data/app/brkptmgr.rb +1 -1
  8. data/app/client.rb +15 -4
  9. data/app/core.rb +4 -4
  10. data/app/default.rb +1 -0
  11. data/app/display.rb +1 -1
  12. data/app/frame.rb +38 -19
  13. data/app/options.rb +4 -1
  14. data/app/run.rb +12 -2
  15. data/bin/trepan +2 -1
  16. data/check-filter.rb +18 -0
  17. data/interface/client.rb +1 -1
  18. data/interface/comcodes.rb +9 -8
  19. data/interface/server.rb +38 -2
  20. data/interface/user.rb +2 -2
  21. data/io/input.rb +11 -3
  22. data/io/tcpclient.rb +0 -2
  23. data/io/tcpserver.rb +3 -2
  24. data/lib/trepanning.rb +8 -8
  25. data/processor.rb +4 -4
  26. data/processor/command/backtrace.rb +1 -1
  27. data/processor/command/base/subcmd.rb +4 -1
  28. data/processor/command/break.rb +1 -1
  29. data/processor/command/condition.rb +1 -1
  30. data/processor/command/debug.rb +19 -15
  31. data/processor/command/delete.rb +2 -1
  32. data/processor/command/disassemble.rb +2 -2
  33. data/processor/command/display.rb +1 -1
  34. data/processor/command/down.rb +1 -2
  35. data/processor/command/finish.rb +8 -4
  36. data/processor/command/frame.rb +1 -1
  37. data/processor/command/help.rb +1 -1
  38. data/processor/command/info_subcmd/breakpoints.rb +1 -1
  39. data/processor/command/info_subcmd/registers.rb +1 -1
  40. data/processor/command/info_subcmd/source.rb +1 -1
  41. data/processor/command/info_subcmd/thread.rb +2 -2
  42. data/processor/command/list.rb +1 -1
  43. data/processor/command/set_subcmd/auto_subcmd/eval.rb +10 -6
  44. data/processor/command/set_subcmd/auto_subcmd/irb.rb +2 -2
  45. data/processor/command/set_subcmd/auto_subcmd/list.rb +2 -2
  46. data/processor/command/set_subcmd/substitute_subcmd/eval.rb +1 -1
  47. data/processor/command/show_subcmd/abbrev.rb +2 -2
  48. data/processor/command/undisplay.rb +1 -1
  49. data/processor/command/up.rb +1 -2
  50. data/processor/eval.rb +9 -5
  51. data/processor/frame.rb +1 -1
  52. data/processor/list.rb +1 -1
  53. data/processor/location.rb +3 -2
  54. data/processor/mock.rb +3 -3
  55. data/processor/running.rb +1 -1
  56. data/processor/validate.rb +1 -1
  57. data/test/example/factorial.rb +10 -0
  58. data/test/example/gcd1.rb +1 -1
  59. data/test/functional/fn_helper.rb +1 -1
  60. data/test/functional/test-recursive-bt.rb +103 -0
  61. data/test/functional/test-remap.rb +50 -0
  62. data/test/integration/test-remote.rb +23 -0
  63. data/test/unit/test-app-brkpt.rb +1 -1
  64. data/test/unit/test-app-brkptmgr.rb +2 -2
  65. data/test/unit/test-app-display.rb +1 -1
  66. data/test/unit/test-app-frame.rb +3 -3
  67. data/test/unit/test-app-options.rb +1 -1
  68. data/test/unit/test-cmd-break.rb +2 -2
  69. data/test/unit/test-cmd-endisable.rb +1 -1
  70. data/test/unit/test-cmd-parse_list_cmd.rb +1 -1
  71. data/test/unit/test-cmd-quit.rb +1 -0
  72. data/test/unit/test-cmd-set-auto-eval.rb.try +19 -0
  73. data/test/unit/test-proc-eval.rb +1 -1
  74. data/test/unit/test-proc-frame.rb +2 -2
  75. data/test/unit/test-proc-list.rb +1 -1
  76. data/test/unit/test-proc-location.rb +1 -1
  77. data/test/unit/test-proc-validate.rb +3 -3
  78. data/trepanning.gemspec +5 -5
  79. metadata +101 -104
@@ -8,7 +8,7 @@ require 'optparse'
8
8
  class Trepan
9
9
  require_relative 'default'
10
10
 
11
- VERSION = '0.1.4'
11
+ VERSION = '0.1.6'
12
12
  PROGRAM = 'trepan'
13
13
 
14
14
  def self.show_version
@@ -89,6 +89,9 @@ EOB
89
89
  |num|
90
90
  options[:port] = num
91
91
  end
92
+ # opts.on('-m', '--post-mortem', 'Activate post-mortem mode') do
93
+ # options[:post_mortem] = true
94
+ # end
92
95
  opts.on('--[no-]readline',
93
96
  'Try [not] GNU Readline') do |v|
94
97
  options[:readline] = v
data/app/run.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  require 'rbconfig'
4
4
  module Trepanning
5
5
 
@@ -35,7 +35,7 @@ module Trepanning
35
35
 
36
36
  dbgr.debugger(:hide_stack=>true) do
37
37
  dbgr.core.processor.hidelevels[Thread.current] =
38
- RubyVM::ThreadFrame.current.stack_size + 1
38
+ RubyVM::Frame.current.stack_size + 1
39
39
  begin
40
40
  Kernel::load program_to_debug
41
41
  rescue Interrupt
@@ -46,6 +46,15 @@ module Trepanning
46
46
  # above.
47
47
  $0 = old_dollar_0
48
48
  untrace_var(:$0, dollar_0_tracker)
49
+ rescue
50
+ if dbgr.settings[:post_mortem]
51
+ frame = RubyVM::Frame.current.prev(0)
52
+ dbgr.core.step_count = 0 # Make event processor stop
53
+ dbgr.core.processor.settings[:debugstack] = 0 # Make event processor stop
54
+ dbgr.core.event_processor('post-mortem', frame, $!)
55
+ else
56
+ raise
57
+ end
49
58
  end
50
59
 
51
60
  # Do a shell-like path lookup for prog_script and return the results.
@@ -71,6 +80,7 @@ module Trepanning
71
80
  end
72
81
  return nil
73
82
  end
83
+ module_function :ruby_syntax_errors
74
84
  end
75
85
 
76
86
  if __FILE__ == $0
data/bin/trepan CHANGED
@@ -54,7 +54,8 @@ if File.basename(__FILE__) == File.basename($0)
54
54
  Trepan::PROG_SCRIPT = program_to_debug
55
55
 
56
56
  opts = {}
57
- %w(cmdfiles highlight initial_dir host nx port readline server traceprint
57
+ %w(cmdfiles highlight initial_dir host nx port post_mortem
58
+ readline server traceprint
58
59
  ).each do |opt|
59
60
  opts[opt.to_sym] = options[opt.to_sym]
60
61
  end
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+ # Use this to cut out the crud from make check.
3
+ # Use like this:
4
+ # make check 2>&1 | ruby ../make-check-filter.rb
5
+ # See Makefile.am
6
+ pats = ["^(?:Loaded",
7
+ 'Started',
8
+ "Making check in",
9
+ 'Test run options',
10
+ "^trepan: That",
11
+ ].join('|') + ')'
12
+ # puts pats
13
+ skip_re = /#{pats}/
14
+
15
+ while gets()
16
+ next if $_ =~ skip_re
17
+ puts $_
18
+ end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2011, 2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Interface for client (i.e. user to communication-device) interaction.
5
5
  # The debugged program is at the other end of the communcation.
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2011, 2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Communication status codes
5
5
  module Trepanning
@@ -7,14 +7,15 @@ module Trepanning
7
7
  # client interface. COMMAND goes the other way.
8
8
  module RemoteCommunication
9
9
  unless defined?(PRINT)
10
- PRINT = '.'
11
- COMMAND = 'C'
12
- CONFIRM_TRUE = 'Y'
13
- CONFIRM_FALSE = 'N'
10
+ PRINT = '.' # Server wants to print
11
+ COMMAND = 'C' # read a command
12
+ CONFIRM_TRUE = 'Y' # Confirm read, default true
13
+ CONFIRM_FALSE = 'N' # Confirm read, default false
14
14
  CONFIRM_REPLY = '?'
15
- QUIT = 'q'
16
- PROMPT = 'p'
17
- RESTART = 'r'
15
+ QUIT = 'q' # End debug session
16
+ PROMPT = 'p' # Write prompt
17
+ SYNC = 's' # Resynchronize communication
18
+ RESTART = 'r' # Restart
18
19
  end
19
20
  end
20
21
  end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2011, 2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Our local modules
5
5
  require_relative '../interface'
@@ -37,6 +37,11 @@ class Trepan::ServerInterface < Trepan::Interface
37
37
  Trepan::TCPDbgServer.new(@connection_opts)
38
38
  # end
39
39
  end
40
+
41
+ # In case we need to resync
42
+ @last_action = :nop
43
+ @last_args = []
44
+
40
45
  # For Compatability
41
46
  @output = @inout
42
47
  @input = @inout
@@ -74,6 +79,8 @@ class Trepan::ServerInterface < Trepan::Interface
74
79
  msg "Please answer 'yes' or 'no'. Try again."
75
80
  end
76
81
  end
82
+ @last_action = :confirm
83
+ @last_args = [prompt, default]
77
84
  return default
78
85
  end
79
86
 
@@ -95,16 +102,22 @@ class Trepan::ServerInterface < Trepan::Interface
95
102
  # used to write to a debugger that is connected to this
96
103
  # server; `str' written will have a newline added to it
97
104
  def msg(msg)
105
+ @last_args = [msg]
106
+ @last_action = :msg
98
107
  @inout.writeline(PRINT + msg)
99
108
  end
100
109
 
101
110
  # used to write to a debugger that is connected to this
102
111
  # server; `str' written will not have a newline added to it
103
112
  def msg_nocr(msg)
113
+ @last_args = [msg]
114
+ @last_action = :msg_nocr
104
115
  @inout.write(PRINT + msg)
105
116
  end
106
117
 
107
118
  def read_command(prompt)
119
+ @last_args = [prompt]
120
+ @last_action = :read_command
108
121
  readline(prompt)
109
122
  end
110
123
 
@@ -112,12 +125,23 @@ class Trepan::ServerInterface < Trepan::Interface
112
125
  @inout.read_dat
113
126
  end
114
127
 
128
+ def nop; end
129
+
130
+ def resync
131
+ # puts "resync", @last_action, @last_args
132
+ method(@last_action).call(*@last_args)
133
+ end
134
+
115
135
  def readline(prompt, add_to_history=true)
116
136
  if prompt
117
137
  write_prompt(prompt)
118
138
  end
139
+
119
140
  coded_line = @inout.read_msg()
120
- @read_ctrl = coded_line[0..0]
141
+ while (SYNC == @read_ctrl = coded_line[0..0])
142
+ resync
143
+ coded_line = @inout.read_msg()
144
+ end
121
145
  coded_line[1..-1]
122
146
  end
123
147
 
@@ -128,6 +152,8 @@ class Trepan::ServerInterface < Trepan::Interface
128
152
 
129
153
  def write_prompt(prompt)
130
154
  @inout.write(PROMPT + prompt)
155
+ @last_args = [prompt]
156
+ @last_action = :write_prompt
131
157
  end
132
158
 
133
159
  def write_confirm(prompt, default)
@@ -137,10 +163,20 @@ class Trepan::ServerInterface < Trepan::Interface
137
163
  code = CONFIRM_FALSE
138
164
  end
139
165
  @inout.write(code + prompt)
166
+ @last_args = [prompt, default]
167
+ @last_action = :write_confirm
140
168
  end
141
169
  end
142
170
 
143
171
  # Demo
144
172
  if __FILE__ == $0
145
173
  intf = Trepan::ServerInterface.new(nil, nil, :open => false)
174
+ intf.resync
175
+ def intf.msg(msg)
176
+ @last_args = [msg]
177
+ @last_action = :msg
178
+ puts msg
179
+ end
180
+ intf.msg('Hi!')
181
+ intf.resync
146
182
  end
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Interface when communicating with the user.
5
5
 
@@ -118,7 +118,7 @@ class Trepan::UserInterface < Trepan::Interface
118
118
 
119
119
  def readline(prompt='')
120
120
  @output.flush
121
- if @input.line_edit && @opts[:readline]
121
+ if @input.line_edit && @input.use_readline
122
122
  @input.readline(prompt)
123
123
  else
124
124
  @output.write(prompt) if prompt and prompt.size > 0
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
 
4
4
  # Debugger user/command-oriented input possibly attached to IO-style
5
5
  # input or GNU Readline.
@@ -13,6 +13,8 @@ class Trepan
13
13
  # input or GNU Readline.
14
14
  class UserInput < Trepan::InputBase
15
15
 
16
+ attr_reader :use_readline
17
+
16
18
  @@readline_finalized = false
17
19
 
18
20
  def initialize(inp, opts={})
@@ -36,6 +38,12 @@ class Trepan
36
38
  if @line_edit && @use_readline
37
39
  line = Readline.readline(prompt, true)
38
40
  else
41
+ # Prompt should be empty and should have been
42
+ # handled by caller.
43
+ unless prompt.empty?
44
+ raise RuntimeError,
45
+ "Internal error: prompt '#{prompt}' should have been handled by caller" unless prompt.empty?
46
+ end
39
47
  line = @input.gets
40
48
  end
41
49
  rescue Interrupt
@@ -66,7 +74,7 @@ class Trepan
66
74
  end
67
75
 
68
76
  def finalize
69
- if defined?(RbReadline) && !@@readline_finalized
77
+ if defined?(RbReadline) && !@@readline_finalized
70
78
  begin
71
79
  RbReadline.rl_cleanup_after_signal()
72
80
  rescue
@@ -76,7 +84,7 @@ class Trepan
76
84
  rescue
77
85
  end
78
86
  @@readline_finalized = true
79
- end
87
+ end
80
88
  end
81
89
  end
82
90
  end
@@ -12,8 +12,6 @@ class Trepan
12
12
 
13
13
  include Trepanning::TCPPacking
14
14
 
15
- DEFAULT_INIT_OPTS = {:open => true}
16
-
17
15
  CLIENT_SOCKET_OPTS = {
18
16
  :host => 'localhost', # Symbolic name
19
17
  :port => 1027, # Arbitrary non-privileged port
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2011, 2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  # Debugger Server Input/Output interface.
4
4
 
5
5
  require 'socket'
@@ -84,7 +84,8 @@ class Trepan
84
84
  def write(msg)
85
85
  wait_for_connect() unless connected?
86
86
  # FIXME: do we have to check the size of msg and split output?
87
- @session.print(pack_msg(msg))
87
+ pack_msg = pack_msg(msg)
88
+ @session.print(pack_msg)
88
89
  end
89
90
 
90
91
  def writeline(msg)
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # -*- coding: utf-8 -*-
3
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
3
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
4
4
  require 'trace' # Trace filtering
5
5
  require 'thread_frame' # Stack frame introspection and more.
6
6
  require_relative '../app/complete' # command completion
@@ -42,7 +42,7 @@ class Trepan
42
42
  # FIXME: Tracing through intialization code is slow. Need to figure
43
43
  # out better ways to do this.
44
44
  th = Thread.current
45
- th.exec_event_tracing = true
45
+ th.exec_event_tracing = true
46
46
 
47
47
  @settings = Trepan::DEFAULT_SETTINGS.merge(settings)
48
48
  @input = @settings[:input] || STDIN
@@ -65,8 +65,8 @@ class Trepan
65
65
  opts[:port] = @settings[:port] if @settings[:port]
66
66
  opts[:host] = @settings[:host] if @settings[:host]
67
67
  opts[:complete] = @completion_proc
68
- opts[:readline] ||= @settings[:readline]
69
- [Trepan::ClientInterface.new(nil, nil, nil, {}, opts)]
68
+ user_opts = @settings[:user_opts] || {}
69
+ [Trepan::ClientInterface.new(nil, nil, nil, user_opts, opts)]
70
70
  else
71
71
  opts = {:complete => @completion_proc,
72
72
  :readline => @settings[:readline]}
@@ -111,7 +111,7 @@ class Trepan
111
111
  clear_trace_func
112
112
  @intf[-1].close
113
113
  end
114
- th.exec_event_tracing = false
114
+ th.exec_event_tracing = false
115
115
  end
116
116
 
117
117
  # The method is called when we want to do debugger command completion
@@ -179,7 +179,7 @@ class Trepan
179
179
  # FIXME: one option we may want to pass is the initial trace filter.
180
180
  if opts[:hide_stack]
181
181
  @core.processor.hidelevels[Thread.current] =
182
- RubyVM::ThreadFrame.current.stack_size
182
+ RubyVM::Frame.current.stack_size
183
183
  end
184
184
  # unless defined?(PROG_UNRESOLVED_SCRIPT)
185
185
  # # We may later do more sophisticated things...
@@ -194,12 +194,12 @@ class Trepan
194
194
  elsif opts[:immediate]
195
195
  # Stop immediately after this method returns. But if opts[:debugme]
196
196
  # is set, we can stop in this method.
197
- RubyVM::ThreadFrame::current.trace_off = true unless opts[:debugme]
197
+ RubyVM::Frame::current.trace_off = true unless opts[:debugme]
198
198
  @trace_filter.set_trace_func(@core.event_proc)
199
199
  Trace.event_masks[0] |= @core.step_events
200
200
  @core.debugger(1)
201
201
  else
202
- RubyVM::ThreadFrame::current.trace_off = true unless opts[:debugme]
202
+ RubyVM::Frame::current.trace_off = true unless opts[:debugme]
203
203
 
204
204
  @trace_filter.set_trace_func(@core.event_proc)
205
205
  Trace.event_masks[0] |= @core.step_events
@@ -79,11 +79,11 @@ class Trepan
79
79
  # FIXME: Rework using a general "set substitute file" command and
80
80
  # a global default profile which gets read.
81
81
  file = File.expand_path(File.join(File.dirname(__FILE__),
82
- %w(.. data prelude.rb)))
82
+ %w(data prelude.rb)))
83
83
  LineCache::cache(file)
84
84
  LineCache::remap_file('<internal:prelude>', file)
85
85
  file = File.expand_path(File.join(File.dirname(__FILE__),
86
- %w(.. data custom_require.rb)))
86
+ %w(data custom_require.rb)))
87
87
  LineCache::cache(file)
88
88
  LineCache::remap_file('<internal:lib/rubygems/custom_require>',
89
89
  file)
@@ -193,8 +193,8 @@ class Trepan
193
193
  # This is the main entry point.
194
194
  def process_commands(frame)
195
195
 
196
- frame_setup(frame)
197
196
  @event = @core.event
197
+ frame_setup(frame)
198
198
 
199
199
  @unconditional_prehooks.run
200
200
 
@@ -219,7 +219,7 @@ class Trepan
219
219
  @last_pos = [@frame.source_container, frame_line,
220
220
  @stack_size, @current_thread, @event,
221
221
  @frame.pc_offset]
222
- else
222
+ elsif @event != 'post-mortem'
223
223
  return if stepping_skip? || @stack_size <= @hide_level
224
224
  if @settings[:traceprint]
225
225
  step
@@ -90,7 +90,7 @@ if __FILE__ == $0
90
90
  %w(1 100).each {|count| run_cmd(cmd, [cmd.name, count])}
91
91
  cmd.settings[:basename] = true
92
92
  def foo(cmd, name)
93
- cmd.proc.frame_setup(RubyVM::ThreadFrame::current)
93
+ cmd.proc.frame_setup(RubyVM::Frame::current)
94
94
  run_cmd(cmd, [cmd.name])
95
95
  end
96
96
  foo(cmd, cmd.name)
@@ -1,5 +1,5 @@
1
1
  # -*- coding: utf-8 -*-
2
- # Copyright (C) 2010, 2011 Rocky Bernstein <rockyb@rubyforge.net>
2
+ # Copyright (C) 2010-2012 Rocky Bernstein <rockyb@rubyforge.net>
3
3
  # A base class for debugger subcommands.
4
4
  #
5
5
  # Note: don't end classname with Command (capital C) since main
@@ -164,6 +164,9 @@ class Trepan
164
164
  run_set_bool(args)
165
165
  end
166
166
 
167
+ # Returns an Array of commands needed to save this setting.
168
+ # Here it is simply:
169
+ # set xx ... {on|off}
167
170
  def save_command
168
171
  val = settings[subcmd_setting_key] ? 'on' : 'off'
169
172
  ["#{subcmd_prefix_string} #{val}"]
@@ -86,7 +86,7 @@ if __FILE__ == $0
86
86
  run_cmd(cmd, [cmd.name])
87
87
  run_cmd(cmd, [cmd.name, __LINE__.to_s])
88
88
  require 'thread_frame'
89
- tf = RubyVM::ThreadFrame.current
89
+ tf = RubyVM::Frame.current
90
90
  pc_offset = tf.pc_offset
91
91
  run_cmd(cmd, [cmd.name, "@#{pc_offset}"])
92
92
  def foo