gdbdump 0.1.0 → 0.9.0
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/CHANGELOG.md +16 -0
- data/Gemfile +1 -1
- data/README.md +54 -33
- data/example/loop.rb +18 -0
- data/lib/gdbdump.rb +5 -0
- data/lib/gdbdump/cli.rb +9 -1
- data/lib/gdbdump/gdb.rb +36 -16
- data/lib/gdbdump/procfs.rb +2 -2
- data/lib/gdbdump/version.rb +1 -1
- data/vendor/ruby/2.3.0/gdbinit +966 -0
- data/vendor/ruby/2.3.1/gdbinit +1 -0
- data/vendor/ruby/2.3.2/gdbinit +1 -0
- data/vendor/ruby/2.3.3/gdbinit +1 -0
- data/vendor/ruby/2.3.4/gdbinit +1 -0
- data/vendor/ruby/2.4.0/gdbinit +1215 -0
- data/vendor/ruby/2.4.1/gdbinit +1 -0
- data/vendor/ruby/LICENSE +1 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 806c8f4485ae5cfad83522a88e00ea3a625d7ed5
|
4
|
+
data.tar.gz: a125ef9b802bb4cece94f042a11340a3ca862296
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e9373b1893dac6dad697b3eb95dca41e0f43d64b2400e136e9387850755152474e472e0c5038a1ee181e180dfb4e3e8d0bbb7d365bf263a8c2b973cc4e405e0
|
7
|
+
data.tar.gz: f2eb578d9859bbccd7149156bba3e1a35dcedb70dab66915597c6bbea807492c426e3da7b076d7588b8776f0c4c79c7bc9a51b01a3d77a6542ee5246c6031615
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# 0.9.0
|
2
|
+
|
3
|
+
Enhancements:
|
4
|
+
|
5
|
+
* Use rb_ps defined in ruby trunk .gdbinit to
|
6
|
+
* get backtrace of all treads
|
7
|
+
* print backtrace to STDOUT of gdbdump process, rather than STDERR of the attached process
|
8
|
+
* Use `sudo` to execute gdb command inside so that
|
9
|
+
* we can run as `$ gdbdump PID` rather than `$ sudo /path/to/ruby gdbdump PID`
|
10
|
+
* (previously, it was burdensome to use rbenv rubys and bundler via sudo)
|
11
|
+
|
12
|
+
# 0.1.0
|
13
|
+
|
14
|
+
First version
|
15
|
+
|
16
|
+
* Use rb_backtrace (for ruby level backtrace) and rb_print_backtrace (for C level backtrace)
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,64 +1,85 @@
|
|
1
|
-
#
|
1
|
+
# gdbdump
|
2
2
|
|
3
|
-
Print C level and Ruby level backtrace of living process using gdb
|
3
|
+
Print C level and Ruby level backtrace of living ruby process using gdb
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
7
|
+
```
|
8
|
+
$ gem install gdbdump
|
9
|
+
```
|
8
10
|
|
9
11
|
## Requirements
|
10
12
|
|
11
|
-
*
|
12
|
-
*
|
13
|
-
|
14
|
-
I verified that this gem works with ruby executables built by [rbenv/ruby-build](https://github.com/rbenv/ruby-build).
|
13
|
+
* gdb
|
14
|
+
* linux
|
15
|
+
* `sudo gdb` must be allowed
|
15
16
|
|
16
|
-
|
17
|
+
It was verfied that gdbdump works with ruby executables built by [rbenv/ruby-build](https://github.com/rbenv/ruby-build).
|
17
18
|
|
18
|
-
|
19
|
+
## Usage
|
19
20
|
|
20
21
|
```
|
21
|
-
|
22
|
+
Usage: gdbdump [options] [pid|prog pid]
|
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 bundle in this gem, and used})
|
25
|
+
--gdb PATH path to gdb command (default: gdb)
|
22
26
|
```
|
23
27
|
|
24
|
-
|
28
|
+
### .gdbinit
|
25
29
|
|
26
|
-
|
27
|
-
== c backtrace ==
|
28
|
-
/home/ubuntu/.rbenv/versions/2.4.1/bin/ruby(rb_print_backtrace+0x15) [0x7fd23062c115] vm_dump.c:684
|
29
|
-
[0x7ffc98c378af]
|
30
|
-
== ruby backtrace ==
|
31
|
-
from loop.rb:3:in `<main>'
|
32
|
-
from loop.rb:3:in `loop'
|
33
|
-
from loop.rb:5:in `block in <main>'
|
34
|
-
from loop.rb:5:in `sleep'
|
35
|
-
```
|
30
|
+
Default supported ruby versions: 2.3.0 - 2.4.1
|
36
31
|
|
37
|
-
|
32
|
+
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
|
+
Some versions of .gdbinit are bundled in this gem, but if you want to use `gdbdump` for older or newer ruby versions:
|
34
|
+
|
35
|
+
1. Download .gdbinit from ruby repo like https://github.com/ruby/ruby/blob/v2_4_1/.gdbinit, and specify with `-x` option
|
36
|
+
2. Or, send PR to bundle the .gdbinit in `gdbdump` gem.
|
37
|
+
|
38
|
+
## Example
|
39
|
+
|
40
|
+
With living ruby 2.4.1 process of pid 1897,
|
38
41
|
|
39
42
|
```
|
40
|
-
|
41
|
-
-d, --[no-]debug print debug log (default: false)
|
43
|
+
$ gdbdump 1897
|
42
44
|
```
|
43
45
|
|
44
|
-
|
46
|
+
You will see C and Ruby level backtrace on STDERR of **the target process** of pid 1897 as:
|
45
47
|
|
46
|
-
|
48
|
+
```
|
49
|
+
$1 = (rb_vm_t *) 0x7f46bb071f20
|
50
|
+
* #<Thread:0x7f46bb0a5ee8 rb_thread_t:0x7f46bb0725d0 native_thread:0x7f46ba514740>
|
51
|
+
0x7f46ba16d700 <thread_join_m at thread.c:980>:in `join'
|
52
|
+
loop.rb:17:in `<main>'
|
53
|
+
* #<Thread:0x7f46bb202750 rb_thread_t:0x7f46bb3e03d0 native_thread:0x7f46b89c0700>
|
54
|
+
0x7f46ba0e4f30 <rb_f_sleep at process.c:4388>:in `sleep'
|
55
|
+
loop.rb:6:in `block (2 levels) in <main>'
|
56
|
+
0x7f46ba1a72b0 <rb_f_loop at vm_eval.c:1137>:in `loop'
|
57
|
+
loop.rb:4:in `block in <main>'
|
58
|
+
* #<Thread:0x7f46bb202660 rb_thread_t:0x7f46bb3e47e0 native_thread:0x7f46b87be700>
|
59
|
+
0x7f46ba0e4f30 <rb_f_sleep at process.c:4388>:in `sleep'
|
60
|
+
loop.rb:13:in `block (2 levels) in <main>'
|
61
|
+
0x7f46ba1a72b0 <rb_f_loop at vm_eval.c:1137>:in `loop'
|
62
|
+
loop.rb:11:in `block in <main>'
|
63
|
+
```
|
47
64
|
|
48
|
-
|
65
|
+
## FAQ
|
49
66
|
|
50
|
-
|
67
|
+
Q. How this work?
|
68
|
+
A. Attach to the ruby process with gdb, and call `rb_ps` defined in gdbinit. That's it.
|
51
69
|
|
52
|
-
|
53
|
-
|
54
|
-
* If they are available, gdbdump can dump to a file and, then read and print into STDOUT of gdbdump process.
|
70
|
+
Q. Is this available for production process?
|
71
|
+
A. GDB stops the process during printing backtrace, would cause some issues
|
55
72
|
|
56
73
|
## Comparisons
|
57
74
|
|
58
75
|
* gdb
|
59
|
-
* You can
|
76
|
+
* You can print C level backtrace with raw gdb, of course
|
60
77
|
* [sigdump](https://github.com/frsyuki/sigdump)
|
61
|
-
*
|
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.
|
80
|
+
* [gdbruby](https://github.com/gunyarakun/gdbruby)
|
81
|
+
* gdbruby enables to print C level and ruby level backtrace of living ruby process and core file.
|
82
|
+
* 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.
|
62
83
|
|
63
84
|
## Development
|
64
85
|
|
data/example/loop.rb
ADDED
data/lib/gdbdump.rb
CHANGED
data/lib/gdbdump/cli.rb
CHANGED
@@ -16,11 +16,19 @@ class Gdbdump
|
|
16
16
|
|
17
17
|
opts = {
|
18
18
|
debug: false,
|
19
|
+
gdbinit: nil,
|
20
|
+
gdb: nil,
|
19
21
|
}
|
20
22
|
|
21
23
|
op.on('-d', '--[no-]debug', "print debug log (default: #{opts[:debug]})") {|v|
|
22
24
|
opts[:debug] = v
|
23
25
|
}
|
26
|
+
op.on('-x', '--gdbinit FILE', "path to ruby trunk's .gdbinit (default: some of ruby trunk's .gdbinit is bundle in this gem, and used})") {|v|
|
27
|
+
opts[:gdbinit] = v
|
28
|
+
}
|
29
|
+
op.on('--gdb PATH', "path to gdb command (default: gdb)") {|v|
|
30
|
+
opts[:gdb] = v
|
31
|
+
}
|
24
32
|
|
25
33
|
op.banner += ' [pid|prog pid]'
|
26
34
|
begin
|
@@ -43,7 +51,7 @@ class Gdbdump
|
|
43
51
|
|
44
52
|
def run
|
45
53
|
parse_options
|
46
|
-
GDB.new(pid: @pid, prog: @prog,
|
54
|
+
GDB.new(pid: @pid, prog: @prog, **(@opts)).print_backtrace
|
47
55
|
end
|
48
56
|
end
|
49
57
|
end
|
data/lib/gdbdump/gdb.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen-string-literal: true
|
1
2
|
require 'open3'
|
2
3
|
|
3
4
|
class Gdbdump
|
@@ -6,27 +7,36 @@ class Gdbdump
|
|
6
7
|
# end
|
7
8
|
class GDB
|
8
9
|
COMMAND_READ_BUFFER_SIZE = 1024
|
10
|
+
STRINGS_CMD = 'strings'
|
11
|
+
SUDO_CMD = 'sudo'
|
9
12
|
|
10
|
-
def initialize(pid:, prog
|
11
|
-
@prog = prog
|
13
|
+
def initialize(pid:, prog: nil, debug: false, gdbinit: nil, gdb: nil)
|
12
14
|
@pid = pid.to_s
|
15
|
+
@prog = prog
|
13
16
|
@debug = debug
|
14
|
-
@
|
17
|
+
@gdbinit = gdbinit || File.join(ROOT, 'vendor', 'ruby', ruby_version, 'gdbinit')
|
18
|
+
@gdb = gdb || 'gdb'
|
19
|
+
@exec_options = [SUDO_CMD, @gdb, '-silent', '-nw', '-x', @gdbinit, @prog, @pid]
|
15
20
|
end
|
16
21
|
|
17
22
|
def print_backtrace
|
18
23
|
run do |gdb|
|
19
|
-
gdb.cmd_exec('
|
20
|
-
|
21
|
-
|
22
|
-
gdb.cmd_exec('call rb_backtrace()')
|
24
|
+
out, err = gdb.cmd_exec('rb_ps')
|
25
|
+
$stdout.puts out
|
26
|
+
$stderr.puts err unless err.empty?
|
23
27
|
end
|
28
|
+
# run do |gdb|
|
29
|
+
# gdb.cmd_exec('call write(2, "== c backtrace ==\n", 18)')
|
30
|
+
# gdb.cmd_exec('call rb_print_backtrace()')
|
31
|
+
# gdb.cmd_exec('call write(2, "== ruby backtrace ==\n", 21)')
|
32
|
+
# gdb.cmd_exec('call rb_backtrace()')
|
33
|
+
# end
|
24
34
|
end
|
25
35
|
|
26
36
|
def run
|
27
37
|
@stdin, @stdout, @stderr = Open3.popen3(*@exec_options)
|
28
|
-
if get_response =~ /ptrace: Operation not permitted
|
29
|
-
raise '
|
38
|
+
if get_response =~ /ptrace: Operation not permitted/
|
39
|
+
raise 'root privilege is required'
|
30
40
|
end
|
31
41
|
prepare
|
32
42
|
begin
|
@@ -40,6 +50,15 @@ class Gdbdump
|
|
40
50
|
end
|
41
51
|
end
|
42
52
|
|
53
|
+
# ToDo: Any faster way to get ruby_version from pid?
|
54
|
+
# NOTE: I want ruby_version before starting gdb
|
55
|
+
def ruby_version
|
56
|
+
return @ruby_version if @ruby_version
|
57
|
+
ret = `#{STRINGS_CMD} #{@prog}`
|
58
|
+
line = ret.lines.find {|_| _.start_with?('RUBY_VERSION "') }
|
59
|
+
@ruby_version = line[14..-3] if line
|
60
|
+
end
|
61
|
+
|
43
62
|
def cmd_exec(cmd)
|
44
63
|
log('C', cmd)
|
45
64
|
if cmd
|
@@ -52,18 +71,19 @@ class Gdbdump
|
|
52
71
|
end
|
53
72
|
|
54
73
|
def get_response
|
55
|
-
|
56
|
-
|
74
|
+
out = +''
|
57
75
|
loop do
|
58
76
|
begin
|
59
77
|
buf = @stdout.sysread(COMMAND_READ_BUFFER_SIZE)
|
60
78
|
rescue EOFError
|
61
79
|
break
|
62
80
|
end
|
63
|
-
response << buf
|
64
81
|
break if buf =~ /\(gdb\) $/
|
82
|
+
out << buf
|
65
83
|
end
|
84
|
+
log('O', out)
|
66
85
|
|
86
|
+
err = +''
|
67
87
|
loop do
|
68
88
|
begin
|
69
89
|
buf = @stderr.read_nonblock(COMMAND_READ_BUFFER_SIZE)
|
@@ -72,17 +92,16 @@ class Gdbdump
|
|
72
92
|
rescue EOFError
|
73
93
|
break
|
74
94
|
end
|
75
|
-
|
95
|
+
err << buf if buf
|
76
96
|
end
|
97
|
+
log('E', err)
|
77
98
|
|
78
|
-
|
79
|
-
response
|
99
|
+
[out, err]
|
80
100
|
end
|
81
101
|
|
82
102
|
private
|
83
103
|
|
84
104
|
def prepare
|
85
|
-
cmd_exec('')
|
86
105
|
cmd_exec('set pagination off')
|
87
106
|
end
|
88
107
|
|
@@ -93,6 +112,7 @@ class Gdbdump
|
|
93
112
|
|
94
113
|
def log(pre, message)
|
95
114
|
return unless @debug
|
115
|
+
return if message.nil? or message.empty?
|
96
116
|
message.each_line do |line|
|
97
117
|
puts "#{pre}: #{line}"
|
98
118
|
end
|
data/lib/gdbdump/procfs.rb
CHANGED
@@ -8,9 +8,9 @@ class Gdbdump
|
|
8
8
|
|
9
9
|
def exe
|
10
10
|
begin
|
11
|
-
File.readlink("/proc/#{@pid}/exe")
|
11
|
+
@exe ||= File.readlink("/proc/#{@pid}/exe")
|
12
12
|
rescue Errno::ENOENT
|
13
|
-
raise "/proc/#{@pid}/exe does not exist, it seems pid #{@pid}
|
13
|
+
raise "/proc/#{@pid}/exe does not exist, it seems no process of pid #{@pid} exists"
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
data/lib/gdbdump/version.rb
CHANGED
@@ -0,0 +1,966 @@
|
|
1
|
+
define hook-run
|
2
|
+
set $color_type = 0
|
3
|
+
set $color_highlite = 0
|
4
|
+
set $color_end = 0
|
5
|
+
end
|
6
|
+
|
7
|
+
define ruby_gdb_init
|
8
|
+
if !$color_type
|
9
|
+
set $color_type = "\033[31m"
|
10
|
+
end
|
11
|
+
if !$color_highlite
|
12
|
+
set $color_highlite = "\033[36m"
|
13
|
+
end
|
14
|
+
if !$color_end
|
15
|
+
set $color_end = "\033[m"
|
16
|
+
end
|
17
|
+
if ruby_dummy_gdb_enums.special_consts
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# set prompt \033[36m(gdb)\033[m\040
|
22
|
+
|
23
|
+
define rp
|
24
|
+
ruby_gdb_init
|
25
|
+
if (VALUE)($arg0) & RUBY_FIXNUM_FLAG
|
26
|
+
printf "FIXNUM: %ld\n", (long)($arg0) >> 1
|
27
|
+
else
|
28
|
+
if ((VALUE)($arg0) & ~(~(VALUE)0<<RUBY_SPECIAL_SHIFT)) == RUBY_SYMBOL_FLAG
|
29
|
+
set $id = (($arg0) >> RUBY_SPECIAL_SHIFT)
|
30
|
+
printf "%sSYMBOL%s: ", $color_type, $color_end
|
31
|
+
rp_id $id
|
32
|
+
else
|
33
|
+
if ($arg0) == RUBY_Qfalse
|
34
|
+
echo false\n
|
35
|
+
else
|
36
|
+
if ($arg0) == RUBY_Qtrue
|
37
|
+
echo true\n
|
38
|
+
else
|
39
|
+
if ($arg0) == RUBY_Qnil
|
40
|
+
echo nil\n
|
41
|
+
else
|
42
|
+
if ($arg0) == RUBY_Qundef
|
43
|
+
echo undef\n
|
44
|
+
else
|
45
|
+
if (VALUE)($arg0) & RUBY_IMMEDIATE_MASK
|
46
|
+
if ((VALUE)($arg0) & RUBY_FLONUM_MASK) == RUBY_FLONUM_FLAG
|
47
|
+
printf "%sFLONUM%s: %g\n", $color_type, $color_end, (double)rb_float_value($arg0)
|
48
|
+
else
|
49
|
+
echo immediate\n
|
50
|
+
end
|
51
|
+
else
|
52
|
+
set $flags = ((struct RBasic*)($arg0))->flags
|
53
|
+
if ($flags & RUBY_FL_PROMOTED) == RUBY_FL_PROMOTED
|
54
|
+
printf "[PROMOTED] "
|
55
|
+
end
|
56
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_NONE
|
57
|
+
printf "%sT_NONE%s: ", $color_type, $color_end
|
58
|
+
print (struct RBasic *)($arg0)
|
59
|
+
else
|
60
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_NIL
|
61
|
+
printf "%sT_NIL%s: ", $color_type, $color_end
|
62
|
+
print (struct RBasic *)($arg0)
|
63
|
+
else
|
64
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_OBJECT
|
65
|
+
printf "%sT_OBJECT%s: ", $color_type, $color_end
|
66
|
+
print (struct RObject *)($arg0)
|
67
|
+
else
|
68
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_CLASS
|
69
|
+
printf "%sT_CLASS%s%s: ", $color_type, ($flags & RUBY_FL_SINGLETON) ? "*" : "", $color_end
|
70
|
+
rp_class $arg0
|
71
|
+
else
|
72
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_ICLASS
|
73
|
+
printf "%sT_ICLASS%s: ", $color_type, $color_end
|
74
|
+
rp_class $arg0
|
75
|
+
else
|
76
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_MODULE
|
77
|
+
printf "%sT_MODULE%s: ", $color_type, $color_end
|
78
|
+
rp_class $arg0
|
79
|
+
else
|
80
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_FLOAT
|
81
|
+
printf "%sT_FLOAT%s: %.16g ", $color_type, $color_end, (((struct RFloat*)($arg0))->float_value)
|
82
|
+
print (struct RFloat *)($arg0)
|
83
|
+
else
|
84
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_STRING
|
85
|
+
printf "%sT_STRING%s: ", $color_type, $color_end
|
86
|
+
rp_string $arg0 $flags
|
87
|
+
else
|
88
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_REGEXP
|
89
|
+
set $regsrc = ((struct RRegexp*)($arg0))->src
|
90
|
+
set $rsflags = ((struct RBasic*)$regsrc)->flags
|
91
|
+
printf "%sT_REGEXP%s: ", $color_type, $color_end
|
92
|
+
set print address off
|
93
|
+
output (char *)(($rsflags & RUBY_FL_USER1) ? \
|
94
|
+
((struct RString*)$regsrc)->as.heap.ptr : \
|
95
|
+
((struct RString*)$regsrc)->as.ary)
|
96
|
+
set print address on
|
97
|
+
printf " len:%ld ", ($rsflags & RUBY_FL_USER1) ? \
|
98
|
+
((struct RString*)$regsrc)->as.heap.len : \
|
99
|
+
(($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
|
100
|
+
if $flags & RUBY_FL_USER6
|
101
|
+
printf "(none) "
|
102
|
+
end
|
103
|
+
if $flags & RUBY_FL_USER5
|
104
|
+
printf "(literal) "
|
105
|
+
end
|
106
|
+
if $flags & RUBY_FL_USER4
|
107
|
+
printf "(fixed) "
|
108
|
+
end
|
109
|
+
printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT
|
110
|
+
print (struct RRegexp *)($arg0)
|
111
|
+
else
|
112
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_ARRAY
|
113
|
+
if ($flags & RUBY_FL_USER1)
|
114
|
+
set $len = (($flags & (RUBY_FL_USER3|RUBY_FL_USER4)) >> (RUBY_FL_USHIFT+3))
|
115
|
+
printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len
|
116
|
+
printf "(embed) "
|
117
|
+
if ($len == 0)
|
118
|
+
printf "{(empty)} "
|
119
|
+
else
|
120
|
+
output/x *((VALUE*)((struct RArray*)($arg0))->as.ary) @ $len
|
121
|
+
printf " "
|
122
|
+
end
|
123
|
+
else
|
124
|
+
set $len = ((struct RArray*)($arg0))->as.heap.len
|
125
|
+
printf "%sT_ARRAY%s: len=%ld ", $color_type, $color_end, $len
|
126
|
+
if ($flags & RUBY_FL_USER2)
|
127
|
+
printf "(shared) shared="
|
128
|
+
output/x ((struct RArray*)($arg0))->as.heap.aux.shared
|
129
|
+
printf " "
|
130
|
+
else
|
131
|
+
printf "(ownership) capa=%ld ", ((struct RArray*)($arg0))->as.heap.aux.capa
|
132
|
+
end
|
133
|
+
if ($len == 0)
|
134
|
+
printf "{(empty)} "
|
135
|
+
else
|
136
|
+
output/x *((VALUE*)((struct RArray*)($arg0))->as.heap.ptr) @ $len
|
137
|
+
printf " "
|
138
|
+
end
|
139
|
+
end
|
140
|
+
print (struct RArray *)($arg0)
|
141
|
+
else
|
142
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_FIXNUM
|
143
|
+
printf "%sT_FIXNUM%s: ", $color_type, $color_end
|
144
|
+
print (struct RBasic *)($arg0)
|
145
|
+
else
|
146
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_HASH
|
147
|
+
printf "%sT_HASH%s: ", $color_type, $color_end,
|
148
|
+
if ((struct RHash *)($arg0))->ntbl
|
149
|
+
printf "len=%ld ", ((struct RHash *)($arg0))->ntbl->num_entries
|
150
|
+
end
|
151
|
+
print (struct RHash *)($arg0)
|
152
|
+
else
|
153
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT
|
154
|
+
printf "%sT_STRUCT%s: len=%ld ", $color_type, $color_end, \
|
155
|
+
(($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \
|
156
|
+
($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) >> (RUBY_FL_USHIFT+1) : \
|
157
|
+
((struct RStruct *)($arg0))->as.heap.len)
|
158
|
+
print (struct RStruct *)($arg0)
|
159
|
+
x/xw (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \
|
160
|
+
((struct RStruct *)($arg0))->as.ary : \
|
161
|
+
((struct RStruct *)($arg0))->as.heap.ptr)
|
162
|
+
else
|
163
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_BIGNUM
|
164
|
+
printf "%sT_BIGNUM%s: sign=%d len=%ld ", $color_type, $color_end, \
|
165
|
+
(($flags & RUBY_FL_USER1) != 0), \
|
166
|
+
(($flags & RUBY_FL_USER2) ? \
|
167
|
+
($flags & (RUBY_FL_USER5|RUBY_FL_USER4|RUBY_FL_USER3)) >> (RUBY_FL_USHIFT+3) : \
|
168
|
+
((struct RBignum*)($arg0))->as.heap.len)
|
169
|
+
if $flags & RUBY_FL_USER2
|
170
|
+
printf "(embed) "
|
171
|
+
end
|
172
|
+
print (struct RBignum *)($arg0)
|
173
|
+
x/xw (($flags & RUBY_FL_USER2) ? \
|
174
|
+
((struct RBignum*)($arg0))->as.ary : \
|
175
|
+
((struct RBignum*)($arg0))->as.heap.digits)
|
176
|
+
else
|
177
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_RATIONAL
|
178
|
+
printf "%sT_RATIONAL%s: ", $color_type, $color_end
|
179
|
+
print (struct RRational *)($arg0)
|
180
|
+
else
|
181
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_COMPLEX
|
182
|
+
printf "%sT_COMPLEX%s: ", $color_type, $color_end
|
183
|
+
print (struct RComplex *)($arg0)
|
184
|
+
else
|
185
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_FILE
|
186
|
+
printf "%sT_FILE%s: ", $color_type, $color_end
|
187
|
+
print (struct RFile *)($arg0)
|
188
|
+
output *((struct RFile *)($arg0))->fptr
|
189
|
+
printf "\n"
|
190
|
+
else
|
191
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_TRUE
|
192
|
+
printf "%sT_TRUE%s: ", $color_type, $color_end
|
193
|
+
print (struct RBasic *)($arg0)
|
194
|
+
else
|
195
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_FALSE
|
196
|
+
printf "%sT_FALSE%s: ", $color_type, $color_end
|
197
|
+
print (struct RBasic *)($arg0)
|
198
|
+
else
|
199
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_DATA
|
200
|
+
if ((struct RTypedData *)($arg0))->typed_flag == 1
|
201
|
+
printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((struct RTypedData *)($arg0))->type->wrap_struct_name
|
202
|
+
print (struct RTypedData *)($arg0)
|
203
|
+
else
|
204
|
+
printf "%sT_DATA%s: ", $color_type, $color_end
|
205
|
+
print (struct RData *)($arg0)
|
206
|
+
end
|
207
|
+
else
|
208
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_MATCH
|
209
|
+
printf "%sT_MATCH%s: ", $color_type, $color_end
|
210
|
+
print (struct RMatch *)($arg0)
|
211
|
+
else
|
212
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_SYMBOL
|
213
|
+
printf "%sT_SYMBOL%s: ", $color_type, $color_end
|
214
|
+
print (struct RSymbol *)($arg0)
|
215
|
+
set $id_type = ((struct RSymbol *)($arg0))->id & RUBY_ID_SCOPE_MASK
|
216
|
+
if $id_type == RUBY_ID_LOCAL
|
217
|
+
printf "l"
|
218
|
+
else
|
219
|
+
if $id_type == RUBY_ID_INSTANCE
|
220
|
+
printf "i"
|
221
|
+
else
|
222
|
+
if $id_type == RUBY_ID_GLOBAL
|
223
|
+
printf "G"
|
224
|
+
else
|
225
|
+
if $id_type == RUBY_ID_ATTRSET
|
226
|
+
printf "a"
|
227
|
+
else
|
228
|
+
if $id_type == RUBY_ID_CONST
|
229
|
+
printf "C"
|
230
|
+
else
|
231
|
+
if $id_type == RUBY_ID_CLASS
|
232
|
+
printf "c"
|
233
|
+
else
|
234
|
+
printf "j"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
set $id_fstr = ((struct RSymbol *)($arg0))->fstr
|
242
|
+
rp_string $id_fstr
|
243
|
+
else
|
244
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_UNDEF
|
245
|
+
printf "%sT_UNDEF%s: ", $color_type, $color_end
|
246
|
+
print (struct RBasic *)($arg0)
|
247
|
+
else
|
248
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_IMEMO
|
249
|
+
printf "%sT_IMEMO%s(", $color_type, $color_end
|
250
|
+
output (enum imemo_type)(($flags>>RUBY_FL_USHIFT)&imemo_mask)
|
251
|
+
printf "): "
|
252
|
+
rp_imemo $arg0
|
253
|
+
else
|
254
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_NODE
|
255
|
+
printf "%sT_NODE%s(", $color_type, $color_end
|
256
|
+
output (enum node_type)(($flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT)
|
257
|
+
printf "): "
|
258
|
+
print *(NODE *)($arg0)
|
259
|
+
else
|
260
|
+
if ($flags & RUBY_T_MASK) == RUBY_T_ZOMBIE
|
261
|
+
printf "%sT_ZOMBIE%s: ", $color_type, $color_end
|
262
|
+
print (struct RData *)($arg0)
|
263
|
+
else
|
264
|
+
printf "%sunknown%s: ", $color_type, $color_end
|
265
|
+
print (struct RBasic *)($arg0)
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
end
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
document rp
|
301
|
+
Print a Ruby's VALUE.
|
302
|
+
end
|
303
|
+
|
304
|
+
define rp_id
|
305
|
+
set $id = (ID)$arg0
|
306
|
+
if $id == '!' || $id == '+' || $id == '-' || $id == '*' || $id == '/' || $id == '%' || $id == '<' || $id == '>' || $id == '`'
|
307
|
+
printf "(:%c)\n", $id
|
308
|
+
else
|
309
|
+
if $id == idDot2
|
310
|
+
printf "(:..)\n"
|
311
|
+
else
|
312
|
+
if $id == idDot3
|
313
|
+
printf "(:...)\n"
|
314
|
+
else
|
315
|
+
if $id == idUPlus
|
316
|
+
printf "(:+@)\n"
|
317
|
+
else
|
318
|
+
if $id == idUMinus
|
319
|
+
printf "(:-@)\n"
|
320
|
+
else
|
321
|
+
if $id == idPow
|
322
|
+
printf "(:**)\n"
|
323
|
+
else
|
324
|
+
if $id == idCmp
|
325
|
+
printf "(:<=>)\n"
|
326
|
+
else
|
327
|
+
if $id == idLTLT
|
328
|
+
printf "(:<<)\n"
|
329
|
+
else
|
330
|
+
if $id == idLE
|
331
|
+
printf "(:<=)\n"
|
332
|
+
else
|
333
|
+
if $id == idGE
|
334
|
+
printf "(:>=)\n"
|
335
|
+
else
|
336
|
+
if $id == idEq
|
337
|
+
printf "(:==)\n"
|
338
|
+
else
|
339
|
+
if $id == idEqq
|
340
|
+
printf "(:===)\n"
|
341
|
+
else
|
342
|
+
if $id == idNeq
|
343
|
+
printf "(:!=)\n"
|
344
|
+
else
|
345
|
+
if $id == idEqTilde
|
346
|
+
printf "(:=~)\n"
|
347
|
+
else
|
348
|
+
if $id == idNeqTilde
|
349
|
+
printf "(:!~)\n"
|
350
|
+
else
|
351
|
+
if $id == idAREF
|
352
|
+
printf "(:[])\n"
|
353
|
+
else
|
354
|
+
if $id == idASET
|
355
|
+
printf "(:[]=)\n"
|
356
|
+
else
|
357
|
+
if $id <= tLAST_OP_ID
|
358
|
+
printf "O"
|
359
|
+
else
|
360
|
+
set $id_type = $id & RUBY_ID_SCOPE_MASK
|
361
|
+
if $id_type == RUBY_ID_LOCAL
|
362
|
+
printf "l"
|
363
|
+
else
|
364
|
+
if $id_type == RUBY_ID_INSTANCE
|
365
|
+
printf "i"
|
366
|
+
else
|
367
|
+
if $id_type == RUBY_ID_GLOBAL
|
368
|
+
printf "G"
|
369
|
+
else
|
370
|
+
if $id_type == RUBY_ID_ATTRSET
|
371
|
+
printf "a"
|
372
|
+
else
|
373
|
+
if $id_type == RUBY_ID_CONST
|
374
|
+
printf "C"
|
375
|
+
else
|
376
|
+
if $id_type == RUBY_ID_CLASS
|
377
|
+
printf "c"
|
378
|
+
else
|
379
|
+
printf "j"
|
380
|
+
end
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
printf "(%ld): ", $id
|
388
|
+
set $str = lookup_id_str($id)
|
389
|
+
if $str
|
390
|
+
rp_string $str
|
391
|
+
else
|
392
|
+
echo undef\n
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
end
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|
401
|
+
end
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
document rp_id
|
413
|
+
Print an ID.
|
414
|
+
end
|
415
|
+
|
416
|
+
define rp_string
|
417
|
+
set $flags = ((struct RBasic*)($arg0))->flags
|
418
|
+
set print address off
|
419
|
+
output (char *)(($flags & RUBY_FL_USER1) ? \
|
420
|
+
((struct RString*)($arg0))->as.heap.ptr : \
|
421
|
+
((struct RString*)($arg0))->as.ary)
|
422
|
+
set print address on
|
423
|
+
printf " bytesize:%ld ", ($flags & RUBY_FL_USER1) ? \
|
424
|
+
((struct RString*)($arg0))->as.heap.len : \
|
425
|
+
(($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2)
|
426
|
+
if !($flags & RUBY_FL_USER1)
|
427
|
+
printf "(embed) "
|
428
|
+
else
|
429
|
+
if ($flags & RUBY_FL_USER2)
|
430
|
+
printf "(shared) "
|
431
|
+
end
|
432
|
+
if ($flags & RUBY_FL_USER3)
|
433
|
+
printf "(assoc) "
|
434
|
+
end
|
435
|
+
end
|
436
|
+
printf "encoding:%d ", ($flags & RUBY_ENCODING_MASK) >> RUBY_ENCODING_SHIFT
|
437
|
+
if ($flags & RUBY_ENC_CODERANGE_MASK) == 0
|
438
|
+
printf "coderange:unknown "
|
439
|
+
else
|
440
|
+
if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_7BIT
|
441
|
+
printf "coderange:7bit "
|
442
|
+
else
|
443
|
+
if ($flags & RUBY_ENC_CODERANGE_MASK) == RUBY_ENC_CODERANGE_VALID
|
444
|
+
printf "coderange:valid "
|
445
|
+
else
|
446
|
+
printf "coderange:broken "
|
447
|
+
end
|
448
|
+
end
|
449
|
+
end
|
450
|
+
print (struct RString *)($arg0)
|
451
|
+
end
|
452
|
+
document rp_string
|
453
|
+
Print the content of a String.
|
454
|
+
end
|
455
|
+
|
456
|
+
define rp_class
|
457
|
+
printf "(struct RClass *) %p", (void*)$arg0
|
458
|
+
if ((struct RClass *)($arg0))->ptr.origin_ != $arg0
|
459
|
+
printf " -> %p", ((struct RClass *)($arg0))->ptr.origin_
|
460
|
+
end
|
461
|
+
printf "\n"
|
462
|
+
rb_classname $arg0
|
463
|
+
print *(struct RClass *)($arg0)
|
464
|
+
print *((struct RClass *)($arg0))->ptr
|
465
|
+
end
|
466
|
+
document rp_class
|
467
|
+
Print the content of a Class/Module.
|
468
|
+
end
|
469
|
+
|
470
|
+
define rp_imemo
|
471
|
+
set $flags = (((struct RBasic *)($arg0))->flags >> RUBY_FL_USHIFT) & imemo_mask
|
472
|
+
if $flags == imemo_cref
|
473
|
+
printf "(rb_cref_t *) %p\n", (void*)$arg0
|
474
|
+
print *(rb_cref_t *)$arg0
|
475
|
+
else
|
476
|
+
if $flags == imemo_svar
|
477
|
+
printf "(struct vm_svar *) %p\n", (void*)$arg0
|
478
|
+
print *(struct vm_svar *)$arg0
|
479
|
+
else
|
480
|
+
if $flags == imemo_throw_data
|
481
|
+
printf "(struct vm_throw_data *) %p\n", (void*)$arg0
|
482
|
+
print *(struct vm_throw_data *)$arg0
|
483
|
+
else
|
484
|
+
if $flags == imemo_ifunc
|
485
|
+
printf "(struct vm_ifunc *) %p\n", (void*)$arg0
|
486
|
+
print *(struct vm_ifunc *)$arg0
|
487
|
+
else
|
488
|
+
if $flags == imemo_memo
|
489
|
+
printf "(struct MEMO *) %p\n", (void*)$arg0
|
490
|
+
print *(struct MEMO *)$arg0
|
491
|
+
else
|
492
|
+
printf "(struct RIMemo *) %p\n", (void*)$arg0
|
493
|
+
print *(struct RIMemo *)$arg0
|
494
|
+
end
|
495
|
+
end
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
document rp_imemo
|
501
|
+
Print the content of a memo
|
502
|
+
end
|
503
|
+
|
504
|
+
define nd_type
|
505
|
+
print (enum node_type)((((NODE*)($arg0))->flags&RUBY_NODE_TYPEMASK)>>RUBY_NODE_TYPESHIFT)
|
506
|
+
end
|
507
|
+
document nd_type
|
508
|
+
Print a Ruby' node type.
|
509
|
+
end
|
510
|
+
|
511
|
+
define nd_file
|
512
|
+
print ((NODE*)($arg0))->nd_file
|
513
|
+
end
|
514
|
+
document nd_file
|
515
|
+
Print the source file name of a node.
|
516
|
+
end
|
517
|
+
|
518
|
+
define nd_line
|
519
|
+
print ((unsigned int)((((NODE*)($arg0))->flags>>RUBY_NODE_LSHIFT)&RUBY_NODE_LMASK))
|
520
|
+
end
|
521
|
+
document nd_line
|
522
|
+
Print the source line number of a node.
|
523
|
+
end
|
524
|
+
|
525
|
+
# Print members of ruby node.
|
526
|
+
|
527
|
+
define nd_head
|
528
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
529
|
+
rp ($arg0).u1.node
|
530
|
+
end
|
531
|
+
|
532
|
+
define nd_alen
|
533
|
+
printf "%su2.argc%s: ", $color_highlite, $color_end
|
534
|
+
p ($arg0).u2.argc
|
535
|
+
end
|
536
|
+
|
537
|
+
define nd_next
|
538
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
539
|
+
rp ($arg0).u3.node
|
540
|
+
end
|
541
|
+
|
542
|
+
|
543
|
+
define nd_cond
|
544
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
545
|
+
rp ($arg0).u1.node
|
546
|
+
end
|
547
|
+
|
548
|
+
define nd_body
|
549
|
+
printf "%su2.node%s: ", $color_highlite, $color_end
|
550
|
+
rp ($arg0).u2.node
|
551
|
+
end
|
552
|
+
|
553
|
+
define nd_else
|
554
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
555
|
+
rp ($arg0).u3.node
|
556
|
+
end
|
557
|
+
|
558
|
+
|
559
|
+
define nd_orig
|
560
|
+
printf "%su3.value%s: ", $color_highlite, $color_end
|
561
|
+
rp ($arg0).u3.value
|
562
|
+
end
|
563
|
+
|
564
|
+
|
565
|
+
define nd_resq
|
566
|
+
printf "%su2.node%s: ", $color_highlite, $color_end
|
567
|
+
rp ($arg0).u2.node
|
568
|
+
end
|
569
|
+
|
570
|
+
define nd_ensr
|
571
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
572
|
+
rp ($arg0).u3.node
|
573
|
+
end
|
574
|
+
|
575
|
+
|
576
|
+
define nd_1st
|
577
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
578
|
+
rp ($arg0).u1.node
|
579
|
+
end
|
580
|
+
|
581
|
+
define nd_2nd
|
582
|
+
printf "%su2.node%s: ", $color_highlite, $color_end
|
583
|
+
rp ($arg0).u2.node
|
584
|
+
end
|
585
|
+
|
586
|
+
|
587
|
+
define nd_stts
|
588
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
589
|
+
rp ($arg0).u1.node
|
590
|
+
end
|
591
|
+
|
592
|
+
|
593
|
+
define nd_entry
|
594
|
+
printf "%su3.entry%s: ", $color_highlite, $color_end
|
595
|
+
p ($arg0).u3.entry
|
596
|
+
end
|
597
|
+
|
598
|
+
define nd_vid
|
599
|
+
printf "%su1.id%s: ", $color_highlite, $color_end
|
600
|
+
p ($arg0).u1.id
|
601
|
+
end
|
602
|
+
|
603
|
+
define nd_cflag
|
604
|
+
printf "%su2.id%s: ", $color_highlite, $color_end
|
605
|
+
p ($arg0).u2.id
|
606
|
+
end
|
607
|
+
|
608
|
+
define nd_cval
|
609
|
+
printf "%su3.value%s: ", $color_highlite, $color_end
|
610
|
+
rp ($arg0).u3.value
|
611
|
+
end
|
612
|
+
|
613
|
+
|
614
|
+
define nd_cnt
|
615
|
+
printf "%su3.cnt%s: ", $color_highlite, $color_end
|
616
|
+
p ($arg0).u3.cnt
|
617
|
+
end
|
618
|
+
|
619
|
+
define nd_tbl
|
620
|
+
printf "%su1.tbl%s: ", $color_highlite, $color_end
|
621
|
+
p ($arg0).u1.tbl
|
622
|
+
end
|
623
|
+
|
624
|
+
|
625
|
+
define nd_var
|
626
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
627
|
+
rp ($arg0).u1.node
|
628
|
+
end
|
629
|
+
|
630
|
+
define nd_ibdy
|
631
|
+
printf "%su2.node%s: ", $color_highlite, $color_end
|
632
|
+
rp ($arg0).u2.node
|
633
|
+
end
|
634
|
+
|
635
|
+
define nd_iter
|
636
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
637
|
+
rp ($arg0).u3.node
|
638
|
+
end
|
639
|
+
|
640
|
+
|
641
|
+
define nd_value
|
642
|
+
printf "%su2.node%s: ", $color_highlite, $color_end
|
643
|
+
rp ($arg0).u2.node
|
644
|
+
end
|
645
|
+
|
646
|
+
define nd_aid
|
647
|
+
printf "%su3.id%s: ", $color_highlite, $color_end
|
648
|
+
p ($arg0).u3.id
|
649
|
+
end
|
650
|
+
|
651
|
+
|
652
|
+
define nd_lit
|
653
|
+
printf "%su1.value%s: ", $color_highlite, $color_end
|
654
|
+
rp ($arg0).u1.value
|
655
|
+
end
|
656
|
+
|
657
|
+
|
658
|
+
define nd_frml
|
659
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
660
|
+
rp ($arg0).u1.node
|
661
|
+
end
|
662
|
+
|
663
|
+
define nd_rest
|
664
|
+
printf "%su2.argc%s: ", $color_highlite, $color_end
|
665
|
+
p ($arg0).u2.argc
|
666
|
+
end
|
667
|
+
|
668
|
+
define nd_opt
|
669
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
670
|
+
rp ($arg0).u1.node
|
671
|
+
end
|
672
|
+
|
673
|
+
|
674
|
+
define nd_recv
|
675
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
676
|
+
rp ($arg0).u1.node
|
677
|
+
end
|
678
|
+
|
679
|
+
define nd_mid
|
680
|
+
printf "%su2.id%s: ", $color_highlite, $color_end
|
681
|
+
p ($arg0).u2.id
|
682
|
+
end
|
683
|
+
|
684
|
+
define nd_args
|
685
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
686
|
+
rp ($arg0).u3.node
|
687
|
+
end
|
688
|
+
|
689
|
+
|
690
|
+
define nd_noex
|
691
|
+
printf "%su1.id%s: ", $color_highlite, $color_end
|
692
|
+
p ($arg0).u1.id
|
693
|
+
end
|
694
|
+
|
695
|
+
define nd_defn
|
696
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
697
|
+
rp ($arg0).u3.node
|
698
|
+
end
|
699
|
+
|
700
|
+
|
701
|
+
define nd_old
|
702
|
+
printf "%su1.id%s: ", $color_highlite, $color_end
|
703
|
+
p ($arg0).u1.id
|
704
|
+
end
|
705
|
+
|
706
|
+
define nd_new
|
707
|
+
printf "%su2.id%s: ", $color_highlite, $color_end
|
708
|
+
p ($arg0).u2.id
|
709
|
+
end
|
710
|
+
|
711
|
+
|
712
|
+
define nd_cfnc
|
713
|
+
printf "%su1.cfunc%s: ", $color_highlite, $color_end
|
714
|
+
p ($arg0).u1.cfunc
|
715
|
+
end
|
716
|
+
|
717
|
+
define nd_argc
|
718
|
+
printf "%su2.argc%s: ", $color_highlite, $color_end
|
719
|
+
p ($arg0).u2.argc
|
720
|
+
end
|
721
|
+
|
722
|
+
|
723
|
+
define nd_cname
|
724
|
+
printf "%su1.id%s: ", $color_highlite, $color_end
|
725
|
+
p ($arg0).u1.id
|
726
|
+
end
|
727
|
+
|
728
|
+
define nd_super
|
729
|
+
printf "%su3.node%s: ", $color_highlite, $color_end
|
730
|
+
rp ($arg0).u3.node
|
731
|
+
end
|
732
|
+
|
733
|
+
|
734
|
+
define nd_modl
|
735
|
+
printf "%su1.id%s: ", $color_highlite, $color_end
|
736
|
+
p ($arg0).u1.id
|
737
|
+
end
|
738
|
+
|
739
|
+
define nd_clss
|
740
|
+
printf "%su1.value%s: ", $color_highlite, $color_end
|
741
|
+
rp ($arg0).u1.value
|
742
|
+
end
|
743
|
+
|
744
|
+
|
745
|
+
define nd_beg
|
746
|
+
printf "%su1.node%s: ", $color_highlite, $color_end
|
747
|
+
rp ($arg0).u1.node
|
748
|
+
end
|
749
|
+
|
750
|
+
define nd_end
|
751
|
+
printf "%su2.node%s: ", $color_highlite, $color_end
|
752
|
+
rp ($arg0).u2.node
|
753
|
+
end
|
754
|
+
|
755
|
+
define nd_state
|
756
|
+
printf "%su3.state%s: ", $color_highlite, $color_end
|
757
|
+
p ($arg0).u3.state
|
758
|
+
end
|
759
|
+
|
760
|
+
define nd_rval
|
761
|
+
printf "%su2.value%s: ", $color_highlite, $color_end
|
762
|
+
rp ($arg0).u2.value
|
763
|
+
end
|
764
|
+
|
765
|
+
|
766
|
+
define nd_nth
|
767
|
+
printf "%su2.argc%s: ", $color_highlite, $color_end
|
768
|
+
p ($arg0).u2.argc
|
769
|
+
end
|
770
|
+
|
771
|
+
|
772
|
+
define nd_tag
|
773
|
+
printf "%su1.id%s: ", $color_highlite, $color_end
|
774
|
+
p ($arg0).u1.id
|
775
|
+
end
|
776
|
+
|
777
|
+
define nd_tval
|
778
|
+
printf "%su2.value%s: ", $color_highlite, $color_end
|
779
|
+
rp ($arg0).u2.value
|
780
|
+
end
|
781
|
+
|
782
|
+
define nd_tree
|
783
|
+
set $buf = (struct RString *)rb_str_buf_new(0)
|
784
|
+
call dump_node((VALUE)($buf), rb_str_new(0, 0), 0, ($arg0))
|
785
|
+
printf "%s\n", $buf->as.heap.ptr
|
786
|
+
end
|
787
|
+
|
788
|
+
define rb_p
|
789
|
+
call rb_p($arg0)
|
790
|
+
end
|
791
|
+
|
792
|
+
define rb_numtable_entry
|
793
|
+
set $rb_numtable_tbl = $arg0
|
794
|
+
set $rb_numtable_id = (st_data_t)$arg1
|
795
|
+
set $rb_numtable_key = 0
|
796
|
+
set $rb_numtable_rec = 0
|
797
|
+
if $rb_numtable_tbl->entries_packed
|
798
|
+
set $rb_numtable_p = $rb_numtable_tbl->as.packed.bins
|
799
|
+
while $rb_numtable_p && $rb_numtable_p < $rb_numtable_tbl->as.packed.bins+$rb_numtable_tbl->num_entries
|
800
|
+
if $rb_numtable_p.k == $rb_numtable_id
|
801
|
+
set $rb_numtable_key = $rb_numtable_p.k
|
802
|
+
set $rb_numtable_rec = $rb_numtable_p.v
|
803
|
+
set $rb_numtable_p = 0
|
804
|
+
else
|
805
|
+
set $rb_numtable_p = $rb_numtable_p + 1
|
806
|
+
end
|
807
|
+
end
|
808
|
+
else
|
809
|
+
set $rb_numtable_p = $rb_numtable_tbl->as.big.bins[st_numhash($rb_numtable_id) % $rb_numtable_tbl->num_bins]
|
810
|
+
while $rb_numtable_p
|
811
|
+
if $rb_numtable_p->key == $rb_numtable_id
|
812
|
+
set $rb_numtable_key = $rb_numtable_p->key
|
813
|
+
set $rb_numtable_rec = $rb_numtable_p->record
|
814
|
+
set $rb_numtable_p = 0
|
815
|
+
else
|
816
|
+
set $rb_numtable_p = $rb_numtable_p->next
|
817
|
+
end
|
818
|
+
end
|
819
|
+
end
|
820
|
+
end
|
821
|
+
|
822
|
+
define rb_id2name
|
823
|
+
ruby_gdb_init
|
824
|
+
printf "%sID%s: ", $color_type, $color_end
|
825
|
+
rp_id $arg0
|
826
|
+
end
|
827
|
+
document rb_id2name
|
828
|
+
Print the name of id
|
829
|
+
end
|
830
|
+
|
831
|
+
define rb_method_entry
|
832
|
+
set $rb_method_entry_klass = (struct RClass *)$arg0
|
833
|
+
set $rb_method_entry_id = (ID)$arg1
|
834
|
+
set $rb_method_entry_me = (rb_method_entry_t *)0
|
835
|
+
while !$rb_method_entry_me && $rb_method_entry_klass
|
836
|
+
rb_numtable_entry $rb_method_entry_klass->m_tbl_wrapper->tbl $rb_method_entry_id
|
837
|
+
set $rb_method_entry_me = (rb_method_entry_t *)$rb_numtable_rec
|
838
|
+
if !$rb_method_entry_me
|
839
|
+
set $rb_method_entry_klass = (struct RClass *)RCLASS_SUPER($rb_method_entry_klass)
|
840
|
+
end
|
841
|
+
end
|
842
|
+
if $rb_method_entry_me
|
843
|
+
print *$rb_method_entry_klass
|
844
|
+
print *$rb_method_entry_me
|
845
|
+
else
|
846
|
+
echo method not found\n
|
847
|
+
end
|
848
|
+
end
|
849
|
+
document rb_method_entry
|
850
|
+
Search method entry by class and id
|
851
|
+
end
|
852
|
+
|
853
|
+
define rb_classname
|
854
|
+
# up to 128bit int
|
855
|
+
set $rb_classname_permanent = "0123456789ABCDEF"
|
856
|
+
set $rb_classname = classname($arg0, $rb_classname_permanent)
|
857
|
+
if $rb_classname != RUBY_Qnil
|
858
|
+
rp $rb_classname
|
859
|
+
else
|
860
|
+
echo anonymous class/module\n
|
861
|
+
end
|
862
|
+
end
|
863
|
+
|
864
|
+
define rb_ancestors
|
865
|
+
set $rb_ancestors_module = $arg0
|
866
|
+
while $rb_ancestors_module
|
867
|
+
rp_class $rb_ancestors_module
|
868
|
+
set $rb_ancestors_module = RCLASS_SUPER($rb_ancestors_module)
|
869
|
+
end
|
870
|
+
end
|
871
|
+
document rb_ancestors
|
872
|
+
Print ancestors.
|
873
|
+
end
|
874
|
+
|
875
|
+
define rb_backtrace
|
876
|
+
call rb_backtrace()
|
877
|
+
end
|
878
|
+
|
879
|
+
define iseq
|
880
|
+
if ruby_dummy_gdb_enums.special_consts
|
881
|
+
end
|
882
|
+
if ($arg0)->type == ISEQ_ELEMENT_NONE
|
883
|
+
echo [none]\n
|
884
|
+
end
|
885
|
+
if ($arg0)->type == ISEQ_ELEMENT_LABEL
|
886
|
+
print *(LABEL*)($arg0)
|
887
|
+
end
|
888
|
+
if ($arg0)->type == ISEQ_ELEMENT_INSN
|
889
|
+
print *(INSN*)($arg0)
|
890
|
+
if ((INSN*)($arg0))->insn_id != YARVINSN_jump
|
891
|
+
set $i = 0
|
892
|
+
set $operand_size = ((INSN*)($arg0))->operand_size
|
893
|
+
set $operands = ((INSN*)($arg0))->operands
|
894
|
+
while $i < $operand_size
|
895
|
+
rp $operands[$i++]
|
896
|
+
end
|
897
|
+
end
|
898
|
+
end
|
899
|
+
if ($arg0)->type == ISEQ_ELEMENT_ADJUST
|
900
|
+
print *(ADJUST*)($arg0)
|
901
|
+
end
|
902
|
+
end
|
903
|
+
|
904
|
+
define rb_ps
|
905
|
+
rb_ps_vm ruby_current_vm
|
906
|
+
end
|
907
|
+
document rb_ps
|
908
|
+
Dump all threads and their callstacks
|
909
|
+
end
|
910
|
+
|
911
|
+
define rb_ps_vm
|
912
|
+
print $ps_vm = (rb_vm_t*)$arg0
|
913
|
+
set $ps_thread_ln = $ps_vm->living_threads.n.next
|
914
|
+
set $ps_thread_ln_last = $ps_vm->living_threads.n.prev
|
915
|
+
while 1
|
916
|
+
set $ps_thread_th = (rb_thread_t *)$ps_thread_ln
|
917
|
+
set $ps_thread = (VALUE)($ps_thread_th->self)
|
918
|
+
rb_ps_thread $ps_thread
|
919
|
+
if $ps_thread_ln == $ps_thread_ln_last
|
920
|
+
loop_break
|
921
|
+
end
|
922
|
+
set $ps_thread_ln = $ps_thread_ln->next
|
923
|
+
end
|
924
|
+
end
|
925
|
+
document rb_ps_vm
|
926
|
+
Dump all threads in a (rb_vm_t*) and their callstacks
|
927
|
+
end
|
928
|
+
|
929
|
+
define rb_ps_thread
|
930
|
+
set $ps_thread = (struct RTypedData*)$arg0
|
931
|
+
set $ps_thread_th = (rb_thread_t*)$ps_thread->data
|
932
|
+
printf "* #<Thread:%p rb_thread_t:%p native_thread:%p>\n", \
|
933
|
+
$ps_thread, $ps_thread_th, $ps_thread_th->thread_id
|
934
|
+
end
|
935
|
+
|
936
|
+
# Details: https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/MachineInstructionsTraceWithGDB
|
937
|
+
define trace_machine_instructions
|
938
|
+
set logging on
|
939
|
+
set height 0
|
940
|
+
set width 0
|
941
|
+
display/i $pc
|
942
|
+
while !$exit_code
|
943
|
+
info line *$pc
|
944
|
+
si
|
945
|
+
end
|
946
|
+
end
|
947
|
+
|
948
|
+
define SDR
|
949
|
+
call rb_vmdebug_stack_dump_raw_current()
|
950
|
+
end
|
951
|
+
|
952
|
+
define rbi
|
953
|
+
if ((LINK_ELEMENT*)$arg0)->type == ISEQ_ELEMENT_LABEL
|
954
|
+
p *(LABEL*)$arg0
|
955
|
+
else
|
956
|
+
if ((LINK_ELEMENT*)$arg0)->type == ISEQ_ELEMENT_INSN
|
957
|
+
p *(INSN*)$arg0
|
958
|
+
else
|
959
|
+
if ((LINK_ELEMENT*)$arg0)->type == ISEQ_ELEMENT_ADJUST
|
960
|
+
p *(ADJUST*)$arg0
|
961
|
+
else
|
962
|
+
print *$arg0
|
963
|
+
end
|
964
|
+
end
|
965
|
+
end
|
966
|
+
end
|