# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. # Pretty-printers for SpiderMonkey strings. import gdb import mozilla.prettyprinters from mozilla.CellHeader import get_header_length_and_flags from mozilla.prettyprinters import ptr_pretty_printer try: chr(10000) # UPPER RIGHT PENCIL except ValueError: # yuck, we are in Python 2.x, so chr() is 8-bit chr = unichr # replace with teh unicodes # Forget any printers from previous loads of this module. mozilla.prettyprinters.clear_module_printers(__name__) class JSStringTypeCache(object): # Cache information about the JSString type for this objfile. def __init__(self, cache): dummy = gdb.Value(0).cast(cache.JSString_ptr_t) self.ATOM_BIT = dummy["ATOM_BIT"] self.LINEAR_BIT = dummy["LINEAR_BIT"] self.INLINE_CHARS_BIT = dummy["INLINE_CHARS_BIT"] self.TYPE_FLAGS_MASK = dummy["TYPE_FLAGS_MASK"] self.LATIN1_CHARS_BIT = dummy["LATIN1_CHARS_BIT"] class Common(mozilla.prettyprinters.Pointer): def __init__(self, value, cache): super(Common, self).__init__(value, cache) if not cache.mod_JSString: cache.mod_JSString = JSStringTypeCache(cache) self.stc = cache.mod_JSString @ptr_pretty_printer("JSString") class JSStringPtr(Common): def display_hint(self): return "string" def chars(self): d = self.value["d"] length, flags = get_header_length_and_flags(self.value, self.cache) corrupt = { 0x2F2F2F2F: "JS_FRESH_NURSERY_PATTERN", 0x2B2B2B2B: "JS_SWEPT_NURSERY_PATTERN", 0xE5E5E5E5: "jemalloc freed memory", }.get(flags & 0xFFFFFFFF) if corrupt: for ch in "" % corrupt: yield ch return is_rope = (flags & self.stc.LINEAR_BIT) == 0 if is_rope: for c in JSStringPtr(d["s"]["u2"]["left"], self.cache).chars(): yield c for c in JSStringPtr(d["s"]["u3"]["right"], self.cache).chars(): yield c else: is_inline = (flags & self.stc.INLINE_CHARS_BIT) != 0 is_latin1 = (flags & self.stc.LATIN1_CHARS_BIT) != 0 if is_inline: if is_latin1: chars = d["inlineStorageLatin1"] else: chars = d["inlineStorageTwoByte"] else: if is_latin1: chars = d["s"]["u2"]["nonInlineCharsLatin1"] else: chars = d["s"]["u2"]["nonInlineCharsTwoByte"] for i in range(int(length)): yield chars[i] def to_string(self, maxlen=200): s = "" invalid_chars_allowed = 2 for c in self.chars(): if len(s) >= maxlen: s += "..." break try: # Convert from gdb.Value to string. s += chr(c) except ValueError: if invalid_chars_allowed == 0: s += "" break else: invalid_chars_allowed -= 1 s += "\\x%04x" % (c & 0xFFFF) return s @ptr_pretty_printer("JSAtom") class JSAtomPtr(Common): def to_string(self): return self.value.cast(self.cache.JSString_ptr_t)