gdb.rb 0.1.3 → 0.1.5
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.
- 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
|