debug 1.0.0.beta6 → 1.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,242 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DEBUGGER__
4
+ class Tracer
5
+ include SkipPathHelper
6
+ include Color
7
+
8
+ def colorize(str, color)
9
+ # don't colorize trace sent into a file
10
+ if @into
11
+ str
12
+ else
13
+ super
14
+ end
15
+ end
16
+
17
+ attr_reader :type
18
+
19
+ def initialize ui, pattern: nil, into: nil
20
+ if /\ADEBUGGER__::(([A-Z][a-z]+?)[A-Z][a-z]+)/ =~ self.class.name
21
+ @name = $1
22
+ @type = $2.downcase
23
+ end
24
+
25
+ setup
26
+
27
+ if pattern
28
+ @pattern = Regexp.compile(pattern)
29
+ else
30
+ @pattern = nil
31
+ end
32
+
33
+ if @into = into
34
+ @output = File.open(into, 'w')
35
+ @output.puts "PID:#{Process.pid} #{self}"
36
+ else
37
+ @output = ui
38
+ end
39
+
40
+ enable
41
+ end
42
+
43
+ def header depth
44
+ "DEBUGGER (trace/#{@type}) \#th:#{Thread.current.instance_variable_get(:@__thread_client_id)} \#depth:#{'%-2d'%depth}"
45
+ end
46
+
47
+ def enable
48
+ @tracer.enable
49
+ end
50
+
51
+ def disable
52
+ @tracer.disable
53
+ end
54
+
55
+ def description
56
+ nil
57
+ end
58
+
59
+ def to_s
60
+ s = "#{@name}#{description} (#{@tracer.enabled? ? 'enabled' : 'disabled'})"
61
+ s += " with pattern #{@pattern.inspect}" if @pattern
62
+ s += " into: #{@into}" if @into
63
+ s
64
+ end
65
+
66
+ def skip? tp
67
+ if tp.path.start_with?(__dir__) ||
68
+ tp.path.start_with?('<internal:') ||
69
+ ThreadClient.current.management? ||
70
+ skip_path?(tp.path) ||
71
+ skip_with_pattern?(tp)
72
+ true
73
+ else
74
+ false
75
+ end
76
+ end
77
+
78
+ def skip_with_pattern?(tp)
79
+ @pattern && !tp.path.match?(@pattern)
80
+ end
81
+
82
+ def out tp, msg = nil, depth = caller.size - 1
83
+ location_str = colorize("#{tp.path}:#{tp.lineno}", [:GREEN])
84
+ buff = "#{header(depth)}#{msg} at #{location_str}"
85
+
86
+ if false # TODO: Ractor.main?
87
+ ThreadClient.current.on_trace self.object_id, buff
88
+ else
89
+ @output.puts buff
90
+ end
91
+ end
92
+
93
+ def puts msg
94
+ @output.puts msg
95
+ end
96
+
97
+ def minfo tp
98
+ klass = tp.defined_class
99
+
100
+ if klass.singleton_class?
101
+ "#{tp.self}.#{tp.method_id}"
102
+ else
103
+ "#{klass}\##{tp.method_id}"
104
+ end
105
+ end
106
+ end
107
+
108
+ class LineTracer < Tracer
109
+ def setup
110
+ @tracer = TracePoint.new(:line){|tp|
111
+ next if skip?(tp)
112
+ # pp tp.object_id, caller(0)
113
+ out tp
114
+ }
115
+ end
116
+ end
117
+
118
+ class CallTracer < Tracer
119
+ def setup
120
+ @tracer = TracePoint.new(:a_call, :a_return){|tp|
121
+ next if skip?(tp)
122
+
123
+ depth = caller.size
124
+ sp = ' ' * depth
125
+
126
+ call_identifier_str =
127
+ if tp.defined_class
128
+ minfo(tp)
129
+ else
130
+ "block"
131
+ end
132
+
133
+ call_identifier_str = colorize_blue(call_identifier_str)
134
+
135
+ case tp.event
136
+ when :call, :c_call, :b_call
137
+ depth += 1 if tp.event == :c_call
138
+ out tp, ">#{sp}#{call_identifier_str}", depth
139
+ when :return, :c_return, :b_return
140
+ depth += 1 if tp.event == :c_return
141
+ return_str = colorize_magenta(DEBUGGER__.short_inspect(tp.return_value))
142
+ out tp, "<#{sp}#{call_identifier_str} #=> #{return_str}", depth
143
+ end
144
+ }
145
+ end
146
+
147
+ def skip_with_pattern?(tp)
148
+ super && !tp.method_id&.match?(@pattern)
149
+ end
150
+ end
151
+
152
+ class ExceptionTracer < Tracer
153
+ def setup
154
+ @tracer = TracePoint.new(:raise) do |tp|
155
+ next if skip?(tp)
156
+
157
+ exc = tp.raised_exception
158
+
159
+ out tp, " #{colorize_magenta(exc.inspect)}"
160
+ rescue Exception => e
161
+ p e
162
+ end
163
+ end
164
+
165
+ def skip_with_pattern?(tp)
166
+ super && !tp.raised_exception.inspect.match?(@pattern)
167
+ end
168
+ end
169
+
170
+ class ObjectTracer < Tracer
171
+ def initialize ui, obj_id, obj_inspect, **kw
172
+ @obj_id = obj_id
173
+ @obj_inspect = obj_inspect
174
+ super(ui, **kw)
175
+ end
176
+
177
+ def description
178
+ " for #{@obj_inspect}"
179
+ end
180
+
181
+ def colorized_obj_inspect
182
+ colorize_magenta(@obj_inspect)
183
+ end
184
+
185
+ def setup
186
+ @tracer = TracePoint.new(:a_call){|tp|
187
+ next if skip?(tp)
188
+
189
+ if tp.self.object_id == @obj_id
190
+ klass = tp.defined_class
191
+ method = tp.method_id
192
+ method_info =
193
+ if klass.singleton_class?
194
+ if tp.self.is_a?(Class)
195
+ ".#{method} (#{klass}.#{method})"
196
+ else
197
+ ".#{method}"
198
+ end
199
+ else
200
+ "##{method} (#{klass}##{method})"
201
+ end
202
+
203
+ out tp, " #{colorized_obj_inspect} receives #{colorize_blue(method_info)}"
204
+ else
205
+ b = tp.binding
206
+ method_info = colorize_blue(minfo(tp))
207
+
208
+ tp.parameters.each{|type, name|
209
+ next unless name
210
+
211
+ colorized_name = colorize_cyan(name)
212
+
213
+ case type
214
+ when :req, :opt, :key, :keyreq
215
+ if b.local_variable_get(name).object_id == @obj_id
216
+ out tp, " #{colorized_obj_inspect} is used as a parameter #{colorized_name} of #{method_info}"
217
+ end
218
+ when :rest
219
+ next name == :"*"
220
+
221
+ ary = b.local_variable_get(name)
222
+ ary.each{|e|
223
+ if e.object_id == @obj_id
224
+ out tp, " #{colorized_obj_inspect} is used as a parameter in #{colorized_name} of #{method_info}"
225
+ end
226
+ }
227
+ when :keyrest
228
+ next if name == :'**'
229
+ h = b.local_variable_get(name)
230
+ h.each{|k, e|
231
+ if e.object_id == @obj_id
232
+ out tp, " #{colorized_obj_inspect} is used as a parameter in #{colorized_name} of #{method_info}"
233
+ end
234
+ }
235
+ end
236
+ }
237
+ end
238
+ }
239
+ end
240
+ end
241
+ end
242
+
data/lib/debug/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DEBUGGER__
4
- VERSION = "1.0.0.beta6"
4
+ VERSION = "1.0.0.rc2"
5
5
  end
