ruby-debug-ide22 0.7.4 → 0.7.5

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +75 -75
  3. data/ChangeLog.archive +1073 -1073
  4. data/ChangeLog.md +594 -594
  5. data/Gemfile +38 -38
  6. data/MIT-LICENSE +24 -24
  7. data/Rakefile +92 -92
  8. data/bin/gdb_wrapper +96 -96
  9. data/bin/rdebug-ide +200 -200
  10. data/ext/mkrf_conf.rb +44 -44
  11. data/lib/ruby-debug-ide/attach/debugger_loader.rb +20 -20
  12. data/lib/ruby-debug-ide/attach/gdb.rb +73 -73
  13. data/lib/ruby-debug-ide/attach/lldb.rb +71 -71
  14. data/lib/ruby-debug-ide/attach/native_debugger.rb +133 -133
  15. data/lib/ruby-debug-ide/attach/process_thread.rb +54 -54
  16. data/lib/ruby-debug-ide/attach/util.rb +114 -114
  17. data/lib/ruby-debug-ide/command.rb +187 -187
  18. data/lib/ruby-debug-ide/commands/breakpoints.rb +128 -128
  19. data/lib/ruby-debug-ide/commands/catchpoint.rb +64 -64
  20. data/lib/ruby-debug-ide/commands/condition.rb +51 -51
  21. data/lib/ruby-debug-ide/commands/control.rb +164 -158
  22. data/lib/ruby-debug-ide/commands/enable.rb +203 -203
  23. data/lib/ruby-debug-ide/commands/eval.rb +64 -64
  24. data/lib/ruby-debug-ide/commands/expression_info.rb +71 -71
  25. data/lib/ruby-debug-ide/commands/file_filtering.rb +106 -106
  26. data/lib/ruby-debug-ide/commands/frame.rb +155 -155
  27. data/lib/ruby-debug-ide/commands/inspect.rb +25 -25
  28. data/lib/ruby-debug-ide/commands/load.rb +17 -17
  29. data/lib/ruby-debug-ide/commands/stepping.rb +108 -108
  30. data/lib/ruby-debug-ide/commands/threads.rb +178 -178
  31. data/lib/ruby-debug-ide/commands/variables.rb +154 -154
  32. data/lib/ruby-debug-ide/event_processor.rb +71 -71
  33. data/lib/ruby-debug-ide/greeter.rb +42 -42
  34. data/lib/ruby-debug-ide/helper.rb +33 -33
  35. data/lib/ruby-debug-ide/ide_processor.rb +155 -155
  36. data/lib/ruby-debug-ide/interface.rb +47 -45
  37. data/lib/ruby-debug-ide/multiprocess/monkey.rb +46 -46
  38. data/lib/ruby-debug-ide/multiprocess/pre_child.rb +58 -58
  39. data/lib/ruby-debug-ide/multiprocess/starter.rb +10 -10
  40. data/lib/ruby-debug-ide/multiprocess/unmonkey.rb +30 -30
  41. data/lib/ruby-debug-ide/multiprocess.rb +22 -22
  42. data/lib/ruby-debug-ide/thread_alias.rb +26 -26
  43. data/lib/ruby-debug-ide/version.rb +3 -3
  44. data/lib/ruby-debug-ide/xml_printer.rb +570 -570
  45. data/lib/ruby-debug-ide.rb +230 -228
  46. data/ruby-debug-ide.gemspec +47 -47
  47. metadata +4 -4
