def python_categorization(usage_set): # special-cased categorization for CPython # The Objects/stringobject.c:interned dictionary is typically large, # with its PyDictEntry table occuping 200k on a 64-bit build of python 2.6 # Identify it: try: val_interned = gdb.parse_and_eval('interned') pyop = PyDictObjectPtr.from_pyobject_ptr(val_interned) ma_table = int(pyop.field('ma_table')) usage_set.set_addr_category(ma_table, Category('cpython', 'PyDictEntry table', 'interned'), level=1) except RuntimeError: pass # Various kinds of per-type optimized allocator # See Modules/gcmodule.c:clear_freelists # The Objects/intobject.c: block_list try: val_block_list = gdb.parse_and_eval('block_list') if str(val_block_list.type.target()) != 'PyIntBlock': raise RuntimeError while int(val_block_list) != 0: usage_set.set_addr_category(int(val_block_list), Category('cpython', '_intblock', ''), level=0) val_block_list = val_block_list['next'] except RuntimeError: pass
def categorize_refs(self, usage_set, level=0, detail=None): return True # FIXME cl_name = self.cl_name() # print 'cl_name', cl_name # Visit the in_dict: in_dict = self.field('in_dict') # print 'in_dict', in_dict dict_detail = '%s.__dict__' % cl_name # Mark the ptr as being a dictionary, adding detail usage_set.set_addr_category(obj_addr_to_gc_addr(in_dict), Category('cpython', 'PyDictObject', dict_detail), level=1) # Visit ma_table: _type_PyDictObject_ptr = caching_lookup_type('PyDictObject').pointer() in_dict = in_dict.cast(_type_PyDictObject_ptr) ma_table = int(in_dict['ma_table']) # Record details: usage_set.set_addr_category(ma_table, Category('cpython', 'PyDictEntry table', dict_detail), level=2) return True
def iter_usage(self): # The struct pool_header at the front: yield Usage(self.as_address(), POOL_OVERHEAD(), Category('pyarena', 'pool_header overhead')) fb = list(self.iter_free_blocks()) for (start, size) in fb: yield Usage(start, size, Category('pyarena', 'freed pool chunk')) for (start, size) in self.iter_used_blocks(): if (start, size) not in fb: yield Usage(start, size) #, 'python pool: ' + categorize(start, size, None))
def categorize_refs(self, usage_set, level=0, detail=None): dims = '%sw x %sh' % (self._gdbval['width'], self._gdbval['height']) usage_set.set_addr_category(int(self._gdbval['pixels']), Category('GType', 'GdkPixbuf pixels', dims), level=level + 1, debug=True)
def categorize_refs(self, usage_set, level=0, detail=None): # This gives us access to the freetype library: FT_Library = WrappedPointer(self._gdbval['library']) # This is actually a "struct FT_LibraryRec_", in FreeType's # include/freetype/internal/ftobjs.h # print FT_Library._gdbval.dereference() usage_set.set_addr_category(FT_Library.as_address(), Category('FreeType', 'Library', ''), level=level + 1, debug=True) usage_set.set_addr_category(int(FT_Library.field('raster_pool')), Category('FreeType', 'raster_pool', ''), level=level + 2, debug=True)
def iter_usage(self): '''Yield a series of Usage instances''' if self.excess != 0: # FIXME: this size is wrong yield Usage(self.as_address(), self.excess, Category('pyarena', 'alignment wastage')) for pool in self.iter_pools(): # print 'pool:', pool for u in pool.iter_usage(): yield u
def categorize_sqlite3(addr, usage_set, visited): # "struct sqlite3" is defined in src/sqliteInt.h, which is an internal header ptr_type = caching_lookup_type('sqlite3').pointer() obj_ptr = gdb.Value(addr).cast(ptr_type) # print obj_ptr.dereference() aDb = obj_ptr['aDb'] Db_addr = long(aDb) Db_malloc_addr = Db_addr - 8 if usage_set.set_addr_category(Db_malloc_addr, Category('sqlite3', 'struct Db', None), visited): print aDb['pBt'].dereference()
def categorize(self): # Python objects will be categorized as ("python", tp_name), but # old-style classes have to do more work # l = [str(self)] # try: # l.append(str(self.type())) # l.append(self.type().field('tp_name').string()) # except Exception as e: # print('categorize') # print('\n'.join(l)) # print(e) return Category('python', self.safe_tp_name())
def categorize_refs(self, usage_set, level=0, detail=None): attr_dict = self.get_attr_dict() if attr_dict: # Mark the dictionary's "detail" with our typename # gdb.execute('print (PyObject*)0x%x' % int(attr_dict._gdbval)) usage_set.set_addr_category(obj_addr_to_gc_addr(attr_dict._gdbval), Category('python', 'dict', '%s.__dict__' % self.safe_tp_name()), level=level+1) # and mark the dict's PyDictEntry with our typename: attr_dict.categorize_refs(usage_set, level=level+1, detail='%s.__dict__' % self.safe_tp_name()) return True
def categorize_refs(self, usage_set, level=0, detail=None): priv_type = caching_lookup_type('GdkImagePrivateX11').pointer() priv_data = WrappedPointer( self._gdbval['windowing_data'].cast(priv_type)) usage_set.set_addr_category(priv_data.as_address(), Category('GType', 'GdkImagePrivateX11', ''), level=level + 1, debug=True) ximage = WrappedPointer(priv_data.field('ximage')) dims = '%sw x %sh x %sbpp' % (ximage.field('width'), ximage.field('height'), ximage.field('depth')) usage_set.set_addr_category(ximage.as_address(), Category('X11', 'Image', dims), level=level + 2, debug=True) usage_set.set_addr_category(int(ximage.field('data')), Category('X11', 'Image data', dims), level=level + 2, debug=True)
def categorize(self): return Category('GType', self.typename, '')
def categorize(self): return Category('python', self.cl_name(), 'old-style')
def categorize_refs(self, usage_set, level=0, detail=None): ma_keys = int(self.field('ma_keys')) usage_set.set_addr_category( ma_keys, Category('cpython', 'PyDictKeysObject', detail), level) return True
def categorize_refs(self, usage_set, level=0, detail=None): ma_table = to_int(self.field('ma_table')) usage_set.set_addr_category(ma_table, Category('cpython', 'PyDictEntry table', detail), level) return True
def categorize_refs(self, usage_set, level=0, detail=None): m_str = to_int(self.field('str')) usage_set.set_addr_category(m_str, Category('cpython', 'PyUnicodeObject buffer', detail), level) return True
def categorize(self): # Python objects will be categorized as ("python", tp_name), but # old-style classes have to do more work return Category('python', self.safe_tp_name())