diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-23 22:42:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-23 22:42:28 -0400 |
commit | 84787c572d402644dca4874aba73324d9f8e3948 (patch) | |
tree | 31783e50b09fee00ee7ff87c0c9708a3c7106482 /scripts/gdb/linux/proc.py | |
parent | d62a0234c87f1457a3d2ba519ef90cf164a5eb23 (diff) | |
parent | c5d2cac0f1caaf7dd21350146fb29c55b3e74249 (diff) |
Merge branch 'akpm' (patches from Andrew)
Merge yet more updates from Andrew Morton:
- Oleg's "wait/ptrace: assume __WALL if the child is traced". It's a
kernel-based workaround for existing userspace issues.
- A few hotfixes
- befs cleanups
- nilfs2 updates
- sys_wait() changes
- kexec updates
- kdump
- scripts/gdb updates
- the last of the MM queue
- a few other misc things
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (84 commits)
kgdb: depends on VT
drm/amdgpu: make amdgpu_mn_get wait for mmap_sem killable
drm/radeon: make radeon_mn_get wait for mmap_sem killable
drm/i915: make i915_gem_mmap_ioctl wait for mmap_sem killable
uprobes: wait for mmap_sem for write killable
prctl: make PR_SET_THP_DISABLE wait for mmap_sem killable
exec: make exec path waiting for mmap_sem killable
aio: make aio_setup_ring killable
coredump: make coredump_wait wait for mmap_sem for write killable
vdso: make arch_setup_additional_pages wait for mmap_sem for write killable
ipc, shm: make shmem attach/detach wait for mmap_sem killable
mm, fork: make dup_mmap wait for mmap_sem for write killable
mm, proc: make clear_refs killable
mm: make vm_brk killable
mm, elf: handle vm_brk error
mm, aout: handle vm_brk failures
mm: make vm_munmap killable
mm: make vm_mmap killable
mm: make mmap_sem for write waits killable for mm syscalls
MAINTAINERS: add co-maintainer for scripts/gdb
...
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() | ||