179939c4aSKuan-Ying Lee# SPDX-License-Identifier: GPL-2.0 279939c4aSKuan-Ying Lee# 379939c4aSKuan-Ying Lee# Copyright (c) 2023 MediaTek Inc. 479939c4aSKuan-Ying Lee# 579939c4aSKuan-Ying Lee# Authors: 679939c4aSKuan-Ying Lee# Kuan-Ying Lee <[email protected]> 779939c4aSKuan-Ying Lee# 879939c4aSKuan-Ying Lee 979939c4aSKuan-Ying Leeimport gdb 1079939c4aSKuan-Ying Leeimport re 1179939c4aSKuan-Ying Leeimport traceback 1279939c4aSKuan-Ying Leefrom linux import lists, utils, stackdepot, constants, mm 1379939c4aSKuan-Ying Lee 1479939c4aSKuan-Ying LeeSLAB_RED_ZONE = constants.LX_SLAB_RED_ZONE 1579939c4aSKuan-Ying LeeSLAB_POISON = constants.LX_SLAB_POISON 1679939c4aSKuan-Ying LeeSLAB_KMALLOC = constants.LX_SLAB_KMALLOC 1779939c4aSKuan-Ying LeeSLAB_HWCACHE_ALIGN = constants.LX_SLAB_HWCACHE_ALIGN 1879939c4aSKuan-Ying LeeSLAB_CACHE_DMA = constants.LX_SLAB_CACHE_DMA 1979939c4aSKuan-Ying LeeSLAB_CACHE_DMA32 = constants.LX_SLAB_CACHE_DMA32 2079939c4aSKuan-Ying LeeSLAB_STORE_USER = constants.LX_SLAB_STORE_USER 2179939c4aSKuan-Ying LeeSLAB_PANIC = constants.LX_SLAB_PANIC 2279939c4aSKuan-Ying Lee 2379939c4aSKuan-Ying LeeOO_SHIFT = 16 2479939c4aSKuan-Ying LeeOO_MASK = (1 << OO_SHIFT) - 1 2579939c4aSKuan-Ying Lee 2679939c4aSKuan-Ying Leeif constants.LX_CONFIG_SLUB_DEBUG: 2779939c4aSKuan-Ying Lee slab_type = utils.CachedType("struct slab") 2879939c4aSKuan-Ying Lee slab_ptr_type = slab_type.get_type().pointer() 2979939c4aSKuan-Ying Lee kmem_cache_type = utils.CachedType("struct kmem_cache") 3079939c4aSKuan-Ying Lee kmem_cache_ptr_type = kmem_cache_type.get_type().pointer() 3179939c4aSKuan-Ying Lee freeptr_t = utils.CachedType("freeptr_t") 3279939c4aSKuan-Ying Lee freeptr_t_ptr = freeptr_t.get_type().pointer() 3379939c4aSKuan-Ying Lee 3479939c4aSKuan-Ying Lee track_type = gdb.lookup_type('struct track') 3579939c4aSKuan-Ying Lee track_alloc = int(gdb.parse_and_eval('TRACK_ALLOC')) 3679939c4aSKuan-Ying Lee track_free = int(gdb.parse_and_eval('TRACK_FREE')) 3779939c4aSKuan-Ying Lee 3879939c4aSKuan-Ying Leedef slab_folio(slab): 3979939c4aSKuan-Ying Lee return slab.cast(gdb.lookup_type("struct folio").pointer()) 4079939c4aSKuan-Ying Lee 4179939c4aSKuan-Ying Leedef slab_address(slab): 4279939c4aSKuan-Ying Lee p_ops = mm.page_ops().ops 4379939c4aSKuan-Ying Lee folio = slab_folio(slab) 4479939c4aSKuan-Ying Lee return p_ops.folio_address(folio) 4579939c4aSKuan-Ying Lee 4679939c4aSKuan-Ying Leedef for_each_object(cache, addr, slab_objects): 4779939c4aSKuan-Ying Lee p = addr 4879939c4aSKuan-Ying Lee if cache['flags'] & SLAB_RED_ZONE: 4979939c4aSKuan-Ying Lee p += int(cache['red_left_pad']) 5079939c4aSKuan-Ying Lee while p < addr + (slab_objects * cache['size']): 5179939c4aSKuan-Ying Lee yield p 5279939c4aSKuan-Ying Lee p = p + int(cache['size']) 5379939c4aSKuan-Ying Lee 5479939c4aSKuan-Ying Leedef get_info_end(cache): 5579939c4aSKuan-Ying Lee if (cache['offset'] >= cache['inuse']): 5679939c4aSKuan-Ying Lee return cache['inuse'] + gdb.lookup_type("void").pointer().sizeof 5779939c4aSKuan-Ying Lee else: 5879939c4aSKuan-Ying Lee return cache['inuse'] 5979939c4aSKuan-Ying Lee 6079939c4aSKuan-Ying Leedef get_orig_size(cache, obj): 6179939c4aSKuan-Ying Lee if cache['flags'] & SLAB_STORE_USER and cache['flags'] & SLAB_KMALLOC: 6279939c4aSKuan-Ying Lee p = mm.page_ops().ops.kasan_reset_tag(obj) 6379939c4aSKuan-Ying Lee p += get_info_end(cache) 6479939c4aSKuan-Ying Lee p += gdb.lookup_type('struct track').sizeof * 2 6579939c4aSKuan-Ying Lee p = p.cast(utils.get_uint_type().pointer()) 6679939c4aSKuan-Ying Lee return p.dereference() 6779939c4aSKuan-Ying Lee else: 6879939c4aSKuan-Ying Lee return cache['object_size'] 6979939c4aSKuan-Ying Lee 7079939c4aSKuan-Ying Leedef get_track(cache, object_pointer, alloc): 7179939c4aSKuan-Ying Lee p = object_pointer + get_info_end(cache) 7279939c4aSKuan-Ying Lee p += (alloc * track_type.sizeof) 7379939c4aSKuan-Ying Lee return p 7479939c4aSKuan-Ying Lee 7579939c4aSKuan-Ying Leedef oo_objects(x): 7679939c4aSKuan-Ying Lee return int(x['x']) & OO_MASK 7779939c4aSKuan-Ying Lee 7879939c4aSKuan-Ying Leedef oo_order(x): 7979939c4aSKuan-Ying Lee return int(x['x']) >> OO_SHIFT 8079939c4aSKuan-Ying Lee 8179939c4aSKuan-Ying Leedef reciprocal_divide(a, R): 8279939c4aSKuan-Ying Lee t = (a * int(R['m'])) >> 32 8379939c4aSKuan-Ying Lee return (t + ((a - t) >> int(R['sh1']))) >> int(R['sh2']) 8479939c4aSKuan-Ying Lee 8579939c4aSKuan-Ying Leedef __obj_to_index(cache, addr, obj): 8679939c4aSKuan-Ying Lee return reciprocal_divide(int(mm.page_ops().ops.kasan_reset_tag(obj)) - addr, cache['reciprocal_size']) 8779939c4aSKuan-Ying Lee 8879939c4aSKuan-Ying Leedef swab64(x): 8979939c4aSKuan-Ying Lee result = (((x & 0x00000000000000ff) << 56) | \ 9079939c4aSKuan-Ying Lee ((x & 0x000000000000ff00) << 40) | \ 9179939c4aSKuan-Ying Lee ((x & 0x0000000000ff0000) << 24) | \ 9279939c4aSKuan-Ying Lee ((x & 0x00000000ff000000) << 8) | \ 9379939c4aSKuan-Ying Lee ((x & 0x000000ff00000000) >> 8) | \ 9479939c4aSKuan-Ying Lee ((x & 0x0000ff0000000000) >> 24) | \ 9579939c4aSKuan-Ying Lee ((x & 0x00ff000000000000) >> 40) | \ 9679939c4aSKuan-Ying Lee ((x & 0xff00000000000000) >> 56)) 9779939c4aSKuan-Ying Lee return result 9879939c4aSKuan-Ying Lee 9979939c4aSKuan-Ying Leedef freelist_ptr_decode(cache, ptr, ptr_addr): 10079939c4aSKuan-Ying Lee if constants.LX_CONFIG_SLAB_FREELIST_HARDENED: 10179939c4aSKuan-Ying Lee return ptr['v'] ^ cache['random'] ^ swab64(int(ptr_addr)) 10279939c4aSKuan-Ying Lee else: 10379939c4aSKuan-Ying Lee return ptr['v'] 10479939c4aSKuan-Ying Lee 10579939c4aSKuan-Ying Leedef get_freepointer(cache, obj): 10679939c4aSKuan-Ying Lee obj = mm.page_ops().ops.kasan_reset_tag(obj) 10779939c4aSKuan-Ying Lee ptr_addr = obj + cache['offset'] 10879939c4aSKuan-Ying Lee p = ptr_addr.cast(freeptr_t_ptr).dereference() 10979939c4aSKuan-Ying Lee return freelist_ptr_decode(cache, p, ptr_addr) 11079939c4aSKuan-Ying Lee 11179939c4aSKuan-Ying Leedef loc_exist(loc_track, addr, handle, waste): 11279939c4aSKuan-Ying Lee for loc in loc_track: 11379939c4aSKuan-Ying Lee if loc['addr'] == addr and loc['handle'] == handle and loc['waste'] == waste: 11479939c4aSKuan-Ying Lee return loc 11579939c4aSKuan-Ying Lee return None 11679939c4aSKuan-Ying Lee 11779939c4aSKuan-Ying Leedef add_location(loc_track, cache, track, orig_size): 11879939c4aSKuan-Ying Lee jiffies = gdb.parse_and_eval("jiffies_64") 11979939c4aSKuan-Ying Lee age = jiffies - track['when'] 12079939c4aSKuan-Ying Lee handle = 0 12179939c4aSKuan-Ying Lee waste = cache['object_size'] - int(orig_size) 12279939c4aSKuan-Ying Lee pid = int(track['pid']) 12379939c4aSKuan-Ying Lee cpuid = int(track['cpu']) 12479939c4aSKuan-Ying Lee addr = track['addr'] 12579939c4aSKuan-Ying Lee if constants.LX_CONFIG_STACKDEPOT: 12679939c4aSKuan-Ying Lee handle = track['handle'] 12779939c4aSKuan-Ying Lee 12879939c4aSKuan-Ying Lee loc = loc_exist(loc_track, addr, handle, waste) 12979939c4aSKuan-Ying Lee if loc: 13079939c4aSKuan-Ying Lee loc['count'] += 1 13179939c4aSKuan-Ying Lee if track['when']: 13279939c4aSKuan-Ying Lee loc['sum_time'] += age 13379939c4aSKuan-Ying Lee loc['min_time'] = min(loc['min_time'], age) 13479939c4aSKuan-Ying Lee loc['max_time'] = max(loc['max_time'], age) 13579939c4aSKuan-Ying Lee loc['min_pid'] = min(loc['min_pid'], pid) 13679939c4aSKuan-Ying Lee loc['max_pid'] = max(loc['max_pid'], pid) 13779939c4aSKuan-Ying Lee loc['cpus'].add(cpuid) 13879939c4aSKuan-Ying Lee else: 13979939c4aSKuan-Ying Lee loc_track.append({ 14079939c4aSKuan-Ying Lee 'count' : 1, 14179939c4aSKuan-Ying Lee 'addr' : addr, 14279939c4aSKuan-Ying Lee 'sum_time' : age, 14379939c4aSKuan-Ying Lee 'min_time' : age, 14479939c4aSKuan-Ying Lee 'max_time' : age, 14579939c4aSKuan-Ying Lee 'min_pid' : pid, 14679939c4aSKuan-Ying Lee 'max_pid' : pid, 14779939c4aSKuan-Ying Lee 'handle' : handle, 14879939c4aSKuan-Ying Lee 'waste' : waste, 14979939c4aSKuan-Ying Lee 'cpus' : {cpuid} 15079939c4aSKuan-Ying Lee } 15179939c4aSKuan-Ying Lee ) 15279939c4aSKuan-Ying Lee 15379939c4aSKuan-Ying Leedef slabtrace(alloc, cache_name): 15479939c4aSKuan-Ying Lee 15579939c4aSKuan-Ying Lee def __fill_map(obj_map, cache, slab): 15679939c4aSKuan-Ying Lee p = slab['freelist'] 15779939c4aSKuan-Ying Lee addr = slab_address(slab) 15879939c4aSKuan-Ying Lee while p != gdb.Value(0): 15979939c4aSKuan-Ying Lee index = __obj_to_index(cache, addr, p) 16079939c4aSKuan-Ying Lee obj_map[index] = True # free objects 16179939c4aSKuan-Ying Lee p = get_freepointer(cache, p) 16279939c4aSKuan-Ying Lee 16379939c4aSKuan-Ying Lee # process every slab page on the slab_list (partial and full list) 16479939c4aSKuan-Ying Lee def process_slab(loc_track, slab_list, alloc, cache): 16579939c4aSKuan-Ying Lee for slab in lists.list_for_each_entry(slab_list, slab_ptr_type, "slab_list"): 16679939c4aSKuan-Ying Lee obj_map[:] = [False] * oo_objects(cache['oo']) 16779939c4aSKuan-Ying Lee __fill_map(obj_map, cache, slab) 16879939c4aSKuan-Ying Lee addr = slab_address(slab) 16979939c4aSKuan-Ying Lee for object_pointer in for_each_object(cache, addr, slab['objects']): 17079939c4aSKuan-Ying Lee if obj_map[__obj_to_index(cache, addr, object_pointer)] == True: 17179939c4aSKuan-Ying Lee continue 17279939c4aSKuan-Ying Lee p = get_track(cache, object_pointer, alloc) 17379939c4aSKuan-Ying Lee track = gdb.Value(p).cast(track_type.pointer()) 17479939c4aSKuan-Ying Lee if alloc == track_alloc: 17579939c4aSKuan-Ying Lee size = get_orig_size(cache, object_pointer) 17679939c4aSKuan-Ying Lee else: 17779939c4aSKuan-Ying Lee size = cache['object_size'] 17879939c4aSKuan-Ying Lee add_location(loc_track, cache, track, size) 17979939c4aSKuan-Ying Lee continue 18079939c4aSKuan-Ying Lee 18179939c4aSKuan-Ying Lee slab_caches = gdb.parse_and_eval("slab_caches") 18279939c4aSKuan-Ying Lee if mm.page_ops().ops.MAX_NUMNODES > 1: 18379939c4aSKuan-Ying Lee nr_node_ids = int(gdb.parse_and_eval("nr_node_ids")) 18479939c4aSKuan-Ying Lee else: 18579939c4aSKuan-Ying Lee nr_node_ids = 1 18679939c4aSKuan-Ying Lee 18779939c4aSKuan-Ying Lee target_cache = None 18879939c4aSKuan-Ying Lee loc_track = [] 18979939c4aSKuan-Ying Lee 19079939c4aSKuan-Ying Lee for cache in lists.list_for_each_entry(slab_caches, kmem_cache_ptr_type, 'list'): 19179939c4aSKuan-Ying Lee if cache['name'].string() == cache_name: 19279939c4aSKuan-Ying Lee target_cache = cache 19379939c4aSKuan-Ying Lee break 19479939c4aSKuan-Ying Lee 19579939c4aSKuan-Ying Lee obj_map = [False] * oo_objects(target_cache['oo']) 19679939c4aSKuan-Ying Lee 19779939c4aSKuan-Ying Lee if target_cache['flags'] & SLAB_STORE_USER: 19879939c4aSKuan-Ying Lee for i in range(0, nr_node_ids): 19979939c4aSKuan-Ying Lee cache_node = target_cache['node'][i] 20079939c4aSKuan-Ying Lee if cache_node['nr_slabs']['counter'] == 0: 20179939c4aSKuan-Ying Lee continue 20279939c4aSKuan-Ying Lee process_slab(loc_track, cache_node['partial'], alloc, target_cache) 20379939c4aSKuan-Ying Lee process_slab(loc_track, cache_node['full'], alloc, target_cache) 20479939c4aSKuan-Ying Lee else: 20579939c4aSKuan-Ying Lee raise gdb.GdbError("SLAB_STORE_USER is not set in %s" % target_cache['name'].string()) 20679939c4aSKuan-Ying Lee 20779939c4aSKuan-Ying Lee for loc in sorted(loc_track, key=lambda x:x['count'], reverse=True): 20879939c4aSKuan-Ying Lee if loc['addr']: 20979939c4aSKuan-Ying Lee addr = loc['addr'].cast(utils.get_ulong_type().pointer()) 21079939c4aSKuan-Ying Lee gdb.write("%d %s" % (loc['count'], str(addr).split(' ')[-1])) 21179939c4aSKuan-Ying Lee else: 21279939c4aSKuan-Ying Lee gdb.write("%d <not-available>" % loc['count']) 21379939c4aSKuan-Ying Lee 21479939c4aSKuan-Ying Lee if loc['waste']: 21579939c4aSKuan-Ying Lee gdb.write(" waste=%d/%d" % (loc['count'] * loc['waste'], loc['waste'])) 21679939c4aSKuan-Ying Lee 21779939c4aSKuan-Ying Lee if loc['sum_time'] != loc['min_time']: 21879939c4aSKuan-Ying Lee gdb.write(" age=%d/%d/%d" % (loc['min_time'], loc['sum_time']/loc['count'], loc['max_time'])) 21979939c4aSKuan-Ying Lee else: 22079939c4aSKuan-Ying Lee gdb.write(" age=%d" % loc['min_time']) 22179939c4aSKuan-Ying Lee 22279939c4aSKuan-Ying Lee if loc['min_pid'] != loc['max_pid']: 22379939c4aSKuan-Ying Lee gdb.write(" pid=%d-%d" % (loc['min_pid'], loc['max_pid'])) 22479939c4aSKuan-Ying Lee else: 22579939c4aSKuan-Ying Lee gdb.write(" pid=%d" % loc['min_pid']) 22679939c4aSKuan-Ying Lee 22779939c4aSKuan-Ying Lee if constants.LX_NR_CPUS > 1: 22879939c4aSKuan-Ying Lee nr_cpu = gdb.parse_and_eval('__num_online_cpus')['counter'] 22979939c4aSKuan-Ying Lee if nr_cpu > 1: 23079939c4aSKuan-Ying Lee gdb.write(" cpus=") 231*e52ec6a2SKuan-Ying Lee gdb.write(','.join(str(cpu) for cpu in loc['cpus'])) 23279939c4aSKuan-Ying Lee gdb.write("\n") 23379939c4aSKuan-Ying Lee if constants.LX_CONFIG_STACKDEPOT: 23479939c4aSKuan-Ying Lee if loc['handle']: 23579939c4aSKuan-Ying Lee stackdepot.stack_depot_print(loc['handle']) 23679939c4aSKuan-Ying Lee gdb.write("\n") 23779939c4aSKuan-Ying Lee 23879939c4aSKuan-Ying Leedef help(): 23979939c4aSKuan-Ying Lee t = """Usage: lx-slabtrace --cache_name [cache_name] [Options] 24079939c4aSKuan-Ying Lee Options: 24179939c4aSKuan-Ying Lee --alloc 24279939c4aSKuan-Ying Lee print information of allocation trace of the allocated objects 24379939c4aSKuan-Ying Lee --free 24479939c4aSKuan-Ying Lee print information of freeing trace of the allocated objects 24579939c4aSKuan-Ying Lee Example: 24679939c4aSKuan-Ying Lee lx-slabtrace --cache_name kmalloc-1k --alloc 24779939c4aSKuan-Ying Lee lx-slabtrace --cache_name kmalloc-1k --free\n""" 24879939c4aSKuan-Ying Lee gdb.write("Unrecognized command\n") 24979939c4aSKuan-Ying Lee raise gdb.GdbError(t) 25079939c4aSKuan-Ying Lee 25179939c4aSKuan-Ying Leeclass LxSlabTrace(gdb.Command): 25279939c4aSKuan-Ying Lee """Show specific cache slabtrace""" 25379939c4aSKuan-Ying Lee 25479939c4aSKuan-Ying Lee def __init__(self): 25579939c4aSKuan-Ying Lee super(LxSlabTrace, self).__init__("lx-slabtrace", gdb.COMMAND_DATA) 25679939c4aSKuan-Ying Lee 25779939c4aSKuan-Ying Lee def invoke(self, arg, from_tty): 25879939c4aSKuan-Ying Lee if not constants.LX_CONFIG_SLUB_DEBUG: 25979939c4aSKuan-Ying Lee raise gdb.GdbError("CONFIG_SLUB_DEBUG is not enabled") 26079939c4aSKuan-Ying Lee 26179939c4aSKuan-Ying Lee argv = gdb.string_to_argv(arg) 26279939c4aSKuan-Ying Lee alloc = track_alloc # default show alloc_traces 26379939c4aSKuan-Ying Lee 26479939c4aSKuan-Ying Lee if len(argv) == 3: 26579939c4aSKuan-Ying Lee if argv[2] == '--alloc': 26679939c4aSKuan-Ying Lee alloc = track_alloc 26779939c4aSKuan-Ying Lee elif argv[2] == '--free': 26879939c4aSKuan-Ying Lee alloc = track_free 26979939c4aSKuan-Ying Lee else: 27079939c4aSKuan-Ying Lee help() 27179939c4aSKuan-Ying Lee if len(argv) >= 2 and argv[0] == '--cache_name': 27279939c4aSKuan-Ying Lee slabtrace(alloc, argv[1]) 27379939c4aSKuan-Ying Lee else: 27479939c4aSKuan-Ying Lee help() 27579939c4aSKuan-Ying LeeLxSlabTrace() 27679939c4aSKuan-Ying Lee 27779939c4aSKuan-Ying Leedef slabinfo(): 27879939c4aSKuan-Ying Lee nr_node_ids = None 27979939c4aSKuan-Ying Lee 28079939c4aSKuan-Ying Lee if not constants.LX_CONFIG_SLUB_DEBUG: 28179939c4aSKuan-Ying Lee raise gdb.GdbError("CONFIG_SLUB_DEBUG is not enabled") 28279939c4aSKuan-Ying Lee 28379939c4aSKuan-Ying Lee def count_free(slab): 28479939c4aSKuan-Ying Lee total_free = 0 28579939c4aSKuan-Ying Lee for slab in lists.list_for_each_entry(slab, slab_ptr_type, 'slab_list'): 28679939c4aSKuan-Ying Lee total_free += int(slab['objects'] - slab['inuse']) 28779939c4aSKuan-Ying Lee return total_free 28879939c4aSKuan-Ying Lee 28979939c4aSKuan-Ying Lee gdb.write("{:^18} | {:^20} | {:^12} | {:^12} | {:^8} | {:^11} | {:^13}\n".format('Pointer', 'name', 'active_objs', 'num_objs', 'objsize', 'objperslab', 'pagesperslab')) 29079939c4aSKuan-Ying Lee gdb.write("{:-^18} | {:-^20} | {:-^12} | {:-^12} | {:-^8} | {:-^11} | {:-^13}\n".format('', '', '', '', '', '', '')) 29179939c4aSKuan-Ying Lee 29279939c4aSKuan-Ying Lee slab_caches = gdb.parse_and_eval("slab_caches") 29379939c4aSKuan-Ying Lee if mm.page_ops().ops.MAX_NUMNODES > 1: 29479939c4aSKuan-Ying Lee nr_node_ids = int(gdb.parse_and_eval("nr_node_ids")) 29579939c4aSKuan-Ying Lee else: 29679939c4aSKuan-Ying Lee nr_node_ids = 1 29779939c4aSKuan-Ying Lee 29879939c4aSKuan-Ying Lee for cache in lists.list_for_each_entry(slab_caches, kmem_cache_ptr_type, 'list'): 29979939c4aSKuan-Ying Lee nr_objs = 0 30079939c4aSKuan-Ying Lee nr_free = 0 30179939c4aSKuan-Ying Lee nr_slabs = 0 30279939c4aSKuan-Ying Lee for i in range(0, nr_node_ids): 30379939c4aSKuan-Ying Lee cache_node = cache['node'][i] 30479939c4aSKuan-Ying Lee try: 30579939c4aSKuan-Ying Lee nr_slabs += cache_node['nr_slabs']['counter'] 30679939c4aSKuan-Ying Lee nr_objs = int(cache_node['total_objects']['counter']) 30779939c4aSKuan-Ying Lee nr_free = count_free(cache_node['partial']) 30879939c4aSKuan-Ying Lee except: 30979939c4aSKuan-Ying Lee raise gdb.GdbError(traceback.format_exc()) 31079939c4aSKuan-Ying Lee active_objs = nr_objs - nr_free 31179939c4aSKuan-Ying Lee num_objs = nr_objs 31279939c4aSKuan-Ying Lee active_slabs = nr_slabs 31379939c4aSKuan-Ying Lee objects_per_slab = oo_objects(cache['oo']) 31479939c4aSKuan-Ying Lee cache_order = oo_order(cache['oo']) 31579939c4aSKuan-Ying Lee gdb.write("{:18s} | {:20.19s} | {:12} | {:12} | {:8} | {:11} | {:13}\n".format(hex(cache), cache['name'].string(), str(active_objs), str(num_objs), str(cache['size']), str(objects_per_slab), str(1 << cache_order))) 31679939c4aSKuan-Ying Lee 31779939c4aSKuan-Ying Leeclass LxSlabInfo(gdb.Command): 31879939c4aSKuan-Ying Lee """Show slabinfo""" 31979939c4aSKuan-Ying Lee 32079939c4aSKuan-Ying Lee def __init__(self): 32179939c4aSKuan-Ying Lee super(LxSlabInfo, self).__init__("lx-slabinfo", gdb.COMMAND_DATA) 32279939c4aSKuan-Ying Lee 32379939c4aSKuan-Ying Lee def invoke(self, arg, from_tty): 32479939c4aSKuan-Ying Lee slabinfo() 32579939c4aSKuan-Ying LeeLxSlabInfo() 326