tor-browser

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

ExecutableAllocator.py (3642B)


      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 """
      6 All jitted code is allocated via the ExecutableAllocator class. Make GDB aware
      7 of them, such that we can query for pages which are containing code which are
      8 allocated by the Jits.
      9 """
     10 
     11 import gdb
     12 
     13 import mozilla.prettyprinters
     14 from mozilla.prettyprinters import pretty_printer, ptr_pretty_printer
     15 
     16 # Forget any printers from previous loads of this module.
     17 mozilla.prettyprinters.clear_module_printers(__name__)
     18 
     19 
     20 class jsjitExecutableAllocatorCache:
     21    """Cache information about the ExecutableAllocator type for this objfile."""
     22 
     23    def __init__(self):
     24        self.d = None
     25 
     26    def __getattr__(self, name):
     27        if self.d is None:
     28            self.initialize()
     29        return self.d[name]
     30 
     31    def initialize(self):
     32        self.d = {}
     33        self.d["ExecutableAllocator"] = gdb.lookup_type("js::jit::ExecutableAllocator")
     34        self.d["ExecutablePool"] = gdb.lookup_type("js::jit::ExecutablePool")
     35        self.d["HashNumber"] = gdb.lookup_type("mozilla::HashNumber")
     36 
     37 
     38 @pretty_printer("js::jit::ExecutableAllocator")
     39 class jsjitExecutableAllocator:
     40    def __init__(self, value, cache):
     41        if not cache.mod_ExecutableAllocator:
     42            cache.mod_ExecutableAllocator = jsjitExecutableAllocatorCache()
     43        self.value = value
     44        self.cache = cache.mod_ExecutableAllocator
     45 
     46    def to_string(self):
     47        return "ExecutableAllocator([%s])" % ", ".join([str(x) for x in self])
     48 
     49    def __iter__(self):
     50        return self.PoolIterator(self)
     51 
     52    class PoolIterator:
     53        def __init__(self, allocator):
     54            self.allocator = allocator
     55            self.entryType = allocator.cache.ExecutablePool.pointer()
     56            self.hashNumType = allocator.cache.HashNumber
     57            # Emulate the HashSet::Range
     58            self.table = allocator.value["m_pools"]["mImpl"]["mTable"]
     59            self.index = 0
     60            kHashNumberBits = 32
     61            hashShiftMask = 0xFF
     62            genAndHashShift = allocator.value["m_pools"]["mImpl"]["mGenAndHashShift"]
     63            hashShift = genAndHashShift & hashShiftMask
     64            self.capacity = 1 << (kHashNumberBits - hashShift)
     65            if self.table == 0:
     66                self.capacity = 0
     67            # auto hashes = reinterpret_cast<HashNumber*>(mTable);
     68            self.hashes = self.table.cast(self.hashNumType.pointer())
     69            # auto entries = reinterpret_cast<Entry*>(&hashes[capacity()]);
     70            self.entries = (self.hashes + self.capacity).cast(self.entryType.pointer())
     71 
     72        def __iter__(self):
     73            return self
     74 
     75        def next(self):
     76            return self.__next__()
     77 
     78        def __next__(self):
     79            cur = self.index
     80            if cur >= self.capacity:
     81                raise StopIteration()
     82            self.index = self.index + 1
     83            if self.hashes[cur] > 1:  # table[i]->isLive()
     84                return self.entries[cur]
     85            return self.__next__()
     86 
     87 
     88 @ptr_pretty_printer("js::jit::ExecutablePool")
     89 class jsjitExecutablePool(mozilla.prettyprinters.Pointer):
     90    def __init__(self, value, cache):
     91        if not cache.mod_ExecutableAllocator:
     92            cache.mod_ExecutableAllocator = jsjitExecutableAllocatorCache()
     93        self.value = value
     94        self.cache = cache.mod_ExecutableAllocator
     95 
     96    def to_string(self):
     97        pages = self.value["m_allocation"]["pages"]
     98        size = self.value["m_allocation"]["size"]
     99        return "ExecutablePool %08x-%08x" % (pages, pages + size)