class LxLsmod(gdb.Command): """List currently loaded modules.""" _module_use_type = utils.CachedType("struct module_use") def __init__(self): super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): gdb.write( "Address{0} Module Size Used by\n".format( " " if utils.get_long_type().sizeof == 8 else "")) for module in module_list(): gdb.write("{address} {name:<19} {size:>8} {ref}".format( address=str(module['module_core']).split()[0], name=module['name'].string(), size=str(module['core_size']), ref=str(module['refcnt']['counter']))) source_list = module['source_list'] t = self._module_use_type.get_type().pointer() entry = source_list['next'] first = True while entry != source_list.address: use = utils.container_of(entry, t, "source_list") gdb.write("{separator}{name}".format( separator=" " if first else ",", name=use['source']['name'].string())) first = False entry = entry['next'] gdb.write("\n")
class LxLsmod(gdb.Command): """List currently loaded modules.""" _module_use_type = utils.CachedType("struct module_use") def __init__(self): super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): gdb.write( "Address{0} Module Size Used by\n".format( " " if utils.get_long_type().sizeof == 8 else "")) for module in module_list(): layout = module['core_layout'] gdb.write("{address} {name:<19} {size:>8} {ref}".format( address=str(layout['base']).split()[0], name=module['name'].string(), size=str(layout['size']), ref=str(module['refcnt']['counter'] - 1))) t = self._module_use_type.get_type().pointer() first = True sources = module['source_list'] for use in lists.list_for_each_entry(sources, t, "source_list"): gdb.write("{separator}{name}".format( separator=" " if first else ",", name=use['source']['name'].string())) first = False gdb.write("\n")
# # task & thread tools # # Copyright (c) Siemens AG, 2011-2013 # # Authors: # Jan Kiszka <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb from linux import utils task_type = utils.CachedType("struct task_struct") def task_lists(): task_ptr_type = task_type.get_type().pointer() init_task = gdb.parse_and_eval("init_task").address t = g = init_task while True: while True: yield t t = utils.container_of(t['thread_group']['next'], task_ptr_type, "thread_group") if t == g: break
# kernel log buffer dump # # Copyright (c) Siemens AG, 2011, 2012 # # Authors: # Jan Kiszka <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb import sys from linux import utils printk_info_type = utils.CachedType("struct printk_info") prb_data_blk_lpos_type = utils.CachedType("struct prb_data_blk_lpos") prb_desc_type = utils.CachedType("struct prb_desc") prb_desc_ring_type = utils.CachedType("struct prb_desc_ring") prb_data_ring_type = utils.CachedType("struct prb_data_ring") printk_ringbuffer_type = utils.CachedType("struct printk_ringbuffer") atomic_long_type = utils.CachedType("atomic_long_t") class LxDmesg(gdb.Command): """Print Linux kernel log buffer.""" def __init__(self): super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): inf = gdb.inferiors()[0]
# SPDX-License-Identifier: GPL-2.0 # # Copyright 2019 Google LLC. import gdb from linux import utils rb_root_type = utils.CachedType("struct rb_root") rb_node_type = utils.CachedType("struct rb_node") def rb_first(root): if root.type == rb_root_type.get_type(): node = root.address.cast(rb_root_type.get_type().pointer()) elif root.type != rb_root_type.get_type().pointer(): raise gdb.GdbError("Must be struct rb_root not {}".format(root.type)) node = root['rb_node'] if node is 0: return None while node['rb_left']: node = node['rb_left'] return node def rb_last(root): if root.type == rb_root_type.get_type(): node = root.address.cast(rb_root_type.get_type().pointer())
constants.LX_MS_MANDLOCK: ",mand", constants.LX_MS_DIRSYNC: ",dirsync", constants.LX_MS_NOATIME: ",noatime", constants.LX_MS_NODIRATIME: ",nodiratime" } MNT_INFO = { constants.LX_MNT_NOSUID: ",nosuid", constants.LX_MNT_NODEV: ",nodev", constants.LX_MNT_NOEXEC: ",noexec", constants.LX_MNT_NOATIME: ",noatime", constants.LX_MNT_NODIRATIME: ",nodiratime", constants.LX_MNT_RELATIME: ",relatime" } mount_type = utils.CachedType("struct mount") mount_ptr_type = mount_type.get_type().pointer() class LxMounts(gdb.Command): """Report the VFS mounts of the current process namespace. Equivalent to cat /proc/mounts on a running target An integer value can be supplied to display the mount values of that process namespace""" def __init__(self): super(LxMounts, self).__init__("lx-mounts", gdb.COMMAND_DATA) # Equivalent to proc_namespace.c:show_vfsmnt # However, that has the ability to call into s_op functions # whereas we cannot and must make do with the information we can obtain.
# module tools # # Copyright (c) Siemens AG, 2013 # # Authors: # Jan Kiszka <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb from linux import cpus, utils, lists module_type = utils.CachedType("struct module") def module_list(): global module_type modules = utils.gdb_eval_or_none("modules") if modules is None: return module_ptr_type = module_type.get_type().pointer() for module in lists.list_for_each_entry(modules, module_ptr_type, "list"): yield module def find_module_by_name(name):
# SPDX-License-Identifier: GPL-2.0 # # Copyright (c) NXP 2019 import gdb import sys from linux import utils, lists, constants clk_core_type = utils.CachedType("struct clk_core") def clk_core_for_each_child(hlist_head): return lists.hlist_for_each_entry(hlist_head, clk_core_type.get_type().pointer(), "child_node") class LxClkSummary(gdb.Command): """Print clk tree summary Output is a subset of /sys/kernel/debug/clk/clk_summary No calls are made during printing, instead a (c) if printed after values which are cached and potentially out of date""" def __init__(self): super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA) def show_subtree(self, clk, level): gdb.write("%*s%-*s %7d %8d %8d %11lu%s\n" % (level * 3 + 1, "", 30 - level * 3, clk['name'].string(),
# kernel log buffer dump # # Copyright (c) Siemens AG, 2011, 2012 # # Authors: # Jan Kiszka <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb import sys from linux import utils printk_log_type = utils.CachedType("struct printk_log") class LxDmesg(gdb.Command): """Print Linux kernel log buffer.""" def __init__(self): super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): log_buf_addr = int( str(gdb.parse_and_eval("(void *)'printk.c'::log_buf")).split()[0], 16) log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx")) log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx")) log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len"))
# # per-cpu tools # # Copyright (c) Siemens AG, 2011-2013 # # Authors: # Jan Kiszka <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb from linux import tasks, utils task_type = utils.CachedType("struct task_struct") MAX_CPUS = 4096 def get_current_cpu(): if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU: return gdb.selected_thread().num - 1 elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB: tid = gdb.selected_thread().ptid[2] if tid > (0x100000000 - MAX_CPUS - 2): return 0x100000000 - tid - 2 else: return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu'] else: raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
# # list tools # # Copyright (c) Thiebaud Weksteen, 2015 # # Authors: # Thiebaud Weksteen <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb from linux import utils list_head = utils.CachedType("struct list_head") def list_check(head): nb = 0 if (head.type == list_head.get_type().pointer()): head = head.dereference() elif (head.type != list_head.get_type()): raise gdb.GdbError('argument must be of type (struct list_head [*])') c = head try: gdb.write("Starting with: {}\n".format(c)) except gdb.MemoryError: gdb.write('head is not accessible\n') return while True:
import gdb from linux import utils VM_EXEC = 0x4 task_type = utils.CachedType("struct task_struct") def task_lists(): task_ptr_type = task_type.get_type().pointer() init_task = gdb.parse_and_eval("init_task").address t = g = init_task while True: while True: yield t t = utils.container_of(t['thread_group']['next'], task_ptr_type, "thread_group") if t == g: break t = g = utils.container_of(g['tasks']['next'], task_ptr_type, "tasks") if t == init_task: return def task_name(name): for task in task_lists(): if name in task['comm'].string(): return task
# Radix Tree Parser # # Copyright (c) 2016 Linaro Ltd # # Authors: # Kieran Bingham <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb from linux import utils from linux import constants radix_tree_root_type = utils.CachedType("struct radix_tree_root") radix_tree_node_type = utils.CachedType("struct radix_tree_node") def is_indirect_ptr(node): long_type = utils.get_long_type() return (node.cast(long_type) & constants.LX_RADIX_TREE_INDIRECT_PTR) def indirect_to_ptr(node): long_type = utils.get_long_type() node_type = node.type indirect_ptr = node.cast(long_type) & ~constants.LX_RADIX_TREE_INDIRECT_PTR return indirect_ptr.cast(node_type)
# # list tools # # Copyright (c) Thiebaud Weksteen, 2015 # # Authors: # Thiebaud Weksteen <*****@*****.**> # # This work is licensed under the terms of the GNU GPL version 2. # import gdb from linux import utils list_head = utils.CachedType("struct list_head") hlist_head = utils.CachedType("struct hlist_head") hlist_node = utils.CachedType("struct hlist_node") def list_for_each(head): if head.type == list_head.get_type().pointer(): head = head.dereference() elif head.type != list_head.get_type(): raise TypeError("Must be struct list_head not {}".format(head.type)) node = head['next'].dereference() while node.address != head.address: yield node.address node = node['next'].dereference()
# SPDX-License-Identifier: GPL-2.0 # # Copyright 2019 Google LLC. import binascii import gdb from linux import constants from linux import cpus from linux import rbtree from linux import utils timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type() hrtimer_type = utils.CachedType("struct hrtimer").get_type() def ktime_get(): """Returns the current time, but not very accurately We can't read the hardware timer itself to add any nanoseconds that need to be added since we last stored the time in the timekeeper. But this is probably good enough for debug purposes.""" tk_core = gdb.parse_and_eval("&tk_core") return tk_core['timekeeper']['tkr_mono']['base'] def print_timer(rb_node, idx): timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(), "node") timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")