ruby-debug-ide-docker 0.6.1

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 (49) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +75 -0
  3. data/ChangeLog.archive +1073 -0
  4. data/ChangeLog.md +594 -0
  5. data/Gemfile +28 -0
  6. data/MIT-LICENSE +24 -0
  7. data/Rakefile +42 -0
  8. data/bin/gdb_wrapper +96 -0
  9. data/bin/rdebug-ide +183 -0
  10. data/ext/mkrf_conf.rb +48 -0
  11. data/lib/ruby-debug-ide.rb +173 -0
  12. data/lib/ruby-debug-ide/attach/debugger_loader.rb +20 -0
  13. data/lib/ruby-debug-ide/attach/gdb.rb +73 -0
  14. data/lib/ruby-debug-ide/attach/lldb.rb +71 -0
  15. data/lib/ruby-debug-ide/attach/native_debugger.rb +133 -0
  16. data/lib/ruby-debug-ide/attach/process_thread.rb +54 -0
  17. data/lib/ruby-debug-ide/attach/util.rb +115 -0
  18. data/lib/ruby-debug-ide/command.rb +177 -0
  19. data/lib/ruby-debug-ide/commands/breakpoints.rb +128 -0
  20. data/lib/ruby-debug-ide/commands/catchpoint.rb +64 -0
  21. data/lib/ruby-debug-ide/commands/condition.rb +51 -0
  22. data/lib/ruby-debug-ide/commands/control.rb +158 -0
  23. data/lib/ruby-debug-ide/commands/enable.rb +203 -0
  24. data/lib/ruby-debug-ide/commands/eval.rb +64 -0
  25. data/lib/ruby-debug-ide/commands/expression_info.rb +71 -0
  26. data/lib/ruby-debug-ide/commands/file_filtering.rb +107 -0
  27. data/lib/ruby-debug-ide/commands/frame.rb +155 -0
  28. data/lib/ruby-debug-ide/commands/inspect.rb +25 -0
  29. data/lib/ruby-debug-ide/commands/jump.rb +73 -0
  30. data/lib/ruby-debug-ide/commands/load.rb +18 -0
  31. data/lib/ruby-debug-ide/commands/pause.rb +33 -0
  32. data/lib/ruby-debug-ide/commands/set_type.rb +47 -0
  33. data/lib/ruby-debug-ide/commands/stepping.rb +108 -0
  34. data/lib/ruby-debug-ide/commands/threads.rb +178 -0
  35. data/lib/ruby-debug-ide/commands/variables.rb +154 -0
  36. data/lib/ruby-debug-ide/event_processor.rb +71 -0
  37. data/lib/ruby-debug-ide/greeter.rb +40 -0
  38. data/lib/ruby-debug-ide/helper.rb +33 -0
  39. data/lib/ruby-debug-ide/ide_processor.rb +155 -0
  40. data/lib/ruby-debug-ide/interface.rb +45 -0
  41. data/lib/ruby-debug-ide/multiprocess.rb +23 -0
  42. data/lib/ruby-debug-ide/multiprocess/monkey.rb +47 -0
  43. data/lib/ruby-debug-ide/multiprocess/pre_child.rb +67 -0
  44. data/lib/ruby-debug-ide/multiprocess/starter.rb +11 -0
  45. data/lib/ruby-debug-ide/multiprocess/unmonkey.rb +31 -0
  46. data/lib/ruby-debug-ide/version.rb +3 -0
  47. data/lib/ruby-debug-ide/xml_printer.rb +545 -0
  48. data/ruby-debug-ide-docker.gemspec +51 -0
  49. metadata +110 -0
