summaryrefslogtreecommitdiffstats
path: root/js/src/gdb/mozilla/ExecutableAllocator.py
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/gdb/mozilla/ExecutableAllocator.py')
-rw-r--r--js/src/gdb/mozilla/ExecutableAllocator.py97
1 files changed, 97 insertions, 0 deletions
diff --git a/js/src/gdb/mozilla/ExecutableAllocator.py b/js/src/gdb/mozilla/ExecutableAllocator.py
new file mode 100644
index 0000000000..5187e2d1f1
--- /dev/null
+++ b/js/src/gdb/mozilla/ExecutableAllocator.py
@@ -0,0 +1,97 @@
+# 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/.
+
+"""
+All jitted code is allocated via the ExecutableAllocator class. Make GDB aware
+of them, such that we can query for pages which are containing code which are
+allocated by the Jits.
+"""
+
+import gdb
+
+import mozilla.prettyprinters
+from mozilla.prettyprinters import pretty_printer, ptr_pretty_printer
+
+# Forget any printers from previous loads of this module.
+mozilla.prettyprinters.clear_module_printers(__name__)
+
+
+class jsjitExecutableAllocatorCache(object):
+ """Cache information about the ExecutableAllocator type for this objfile."""
+
+ def __init__(self):
+ self.d = None
+
+ def __getattr__(self, name):
+ if self.d is None:
+ self.initialize()
+ return self.d[name]
+
+ def initialize(self):
+ self.d = {}
+ self.d["ExecutableAllocator"] = gdb.lookup_type("js::jit::ExecutableAllocator")
+ self.d["ExecutablePool"] = gdb.lookup_type("js::jit::ExecutablePool")
+ self.d["HashNumber"] = gdb.lookup_type("mozilla::HashNumber")
+
+
+@pretty_printer("js::jit::ExecutableAllocator")
+class jsjitExecutableAllocator(object):
+ def __init__(self, value, cache):
+ if not cache.mod_ExecutableAllocator:
+ cache.mod_ExecutableAllocator = jsjitExecutableAllocatorCache()
+ self.value = value
+ self.cache = cache.mod_ExecutableAllocator
+
+ def to_string(self):
+ return "ExecutableAllocator([%s])" % ", ".join([str(x) for x in self])
+
+ def __iter__(self):
+ return self.PoolIterator(self)
+
+ class PoolIterator(object):
+ def __init__(self, allocator):
+ self.allocator = allocator
+ self.entryType = allocator.cache.ExecutablePool.pointer()
+ self.hashNumType = allocator.cache.HashNumber
+ # Emulate the HashSet::Range
+ self.table = allocator.value["m_pools"]["mImpl"]["mTable"]
+ self.index = 0
+ kHashNumberBits = 32
+ hashShift = allocator.value["m_pools"]["mImpl"]["mHashShift"]
+ self.capacity = 1 << (kHashNumberBits - hashShift)
+ if self.table == 0:
+ self.capacity = 0
+ # auto hashes = reinterpret_cast<HashNumber*>(mTable);
+ self.hashes = self.table.cast(self.hashNumType.pointer())
+ # auto entries = reinterpret_cast<Entry*>(&hashes[capacity()]);
+ self.entries = (self.hashes + self.capacity).cast(self.entryType.pointer())
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ return self.__next__()
+
+ def __next__(self):
+ cur = self.index
+ if cur >= self.capacity:
+ raise StopIteration()
+ self.index = self.index + 1
+ if self.hashes[cur] > 1: # table[i]->isLive()
+ return self.entries[cur]
+ return self.__next__()
+
+
+@ptr_pretty_printer("js::jit::ExecutablePool")
+class jsjitExecutablePool(mozilla.prettyprinters.Pointer):
+ def __init__(self, value, cache):
+ if not cache.mod_ExecutableAllocator:
+ cache.mod_ExecutableAllocator = jsjitExecutableAllocatorCache()
+ self.value = value
+ self.cache = cache.mod_ExecutableAllocator
+
+ def to_string(self):
+ pages = self.value["m_allocation"]["pages"]
+ size = self.value["m_allocation"]["size"]
+ return "ExecutablePool %08x-%08x" % (pages, pages + size)