gdbdump 0.9.2 → 0.9.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4404278dd2a252a8c175717c167a796adee717c6
4
- data.tar.gz: 5b6e430c94796dab5eab7db5933c83757455c295
3
+ metadata.gz: 47f96b6948a61ee96134de40f22548c97d265549
4
+ data.tar.gz: 406b7e0a333f356278bc813082cbffc599f7fcc6
5
5
  SHA512:
6
- metadata.gz: eb73707296f26c46c4c8e8def9a9cab0584e27c6f5c14d62b8b549cb90ca047ccaa8bd17c1dffcefa0063c5e46484f4ab0fc0f3f8d241093e5f38d5eb3136a25
7
- data.tar.gz: 6c6ead8c0f79e04ace82dc5dc68fca17fdce94ece83a346110bab569505415b79308b6dd8c3bd281cb97ef4c7bbdcd3184a3f4a6df8d01942650d73f7f50237f
6
+ metadata.gz: 73adc0c34ac5e358de859b99be87e59da5558cce6fbcc1ba5ffc01d366d1c0d3fe27abe82afc1b2966dccd6b9165e09932147402a09f29172b7345fc30a0e4b3
7
+ data.tar.gz: eea4efc06c19748d84b626b6593a2afcb89ab9876f5e44c3686658bf222ce9f30d2a875de4efd4ff3db78373b5a5b532655cee35a21db5ea013d733794fe5486
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ # 0.9.3
2
+
3
+ Enhancements:
4
+
5
+ * Trivial enhancements of error messages
6
+
1
7
  # 0.9.2
2
8
 
3
9
  Enhancements:
