2 # gdb helper commands and functions for Linux kernel debugging
4 # Kernel proc information reader
6 # Copyright (c) 2016 Linaro Ltd
9 # Kieran Bingham <kieran.bingham@linaro.org>
11 # This work is licensed under the terms of the GNU GPL version 2.
15 from linux import constants
16 from linux import utils
17 from linux import tasks
18 from linux import lists
21 class LxCmdLine(gdb.Command):
22 """ Report the Linux Commandline used in the current kernel.
23 Equivalent to cat /proc/cmdline on a running target"""
26 super(LxCmdLine, self).__init__("lx-cmdline", gdb.COMMAND_DATA)
28 def invoke(self, arg, from_tty):
29 gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n")
34 class LxVersion(gdb.Command):
35 """ Report the Linux Version of the current kernel.
36 Equivalent to cat /proc/version on a running target"""
39 super(LxVersion, self).__init__("lx-version", gdb.COMMAND_DATA)
41 def invoke(self, arg, from_tty):
42 # linux_banner should contain a newline
43 gdb.write(gdb.parse_and_eval("(char *)linux_banner").string())
48 # Resource Structure Printers
52 def get_resources(resource, depth):
56 child = resource['child']
58 for res, deep in get_resources(child, depth + 1):
61 resource = resource['sibling']
64 def show_lx_resources(resource_str):
65 resource = gdb.parse_and_eval(resource_str)
66 width = 4 if resource['end'] < 0x10000 else 8
67 # Iterate straight to the first child
68 for res, depth in get_resources(resource['child'], 0):
69 start = int(res['start'])
71 gdb.write(" " * depth * 2 +
72 "{0:0{1}x}-".format(start, width) +
73 "{0:0{1}x} : ".format(end, width) +
74 res['name'].string() + "\n")
77 class LxIOMem(gdb.Command):
78 """Identify the IO memory resource locations defined by the kernel
80 Equivalent to cat /proc/iomem on a running target"""
83 super(LxIOMem, self).__init__("lx-iomem", gdb.COMMAND_DATA)
85 def invoke(self, arg, from_tty):
86 return show_lx_resources("iomem_resource")
91 class LxIOPorts(gdb.Command):
92 """Identify the IO port resource locations defined by the kernel
94 Equivalent to cat /proc/ioports on a running target"""
97 super(LxIOPorts, self).__init__("lx-ioports", gdb.COMMAND_DATA)
99 def invoke(self, arg, from_tty):
100 return show_lx_resources("ioport_resource")
105 # Mount namespace viewer
108 def info_opts(lst, opt):
110 for key, string in lst.items():
116 FS_INFO = {constants.LX_MS_SYNCHRONOUS: ",sync",
117 constants.LX_MS_MANDLOCK: ",mand",
118 constants.LX_MS_DIRSYNC: ",dirsync",
119 constants.LX_MS_NOATIME: ",noatime",
120 constants.LX_MS_NODIRATIME: ",nodiratime"}
122 MNT_INFO = {constants.LX_MNT_NOSUID: ",nosuid",
123 constants.LX_MNT_NODEV: ",nodev",
124 constants.LX_MNT_NOEXEC: ",noexec",
125 constants.LX_MNT_NOATIME: ",noatime",
126 constants.LX_MNT_NODIRATIME: ",nodiratime",
127 constants.LX_MNT_RELATIME: ",relatime"}
129 mount_type = utils.CachedType("struct mount")
130 mount_ptr_type = mount_type.get_type().pointer()
133 class LxMounts(gdb.Command):
134 """Report the VFS mounts of the current process namespace.
136 Equivalent to cat /proc/mounts on a running target
137 An integer value can be supplied to display the mount
138 values of that process namespace"""
141 super(LxMounts, self).__init__("lx-mounts", gdb.COMMAND_DATA)
143 # Equivalent to proc_namespace.c:show_vfsmnt
144 # However, that has the ability to call into s_op functions
145 # whereas we cannot and must make do with the information we can obtain.
146 def invoke(self, arg, from_tty):
147 argv = gdb.string_to_argv(arg)
152 raise gdb.GdbError("Provide a PID as integer value")
156 task = tasks.get_task_by_pid(pid)
158 raise gdb.GdbError("Couldn't find a process with PID {}"
161 namespace = task['nsproxy']['mnt_ns']
163 raise gdb.GdbError("No namespace for current process")
165 for vfs in lists.list_for_each_entry(namespace['list'],
166 mount_ptr_type, "mnt_list"):
167 devname = vfs['mnt_devname'].string()
168 devname = devname if devname else "none"
173 mntpoint = parent['mnt_mountpoint']
174 pathname = utils.dentry_name(mntpoint) + pathname
175 if (parent == parent['mnt_parent']):
177 parent = parent['mnt_parent']
182 superblock = vfs['mnt']['mnt_sb']
183 fstype = superblock['s_type']['name'].string()
184 s_flags = int(superblock['s_flags'])
185 m_flags = int(vfs['mnt']['mnt_flags'])
186 rd = "ro" if (s_flags & constants.LX_MS_RDONLY) else "rw"
189 "{} {} {} {}{}{} 0 0\n"
194 info_opts(FS_INFO, s_flags),
195 info_opts(MNT_INFO, m_flags)))