data/misc/README.md.erb CHANGED
@@ -12,7 +12,7 @@ New debug.rb has several advantages:
12
12
  * UNIX domain socket
13
13
  * TCP/IP
14
14
  * VSCode/DAP integration ([VSCode rdbg Ruby Debugger - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg))
15
- * Extensible: application can introduce debugging support with several methods
15
+ * Extensible: application can introduce debugging support with several ways:
16
16
  * By `rdbg` command
17
17
  * By loading libraries with `-r` command line option
18
18
  * By calling Ruby's method explicitly
@@ -20,6 +20,7 @@ New debug.rb has several advantages:
20
20
  * Support threads (almost done) and ractors (TODO).
21
21
  * Support suspending and entering to the console debugging with `Ctrl-C` at most of timing.
22
22
  * Show parameters on backtrace command.
23
+ * Support recording & reply debugging.
23
24
 
24
25
  # Installation
25
26
 
@@ -29,313 +30,432 @@ $ gem install debug --pre
29
30
 
30
31
  or specify `-Ipath/to/debug/lib` in `RUBYOPT` or each ruby command-line option, especially for debug this gem development.
31
32
 
32
- If you use Bundler, write the following line to your Gemfile. And use rdbg command with -c option.
33
+ If you use Bundler, write the following line to your Gemfile.
34
+
35
+ ```
36
+ gem "debug", ">= 1.0.0.rc"
37
+ ```
38
+
39
+ # HOW TO USE
40
+
41
+ To use a debugger, roughly you will do the following steps:
42
+
43
+ 1. Set breakpoints.
44
+ 2. Run a program with the debugger.
45
+ 3. At the breakpoint, enter the debugger console.
46
+ 4. Use debug commands.
47
+ * Query the program status (e.g. `p lvar` to see the local variable `lvar`).
48
+ * Control program flow (e.g. move to the another line with `step`, to the next line with `next`).
49
+ * Set another breakpoint (e.g. `catch Exception` to set a breakpoint when `Exception` is raised).
50
+ * Change the configuration (e.g. `config set no_color true` to disable coloring).
51
+ * Continue the program (`c` or `continue`) and goto 3.
52
+
53
+ ## Invoke with the debugger
54
+
55
+ There are several options for (1) and (2). Please choose your favorite way.
56
+
57
+ ### Modify source code as `binding.pry` and `binding.irb`
58
+
59
+ If you can modify the source code, you can use the debugger by adding `require 'debug'` line at the top of your program and putting `binding.break` method (`binding.b` for short) into lines where you want to stop as breakpoints like `binding.pry` and `binding.irb`.
60
+ After that, you run the program as usual and you will enter the debug console at breakpoints you inserted.
61
+
62
+ The following example shows the demonstration of `binding.break`.
63
+
64
+ ```shell
65
+ $ cat target.rb # Sample program
66
+ require 'debug'
67
+
68
+ a = 1
69
+ b = 2
70
+ binding.break # Program will stop here
71
+ c = 3
72
+ d = 4
73
+ binding.break # Program will stop here
74
+ p [a, b, c, d]
75
+
76
+ $ ruby target.rb # Run the program normally.
77
+ DEBUGGER: Session start (pid: 7604)
78
+ [1, 10] in target.rb
79
+ 1| require 'debug'
80
+ 2|
81
+ 3| a = 1
82
+ 4| b = 2
83
+ => 5| binding.break # Now you can see it stops at this line
84
+ 6| c = 3
85
+ 7| d = 4
86
+ 8| binding.break
87
+ 9| p [a, b, c, d]
88
+ 10|
89
+ =>#0 <main> at target.rb:5
90
+
91
+ (rdbg) info locals # You can show local variables
92
+ =>#0 <main> at target.rb:5
93
+ %self => main
94
+ a => 1
95
+ b => 2
96
+ c => nil
97
+ d => nil
98
+
99
+ (rdbg) continue # Continue the execution
100
+ [3, 11] in target.rb
101
+ 3| a = 1
102
+ 4| b = 2
103
+ 5| binding.break
104
+ 6| c = 3
105
+ 7| d = 4
106
+ => 8| binding.break # Again the program stops at here
107
+ 9| p [a, b, c, d]
108
+ 10|
109
+ 11| __END__
110
+ =>#0 <main> at target.rb:8
111
+
112
+ (rdbg) info locals # And you can see the updated local variables
113
+ =>#0 <main> at target.rb:8
114
+ %self => main
115
+ a => 1
116
+ b => 2
117
+ c => 3
118
+ d => 4
119
+
120
+ (rdbg) continue
121
+ [1, 2, 3, 4]
122
+ ```
123
+
124
+ ### Invoke the program from the debugger as a traditional debuggers
125
+
126
+ If you don't want to modify the source code, you can set breakpoints with a debug command `break` (`b` for short).
127
+ Using `rdbg` command to launch the program without any modifications, you can run the program with the debugger.
128
+
129
+ ```shell
130
+ $ cat target.rb # Sample program
131
+ a = 1
132
+ b = 2
133
+ c = 3
134
+ d = 4
135
+ p [a, b, c, d]
136
+
137
+ $ rdbg target.rb # run like `ruby target.rb`
138
+ DEBUGGER: Session start (pid: 7656)
139
+ [1, 7] in target.rb
140
+ => 1| a = 1
141
+ 2| b = 2
142
+ 3| c = 3
143
+ 4| d = 4
144
+ 5| p [a, b, c, d]
145
+ 6|
146
+ 7| __END__
147
+ =>#0 <main> at target.rb:1
33
148
 
34
- ```
35
- gem "debug", ">= 1.0.0.beta"
149
+ (rdbg)
36
150
  ```
37
151
 
38
- ```
39
- $ rdbg -c bundle exec ruby target.rb
152
+ `rdbg` command suspends the program at the beginning of the given script (`target.rb` in this case) and you can use debug commands. `(rdbg)` is prompt. Let's set breakpoints on line 3 and line 5 with `break` command (`b` for short).
153
+
154
+ ```shell
155
+ (rdbg) break 3 # set breakpoint at line 3
156
+ #0 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:3 (line)
157
+
158
+ (rdbg) b 5 # set breakpoint at line 5
159
+ #1 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:5 (line)
160
+
161
+ (rdbg) break # show all registered breakpoints
162
+ #0 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:3 (line)
163
+ #1 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:5 (line)
40
164
  ```
