readapt 1.4.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec.yml +38 -0
  3. data/.gitignore +16 -16
  4. data/.rspec +2 -2
  5. data/.travis.yml +19 -19
  6. data/CHANGELOG.md +103 -100
  7. data/Gemfile +4 -4
  8. data/LICENSE.txt +21 -21
  9. data/README.md +37 -37
  10. data/Rakefile +14 -14
  11. data/bin/console +14 -14
  12. data/bin/setup +8 -8
  13. data/exe/readapt +5 -5
  14. data/ext/readapt/breakpoints.c +83 -83
  15. data/ext/readapt/breakpoints.h +11 -11
  16. data/ext/readapt/extconf.rb +0 -0
  17. data/ext/readapt/frame.c +137 -137
  18. data/ext/readapt/frame.h +17 -17
  19. data/ext/readapt/inspector.c +51 -51
  20. data/ext/readapt/inspector.h +8 -8
  21. data/ext/readapt/lookup_table.c +211 -211
  22. data/ext/readapt/lookup_table.h +30 -30
  23. data/ext/readapt/monitor.c +0 -0
  24. data/ext/readapt/monitor.h +0 -0
  25. data/ext/readapt/normalize.c +62 -62
  26. data/ext/readapt/normalize.h +7 -7
  27. data/ext/readapt/readapt.c +18 -18
  28. data/ext/readapt/stack.c +86 -86
  29. data/ext/readapt/stack.h +20 -20
  30. data/ext/readapt/threads.c +1 -1
  31. data/ext/readapt/threads.h +0 -0
  32. data/lib/readapt/adapter.rb +98 -98
  33. data/lib/readapt/breakpoint.rb +21 -21
  34. data/lib/readapt/data_reader.rb +62 -62
  35. data/lib/readapt/debugger.rb +227 -227
  36. data/lib/readapt/error.rb +63 -63
  37. data/lib/readapt/finder.rb +34 -34
  38. data/lib/readapt/frame.rb +40 -40
  39. data/lib/readapt/input.rb +7 -7
  40. data/lib/readapt/message/attach.rb +11 -11
  41. data/lib/readapt/message/base.rb +32 -32
  42. data/lib/readapt/message/configuration_done.rb +11 -11
  43. data/lib/readapt/message/continue.rb +15 -15
  44. data/lib/readapt/message/disconnect.rb +13 -13
  45. data/lib/readapt/message/evaluate.rb +19 -19
  46. data/lib/readapt/message/initialize.rb +21 -21
  47. data/lib/readapt/message/launch.rb +11 -11
  48. data/lib/readapt/message/next.rb +12 -12
  49. data/lib/readapt/message/pause.rb +11 -11
  50. data/lib/readapt/message/scopes.rb +26 -26
  51. data/lib/readapt/message/set_breakpoints.rb +25 -25
  52. data/lib/readapt/message/set_exception_breakpoints.rb +11 -11
  53. data/lib/readapt/message/stack_trace.rb +38 -38
  54. data/lib/readapt/message/step_in.rb +11 -11
  55. data/lib/readapt/message/step_out.rb +11 -11
  56. data/lib/readapt/message/threads.rb +18 -18
  57. data/lib/readapt/message/variables.rb +53 -53
  58. data/lib/readapt/message.rb +62 -62
  59. data/lib/readapt/monitor.rb +0 -0
  60. data/lib/readapt/output.rb +25 -25
  61. data/lib/readapt/references.rb +27 -27
  62. data/lib/readapt/server.rb +22 -22
  63. data/lib/readapt/shell.rb +104 -104
  64. data/lib/readapt/snapshot.rb +0 -0
  65. data/lib/readapt/thread.rb +20 -20
  66. data/lib/readapt/variable.rb +0 -0
  67. data/lib/readapt/version.rb +3 -3
  68. data/lib/readapt.rb +21 -21
  69. data/readapt.gemspec +39 -39
  70. 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
@@ -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
File without changes
@@ -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
@@ -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
@@ -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
File without changes
@@ -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