aboutsummaryrefslogtreecommitdiffstats
path: root/scripts/gdb
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-20 00:07:56 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2019-07-20 00:07:56 -0400
commitc39f2d9db0fd81ea20bb5cce9b3f082ca63753e2 (patch)
tree8e80ed5601b4fb8880a2ca8e08802bc8b1f850bd /scripts/gdb
parent597473720f4dc69749542bfcfed4a927a43d935e (diff)
parent771a081e44a9baa1991ef011cc453ef425591740 (diff)
Merge branch 'next' into for-linus
Prepare second round of input updates for 5.3 merge window.
Diffstat (limited to 'scripts/gdb')
-rw-r--r--scripts/gdb/Makefile1
-rw-r--r--scripts/gdb/linux/Makefile2
-rw-r--r--scripts/gdb/linux/clk.py76
-rw-r--r--scripts/gdb/linux/config.py44
-rw-r--r--scripts/gdb/linux/constants.py.in18
-rw-r--r--scripts/gdb/linux/cpus.py1
-rw-r--r--scripts/gdb/linux/lists.py26
-rw-r--r--scripts/gdb/linux/proc.py10
-rw-r--r--scripts/gdb/linux/rbtree.py177
-rw-r--r--scripts/gdb/linux/symbols.py6
-rw-r--r--scripts/gdb/linux/tasks.py2
-rw-r--r--scripts/gdb/linux/timerlist.py219
-rw-r--r--scripts/gdb/linux/utils.py7
-rw-r--r--scripts/gdb/vmlinux-gdb.py4
14 files changed, 582 insertions, 11 deletions
diff --git a/scripts/gdb/Makefile b/scripts/gdb/Makefile
index 62f5f65becfd..3fca1937d956 100644
--- a/scripts/gdb/Makefile
+++ b/scripts/gdb/Makefile
@@ -1 +1,2 @@
1# SPDX-License-Identifier: GPL-2.0-only
1subdir-y := linux 2subdir-y := linux
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
index 3df395a9c2ce..9fd3d8ed731a 100644
--- a/scripts/gdb/linux/Makefile
+++ b/scripts/gdb/linux/Makefile
@@ -1,6 +1,6 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2 2
3ifneq ($(KBUILD_SRC),) 3ifneq ($(srctree),.)
4 4
5symlinks := $(patsubst $(srctree)/$(src)/%,%,$(wildcard $(srctree)/$(src)/*.py)) 5symlinks := $(patsubst $(srctree)/$(src)/%,%,$(wildcard $(srctree)/$(src)/*.py))
6 6
diff --git a/scripts/gdb/linux/clk.py b/scripts/gdb/linux/clk.py
new file mode 100644
index 000000000000..061aecfa294e
--- /dev/null
+++ b/scripts/gdb/linux/clk.py
@@ -0,0 +1,76 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Copyright (c) NXP 2019
4
5import gdb
6import sys
7
8from linux import utils, lists, constants
9
10clk_core_type = utils.CachedType("struct clk_core")
11
12
13def clk_core_for_each_child(hlist_head):
14 return lists.hlist_for_each_entry(hlist_head,
15 clk_core_type.get_type().pointer(), "child_node")
16
17
18class LxClkSummary(gdb.Command):
19 """Print clk tree summary
20
21Output is a subset of /sys/kernel/debug/clk/clk_summary
22
23No calls are made during printing, instead a (c) if printed after values which
24are cached and potentially out of date"""
25
26 def __init__(self):
27 super(LxClkSummary, self).__init__("lx-clk-summary", gdb.COMMAND_DATA)
28
29 def show_subtree(self, clk, level):
30 gdb.write("%*s%-*s %7d %8d %8d %11lu%s\n" % (
31 level * 3 + 1, "",
32 30 - level * 3,
33 clk['name'].string(),
34 clk['enable_count'],
35 clk['prepare_count'],
36 clk['protect_count'],
37 clk['rate'],
38 '(c)' if clk['flags'] & constants.LX_CLK_GET_RATE_NOCACHE else ' '))
39
40 for child in clk_core_for_each_child(clk['children']):
41 self.show_subtree(child, level + 1)
42
43 def invoke(self, arg, from_tty):
44 gdb.write(" enable prepare protect \n")
45 gdb.write(" clock count count count rate \n")
46 gdb.write("------------------------------------------------------------------------\n")
47 for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_root_list")):
48 self.show_subtree(clk, 0)
49 for clk in clk_core_for_each_child(gdb.parse_and_eval("clk_orphan_list")):
50 self.show_subtree(clk, 0)
51
52
53LxClkSummary()
54
55
56class LxClkCoreLookup(gdb.Function):
57 """Find struct clk_core by name"""
58
59 def __init__(self):
60 super(LxClkCoreLookup, self).__init__("lx_clk_core_lookup")
61
62 def lookup_hlist(self, hlist_head, name):
63 for child in clk_core_for_each_child(hlist_head):
64 if child['name'].string() == name:
65 return child
66 result = self.lookup_hlist(child['children'], name)
67 if result:
68 return result
69
70 def invoke(self, name):
71 name = name.string()
72 return (self.lookup_hlist(gdb.parse_and_eval("clk_root_list"), name) or
73 self.lookup_hlist(gdb.parse_and_eval("clk_orphan_list"), name))
74
75
76LxClkCoreLookup()
diff --git a/scripts/gdb/linux/config.py b/scripts/gdb/linux/config.py
new file mode 100644
index 000000000000..90e1565b1967
--- /dev/null
+++ b/scripts/gdb/linux/config.py
@@ -0,0 +1,44 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Copyright 2019 Google LLC.
4
5import gdb
6import zlib
7
8from linux import utils
9
10
11class LxConfigDump(gdb.Command):
12 """Output kernel config to the filename specified as the command
13 argument. Equivalent to 'zcat /proc/config.gz > config.txt' on
14 a running target"""
15
16 def __init__(self):
17 super(LxConfigDump, self).__init__("lx-configdump", gdb.COMMAND_DATA,
18 gdb.COMPLETE_FILENAME)
19
20 def invoke(self, arg, from_tty):
21 if len(arg) == 0:
22 filename = "config.txt"
23 else:
24 filename = arg
25
26 try:
27 py_config_ptr = gdb.parse_and_eval("kernel_config_data + 8")
28 py_config_size = gdb.parse_and_eval(
29 "sizeof(kernel_config_data) - 1 - 8 * 2")
30 except gdb.error as e:
31 raise gdb.GdbError("Can't find config, enable CONFIG_IKCONFIG?")
32
33 inf = gdb.inferiors()[0]
34 zconfig_buf = utils.read_memoryview(inf, py_config_ptr,
35 py_config_size).tobytes()
36
37 config_buf = zlib.decompress(zconfig_buf, 16)
38 with open(filename, 'wb') as f:
39 f.write(config_buf)
40
41 gdb.write("Dumped config to " + filename + "\n")
42
43
44LxConfigDump()
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index d3319a80788a..2efbec6b6b8d 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -12,9 +12,12 @@
12 * 12 *
13 */ 13 */
14 14
15#include <linux/clk-provider.h>
15#include <linux/fs.h> 16#include <linux/fs.h>
17#include <linux/hrtimer.h>
16#include <linux/mount.h> 18#include <linux/mount.h>
17#include <linux/of_fdt.h> 19#include <linux/of_fdt.h>
20#include <linux/threads.h>
18 21
19/* We need to stringify expanded macros so that they can be parsed */ 22/* We need to stringify expanded macros so that they can be parsed */
20 23
@@ -36,6 +39,10 @@
36 39
37import gdb 40import gdb
38 41
42/* linux/clk-provider.h */
43if IS_BUILTIN(CONFIG_COMMON_CLK):
44 LX_GDBPARSED(CLK_GET_RATE_NOCACHE)
45
39/* linux/fs.h */ 46/* linux/fs.h */
40LX_VALUE(SB_RDONLY) 47LX_VALUE(SB_RDONLY)
41LX_VALUE(SB_SYNCHRONOUS) 48LX_VALUE(SB_SYNCHRONOUS)
@@ -44,6 +51,9 @@ LX_VALUE(SB_DIRSYNC)
44LX_VALUE(SB_NOATIME) 51LX_VALUE(SB_NOATIME)
45LX_VALUE(SB_NODIRATIME) 52LX_VALUE(SB_NODIRATIME)
46 53
54/* linux/htimer.h */
55LX_GDBPARSED(hrtimer_resolution)
56
47/* linux/mount.h */ 57/* linux/mount.h */
48LX_VALUE(MNT_NOSUID) 58LX_VALUE(MNT_NOSUID)
49LX_VALUE(MNT_NODEV) 59LX_VALUE(MNT_NODEV)
@@ -52,8 +62,16 @@ LX_VALUE(MNT_NOATIME)
52LX_VALUE(MNT_NODIRATIME) 62LX_VALUE(MNT_NODIRATIME)
53LX_VALUE(MNT_RELATIME) 63LX_VALUE(MNT_RELATIME)
54 64
65/* linux/threads.h */
66LX_VALUE(NR_CPUS)
67
55/* linux/of_fdt.h> */ 68/* linux/of_fdt.h> */
56LX_VALUE(OF_DT_HEADER) 69LX_VALUE(OF_DT_HEADER)
57 70
58/* Kernel Configs */ 71/* Kernel Configs */
72LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS)
73LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
74LX_CONFIG(CONFIG_HIGH_RES_TIMERS)
75LX_CONFIG(CONFIG_NR_CPUS)
59LX_CONFIG(CONFIG_OF) 76LX_CONFIG(CONFIG_OF)
77LX_CONFIG(CONFIG_TICK_ONESHOT)
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index ca11e8df31b6..008e62f3190d 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -135,6 +135,7 @@ and can help identify the state of hotplugged CPUs"""
135 gdb.write("Online CPUs : {}\n".format(list(each_online_cpu()))) 135 gdb.write("Online CPUs : {}\n".format(list(each_online_cpu())))
136 gdb.write("Active CPUs : {}\n".format(list(each_active_cpu()))) 136 gdb.write("Active CPUs : {}\n".format(list(each_active_cpu())))
137 137
138
138LxCpus() 139LxCpus()
139 140
140 141
diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py
index 2f335fbd86fd..c487ddf09d38 100644
--- a/scripts/gdb/linux/lists.py
+++ b/scripts/gdb/linux/lists.py
@@ -16,13 +16,15 @@ import gdb
16from linux import utils 16from linux import utils
17 17
18list_head = utils.CachedType("struct list_head") 18list_head = utils.CachedType("struct list_head")
19hlist_head = utils.CachedType("struct hlist_head")
20hlist_node = utils.CachedType("struct hlist_node")
19 21
20 22
21def list_for_each(head): 23def list_for_each(head):
22 if head.type == list_head.get_type().pointer(): 24 if head.type == list_head.get_type().pointer():
23 head = head.dereference() 25 head = head.dereference()
24 elif head.type != list_head.get_type(): 26 elif head.type != list_head.get_type():
25 raise gdb.GdbError("Must be struct list_head not {}" 27 raise TypeError("Must be struct list_head not {}"
26 .format(head.type)) 28 .format(head.type))
27 29
28 node = head['next'].dereference() 30 node = head['next'].dereference()
@@ -33,9 +35,24 @@ def list_for_each(head):
33 35
34def list_for_each_entry(head, gdbtype, member): 36def list_for_each_entry(head, gdbtype, member):
35 for node in list_for_each(head): 37 for node in list_for_each(head):
36 if node.type != list_head.get_type().pointer(): 38 yield utils.container_of(node, gdbtype, member)
37 raise TypeError("Type {} found. Expected struct list_head *." 39
38 .format(node.type)) 40
41def hlist_for_each(head):
42 if head.type == hlist_head.get_type().pointer():
43 head = head.dereference()
44 elif head.type != hlist_head.get_type():
45 raise TypeError("Must be struct hlist_head not {}"
46 .format(head.type))
47
48 node = head['first'].dereference()
49 while node.address:
50 yield node.address
51 node = node['next'].dereference()
52
53
54def hlist_for_each_entry(head, gdbtype, member):
55 for node in hlist_for_each(head):
39 yield utils.container_of(node, gdbtype, member) 56 yield utils.container_of(node, gdbtype, member)
40 57
41 58
@@ -110,4 +127,5 @@ class LxListChk(gdb.Command):
110 raise gdb.GdbError("lx-list-check takes one argument") 127 raise gdb.GdbError("lx-list-check takes one argument")
111 list_check(gdb.parse_and_eval(argv[0])) 128 list_check(gdb.parse_and_eval(argv[0]))
112 129
130
113LxListChk() 131LxListChk()
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 2f01a958eb22..6a56bba233a9 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -29,6 +29,7 @@ class LxCmdLine(gdb.Command):
29 def invoke(self, arg, from_tty): 29 def invoke(self, arg, from_tty):
30 gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n") 30 gdb.write(gdb.parse_and_eval("saved_command_line").string() + "\n")
31 31
32
32LxCmdLine() 33LxCmdLine()
33 34
34 35
@@ -43,6 +44,7 @@ class LxVersion(gdb.Command):
43 # linux_banner should contain a newline 44 # linux_banner should contain a newline
44 gdb.write(gdb.parse_and_eval("(char *)linux_banner").string()) 45 gdb.write(gdb.parse_and_eval("(char *)linux_banner").string())
45 46
47
46LxVersion() 48LxVersion()
47 49
48 50
@@ -86,6 +88,7 @@ Equivalent to cat /proc/iomem on a running target"""
86 def invoke(self, arg, from_tty): 88 def invoke(self, arg, from_tty):
87 return show_lx_resources("iomem_resource") 89 return show_lx_resources("iomem_resource")
88 90
91
89LxIOMem() 92LxIOMem()
90 93
91 94
@@ -100,6 +103,7 @@ Equivalent to cat /proc/ioports on a running target"""
100 def invoke(self, arg, from_tty): 103 def invoke(self, arg, from_tty):
101 return show_lx_resources("ioport_resource") 104 return show_lx_resources("ioport_resource")
102 105
106
103LxIOPorts() 107LxIOPorts()
104 108
105 109
@@ -149,7 +153,7 @@ values of that process namespace"""
149 if len(argv) >= 1: 153 if len(argv) >= 1:
150 try: 154 try:
151 pid = int(argv[0]) 155 pid = int(argv[0])
152 except: 156 except gdb.error:
153 raise gdb.GdbError("Provide a PID as integer value") 157 raise gdb.GdbError("Provide a PID as integer value")
154 else: 158 else:
155 pid = 1 159 pid = 1
@@ -195,6 +199,7 @@ values of that process namespace"""
195 info_opts(FS_INFO, s_flags), 199 info_opts(FS_INFO, s_flags),
196 info_opts(MNT_INFO, m_flags))) 200 info_opts(MNT_INFO, m_flags)))
197 201
202
198LxMounts() 203LxMounts()
199 204
200 205
@@ -259,7 +264,7 @@ class LxFdtDump(gdb.Command):
259 264
260 try: 265 try:
261 f = open(filename, 'wb') 266 f = open(filename, 'wb')
262 except: 267 except gdb.error:
263 raise gdb.GdbError("Could not open file to dump fdt") 268 raise gdb.GdbError("Could not open file to dump fdt")
264 269
265 f.write(fdt_buf) 270 f.write(fdt_buf)
@@ -267,4 +272,5 @@ class LxFdtDump(gdb.Command):
267 272
268 gdb.write("Dumped fdt blob to " + filename + "\n") 273 gdb.write("Dumped fdt blob to " + filename + "\n")
269 274
275
270LxFdtDump() 276LxFdtDump()
diff --git a/scripts/gdb/linux/rbtree.py b/scripts/gdb/linux/rbtree.py
new file mode 100644
index 000000000000..39db889b874c
--- /dev/null
+++ b/scripts/gdb/linux/rbtree.py
@@ -0,0 +1,177 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Copyright 2019 Google LLC.
4
5import gdb
6
7from linux import utils
8
9rb_root_type = utils.CachedType("struct rb_root")
10rb_node_type = utils.CachedType("struct rb_node")
11
12
13def rb_first(root):
14 if root.type == rb_root_type.get_type():
15 node = node.address.cast(rb_root_type.get_type().pointer())
16 elif root.type != rb_root_type.get_type().pointer():
17 raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
18
19 node = root['rb_node']
20 if node is 0:
21 return None
22
23 while node['rb_left']:
24 node = node['rb_left']
25
26 return node
27
28
29def rb_last(root):
30 if root.type == rb_root_type.get_type():
31 node = node.address.cast(rb_root_type.get_type().pointer())
32 elif root.type != rb_root_type.get_type().pointer():
33 raise gdb.GdbError("Must be struct rb_root not {}".format(root.type))
34
35 node = root['rb_node']
36 if node is 0:
37 return None
38
39 while node['rb_right']:
40 node = node['rb_right']
41
42 return node
43
44
45def rb_parent(node):
46 parent = gdb.Value(node['__rb_parent_color'] & ~3)
47 return parent.cast(rb_node_type.get_type().pointer())
48
49
50def rb_empty_node(node):
51 return node['__rb_parent_color'] == node.address
52
53
54def rb_next(node):
55 if node.type == rb_node_type.get_type():
56 node = node.address.cast(rb_node_type.get_type().pointer())
57 elif node.type != rb_node_type.get_type().pointer():
58 raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
59
60 if rb_empty_node(node):
61 return None
62
63 if node['rb_right']:
64 node = node['rb_right']
65 while node['rb_left']:
66 node = node['rb_left']
67 return node
68
69 parent = rb_parent(node)
70 while parent and node == parent['rb_right']:
71 node = parent
72 parent = rb_parent(node)
73
74 return parent
75
76
77def rb_prev(node):
78 if node.type == rb_node_type.get_type():
79 node = node.address.cast(rb_node_type.get_type().pointer())
80 elif node.type != rb_node_type.get_type().pointer():
81 raise gdb.GdbError("Must be struct rb_node not {}".format(node.type))
82
83 if rb_empty_node(node):
84 return None
85
86 if node['rb_left']:
87 node = node['rb_left']
88 while node['rb_right']:
89 node = node['rb_right']
90 return node.dereference()
91
92 parent = rb_parent(node)
93 while parent and node == parent['rb_left'].dereference():
94 node = parent
95 parent = rb_parent(node)
96
97 return parent
98
99
100class LxRbFirst(gdb.Function):
101 """Lookup and return a node from an RBTree
102
103$lx_rb_first(root): Return the node at the given index.
104If index is omitted, the root node is dereferenced and returned."""
105
106 def __init__(self):
107 super(LxRbFirst, self).__init__("lx_rb_first")
108
109 def invoke(self, root):
110 result = rb_first(root)
111 if result is None:
112 raise gdb.GdbError("No entry in tree")
113
114 return result
115
116
117LxRbFirst()
118
119
120class LxRbLast(gdb.Function):
121 """Lookup and return a node from an RBTree.
122
123$lx_rb_last(root): Return the node at the given index.
124If index is omitted, the root node is dereferenced and returned."""
125
126 def __init__(self):
127 super(LxRbLast, self).__init__("lx_rb_last")
128
129 def invoke(self, root):
130 result = rb_last(root)
131 if result is None:
132 raise gdb.GdbError("No entry in tree")
133
134 return result
135
136
137LxRbLast()
138
139
140class LxRbNext(gdb.Function):
141 """Lookup and return a node from an RBTree.
142
143$lx_rb_next(node): Return the node at the given index.
144If index is omitted, the root node is dereferenced and returned."""
145
146 def __init__(self):
147 super(LxRbNext, self).__init__("lx_rb_next")
148
149 def invoke(self, node):
150 result = rb_next(node)
151 if result is None:
152 raise gdb.GdbError("No entry in tree")
153
154 return result
155
156
157LxRbNext()
158
159
160class LxRbPrev(gdb.Function):
161 """Lookup and return a node from an RBTree.
162
163$lx_rb_prev(node): Return the node at the given index.
164If index is omitted, the root node is dereferenced and returned."""
165
166 def __init__(self):
167 super(LxRbPrev, self).__init__("lx_rb_prev")
168
169 def invoke(self, node):
170 result = rb_prev(node)
171 if result is None:
172 raise gdb.GdbError("No entry in tree")
173
174 return result
175
176
177LxRbPrev()
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index 004b0ac7fa72..2f5b95f09fa0 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -139,8 +139,12 @@ lx-symbols command."""
139 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled}) 139 saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
140 140
141 # drop all current symbols and reload vmlinux 141 # drop all current symbols and reload vmlinux
142 orig_vmlinux = 'vmlinux'
143 for obj in gdb.objfiles():
144 if obj.filename.endswith('vmlinux'):
145 orig_vmlinux = obj.filename
142 gdb.execute("symbol-file", to_string=True) 146 gdb.execute("symbol-file", to_string=True)
143 gdb.execute("symbol-file vmlinux") 147 gdb.execute("symbol-file {0}".format(orig_vmlinux))
144 148
145 self.loaded_modules = [] 149 self.loaded_modules = []
146 module_list = modules.module_list() 150 module_list = modules.module_list()
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index f6ab3ccf698f..0301dc1e0138 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -79,6 +79,7 @@ class LxPs(gdb.Command):
79 pid=task["pid"], 79 pid=task["pid"],
80 comm=task["comm"].string())) 80 comm=task["comm"].string()))
81 81
82
82LxPs() 83LxPs()
83 84
84 85
@@ -134,4 +135,5 @@ variable."""
134 else: 135 else:
135 raise gdb.GdbError("No task of PID " + str(pid)) 136 raise gdb.GdbError("No task of PID " + str(pid))
136 137
138
137LxThreadInfoByPidFunc() 139LxThreadInfoByPidFunc()
diff --git a/scripts/gdb/linux/timerlist.py b/scripts/gdb/linux/timerlist.py
new file mode 100644
index 000000000000..071d0dd5a634
--- /dev/null
+++ b/scripts/gdb/linux/timerlist.py
@@ -0,0 +1,219 @@
1# SPDX-License-Identifier: GPL-2.0
2#
3# Copyright 2019 Google LLC.
4
5import binascii
6import gdb
7
8from linux import constants
9from linux import cpus
10from linux import rbtree
11from linux import utils
12
13timerqueue_node_type = utils.CachedType("struct timerqueue_node").get_type()
14hrtimer_type = utils.CachedType("struct hrtimer").get_type()
15
16
17def ktime_get():
18 """Returns the current time, but not very accurately
19
20 We can't read the hardware timer itself to add any nanoseconds
21 that need to be added since we last stored the time in the
22 timekeeper. But this is probably good enough for debug purposes."""
23 tk_core = gdb.parse_and_eval("&tk_core")
24
25 return tk_core['timekeeper']['tkr_mono']['base']
26
27
28def print_timer(rb_node, idx):
29 timerqueue = utils.container_of(rb_node, timerqueue_node_type.pointer(),
30 "node")
31 timer = utils.container_of(timerqueue, hrtimer_type.pointer(), "node")
32
33 function = str(timer['function']).split(" ")[1].strip("<>")
34 softexpires = timer['_softexpires']
35 expires = timer['node']['expires']
36 now = ktime_get()
37
38 text = " #{}: <{}>, {}, ".format(idx, timer, function)
39 text += "S:{:02x}\n".format(int(timer['state']))
40 text += " # expires at {}-{} nsecs [in {} to {} nsecs]\n".format(
41 softexpires, expires, softexpires - now, expires - now)
42 return text
43
44
45def print_active_timers(base):
46 curr = base['active']['next']['node']
47 curr = curr.address.cast(rbtree.rb_node_type.get_type().pointer())
48 idx = 0
49 while curr:
50 yield print_timer(curr, idx)
51 curr = rbtree.rb_next(curr)
52 idx += 1
53
54
55def print_base(base):
56 text = " .base: {}\n".format(base.address)
57 text += " .index: {}\n".format(base['index'])
58
59 text += " .resolution: {} nsecs\n".format(constants.LX_hrtimer_resolution)
60
61 text += " .get_time: {}\n".format(base['get_time'])
62 if constants.LX_CONFIG_HIGH_RES_TIMERS:
63 text += " .offset: {} nsecs\n".format(base['offset'])
64 text += "active timers:\n"
65 text += "".join([x for x in print_active_timers(base)])
66 return text
67
68
69def print_cpu(hrtimer_bases, cpu, max_clock_bases):
70 cpu_base = cpus.per_cpu(hrtimer_bases, cpu)
71 jiffies = gdb.parse_and_eval("jiffies_64")
72 tick_sched_ptr = gdb.parse_and_eval("&tick_cpu_sched")
73 ts = cpus.per_cpu(tick_sched_ptr, cpu)
74
75 text = "cpu: {}\n".format(cpu)
76 for i in xrange(max_clock_bases):
77 text += " clock {}:\n".format(i)
78 text += print_base(cpu_base['clock_base'][i])
79
80 if constants.LX_CONFIG_HIGH_RES_TIMERS:
81 fmts = [(" .{} : {} nsecs", 'expires_next'),
82 (" .{} : {}", 'hres_active'),
83 (" .{} : {}", 'nr_events'),
84 (" .{} : {}", 'nr_retries'),
85 (" .{} : {}", 'nr_hangs'),
86 (" .{} : {}", 'max_hang_time')]
87 text += "\n".join([s.format(f, cpu_base[f]) for s, f in fmts])
88 text += "\n"
89
90 if constants.LX_CONFIG_TICK_ONESHOT:
91 fmts = [(" .{} : {}", 'nohz_mode'),
92 (" .{} : {} nsecs", 'last_tick'),
93 (" .{} : {}", 'tick_stopped'),
94 (" .{} : {}", 'idle_jiffies'),
95 (" .{} : {}", 'idle_calls'),
96 (" .{} : {}", 'idle_sleeps'),
97 (" .{} : {} nsecs", 'idle_entrytime'),
98 (" .{} : {} nsecs", 'idle_waketime'),
99 (" .{} : {} nsecs", 'idle_exittime'),
100 (" .{} : {} nsecs", 'idle_sleeptime'),
101 (" .{}: {} nsecs", 'iowait_sleeptime'),
102 (" .{} : {}", 'last_jiffies'),
103 (" .{} : {}", 'next_timer'),
104 (" .{} : {} nsecs", 'idle_expires')]
105 text += "\n".join([s.format(f, ts[f]) for s, f in fmts])
106 text += "\njiffies: {}\n".format(jiffies)
107
108 text += "\n"
109
110 return text
111
112
113def print_tickdevice(td, cpu):
114 dev = td['evtdev']
115 text = "Tick Device: mode: {}\n".format(td['mode'])
116 if cpu < 0:
117 text += "Broadcast device\n"
118 else:
119 text += "Per CPU device: {}\n".format(cpu)
120
121 text += "Clock Event Device: "
122 if dev == 0:
123 text += "<NULL>\n"
124 return text
125
126 text += "{}\n".format(dev['name'])
127 text += " max_delta_ns: {}\n".format(dev['max_delta_ns'])
128 text += " min_delta_ns: {}\n".format(dev['min_delta_ns'])
129 text += " mult: {}\n".format(dev['mult'])
130 text += " shift: {}\n".format(dev['shift'])
131 text += " mode: {}\n".format(dev['state_use_accessors'])
132 text += " next_event: {} nsecs\n".format(dev['next_event'])
133
134 text += " set_next_event: {}\n".format(dev['set_next_event'])
135
136 members = [('set_state_shutdown', " shutdown: {}\n"),
137 ('set_state_periodic', " periodic: {}\n"),
138 ('set_state_oneshot', " oneshot: {}\n"),
139 ('set_state_oneshot_stopped', " oneshot stopped: {}\n"),
140 ('tick_resume', " resume: {}\n")]
141 for member, fmt in members:
142 if dev[member]:
143 text += fmt.format(dev[member])
144
145 text += " event_handler: {}\n".format(dev['event_handler'])
146 text += " retries: {}\n".format(dev['retries'])
147
148 return text
149
150
151def pr_cpumask(mask):
152 nr_cpu_ids = 1
153 if constants.LX_NR_CPUS > 1:
154 nr_cpu_ids = gdb.parse_and_eval("nr_cpu_ids")
155
156 inf = gdb.inferiors()[0]
157 bits = mask['bits']
158 num_bytes = (nr_cpu_ids + 7) / 8
159 buf = utils.read_memoryview(inf, bits, num_bytes).tobytes()
160 buf = binascii.b2a_hex(buf)
161
162 chunks = []
163 i = num_bytes
164 while i > 0:
165 i -= 1
166 start = i * 2
167 end = start + 2
168 chunks.append(buf[start:end])
169 if i != 0 and i % 4 == 0:
170 chunks.append(',')
171
172 extra = nr_cpu_ids % 8
173 if 0 < extra <= 4:
174 chunks[0] = chunks[0][0] # Cut off the first 0
175
176 return "".join(chunks)
177
178
179class LxTimerList(gdb.Command):
180 """Print /proc/timer_list"""
181
182 def __init__(self):
183 super(LxTimerList, self).__init__("lx-timerlist", gdb.COMMAND_DATA)
184
185 def invoke(self, arg, from_tty):
186 hrtimer_bases = gdb.parse_and_eval("&hrtimer_bases")
187 max_clock_bases = gdb.parse_and_eval("HRTIMER_MAX_CLOCK_BASES")
188
189 text = "Timer List Version: gdb scripts\n"
190 text += "HRTIMER_MAX_CLOCK_BASES: {}\n".format(max_clock_bases)
191 text += "now at {} nsecs\n".format(ktime_get())
192
193 for cpu in cpus.each_online_cpu():
194 text += print_cpu(hrtimer_bases, cpu, max_clock_bases)
195
196 if constants.LX_CONFIG_GENERIC_CLOCKEVENTS:
197 if constants.LX_CONFIG_GENERIC_CLOCKEVENTS_BROADCAST:
198 bc_dev = gdb.parse_and_eval("&tick_broadcast_device")
199 text += print_tickdevice(bc_dev, -1)
200 text += "\n"
201 mask = gdb.parse_and_eval("tick_broadcast_mask")
202 mask = pr_cpumask(mask)
203 text += "tick_broadcast_mask: {}\n".format(mask)
204 if constants.LX_CONFIG_TICK_ONESHOT:
205 mask = gdb.parse_and_eval("tick_broadcast_oneshot_mask")
206 mask = pr_cpumask(mask)
207 text += "tick_broadcast_oneshot_mask: {}\n".format(mask)
208 text += "\n"
209
210 tick_cpu_devices = gdb.parse_and_eval("&tick_cpu_device")
211 for cpu in cpus.each_online_cpu():
212 tick_dev = cpus.per_cpu(tick_cpu_devices, cpu)
213 text += print_tickdevice(tick_dev, cpu)
214 text += "\n"
215
216 gdb.write(text)
217
218
219LxTimerList()
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 50805874cfc3..bc67126118c4 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -66,6 +66,7 @@ Note that TYPE and ELEMENT have to be quoted as strings."""
66 return container_of(ptr, gdb.lookup_type(typename.string()).pointer(), 66 return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
67 elementname.string()) 67 elementname.string())
68 68
69
69ContainerOf() 70ContainerOf()
70 71
71 72
@@ -148,14 +149,14 @@ def get_gdbserver_type():
148 def probe_qemu(): 149 def probe_qemu():
149 try: 150 try:
150 return gdb.execute("monitor info version", to_string=True) != "" 151 return gdb.execute("monitor info version", to_string=True) != ""
151 except: 152 except gdb.error:
152 return False 153 return False
153 154
154 def probe_kgdb(): 155 def probe_kgdb():
155 try: 156 try:
156 thread_info = gdb.execute("info thread 2", to_string=True) 157 thread_info = gdb.execute("info thread 2", to_string=True)
157 return "shadowCPU0" in thread_info 158 return "shadowCPU0" in thread_info
158 except: 159 except gdb.error:
159 return False 160 return False
160 161
161 global gdbserver_type 162 global gdbserver_type
@@ -172,7 +173,7 @@ def get_gdbserver_type():
172def gdb_eval_or_none(expresssion): 173def gdb_eval_or_none(expresssion):
173 try: 174 try:
174 return gdb.parse_and_eval(expresssion) 175 return gdb.parse_and_eval(expresssion)
175 except: 176 except gdb.error:
176 return None 177 return None
177 178
178 179
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 6e0b0afd888a..eff5a48ac026 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -27,7 +27,11 @@ else:
27 import linux.modules 27 import linux.modules
28 import linux.dmesg 28 import linux.dmesg
29 import linux.tasks 29 import linux.tasks
30 import linux.config
30 import linux.cpus 31 import linux.cpus
31 import linux.lists 32 import linux.lists
33 import linux.rbtree
32 import linux.proc 34 import linux.proc
33 import linux.constants 35 import linux.constants
36 import linux.timerlist
37 import linux.clk