41
165
 
42
- # How to use
166
+ You can see that two breakpoints are registered. Let's continue the program by `continue` command.
43
167
 
44
- ## Invoke with debugger
168
+ ```shell
169
+ (rdbg) continue
170
+ [1, 7] in target.rb
171
+ 1| a = 1
172
+ 2| b = 2
173
+ => 3| c = 3
174
+ 4| d = 4
175
+ 5| p [a, b, c, d]
176
+ 6|
177
+ 7| __END__
178
+ =>#0 <main> at target.rb:3
45
179
 
46
- You can run ruby program on debugger with the local debug console or the remote debug console.
180
+ Stop by #0 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:3 (line)
47
181
 
48
- * (a) Run a ruby program with the local debug console
49
- * (b) Run a ruby program with the remote debug console by opening a network port
50
- * (b-1) Open with UNIX domain socket
51
- * (b-2) Open with TCP/IP port
182
+ (rdbg)
183
+ ```
52
184
 
53
- (b-1) is useful when you want to use debugging features after running the program.
54
- (b-2) is also useful when you don't have a ssh access for the Ruby process.
185
+ You can see that we can stop at line 3.
186
+ Let's see the local variables with `info` command, and continue.
187
+ You can also confirm that the program will suspend at line 5 and you can use `info` command again.
55
188
 
