JSString.py (3475B)
1 # This Source Code Form is subject to the terms of the Mozilla Public 2 # License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 # You can obtain one at http://mozilla.org/MPL/2.0/. 4 5 # Pretty-printers for SpiderMonkey strings. 6 7 import gdb 8 9 import mozilla.prettyprinters 10 from mozilla.CellHeader import get_header_length_and_flags 11 from mozilla.prettyprinters import ptr_pretty_printer 12 13 try: 14 chr(10000) # UPPER RIGHT PENCIL 15 except ValueError: # yuck, we are in Python 2.x, so chr() is 8-bit 16 chr = unichr # replace with teh unicodes 17 18 # Forget any printers from previous loads of this module. 19 mozilla.prettyprinters.clear_module_printers(__name__) 20 21 22 class JSStringTypeCache: 23 # Cache information about the JSString type for this objfile. 24 def __init__(self, cache): 25 dummy = gdb.Value(0).cast(cache.JSString_ptr_t) 26 self.ATOM_BIT = dummy["ATOM_BIT"] 27 self.LINEAR_BIT = dummy["LINEAR_BIT"] 28 self.INLINE_CHARS_BIT = dummy["INLINE_CHARS_BIT"] 29 self.TYPE_FLAGS_MASK = dummy["TYPE_FLAGS_MASK"] 30 self.LATIN1_CHARS_BIT = dummy["LATIN1_CHARS_BIT"] 31 32 33 class Common(mozilla.prettyprinters.Pointer): 34 def __init__(self, value, cache): 35 super().__init__(value, cache) 36 if not cache.mod_JSString: 37 cache.mod_JSString = JSStringTypeCache(cache) 38 self.stc = cache.mod_JSString 39 40 41 @ptr_pretty_printer("JSString") 42 class JSStringPtr(Common): 43 def display_hint(self): 44 return "string" 45 46 def chars(self): 47 d = self.value["d"] 48 length, flags = get_header_length_and_flags(self.value, self.cache) 49 50 corrupt = { 51 0x2F2F2F2F: "JS_FRESH_NURSERY_PATTERN", 52 0x2B2B2B2B: "JS_SWEPT_NURSERY_PATTERN", 53 0xE5E5E5E5: "jemalloc freed memory", 54 }.get(flags & 0xFFFFFFFF) 55 if corrupt: 56 yield from "<CORRUPT:%s>" % corrupt 57 return 58 is_rope = (flags & self.stc.LINEAR_BIT) == 0 59 if is_rope: 60 for c in JSStringPtr(d["s"]["u2"]["left"], self.cache).chars(): 61 yield c 62 for c in JSStringPtr(d["s"]["u3"]["right"], self.cache).chars(): 63 yield c 64 else: 65 is_inline = (flags & self.stc.INLINE_CHARS_BIT) != 0 66 is_latin1 = (flags & self.stc.LATIN1_CHARS_BIT) != 0 67 if is_inline: 68 if is_latin1: 69 chars = d["inlineStorageLatin1"] 70 else: 71 chars = d["inlineStorageTwoByte"] 72 elif is_latin1: 73 chars = d["s"]["u2"]["nonInlineCharsLatin1"] 74 else: 75 chars = d["s"]["u2"]["nonInlineCharsTwoByte"] 76 for i in range(int(length)): 77 yield chars[i] 78 79 def to_string(self, maxlen=200): 80 s = "" 81 invalid_chars_allowed = 2 82 for c in self.chars(): 83 if len(s) >= maxlen: 84 s += "..." 85 break 86 87 try: 88 # Convert from gdb.Value to string. 89 s += chr(c) 90 except ValueError: 91 if invalid_chars_allowed == 0: 92 s += "<TOO_MANY_INVALID_CHARS>" 93 break 94 else: 95 invalid_chars_allowed -= 1 96 s += "\\x%04x" % (c & 0xFFFF) 97 return s 98 99 100 @ptr_pretty_printer("JSAtom") 101 class JSAtomPtr(Common): 102 def to_string(self): 103 return self.value.cast(self.cache.JSString_ptr_t)