gdb.rb 0.1.3 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +7 -1
- data/bin/gdb.rb +4 -3
- data/ext/extconf.rb +1 -3
- data/ext/src/{gdb-7.0.tar.bz2 → gdb-7.2.tar.bz2} +0 -0
- data/gdb.rb.gemspec +5 -18
- data/patches/gdb-leak.patch +41 -61
- data/scripts/ruby-gdb.py +54 -27
- metadata +20 -10
- data/patches/gdb-breakpoints.patch +0 -744
- data/patches/gdb-eval.patch +0 -57
data/README
CHANGED
@@ -17,6 +17,12 @@ gdb7 hooks for MRI
|
|
17
17
|
Attaching to program: /usr/bin/ruby, process 13074
|
18
18
|
0x00007fa8b9cb3c93 in select () from /lib/libc.so.6
|
19
19
|
|
20
|
+
(gdb) ruby eval 1+2
|
21
|
+
2
|
22
|
+
|
23
|
+
(gdb) ruby eval Thread.list.count
|
24
|
+
17
|
25
|
+
|
20
26
|
(gdb) ruby threads list
|
21
27
|
0x1589000 main thread THREAD_STOPPED WAIT_JOIN(0x19ef400) 4417 bytes
|
22
28
|
0x19ef400 thread THREAD_STOPPED WAIT_TIME(57.10) 6267 bytes
|
@@ -34,7 +40,7 @@ gdb7 hooks for MRI
|
|
34
40
|
0x19dc800 thread THREAD_STOPPED WAIT_NONE 14237 bytes
|
35
41
|
0x19dcc00 thread THREAD_STOPPED WAIT_NONE 14237 bytes
|
36
42
|
0x2266800 thread THREAD_STOPPED WAIT_NONE 14237 bytes
|
37
|
-
0x1d63000 curr thread THREAD_RUNNABLE WAIT_NONE
|
43
|
+
0x1d63000 curr thread THREAD_RUNNABLE WAIT_NONE
|
38
44
|
|
39
45
|
(gdb) ruby threads
|
40
46
|
0x1589000 main thread THREAD_STOPPED WAIT_JOIN(0x19ef400) 4417 bytes
|
data/bin/gdb.rb
CHANGED
@@ -13,15 +13,16 @@ else
|
|
13
13
|
exit(1)
|
14
14
|
end
|
15
15
|
|
16
|
-
dir = File.expand_path(
|
16
|
+
dir = File.expand_path('../../', __FILE__)
|
17
|
+
binary = "#{Config::CONFIG['bindir']}/#{Config::CONFIG['ruby_install_name']}"
|
17
18
|
|
18
19
|
args = []
|
19
20
|
args << "#{dir}/ext/dst/bin/gdb"
|
20
|
-
args << "-ex 'py execfile(\"#{dir}/scripts/ruby-gdb.py\")'"
|
21
21
|
if pid
|
22
22
|
args << "-ex 'attach #{pid}'"
|
23
23
|
else
|
24
|
-
args <<
|
24
|
+
args << binary
|
25
25
|
end
|
26
|
+
args << %{-ex 'py execfile("#{dir}/scripts/ruby-gdb.py")'}
|
26
27
|
|
27
28
|
exec(args.join(' '))
|
data/ext/extconf.rb
CHANGED
@@ -36,7 +36,7 @@ unless have_header('python2.5/Python.h') or have_header('python2.6/Python.h') or
|
|
36
36
|
exit(1)
|
37
37
|
end
|
38
38
|
|
39
|
-
gdb = File.basename('gdb-7.
|
39
|
+
gdb = File.basename('gdb-7.2.tar.bz2')
|
40
40
|
dir = File.basename(gdb, '.tar.bz2')
|
41
41
|
|
42
42
|
puts "(I'm about to compile gdb7.. this will definitely take a while)"
|
@@ -53,8 +53,6 @@ Dir.chdir('src') do
|
|
53
53
|
end
|
54
54
|
|
55
55
|
%w[
|
56
|
-
gdb-eval
|
57
|
-
gdb-breakpoints
|
58
56
|
gdb-leak
|
59
57
|
gdb-strings
|
60
58
|
].each do |patch|
|
Binary file
|
data/gdb.rb.gemspec
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
spec = Gem::Specification.new do |s|
|
2
2
|
s.name = 'gdb.rb'
|
3
|
-
s.version = '0.1.
|
4
|
-
s.date = '
|
3
|
+
s.version = '0.1.5'
|
4
|
+
s.date = '2010-11-04'
|
5
5
|
s.rubyforge_project = 'gdb-rb'
|
6
|
-
s.summary = 'gdb hooks for MRI'
|
7
|
-
s.description = 'A set of gdb7 extensions for the MRI interpreter'
|
6
|
+
s.summary = 'gdb hooks for MRI and REE'
|
7
|
+
s.description = 'A set of gdb7 extensions for the MRI/REE 1.8.x interpreter'
|
8
8
|
|
9
9
|
s.homepage = "http://github.com/tmm1/gdb.rb"
|
10
10
|
|
@@ -16,18 +16,5 @@ spec = Gem::Specification.new do |s|
|
|
16
16
|
s.bindir = 'bin'
|
17
17
|
s.executables << 'gdb.rb'
|
18
18
|
|
19
|
-
|
20
|
-
s.files = %w[
|
21
|
-
README
|
22
|
-
bin/gdb.rb
|
23
|
-
ext/Makefile
|
24
|
-
ext/extconf.rb
|
25
|
-
ext/src/gdb-7.0.tar.bz2
|
26
|
-
gdb.rb.gemspec
|
27
|
-
patches/gdb-breakpoints.patch
|
28
|
-
patches/gdb-eval.patch
|
29
|
-
patches/gdb-leak.patch
|
30
|
-
patches/gdb-strings.patch
|
31
|
-
scripts/ruby-gdb.py
|
32
|
-
]
|
19
|
+
s.files = `git ls-files`.split("\n").sort
|
33
20
|
end
|
data/patches/gdb-leak.patch
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
diff --git a/python/py-value.c b/python/py-value.c
|
2
|
-
index
|
2
|
+
index 4445655..f3c6309 100644
|
3
3
|
--- a/python/py-value.c
|
4
4
|
+++ b/python/py-value.c
|
5
|
-
@@ -
|
5
|
+
@@ -150,7 +150,7 @@ valpy_new (PyTypeObject *subtype, PyObject *args, PyObject *keywords)
|
6
6
|
}
|
7
7
|
|
8
8
|
value_obj->value = value;
|
@@ -10,16 +10,8 @@ index 8f8c610..c3a6cbf 100644
|
|
10
10
|
+ release_value_or_incref (value);
|
11
11
|
value_obj->address = NULL;
|
12
12
|
value_obj->type = NULL;
|
13
|
-
|
14
|
-
@@ -
|
15
|
-
{
|
16
|
-
PyObject *type_obj;
|
17
|
-
struct type *type;
|
18
|
-
+ PyObject *res_obj = NULL;
|
19
|
-
struct value *res_val = NULL; /* Initialize to appease gcc warning. */
|
20
|
-
volatile struct gdb_exception except;
|
21
|
-
|
22
|
-
@@ -301,8 +302,10 @@ valpy_getitem (PyObject *self, PyObject *key)
|
13
|
+
value_obj->dynamic_type = NULL;
|
14
|
+
@@ -445,8 +445,10 @@ valpy_getitem (PyObject *self, PyObject *key)
|
23
15
|
{
|
24
16
|
value_object *self_value = (value_object *) self;
|
25
17
|
char *field = NULL;
|
@@ -30,23 +22,24 @@ index 8f8c610..c3a6cbf 100644
|
|
30
22
|
|
31
23
|
if (gdbpy_is_string (key))
|
32
24
|
{
|
33
|
-
@@ -
|
25
|
+
@@ -486,9 +488,15 @@ valpy_getitem (PyObject *self, PyObject *key)
|
34
26
|
}
|
35
27
|
|
36
28
|
xfree (field);
|
37
|
-
|
38
|
-
+
|
39
|
-
|
40
|
-
+ if (res_val)
|
41
|
-
+ res_obj = value_to_value_object (res_val);
|
29
|
+
+ if (except.reason < 0)
|
30
|
+
+ value_free_to_mark (mark);
|
31
|
+
GDB_PY_HANDLE_EXCEPTION (except);
|
42
32
|
|
43
33
|
- return res_val ? value_to_value_object (res_val) : NULL;
|
34
|
+
+ if (res_val)
|
35
|
+
+ res_obj = value_to_value_object (res_val);
|
36
|
+
+
|
44
37
|
+ value_free_to_mark (mark);
|
45
38
|
+ return res_obj;
|
46
39
|
}
|
47
40
|
|
48
41
|
static int
|
49
|
-
@@ -
|
42
|
+
@@ -625,8 +633,10 @@ enum valpy_opcode
|
50
43
|
static PyObject *
|
51
44
|
valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
52
45
|
{
|
@@ -57,23 +50,25 @@ index 8f8c610..c3a6cbf 100644
|
|
57
50
|
|
58
51
|
TRY_CATCH (except, RETURN_MASK_ALL)
|
59
52
|
{
|
60
|
-
@@ -
|
53
|
+
@@ -717,9 +727,16 @@ valpy_binop (enum valpy_opcode opcode, PyObject *self, PyObject *other)
|
61
54
|
break;
|
62
55
|
}
|
63
56
|
}
|
64
|
-
- GDB_PY_HANDLE_EXCEPTION (except);
|
65
|
-
+ GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP (except, mark);
|
66
57
|
+
|
67
|
-
+ if (
|
68
|
-
+
|
58
|
+
+ if (except.reason < 0)
|
59
|
+
+ value_free_to_mark (mark);
|
60
|
+
GDB_PY_HANDLE_EXCEPTION (except);
|
69
61
|
|
70
62
|
- return res_val ? value_to_value_object (res_val) : NULL;
|
63
|
+
+ if (res_val)
|
64
|
+
+ res_obj = value_to_value_object (res_val);
|
65
|
+
+
|
71
66
|
+ value_free_to_mark (mark);
|
72
67
|
+ return res_obj;
|
73
68
|
}
|
74
69
|
|
75
70
|
static PyObject *
|
76
|
-
@@ -
|
71
|
+
@@ -881,6 +898,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
|
77
72
|
int result = 0;
|
78
73
|
struct value *value_other;
|
79
74
|
volatile struct gdb_exception except;
|
@@ -81,7 +76,7 @@ index 8f8c610..c3a6cbf 100644
|
|
81
76
|
|
82
77
|
if (other == Py_None)
|
83
78
|
/* Comparing with None is special. From what I can tell, in Python
|
84
|
-
@@ -
|
79
|
+
@@ -939,6 +957,7 @@ valpy_richcompare (PyObject *self, PyObject *other, int op)
|
85
80
|
break;
|
86
81
|
}
|
87
82
|
}
|
@@ -89,7 +84,7 @@ index 8f8c610..c3a6cbf 100644
|
|
89
84
|
GDB_PY_HANDLE_EXCEPTION (except);
|
90
85
|
|
91
86
|
/* In this case, the Python exception has already been set. */
|
92
|
-
@@ -
|
87
|
+
@@ -1062,7 +1081,7 @@ value_to_value_object (struct value *val)
|
93
88
|
if (val_obj != NULL)
|
94
89
|
{
|
95
90
|
val_obj->value = val;
|
@@ -97,37 +92,18 @@ index 8f8c610..c3a6cbf 100644
|
|
97
92
|
+ release_value_or_incref (val);
|
98
93
|
val_obj->address = NULL;
|
99
94
|
val_obj->type = NULL;
|
100
|
-
|
101
|
-
diff --git a/python/python-internal.h b/python/python-internal.h
|
102
|
-
index fa4a62b..bc9c8c0 100644
|
103
|
-
--- a/python/python-internal.h
|
104
|
-
+++ b/python/python-internal.h
|
105
|
-
@@ -103,11 +103,17 @@ extern const struct language_defn *python_language;
|
106
|
-
/* Use this after a TRY_EXCEPT to throw the appropriate Python
|
107
|
-
exception. */
|
108
|
-
#define GDB_PY_HANDLE_EXCEPTION(Exception) \
|
109
|
-
+ GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP(Exception, NULL)
|
110
|
-
+
|
111
|
-
+#define GDB_PY_HANDLE_EXCEPTION_AND_CLEANUP(Exception, mark) \
|
112
|
-
do { \
|
113
|
-
- if (Exception.reason < 0) \
|
114
|
-
+ if (Exception.reason < 0) { \
|
115
|
-
+ if (mark) \
|
116
|
-
+ value_free_to_mark (mark); \
|
117
|
-
return PyErr_Format (Exception.reason == RETURN_QUIT \
|
118
|
-
? PyExc_KeyboardInterrupt : PyExc_RuntimeError, \
|
119
|
-
"%s", Exception.message); \
|
120
|
-
+ } \
|
121
|
-
} while (0)
|
122
|
-
|
123
|
-
|
95
|
+
val_obj->dynamic_type = NULL;
|
124
96
|
diff --git a/value.c b/value.c
|
125
|
-
index
|
97
|
+
index 381318b..805dcf0 100644
|
126
98
|
--- a/value.c
|
127
99
|
+++ b/value.c
|
128
|
-
@@ -
|
100
|
+
@@ -737,9 +737,10 @@ free_value_chain (struct value *v)
|
101
|
+
}
|
102
|
+
|
129
103
|
/* Remove VAL from the chain all_values
|
130
|
-
|
104
|
+
- so it will not be freed automatically. */
|
105
|
+
+ so it will not be freed automatically.
|
106
|
+
+ Result of 0 indicates the value was found and released. */
|
131
107
|
|
132
108
|
-void
|
133
109
|
+int
|
@@ -139,7 +115,7 @@ index 589e03b..59a0196 100644
|
|
139
115
|
{
|
140
116
|
all_values = val->next;
|
141
117
|
- return;
|
142
|
-
+ return
|
118
|
+
+ return 0;
|
143
119
|
}
|
144
120
|
|
145
121
|
for (v = all_values; v; v = v->next)
|
@@ -148,11 +124,11 @@ index 589e03b..59a0196 100644
|
|
148
124
|
{
|
149
125
|
v->next = val->next;
|
150
126
|
- break;
|
151
|
-
+ return
|
127
|
+
+ return 0;
|
152
128
|
}
|
153
129
|
}
|
154
130
|
+
|
155
|
-
+ return
|
131
|
+
+ return -1;
|
156
132
|
+}
|
157
133
|
+
|
158
134
|
+/* Release VAL or increment its reference count if
|
@@ -161,18 +137,22 @@ index 589e03b..59a0196 100644
|
|
161
137
|
+void
|
162
138
|
+release_value_or_incref (struct value *val)
|
163
139
|
+{
|
164
|
-
+ if (release_value (val)
|
140
|
+
+ if (release_value (val) != 0)
|
165
141
|
+ value_incref (val);
|
166
142
|
}
|
167
143
|
|
168
144
|
/* Release all values up to mark */
|
145
|
+
+
|
146
|
+
struct value *
|
147
|
+
value_release_to_mark (struct value *mark)
|
148
|
+
{
|
169
149
|
diff --git a/value.h b/value.h
|
170
|
-
index
|
150
|
+
index 543290a..e7e00d2 100644
|
171
151
|
--- a/value.h
|
172
152
|
+++ b/value.h
|
173
|
-
@@ -
|
153
|
+
@@ -641,7 +641,9 @@ extern void free_all_values (void);
|
174
154
|
|
175
|
-
extern void
|
155
|
+
extern void free_value_chain (struct value *v);
|
176
156
|
|
177
157
|
-extern void release_value (struct value *val);
|
178
158
|
+extern int release_value (struct value *val);
|
data/scripts/ruby-gdb.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import re
|
2
2
|
import gdb
|
3
3
|
import time
|
4
|
+
import os
|
4
5
|
|
5
6
|
class ZeroDict(dict):
|
6
7
|
def __getitem__(self, i):
|
@@ -40,7 +41,7 @@ class RubyThreads (gdb.Command):
|
|
40
41
|
def trace (self):
|
41
42
|
self.type = 'list'
|
42
43
|
self.curr = None
|
43
|
-
self.main = gdb.
|
44
|
+
self.main = gdb.parse_and_eval('rb_main_thread')
|
44
45
|
|
45
46
|
self.unwind = gdb.parameter('unwindonsignal')
|
46
47
|
gdb.execute('set unwindonsignal on')
|
@@ -53,7 +54,7 @@ class RubyThreads (gdb.Command):
|
|
53
54
|
prev = None
|
54
55
|
while True:
|
55
56
|
gdb.execute('continue')
|
56
|
-
curr = gdb.
|
57
|
+
curr = gdb.parse_and_eval('rb_curr_thread')
|
57
58
|
if curr == prev: break
|
58
59
|
self.print_thread(curr)
|
59
60
|
prev = curr
|
@@ -64,12 +65,12 @@ class RubyThreads (gdb.Command):
|
|
64
65
|
gdb.execute('set unwindonsignal %s' % (self.unwind and 'on' or 'off'))
|
65
66
|
|
66
67
|
def show (self):
|
67
|
-
self.main = gdb.
|
68
|
-
self.curr = gdb.
|
68
|
+
self.main = gdb.parse_and_eval('rb_main_thread')
|
69
|
+
self.curr = gdb.parse_and_eval('rb_curr_thread')
|
69
70
|
self.now = time.time()
|
70
71
|
|
71
72
|
try:
|
72
|
-
gdb.
|
73
|
+
gdb.parse_and_eval('rb_thread_start_2')
|
73
74
|
except RuntimeError:
|
74
75
|
self.is_heap_stack = False
|
75
76
|
else:
|
@@ -100,8 +101,8 @@ class RubyThreads (gdb.Command):
|
|
100
101
|
if self.type == 'list': return
|
101
102
|
|
102
103
|
if th == self.curr:
|
103
|
-
frame = gdb.
|
104
|
-
node = gdb.
|
104
|
+
frame = gdb.parse_and_eval('ruby_frame')
|
105
|
+
node = gdb.parse_and_eval('ruby_current_node')
|
105
106
|
else:
|
106
107
|
frame = th['frame']
|
107
108
|
node = frame['node']
|
@@ -127,20 +128,20 @@ class RubyThreads (gdb.Command):
|
|
127
128
|
stk_pos = th['stk_pos']
|
128
129
|
stk_ptr = th['stk_ptr']
|
129
130
|
stk_len = th['stk_len']
|
130
|
-
addr = gdb.
|
131
|
+
addr = gdb.parse_and_eval('(VALUE*)%s' % frame)
|
131
132
|
|
132
133
|
if not self.is_heap_stack and th != self.curr and stk_pos < addr and addr < (stk_pos+stk_len):
|
133
134
|
frame = (addr-stk_pos) + stk_ptr
|
134
|
-
frame = gdb.
|
135
|
+
frame = gdb.parse_and_eval('(struct FRAME *)%s' % frame)
|
135
136
|
node = frame['node']
|
136
137
|
|
137
138
|
file = node['nd_file'].string()
|
138
|
-
line = gdb.
|
139
|
-
type = gdb.
|
139
|
+
line = gdb.parse_and_eval('nd_line(%s)' % node)
|
140
|
+
type = gdb.parse_and_eval('(enum node_type) nd_type(%s)' % node)
|
140
141
|
|
141
142
|
if frame['last_func']:
|
142
143
|
try:
|
143
|
-
method = gdb.
|
144
|
+
method = gdb.parse_and_eval('rb_id2name(%s)' % frame['last_func']).string()
|
144
145
|
except:
|
145
146
|
method = '(unknown)'
|
146
147
|
else:
|
@@ -171,7 +172,7 @@ class RubyTrace (gdb.Command):
|
|
171
172
|
gdb.execute(c)
|
172
173
|
|
173
174
|
gdb.breakpoints()[-1].silent = True
|
174
|
-
self.func = gdb.
|
175
|
+
self.func = gdb.parse_and_eval('$func')
|
175
176
|
|
176
177
|
self.unwind = gdb.parameter('unwindonsignal')
|
177
178
|
gdb.execute('set unwindonsignal on')
|
@@ -205,10 +206,10 @@ class RubyTrace (gdb.Command):
|
|
205
206
|
if frame.pc() != self.func:
|
206
207
|
raise KeyboardInterrupt
|
207
208
|
|
208
|
-
node = gdb.
|
209
|
+
node = gdb.parse_and_eval('(NODE*) $rsi')
|
209
210
|
file = node['nd_file'].string()
|
210
|
-
line = gdb.
|
211
|
-
method = gdb.
|
211
|
+
line = gdb.parse_and_eval('nd_line(%s)' % node)
|
212
|
+
method = gdb.parse_and_eval('rb_id2name($rcx)')
|
212
213
|
method = method > 0 and method.string() or '(unknown)'
|
213
214
|
|
214
215
|
print "%s in %s:%d" % (method,file,line)
|
@@ -263,7 +264,7 @@ class RubyObjects (gdb.Command):
|
|
263
264
|
nodes[ (int(obj['as']['node']['flags']) >> 12) & 0xff ] += 1
|
264
265
|
|
265
266
|
for (node, num) in sorted(nodes.items(), key=lambda(k,v):(v,k)):
|
266
|
-
print "% 8d %s" % (num, gdb.
|
267
|
+
print "% 8d %s" % (num, gdb.parse_and_eval('(enum node_type) (%d)' % node))
|
267
268
|
|
268
269
|
def print_classes (self):
|
269
270
|
classes = ZeroDict()
|
@@ -287,7 +288,7 @@ class RubyObjects (gdb.Command):
|
|
287
288
|
classes[ int(klass) ] += 1
|
288
289
|
|
289
290
|
for (klass, num) in sorted(classes.items(), key=lambda(k,v):(v,k)):
|
290
|
-
print "% 8d %s" % (num, gdb.
|
291
|
+
print "% 8d %s" % (num, gdb.parse_and_eval('rb_class2name(%d)' % klass).string())
|
291
292
|
|
292
293
|
def print_strings (self):
|
293
294
|
strings = ZeroDict()
|
@@ -385,11 +386,11 @@ class RubyObjects (gdb.Command):
|
|
385
386
|
print
|
386
387
|
|
387
388
|
def all_objects (self):
|
388
|
-
self.heaps_used = gdb.
|
389
|
+
self.heaps_used = gdb.parse_and_eval('heaps_used')
|
389
390
|
|
390
391
|
for i in xrange(self.heaps_used):
|
391
|
-
p = gdb.
|
392
|
-
pend = p + gdb.
|
392
|
+
p = gdb.parse_and_eval("(RVALUE*) heaps[%i].slot" % i)
|
393
|
+
pend = p + gdb.parse_and_eval("heaps[%i].limit" % i)
|
393
394
|
|
394
395
|
while p < pend:
|
395
396
|
yield p, p['as']['basic']['flags']
|
@@ -409,15 +410,15 @@ class RubyMethodCache (gdb.Command):
|
|
409
410
|
|
410
411
|
def invoke (self, arg, from_tty):
|
411
412
|
self.dont_repeat()
|
412
|
-
cache = gdb.
|
413
|
+
cache = gdb.parse_and_eval('cache')
|
413
414
|
size = 0x800
|
414
415
|
empty = 0
|
415
416
|
|
416
417
|
for i in xrange(size):
|
417
418
|
entry = cache[i]
|
418
419
|
if entry['mid'] != 0:
|
419
|
-
klass = gdb.
|
420
|
-
method = gdb.
|
420
|
+
klass = gdb.parse_and_eval('rb_class2name(%d)' % entry['klass'])
|
421
|
+
method = gdb.parse_and_eval('rb_id2name(%d)' % entry['mid'])
|
421
422
|
print " %s#%s" % (klass and klass.string() or '(unknown)', method and method.string() or '(unknown)')
|
422
423
|
else:
|
423
424
|
empty += 1
|
@@ -433,7 +434,7 @@ class RubyPrint (gdb.Command):
|
|
433
434
|
def invoke (self, arg, from_tty):
|
434
435
|
self.dont_repeat()
|
435
436
|
|
436
|
-
type = int(gdb.
|
437
|
+
type = int(gdb.parse_and_eval("((struct RBasic *)(%d))->flags & 0x3f" % int(arg,0)))
|
437
438
|
rtype = RubyObjects.TYPES.get(type, 'unknown')
|
438
439
|
|
439
440
|
if rtype == 'array':
|
@@ -449,7 +450,12 @@ class RubyEval (gdb.Command):
|
|
449
450
|
|
450
451
|
def invoke (self, arg, from_tty):
|
451
452
|
self.dont_repeat()
|
452
|
-
|
453
|
+
arg = arg.replace('\\', '\\\\').replace('"', '\\\"')
|
454
|
+
print gdb.parse_and_eval("((struct RString*)rb_eval_string_protect(\"begin; (%s).inspect; rescue Exception => e; e.inspect; end\", 0))->ptr" % arg).string()
|
455
|
+
|
456
|
+
|
457
|
+
##
|
458
|
+
# Create GDB commands
|
453
459
|
|
454
460
|
Ruby()
|
455
461
|
RubyThreads()
|
@@ -459,10 +465,25 @@ RubyMethodCache()
|
|
459
465
|
RubyPrint()
|
460
466
|
RubyEval()
|
461
467
|
|
468
|
+
##
|
469
|
+
# Detect MRI vs REE
|
470
|
+
|
471
|
+
ruby = gdb.execute("info files", to_string=True).split("\n")[0]
|
472
|
+
ruby = re.search('"(.+)"\.?$', ruby)
|
473
|
+
ruby = ruby.group(1)
|
474
|
+
ruby = os.popen("%s -v" % ruby).read()
|
475
|
+
|
476
|
+
if re.search('Enterprise', ruby):
|
477
|
+
gdb.execute("macro define FL_USHIFT 12")
|
478
|
+
else:
|
479
|
+
gdb.execute("macro define FL_USHIFT 11")
|
480
|
+
|
481
|
+
##
|
482
|
+
# Define common macros
|
483
|
+
|
462
484
|
macros = """
|
463
485
|
macro define R_CAST(st) (struct st*)
|
464
486
|
macro define RNODE(obj) (R_CAST(RNode)(obj))
|
465
|
-
macro define FL_USHIFT 12
|
466
487
|
macro define CHAR_BIT 8
|
467
488
|
macro define NODE_LSHIFT (FL_USHIFT+8)
|
468
489
|
macro define NODE_LMASK (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
|
@@ -486,6 +507,9 @@ for m in macros:
|
|
486
507
|
if len(m.strip()) > 0:
|
487
508
|
gdb.execute(m)
|
488
509
|
|
510
|
+
##
|
511
|
+
# Define types
|
512
|
+
|
489
513
|
types = """
|
490
514
|
T_NONE 0x00
|
491
515
|
|
@@ -525,6 +549,9 @@ for t in types:
|
|
525
549
|
gdb.execute("macro define %s %s" % (name, val))
|
526
550
|
RubyObjects.TYPES[int(val,16)] = name[2:].lower()
|
527
551
|
|
552
|
+
##
|
553
|
+
# Set GDB options
|
554
|
+
|
528
555
|
settings = """
|
529
556
|
set height 0
|
530
557
|
set width 0
|