56
- To use debugging feature, you can have 3 ways.
189
+ ```shell
190
+ (rdbg) info
191
+ =>#0 <main> at target.rb:3
192
+ %self => main
193
+ a => 1
194
+ b => 2
195
+ c => nil
196
+ d => nil
57
197
 
58
- * (1) Use `rdbg` command
59
- * (2) Use `ruby -r debug...` command line option
60
- * (3) Write `require 'debug...'` in .rb files
198
+ (rdbg) continue
199
+ [1, 7] in target.rb
200
+ 1| a = 1
201
+ 2| b = 2
202
+ 3| c = 3
203
+ 4| d = 4
204
+ => 5| p [a, b, c, d]
205
+ 6|
206
+ 7| __END__
207
+ =>#0 <main> at target.rb:5
61
208
 
62
- ### Local debug console
209
+ Stop by #1 BP - Line /mnt/c/ko1/src/rb/ruby-debug/target.rb:5 (line)
63
210
 
64
- #### (1) Use `rdbg` command
211
+ (rdbg) info
212
+ =>#0 <main> at target.rb:5
213
+ %self => main
214
+ a => 1
215
+ b => 2
216
+ c => 3
217
+ d => 4
65
218
 
66
- ```
67
- $ rdbg target.rb
68
- $ rdbg -- -r foo -e expr # -- is required to make clear rdbg options and ruby's options
219
+ (rdbg) continue
220
+ [1, 2, 3, 4]
69
221
  ```
70
222
 
71
- #### (2) Use `-r debug/run` command line option
223
+ By the way, using `rdbg` command you can suspend your application with `C-c` (SIGINT) and enter the debug console.
224
+ It will help that if you want to know what the program is doing.
72
225
 
73
- ```
74
- $ ruby -r debug/run target.rb
75
- ```
226
+ ### Use `rdbg` with commands written in Ruby
76
227
 
77
- #### (3) Write `require 'debug...'` in .rb files
228
+ If you want to run a command written in Ruby like like `rake`, `rails`, `bundle`, `rspec` and so on, you can use `rdbg -c` option.
78
229
 
79
- ```ruby
80
- # target.rb
81
- require 'debug/run' # start the debug console
230
+ * Without `-c` option, `rdbg <name>` means that `<name>` is Ruby script and invoke it like `ruby <name>` with the debugger.
231
+ * With `-c` option, `rdbg -c <name>` means that `<name>` is command in `PATH` and simply invoke it with the debugger.
82
232
 
83
- # ... rest of program ...
84
- ```
233
+ Examples:
234
+ * `rdbg -c -- rails server`
235
+ * `rdbg -c -- bundle exec ruby foo.rb`
236
+ * `rdbg -c -- bundle exec rake test`
237
+ * `rdbg -c -- ruby target.rb` is same as `rdbg target.rb`
85
238
 
86
- ```
87
- $ ruby target.rb
88
- ```
239
+ NOTE: `--` is needed to separate the command line options for `rdbg` and invoking command. For example, `rdbg -c rake -T` is recognized like `rdbg -c -T -- rake`. It should be `rdbg -c -- rake -T`.
89
240
 
90
- When you run the program with the debug console, you will see the debug console prompt `(rdbg)`.
91
- The debuggee program (`target.rb`) is suspended at the beginning of `target.rb`.
241
+ NOTE: If you want to use bundler (`bundle` command), you need to write `gem debug` line in your `Gemfile`.
92
242
 
93
- You can type any debugger's command described bellow. "c" or "continue" resume the debuggee program.
94
- You can suspend the debuggee program and show the debug console with `Ctrl-C`.
243
+ ### Using VSCode
95
244
 
96
- The following example shows simple usage of the debug console. You can show the all variables
245
+ Like other languages, you can use this debugger on the VSCode.
97
246
 
98
- ```
99
- $ rdbg ~/src/rb/target.rb
247
+ 1. Install [VSCode rdbg Ruby Debugger - Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=KoichiSasada.vscode-rdbg)
248
+ 2. Open `.rb` file (e.g. `target.rb`)
249
+ 3. Register breakpoints with "Toggle breakpoint" in Run menu (or type F9 key)
250
+ 4. Choose "Start debugging" in "Run" menu (or type F5 key)
251
+ 5. You will see a dialog "Debug command line" and you can choose your favorite command line your want to run.
252
+ 6. Chosen command line is invoked with `rdbg -c` and VSCode shows the details at breakpoints.
100
253
 