data/README.md CHANGED
@@ -21,7 +21,7 @@ It was verfied that gdbdump works with ruby executables built by [rbenv/ruby-bui
21
21
  ```
22
22
  Usage: gdbdump [options] pid
23
23
  -d, --[no-]debug print debug log (default: false)
24
- -x, --gdbinit FILE path to ruby trunk's .gdbinit (default: some of ruby trunk's .gdbinit is pre-bundle in this gem)
24
+ -x, --gdbinit FILE path to ruby repo's .gdbinit (default: some of ruby repo's .gdbinit is pre-bundle in this gem)
25
25
  --gdb PATH path to gdb command (default: gdb)
26
26
  --ruby PATH path to ruby which the attached process uses (default: get from /proc/[PID]/exe)
27
27
  ```
@@ -30,7 +30,7 @@ Usage: gdbdump [options] pid
30
30
 
31
31
  Default supported ruby versions: 2.1.x - 2.4.x
32
32
 
33
- Ruby trunk's [.gdbinit](https://github.com/ruby/ruby/blob/trunk/.gdbinit) file defines useful helper functions and it is maintained by ruby core team. `gdbdump` uses it.
33
+ Ruby repo's [.gdbinit](https://github.com/ruby/ruby/blob/trunk/.gdbinit) file defines useful helper functions and it is maintained by ruby core team. `gdbdump` uses it.
34
34
  Some versions written as above of .gdbinit are bundled in this gem, but if you want to use `gdbdump` for older or newer ruby versions:
35
35
 
36
36
  1. Download .gdbinit from ruby repo like [ruby/2.4.1/.gdbinit](https://github.com/ruby/ruby/blob/v2_4_1/.gdbinit), and specify with `-x` option
@@ -76,11 +76,11 @@ loop.rb:11:in `block in <main>'
76
76
  * You can print C level backtrace with raw gdb, of course
77
77
  * [sigdump](https://github.com/frsyuki/sigdump)
78
78
  * sigdump enables to print ruby level backtrace with sending CONT signal to living ruby process.
79
- * The ruby process must pre-install `sigdump` gem and `require 'sigdump/setup'` unlike gdbdump.
79
+ * The ruby process **must pre-install** `sigdump` gem and `require 'sigdump/setup'` unlike gdbdump.
80
80
  * sigdump prints backtrace in signal handler, so blocks main thread, but other threads still work unlike gdbdump.
81
81
  * [gdbruby](https://github.com/gunyarakun/gdbruby)
82
82
  * gdbruby enables to print C level and ruby level backtrace of living ruby process and core file.
83
- * gdbruby must follow changes of C level interfaces of CRuby to get backtrace of the core file, it rises fragility that it will be broken on newer ruby versions.
83
+ * gdbruby **must follow changes of C level interfaces of CRuby** to get backtrace of the core file, it rises fragility that it will be broken on newer ruby versions.
84
84
  * gdbruby stops the process during printing backtrace as gdbdump, but it supports also core file. Using `gcore` command to get core file, it would be possible to analyze without stopping the process.
85
85
 
86
86
  ## Development
@@ -89,6 +89,70 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
89
89
 
90
90
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
91
91
 
92
+ ### Investigation
93
+
94
+ Belows are my investigation notes about how to print C level and Ruby level backtrace via gdb.
95
+
96
+ #### (1) rb_print_backtrace() and rb_backtrace()
97
+
98
+ CRuby itself has [rb_print_backtrace](https://github.com/ruby/ruby/blob/26864584d269b6141a27c783cf8b751c067c7dbe/vm_dump.c#L671) function to print C level backtrace, and [rb_backtrace](https://github.com/ruby/ruby/blob/eb59047e2aabb050b23061d513f7b89dc2905670/vm_backtrace.c#L770) function to print Ruby level backtrace.
99
+ I first tried to use them.
100
+
101
+ However, they print a backtrace of only current thread. Furthermore, rb_print_backtrace supports printing outputs to only STDERR.
102
+
103
+ ```ruby
104
+ def print_backtrace
105
+ run do |gdb|
106
+ gdb.cmd_exec('call write(2, "== c backtrace ==\n", 18)')
107
+ gdb.cmd_exec('call rb_print_backtrace()')
108
+ gdb.cmd_exec('call write(2, "== ruby backtrace ==\n", 21)')
109
+ gdb.cmd_exec('call rb_backtrace()')
110
+ end
111
+ end
112
+ ```
113
+
114
+ #### (2) bt and rb_eval_string()
115
+
116
+ I secondly tried to use GDB's `info threads` and `bt` command to print C level backtrace. This was fine.
117
+
118
+ I also tried to print Ruby level backtrace by calling [rb_eval_string](https://github.com/ruby/ruby/blob/44396dbe123511678710cfb21223c954b9ceaafb/vm_eval.c#L1474) with Ruby codes as:
119
+
120
+ ```ruby
121
+ def ruby_backtrace_code
122
+ code = +%Q[File.open('#{dumpfile}', 'a') {|f|]
123
+ code << %q[
124
+ Thread.list.each {|th|
125
+ f.write %Q[ Thread #{th} status=#{th.status} priority=#{th.priority}\n]
126
+ th.backtrace.each {|bt|
127
+ f.write %Q[ #{bt}\n]
128
+ }
129
+ }
130
+ }]
131
+ code.split("\n").map(&:strip).join('; ')
132
+ end
133
+
134
+ def print_backtrace
135
+ run do |gdb|
136
+ gdb.cmd_exec(%Q[call rb_eval_string("#{ruby_backtrace_code}")])
137
+ end
138
+ end
139
+ ```
140
+
141
+ However, the debugee (target) process got stuck after `call rb_eval_string`. It seemed the ruby process will be broken if ruby codes are executed via gdb.
142
+
143
+ #### (3) rb_ps from ruby trunk's .gdbinit
144
+
145
+ I thirdly tried to use `rb_ps` function defined in [.gdbinit](https://github.com/ruby/ruby/blob/44396dbe123511678710cfb21223c954b9ceaafb/.gdbinit#L983) of ruby repository to print C level and Ruby level backtrace of all threads.
146
+
147
+ Since `.gdbinit` is maintained by ruby core team, I do not need to follow changes of C level interfaces of CRuby as long as I follow `.gdbinit`.
148
+
149
+ The drawback of this way is that
150
+
151
+ 1. I have to follow changes of `.gdbinit` in newer ruby versions
152
+ 2. `rb_ps` takes somewhat long time like 2.6 seconds to print backtrace.
153
+
154
+ Currently, I am taking this way.
155
+
92
156
  ## Contributing
93
157
 
94
158
  Bug reports and pull requests are welcome on GitHub at https://github.com/sonots/gdbdump. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/lib/gdbdump/cli.rb CHANGED
@@ -24,7 +24,7 @@ class Gdbdump
24
24
  op.on('-d', '--[no-]debug', "print debug log (default: #{opts[:debug]})") {|v|
25
25
  opts[:debug] = v
26
26
  }
27
- op.on('-x', '--gdbinit FILE', "path to ruby trunk's .gdbinit (default: some of ruby trunk's .gdbinit is pre-bundle in this gem)") {|v|
27
+ op.on('-x', '--gdbinit FILE', "path to ruby repo's .gdbinit (default: some of ruby repo's .gdbinit are pre-bundle in this gem)") {|v|
28
28
  opts[:gdbinit] = v
29
29
  }
30
30
  op.on('--gdb PATH', "path to gdb command (default: gdb)") {|v|
data/lib/gdbdump/gdb.rb CHANGED
@@ -13,8 +13,12 @@ class Gdbdump
13
13
  @pid = pid.to_s
14
14
  @debug = debug
15
15
  @gdb = gdb || 'gdb'
16
- @ruby = ruby || Procfs.new(@pid).exe
17
- @gdbinit = gdbinit || File.join(ROOT, 'vendor', 'ruby', ruby_minor_version, 'gdbinit')
16
+ @ruby = (ruby || Procfs.new(@pid).exe).tap do |path|
17
+ raise "ruby #{path} is not accessible" unless File.executable?(path)
18
+ end
19
+ @gdbinit = (gdbinit || File.join(ROOT, 'vendor', 'ruby', ruby_minor_version, 'gdbinit')).tap do |path|
20
+ raise "gdbinit #{path} is not readable" unless File.readable?(path)
21
+ end
18
22
  @exec_options = [SUDO_CMD, @gdb, '-silent', '-nw', '-x', @gdbinit, @ruby, @pid]
19
23
  end
20
24
 
@@ -1,3 +1,3 @@
1
1
  class Gdbdump
2
- VERSION = "0.9.2"
2
+ VERSION = "0.9.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gdbdump
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.2
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Naotoshi Seo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-02 00:00:00.000000000 Z
11
+ date: 2017-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler