ruby-debug-ide-docker 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGES +75 -0
- data/ChangeLog.archive +1073 -0
- data/ChangeLog.md +594 -0
- data/Gemfile +28 -0
- data/MIT-LICENSE +24 -0
- data/Rakefile +42 -0
- data/bin/gdb_wrapper +96 -0
- data/bin/rdebug-ide +183 -0
- data/ext/mkrf_conf.rb +48 -0
- data/lib/ruby-debug-ide.rb +173 -0
- data/lib/ruby-debug-ide/attach/debugger_loader.rb +20 -0
- data/lib/ruby-debug-ide/attach/gdb.rb +73 -0
- data/lib/ruby-debug-ide/attach/lldb.rb +71 -0
- data/lib/ruby-debug-ide/attach/native_debugger.rb +133 -0
- data/lib/ruby-debug-ide/attach/process_thread.rb +54 -0
- data/lib/ruby-debug-ide/attach/util.rb +115 -0
- data/lib/ruby-debug-ide/command.rb +177 -0
- data/lib/ruby-debug-ide/commands/breakpoints.rb +128 -0
- data/lib/ruby-debug-ide/commands/catchpoint.rb +64 -0
- data/lib/ruby-debug-ide/commands/condition.rb +51 -0
- data/lib/ruby-debug-ide/commands/control.rb +158 -0
- data/lib/ruby-debug-ide/commands/enable.rb +203 -0
- data/lib/ruby-debug-ide/commands/eval.rb +64 -0
- data/lib/ruby-debug-ide/commands/expression_info.rb +71 -0
- data/lib/ruby-debug-ide/commands/file_filtering.rb +107 -0
- data/lib/ruby-debug-ide/commands/frame.rb +155 -0
- data/lib/ruby-debug-ide/commands/inspect.rb +25 -0
- data/lib/ruby-debug-ide/commands/jump.rb +73 -0
- data/lib/ruby-debug-ide/commands/load.rb +18 -0
- data/lib/ruby-debug-ide/commands/pause.rb +33 -0
- data/lib/ruby-debug-ide/commands/set_type.rb +47 -0
- data/lib/ruby-debug-ide/commands/stepping.rb +108 -0
- data/lib/ruby-debug-ide/commands/threads.rb +178 -0
- data/lib/ruby-debug-ide/commands/variables.rb +154 -0
- data/lib/ruby-debug-ide/event_processor.rb +71 -0
- data/lib/ruby-debug-ide/greeter.rb +40 -0
- data/lib/ruby-debug-ide/helper.rb +33 -0
- data/lib/ruby-debug-ide/ide_processor.rb +155 -0
- data/lib/ruby-debug-ide/interface.rb +45 -0
- data/lib/ruby-debug-ide/multiprocess.rb +23 -0
- data/lib/ruby-debug-ide/multiprocess/monkey.rb +47 -0
- data/lib/ruby-debug-ide/multiprocess/pre_child.rb +67 -0
- data/lib/ruby-debug-ide/multiprocess/starter.rb +11 -0
- data/lib/ruby-debug-ide/multiprocess/unmonkey.rb +31 -0
- data/lib/ruby-debug-ide/version.rb +3 -0
- data/lib/ruby-debug-ide/xml_printer.rb +545 -0
- data/ruby-debug-ide-docker.gemspec +51 -0
- metadata +110 -0
data/Gemfile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
# @param [Array<String>] versions compatible ruby versions
|
4
|
+
# @return [Array<String>] an array with mri platforms of given versions
|
5
|
+
def mries(*versions)
|
6
|
+
versions.flat_map do |v|
|
7
|
+
%w(ruby mingw x64_mingw)
|
8
|
+
.map { |platform| "#{platform}_#{v}".to_sym unless platform == "x64_mingw" && v < "2.0" }
|
9
|
+
.delete_if &:nil?
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
gem "ruby-debug-base", :platforms => [:jruby, *mries('18')]
|
14
|
+
gem "ruby-debug-base19x", ">= 0.11.32", :platforms => mries('19')
|
15
|
+
if RUBY_VERSION && RUBY_VERSION >= "2.0"
|
16
|
+
gem "debase", "~> 0.2.2", :platforms => mries('20', '21', '22', '23', '24', '25')
|
17
|
+
end
|
18
|
+
|
19
|
+
gemspec
|
20
|
+
|
21
|
+
group :development do
|
22
|
+
gem "bundler"
|
23
|
+
end
|
24
|
+
|
25
|
+
group :test do
|
26
|
+
gem "test-unit"
|
27
|
+
end
|
28
|
+
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
The file lib/classic-debug.rb is based on the debug.rb file from Ruby
|
2
|
+
project.
|
3
|
+
|
4
|
+
Copyright (c) 2007-2008, debug-commons team
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
desc 'Default: run unit tests.'
|
5
|
+
task :default => [:test]
|
6
|
+
|
7
|
+
# Unit tests
|
8
|
+
Rake::TestTask.new do |t|
|
9
|
+
t.libs << "test"
|
10
|
+
t.libs << "test-base"
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
t.warning = false
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "Create a ChangeLog"
|
17
|
+
# simple rake task to output a changelog between two commits, tags ...
|
18
|
+
# output is formatted simply, commits are grouped under each author name
|
19
|
+
desc "generate changelog with nice clean output"
|
20
|
+
task :changelog, :since_c, :until_c do |t,args|
|
21
|
+
since_c = args[:since_c] || `git tag | head -1`.chomp
|
22
|
+
until_c = args[:until_c]
|
23
|
+
cmd=`git log --pretty='format:%ci::%an <%ae>::%s::%H' #{since_c}..#{until_c}`
|
24
|
+
|
25
|
+
entries = Hash.new
|
26
|
+
changelog_content = String.new
|
27
|
+
|
28
|
+
cmd.split("\n").each do |entry|
|
29
|
+
date, author, subject, hash = entry.chomp.split("::")
|
30
|
+
entries[author] = Array.new unless entries[author]
|
31
|
+
day = date.split(" ").first
|
32
|
+
entries[author] << "#{subject} (#{hash})" unless subject =~ /Merge/
|
33
|
+
end
|
34
|
+
|
35
|
+
# generate clean output
|
36
|
+
entries.keys.each do |author|
|
37
|
+
changelog_content += author + "\n"
|
38
|
+
entries[author].reverse.each { |entry| changelog_content += " * #{entry}\n" }
|
39
|
+
end
|
40
|
+
|
41
|
+
puts changelog_content
|
42
|
+
end
|
data/bin/gdb_wrapper
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'thread'
|
5
|
+
require 'ostruct'
|
6
|
+
|
7
|
+
$stdout.sync = true
|
8
|
+
$stderr.sync = true
|
9
|
+
|
10
|
+
options = OpenStruct.new(
|
11
|
+
'pid' => nil,
|
12
|
+
'sdk_path' => nil,
|
13
|
+
'uid' => nil,
|
14
|
+
'gems_to_include' => []
|
15
|
+
)
|
16
|
+
|
17
|
+
module DebugPrinter
|
18
|
+
|
19
|
+
class << self
|
20
|
+
attr_accessor :cli_debug
|
21
|
+
|
22
|
+
def print_debug(msg)
|
23
|
+
if DebugPrinter.cli_debug
|
24
|
+
$stderr.puts msg
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
DebugPrinter.cli_debug = ARGV.include? '--debug'
|
32
|
+
|
33
|
+
opts = OptionParser.new do |opts|
|
34
|
+
# TODO need some banner
|
35
|
+
opts.banner = <<EOB
|
36
|
+
Some useful banner.
|
37
|
+
EOB
|
38
|
+
|
39
|
+
opts.on('--pid PID', 'pid of process you want to attach to for debugging') do |pid|
|
40
|
+
options.pid = pid
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on('--ruby-path RUBY_PATH', 'path to ruby interpreter') do |ruby_path|
|
44
|
+
options.ruby_path = ruby_path
|
45
|
+
end
|
46
|
+
|
47
|
+
opts.on('--uid UID', 'uid which this process should set after executing gdb attach') do |uid|
|
48
|
+
options.uid = uid
|
49
|
+
end
|
50
|
+
|
51
|
+
opts.on('--include-gem GEM_LIB_PATH', 'lib of gem to include') do |gem_lib_path|
|
52
|
+
options.gems_to_include << gem_lib_path
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.parse! ARGV
|
57
|
+
|
58
|
+
unless options.pid
|
59
|
+
$stderr.puts 'You should specify PID of process you want to attach to'
|
60
|
+
exit 1
|
61
|
+
end
|
62
|
+
|
63
|
+
unless options.ruby_path
|
64
|
+
$stderr.puts 'You should specify path to the ruby interpreter'
|
65
|
+
exit 1
|
66
|
+
end
|
67
|
+
|
68
|
+
argv = '["' + ARGV * '", "' + '"]'
|
69
|
+
child_argv = '["' + ARGV * '", "' + "', '--ignore-port" + '"]'
|
70
|
+
debugger_loader_path = File.expand_path(File.dirname(__FILE__)) + '/../lib/ruby-debug-ide/attach/debugger_loader'
|
71
|
+
|
72
|
+
options.gems_to_include.each do |gem_path|
|
73
|
+
$LOAD_PATH.unshift(gem_path) unless $LOAD_PATH.include?(gem_path)
|
74
|
+
end
|
75
|
+
|
76
|
+
require 'ruby-debug-ide/greeter'
|
77
|
+
Debugger::print_greeting_msg($stdout, nil, nil)
|
78
|
+
|
79
|
+
require 'ruby-debug-ide/attach/util'
|
80
|
+
require 'ruby-debug-ide/attach/native_debugger'
|
81
|
+
require 'ruby-debug-ide/attach/process_thread'
|
82
|
+
|
83
|
+
|
84
|
+
child_pids = get_child_pids(options.pid.to_s)
|
85
|
+
attach_threads = Array.new
|
86
|
+
attach_threads << attach_and_return_thread(options, options.pid, debugger_loader_path, argv)
|
87
|
+
|
88
|
+
attach_threads << child_pids.map {|pid| attach_and_return_thread(options, pid, debugger_loader_path, child_argv)}
|
89
|
+
|
90
|
+
|
91
|
+
attach_threads.each {|thread| thread.join}
|
92
|
+
if options.uid
|
93
|
+
DebugPrinter.print_debug("changing current uid from #{Process.uid} to #{options.uid}")
|
94
|
+
Process::Sys.setuid(options.uid.to_i)
|
95
|
+
end
|
96
|
+
sleep
|
data/bin/rdebug-ide
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'optparse'
|
4
|
+
require "ostruct"
|
5
|
+
if RUBY_VERSION < "1.9"
|
6
|
+
require 'ruby-debug-ide'
|
7
|
+
else
|
8
|
+
require_relative '../lib/ruby-debug-ide'
|
9
|
+
end
|
10
|
+
|
11
|
+
$stdout.sync=true
|
12
|
+
|
13
|
+
options = OpenStruct.new(
|
14
|
+
'frame_bind' => false,
|
15
|
+
'host' => nil,
|
16
|
+
'load_mode' => false,
|
17
|
+
'port' => 1234,
|
18
|
+
'stop' => false,
|
19
|
+
'tracing' => false,
|
20
|
+
'int_handler' => true,
|
21
|
+
'dispatcher_port' => -1,
|
22
|
+
'evaluation_timeout' => 10,
|
23
|
+
'trace_to_s' => false,
|
24
|
+
'debugger_memory_limit' => 10,
|
25
|
+
'inspect_time_limit' => 100,
|
26
|
+
'rm_protocol_extensions' => false,
|
27
|
+
'catchpoint_deleted_event' => false,
|
28
|
+
'value_as_nested_element' => false,
|
29
|
+
'attach_mode' => false,
|
30
|
+
'cli_debug' => false
|
31
|
+
)
|
32
|
+
|
33
|
+
opts = OptionParser.new do |opts|
|
34
|
+
opts.banner = <<EOB
|
35
|
+
Using ruby-debug-base #{Debugger::VERSION}
|
36
|
+
Usage: rdebug-ide is supposed to be called from RDT, NetBeans, RubyMine, or
|
37
|
+
the IntelliJ IDEA Ruby plugin. The command line interface to
|
38
|
+
ruby-debug is rdebug.
|
39
|
+
EOB
|
40
|
+
opts.separator ""
|
41
|
+
opts.separator "Options:"
|
42
|
+
|
43
|
+
opts.on("-h", "--host HOST", "Host name used for remote debugging") {|host| options.host = host}
|
44
|
+
opts.on("-p", "--port PORT", Integer, "Port used for remote debugging") {|port| options.port = port}
|
45
|
+
opts.on("--dispatcher-port PORT", Integer, "Port used for multi-process debugging dispatcher") do |dp|
|
46
|
+
options.dispatcher_port = dp
|
47
|
+
end
|
48
|
+
opts.on('--evaluation-timeout TIMEOUT', Integer,'evaluation timeout in seconds (default: 10)') do |timeout|
|
49
|
+
options.evaluation_timeout = timeout
|
50
|
+
end
|
51
|
+
opts.on("--evaluation-control", "trace to_s evaluation") {options.trace_to_s = true}
|
52
|
+
|
53
|
+
opts.on("-m", "--memory-limit LIMIT", Integer, "evaluation memory limit in mb (default: 10)") do |limit|
|
54
|
+
if defined?(JRUBY_VERSION) || RUBY_VERSION < '2.0'
|
55
|
+
$stderr.puts "Evaluation memory limit is ineffective in JRuby and MRI < 2.0"
|
56
|
+
limit = 0
|
57
|
+
end
|
58
|
+
options.debugger_memory_limit = limit
|
59
|
+
options.trace_to_s ||= limit > 0
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on("-t", "--time-limit LIMIT", Integer, "evaluation time limit in milliseconds (default: 100)") do |limit|
|
63
|
+
options.inspect_time_limit = limit
|
64
|
+
options.trace_to_s ||= limit > 0
|
65
|
+
end
|
66
|
+
|
67
|
+
opts.on('--stop', 'stop when the script is loaded') {options.stop = true}
|
68
|
+
opts.on("-x", "--trace", "turn on line tracing") {options.tracing = true}
|
69
|
+
opts.on("-l", "--load-mode", "load mode (experimental)") {options.load_mode = true}
|
70
|
+
opts.on("-d", "--debug", "Debug self - prints information for debugging ruby-debug itself") do
|
71
|
+
Debugger.cli_debug = true
|
72
|
+
options.cli_debug = true
|
73
|
+
end
|
74
|
+
opts.on("--xml-debug", "Debug self - sends information <message>s for debugging ruby-debug itself") do
|
75
|
+
Debugger.xml_debug = true
|
76
|
+
end
|
77
|
+
opts.on("-I", "--include PATH", String, "Add PATH to $LOAD_PATH") do |path|
|
78
|
+
$LOAD_PATH.unshift(path)
|
79
|
+
end
|
80
|
+
opts.on("--attach-mode", "Tells that rdebug-ide is working in attach mode") do
|
81
|
+
options.attach_mode = true
|
82
|
+
end
|
83
|
+
opts.on("--ignore-port", "Generate another port") do
|
84
|
+
options.ignore_port = true
|
85
|
+
end
|
86
|
+
opts.on("--keep-frame-binding", "Keep frame bindings") {options.frame_bind = true}
|
87
|
+
opts.on("--disable-int-handler", "Disables interrupt signal handler") {options.int_handler = false}
|
88
|
+
opts.on("--rubymine-protocol-extensions", "Enable all RubyMine-specific incompatible protocol extensions") do
|
89
|
+
options.rm_protocol_extensions = true
|
90
|
+
end
|
91
|
+
opts.on("--catchpoint-deleted-event", "Enable chatchpointDeleted event") do
|
92
|
+
options.catchpoint_deleted_event = true
|
93
|
+
end
|
94
|
+
opts.on("--value-as-nested-element", "Allow to pass variable's value as nested element instead of attribute") do
|
95
|
+
options.value_as_nested_element = true
|
96
|
+
end
|
97
|
+
opts.separator ""
|
98
|
+
opts.separator "Common options:"
|
99
|
+
opts.on_tail("-v", "--version", "Show version") do
|
100
|
+
puts "Using ruby-debug-base #{Debugger::VERSION}"
|
101
|
+
exit
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
begin
|
106
|
+
Debugger::ARGV = ARGV.clone
|
107
|
+
rdebug_path = File.expand_path($0)
|
108
|
+
if RUBY_PLATFORM =~ /mswin/
|
109
|
+
rdebug_path += ".cmd" unless rdebug_path =~ /\.cmd$/i
|
110
|
+
end
|
111
|
+
Debugger::RDEBUG_SCRIPT = rdebug_path
|
112
|
+
opts.parse! ARGV
|
113
|
+
rescue StandardError => e
|
114
|
+
puts opts
|
115
|
+
puts
|
116
|
+
puts e.message
|
117
|
+
exit(1)
|
118
|
+
end
|
119
|
+
|
120
|
+
if ARGV.empty? && !options.attach_mode
|
121
|
+
puts opts
|
122
|
+
puts
|
123
|
+
puts "Must specify a script to run"
|
124
|
+
exit(1)
|
125
|
+
end
|
126
|
+
|
127
|
+
# save script name
|
128
|
+
if !options.attach_mode
|
129
|
+
Debugger::PROG_SCRIPT = ARGV.shift
|
130
|
+
else
|
131
|
+
Debugger::PROG_SCRIPT = $0
|
132
|
+
end
|
133
|
+
|
134
|
+
if options.dispatcher_port != -1
|
135
|
+
ENV['IDE_PROCESS_DISPATCHER'] = options.dispatcher_port.to_s
|
136
|
+
if RUBY_VERSION < "1.9"
|
137
|
+
lib_path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
138
|
+
$: << lib_path unless $:.include? lib_path
|
139
|
+
require 'ruby-debug-ide/multiprocess'
|
140
|
+
else
|
141
|
+
require_relative '../lib/ruby-debug-ide/multiprocess'
|
142
|
+
end
|
143
|
+
Debugger::MultiProcess.do_monkey
|
144
|
+
|
145
|
+
ENV['DEBUGGER_STORED_RUBYLIB'] = ENV['RUBYLIB']
|
146
|
+
old_opts = ENV['RUBYOPT'] || ''
|
147
|
+
starter = "-r#{File.expand_path(File.dirname(__FILE__))}/../lib/ruby-debug-ide/multiprocess/starter"
|
148
|
+
unless old_opts.include? starter
|
149
|
+
ENV['RUBYOPT'] = starter
|
150
|
+
ENV['RUBYOPT'] += " #{old_opts}" if old_opts != ''
|
151
|
+
end
|
152
|
+
ENV['DEBUGGER_CLI_DEBUG'] = Debugger.cli_debug.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
if options.int_handler
|
156
|
+
# install interruption handler
|
157
|
+
trap('INT') { Debugger.interrupt_last }
|
158
|
+
end
|
159
|
+
|
160
|
+
# set options
|
161
|
+
Debugger.keep_frame_binding = options.frame_bind
|
162
|
+
Debugger.tracing = options.tracing
|
163
|
+
Debugger.evaluation_timeout = options.evaluation_timeout
|
164
|
+
Debugger.trace_to_s = options.trace_to_s && (options.debugger_memory_limit > 0 || options.inspect_time_limit > 0)
|
165
|
+
Debugger.debugger_memory_limit = options.debugger_memory_limit
|
166
|
+
Debugger.inspect_time_limit = options.inspect_time_limit
|
167
|
+
Debugger.catchpoint_deleted_event = options.catchpoint_deleted_event || options.rm_protocol_extensions
|
168
|
+
Debugger.value_as_nested_element = options.value_as_nested_element || options.rm_protocol_extensions
|
169
|
+
|
170
|
+
if options.attach_mode
|
171
|
+
if Debugger::FRONT_END == "debase"
|
172
|
+
Debugger.init_variables
|
173
|
+
end
|
174
|
+
|
175
|
+
Debugger::MultiProcess::pre_child(options)
|
176
|
+
|
177
|
+
if Debugger::FRONT_END == "debase"
|
178
|
+
Debugger.setup_tracepoints
|
179
|
+
Debugger.prepare_context
|
180
|
+
end
|
181
|
+
else
|
182
|
+
Debugger.debug_program(options)
|
183
|
+
end
|
data/ext/mkrf_conf.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
jruby = defined?(JRUBY_VERSION) || (defined?(RUBY_ENGINE) && 'jruby' == RUBY_ENGINE)
|
2
|
+
rbx = defined?(RUBY_ENGINE) && 'rbx' == RUBY_ENGINE
|
3
|
+
|
4
|
+
def already_installed(dep)
|
5
|
+
!Gem::DependencyInstaller.new(:domain => :local).find_gems_with_sources(dep).empty? ||
|
6
|
+
!Gem::DependencyInstaller.new(:domain => :local,:prerelease => true).find_gems_with_sources(dep).empty?
|
7
|
+
end
|
8
|
+
|
9
|
+
unless jruby || rbx
|
10
|
+
require 'rubygems'
|
11
|
+
require 'rubygems/command.rb'
|
12
|
+
require 'rubygems/dependency.rb'
|
13
|
+
require 'rubygems/dependency_installer.rb'
|
14
|
+
|
15
|
+
begin
|
16
|
+
Gem::Command.build_args = ARGV
|
17
|
+
rescue NoMethodError
|
18
|
+
end
|
19
|
+
|
20
|
+
if RUBY_VERSION < "1.9"
|
21
|
+
dep = Gem::Dependency.new("ruby-debug-base", '>=0.10.4')
|
22
|
+
elsif RUBY_VERSION < '2.0'
|
23
|
+
dep = Gem::Dependency.new("ruby-debug-base19x", '>=0.11.30.pre15')
|
24
|
+
else
|
25
|
+
dep = Gem::Dependency.new("debase", '> 0')
|
26
|
+
end
|
27
|
+
|
28
|
+
begin
|
29
|
+
puts "Installing base gem"
|
30
|
+
inst = Gem::DependencyInstaller.new :prerelease => dep.prerelease?
|
31
|
+
inst.install dep
|
32
|
+
rescue
|
33
|
+
begin
|
34
|
+
inst = Gem::DependencyInstaller.new(:prerelease => true)
|
35
|
+
inst.install dep
|
36
|
+
rescue Exception => e
|
37
|
+
puts e
|
38
|
+
puts e.backtrace.join "\n "
|
39
|
+
exit(1)
|
40
|
+
end
|
41
|
+
end unless dep.nil? || already_installed(dep)
|
42
|
+
end
|
43
|
+
|
44
|
+
# create dummy rakefile to indicate success
|
45
|
+
f = File.open(File.join(File.dirname(__FILE__), "Rakefile"), "w")
|
46
|
+
f.write("task :default\n")
|
47
|
+
f.close
|
48
|
+
|
@@ -0,0 +1,173 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'stringio'
|
3
|
+
require "socket"
|
4
|
+
require 'thread'
|
5
|
+
if RUBY_VERSION < '2.0' || defined?(JRUBY_VERSION)
|
6
|
+
require 'ruby-debug-base'
|
7
|
+
Debugger::FRONT_END = "ruby-debug-base"
|
8
|
+
else
|
9
|
+
require 'debase'
|
10
|
+
Debugger::FRONT_END = "debase"
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'ruby-debug-ide/greeter'
|
14
|
+
require 'ruby-debug-ide/xml_printer'
|
15
|
+
require 'ruby-debug-ide/ide_processor'
|
16
|
+
require 'ruby-debug-ide/event_processor'
|
17
|
+
|
18
|
+
module Debugger
|
19
|
+
|
20
|
+
class << self
|
21
|
+
# Prints to the stderr using printf(*args) if debug logging flag (-d) is on.
|
22
|
+
def print_debug(*args)
|
23
|
+
if Debugger.cli_debug
|
24
|
+
$stderr.printf("#{Process.pid}: ")
|
25
|
+
$stderr.printf(*args)
|
26
|
+
$stderr.printf("\n")
|
27
|
+
$stderr.flush
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def cleanup_backtrace(backtrace)
|
32
|
+
cleared = []
|
33
|
+
return cleared unless backtrace
|
34
|
+
backtrace.each do |line|
|
35
|
+
if line.index(File.expand_path(File.dirname(__FILE__) + "/..")) == 0
|
36
|
+
next
|
37
|
+
end
|
38
|
+
if line.index("-e:1") == 0
|
39
|
+
break
|
40
|
+
end
|
41
|
+
cleared << line
|
42
|
+
end
|
43
|
+
cleared
|
44
|
+
end
|
45
|
+
|
46
|
+
attr_accessor :attached
|
47
|
+
attr_accessor :cli_debug, :xml_debug, :evaluation_timeout
|
48
|
+
attr_accessor :trace_to_s, :debugger_memory_limit, :inspect_time_limit
|
49
|
+
attr_accessor :control_thread
|
50
|
+
attr_reader :interface
|
51
|
+
# protocol extensions
|
52
|
+
attr_accessor :catchpoint_deleted_event, :value_as_nested_element
|
53
|
+
|
54
|
+
|
55
|
+
#
|
56
|
+
# Interrupts the last debugged thread
|
57
|
+
#
|
58
|
+
def interrupt_last
|
59
|
+
skip do
|
60
|
+
if context = last_context
|
61
|
+
return nil unless context.thread.alive?
|
62
|
+
context.interrupt
|
63
|
+
end
|
64
|
+
context
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def start_server(host = nil, port = 1234, notify_dispatcher = false)
|
69
|
+
return if started?
|
70
|
+
start
|
71
|
+
start_control(host, port, notify_dispatcher)
|
72
|
+
end
|
73
|
+
|
74
|
+
def prepare_debugger(options)
|
75
|
+
@mutex = Mutex.new
|
76
|
+
@proceed = ConditionVariable.new
|
77
|
+
|
78
|
+
start_server(options.host, options.port, options.notify_dispatcher)
|
79
|
+
|
80
|
+
raise "Control thread did not start (#{@control_thread}}" unless @control_thread && @control_thread.alive?
|
81
|
+
|
82
|
+
# wait for 'start' command
|
83
|
+
@mutex.synchronize do
|
84
|
+
@proceed.wait(@mutex)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def debug_program(options)
|
89
|
+
prepare_debugger(options)
|
90
|
+
|
91
|
+
abs_prog_script = File.expand_path(Debugger::PROG_SCRIPT)
|
92
|
+
bt = debug_load(abs_prog_script, options.stop, options.load_mode)
|
93
|
+
if bt && !bt.is_a?(SystemExit)
|
94
|
+
$stderr.print "Uncaught exception: #{bt}\n"
|
95
|
+
$stderr.print Debugger.cleanup_backtrace(bt.backtrace).map{|l| "\t#{l}"}.join("\n"), "\n"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def run_prog_script
|
100
|
+
return unless @mutex
|
101
|
+
@mutex.synchronize do
|
102
|
+
@proceed.signal
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def start_control(host, port, notify_dispatcher)
|
107
|
+
raise "Debugger is not started" unless started?
|
108
|
+
return if @control_thread
|
109
|
+
@control_thread = DebugThread.new do
|
110
|
+
begin
|
111
|
+
# 127.0.0.1 seemingly works with all systems and with IPv6 as well.
|
112
|
+
# "localhost" and nil have problems on some systems.
|
113
|
+
host ||= '127.0.0.1'
|
114
|
+
server = TCPServer.new(host, port)
|
115
|
+
print_greeting_msg($stderr, host, port) if defined? IDE_VERSION
|
116
|
+
notify_dispatcher(port) if notify_dispatcher
|
117
|
+
while (session = server.accept)
|
118
|
+
$stderr.puts "Connected from #{session.peeraddr[2]}" if Debugger.cli_debug
|
119
|
+
dispatcher = ENV['IDE_PROCESS_DISPATCHER']
|
120
|
+
if dispatcher
|
121
|
+
ENV['IDE_PROCESS_DISPATCHER'] = "#{session.peeraddr[2]}:#{dispatcher}" unless dispatcher.include?(":")
|
122
|
+
ENV['DEBUGGER_HOST'] = host
|
123
|
+
end
|
124
|
+
begin
|
125
|
+
@interface = RemoteInterface.new(session)
|
126
|
+
self.handler = EventProcessor.new(interface)
|
127
|
+
IdeControlCommandProcessor.new(interface).process_commands
|
128
|
+
rescue StandardError, ScriptError => ex
|
129
|
+
bt = ex.backtrace
|
130
|
+
$stderr.printf "#{Process.pid}: Exception in DebugThread loop: #{ex.message}(#{ex.class})\nBacktrace:\n#{bt ? bt.join("\n from: ") : "<none>"}\n"
|
131
|
+
exit 1
|
132
|
+
end
|
133
|
+
end
|
134
|
+
rescue
|
135
|
+
bt = $!.backtrace
|
136
|
+
$stderr.printf "Fatal exception in DebugThread loop: #{$!.message}\nBacktrace:\n#{bt ? bt.join("\n from: ") : "<none>"}\n"
|
137
|
+
exit 2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
|
145
|
+
def notify_dispatcher(port)
|
146
|
+
return unless ENV['IDE_PROCESS_DISPATCHER']
|
147
|
+
acceptor_host, acceptor_port = ENV['IDE_PROCESS_DISPATCHER'].split(":")
|
148
|
+
acceptor_host, acceptor_port = '127.0.0.1', acceptor_host unless acceptor_port
|
149
|
+
connected = false
|
150
|
+
|
151
|
+
3.times do |i|
|
152
|
+
begin
|
153
|
+
s = TCPSocket.open(acceptor_host, acceptor_port)
|
154
|
+
s.print(port)
|
155
|
+
s.close
|
156
|
+
connected = true
|
157
|
+
print_debug "Ide process dispatcher notified about sub-debugger which listens on #{port}\n"
|
158
|
+
return
|
159
|
+
rescue => bt
|
160
|
+
$stderr.puts "#{Process.pid}: connection failed(#{i+1})"
|
161
|
+
$stderr.puts "Exception: #{bt}"
|
162
|
+
$stderr.puts bt.backtrace.map { |l| "\t#{l}" }.join("\n")
|
163
|
+
sleep 0.3
|
164
|
+
end unless connected
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
class Exception # :nodoc:
|
171
|
+
attr_reader :__debug_file, :__debug_line, :__debug_binding, :__debug_context
|
172
|
+
end
|
173
|
+
end
|