Module: Trepanning

Includes:
RemoteCommunication
Defined in:
app/file.rb,
app/run.rb,
app/client.rb,
app/method.rb

Overview

Copyright © 2010, 2013 Rocky Bernstein <[email protected]>

Defined Under Namespace

Modules: FileName, Method

Class Method Summary collapse

Class Method Details

.debug_program(dbgr, ruby_path, program_to_debug, start_opts = {}) ⇒ Object

Given a Ruby interpreter and program we are to debug, debug it. The caller must ensure that ARGV is set up to remove any debugger arguments or things that the debugged program isn’t supposed to see. FIXME: Should we make ARGV an explicit parameter?



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'app/run.rb', line 13

def debug_program(dbgr, ruby_path, program_to_debug, start_opts={})

  # Make sure Ruby script syntax checks okay.
  # Otherwise we get a load message that looks like trepanning has 
  # a problem. 
  output = `#{ruby_path} -c #{program_to_debug.inspect} 2>&1`
  if $?.exitstatus != 0 and RUBY_PLATFORM !~ /mswin/
    puts output
    exit $?.exitstatus 
  end
  # print "\032\032starting\n" if Trepan.annotate and Trepan.annotate > 2

  ## FIXME: put in fn.
  m = self.method(:debug_program).executable
  dbgr.processor.ignore_methods[m]='step'

  # m = Kernel.method(:load).executable
  # dbgr.processor.ignore_methods[m]='step'

  # Any frame from us or below should be hidden by default.
  hide_level = Rubinius::VM.backtrace(0, true).size+1

  old_dollar_0 = $0

  # Without the dance below to set $0, setting it to a signifcantly
  # longer value will truncate it in some OS's. See
  # http://www.ruby-forum.com/topic/187083
  $progname = program_to_debug
  alias $0 $progname
  ## dollar_0_tracker = lambda {|val| $program_name = val} 
  ## trace_var(:$0, dollar_0_tracker)

  ## FIXME: we gets lots of crap before we get to the real stuff.
  start_opts = {
    :skip_loader => true
  }.merge(start_opts)
  dbgr.start(start_opts)
  begin
    Kernel::load program_to_debug
  rescue Interrupt
  end

  # The dance we have to undo to restore $0 and undo the mess created
  # above.
  $0 = old_dollar_0
  ## untrace_var(:$0, dollar_0_tracker)
end

.start_client(options) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'app/client.rb', line 10

def start_client(options)
  puts "Client option given"
  user_opts = {}
  %w(readline).each do |opt|
    user_opts[opt.to_sym] = options[opt.to_sym]
  end
  dbgr = Trepan.new(:client      => true,
                    :cmdfiles    => [],
                    :initial_dir => options[:chdir],
                    :nx          => true,
                    :host        => options[:host],
                    :port        => options[:port],
                    :user_opts   => user_opts
                    )
  intf = dbgr.intf[-1]
  while true
    begin
      control_code, line = intf.read_remote
    rescue EOFError, Errno::EPIPE
      puts "Remote debugged process closed connection"
      break
    end
    # p [control_code, line]
    case control_code
    when PRINT

      # FIXME: don't know why server sometimes adds a gratuituous space.
      # the space is added somewhere inside TCPSocket.print
      line = line[0..-2] if line.end_with?("\n ")

      print line
    when CONFIRM_TRUE
      response = intf.confirm(line, true)
      intf.write_remote(CONFIRM_REPLY, response ? 'Y' : 'N')
    when CONFIRM_FALSE
      response = intf.confirm(line, true)
      intf.write_remote(CONFIRM_REPLY, response ? 'Y' : 'N')
    when PROMPT
      # Printing of prompt has been handled already by PRINT.
      begin
        command = intf.read_command(line)
      rescue EOFError
        puts "user-side EOF. Quitting..."
        break
      end
      begin 
        intf.write_remote(COMMAND, command)
      rescue Errno::EPIPE
        puts "Remote debugged process died"
        break
      end
    when QUIT
      break
    when RESTART
      break
    else
      $stderr.puts "** Unknown control code: #{control_code}"
    end
  end
end

.whence_file(prog_script) ⇒ Object

Do a shell-like path lookup for prog_script and return the results. If we can’t find anything return prog_script.



63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/run.rb', line 63

def whence_file(prog_script)
  if prog_script.start_with?(File::SEPARATOR) || prog_script.start_with?('.')
    # Don't search since this name has path is explicitly absolute or
    # relative.
    return prog_script
  end
  for dirname in ENV['PATH'].split(File::PATH_SEPARATOR) do
    prog_script_try = File.join(dirname, prog_script)
    return prog_script_try if File.readable?(prog_script_try)
  end
  # Failure
  return prog_script
end