@@ -1,73 +1,73 @@
1
- require 'ruby-debug-ide/attach/native_debugger'
2
-
3
- class GDB < NativeDebugger
4
-
5
- def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
6
- super(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
7
- end
8
-
9
- def set_flags
10
- execute 'set scheduler-locking off' # we will deadlock with it
11
- execute 'set unwindonsignal on' # in case of some signal we will exit gdb
12
- end
13
-
14
- def update_threads
15
- @process_threads = []
16
- info_threads = (execute 'info threads').split("\n")
17
- info_threads.each do |thread_info|
18
- next unless thread_info =~ /[\s*]*\d+\s+Thread.*/
19
- $stdout.puts "thread_info: #{thread_info}"
20
- is_main = thread_info[0] == '*'
21
- thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i
22
- thread = ProcessThread.new(thread_num, is_main, thread_info, self)
23
- if thread.is_main
24
- @main_thread = thread
25
- end
26
- @process_threads << thread
27
- end
28
- @process_threads
29
- end
30
-
31
- def check_already_under_debug
32
- threads = execute 'info threads'
33
- threads =~ /ruby-debug-ide/
34
- end
35
-
36
- def switch_to_thread(thread_num)
37
- execute "thread #{thread_num}"
38
- end
39
-
40
- def set_break(str)
41
- execute "tbreak #{str}"
42
- end
43
-
44
- def call_start_attach
45
- super()
46
- execute "call dlopen(\"#{@path_to_attach}\", 2)"
47
- execute 'call debase_start_attach()'
48
- set_break(@tbreak)
49
- end
50
-
51
- def print_delimiter
52
- @pipe.puts "print \"#{@delimiter}\""
53
- end
54
-
55
- def check_delimiter(line)
56
- line =~ /\$\d+\s=\s"#{@delimiter}"/
57
- end
58
-
59
- def load_debugger
60
- execute "call #{@eval_string}"
61
- end
62
-
63
- def to_s
64
- GDB.to_s
65
- end
66
-
67
- class << self
68
- def to_s
69
- 'gdb'
70
- end
71
- end
72
-
73
- end
1
+ require 'ruby-debug-ide/attach/native_debugger'
2
+
3
+ class GDB < NativeDebugger
4
+
5
+ def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
6
+ super(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
7
+ end
8
+
9
+ def set_flags
10
+ execute 'set scheduler-locking off' # we will deadlock with it
11
+ execute 'set unwindonsignal on' # in case of some signal we will exit gdb
12
+ end
13
+
14
+ def update_threads
15
+ @process_threads = []
16
+ info_threads = (execute 'info threads').split("\n")
17
+ info_threads.each do |thread_info|
18
+ next unless thread_info =~ /[\s*]*\d+\s+Thread.*/
19
+ $stdout.puts "thread_info: #{thread_info}"
20
+ is_main = thread_info[0] == '*'
21
+ thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i
22
+ thread = ProcessThread.new(thread_num, is_main, thread_info, self)
23
+ if thread.is_main
24
+ @main_thread = thread
25
+ end
26
+ @process_threads << thread
27
+ end
28
+ @process_threads
29
+ end
30
+
31
+ def check_already_under_debug
32
+ threads = execute 'info threads'
33
+ threads =~ /ruby-debug-ide/
34
+ end
35
+
36
+ def switch_to_thread(thread_num)
37
+ execute "thread #{thread_num}"
38
+ end
39
+
40
+ def set_break(str)
41
+ execute "tbreak #{str}"
42
+ end
43
+
44
+ def call_start_attach
45
+ super()
46
+ execute "call dlopen(\"#{@path_to_attach}\", 2)"
47
+ execute 'call debase_start_attach()'
48
+ set_break(@tbreak)
49
+ end
50
+
51
+ def print_delimiter
52
+ @pipe.puts "print \"#{@delimiter}\""
53
+ end
54
+
55
+ def check_delimiter(line)
56
+ line =~ /\$\d+\s=\s"#{@delimiter}"/
57
+ end
58
+
59
+ def load_debugger
60
+ execute "call #{@eval_string}"
61
+ end
62
+
63
+ def to_s
64
+ GDB.to_s
65
+ end
66
+
67
+ class << self
68
+ def to_s
69
+ 'gdb'
70
+ end
71
+ end
72
+
73
+ end
@@ -1,71 +1,71 @@
1
- require 'ruby-debug-ide/attach/native_debugger'
2
-
3
- class LLDB < NativeDebugger
4
-
5
- def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
6
- super(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
7
- end
8
-
9
- def set_flags
10
-
11
- end
12
-
13
- def update_threads
14
- @process_threads = []
15
- info_threads = (execute 'thread list').split("\n")
16
- info_threads.each do |thread_info|
17
- next unless thread_info =~ /[\s*]*thread\s#\d+.*/
18
- is_main = thread_info[0] == '*'
19
- thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i
20
- thread = ProcessThread.new(thread_num, is_main, thread_info, self)
21
- if thread.is_main
22
- @main_thread = thread
23
- end
24
- @process_threads << thread
25
- end
26
- @process_threads
27
- end
28
-
29
- def check_already_under_debug
30
- threads = execute 'thread list'
31
- threads =~ /ruby-debug-ide/
32
- end
33
-
34
- def switch_to_thread(thread_num)
35
- execute "thread select #{thread_num}"
36
- end
37
-
38
- def set_break(str)
39
- execute "breakpoint set --shlib #{@path_to_attach} --name #{str}"
40
- end
41
-
42
- def call_start_attach
43
- super()
44
- execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)"
45
- execute 'expr (int) debase_start_attach()'
46
- set_break(@tbreak)
47
- end
48
-
49
- def print_delimiter
50
- @pipe.puts "script print \"#{@delimiter}\""
51
- end
52
-
53
- def check_delimiter(line)
54
- line =~ /#{@delimiter}$/
55
- end
56
-
57
- def load_debugger
58
- execute "expr (void) #{@eval_string}"
59
- end
60
-
61
- def to_s
62
- LLDB.to_s
63
- end
64
-
65
- class << self
66
- def to_s
67
- 'lldb'
68
- end
69
- end
70
-
71
- end
1
+ require 'ruby-debug-ide/attach/native_debugger'
2
+
3
+ class LLDB < NativeDebugger
4
+
5
+ def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
6
+ super(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
7
+ end
8
+
9
+ def set_flags
10
+
11
+ end
12
+
13
+ def update_threads
14
+ @process_threads = []
15
+ info_threads = (execute 'thread list').split("\n")
16
+ info_threads.each do |thread_info|
17
+ next unless thread_info =~ /[\s*]*thread\s#\d+.*/
18
+ is_main = thread_info[0] == '*'
19
+ thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i
20
+ thread = ProcessThread.new(thread_num, is_main, thread_info, self)
21
+ if thread.is_main
22
+ @main_thread = thread
23
+ end
24
+ @process_threads << thread
25
+ end
26
+ @process_threads
27
+ end
28
+
29
+ def check_already_under_debug
30
+ threads = execute 'thread list'
31
+ threads =~ /ruby-debug-ide/
32
+ end
33
+
34
+ def switch_to_thread(thread_num)
35
+ execute "thread select #{thread_num}"
36
+ end
37
+
38
+ def set_break(str)
39
+ execute "breakpoint set --shlib #{@path_to_attach} --name #{str}"
40
+ end
41
+
42
+ def call_start_attach
43
+ super()
44
+ execute "expr (void *) dlopen(\"#{@path_to_attach}\", 2)"
45
+ execute 'expr (int) debase_start_attach()'
46
+ set_break(@tbreak)
47
+ end
48
+
49
+ def print_delimiter
50
+ @pipe.puts "script print \"#{@delimiter}\""
51
+ end
52
+
53
+ def check_delimiter(line)
54
+ line =~ /#{@delimiter}$/
55
+ end
56
+
57
+ def load_debugger
58
+ execute "expr (void) #{@eval_string}"
59
+ end
60
+
61
+ def to_s
62
+ LLDB.to_s
63
+ end
64
+
65
+ class << self
66
+ def to_s
67
+ 'lldb'
68
+ end
69
+ end
70
+
71
+ end
@@ -1,133 +1,133 @@
1
- class NativeDebugger
2
-
3
- attr_reader :pid, :main_thread, :process_threads, :pipe
4
-
5
- # @param executable -- path to ruby interpreter
6
- # @param pid -- pid of process you want to debug
7
- # @param flags -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit)
8
- def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
9
- @pid = pid
10
- @delimiter = '__OUTPUT_FINISHED__' # for getting response
11
- @tbreak = '__func_to_set_breakpoint_at'
12
- @main_thread = nil
13
- @process_threads = nil
14
- debase_path = gems_to_include.select {|gem_path| gem_path =~ /debase/}
15
- if debase_path.size == 0
16
- raise 'No debase gem found.'
17
- end
18
- @path_to_attach = find_attach_lib(debase_path[0])
19
-
20
- @gems_to_include = '["' + gems_to_include * '", "' + '"]'
21
- @debugger_loader_path = debugger_loader_path
22
- @argv = argv
23
-
24
- @eval_string = "debase_rb_eval(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\")"
25
-
26
- launch_string = "#{self} #{executable} #{flags}"
27
- @pipe = IO.popen(launch_string, 'r+')
28
- $stdout.puts "executed '#{launch_string}'"
29
- end
30
-
31
- def find_attach_lib(debase_path)
32
- attach_lib = debase_path + '/attach'
33
- known_extensions = %w(.so .bundle .dll .dylib)
34
- known_extensions.each do |ext|
35
- if File.file?(attach_lib + ext)
36
- return attach_lib + ext
37
- end
38
- end
39
-
40
- raise 'Could not find attach library'
41
- end
42
-
43
- def attach_to_process
44
- execute "attach #{@pid}"
45
- end
46
-
47
- def execute(command)
48
- @pipe.puts command
49
- $stdout.puts "executed `#{command}` command inside #{self}."
50
- if command == 'q'
51
- return ''
52
- end
53
- get_response
54
- end
55
-
56
- def get_response
57
- # we need this hack to understand that debugger gave us all output from last executed command
58
- print_delimiter
59
-
60
- content = ''
61
- loop do
62
- line = @pipe.readline
63
- DebugPrinter.print_debug('respond line: ' + line)
64
- break if check_delimiter(line)
65
- next if line =~ /\(lldb\)/ # lldb repeats your input to its output
66
- content += line
67
- end
68
-
69
- content
70
- end
71
-
72
- def update_threads
73
-
74
- end
75
-
76
- def check_already_under_debug
77
-
78
- end
79
-
80
- def print_delimiter
81
-
82
- end
83
-
84
- def check_delimiter(line)
85
-
86
- end
87
-
88
- def switch_to_thread
89
-
90
- end
91
-
92
- def set_break(str)
93
-
94
- end
95
-
96
- def continue
97
- $stdout.puts 'continuing'
98
- @pipe.puts 'c'
99
- loop do
100
- line = @pipe.readline
101
- DebugPrinter.print_debug('respond line: ' + line)
102
- break if line =~ /#{Regexp.escape(@tbreak)}/
103
- end
104
- get_response
105
- end
106
-
107
- def call_start_attach
108
- raise 'No main thread found. Did you forget to call `update_threads`?' if @main_thread == nil
109
- @main_thread.switch
110
- end
111
-
112
- def wait_line_event
113
- call_start_attach
114
- continue
115
- end
116
-
117
- def load_debugger
118
-
119
- end
120
-
121
- def exited?
122
- @pipe.closed?
123
- end
124
-
125
- def exit
126
- @pipe.close
127
- end
128
-
129
- def to_s
130
- 'native_debugger'
131
- end
132
-
133
- end
1
+ class NativeDebugger
2
+
3
+ attr_reader :pid, :main_thread, :process_threads, :pipe
4
+
5
+ # @param executable -- path to ruby interpreter
6
+ # @param pid -- pid of process you want to debug
7
+ # @param flags -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit)
8
+ def initialize(executable, pid, flags, gems_to_include, debugger_loader_path, argv)
9
+ @pid = pid
10
+ @delimiter = '__OUTPUT_FINISHED__' # for getting response
11
+ @tbreak = '__func_to_set_breakpoint_at'
12
+ @main_thread = nil
13
+ @process_threads = nil
14
+ debase_path = gems_to_include.select {|gem_path| gem_path =~ /debase/}
15
+ if debase_path.size == 0
16
+ raise 'No debase gem found.'
17
+ end
18
+ @path_to_attach = find_attach_lib(debase_path[0])
19
+
20
+ @gems_to_include = '["' + gems_to_include * '", "' + '"]'
21
+ @debugger_loader_path = debugger_loader_path
22
+ @argv = argv
23
+
24
+ @eval_string = "debase_rb_eval(\"require '#{@debugger_loader_path}'; load_debugger(#{@gems_to_include.gsub("\"", "'")}, #{@argv.gsub("\"", "'")})\")"
25
+
26
+ launch_string = "#{self} #{executable} #{flags}"
27
+ @pipe = IO.popen(launch_string, 'r+')
28
+ $stdout.puts "executed '#{launch_string}'"
29
+ end
30
+
31
+ def find_attach_lib(debase_path)
32
+ attach_lib = debase_path + '/attach'
33
+ known_extensions = %w(.so .bundle .dll .dylib)
34
+ known_extensions.each do |ext|
35
+ if File.file?(attach_lib + ext)
36
+ return attach_lib + ext
37
+ end
38
+ end
39
+
40
+ raise 'Could not find attach library'
41
+ end
42
+
43
+ def attach_to_process
44
+ execute "attach #{@pid}"
45
+ end
46
+
47
+ def execute(command)
48
+ @pipe.puts command
49
+ $stdout.puts "executed `#{command}` command inside #{self}."
50
+ if command == 'q'
51
+ return ''
52
+ end
53
+ get_response
54
+ end
55
+
56
+ def get_response
57
+ # we need this hack to understand that debugger gave us all output from last executed command
58
+ print_delimiter
59
+
60
+ content = ''
61
+ loop do
62
+ line = @pipe.readline
63
+ DebugPrinter.print_debug('respond line: ' + line)
64
+ break if check_delimiter(line)
65
+ next if line =~ /\(lldb\)/ # lldb repeats your input to its output
66
+ content += line
67
+ end
68
+
69
+ content
70
+ end
71
+
72
+ def update_threads
73
+
74
+ end
75
+
76
+ def check_already_under_debug
77
+
78
+ end
79
+
80
+ def print_delimiter
81
+
82
+ end
83
+
84
+ def check_delimiter(line)
85
+
86
+ end
87
+
88
+ def switch_to_thread
89
+
90
+ end
91
+
92
+ def set_break(str)
93
+
94
+ end
95
+
96
+ def continue
97
+ $stdout.puts 'continuing'
98
+ @pipe.puts 'c'
99
+ loop do
100
+ line = @pipe.readline
101
+ DebugPrinter.print_debug('respond line: ' + line)
102
+ break if line =~ /#{Regexp.escape(@tbreak)}/
103
+ end
104
+ get_response
105
+ end
106
+
107
+ def call_start_attach
108
+ raise 'No main thread found. Did you forget to call `update_threads`?' if @main_thread == nil
109
+ @main_thread.switch
110
+ end
111
+
112
+ def wait_line_event
113
+ call_start_attach
114
+ continue
115
+ end
116
+
117
+ def load_debugger
118
+
119
+ end
120
+
121
+ def exited?
122
+ @pipe.closed?
123
+ end
124
+
125
+ def exit
126
+ @pipe.close
127
+ end
128
+
129
+ def to_s
130
+ 'native_debugger'
131
+ end
132
+
133
+ end
@@ -1,54 +1,54 @@
1
- require 'ruby-debug-ide/attach/native_debugger'
2
-
3
- class ProcessThread
4
-
5
- attr_reader :thread_num, :is_main, :thread_info, :last_bt
6
-
7
- def initialize(thread_num, is_main, thread_info, native_debugger)
8
- @thread_num = thread_num
9
- @is_main = is_main
10
- @native_debugger = native_debugger
11
- @thread_info = thread_info
12
- @last_bt = nil
13
- end
14
-
15
- def switch
16
- @native_debugger.switch_to_thread(thread_num)
17
- end
18
-
19
- def finish
20
- @native_debugger.execute 'finish'
21
- end
22
-
23
- def get_bt
24
- @last_bt = @native_debugger.execute 'bt'
25
- end
26
-
27
- def any_caller_match(bt, pattern)
28
- bt =~ /#{pattern}/
29
- end
30
-
31
- def is_inside_malloc(bt = get_bt)
32
- if any_caller_match(bt, '(malloc)')
33
- $stderr.puts "process #{@native_debugger.pid} is currently inside malloc."
34
- true
35
- else
36
- false
37
- end
38
- end
39
-
40
- def is_inside_gc(bt = get_bt)
41
- if any_caller_match(bt, '(gc\.c)')
42
- $stderr.puts "process #{@native_debugger.pid} is currently in garbage collection phase."
43
- true
44
- else
45
- false
46
- end
47
- end
48
-
49
- def need_finish_frame
50
- bt = get_bt
51
- is_inside_malloc(bt) || is_inside_gc(bt)
52
- end
53
-
54
- end
1
+ require 'ruby-debug-ide/attach/native_debugger'
2
+
3
+ class ProcessThread
4
+
5
+ attr_reader :thread_num, :is_main, :thread_info, :last_bt
6
+
7
+ def initialize(thread_num, is_main, thread_info, native_debugger)
8
+ @thread_num = thread_num
9
+ @is_main = is_main
10
+ @native_debugger = native_debugger
11
+ @thread_info = thread_info
12
+ @last_bt = nil
13
+ end
14
+
15
+ def switch
16
+ @native_debugger.switch_to_thread(thread_num)
17
+ end
18
+
19
+ def finish
20
+ @native_debugger.execute 'finish'
21
+ end
22
+
23
+ def get_bt
24
+ @last_bt = @native_debugger.execute 'bt'
25
+ end
26
+
27
+ def any_caller_match(bt, pattern)
28
+ bt =~ /#{pattern}/
29
+ end
30
+
31
+ def is_inside_malloc(bt = get_bt)
32
+ if any_caller_match(bt, '(malloc)')
33
+ $stderr.puts "process #{@native_debugger.pid} is currently inside malloc."
34
+ true
35
+ else
36
+ false
37
+ end
38
+ end
39
+
40
+ def is_inside_gc(bt = get_bt)
41
+ if any_caller_match(bt, '(gc\.c)')
42
+ $stderr.puts "process #{@native_debugger.pid} is currently in garbage collection phase."
43
+ true
44
+ else
45
+ false
46
+ end
47
+ end
48
+
49
+ def need_finish_frame
50
+ bt = get_bt
51
+ is_inside_malloc(bt) || is_inside_gc(bt)
52
+ end
53
+
54
+ end