Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
Note: File does not exist in v3.15.
  1#
  2# gdb helper commands and functions for Linux kernel debugging
  3#
  4#  Kernel proc information reader
  5#
  6# Copyright (c) 2016 Linaro Ltd
  7#
  8# Authors:
  9#  Kieran Bingham <kieran.bingham@linaro.org>
 10#
 11# This work is licensed under the terms of the GNU GPL version 2.
 12#
 13
 14import gdb
 15from linux import constants
 16from linux import utils
 17from linux import tasks
 18from linux import lists
 19
 20
 21class LxCmdLine(gdb.Command):
 22    """ Report the Linux Commandline used in the current kernel.
 23        Equivalent to cat /proc/cmdline on a running target"""
 24
 25    def __init__(self):
 26        super(LxCmdLine, self).__init__("lx-cmdline", gdb.COMMAND_DATA)
 27
 28    def invoke(self, arg, from_tty):
 29        gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n")
 30
 31LxCmdLine()
 32
 33
 34class LxVersion(gdb.Command):
 35    """ Report the Linux Version of the current kernel.
 36        Equivalent to cat /proc/version on a running target"""
 37
 38    def __init__(self):
 39        super(LxVersion, self).__init__("lx-version", gdb.COMMAND_DATA)
 40
 41    def invoke(self, arg, from_tty):
 42        # linux_banner should contain a newline
 43        gdb.write(gdb.parse_and_eval("linux_banner").string())
 44
 45LxVersion()
 46
 47
 48# Resource Structure Printers
 49#  /proc/iomem
 50#  /proc/ioports
 51
 52def get_resources(resource, depth):
 53    while resource:
 54        yield resource, depth
 55
 56        child = resource['child']
 57        if child:
 58            for res, deep in get_resources(child, depth + 1):
 59                yield res, deep
 60
 61        resource = resource['sibling']
 62
 63
 64def 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'])
 70            end = int(res['end'])
 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")
 75
 76
 77class LxIOMem(gdb.Command):
 78    """Identify the IO memory resource locations defined by the kernel
 79
 80Equivalent to cat /proc/iomem on a running target"""
 81
 82    def __init__(self):
 83        super(LxIOMem, self).__init__("lx-iomem", gdb.COMMAND_DATA)
 84
 85    def invoke(self, arg, from_tty):
 86        return show_lx_resources("iomem_resource")
 87
 88LxIOMem()
 89
 90
 91class LxIOPorts(gdb.Command):
 92    """Identify the IO port resource locations defined by the kernel
 93
 94Equivalent to cat /proc/ioports on a running target"""
 95
 96    def __init__(self):
 97        super(LxIOPorts, self).__init__("lx-ioports", gdb.COMMAND_DATA)
 98
 99    def invoke(self, arg, from_tty):
100        return show_lx_resources("ioport_resource")
101
102LxIOPorts()
103
104
105# Mount namespace viewer
106#  /proc/mounts
107
108def info_opts(lst, opt):
109    opts = ""
110    for key, string in lst.items():
111        if opt & key:
112            opts += string
113    return opts
114
115
116FS_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"}
121
122MNT_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"}
128
129mount_type = utils.CachedType("struct mount")
130mount_ptr_type = mount_type.get_type().pointer()
131
132
133class LxMounts(gdb.Command):
134    """Report the VFS mounts of the current process namespace.
135
136Equivalent to cat /proc/mounts on a running target
137An integer value can be supplied to display the mount
138values of that process namespace"""
139
140    def __init__(self):
141        super(LxMounts, self).__init__("lx-mounts", gdb.COMMAND_DATA)
142
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)
148        if len(argv) >= 1:
149            try:
150                pid = int(argv[0])
151            except:
152                raise gdb.GdbError("Provide a PID as integer value")
153        else:
154            pid = 1
155
156        task = tasks.get_task_by_pid(pid)
157        if not task:
158            raise gdb.GdbError("Couldn't find a process with PID {}"
159                               .format(pid))
160
161        namespace = task['nsproxy']['mnt_ns']
162        if not namespace:
163            raise gdb.GdbError("No namespace for current process")
164
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"
169
170            pathname = ""
171            parent = vfs
172            while True:
173                mntpoint = parent['mnt_mountpoint']
174                pathname = utils.dentry_name(mntpoint) + pathname
175                if (parent == parent['mnt_parent']):
176                    break
177                parent = parent['mnt_parent']
178
179            if (pathname == ""):
180                pathname = "/"
181
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"
187
188            gdb.write(
189                "{} {} {} {}{}{} 0 0\n"
190                .format(devname,
191                        pathname,
192                        fstype,
193                        rd,
194                        info_opts(FS_INFO, s_flags),
195                        info_opts(MNT_INFO, m_flags)))
196
197LxMounts()