Skip to content

Commit 36d3686

Browse files
equivalence1dmitrii.kravchenko
authored andcommitted
some cosmetic changes + choosing with debugger to use
1 parent 32f61fe commit 36d3686

File tree

3 files changed

+53
-41
lines changed

3 files changed

+53
-41
lines changed

bin/gdb_wrapper

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,19 @@ end
5959
require 'ruby-debug-ide/greeter'
6060
Debugger::print_greeting_msg(nil, nil)
6161

62-
# this class is some kind of "interface"
6362
class NativeDebugger
6463

65-
attr_reader :pid, :last_bt
64+
attr_reader :pid, :main_thread, :process_threads
6665

6766
# @param executable -- path to ruby interpreter
6867
# @param pid -- pid of process you want to debug
6968
# @param options -- flags you want to specify to your debugger as a string (e.g. "-nx -nh" for gdb to disable .gdbinit)
7069
def initialize(executable, pid, options)
7170
@pid = pid
72-
@main_thread = nil
7371
@delimiter = '__OUTPUT_FINISHED__' # for getting response
74-
@last_bt = '' # to shaw it to user
72+
@tbreak = '__func_to_set_breakpoint_at'
73+
@main_thread = nil
74+
@process_threads = nil
7575

7676
launch_string = "#{self} #{executable} #{options}"
7777
@pipe = IO.popen(launch_string, 'r+')
@@ -90,9 +90,6 @@ class NativeDebugger
9090
return ''
9191
end
9292
response = get_response
93-
if command == 'bt'
94-
@last_bt = response
95-
end
9693
$stdout.puts "response for #{command}:\n#{response}\n\n\n\n"
9794
response
9895
end
@@ -106,7 +103,7 @@ class NativeDebugger
106103
line = @pipe.readline
107104
$stderr.puts line
108105
next if line =~ /\(lldb\)/ # lldb repeats your input to its output
109-
break if line =~ /\$\d+\s=\s"__OUTPUT_FINISHED__"/
106+
break if line =~ /\$\d+\s=\s"#{@delimiter}"/
110107
content += line
111108
end
112109
content
@@ -129,10 +126,12 @@ class NativeDebugger
129126
end
130127

131128
def continue
129+
$stdout.puts 'continuing'
132130
@pipe.puts 'c'
133131
loop do
134132
line = @pipe.readline
135-
break if line =~ /__func_to_set_breakpoint_at/
133+
$stderr.puts line
134+
break if line =~ /#{Regexp.escape(@tbreak)}/
136135
end
137136
get_response
138137
end
@@ -142,6 +141,15 @@ class NativeDebugger
142141
@main_thread.switch
143142
end
144143

144+
def wait_line_event
145+
call_start_attach
146+
continue
147+
end
148+
149+
def load_debugger
150+
execute "call rb_eval_string_protect(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\", (int *)0)"
151+
end
152+
145153
def exit
146154
execute 'q'
147155
end
@@ -163,20 +171,20 @@ class LLDB < NativeDebugger
163171
end
164172