101
- [1, 5] in /home/ko1/src/rb/target.rb
102
- => 1| a = 1
103
- 2| b = 2
104
- 3| c = 3
105
- 4| p [a + b + c]
106
- 5|
107
- --> #0 /home/ko1/src/rb/target.rb:1:in `<main>'
254
+ Please refer [Debugging in Visual Studio Code](https://code.visualstudio.com/docs/editor/debugging) for operations on VSCode.
108
255
 
109
- (rdbg) info # Show all local variables
110
- %self => main
111
- a => nil
112
- b => nil
113
- c => nil
256
+ You can configure the extension in `.vscode/launch.json`.
257
+ Please see the extension page for more details.
114
258
 
115
- (rdbg) p a # Same as p(a)
116
- => nil
259
+ ## Remote debugging
117
260
 
118
- (rdbg) s # Step in ("s" is a short name of "step")
261
+ You can use this debugger as a remote debugger. For example, it will help the following situations:
119
262
 
120
- [1, 5] in /home/ko1/src/rb/target.rb
121
- 1| a = 1
122
- => 2| b = 2
123
- 3| c = 3
124
- 4| p [a + b + c]
125
- 5|
126
- --> #0 /home/ko1/src/rb/target.rb:2:in `<main>'
263
+ * Your application does not run on TTY and it is hard to use `binding.pry` or `binding.irb`.
264
+ * Your application is running on Docker container and there is no TTY.
265
+ * Your application is running as a daemon.
266
+ * Your application uses pipe for STDIN or STDOUT.
267
+ * Your application is running as a daemon and you want to query the running status (checking a backtrace and so on).
127
268
 
128
- (rdbg) <Enter> # Repeat the last command ("step")
269
+ You can run your application as a remote debuggee and the remote debugger console can attach to the debuggee anytime.
129
270
 
130
- [1, 5] in /home/ko1/src/rb/target.rb
131
- 1| a = 1
132
- 2| b = 2
133
- => 3| c = 3
134
- 4| p [a + b + c]
135
- 5|
136
- --> #0 /home/ko1/src/rb/target.rb:3:in `<main>'
271
+ ### Invoke as a remote debuggee
137
272
 
138
- (rdbg) # Repeat the last command ("step")
273
+ There are two ways to invoke a script as remote debuggee: Use `rdbg --open` and require `debug/open` (or `debug/open_nonstop`).
139
274
 
140
- [1, 5] in /home/ko1/src/rb/target.rb
141
- 1| a = 1
275
+ #### `rdbg --open` (or `rdbg -O` for short)
276
+
277
+ You can run a script with `rdbg --open target.rb` command and run a `target.rb` as a debuggee program. It also opens the network port and suspends at the beginning of `target.rb`.
278
+
279
+ ```shell
280
+ $ exe/rdbg --open target.rb
281
+ DEBUGGER: Session start (pid: 7773)
282
+ DEBUGGER: Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-7773)
283
+ DEBUGGER: wait for debugger connection...
284
+ ```
285
+
286
+ By default, `rdbg --open` uses UNIX domain socket and generates path name automatically (`/home/ko1/.ruby-debug-sock/ruby-debug-ko1-7773` in this case).
287
+
288
+ You can connect to the debuggee with `rdbg --attach` command (`rdbg -A` for short).
289
+
290
+ ```shell
291
+ $ rdbg -A
292
+ [1, 7] in target.rb
293
+ => 1| a = 1
142
294
  2| b = 2
143
295
  3| c = 3
144
- => 4| p [a + b + c]
145
- 5|
146
- --> #0 /home/ko1/src/rb/target.rb:4:in `<main>'
147
-
148
- (rdbg) info # Show all local variables
149
- %self => main
150
- a => 1
151
- b => 2
152
- c => 3
153
-
154
- (rdbg) c # Continue the program ("c" is a short name of "continue")
155
- [6]
296
+ 4| d = 4
297
+ 5| p [a, b, c, d]
298
+ 6|
299
+ 7| __END__
300
+ =>#0 <main> at target.rb:1
301
+
302
+ (rdbg:remote)
156
303
  ```
157
304
 
158
- ### Remote debug (1) UNIX domain socket
305
+ If there is no other opening ports on the default directory, `rdbg --attach` command chooses the only one opening UNIX domain socket and connect to it. If there are more files, you need to specify the file.
159
306
 
160
- #### (1) Use `rdbg` command
307
+ When `rdbg --attach` connects to the debuggee, you can use any debug commands (set breakpoints, continue the program and so on) like local debug console. When an debuggee program exits, the remote console will also terminate.
161
308
 
162
- ```
163
- $ rdbg --open target.rb # or rdbg -O target.rb for shorthand
164
- Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-5042)
165
- ```
309
+ NOTE: If you use `quit` command, only remote console exits and the debuggee program continues to run (and you can connect it again). If you want to exit the debuggee program, use `kill` command.
166
310
 
167
- #### (2) Use `-r debug/open` command line option
311
+ If you want to use TCP/IP for the remote debugging, you need to specify the port and host with `--port` like `rdbg --open --port 12345` and it binds to `localhost:12345`.
168
312
 
169
- ```
170
- $ ruby -r debug/open target.rb
171
- Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-5042)
313
+ To connect to the debuggee, you need to specify the port.
314
+
315
+ ```shell
316
+ $ rdbg --attach 12345
172
317
  ```
