2 Assorted utilities for HHVM GDB bindings.
5 from compatibility
import *
16 #------------------------------------------------------------------------------
22 """Simple memoization decorator that ignores **kwargs."""
26 _all_caches
.append(cache
)
28 @functools.wraps(func
)
30 if not isinstance(args
, collections
.Hashable
):
33 cache
[args
] = func(*args
)
38 def invalidate_all_memoizers():
41 for cache
in _all_caches
:
45 #------------------------------------------------------------------------------
46 # Exception debugging.
49 @functools.wraps(func
)
50 def wrapped(*args
, **kwds
):
52 return func(*args
, **kwds
)
61 #------------------------------------------------------------------------------
62 # General-purpose helpers.
64 def parse_argv(args
, limit
=None):
65 """Explode a gdb argument string, then eval all args up to `limit'."""
68 return [gdb
.parse_and_eval(arg
) if i
< limit
else arg
69 for i
, arg
in enumerate(gdb
.string_to_argv(args
))]
72 def gdbprint(val
, ty
=None):
75 gdb
.execute('print (%s)%s' % (str(ty
), str(val
)))
78 def plural_suffix(num
, suffix
='s'):
79 return '' if num
== 1 else suffix
82 #------------------------------------------------------------------------------
85 def _bit_reflect(num
, nbits
):
86 """Perform bit reflection on the bottom `nbits' of `num."""
88 mask
= 1 << (nbits
- 1)
89 for i
in xrange(nbits
):
96 def crc32q(crc
, quad
):
97 """Intel SSE4 CRC32 implementation."""
99 crc
= _bit_reflect(crc
, 32)
100 quad
= _bit_reflect(quad
, 64)
104 dividend
= quad ^
(crc
<< 32)
105 divisor
= 0x11edc6f41 << 31
112 return _bit_reflect(dividend
, 64)
115 #------------------------------------------------------------------------------
118 def string_data_val(val
, keep_case
=True):
119 """Convert an HPHP::StringData[*] to a Python string."""
121 if V('HPHP::use_lowptr'):
122 data
= (deref(val
).address
+ 1).cast(T('char').pointer())
126 s
= data
.string('utf-8', 'ignore', val
['m_len'])
127 return s
if keep_case
else s
.lower()
131 return 0xdfdfdfdfdfdfdfdf & struct
.unpack('<Q', s
)[0]
134 """Hash a string as in hphp/util/hash-crc.S."""
142 for i
in xrange(0, size
, 8):
143 crc
= crc32q(crc
, _unpack(s
[i
:i
+8]))
148 shift
= -((tail_sz
- 8) << 3) & 0b111111
149 tail
= _unpack(s
[size
:].ljust(8, '\0'))
151 crc
= crc32q(crc
, tail
<< shift
)
155 def strinfo(s
, keep_case
=True):
156 """Return the Python string and HHVM hash for `s', or None if `s' is not a
157 stringish gdb.Value."""
165 if (t
== T('char').pointer() or
166 re
.match(r
"char \[\d*\]$", str(t
)) is not None):
171 if rawtype(sd
.type).name
!= 'HPHP::StringData':
174 data
= string_data_val(sd
)
176 if int(sd
['m_hash']) != 0:
177 h
= sd
['m_hash'] & 0x7fffffff
183 'data': data
if keep_case
else data
.lower(),
184 'hash': h
if h
is not None else hash_string(str(data
)),
190 """Stringify a value without pretty-printing."""
192 for pp
in gdb
.pretty_printers
:
194 pp
.saved
= pp
.enabled
195 except AttributeError:
205 for pp
in gdb
.pretty_printers
:
206 pp
.enabled
= pp
.saved
211 #------------------------------------------------------------------------------
216 return gdb
.lookup_type(name
)
220 return gdb
.lookup_global_symbol(name
).value()
228 return gdb
.Value(0).cast(T('void').pointer())
233 return gdb
.lookup_symbol(name
)[0].value()
235 return gdb
.lookup_symbol(name
)[0].value(gdb
.selected_frame())
238 #------------------------------------------------------------------------------
239 # Type manipulations.
242 return t
.unqualified().strip_typedefs()
245 def template_type(t
):
246 """Get the unparametrized name of a template type."""
247 return str(t
).split('<')[0]
251 """Fully strip a smart pointer type to a raw pointer. References are
252 re-cast as pointers."""
254 t
= rawtype(val
.type)
256 if t
.code
== gdb
.TYPE_CODE_PTR
:
258 elif t
.code
== gdb
.TYPE_CODE_REF
:
259 return val
.referenced_value().address
261 name
= template_type(t
)
264 if name
== 'std::unique_ptr':
265 ptr
= val
['_M_t']['_M_head_impl']
267 if name
== 'HPHP::default_ptr':
270 if name
== 'HPHP::req::ptr' or name
== 'HPHP::AtomicSharedPtrImpl':
273 if name
== 'HPHP::LowPtr' or name
== 'HPHP::detail::LowPtrImpl':
274 inner
= t
.template_argument(0)
275 ptr
= val
['m_s'].cast(inner
.pointer())
277 if name
== 'HPHP::CompactTaggedPtr':
278 inner
= t
.template_argument(0)
279 ptr
= (val
['m_data'] & 0xffffffffffff).cast(inner
.pointer())
281 if name
== 'HPHP::CompactSizedPtr':
282 ptr
= rawptr(val
['m_data'])
291 """Fully dereference a value, stripping away *, &, and all known smart
292 pointer wrappers (as well as const/volatile qualifiers)."""
297 return val
.cast(rawtype(val
.type))
299 return deref(p
.referenced_value())