165173
def update_threads
166-
process_threads = []
174+
@process_threads = []
167175
info_threads = (execute 'thread list').split("\n")
168176
info_threads.each do |thread_info|
169177
next unless thread_info =~ /[\s*]*thread\s#\d+.*/
170178
$stdout.puts "thread_info: #{thread_info}"
171179
is_main = thread_info[0] == '*'
172180
thread_num = thread_info.sub(/[\s*]*thread\s#/, '').sub(/:\s.*$/, '').to_i
173-
thread = ProcessThread.new(thread_num, is_main, self)
181+
thread = ProcessThread.new(thread_num, is_main, thread_info, self)
174182
if thread.is_main
175183
@main_thread = thread
176184
end
177-
process_threads << thread
185+
@process_threads << thread
178186
end
179-
process_threads
187+
@process_threads
180188
end
181189

182190
def check_already_under_debug
@@ -191,11 +199,12 @@ class LLDB < NativeDebugger
191199
def call_start_attach
192200
super()
193201
execute "expr (void *) dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)"
194-
execute "call start_attach(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\")"
202+
execute 'call start_attach()'
203+
set_tbreak(@tbreak)
195204
end
196205

197206
def to_s
198-
'lldb-3.8'
207+
'lldb'
199208
end
200209

201210
end
@@ -212,22 +221,20 @@ class GDB < NativeDebugger
212221
end
213222

214223
def update_threads
215-
process_threads = []
224+
@process_threads = []
216225
info_threads = (execute 'info threads').split("\n")
217-
# each thread info looks like this:
218-
# 3 Thread 0x7ff535405700 (LWP 8291) "ruby-timer-thr" 0x00007ff534a15fdd in poll () at ../sysdeps/unix/syscall-template.S:81
219226
info_threads.each do |thread_info|
220227
next unless thread_info =~ /[\s*]*\d+\s+Thread.*/
221228
$stdout.puts "thread_info: #{thread_info}"
222229
is_main = thread_info[0] == '*'
223230
thread_num = thread_info.sub(/[\s*]*/, '').sub(/\s.*$/, '').to_i
224-
thread = ProcessThread.new(thread_num, is_main, self)
231+
thread = ProcessThread.new(thread_num, is_main, thread_info, self)
225232
if thread.is_main
226233
@main_thread = thread
227234
end
228-
process_threads << thread
235+
@process_threads << thread
229236
end
230-
process_threads
237+
@process_threads
231238
end
232239

233240
def check_already_under_debug
@@ -242,7 +249,8 @@ class GDB < NativeDebugger
242249
def call_start_attach
243250
super()
244251
execute "call dlopen(\"/home/equi/Job/JetBrains/Internship_2016/ruby-debug-ide/ext/libAttach.so\", 2)"
245-
execute "call start_attach(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\")"
252+
execute 'call start_attach()'
253+
set_tbreak(@tbreak)
246254
end
247255

248256
def to_s
@@ -253,12 +261,14 @@ end
253261

254262
class ProcessThread
255263

256-
attr_reader :thread_num, :is_main
264+
attr_reader :thread_num, :is_main, :thread_info, :last_bt
257265

258-
def initialize(thread_num, is_main, native_debugger)
266+
def initialize(thread_num, is_main, thread_info, native_debugger)
259267
@thread_num = thread_num
260268
@is_main = is_main
261269
@native_debugger = native_debugger
270+
@thread_info = thread_info
271+
@last_bt = nil
262272
end
263273

264274
def switch
@@ -270,7 +280,7 @@ class ProcessThread
270280
end
271281

272282
def get_bt
273-
@native_debugger.execute 'bt'
283+
@last_bt = @native_debugger.execute 'bt'
274284
end
275285

276286
def any_caller_match(bt, pattern)
@@ -302,11 +312,19 @@ class ProcessThread
302312

303313
end
304314

315+
def exists_command(command)
316+
`command -v #{command} >/dev/null 2>&1 || { exit 1; }`
317+
$?.exitstatus == 0
318+
end
319+
305320
def choose_debugger
306-
if true
321+
$stderr.puts "exists: #{exists_command('gdb')}, #{exists_command('lldb')}"
322+
if exists_command('gdb')
307323
GDB.new(@options.ruby_path, @options.pid, '-nh -nx')
308-
else
324+
elsif exists_command('lldb')
309325
LLDB.new(@options.ruby_path, @options.pid, '--no-lldbinit')
326+
else
327+
raise 'Neither gdb nor lldb was found. Aborting.'
310328
end
311329
end
312330

@@ -333,14 +351,14 @@ while should_check_threads_state
333351
end
334352
end
335353

336-
gdb.call_start_attach
337-
gdb.set_tbreak('__func_to_set_breakpoint_at')
338-
gdb.continue
339-
gdb.execute "call rb_eval_string_protect(\"require '#{$path_to_debugger_loader}'; load_debugger(#{$gems_to_include.gsub("\"", "'")}, #{$argv.gsub("\"", "'")})\", (int *)0)"
354+
gdb.wait_line_event
355+
gdb.load_debugger
340356
gdb.exit
341357

342358
trap('INT') do
343-
$stderr.puts "Last backtrace:\n#{gdb.last_bt}"
359+
gdb.process_threads.each do |thread|
360+
$stderr.puts "Last backtrace for thread #{thread.thread_info}:\n#{thread.last_bt}"
361+
end
344362
exit!
345363
end
346364

ext/do_attach.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#include "do_attach.h"
22

3-
static const char *_command_to_eval;
4-
53
static int
64
__check_gc(void)
75
{
@@ -29,17 +27,13 @@ __catch_line_event(rb_event_flag_t evflag, VALUE data, VALUE self, ID mid, VALUE
2927
if (__check_gc())
3028
return;
3129
__func_to_set_breakpoint_at();
32-
// rb_eval_string_protect(_command_to_eval, NULL); // TODO pass something more useful than NULL
3330
}
3431

3532
int
36-
start_attach(const char* command)
33+
start_attach()
3734
{
38-
rb_eval_string("puts 'bla bla bla'");
39-
_command_to_eval = command;
4035
if (__check_gc())
4136
return 1;
42-
rb_global_variable((VALUE *) _command_to_eval);
4337
rb_add_event_hook(__catch_line_event, RUBY_EVENT_LINE, (VALUE) NULL);
44-
return 2323;
38+
return 0;
4539
}

ext/do_attach.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
#include <ruby/debug.h>
66
#include <stdio.h>
77

8-
int start_attach(const char *command);
8+
int start_attach();
99

1010
#endif //__DO_ATTACH_H__

0 commit comments

Comments
 (0)