173
318
 
174
- #### (3) Write `require 'debug/open'` in .rb files
319
+ If you want to choose the host to bind, you can use `--host` option.
320
+ Note that all messages communicated between the debugger and the debuggee are *NOT* encrypted so please use remote debugging carefully.
175
321
 
176
- ```ruby
177
- # target.rb
178
- require 'debug/open' # open the debugger entry point by UNIX domain socket.
322
+ #### `require 'debug/open'` in a program
179
323
 
180
- # or
324
+ If you can modify the program, you can open debugging port by adding `require 'debug/open'` line in the program.
181
325
 
182
- require 'debug/server' # introduce remote debugging feature
183
- DEBUGGER__.open # open the debugger entry point by UNIX domain socket.
184
- # or DEBUGGER__.open_unix to specify UNIX domain socket.
185
- ```
326
+ If you don't want to stop the program at the beginning, you can also use `require 'debug/open_nonstop'`.
327
+ Using `debug/open_nonstop` is useful if you want to open a backdoor to the application.
328
+ However, it is also danger because it can become another vulnerability.
329
+ Please use it carefully.
186
330
 
187
- ```
188
- $ ruby target.rb
189
- Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-5042)
331
+ By default, UNIX domain socket is used for the debugging port. To use TCP/IP, you can set the `RUBY_DEBUG_PORT` environment variable.
332
+
333
+ ```shell
334
+ $ RUBY_DEBUG_PORT=12345 ruby target.rb
190
335
  ```
191
336
 
192
- It runs target.rb and accept debugger connection within UNIX domain socket.
193
- The debuggee process waits for debugger connection at the beginning of `target.rb` like that:
337
+ ## Configuration
194
338
 
195
- ```
196
- $ rdbg -O ~/src/rb/target.rb
197
- DEBUGGER: Debugger can attach via UNIX domain socket (/home/ko1/.ruby-debug-sock/ruby-debug-ko1-29828)
198
- DEBUGGER: wait for debugger connection...
199
- ```
339
+ You can configure the debugger's behavior with debug commands and environment variables.
340
+ When the debug session is started, initial scripts are loaded so you can put your favorite configurations in the initial scripts.
200
341
 
201
- You can attach the program with the following command:
342
+ ### Configuration list
343
+
344
+ You can configure debugger's behavior with environment variables and `config` command. Each configuration has environment variable and the name which can be specified by `config` command.
202
345
 
203
346
  ```
