readapt 1.4.4 → 2.0.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/rspec.yml +38 -0
- data/.gitignore +16 -16
- data/.rspec +2 -2
- data/.travis.yml +19 -19
- data/CHANGELOG.md +103 -100
- data/Gemfile +4 -4
- data/LICENSE.txt +21 -21
- data/README.md +37 -37
- data/Rakefile +14 -14
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/exe/readapt +5 -5
- data/ext/readapt/breakpoints.c +83 -83
- data/ext/readapt/breakpoints.h +11 -11
- data/ext/readapt/extconf.rb +0 -0
- data/ext/readapt/frame.c +137 -137
- data/ext/readapt/frame.h +17 -17
- data/ext/readapt/inspector.c +51 -51
- data/ext/readapt/inspector.h +8 -8
- data/ext/readapt/lookup_table.c +211 -211
- data/ext/readapt/lookup_table.h +30 -30
- data/ext/readapt/monitor.c +0 -0
- data/ext/readapt/monitor.h +0 -0
- data/ext/readapt/normalize.c +62 -62
- data/ext/readapt/normalize.h +7 -7
- data/ext/readapt/readapt.c +18 -18
- data/ext/readapt/stack.c +86 -86
- data/ext/readapt/stack.h +20 -20
- data/ext/readapt/threads.c +1 -1
- data/ext/readapt/threads.h +0 -0
- data/lib/readapt/adapter.rb +98 -98
- data/lib/readapt/breakpoint.rb +21 -21
- data/lib/readapt/data_reader.rb +62 -62
- data/lib/readapt/debugger.rb +227 -227
- data/lib/readapt/error.rb +63 -63
- data/lib/readapt/finder.rb +34 -34
- data/lib/readapt/frame.rb +40 -40
- data/lib/readapt/input.rb +7 -7
- data/lib/readapt/message/attach.rb +11 -11
- data/lib/readapt/message/base.rb +32 -32
- data/lib/readapt/message/configuration_done.rb +11 -11
- data/lib/readapt/message/continue.rb +15 -15
- data/lib/readapt/message/disconnect.rb +13 -13
- data/lib/readapt/message/evaluate.rb +19 -19
- data/lib/readapt/message/initialize.rb +21 -21
- data/lib/readapt/message/launch.rb +11 -11
- data/lib/readapt/message/next.rb +12 -12
- data/lib/readapt/message/pause.rb +11 -11
- data/lib/readapt/message/scopes.rb +26 -26
- data/lib/readapt/message/set_breakpoints.rb +25 -25
- data/lib/readapt/message/set_exception_breakpoints.rb +11 -11
- data/lib/readapt/message/stack_trace.rb +38 -38
- data/lib/readapt/message/step_in.rb +11 -11
- data/lib/readapt/message/step_out.rb +11 -11
- data/lib/readapt/message/threads.rb +18 -18
- data/lib/readapt/message/variables.rb +53 -53
- data/lib/readapt/message.rb +62 -62
- data/lib/readapt/monitor.rb +0 -0
- data/lib/readapt/output.rb +25 -25
- data/lib/readapt/references.rb +27 -27
- data/lib/readapt/server.rb +22 -22
- data/lib/readapt/shell.rb +104 -104
- data/lib/readapt/snapshot.rb +0 -0
- data/lib/readapt/thread.rb +20 -20
- data/lib/readapt/variable.rb +0 -0
- data/lib/readapt/version.rb +3 -3
- data/lib/readapt.rb +21 -21
- data/readapt.gemspec +39 -39
- metadata +8 -7
@@ -1,18 +1,18 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Readapt
|
4
|
-
module Message
|
5
|
-
class Threads < Base
|
6
|
-
def run
|
7
|
-
set_body({
|
8
|
-
threads: debugger.threads.map do |thr|
|
9
|
-
{
|
10
|
-
id: thr.id,
|
11
|
-
name: thr.name
|
12
|
-
}
|
13
|
-
end
|
14
|
-
})
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class Threads < Base
|
6
|
+
def run
|
7
|
+
set_body({
|
8
|
+
threads: debugger.threads.map do |thr|
|
9
|
+
{
|
10
|
+
id: thr.id,
|
11
|
+
name: thr.name
|
12
|
+
}
|
13
|
+
end
|
14
|
+
})
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,53 +1,53 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Readapt
|
4
|
-
module Message
|
5
|
-
class Variables < Base
|
6
|
-
def run
|
7
|
-
ref = arguments['variablesReference']
|
8
|
-
frame = debugger.frame(ref)
|
9
|
-
# @todo 1 is a magic number representing the toplevel binding (see
|
10
|
-
# Message::Scopes)
|
11
|
-
vars = if ref == 1
|
12
|
-
global_variables.map do |gv|
|
13
|
-
Variable.new(gv, eval(gv.to_s))
|
14
|
-
end
|
15
|
-
else
|
16
|
-
if frame != Frame::NULL_FRAME && !frame.nil?
|
17
|
-
frame.locals
|
18
|
-
else
|
19
|
-
obj = References.get(ref)
|
20
|
-
result = []
|
21
|
-
if obj.is_a?(Array)
|
22
|
-
obj.each_with_index do |itm, idx|
|
23
|
-
result.push Variable.new("[#{idx}]", itm)
|
24
|
-
end
|
25
|
-
elsif obj.is_a?(Hash)
|
26
|
-
obj.each_pair do |idx, itm|
|
27
|
-
result.push Variable.new("[#{idx}]", itm)
|
28
|
-
end
|
29
|
-
else
|
30
|
-
obj.instance_variables.sort.each do |iv|
|
31
|
-
result.push Variable.new(iv, obj.instance_variable_get(iv))
|
32
|
-
end
|
33
|
-
obj.class.class_variables.sort.each do |cv|
|
34
|
-
result.push Variable.new(cv, obj.class.class_variable_get(cv))
|
35
|
-
end
|
36
|
-
end
|
37
|
-
result
|
38
|
-
end
|
39
|
-
end
|
40
|
-
set_body({
|
41
|
-
variables: vars.map do |var|
|
42
|
-
{
|
43
|
-
name: var.name,
|
44
|
-
value: var.value,
|
45
|
-
type: var.type,
|
46
|
-
variablesReference: var.reference
|
47
|
-
}
|
48
|
-
end
|
49
|
-
})
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Readapt
|
4
|
+
module Message
|
5
|
+
class Variables < Base
|
6
|
+
def run
|
7
|
+
ref = arguments['variablesReference']
|
8
|
+
frame = debugger.frame(ref)
|
9
|
+
# @todo 1 is a magic number representing the toplevel binding (see
|
10
|
+
# Message::Scopes)
|
11
|
+
vars = if ref == 1
|
12
|
+
global_variables.map do |gv|
|
13
|
+
Variable.new(gv, eval(gv.to_s))
|
14
|
+
end
|
15
|
+
else
|
16
|
+
if frame != Frame::NULL_FRAME && !frame.nil?
|
17
|
+
frame.locals
|
18
|
+
else
|
19
|
+
obj = References.get(ref)
|
20
|
+
result = []
|
21
|
+
if obj.is_a?(Array)
|
22
|
+
obj.each_with_index do |itm, idx|
|
23
|
+
result.push Variable.new("[#{idx}]", itm)
|
24
|
+
end
|
25
|
+
elsif obj.is_a?(Hash)
|
26
|
+
obj.each_pair do |idx, itm|
|
27
|
+
result.push Variable.new("[#{idx}]", itm)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
obj.instance_variables.sort.each do |iv|
|
31
|
+
result.push Variable.new(iv, obj.instance_variable_get(iv))
|
32
|
+
end
|
33
|
+
obj.class.class_variables.sort.each do |cv|
|
34
|
+
result.push Variable.new(cv, obj.class.class_variable_get(cv))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
set_body({
|
41
|
+
variables: vars.map do |var|
|
42
|
+
{
|
43
|
+
name: var.name,
|
44
|
+
value: var.value,
|
45
|
+
type: var.type,
|
46
|
+
variablesReference: var.reference
|
47
|
+
}
|
48
|
+
end
|
49
|
+
})
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/readapt/message.rb
CHANGED
@@ -1,62 +1,62 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'readapt/message/base'
|
4
|
-
require 'readapt/message/initialize'
|
5
|
-
require 'readapt/message/launch'
|
6
|
-
require 'readapt/message/set_breakpoints'
|
7
|
-
require 'readapt/message/set_exception_breakpoints'
|
8
|
-
require 'readapt/message/configuration_done'
|
9
|
-
require 'readapt/message/threads'
|
10
|
-
require 'readapt/message/stack_trace'
|
11
|
-
require 'readapt/message/scopes'
|
12
|
-
require 'readapt/message/continue'
|
13
|
-
require 'readapt/message/variables'
|
14
|
-
require 'readapt/message/next'
|
15
|
-
require 'readapt/message/step_in'
|
16
|
-
require 'readapt/message/step_out'
|
17
|
-
require 'readapt/message/disconnect'
|
18
|
-
require 'readapt/message/attach'
|
19
|
-
require 'readapt/message/pause'
|
20
|
-
require 'readapt/message/evaluate'
|
21
|
-
|
22
|
-
module Readapt
|
23
|
-
module Message
|
24
|
-
@@messages = {}
|
25
|
-
@@seq = 0
|
26
|
-
|
27
|
-
def self.register name, klass
|
28
|
-
@@messages[name] = klass
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.process arguments, debugger
|
32
|
-
klass = @@messages[arguments['command']]
|
33
|
-
if klass.nil?
|
34
|
-
STDERR.puts "Debugger received unrecognized command `#{arguments['command']}`"
|
35
|
-
Message::Base.new(arguments, debugger)
|
36
|
-
else
|
37
|
-
message = klass.new(arguments['arguments'], debugger)
|
38
|
-
message.run
|
39
|
-
message
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
register 'initialize', Message::Initialize
|
44
|
-
register 'attach', Message::Attach
|
45
|
-
register 'launch', Message::Launch
|
46
|
-
register 'setBreakpoints', Message::SetBreakpoints
|
47
|
-
register 'setExceptionBreakpoints', Message::SetExceptionBreakpoints
|
48
|
-
register 'configurationDone', Message::ConfigurationDone
|
49
|
-
register 'threads', Message::Threads
|
50
|
-
register 'stackTrace', Message::StackTrace
|
51
|
-
register 'scopes', Message::Scopes
|
52
|
-
register 'continue', Message::Continue
|
53
|
-
register 'variables', Message::Variables
|
54
|
-
register 'next', Message::Next
|
55
|
-
register 'stepIn', Message::StepIn
|
56
|
-
register 'stepOut', Message::StepOut
|
57
|
-
register 'disconnect', Message::Disconnect
|
58
|
-
register 'pause', Message::Pause
|
59
|
-
register 'evaluate', Message::Evaluate
|
60
|
-
# register 'source', Message::Base # @todo Placeholder
|
61
|
-
end
|
62
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'readapt/message/base'
|
4
|
+
require 'readapt/message/initialize'
|
5
|
+
require 'readapt/message/launch'
|
6
|
+
require 'readapt/message/set_breakpoints'
|
7
|
+
require 'readapt/message/set_exception_breakpoints'
|
8
|
+
require 'readapt/message/configuration_done'
|
9
|
+
require 'readapt/message/threads'
|
10
|
+
require 'readapt/message/stack_trace'
|
11
|
+
require 'readapt/message/scopes'
|
12
|
+
require 'readapt/message/continue'
|
13
|
+
require 'readapt/message/variables'
|
14
|
+
require 'readapt/message/next'
|
15
|
+
require 'readapt/message/step_in'
|
16
|
+
require 'readapt/message/step_out'
|
17
|
+
require 'readapt/message/disconnect'
|
18
|
+
require 'readapt/message/attach'
|
19
|
+
require 'readapt/message/pause'
|
20
|
+
require 'readapt/message/evaluate'
|
21
|
+
|
22
|
+
module Readapt
|
23
|
+
module Message
|
24
|
+
@@messages = {}
|
25
|
+
@@seq = 0
|
26
|
+
|
27
|
+
def self.register name, klass
|
28
|
+
@@messages[name] = klass
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.process arguments, debugger
|
32
|
+
klass = @@messages[arguments['command']]
|
33
|
+
if klass.nil?
|
34
|
+
STDERR.puts "Debugger received unrecognized command `#{arguments['command']}`"
|
35
|
+
Message::Base.new(arguments, debugger)
|
36
|
+
else
|
37
|
+
message = klass.new(arguments['arguments'], debugger)
|
38
|
+
message.run
|
39
|
+
message
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
register 'initialize', Message::Initialize
|
44
|
+
register 'attach', Message::Attach
|
45
|
+
register 'launch', Message::Launch
|
46
|
+
register 'setBreakpoints', Message::SetBreakpoints
|
47
|
+
register 'setExceptionBreakpoints', Message::SetExceptionBreakpoints
|
48
|
+
register 'configurationDone', Message::ConfigurationDone
|
49
|
+
register 'threads', Message::Threads
|
50
|
+
register 'stackTrace', Message::StackTrace
|
51
|
+
register 'scopes', Message::Scopes
|
52
|
+
register 'continue', Message::Continue
|
53
|
+
register 'variables', Message::Variables
|
54
|
+
register 'next', Message::Next
|
55
|
+
register 'stepIn', Message::StepIn
|
56
|
+
register 'stepOut', Message::StepOut
|
57
|
+
register 'disconnect', Message::Disconnect
|
58
|
+
register 'pause', Message::Pause
|
59
|
+
register 'evaluate', Message::Evaluate
|
60
|
+
# register 'source', Message::Base # @todo Placeholder
|
61
|
+
end
|
62
|
+
end
|
data/lib/readapt/monitor.rb
CHANGED
File without changes
|
data/lib/readapt/output.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
module Readapt
|
2
|
-
module Output
|
3
|
-
class << self
|
4
|
-
attr_accessor :adapter
|
5
|
-
end
|
6
|
-
|
7
|
-
def receiving data
|
8
|
-
send_event('output', {
|
9
|
-
output: data.force_encoding('utf-8'),
|
10
|
-
category: 'stdout'
|
11
|
-
})
|
12
|
-
end
|
13
|
-
|
14
|
-
def send_event event, data
|
15
|
-
obj = {
|
16
|
-
type: 'event',
|
17
|
-
event: event
|
18
|
-
}
|
19
|
-
obj[:body] = data unless data.nil?
|
20
|
-
json = obj.to_json
|
21
|
-
envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
|
22
|
-
Output.adapter.write envelope
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
1
|
+
module Readapt
|
2
|
+
module Output
|
3
|
+
class << self
|
4
|
+
attr_accessor :adapter
|
5
|
+
end
|
6
|
+
|
7
|
+
def receiving data
|
8
|
+
send_event('output', {
|
9
|
+
output: data.force_encoding('utf-8'),
|
10
|
+
category: 'stdout'
|
11
|
+
})
|
12
|
+
end
|
13
|
+
|
14
|
+
def send_event event, data
|
15
|
+
obj = {
|
16
|
+
type: 'event',
|
17
|
+
event: event
|
18
|
+
}
|
19
|
+
obj[:body] = data unless data.nil?
|
20
|
+
json = obj.to_json
|
21
|
+
envelope = "Content-Length: #{json.bytesize}\r\n\r\n#{json}"
|
22
|
+
Output.adapter.write envelope
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/readapt/references.rb
CHANGED
@@ -1,27 +1,27 @@
|
|
1
|
-
module Readapt
|
2
|
-
module References
|
3
|
-
module_function
|
4
|
-
|
5
|
-
@variable_reference_map = {}
|
6
|
-
@reference_variable_map = {}
|
7
|
-
@reference_id = 1000
|
8
|
-
|
9
|
-
def clear
|
10
|
-
@variable_reference_map.clear
|
11
|
-
@reference_variable_map.clear
|
12
|
-
@reference_id = 1000
|
13
|
-
end
|
14
|
-
|
15
|
-
def identify object
|
16
|
-
return @variable_reference_map[object] if @variable_reference_map.has_key?(object)
|
17
|
-
@reference_id += 1
|
18
|
-
@variable_reference_map[object] = @reference_id
|
19
|
-
@reference_variable_map[@reference_id] = object
|
20
|
-
@reference_id
|
21
|
-
end
|
22
|
-
|
23
|
-
def get id
|
24
|
-
@reference_variable_map[id]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
1
|
+
module Readapt
|
2
|
+
module References
|
3
|
+
module_function
|
4
|
+
|
5
|
+
@variable_reference_map = {}
|
6
|
+
@reference_variable_map = {}
|
7
|
+
@reference_id = 1000
|
8
|
+
|
9
|
+
def clear
|
10
|
+
@variable_reference_map.clear
|
11
|
+
@reference_variable_map.clear
|
12
|
+
@reference_id = 1000
|
13
|
+
end
|
14
|
+
|
15
|
+
def identify object
|
16
|
+
return @variable_reference_map[object] if @variable_reference_map.has_key?(object)
|
17
|
+
@reference_id += 1
|
18
|
+
@variable_reference_map[object] = @reference_id
|
19
|
+
@reference_variable_map[@reference_id] = object
|
20
|
+
@reference_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def get id
|
24
|
+
@reference_variable_map[id]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/readapt/server.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
module Readapt
|
5
|
-
module Server
|
6
|
-
class << self
|
7
|
-
attr_accessor :target_in
|
8
|
-
attr_accessor :target_pid
|
9
|
-
end
|
10
|
-
|
11
|
-
def opening
|
12
|
-
Error.adapter = self
|
13
|
-
Output.adapter = self
|
14
|
-
end
|
15
|
-
|
16
|
-
def receiving data
|
17
|
-
Server.target_in.syswrite data
|
18
|
-
rescue Errno::EPIPE, IOError
|
19
|
-
close
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
1
|
+
require 'securerandom'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module Readapt
|
5
|
+
module Server
|
6
|
+
class << self
|
7
|
+
attr_accessor :target_in
|
8
|
+
attr_accessor :target_pid
|
9
|
+
end
|
10
|
+
|
11
|
+
def opening
|
12
|
+
Error.adapter = self
|
13
|
+
Output.adapter = self
|
14
|
+
end
|
15
|
+
|
16
|
+
def receiving data
|
17
|
+
Server.target_in.syswrite data
|
18
|
+
rescue Errno::EPIPE, IOError
|
19
|
+
close
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/readapt/shell.rb
CHANGED
@@ -1,104 +1,104 @@
|
|
1
|
-
require 'thor'
|
2
|
-
require 'backport'
|
3
|
-
require 'open3'
|
4
|
-
require 'securerandom'
|
5
|
-
require 'socket'
|
6
|
-
|
7
|
-
module Readapt
|
8
|
-
class Shell < Thor
|
9
|
-
map %w[--version -v] => :version
|
10
|
-
|
11
|
-
desc "--version, -v", "Print the version"
|
12
|
-
def version
|
13
|
-
puts Readapt::VERSION
|
14
|
-
end
|
15
|
-
|
16
|
-
desc 'socket', 'Run a DAP server over TCP'
|
17
|
-
option :host, type: :string, aliases: :h, description: 'The server host', default: '127.0.0.1'
|
18
|
-
option :port, type: :numeric, aliases: :p, description: 'The server port', default: 1234
|
19
|
-
def socket
|
20
|
-
machine = Backport::Machine.new
|
21
|
-
machine.run do
|
22
|
-
prepare_machine machine
|
23
|
-
server = Backport::Server::Tcpip.new(host: options[:host], port: options[:port], adapter: Readapt::Server)
|
24
|
-
machine.prepare server
|
25
|
-
STDERR.puts "Readapt Debugger #{Readapt::VERSION} is listening HOST=#{options[:host]} PORT=#{options[:port]} PID=#{Process.pid}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
map serve: :socket
|
29
|
-
|
30
|
-
desc 'stdio', 'Run a DAP server over STDIO'
|
31
|
-
def stdio
|
32
|
-
machine = Backport::Machine.new
|
33
|
-
machine.run do
|
34
|
-
prepare_machine machine
|
35
|
-
server = Backport::Server::Stdio.new(adapter: Readapt::Server)
|
36
|
-
machine.prepare server
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
desc 'target [PROCID]', 'Run a target process'
|
41
|
-
def target procid = nil
|
42
|
-
STDIN.binmode
|
43
|
-
STDOUT.binmode
|
44
|
-
STDERR.binmode
|
45
|
-
STDOUT.sync = true
|
46
|
-
STDERR.sync = true
|
47
|
-
Readapt::Adapter.procid = procid
|
48
|
-
machine = Backport::Machine.new
|
49
|
-
Signal.trap("INT") do
|
50
|
-
graceful_shutdown machine
|
51
|
-
end
|
52
|
-
Signal.trap("TERM") do
|
53
|
-
graceful_shutdown machine
|
54
|
-
end
|
55
|
-
machine.run do
|
56
|
-
debugger = Readapt::Debugger.new
|
57
|
-
Readapt::Adapter.host debugger
|
58
|
-
machine.prepare Backport::Server::Stdio.new(input: STDIN, output: STDERR, adapter: Readapt::Adapter)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
# @param machine [Backport::Machine]
|
65
|
-
# @return [void]
|
66
|
-
def prepare_machine machine
|
67
|
-
STDOUT.sync = true
|
68
|
-
STDERR.sync = true
|
69
|
-
Signal.trap("INT") do
|
70
|
-
graceful_shutdown machine
|
71
|
-
end
|
72
|
-
Signal.trap("TERM") do
|
73
|
-
graceful_shutdown machine
|
74
|
-
end
|
75
|
-
procid = SecureRandom.hex(8)
|
76
|
-
Readapt::Error.procid = procid
|
77
|
-
stdin, stdout, stderr, thr = Open3.popen3('ruby', $0, 'target', procid)
|
78
|
-
stdin.sync = true
|
79
|
-
stdout.sync = true
|
80
|
-
stderr.sync = true
|
81
|
-
stdin.binmode
|
82
|
-
Readapt::Server.target_in = stdin
|
83
|
-
Readapt::Server.target_pid = thr[:pid]
|
84
|
-
output = Backport::Server::Stdio.new(input: stdout, output: stdin, adapter: Readapt::Output)
|
85
|
-
error = Backport::Server::Stdio.new(input: stderr, output: stdin, adapter: Readapt::Error)
|
86
|
-
machine.prepare output
|
87
|
-
machine.prepare error
|
88
|
-
at_exit do
|
89
|
-
begin
|
90
|
-
Process.kill 'KILL', thr[:pid]
|
91
|
-
rescue Errno::ESRCH
|
92
|
-
# Ignore
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
# @param machine [Backport::Machine]
|
98
|
-
# @return [void]
|
99
|
-
def graceful_shutdown machine
|
100
|
-
machine.stop
|
101
|
-
exit
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
1
|
+
require 'thor'
|
2
|
+
require 'backport'
|
3
|
+
require 'open3'
|
4
|
+
require 'securerandom'
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
module Readapt
|
8
|
+
class Shell < Thor
|
9
|
+
map %w[--version -v] => :version
|
10
|
+
|
11
|
+
desc "--version, -v", "Print the version"
|
12
|
+
def version
|
13
|
+
puts Readapt::VERSION
|
14
|
+
end
|
15
|
+
|
16
|
+
desc 'socket', 'Run a DAP server over TCP'
|
17
|
+
option :host, type: :string, aliases: :h, description: 'The server host', default: '127.0.0.1'
|
18
|
+
option :port, type: :numeric, aliases: :p, description: 'The server port', default: 1234
|
19
|
+
def socket
|
20
|
+
machine = Backport::Machine.new
|
21
|
+
machine.run do
|
22
|
+
prepare_machine machine
|
23
|
+
server = Backport::Server::Tcpip.new(host: options[:host], port: options[:port], adapter: Readapt::Server)
|
24
|
+
machine.prepare server
|
25
|
+
STDERR.puts "Readapt Debugger #{Readapt::VERSION} is listening HOST=#{options[:host]} PORT=#{options[:port]} PID=#{Process.pid}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
map serve: :socket
|
29
|
+
|
30
|
+
desc 'stdio', 'Run a DAP server over STDIO'
|
31
|
+
def stdio
|
32
|
+
machine = Backport::Machine.new
|
33
|
+
machine.run do
|
34
|
+
prepare_machine machine
|
35
|
+
server = Backport::Server::Stdio.new(adapter: Readapt::Server)
|
36
|
+
machine.prepare server
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'target [PROCID]', 'Run a target process'
|
41
|
+
def target procid = nil
|
42
|
+
STDIN.binmode
|
43
|
+
STDOUT.binmode
|
44
|
+
STDERR.binmode
|
45
|
+
STDOUT.sync = true
|
46
|
+
STDERR.sync = true
|
47
|
+
Readapt::Adapter.procid = procid
|
48
|
+
machine = Backport::Machine.new
|
49
|
+
Signal.trap("INT") do
|
50
|
+
graceful_shutdown machine
|
51
|
+
end
|
52
|
+
Signal.trap("TERM") do
|
53
|
+
graceful_shutdown machine
|
54
|
+
end
|
55
|
+
machine.run do
|
56
|
+
debugger = Readapt::Debugger.new
|
57
|
+
Readapt::Adapter.host debugger
|
58
|
+
machine.prepare Backport::Server::Stdio.new(input: STDIN, output: STDERR, adapter: Readapt::Adapter)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# @param machine [Backport::Machine]
|
65
|
+
# @return [void]
|
66
|
+
def prepare_machine machine
|
67
|
+
STDOUT.sync = true
|
68
|
+
STDERR.sync = true
|
69
|
+
Signal.trap("INT") do
|
70
|
+
graceful_shutdown machine
|
71
|
+
end
|
72
|
+
Signal.trap("TERM") do
|
73
|
+
graceful_shutdown machine
|
74
|
+
end
|
75
|
+
procid = SecureRandom.hex(8)
|
76
|
+
Readapt::Error.procid = procid
|
77
|
+
stdin, stdout, stderr, thr = Open3.popen3('ruby', $0, 'target', procid)
|
78
|
+
stdin.sync = true
|
79
|
+
stdout.sync = true
|
80
|
+
stderr.sync = true
|
81
|
+
stdin.binmode
|
82
|
+
Readapt::Server.target_in = stdin
|
83
|
+
Readapt::Server.target_pid = thr[:pid]
|
84
|
+
output = Backport::Server::Stdio.new(input: stdout, output: stdin, adapter: Readapt::Output)
|
85
|
+
error = Backport::Server::Stdio.new(input: stderr, output: stdin, adapter: Readapt::Error)
|
86
|
+
machine.prepare output
|
87
|
+
machine.prepare error
|
88
|
+
at_exit do
|
89
|
+
begin
|
90
|
+
Process.kill 'KILL', thr[:pid]
|
91
|
+
rescue Errno::ESRCH
|
92
|
+
# Ignore
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @param machine [Backport::Machine]
|
98
|
+
# @return [void]
|
99
|
+
def graceful_shutdown machine
|
100
|
+
machine.stop
|
101
|
+
exit
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/readapt/snapshot.rb
CHANGED
File without changes
|
data/lib/readapt/thread.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
module Readapt
|
6
|
-
class Thread
|
7
|
-
# @return [Symbol]
|
8
|
-
attr_accessor :control
|
9
|
-
|
10
|
-
# @return [String]
|
11
|
-
def name
|
12
|
-
@name ||= "Thread #{id}"
|
13
|
-
end
|
14
|
-
|
15
|
-
# # @return [Object]
|
16
|
-
def object
|
17
|
-
ObjectSpace._id2ref(thread_object_id)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module Readapt
|
6
|
+
class Thread
|
7
|
+
# @return [Symbol]
|
8
|
+
attr_accessor :control
|
9
|
+
|
10
|
+
# @return [String]
|
11
|
+
def name
|
12
|
+
@name ||= "Thread #{id}"
|
13
|
+
end
|
14
|
+
|
15
|
+
# # @return [Object]
|
16
|
+
def object
|
17
|
+
ObjectSpace._id2ref(thread_object_id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|