debug 1.0.0.beta3 → 1.0.0.beta4
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/.gitignore +1 -0
- data/CONTRIBUTING.md +97 -0
- data/Gemfile +1 -1
- data/README.md +18 -14
- data/TODO.md +33 -0
- data/ext/debug/debug.c +1 -1
- data/lib/debug.rb +1 -1
- data/lib/debug/breakpoint.rb +6 -2
- data/lib/debug/config.rb +42 -13
- data/lib/debug/frame_info.rb +113 -0
- data/lib/debug/server.rb +11 -20
- data/lib/debug/session.rb +65 -34
- data/lib/debug/source_repository.rb +36 -6
- data/lib/debug/thread_client.rb +40 -113
- data/lib/debug/version.rb +1 -1
- data/misc/README.md.erb +5 -2
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ebaae12c10e51036f850fd1cbcde66d891a1e50b64bc5d96bfdab610cb42fd1d
|
4
|
+
data.tar.gz: e62eee365aa1409c650049ccb8ed237854aeed6f7a066dc2b84f96c9cffefd12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2aa2b044268220dc79d72850f6366474fff647fa6893360044ce64a8a97e4d759e414da6c39dac52a6b33593512675091ed4fb4a7399c1357b344d342f3c812f
|
7
|
+
data.tar.gz: 506d0afeb3e3926da6631e99234fd2ba4c96220d5def5a95d0e51afa54ae28beb19c30873c3c0cf9a95fa975023364f7088a0190d26452e307e715925e21a78c
|
data/.gitignore
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
## Manually Test Your Changes
|
2
|
+
|
3
|
+
You can manually test your changes with a simple Ruby script + a line of command. The following example will help you check:
|
4
|
+
|
5
|
+
- Breakpoint insertion.
|
6
|
+
- Resume from the breakpoint.
|
7
|
+
- Backtrace display.
|
8
|
+
- Information (local variables, ivars..etc.) display.
|
9
|
+
- Debugger exit.
|
10
|
+
|
11
|
+
|
12
|
+
### Script
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
# target.rb
|
16
|
+
class Foo
|
17
|
+
def first_call
|
18
|
+
second_call(20)
|
19
|
+
end
|
20
|
+
|
21
|
+
def second_call(num)
|
22
|
+
third_call_with_block do |ten|
|
23
|
+
forth_call(num, ten)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def third_call_with_block(&block)
|
28
|
+
@ivar1 = 10; @ivar2 = 20
|
29
|
+
|
30
|
+
yield(10)
|
31
|
+
end
|
32
|
+
|
33
|
+
def forth_call(num1, num2)
|
34
|
+
num1 + num2
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Foo.new.first_call
|
39
|
+
```
|
40
|
+
|
41
|
+
### Command
|
42
|
+
|
43
|
+
```
|
44
|
+
$ exe/rdbg -e 'b 20;; c ;; bt ;; info ;; q!' -e c target.rb
|
45
|
+
```
|
46
|
+
|
47
|
+
### Expect Result
|
48
|
+
|
49
|
+
```
|
50
|
+
❯ exe/rdbg -e 'b 20;; c ;; bt ;; info ;; q!' -e c target.rb
|
51
|
+
[1, 10] in target.rb
|
52
|
+
=> 1| class Foo
|
53
|
+
2| def first_call
|
54
|
+
3| second_call(20)
|
55
|
+
4| end
|
56
|
+
5|
|
57
|
+
6| def second_call(num)
|
58
|
+
7| third_call_with_block do |ten|
|
59
|
+
8| forth_call(num, ten)
|
60
|
+
9| end
|
61
|
+
10| end
|
62
|
+
=>#0 <main> at target.rb:1
|
63
|
+
(rdbg:init) b 20
|
64
|
+
#1 line bp /PATH_TO_PROJECT/debug/target.rb:20 (return)
|
65
|
+
(rdbg:init) c
|
66
|
+
[15, 23] in target.rb
|
67
|
+
15| yield(10)
|
68
|
+
16| end
|
69
|
+
17|
|
70
|
+
18| def forth_call(num1, num2)
|
71
|
+
19| num1 + num2
|
72
|
+
=> 20| end
|
73
|
+
21| end
|
74
|
+
22|
|
75
|
+
23| Foo.new.first_call
|
76
|
+
=>#0 Foo#forth_call(num1=20, num2=10) at target.rb:20 #=> 30
|
77
|
+
#1 block{|ten=10|} in second_call at target.rb:8
|
78
|
+
# and 4 frames (use `bt' command for all frames)
|
79
|
+
|
80
|
+
Stop by #1 line bp /PATH_TO_PROJECT/debug/target.rb:20 (return)
|
81
|
+
(rdbg:init) bt
|
82
|
+
=>#0 Foo#forth_call(num1=20, num2=10) at target.rb:20 #=> 30
|
83
|
+
#1 block{|ten=10|} in second_call at target.rb:8
|
84
|
+
#2 Foo#third_call_with_block(block=#<Proc:0x00007f8bc32f0c28 target.rb:7>) at target.rb:15
|
85
|
+
#3 Foo#second_call(num=20) at target.rb:7
|
86
|
+
#4 first_call at target.rb:3
|
87
|
+
#5 <main> at target.rb:23
|
88
|
+
(rdbg:init) info
|
89
|
+
=>#0 Foo#forth_call(num1=20, num2=10) at target.rb:20 #=> 30
|
90
|
+
%self => #<Foo:0x00007f8bc32f0ed0>
|
91
|
+
%return => 30
|
92
|
+
num1 => 20
|
93
|
+
num2 => 10
|
94
|
+
@ivar1 => 10
|
95
|
+
@ivar2 => 20
|
96
|
+
(rdbg:init) q!
|
97
|
+
```
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -62,13 +62,14 @@ $ ruby -r debug/run target.rb
|
|
62
62
|
|
63
63
|
$ cat target.rb
|
64
64
|
require 'debug/run' # start the debug console
|
65
|
-
...
|
65
|
+
... rest of program ...
|
66
66
|
|
67
67
|
# or
|
68
68
|
|
69
69
|
$ cat target.rb
|
70
70
|
require 'debug/session' # introduce the functionality
|
71
71
|
DEBUGGER__.console # and start the debug console
|
72
|
+
... rest of program ...
|
72
73
|
|
73
74
|
$ ruby target.rb
|
74
75
|
```
|
@@ -373,11 +374,11 @@ The `<...>` notation means the argument.
|
|
373
374
|
* Note that edited file will not be reloaded.
|
374
375
|
* `edit <file>`
|
375
376
|
* Open <file> on the editor.
|
376
|
-
* `i[nfo]`
|
377
|
+
* `i[nfo]`, `i[nfo] l[ocal[s]]`
|
377
378
|
* Show information about the current frame (local variables)
|
378
379
|
* It includes `self` as `%self` and a return value as `%return`.
|
379
|
-
* `i[nfo]
|
380
|
-
* Show
|
380
|
+
* `i[nfo] th[read[s]]
|
381
|
+
* Show all threads (same as `th[read]`).
|
381
382
|
* `display`
|
382
383
|
* Show display setting.
|
383
384
|
* `display <expr>`
|
@@ -437,27 +438,28 @@ Debug console mode:
|
|
437
438
|
-O, --open Start debuggee with opening the debugger port.
|
438
439
|
If TCP/IP options are not given,
|
439
440
|
a UNIX domain socket will be used.
|
441
|
+
--sock-path=[SOCK_PATH] UNIX Doman socket path
|
440
442
|
--port=[PORT] Listening TCP/IP port
|
441
443
|
--host=[HOST] Listening TCP/IP host
|
442
444
|
|
443
445
|
Debug console mode runs Ruby program with the debug console.
|
444
446
|
|
445
|
-
rdbg target.rb foo bar
|
446
|
-
rdbg -- -r foo -e bar
|
447
|
-
rdbg -O target.rb foo bar
|
448
|
-
rdbg -O --port 1234 target.rb foo bar
|
449
|
-
rdbg -O --port 1234 -- -r foo -e bar
|
447
|
+
'rdbg target.rb foo bar' starts like 'ruby target.rb foo bar'.
|
448
|
+
'rdbg -- -r foo -e bar' starts like 'ruby -r foo -e bar'.
|
449
|
+
'rdbg -O target.rb foo bar' starts and accepts attaching with UNIX domain socket.
|
450
|
+
'rdbg -O --port 1234 target.rb foo bar' starts accepts attaching with TCP/IP localhost:1234.
|
451
|
+
'rdbg -O --port 1234 -- -r foo -e bar' starts accepts attaching with TCP/IP localhost:1234.
|
450
452
|
|
451
453
|
Attach mode:
|
452
454
|
-A, --attach Attach to debuggee process.
|
453
455
|
|
454
456
|
Attach mode attaches the remote debug console to the debuggee process.
|
455
457
|
|
456
|
-
'rdbg -A'
|
457
|
-
|
458
|
-
|
459
|
-
'rdbg -A path'
|
460
|
-
'rdbg -A port'
|
458
|
+
'rdbg -A' tries to connect via UNIX domain socket.
|
459
|
+
If there are multiple processes are waiting for the
|
460
|
+
debugger connection, list possible debuggee names.
|
461
|
+
'rdbg -A path' tries to connect via UNIX domain socket with given path name.
|
462
|
+
'rdbg -A port' tries to connect to localhost:port via TCP/IP.
|
461
463
|
'rdbg -A host port' tries to connect to host:port via TCP/IP.
|
462
464
|
|
463
465
|
```
|
@@ -465,3 +467,5 @@ Attach mode:
|
|
465
467
|
# Contributing
|
466
468
|
|
467
469
|
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/debug.
|
470
|
+
|
471
|
+
Please also check the [contributing guideline](/CONTRIBUTING.md).
|
data/TODO.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# TODO
|
2
|
+
|
3
|
+
## Basic functionality
|
4
|
+
|
5
|
+
* VScode DAP support
|
6
|
+
* Support Ractors
|
7
|
+
* Signal (SIGINT) support
|
8
|
+
* Remote connection with openssl
|
9
|
+
|
10
|
+
## UI
|
11
|
+
|
12
|
+
* Coloring
|
13
|
+
* Interactive breakpoint setting
|
14
|
+
* irb integration
|
15
|
+
* Web browser integrated UI
|
16
|
+
|
17
|
+
## Debug command
|
18
|
+
|
19
|
+
* Breakpoints
|
20
|
+
* Lightweight pending method break points with Ruby 3.1 feature (TP:method_added)
|
21
|
+
* Non-stop breakpoint but runs some code.
|
22
|
+
* Watch points
|
23
|
+
* Lightweight watchpoints for instance variables with Ruby 3.1 features (TP:ivar_set)
|
24
|
+
* Faster `next`/`finish` command by specifying target code.
|
25
|
+
* `set`/`show` configurations
|
26
|
+
* In-memory line traces
|
27
|
+
* Timemachine debugging
|
28
|
+
|
29
|
+
## Tests
|
30
|
+
|
31
|
+
* Test framework
|
32
|
+
* Tests for commands
|
33
|
+
* Tests for remote debugging
|
data/ext/debug/debug.c
CHANGED
@@ -90,7 +90,7 @@ method_added_tracker(VALUE tpval, void *ptr)
|
|
90
90
|
VALUE mid = rb_tracearg_callee_id(arg);
|
91
91
|
|
92
92
|
if (RB_UNLIKELY(mid == ID2SYM(rb_intern("method_added")) ||
|
93
|
-
mid == ID2SYM(rb_intern("
|
93
|
+
mid == ID2SYM(rb_intern("singleton_method_added")))) {
|
94
94
|
VALUE args[] = {
|
95
95
|
tpval,
|
96
96
|
};
|
data/lib/debug.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require_relative 'debug/
|
1
|
+
require_relative 'debug/session'
|
data/lib/debug/breakpoint.rb
CHANGED
@@ -209,7 +209,7 @@ module DEBUGGER__
|
|
209
209
|
@tp = TracePoint.new(:raise){|tp|
|
210
210
|
exc = tp.raised_exception
|
211
211
|
exc.class.ancestors.each{|cls|
|
212
|
-
suspend if pat === cls.name
|
212
|
+
suspend if @pat === cls.name
|
213
213
|
}
|
214
214
|
}
|
215
215
|
end
|
@@ -333,7 +333,11 @@ module DEBUGGER__
|
|
333
333
|
end
|
334
334
|
end
|
335
335
|
|
336
|
-
def enable
|
336
|
+
def enable
|
337
|
+
try_enable
|
338
|
+
end
|
339
|
+
|
340
|
+
def try_enable quiet: false
|
337
341
|
eval_class_name
|
338
342
|
search_method
|
339
343
|
|
data/lib/debug/config.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
module DEBUGGER__
|
3
3
|
def self.unix_domain_socket_dir
|
4
4
|
case
|
5
|
-
when path = DEBUGGER__::CONFIG[:sock_dir]
|
5
|
+
when path = ::DEBUGGER__::CONFIG[:sock_dir]
|
6
6
|
when path = ENV['XDG_RUNTIME_DIR']
|
7
7
|
when home = ENV['HOME']
|
8
8
|
path = File.join(home, '.ruby-debug-sock')
|
@@ -40,25 +40,39 @@ module DEBUGGER__
|
|
40
40
|
show_frames: 'RUBY_DEBUG_SHOW_FRAMES', # Show n frames on breakpoint (default: 2 frames).
|
41
41
|
use_short_path: 'RUBY_DEBUG_USE_SHORT_PATH', # Show shoten PATH (like $(Gem)/foo.rb).
|
42
42
|
skip_nosrc: 'RUBY_DEBUG_SKIP_NOSRC', # Skip on no source code lines (default: false).
|
43
|
+
use_colorize: 'RUBY_DEBUG_USE_COLORIZE', # Show coloring
|
43
44
|
|
44
45
|
# remote
|
45
46
|
port: 'RUBY_DEBUG_PORT', # TCP/IP remote debugging: port
|
46
47
|
host: 'RUBY_DEBUG_HOST', # TCP/IP remote debugging: host (localhost if not given)
|
48
|
+
sock_path: 'RUBY_DEBUG_SOCK_PATH', # UNIX Domain Socket remote debugging: socket path
|
47
49
|
sock_dir: 'RUBY_DEBUG_SOCK_DIR', # UNIX Domain Socket remote debugging: socket directory
|
48
50
|
}.freeze
|
49
51
|
|
50
52
|
def self.config_to_env config
|
51
53
|
CONFIG_MAP.each{|key, evname|
|
52
|
-
ENV[evname] = config[key]
|
54
|
+
ENV[evname] = config[key].to_s if config[key]
|
53
55
|
}
|
54
56
|
end
|
55
57
|
|
56
58
|
def self.parse_argv argv
|
57
59
|
config = {
|
58
60
|
mode: :start,
|
61
|
+
use_colorize: true,
|
59
62
|
}
|
60
63
|
CONFIG_MAP.each{|key, evname|
|
61
|
-
|
64
|
+
if val = ENV[evname]
|
65
|
+
if /_USE_/ =~ evname || /NONSTOP/ =~ evname
|
66
|
+
case val
|
67
|
+
when '1', 'true', 'TRUE', 'T'
|
68
|
+
config[key] = true
|
69
|
+
else
|
70
|
+
config[key] = false
|
71
|
+
end
|
72
|
+
else
|
73
|
+
config[key] = val
|
74
|
+
end
|
75
|
+
end
|
62
76
|
}
|
63
77
|
return config if !argv || argv.empty?
|
64
78
|
|
@@ -83,6 +97,9 @@ module DEBUGGER__
|
|
83
97
|
'a UNIX domain socket will be used.') do
|
84
98
|
config[:remote] = true
|
85
99
|
end
|
100
|
+
o.on('--sock-path=[SOCK_PATH]', 'UNIX Doman socket path') do |path|
|
101
|
+
config[:sock_path] = path
|
102
|
+
end
|
86
103
|
o.on('--port=[PORT]', 'Listening TCP/IP port') do |port|
|
87
104
|
config[:port] = port
|
88
105
|
end
|
@@ -95,11 +112,11 @@ module DEBUGGER__
|
|
95
112
|
o.separator ''
|
96
113
|
o.separator ' Debug console mode runs Ruby program with the debug console.'
|
97
114
|
o.separator ''
|
98
|
-
o.separator " #{rdbg} target.rb foo bar
|
99
|
-
o.separator " #{rdbg} -- -r foo -e bar
|
100
|
-
o.separator " #{rdbg} -O target.rb foo bar
|
101
|
-
o.separator " #{rdbg} -O --port 1234 target.rb foo bar
|
102
|
-
o.separator " #{rdbg} -O --port 1234 -- -r foo -e bar
|
115
|
+
o.separator " '#{rdbg} target.rb foo bar' starts like 'ruby target.rb foo bar'."
|
116
|
+
o.separator " '#{rdbg} -- -r foo -e bar' starts like 'ruby -r foo -e bar'."
|
117
|
+
o.separator " '#{rdbg} -O target.rb foo bar' starts and accepts attaching with UNIX domain socket."
|
118
|
+
o.separator " '#{rdbg} -O --port 1234 target.rb foo bar' starts accepts attaching with TCP/IP localhost:1234."
|
119
|
+
o.separator " '#{rdbg} -O --port 1234 -- -r foo -e bar' starts accepts attaching with TCP/IP localhost:1234."
|
103
120
|
|
104
121
|
o.separator ''
|
105
122
|
o.separator 'Attach mode:'
|
@@ -110,11 +127,11 @@ module DEBUGGER__
|
|
110
127
|
o.separator ''
|
111
128
|
o.separator ' Attach mode attaches the remote debug console to the debuggee process.'
|
112
129
|
o.separator ''
|
113
|
-
o.separator " '#{rdbg} -A'
|
114
|
-
o.separator " #{' ' * rdbg.size}
|
115
|
-
o.separator " #{' ' * rdbg.size}
|
116
|
-
o.separator " '#{rdbg} -A path'
|
117
|
-
o.separator " '#{rdbg} -A port'
|
130
|
+
o.separator " '#{rdbg} -A' tries to connect via UNIX domain socket."
|
131
|
+
o.separator " #{' ' * rdbg.size} If there are multiple processes are waiting for the"
|
132
|
+
o.separator " #{' ' * rdbg.size} debugger connection, list possible debuggee names."
|
133
|
+
o.separator " '#{rdbg} -A path' tries to connect via UNIX domain socket with given path name."
|
134
|
+
o.separator " '#{rdbg} -A port' tries to connect to localhost:port via TCP/IP."
|
118
135
|
o.separator " '#{rdbg} -A host port' tries to connect to host:port via TCP/IP."
|
119
136
|
end
|
120
137
|
|
@@ -122,4 +139,16 @@ module DEBUGGER__
|
|
122
139
|
|
123
140
|
config
|
124
141
|
end
|
142
|
+
|
143
|
+
CONFIG = ::DEBUGGER__.parse_argv(ENV['RUBY_DEBUG_OPT'])
|
144
|
+
|
145
|
+
def self.set_config kw
|
146
|
+
kw.each{|k, v|
|
147
|
+
if CONFIG_MAP[k]
|
148
|
+
CONFIG[k] = v # TODO: ractor support
|
149
|
+
else
|
150
|
+
raise "unknown option: #{k}"
|
151
|
+
end
|
152
|
+
}
|
153
|
+
end
|
125
154
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
|
2
|
+
module DEBUGGER__
|
3
|
+
FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :frame_depth,
|
4
|
+
:has_return_value, :return_value, :show_line)
|
5
|
+
|
6
|
+
|
7
|
+
# extend FrameInfo with debug.so
|
8
|
+
if File.exist? File.join(__dir__, 'debug.so')
|
9
|
+
require_relative 'debug.so'
|
10
|
+
else
|
11
|
+
require "debug/debug"
|
12
|
+
end
|
13
|
+
|
14
|
+
class FrameInfo
|
15
|
+
HOME = ENV['HOME'] ? (ENV['HOME'] + '/') : nil
|
16
|
+
|
17
|
+
def path
|
18
|
+
location.path
|
19
|
+
end
|
20
|
+
|
21
|
+
def realpath
|
22
|
+
location.absolute_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def pretty_path
|
26
|
+
use_short_path = ::DEBUGGER__::CONFIG[:use_short_path]
|
27
|
+
|
28
|
+
case
|
29
|
+
when use_short_path && path.start_with?(dir = ::DEBUGGER__::CONFIG["rubylibdir"] + '/')
|
30
|
+
path.sub(dir, '$(rubylibdir)/')
|
31
|
+
when use_short_path && Gem.path.any? do |gp|
|
32
|
+
path.start_with?(dir = gp + '/gems/')
|
33
|
+
end
|
34
|
+
path.sub(dir, '$(Gem)/')
|
35
|
+
when HOME && path.start_with?(HOME)
|
36
|
+
path.sub(HOME, '~/')
|
37
|
+
else
|
38
|
+
path
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def file_lines
|
43
|
+
SESSION.source(realpath || path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def call_identifier_str
|
47
|
+
if binding && iseq
|
48
|
+
if iseq.type == :block
|
49
|
+
if (argc = iseq.argc) > 0
|
50
|
+
args = parameters_info iseq.locals[0...argc]
|
51
|
+
args_str = "{|#{args}|}"
|
52
|
+
end
|
53
|
+
|
54
|
+
location.label.sub('block'){ "block#{args_str}" }
|
55
|
+
elsif (callee = binding.eval('__callee__', __FILE__, __LINE__)) && (argc = iseq.argc) > 0
|
56
|
+
args = parameters_info iseq.locals[0...argc]
|
57
|
+
"#{klass_sig}#{callee}(#{args})"
|
58
|
+
else
|
59
|
+
location.label
|
60
|
+
end
|
61
|
+
else
|
62
|
+
"[C] #{klass_sig}#{location.base_label}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def return_str
|
67
|
+
if binding && iseq && has_return_value
|
68
|
+
short_inspect(return_value)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def location_str
|
73
|
+
"#{pretty_path}:#{location.lineno}"
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
SHORT_INSPECT_LENGTH = 40
|
79
|
+
|
80
|
+
def short_inspect obj
|
81
|
+
str = obj.inspect
|
82
|
+
if str.length > SHORT_INSPECT_LENGTH
|
83
|
+
str[0...SHORT_INSPECT_LENGTH] + '...'
|
84
|
+
else
|
85
|
+
str
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_singleton_class obj
|
90
|
+
obj.singleton_class # TODO: don't use it
|
91
|
+
rescue TypeError
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
|
95
|
+
def parameters_info vars
|
96
|
+
vars.map{|var|
|
97
|
+
begin
|
98
|
+
"#{var}=#{short_inspect(binding.local_variable_get(var))}"
|
99
|
+
rescue NameError, TypeError
|
100
|
+
nil
|
101
|
+
end
|
102
|
+
}.compact.join(', ')
|
103
|
+
end
|
104
|
+
|
105
|
+
def klass_sig
|
106
|
+
if self.class == get_singleton_class(self.self)
|
107
|
+
"#{self.self}."
|
108
|
+
else
|
109
|
+
"#{self.class}#"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
data/lib/debug/server.rb
CHANGED
@@ -187,39 +187,30 @@ module DEBUGGER__
|
|
187
187
|
end
|
188
188
|
|
189
189
|
class UI_UnixDomainServer < UI_ServerBase
|
190
|
-
def initialize sock_dir: nil
|
190
|
+
def initialize sock_dir: nil, sock_path: nil
|
191
|
+
@sock_path = sock_path
|
191
192
|
@sock_dir = sock_dir || DEBUGGER__.unix_domain_socket_dir
|
192
193
|
|
193
194
|
super()
|
194
195
|
end
|
195
196
|
|
196
197
|
def accept
|
197
|
-
|
198
|
+
case
|
199
|
+
when @sock_path
|
200
|
+
when sp = ::DEBUGGER__::CONFIG[:sock_path]
|
201
|
+
@sock_path = sp
|
202
|
+
else
|
203
|
+
@sock_path = DEBUGGER__.create_unix_domain_socket_name(@sock_dir)
|
204
|
+
end
|
198
205
|
|
199
|
-
::DEBUGGER__.message "Debugger can attach via UNIX domain socket (#{@
|
200
|
-
Socket.unix_server_loop @
|
206
|
+
::DEBUGGER__.message "Debugger can attach via UNIX domain socket (#{@sock_path})"
|
207
|
+
Socket.unix_server_loop @sock_path do |sock, client|
|
201
208
|
@client_addr = client
|
202
209
|
yield sock
|
203
210
|
end
|
204
211
|
end
|
205
212
|
end
|
206
213
|
|
207
|
-
def self.open host: nil, port: ::DEBUGGER__::CONFIG[:port], sock_dir: nil
|
208
|
-
if port
|
209
|
-
open_tcp host: host, port: port
|
210
|
-
else
|
211
|
-
open_unix sock_dir: sock_dir
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def self.open_tcp(host: nil, port:)
|
216
|
-
initialize_session UI_TcpServer.new(host: host, port: port)
|
217
|
-
end
|
218
|
-
|
219
|
-
def self.open_unix sock_dir: nil
|
220
|
-
initialize_session UI_UnixDomainServer.new(sock_dir: sock_dir)
|
221
|
-
end
|
222
|
-
|
223
214
|
def self.message msg
|
224
215
|
$stderr.puts "DEBUGGER: #{msg}"
|
225
216
|
end
|
data/lib/debug/session.rb
CHANGED
@@ -1,18 +1,7 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
FrameInfo = Struct.new(:location, :self, :binding, :iseq, :class, :frame_depth,
|
4
|
-
:has_return_value, :return_value, :show_line)
|
5
|
-
end
|
6
|
-
|
7
|
-
if File.exist? File.join(__dir__, 'debug.so')
|
8
|
-
require_relative 'debug.so'
|
9
|
-
else
|
10
|
-
require "debug/debug"
|
11
|
-
end
|
12
|
-
|
1
|
+
|
2
|
+
require_relative 'thread_client'
|
13
3
|
require_relative 'source_repository'
|
14
4
|
require_relative 'breakpoint'
|
15
|
-
require_relative 'thread_client'
|
16
5
|
require_relative 'config'
|
17
6
|
|
18
7
|
class RubyVM::InstructionSequence
|
@@ -61,7 +50,7 @@ module DEBUGGER__
|
|
61
50
|
@bps = {} # bp.key => bp
|
62
51
|
# [file, line] => LineBreakpoint
|
63
52
|
# "Error" => CatchBreakpoint
|
64
|
-
#
|
53
|
+
# "Foo#bar" => MethodBreakpoint
|
65
54
|
# [:watch, expr] => WatchExprBreakpoint
|
66
55
|
# [:check, expr] => CheckBreakpoint
|
67
56
|
@th_clients = {} # {Thread => ThreadClient}
|
@@ -73,7 +62,8 @@ module DEBUGGER__
|
|
73
62
|
|
74
63
|
@tp_load_script = TracePoint.new(:script_compiled){|tp|
|
75
64
|
ThreadClient.current.on_load tp.instruction_sequence, tp.eval_script
|
76
|
-
}
|
65
|
+
}
|
66
|
+
@tp_load_script.enable
|
77
67
|
|
78
68
|
@session_server = Thread.new do
|
79
69
|
Thread.current.abort_on_exception = true
|
@@ -149,7 +139,8 @@ module DEBUGGER__
|
|
149
139
|
|
150
140
|
@tp_thread_begin = TracePoint.new(:thread_begin){|tp|
|
151
141
|
ThreadClient.current.on_thread_begin Thread.current
|
152
|
-
}
|
142
|
+
}
|
143
|
+
@tp_thread_begin.enable
|
153
144
|
end
|
154
145
|
|
155
146
|
def add_initial_commands cmds
|
@@ -160,7 +151,11 @@ module DEBUGGER__
|
|
160
151
|
end
|
161
152
|
|
162
153
|
def source path
|
163
|
-
|
154
|
+
if CONFIG[:use_colorize]
|
155
|
+
@sr.get_colored(path)
|
156
|
+
else
|
157
|
+
@sr.get(path)
|
158
|
+
end
|
164
159
|
end
|
165
160
|
|
166
161
|
def inspect
|
@@ -409,17 +404,23 @@ module DEBUGGER__
|
|
409
404
|
|
410
405
|
@tc << [:show, :edit, arg]
|
411
406
|
|
412
|
-
# * `i[nfo]`
|
407
|
+
# * `i[nfo]`, `i[nfo] l[ocal[s]]`
|
413
408
|
# * Show information about the current frame (local variables)
|
414
409
|
# * It includes `self` as `%self` and a return value as `%return`.
|
415
|
-
# * `i[nfo]
|
416
|
-
# * Show
|
410
|
+
# * `i[nfo] th[read[s]]
|
411
|
+
# * Show all threads (same as `th[read]`).
|
417
412
|
when 'i', 'info'
|
418
413
|
case arg
|
419
414
|
when nil
|
420
415
|
@tc << [:show, :local]
|
416
|
+
when 'l', /locals?/
|
417
|
+
@tc << [:show, :local]
|
418
|
+
when 'th', /threads?/
|
419
|
+
thread_list
|
420
|
+
return :retry
|
421
421
|
else
|
422
|
-
|
422
|
+
show_help 'info'
|
423
|
+
return :retry
|
423
424
|
end
|
424
425
|
|
425
426
|
# * `display`
|
@@ -855,7 +856,7 @@ module DEBUGGER__
|
|
855
856
|
|
856
857
|
def add_catch_breakpoint arg
|
857
858
|
bp = CatchBreakpoint.new(arg)
|
858
|
-
|
859
|
+
add_breakpoint bp
|
859
860
|
end
|
860
861
|
|
861
862
|
def add_check_breakpoint expr
|
@@ -897,26 +898,37 @@ module DEBUGGER__
|
|
897
898
|
b = tp.binding
|
898
899
|
if var_name = b.local_variables.first
|
899
900
|
mid = b.local_variable_get(var_name)
|
900
|
-
|
901
|
+
unresolved = false
|
901
902
|
|
902
903
|
@bps.each{|k, bp|
|
903
904
|
case bp
|
904
905
|
when MethodBreakpoint
|
905
906
|
if bp.method.nil?
|
906
|
-
found = true
|
907
907
|
if bp.sig_method_name == mid.to_s
|
908
|
-
bp.
|
908
|
+
bp.try_enable(quiet: true)
|
909
909
|
end
|
910
910
|
end
|
911
|
+
|
912
|
+
unresolved = true unless bp.enabled?
|
911
913
|
end
|
912
914
|
}
|
913
|
-
unless
|
915
|
+
unless unresolved
|
914
916
|
METHOD_ADDED_TRACKER.disable
|
915
917
|
end
|
916
918
|
end
|
917
919
|
end
|
918
920
|
end
|
919
921
|
|
922
|
+
# manual configuration methods
|
923
|
+
|
924
|
+
def self.add_line_breakpoint file, line, **kw
|
925
|
+
::DEBUGGER__::SESSION.add_line_breakpoint file, line, **kw
|
926
|
+
end
|
927
|
+
|
928
|
+
def self.add_catch_breakpoint pat
|
929
|
+
::DEBUGGER__::SESSION.add_catch_breakpoint pat
|
930
|
+
end
|
931
|
+
|
920
932
|
# String for requring location
|
921
933
|
# nil for -r
|
922
934
|
def self.require_location
|
@@ -934,7 +946,12 @@ module DEBUGGER__
|
|
934
946
|
nil
|
935
947
|
end
|
936
948
|
|
937
|
-
|
949
|
+
# start methods
|
950
|
+
|
951
|
+
def self.console **kw
|
952
|
+
set_config(kw)
|
953
|
+
|
954
|
+
require_relative 'console'
|
938
955
|
initialize_session UI_Console.new
|
939
956
|
|
940
957
|
@prev_handler = trap(:SIGINT){
|
@@ -942,14 +959,30 @@ module DEBUGGER__
|
|
942
959
|
}
|
943
960
|
end
|
944
961
|
|
945
|
-
def self.
|
946
|
-
|
962
|
+
def self.open host: nil, port: ::DEBUGGER__::CONFIG[:port], sock_path: nil, sock_dir: nil, **kw
|
963
|
+
set_config(kw)
|
964
|
+
|
965
|
+
if port
|
966
|
+
open_tcp host: host, port: port
|
967
|
+
else
|
968
|
+
open_unix sock_path: sock_path, sock_dir: sock_dir
|
969
|
+
end
|
947
970
|
end
|
948
971
|
|
949
|
-
def self.
|
950
|
-
|
972
|
+
def self.open_tcp host: nil, port:, **kw
|
973
|
+
set_config(kw)
|
974
|
+
require_relative 'server'
|
975
|
+
initialize_session UI_TcpServer.new(host: host, port: port)
|
951
976
|
end
|
952
977
|
|
978
|
+
def self.open_unix sock_path: nil, sock_dir: nil, **kw
|
979
|
+
set_config(kw)
|
980
|
+
require_relative 'server'
|
981
|
+
initialize_session UI_UnixDomainServer.new(sock_dir: sock_dir, sock_path: sock_path)
|
982
|
+
end
|
983
|
+
|
984
|
+
# boot utilities
|
985
|
+
|
953
986
|
class << self
|
954
987
|
define_method :initialize_session do |ui|
|
955
988
|
::DEBUGGER__.const_set(:SESSION, Session.new(ui))
|
@@ -963,7 +996,7 @@ module DEBUGGER__
|
|
963
996
|
def bp; nil; end
|
964
997
|
end
|
965
998
|
|
966
|
-
if
|
999
|
+
if !::DEBUGGER__::CONFIG[:nonstop]
|
967
1000
|
if loc = ::DEBUGGER__.require_location
|
968
1001
|
# require 'debug/console' or 'debug'
|
969
1002
|
add_line_breakpoint loc.absolute_path, loc.lineno + 1, oneshot: true, hook_call: false
|
@@ -1052,8 +1085,6 @@ module DEBUGGER__
|
|
1052
1085
|
r.join("\n")
|
1053
1086
|
end
|
1054
1087
|
|
1055
|
-
CONFIG = ::DEBUGGER__.parse_argv(ENV['RUBY_DEBUG_OPT'])
|
1056
|
-
|
1057
1088
|
class ::Module
|
1058
1089
|
def method_added mid; end
|
1059
1090
|
def singleton_method_added mid; end
|
@@ -1,27 +1,57 @@
|
|
1
|
+
require 'irb/color' # IRB::Color.colorize_code
|
2
|
+
|
1
3
|
module DEBUGGER__
|
2
4
|
class SourceRepository
|
3
5
|
def initialize
|
4
6
|
@files = {} # filename => [src, iseq]
|
7
|
+
@color_files = {}
|
5
8
|
end
|
6
9
|
|
7
10
|
def add iseq, src
|
8
11
|
path = iseq.absolute_path
|
9
12
|
path = '-e' if iseq.path == '-e'
|
13
|
+
add_path path, src: src
|
14
|
+
end
|
10
15
|
|
16
|
+
def add_path path, src: nil
|
11
17
|
case
|
12
|
-
when
|
13
|
-
|
14
|
-
|
15
|
-
|
18
|
+
when src
|
19
|
+
if File.file?(path)
|
20
|
+
path = '(eval)' + path
|
21
|
+
src = nil
|
22
|
+
end
|
23
|
+
when path == '-e'
|
24
|
+
when path
|
25
|
+
begin
|
26
|
+
src = File.read(path)
|
27
|
+
rescue SystemCallError
|
28
|
+
end
|
16
29
|
else
|
17
30
|
src = nil
|
18
31
|
end
|
19
32
|
|
20
|
-
|
33
|
+
if src
|
34
|
+
src = src.gsub("\r\n", "\n") # CRLF -> LF
|
35
|
+
@files[path] = src.lines
|
36
|
+
end
|
21
37
|
end
|
22
38
|
|
23
39
|
def get path
|
24
|
-
@files
|
40
|
+
if @files.has_key? path
|
41
|
+
@files[path]
|
42
|
+
else
|
43
|
+
add_path path
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def get_colored path
|
48
|
+
if src_lines = @color_files[path]
|
49
|
+
return src_lines
|
50
|
+
else
|
51
|
+
if src_lines = get(path)
|
52
|
+
@color_files[path] = IRB::Color.colorize_code(src_lines.join).lines
|
53
|
+
end
|
54
|
+
end
|
25
55
|
end
|
26
56
|
end
|
27
57
|
end
|
data/lib/debug/thread_client.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'objspace'
|
2
2
|
require 'pp'
|
3
|
+
require 'irb/color'
|
4
|
+
require_relative 'frame_info'
|
3
5
|
|
4
6
|
module DEBUGGER__
|
5
7
|
class ThreadClient
|
@@ -12,6 +14,27 @@ module DEBUGGER__
|
|
12
14
|
|
13
15
|
attr_reader :location, :thread, :mode, :id
|
14
16
|
|
17
|
+
def colorize str, color
|
18
|
+
if CONFIG[:use_colorize]
|
19
|
+
IRB::Color.colorize str, color
|
20
|
+
else
|
21
|
+
str
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def default_frame_formatter frame
|
26
|
+
call_identifier_str = colorize(frame.call_identifier_str, [:BLUE, :BOLD])
|
27
|
+
location_str = colorize(frame.location_str, [:YELLOW])
|
28
|
+
result = "#{call_identifier_str} at #{location_str}"
|
29
|
+
|
30
|
+
if return_str = frame.return_str
|
31
|
+
return_str = colorize(frame.return_str, [:MAGENTA])
|
32
|
+
result += " #=> #{return_str}"
|
33
|
+
end
|
34
|
+
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
15
38
|
def initialize id, q_evt, q_cmd, thr = Thread.current
|
16
39
|
@id = id
|
17
40
|
@thread = thr
|
@@ -19,8 +42,9 @@ module DEBUGGER__
|
|
19
42
|
@q_cmd = q_cmd
|
20
43
|
@step_tp = nil
|
21
44
|
@output = []
|
22
|
-
@src_lines_on_stop = (DEBUGGER__::CONFIG[:show_src_lines] || 10).to_i
|
23
|
-
@show_frames_on_stop = (DEBUGGER__::CONFIG[:show_frames] || 2).to_i
|
45
|
+
@src_lines_on_stop = (::DEBUGGER__::CONFIG[:show_src_lines] || 10).to_i
|
46
|
+
@show_frames_on_stop = (::DEBUGGER__::CONFIG[:show_frames] || 2).to_i
|
47
|
+
@frame_formatter = method(:default_frame_formatter)
|
24
48
|
set_mode nil
|
25
49
|
end
|
26
50
|
|
@@ -129,7 +153,7 @@ module DEBUGGER__
|
|
129
153
|
next if SESSION.break? tp.path, tp.lineno
|
130
154
|
next if !yield
|
131
155
|
next if tp.path.start_with?(__dir__)
|
132
|
-
next unless File.exist?(tp.path) if CONFIG[:skip_nosrc]
|
156
|
+
next unless File.exist?(tp.path) if ::DEBUGGER__::CONFIG[:skip_nosrc]
|
133
157
|
|
134
158
|
tp.disable
|
135
159
|
on_suspend tp.event, tp
|
@@ -140,7 +164,7 @@ module DEBUGGER__
|
|
140
164
|
next if thread != Thread.current
|
141
165
|
next if SESSION.break? tp.path, tp.lineno
|
142
166
|
next if !yield
|
143
|
-
next unless File.exist?(tp.path) if CONFIG[:skip_nosrc]
|
167
|
+
next unless File.exist?(tp.path) if ::DEBUGGER__::CONFIG[:skip_nosrc]
|
144
168
|
|
145
169
|
tp.disable
|
146
170
|
on_suspend tp.event, tp
|
@@ -157,23 +181,15 @@ module DEBUGGER__
|
|
157
181
|
end
|
158
182
|
end
|
159
183
|
|
160
|
-
def file_lines path
|
161
|
-
if (src_lines = SESSION.source(path))
|
162
|
-
src_lines
|
163
|
-
elsif File.exist?(path)
|
164
|
-
File.readlines(path)
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
184
|
def show_src(frame_index: @current_frame_index,
|
169
185
|
update_line: false,
|
170
186
|
max_lines: 10,
|
171
187
|
start_line: nil,
|
172
188
|
end_line: nil,
|
173
189
|
dir: +1)
|
174
|
-
|
190
|
+
|
175
191
|
if @target_frames && frame = @target_frames[frame_index]
|
176
|
-
if file_lines =
|
192
|
+
if file_lines = frame.file_lines
|
177
193
|
frame_line = frame.location.lineno - 1
|
178
194
|
|
179
195
|
lines = file_lines.map.with_index do |e, i|
|
@@ -206,11 +222,11 @@ module DEBUGGER__
|
|
206
222
|
end
|
207
223
|
|
208
224
|
if start_line != end_line && max_lines
|
209
|
-
puts "[#{start_line+1}, #{end_line}] in #{pretty_path
|
225
|
+
puts "[#{start_line+1}, #{end_line}] in #{frame.pretty_path}" if !update_line && max_lines != 1
|
210
226
|
puts lines[start_line ... end_line]
|
211
227
|
end
|
212
228
|
else # no file lines
|
213
|
-
puts "# No sourcefile available for #{path}"
|
229
|
+
puts "# No sourcefile available for #{frame.path}"
|
214
230
|
end
|
215
231
|
end
|
216
232
|
end
|
@@ -218,7 +234,7 @@ module DEBUGGER__
|
|
218
234
|
def show_by_editor path = nil
|
219
235
|
unless path
|
220
236
|
if @target_frames && frame = @target_frames[@current_frame_index]
|
221
|
-
path = frame.
|
237
|
+
path = frame.path
|
222
238
|
else
|
223
239
|
return # can't get path
|
224
240
|
end
|
@@ -287,101 +303,12 @@ module DEBUGGER__
|
|
287
303
|
end
|
288
304
|
end
|
289
305
|
|
290
|
-
def
|
291
|
-
vars.map{|var|
|
292
|
-
begin
|
293
|
-
"#{var}=#{short_inspect(b.local_variable_get(var))}"
|
294
|
-
rescue NameError, TypeError
|
295
|
-
nil
|
296
|
-
end
|
297
|
-
}.compact.join(', ')
|
298
|
-
end
|
299
|
-
|
300
|
-
def get_singleton_class obj
|
301
|
-
obj.singleton_class # TODO: don't use it
|
302
|
-
rescue TypeError
|
303
|
-
nil
|
304
|
-
end
|
305
|
-
|
306
|
-
def klass_sig frame
|
307
|
-
klass = frame.class
|
308
|
-
if klass == get_singleton_class(frame.self)
|
309
|
-
"#{frame.self}."
|
310
|
-
else
|
311
|
-
"#{frame.class}#"
|
312
|
-
end
|
313
|
-
end
|
314
|
-
|
315
|
-
SHORT_INSPECT_LENGTH = 40
|
316
|
-
|
317
|
-
def short_inspect obj
|
318
|
-
str = obj.inspect
|
319
|
-
if str.length > SHORT_INSPECT_LENGTH
|
320
|
-
str[0...SHORT_INSPECT_LENGTH] + '...'
|
321
|
-
else
|
322
|
-
str
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
HOME = ENV['HOME'] ? (ENV['HOME'] + '/') : nil
|
327
|
-
|
328
|
-
def pretty_path path
|
329
|
-
use_short_path = CONFIG[:use_short_path]
|
330
|
-
|
331
|
-
case
|
332
|
-
when use_short_path && path.start_with?(dir = RbConfig::CONFIG["rubylibdir"] + '/')
|
333
|
-
path.sub(dir, '$(rubylibdir)/')
|
334
|
-
when use_short_path && Gem.path.any? do |gp|
|
335
|
-
path.start_with?(dir = gp + '/gems/')
|
336
|
-
end
|
337
|
-
path.sub(dir, '$(Gem)/')
|
338
|
-
when HOME && path.start_with?(HOME)
|
339
|
-
path.sub(HOME, '~/')
|
340
|
-
else
|
341
|
-
path
|
342
|
-
end
|
343
|
-
end
|
344
|
-
|
345
|
-
def pretty_location loc
|
346
|
-
" at #{pretty_path(loc.path)}:#{loc.lineno}"
|
347
|
-
end
|
348
|
-
|
349
|
-
def frame_str i
|
350
|
-
frame = @target_frames[i]
|
351
|
-
b = frame.binding
|
352
|
-
|
306
|
+
def frame_str(i)
|
353
307
|
cur_str = (@current_frame_index == i ? '=>' : ' ')
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
args = parameters_info b, iseq.locals[0...argc]
|
359
|
-
args_str = "{|#{args}|}"
|
360
|
-
end
|
361
|
-
|
362
|
-
label_prefix = frame.location.label.sub('block'){ "block#{args_str}" }
|
363
|
-
ci_str = label_prefix
|
364
|
-
elsif (callee = b.eval('__callee__', __FILE__, __LINE__)) && (argc = iseq.argc) > 0
|
365
|
-
args = parameters_info b, iseq.locals[0...argc]
|
366
|
-
ksig = klass_sig frame
|
367
|
-
ci_str = "#{ksig}#{callee}(#{args})"
|
368
|
-
else
|
369
|
-
ci_str = frame.location.label
|
370
|
-
end
|
371
|
-
|
372
|
-
loc_str = "#{pretty_location(frame.location)}"
|
373
|
-
|
374
|
-
if frame.has_return_value
|
375
|
-
return_str = " #=> #{short_inspect(frame.return_value)}"
|
376
|
-
end
|
377
|
-
else
|
378
|
-
ksig = klass_sig frame
|
379
|
-
callee = frame.location.base_label
|
380
|
-
ci_str = "[C] #{ksig}#{callee}"
|
381
|
-
loc_str = "#{pretty_location(frame.location)}"
|
382
|
-
end
|
383
|
-
|
384
|
-
"#{cur_str}##{i}\t#{ci_str}#{loc_str}#{return_str}"
|
308
|
+
prefix = "#{cur_str}##{i}"
|
309
|
+
frame = @target_frames[i]
|
310
|
+
frame_string = @frame_formatter.call(frame)
|
311
|
+
"#{prefix}\t#{frame_string}"
|
385
312
|
end
|
386
313
|
|
387
314
|
def show_frames max = (@target_frames || []).size
|
@@ -457,7 +384,7 @@ module DEBUGGER__
|
|
457
384
|
step_tp{true}
|
458
385
|
when :next
|
459
386
|
frame = @target_frames.first
|
460
|
-
path = frame.location.absolute_path || "!eval:#{frame.
|
387
|
+
path = frame.location.absolute_path || "!eval:#{frame.path}"
|
461
388
|
line = frame.location.lineno
|
462
389
|
frame.iseq.traceable_lines_norec(lines = {})
|
463
390
|
next_line = lines.keys.bsearch{|e| e > line}
|
@@ -533,7 +460,7 @@ module DEBUGGER__
|
|
533
460
|
case type
|
534
461
|
when :up
|
535
462
|
if @current_frame_index + 1 < @target_frames.size
|
536
|
-
@current_frame_index += 1
|
463
|
+
@current_frame_index += 1
|
537
464
|
show_src max_lines: 1
|
538
465
|
show_frame(@current_frame_index)
|
539
466
|
end
|
data/lib/debug/version.rb
CHANGED
data/misc/README.md.erb
CHANGED
@@ -62,13 +62,14 @@ $ ruby -r debug/run target.rb
|
|
62
62
|
|
63
63
|
$ cat target.rb
|
64
64
|
require 'debug/run' # start the debug console
|
65
|
-
...
|
65
|
+
... rest of program ...
|
66
66
|
|
67
67
|
# or
|
68
68
|
|
69
69
|
$ cat target.rb
|
70
70
|
require 'debug/session' # introduce the functionality
|
71
71
|
DEBUGGER__.console # and start the debug console
|
72
|
+
... rest of program ...
|
72
73
|
|
73
74
|
$ ruby target.rb
|
74
75
|
```
|
@@ -295,10 +296,10 @@ You can control debuggee's behavior with environment variables:
|
|
295
296
|
* `RUBY_DEBUG_COMMANDS`: Debug commands invoked at the first stop. Commands should be separated by ';;'.
|
296
297
|
* `RUBY_DEBUG_SHOW_SRC_LINES`: Show n lines source code on breakpoint (default: 10 lines).
|
297
298
|
* `RUBY_DEBUG_SHOW_FRAMES`: Show n frames on breakpoint (default: 2 frames).
|
298
|
-
|
299
299
|
* Remote debugging
|
300
300
|
* `RUBY_DEBUG_PORT`: TCP/IP remote debugging: port to open.
|
301
301
|
* `RUBY_DEBUG_HOST`: TCP/IP remote debugging: host (localhost if not given) to open.
|
302
|
+
* `RUBY_DEBUG_SOCK_PATH`: UNIX Domain Socket remote debugging: socket path to open.
|
302
303
|
* `RUBY_DEBUG_SOCK_DIR`: UNIX Domain Socket remote debugging: socket directory to open.
|
303
304
|
|
304
305
|
## Debug command on the debug console
|
@@ -322,3 +323,5 @@ The `<...>` notation means the argument.
|
|
322
323
|
# Contributing
|
323
324
|
|
324
325
|
Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/debug.
|
326
|
+
|
327
|
+
Please also check the [contributing guideline](/CONTRIBUTING.md).
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: debug
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.beta4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Koichi Sasada
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Debugging functionality for Ruby. This is completely rewritten debug.rb
|
14
14
|
which was contained by the encient Ruby versions.
|
@@ -21,10 +21,12 @@ extensions:
|
|
21
21
|
extra_rdoc_files: []
|
22
22
|
files:
|
23
23
|
- ".gitignore"
|
24
|
+
- CONTRIBUTING.md
|
24
25
|
- Gemfile
|
25
26
|
- LICENSE.txt
|
26
27
|
- README.md
|
27
28
|
- Rakefile
|
29
|
+
- TODO.md
|
28
30
|
- bin/console
|
29
31
|
- bin/setup
|
30
32
|
- debug.gemspec
|
@@ -38,6 +40,7 @@ files:
|
|
38
40
|
- lib/debug/client.rb
|
39
41
|
- lib/debug/config.rb
|
40
42
|
- lib/debug/console.rb
|
43
|
+
- lib/debug/frame_info.rb
|
41
44
|
- lib/debug/open.rb
|
42
45
|
- lib/debug/run.rb
|
43
46
|
- lib/debug/server.rb
|