204
- $ rdbg --attach # or rdbg -A for shorthand
205
-
206
- [1, 4] in /home/ko1/src/rb/target.rb
207
- 1| (1..).each do |i|
208
- => 2| sleep 0.5
209
- 3| p i
210
- 4| end
211
- --> #0 [C] /home/ko1/src/rb/target.rb:2:in `sleep'
212
- #1 /home/ko1/src/rb/target.rb:2:in `block in <main>' {|i=17|}
213
- #2 [C] /home/ko1/src/rb/target.rb:1:in `each'
214
- # and 1 frames (use `bt' command for all frames)
215
-
216
- (rdb)
347
+ # configuration example
348
+ config set log_level INFO
349
+ config set no_color true
217
350
  ```
218
351
 
219
- and you can input any debug commands. `c` (or `continue`) continues the debuggee process.
352
+ <% cat = nil; DEBUGGER__::CONFIG_SET.each do |key, (env, desc)| %>
353
+ <% /\A(\w+): (.+)/ =~ desc; if cat != $1; cat = 1 %>
354
+ * <%= $1 %>
355
+ <% cat = $1; end %> * `<%= env %>` (`<%= key %>`): <%= $2 %><% end %>
220
356
 
221
- You can detach the debugger from the debugger process with `quit` command.
222
- You can re-connect to the debuggee process by `rdbg -A` command again, and the debuggee process suspends the execution (and debugger can input any debug commands).
357
+ ### Initial scripts
223
358
 
224
- If you don't want to stop the debuggee process at the beginning of debuggee process (`target.rb`), you can use the following to specify "non-stop" option.
359
+ If there is `~/.rdbgrc`, the file is loaded as an initial script (which contains debug commands) when the debug session is started.
225
360
 
226
- * Use `rdbg -n` option
227
- * Set the environment variable `RUBY_DEBUG_NONSTOP=1`
361
+ * `RUBY_DEBUG_INIT_SCRIPT` environment variable can specify the initial script file.
362
+ * You can specify the initial script with `rdbg -x initial_script` (like gdb's `-x` option).
228
363
 
229
- If you are running multiple debuggee processes, the attach command (`rdbg -A`) shows the options like that:
364
+ Initial scripts are useful to write your favorite configurations.
365
+ For example, you can set break points with `break file:123` in `~/.rdbgrc`.
230
366
 
231
- ```
232
- $ rdbg --attach
233
- Please select a debug session:
234
- ruby-debug-ko1-19638
235
- ruby-debug-ko1-19603
236
- ```
367
+ If there are `~/.rdbgrc.rb` is available, it is also loaded as a ruby script at same timing.
237
368
 
238
- and you need to specify one (copy and paste the name):
369
+ ## Debug command on the debug console
239
370
 
240
- ```
241
- $ rdbg --attach ruby-debug-ko1-19638
242
- ```
371
+ On the debug console, you can use the following debug commands.
243
372
 
244
- The socket file is located at
245
- * `RUBY_DEBUG_SOCK_DIR` environment variable if available.
246
- * `XDG_RUNTIME_DIR` environment variable if available.
247
- * `$HOME/.ruby-debug-sock` if `$HOME` is available.
373
+ * `Enter` repeats the last command (useful when repeating `step`s).
374
+ * `Ctrl-D` is equal to `quit` command.
375
+ * [debug command compare sheet - Google Sheets](https://docs.google.com/spreadsheets/d/1TlmmUDsvwK4sSIyoMv-io52BUUz__R5wpu-ComXlsw0/edit?usp=sharing)
248
376
 
249
- ### Remote debug (2) TCP/IP
377
+ You can use the following debug commands. Each command should be written in 1 line.
378
+ The `[...]` notation means this part can be eliminate. For example, `s[tep]` means `s` or `step` are valid command. `ste` is not valid.
379
+ The `<...>` notation means the argument.
250
380
 
251
- You can open the TCP/IP port instead of using UNIX domain socket.
381
+ <%= DEBUGGER__.help %>
252
382
 
253
- #### (1) Use `rdbg` command
383
+ ## Debugger API
254
384
 
255
- ```
256
- $ rdbg -O --port=12345 target.rb
257
- # or
258
- $ rdbg --open --port=12345 target.rb
259
- Debugger can attach via TCP/IP (localhost:12345)
260
- ```
385
+ ### Start debugging
261
386
 
262
- #### (2) Use `-r debug/open` command line option
387
+ #### Start by requiring a library
263
388
 
389
+ You can start debugging without `rdbg` command by requiring the following libraries:
264
390
 
265
- ```
266
- $ RUBY_DEBUG_PORT=12345 ruby -r debug/open target.rb
267
- Debugger can attach via TCP/IP (localhost:12345)
268
- ```
391
+ * `require 'debug'`: Same as `rdbg --nonstop --no-sigint-hook`.
392
+ * `require 'debug/start'`: Same as `rdbg`.
393
+ * `require 'debug/open'`: Same as `rdbg --open`.
394
+ * `require 'debug/open_nonstop'`: Same as `rdbg --open --nonstop`.
269
395
 
270
- #### (3) Write `require 'debug/open'` in .rb files
396
+ You need to require one of them at the very beginning of the application.
397
+ Using `ruby -r` (for example `ruby -r debug/start target.rb`) is another way to invoke with debugger.
271
398
 
272
- ```ruby
273
- # target.rb
274
- require 'debug/open' # open the debugger entry point.
275
- ```
399
+ NOTE: Until Ruby 3.0, there is old `lib/debug.rb` standard library. So that if this gem is not installed, or if `Gemfile` missed to list this gem and `bundle exec` is used, you will see the following output:
276
400
 
277
- and run with environment variable RUBY_DEBUG_PORT
401
+ ```shell
402
+ $ ruby -r debug -e0
403
+ .../2.7.3/lib/ruby/2.7.0/x86_64-linux/continuation.so: warning: callcc is obsolete; use Fiber instead
404
+ Debug.rb
405
+ Emacs support available.
278
406
 
407
+ .../2.7.3/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:162: if RUBYGEMS_ACTIVATION_MONITOR.respond_to?(:mon_owned?)
408
+ (rdb:1)
279
409
  ```
280
- $ RUBY_DEBUG_PORT=12345 ruby target.rb
281
- Debugger can attach via TCP/IP (localhost:12345)
282
- ```
283
-
284
- or
285
410
 
286
- ```ruby
287
- # target.rb
288
- require 'debug/server' # introduce remote debugging feature
289
- DEBUGGER__.open(port: 12345)
290
- # or DEBUGGER__.open_tcp(port: 12345)
291
- ```
411
+ `lib/debug.rb` was not maintained well in recent years, and the purpose of this library is to rewrite old `lib/debug.rb` with recent techniques.
292
412
 
293
- ```
294
- $ ruby target.rb
295
- Debugger can attach via TCP/IP (localhost:12345)
296
- ```
413
+ #### Start by method
297
414
 