@@ -0,0 +1,177 @@
1
+ if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION)
2
+ require 'ruby-debug-base'
3
+ else
4
+ require 'debase'
5
+ end
6
+
7
+ require 'ruby-debug-ide/helper'
8
+ require 'delegate'
9
+
10
+ module Debugger
11
+
12
+ class Command < SimpleDelegator # :nodoc:
13
+ SubcmdStruct=Struct.new(:name, :min, :short_help, :long_help) unless
14
+ defined?(SubcmdStruct)
15
+
16
+ # Find param in subcmds. param id downcased and can be abbreviated
17
+ # to the minimum length listed in the subcommands
18
+ def find(subcmds, param)
19
+ param.downcase!
20
+ for try_subcmd in subcmds do
21
+ if (param.size >= try_subcmd.min) and
22
+ (try_subcmd.name[0..param.size-1] == param)
23
+ return try_subcmd
24
+ end
25
+ end
26
+ return nil
27
+ end
28
+
29
+ class << self
30
+ def commands
31
+ @commands ||= []
32
+ end
33
+
34
+ DEF_OPTIONS = {
35
+ :event => true,
36
+ :control => false,
37
+ :unknown => false,
38
+ :need_context => false,
39
+ }
40
+
41
+ def inherited(klass)
42
+ DEF_OPTIONS.each do |o, v|
43
+ klass.options[o] = v if klass.options[o].nil?
44
+ end
45
+ commands << klass
46
+ end
47
+
48
+ def load_commands
49
+ dir = File.dirname(__FILE__)
50
+ Dir[File.join(dir, 'commands', '*')].each do |file|
51
+ require file if file =~ /\.rb$/
52
+ end
53
+ Debugger.constants.grep(/Functions$/).map { |name| Debugger.const_get(name) }.each do |mod|
54
+ include mod
55
+ end
56
+ end
57
+
58
+ def method_missing(meth, *args, &block)
59
+ if meth.to_s =~ /^(.+?)=$/
60
+ @options[$1.intern] = args.first
61
+ else
62
+ if @options.has_key?(meth)
63
+ @options[meth]
64
+ else
65
+ super
66
+ end
67
+ end
68
+ end
69
+
70
+ def options
71
+ @options ||= {}
72
+ end
73
+
74
+ def unescape_incoming(str)
75
+ str.gsub(/((?:^|[^\\])(?:\\\\)*)((?:\\n)+)/) do |_|
76
+ $1 + "\n" * ($2.size / 2)
77
+ end.gsub(/\\\\/, '\\')
78
+ end
79
+
80
+ def file_filter_supported?
81
+ defined?(Debugger.file_filter)
82
+ end
83
+ end
84
+
85
+ def initialize(state, printer)
86
+ @state, @printer = state, printer
87
+ super @printer
88
+ end
89
+
90
+ def match(input)
91
+ @match = regexp.match(input)
92
+ end
93
+
94
+ protected
95
+
96
+ def errmsg(*args)
97
+ @printer.print_error(*args)
98
+ end
99
+
100
+ def print(*args)
101
+ @state.print(*args)
102
+ end
103
+
104
+ # see Timeout::timeout, the difference is that we must use a DebugThread
105
+ # because every other thread would be halted when the event hook is reached
106
+ # in ruby-debug.c
107
+ def timeout(sec)
108
+ return yield if sec == nil or sec.zero?
109
+ if Thread.respond_to?(:critical) and Thread.critical
110
+ raise ThreadError, "timeout within critical session"
111
+ end
112
+ begin
113
+ x = Thread.current
114
+ y = DebugThread.start {
115
+ sleep sec
116
+ x.raise StandardError, "Timeout: evaluation took longer than #{sec} seconds." if x.alive?
117
+ }
118
+ yield sec
119
+ ensure
120
+ y.kill if y and y.alive?
121
+ end
122
+ end
123
+
124
+ def debug_eval(str, b = get_binding)
125
+ begin
126
+ str = str.to_s
127
+ str.force_encoding('UTF-8') if(RUBY_VERSION >= '2.0')
128
+ to_inspect = Command.unescape_incoming(str)
129
+ max_time = Debugger.evaluation_timeout
130
+ @printer.print_debug("Evaluating %s with timeout after %i sec", str, max_time)
131
+ timeout(max_time) do
132
+ eval(to_inspect, b)
133
+ end
134
+ rescue StandardError, ScriptError => e
135
+ @printer.print_exception(e, @state.binding)
136
+ throw :debug_error
137
+ end
138
+ end
139
+
140
+ def debug_silent_eval(str)
141
+ begin
142
+ str = str.to_s
143
+ eval(str, get_binding)
144
+ rescue StandardError, ScriptError
145
+ nil
146
+ end
147
+ end
148
+
149
+ def get_binding
150
+ @state.context.frame_binding(@state.frame_pos)
151
+ end
152
+
153
+ def line_at(file, line)
154
+ Debugger.line_at(file, line)
155
+ end
156
+
157
+ def get_context(thnum)
158
+ Debugger.contexts.find{|c| c.thnum == thnum}
159
+ end
160
+
161
+ def realpath(filename)
162
+ is_dir = filename.end_with?(File::SEPARATOR)
163
+ if filename.index(File::SEPARATOR) || File::ALT_SEPARATOR && filename.index(File::ALT_SEPARATOR)
164
+ filename = File.expand_path(filename)
165
+ end
166
+ if (RUBY_VERSION < '1.9') || (RbConfig::CONFIG['host_os'] =~ /mswin/)
167
+ filename
168
+ else
169
+ filename = File.realpath(filename) rescue filename
170
+ filename = filename + File::SEPARATOR if is_dir && !filename.end_with?(File::SEPARATOR)
171
+ filename
172
+ end
173
+ end
174
+ end
175
+
176
+ Command.load_commands
177
+ end
@@ -0,0 +1,128 @@
1
+ module Debugger
2
+ class AddBreakpoint < Command # :nodoc:
3
+ self.control = true
4
+
5
+ def regexp
6
+ / ^\s*
7
+ b(?:reak)?
8
+ (?: \s+
9
+ (?:
10
+ (\d+) |
11
+ (.+?)[:.#]([^.:\s]+)
12
+ ))?
13
+ (?:\s+
14
+ if\s+(.+)
15
+ )?
16
+ $
17
+ /x
18
+ end
19
+
20
+ def execute
21
+ if @match[1]
22
+ line, _, _, expr = @match.captures
23
+ else
24
+ _, file, line, expr = @match.captures
25
+ end
26
+
27
+ if file.nil?
28
+ file = File.basename(@state.file)
29
+ else
30
+ if line !~ /^\d+$/
31
+ klass = debug_silent_eval(file)
32
+ if klass && !klass.kind_of?(Module)
33
+ print_error "Unknown class #{file}"
34
+ throw :debug_error
35
+ end
36
+ file = klass.name if klass
37
+ else
38
+ file = realpath(file)
39
+ end
40
+ end
41
+
42
+ if line =~ /^\d+$/
43
+ line = line.to_i
44
+ else
45
+ line = line.intern.id2name
46
+ end
47
+
48
+ b = Debugger.add_breakpoint file, line, expr
49
+ print_breakpoint_added b
50
+ end
51
+
52
+ class << self
53
+ def help_command
54
+ 'break'
55
+ end
56
+
57
+ def help(cmd)
58
+ %{
59
+ b[reak] file:line [if expr]
60
+ b[reak] [file|class(:|.|#)]<line|method> [if expr] -
61
+ \tset breakpoint to some position, (optionally) if expr == true
62
+ }
63
+ end
64
+ end
65
+ end
66
+
67
+ class BreakpointsCommand < Command # :nodoc:
68
+ self.control = true
69
+
70
+ def regexp
71
+ /^\s*info\s*break$/
72
+ end
73
+
74
+ def execute
75
+ print_breakpoints Debugger.breakpoints
76
+ end
77
+
78
+ class << self
79
+ def help_command
80
+ 'break'
81
+ end
82
+
83
+ def help(cmd)
84
+ %{
85
+ b[reak]\tlist breakpoints
86
+ }
87
+ end
88
+ end
89
+ end
90
+
91
+ class DeleteBreakpointCommand < Command # :nodoc:
92
+ self.control = true
93
+
94
+ def regexp
95
+ /^\s*del(?:ete)?(?:\s+(.*))?$/
96
+ end
97
+
98
+ def execute
99
+ brkpts = @match[1]
100
+ unless brkpts
101
+ Debugger.breakpoints.clear
102
+ else
103
+ brkpts.split(/[ \t]+/).each do |pos|
104
+ pos = get_int(pos, "Delete", 1)
105
+ return unless pos
106
+ b = Debugger.remove_breakpoint(pos)
107
+ if b
108
+ print_breakpoint_deleted b
109
+ else
110
+ print_error "No breakpoint number %d\n", pos
111
+ end
112
+ end
113
+ end
114
+ end
115
+
116
+ class << self
117
+ def help_command
118
+ 'delete'
119
+ end
120
+
121
+ def help(cmd)
122
+ %{
123
+ del[ete][ nnn...]\tdelete some or all breakpoints
124
+ }
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,64 @@
1
+ module Debugger
2
+ class CatchCommand < Command # :nodoc:
3
+ self.control = true
4
+
5
+ def regexp
6
+ /^\s* cat(?:ch)?
7
+ (?:\s+ (\S+))?
8
+ (?:\s+ (off))? \s* $/ix
9
+ end
10
+
11
+ def execute
12
+ excn = @match[1]
13
+ if not excn
14
+ # No args given.
15
+ errmsg "Exception class must be specified for 'catch' command"
16
+ elsif not @match[2]
17
+ # One arg given.
18
+ if 'off' == excn
19
+ clear_catchpoints
20
+ else
21
+ Debugger.add_catchpoint(excn)
22
+ print_catchpoint_set(excn)
23
+ end
24
+ elsif @match[2] != 'off'
25
+ errmsg "Off expected. Got %s\n", @match[2]
26
+ elsif remove_catchpoint(excn)
27
+ print_catchpoint_deleted(excn)
28
+ else
29
+ errmsg "Catch for exception %s not found.\n", excn
30
+ end
31
+ end
32
+
33
+ class << self
34
+ def help_command
35
+ 'catch'
36
+ end
37
+
38
+ def help(cmd)
39
+ %{
40
+ cat[ch]\t\t\tshow catchpoint
41
+ cat[ch] off \tremove all catch points
42
+ cat[ch] <an Exception>\tset catchpoint to an exception
43
+ cat[ch] <an Exception> off \tremove catchpoint for an exception
44
+ }
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def clear_catchpoints
51
+ if Debugger.respond_to?(:clear_catchpoints)
52
+ Debugger.clear_catchpoints
53
+ else
54
+ Debugger.catchpoints.clear
55
+ end
56
+ end
57
+
58
+ def remove_catchpoint(excn)
59
+ return Debugger.remove_catchpoint(excn) if Debugger.respond_to?(:remove_catchpoint)
60
+ return Debugger.catchpoints.delete(excn) if Debugger.catchpoints.member?(excn)
61
+ false
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,51 @@
1
+ module Debugger
2
+
3
+ class ConditionCommand < Command # :nodoc:
4
+ self.control = true
5
+
6
+ def regexp
7
+ /^\s* cond(?:ition)? (?:\s+(\d+)\s*(.*))?$/ix
8
+ end
9
+
10
+ def execute
11
+ if not @match[1]
12
+ errmsg "\"condition\" must be followed a breakpoint number and expression\n"
13
+ else
14
+ breakpoints = Debugger.breakpoints.sort_by{|b| b.id }
15
+ largest = breakpoints.inject(0) do |largest_so_far, b|
16
+ b.id if b.id > largest_so_far
17
+ end
18
+ if 0 == largest
19
+ print "No breakpoints have been set.\n"
20
+ return
21
+ end
22
+ pos = get_int(@match[1], "Condition", 1, largest)
23
+ return unless pos
24
+ breakpoints.each do |b|
25
+ if b.id == pos
26
+ b.expr = @match[2].empty? ? nil : @match[2]
27
+ print_contdition_set(b.id)
28
+ break
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+
35
+ class << self
36
+ def help_command
37
+ 'condition'
38
+ end
39
+
40
+ def help(cmd)
41
+ %{
42
+ Condition breakpoint-number expression
43
+ Specify breakpoint number N to break only if COND is true.
44
+ N is an integer and COND is an expression to be evaluated whenever
45
+ breakpoint N is reached. If the empty string is used, the condition is removed.
46
+ }
47
+ end
48
+ end
49
+ end
50
+
51
+ end # module Debugger
@@ -0,0 +1,158 @@
1
+ module Debugger
2
+ class QuitCommand < Command # :nodoc:
3
+ self.control = true
4
+
5
+ def regexp
6
+ /^\s*(?:q(?:uit)?|exit)\s*$/
7
+ end
8
+
9
+ def execute
10
+ begin
11
+ @printer.print_msg("finished")
12
+ @printer.print_debug("Exiting debugger.")
13
+ ensure
14
+ exit! # exit -> exit!: No graceful way to stop threads...
15
+ end
16
+ end
17
+
18
+ class << self
19
+ def help_command
20
+ %w[quit exit]
21
+ end
22
+
23
+ def help(cmd)
24
+ %{
25
+ q[uit]\texit from debugger,
26
+ exit\talias to quit
27
+ }
28
+ end
29
+ end
30
+ end
31
+
32
+ class RestartCommand < Command # :nodoc:
33
+ self.control = true
34
+
35
+ def regexp
36
+ / ^\s*
37
+ (restart|R)
38
+ (\s+ \S+ .*)?
39
+ $
40
+ /x
41
+ end
42
+
43
+ def execute
44
+ if not defined? Debugger::RDEBUG_SCRIPT or not defined? Debugger::ARGV
45
+ print "We are not in a context we can restart from.\n"
46
+ return
47
+ end
48
+ if @match[2]
49
+ args = Debugger::PROG_SCRIPT + " " + @match[2]
50
+ else
51
+ args = Debugger::ARGV.join(" ")
52
+ end
53
+
54
+ # An execv would be preferable to the "exec" below.
55
+ cmd = Debugger::RDEBUG_SCRIPT + " " + args
56
+ print "Re exec'ing:\n\t#{cmd}\n"
57
+ exec cmd
58
+ end
59
+
60
+ class << self
61
+ def help_command
62
+ 'restart'
63
+ end
64
+
65
+ def help(cmd)
66
+ %{
67
+ restart|R [args]
68
+ Restart the program. This is is a re-exec - all debugger state
69
+ is lost. If command arguments are passed those are used.
70
+ }
71
+ end
72
+ end
73
+ end
74
+
75
+ class StartCommand < Command # :nodoc:
76
+ self.control = true
77
+
78
+ def regexp
79
+ /^\s*(start)(\s+ \S+ .*)?$/x
80
+ end
81
+
82
+ def execute
83
+ @printer.print_debug("Starting: running program script")
84
+ Debugger.run_prog_script #Debugger.prog_script_running?
85
+ end
86
+
87
+ class << self
88
+ def help_command
89
+ 'start'
90
+ end
91
+
92
+ def help(cmd)
93
+ %{
94
+ run prog script
95
+ }
96
+ end
97
+ end
98
+ end
99
+
100
+
101
+ class InterruptCommand < Command # :nodoc:
102
+ self.event = false
103
+ self.control = true
104
+ self.need_context = true
105
+
106
+ def regexp
107
+ /^\s*i(?:nterrupt)?\s*$/
108
+ end
109
+
110
+ def execute
111
+ unless Debugger.interrupt_last
112
+ context = Debugger.thread_context(Thread.main)
113
+ context.interrupt
114
+ end
115
+ end
116
+
117
+ class << self
118
+ def help_command
119
+ 'interrupt'
120
+ end
121
+
122
+ def help(cmd)
123
+ %{
124
+ i[nterrupt]\tinterrupt the program
125
+ }
126
+ end
127
+ end
128
+ end
129
+
130
+
131
+ class DetachCommand < Command # :nodoc:
132
+ self.control = true
133
+
134
+ def regexp
135
+ /^\s*detach\s*$/
136
+ end
137
+
138
+ def execute
139
+ Debugger.stop
140
+ Debugger.interface.close
141
+ Debugger::MultiProcess.undo_monkey
142
+ Debugger.control_thread = nil
143
+ Thread.current.exit #@control_thread is a current thread
144
+ end
145
+
146
+ class << self
147
+ def help_command
148
+ 'detach'
149
+ end
150
+
151
+ def help(cmd)
152
+ %{
153
+ detach\ndetach debugger\nnote: this option is only for remote debugging (or local attach)
154
+ }
155
+ end
156
+ end
157
+ end
158
+ end