gdbdump 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
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