298
- You can also specify the host with the `RUBY_DEBUG_HOST` environment variable. And also `DEBUGGER__.open` method accepts a `host:` keyword parameter. If the host is not given, `localhost` will be used.
415
+ After loading `debug/session`, you can start debug session with the following methods. They are convenient if you want to specify debug configurations in your program.
299
416
 
300
- To attach the debuggee process, specify the port number (and hostname if needed) for the `rdbg --attach` (or `rdbg -A`) command.
417
+ * `DEBUGGER__.start(**kw)`: start debug session with local console.
418
+ * `DEBUGGER__.open(**kw)`: open debug port with configuration (without configurations open with UNIX domain socket)
419
+ * `DEBUGGER__.open_unix(**kw)`: open debug port with UNIX domain socket
420
+ * `DEBUGGER__.open_tcp(**kw)`: open debug port with TCP/IP
301
421
 
302
- ```
303
- $ rdbg --attach 12345
304
- $ rdbg --attach hostname 12345
305
- ```
422
+ For example:
306
423
 
307
- ### Initial scripts
424
+ ```ruby
425
+ require 'debug/session'
426
+ DEBUGGER__.start(no_color: true, # disable colorize
427
+ log_level: 'INFO') # Change log_level to INFO
308
428
 
309
- If there are `~/.rdbgrc`, the file is loaded as initial scripts which contains debugger commands at the beginning of debug session. `RUBY_DEBUG_INIT_SCRIPT` environment variable can specify the initial script file. You can write configurations in a file. For example, you can set break points with `break file:123` in `~/.rdbgrc`.
429
+ ... # your application code
430
+ ```
310
431
 
311
- If there are `~/.rdbgrc.rb` is available, it is loaded as a ruby script at same timing.
432
+ ### `binding.break` method
312
433
 
313
- ### Environment variables
434
+ `binding.break` (or `binding.b`) set breakpoints at written line. It also has several keywords.
314
435
 
315
- You can control debuggee's behavior with environment variables:
436
+ If `do: 'command'` is specified, the debugger suspends the program and run the `command` as a debug command and continue the program.
437
+ It is useful if you only want to call a debug command and don't want to stop there.
316
438
 
317
- * `RUBY_DEBUG_NONSTOP`: 1 for nonstop at the beginning of program.
318
- * `RUBY_DEBUG_INIT_SCRIPT`: Initial script path loaded at the first stop.
319
- * `RUBY_DEBUG_COMMANDS`: Debug commands invoked at the first stop. Commands should be separated by ';;'.
320
- * `RUBY_DEBUG_SHOW_SRC_LINES`: Show n lines source code on breakpoint (default: 10 lines).
321
- * `RUBY_DEBUG_SHOW_FRAMES`: Show n frames on breakpoint (default: 2 frames).
322
- * Remote debugging
323
- * `RUBY_DEBUG_PORT`: TCP/IP remote debugging: port to open.
324
- * `RUBY_DEBUG_HOST`: TCP/IP remote debugging: host (localhost if not given) to open.
325
- * `RUBY_DEBUG_SOCK_PATH`: UNIX Domain Socket remote debugging: socket path to open.
326
- * `RUBY_DEBUG_SOCK_DIR`: UNIX Domain Socket remote debugging: socket directory to open.
439
+ ```
440
+ def initialize
441
+ @a = 1
442
+ binding.b do: 'watch @a'
443
+ end
444
+ ```
327
445
 
328
- ## Debug command on the debug console
446
+ On this case, register a watch breakpoint for `@a` and continue to run.
329
447
 
330
- * `Enter` repeats the last command (useful when repeating `step`s).
331
- * `Ctrl-D` is equal to `quit` command.
332
- * [debug command compare sheet - Google Sheets](https://docs.google.com/spreadsheets/d/1TlmmUDsvwK4sSIyoMv-io52BUUz__R5wpu-ComXlsw0/edit?usp=sharing)
448
+ If `pre: 'command'` is specified, the debugger suspends the program and run the `command` as a debug command, and keep suspend.
449
+ It is useful if you have operations before suspend.
333
450
 
334
- You can use the following debug commands. Each command should be written in 1 line.
335
- The `[...]` notation means this part can be eliminate. For example, `s[tep]` means `s` or `step` are valid command. `ste` is not valid.
336
- The `<...>` notation means the argument.
451
+ ```
452
+ def foo
453
+ binding.b pre: 'p bar()'
454
+ ...
455
+ end
456
+ ```
337
457
 
338
- <%= DEBUGGER__.help %>
458
+ On this case, you can see the result of `bar()` every time you stop there.
339
459
 
340
460
  ## rdbg command help
341
461
 
@@ -346,6 +466,7 @@ The `<...>` notation means the argument.
346
466
  # Contributing
347
467
 
348
468
  Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/debug.
469
+ This debugger is not mature so your feedback will help us.
349
470
 
350
471
  Please also check the [contributing guideline](/CONTRIBUTING.md).
351
472