diff options
Diffstat (limited to 'scripts/gdb/linux/proc.py')
-rw-r--r-- | scripts/gdb/linux/proc.py | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py index 6e6709c1830c..38b1f09d1cd9 100644 --- a/scripts/gdb/linux/proc.py +++ b/scripts/gdb/linux/proc.py | |||
@@ -12,6 +12,10 @@ | |||
12 | # | 12 | # |
13 | 13 | ||
14 | import gdb | 14 | import gdb |
15 | from linux import constants | ||
16 | from linux import utils | ||
17 | from linux import tasks | ||
18 | from linux import lists | ||
15 | 19 | ||
16 | 20 | ||
17 | class LxCmdLine(gdb.Command): | 21 | class LxCmdLine(gdb.Command): |
@@ -39,3 +43,155 @@ class LxVersion(gdb.Command): | |||
39 | gdb.write(gdb.parse_and_eval("linux_banner").string()) | 43 | gdb.write(gdb.parse_and_eval("linux_banner").string()) |
40 | 44 | ||
41 | LxVersion() | 45 | LxVersion() |
46 | |||
47 | |||
48 | # Resource Structure Printers | ||
49 | # /proc/iomem | ||
50 | # /proc/ioports | ||
51 | |||
52 | def 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 | |||
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']) | ||
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 | |||
77 | class LxIOMem(gdb.Command): | ||
78 | """Identify the IO memory resource locations defined by the kernel | ||
79 | |||
80 | Equivalent 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 | |||
88 | LxIOMem() | ||
89 | |||
90 | |||
91 | class LxIOPorts(gdb.Command): | ||
92 | """Identify the IO port resource locations defined by the kernel | ||
93 | |||
94 | Equivalent 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 | |||
102 | LxIOPorts() | ||
103 | |||
104 | |||
105 | # Mount namespace viewer | ||
106 | # /proc/mounts | ||
107 | |||
108 | def 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 | |||
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"} | ||
121 | |||
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"} | ||
128 | |||
129 | mount_type = utils.CachedType("struct mount") | ||
130 | mount_ptr_type = mount_type.get_type().pointer() | ||
131 | |||
132 | |||
133 | class LxMounts(gdb.Command): | ||
134 | """Report the VFS mounts of the current process namespace. | ||
135 | |||
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""" | ||
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 | |||
197 | LxMounts() | ||