tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

GCCellPtr.py (4624B)


      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 GCCellPtr values.
      6 
      7 import gdb
      8 
      9 import mozilla.prettyprinters
     10 from mozilla.prettyprinters import pretty_printer
     11 
     12 # Forget any printers from previous loads of this module.
     13 mozilla.prettyprinters.clear_module_printers(__name__)
     14 
     15 # Cache information about the types for this objfile.
     16 
     17 
     18 class GCCellPtrTypeCache:
     19    def __init__(self, cache):
     20        self.TraceKind_t = gdb.lookup_type("JS::TraceKind")
     21        self.AllocKind_t = gdb.lookup_type("js::gc::AllocKind")
     22        self.Arena_t = gdb.lookup_type("js::gc::Arena")
     23        self.Cell_t = gdb.lookup_type("js::gc::Cell")
     24        self.TenuredCell_t = gdb.lookup_type("js::gc::TenuredCell")
     25 
     26        trace_kinds = gdb.types.make_enum_dict(self.TraceKind_t)
     27        alloc_kinds = gdb.types.make_enum_dict(self.AllocKind_t)
     28 
     29        def trace_kind(k):
     30            return trace_kinds["JS::TraceKind::" + k]
     31 
     32        def alloc_kind(k):
     33            return alloc_kinds["js::gc::AllocKind::" + k]
     34 
     35        # Build a mapping from TraceKind enum values to the types they denote.
     36        trace_map = {
     37            # Inline types.
     38            "Object": "JSObject",
     39            "BigInt": "JS::BigInt",
     40            "String": "JSString",
     41            "GetterSetter": "js::GetterSetter",
     42            "Symbol": "JS::Symbol",
     43            "Shape": "js::Shape",
     44            "Null": "std::nullptr_t",
     45            # Out-of-line types.
     46            "BaseShape": "js::BaseShape",
     47            "JitCode": "js::jit::JitCode",
     48            "Script": "js::BaseScript",
     49            "Scope": "js::Scope",
     50            "RegExpShared": "js::RegExpShared",
     51            "PropMap": "js::PropMap",
     52        }
     53 
     54        # Map from AllocKind to TraceKind for out-of-line types.
     55        alloc_map = {
     56            "BASE_SHAPE": "BaseShape",
     57            "JITCODE": "JitCode",
     58            "SCRIPT": "Script",
     59            "SCOPE": "Scope",
     60            "REGEXP_SHARED": "RegExpShared",
     61            "COMPACT_PROP_MAP": "PropMap",
     62            "NORMAL_PROP_MAP": "PropMap",
     63            "DICT_PROP_MAP": "PropMap",
     64        }
     65 
     66        self.trace_kind_to_type = {
     67            trace_kind(k): gdb.lookup_type(v) for k, v in trace_map.items()
     68        }
     69        self.alloc_kind_to_trace_kind = {
     70            alloc_kind(k): trace_kind(v) for k, v in alloc_map.items()
     71        }
     72 
     73        self.Null = trace_kind("Null")
     74        self.tracekind_mask = gdb.parse_and_eval("JS::OutOfLineTraceKindMask")
     75        self.arena_mask = gdb.parse_and_eval("js::gc::ArenaMask")
     76 
     77 
     78 @pretty_printer("JS::GCCellPtr")
     79 class GCCellPtr:
     80    def __init__(self, value, cache):
     81        self.value = value
     82        if not cache.mod_GCCellPtr:
     83            cache.mod_GCCellPtr = GCCellPtrTypeCache(cache)
     84        self.cache = cache
     85 
     86    def to_string(self):
     87        ptr = self.value["ptr"]
     88        kind = ptr & self.cache.mod_GCCellPtr.tracekind_mask
     89        if kind == self.cache.mod_GCCellPtr.Null:
     90            return "JS::GCCellPtr(nullptr)"
     91        if kind == self.cache.mod_GCCellPtr.tracekind_mask:
     92            # Out-of-line trace kinds.
     93            #
     94            # Compute the underlying type for out-of-line kinds by
     95            # reimplementing the GCCellPtr::outOfLineKind() method.
     96            #
     97            # The extra casts below are only present to make it easier to
     98            # compare this code against the C++ implementation.
     99 
    100            # GCCellPtr::asCell()
    101            cell_ptr = ptr & ~self.cache.mod_GCCellPtr.tracekind_mask
    102            cell = cell_ptr.reinterpret_cast(self.cache.mod_GCCellPtr.Cell_t.pointer())
    103 
    104            # Cell::asTenured()
    105            tenured = cell.cast(self.cache.mod_GCCellPtr.TenuredCell_t.pointer())
    106 
    107            # TenuredCell::arena()
    108            addr = int(tenured)
    109            arena_ptr = addr & ~self.cache.mod_GCCellPtr.arena_mask
    110            arena = arena_ptr.reinterpret_cast(
    111                self.cache.mod_GCCellPtr.Arena_t.pointer()
    112            )
    113 
    114            # Arena::getAllocKind()
    115            alloc_kind = arena["allocKind"].cast(self.cache.mod_GCCellPtr.AllocKind_t)
    116            alloc_idx = int(
    117                alloc_kind.cast(self.cache.mod_GCCellPtr.AllocKind_t.target())
    118            )
    119 
    120            # Map the AllocKind to a TraceKind.
    121            kind = self.cache.mod_GCCellPtr.alloc_kind_to_trace_kind[alloc_idx]
    122        type_name = self.cache.mod_GCCellPtr.trace_kind_to_type[int(kind)]
    123        return f"JS::GCCellPtr(({type_name}*) {ptr.cast(self.cache.void_ptr_t)})"