Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1349015 > unrolled thread
| Started by | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| First post | 2016-03-03 12:50 +0100 |
| Last post | 2016-03-03 12:50 +0100 |
| Articles | 12 — 1 participant |
Back to article view | Back to linux.kernel
[PATCHv3 00/13] scripts/gdb: Linux awareness debug commands Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 11/13] scripts/gdb: Add a Radix Tree Parser Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 02/13] scripts/gdb: Provide kernel list item generators Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 05/13] scripts/gdb: Support !CONFIG_MODULES gracefully Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 01/13] scripts/gdb: Provide linux constants Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 04/13] scripts/gdb: Provide exception catching parser Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 13/13] scripts/gdb: Add lx_thread_info_by_pid helper Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 10/13] scripts/gdb: Add cpu iterators Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 12/13] scripts/gdb: Add interrupts command Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 06/13] scripts/gdb: Provide a dentry_name VFS path helper Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 08/13] scripts/gdb: Add mount point list command Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
[PATCHv3 03/13] scripts/gdb: Convert modules usage to lists functions Kieran Bingham <kieran.bingham@linaro.org> - 2016-03-03 12:50 +0100
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 00/13] scripts/gdb: Linux awareness debug commands |
| Message-ID | <r8zVv-6xi-3@gated-at.bofh.it> |
Hi Jan, V3 of the patchset respun. Now finally adding the lx-interrupts command after I resolved my issues with the Radix Tree parsing. This command only provides the interrupts that are available generically, and it seems that the /proc/interrupts function calls into arch specific layers to add extra information about arch specific interrupts. I'm not sure what to do about this yet - The values returned appear to be accurarate - but it's just a subset of the information returned by proc. lx_thread_info_by_pid has been useful to me while looking at thread awareness, so I've included it into this patch set now. It makes finding internal thread information much more convenient. dentry_name has been moved to the utils module, as I am already using it in another command, so it's just not appropriate to be in proc.py The cpu_list mask iterators make calling for cpu in each_online_cpu() read nicely, and I've left the print_cpus() function in for now as a hidden helper. It can be used by calling: python linux.cpus.print_cpus() to check these generators, which I thought was quite nice - but I didn't know if it warranted a full command class for this. For convenience, this patch set submission can be found at http://git.linaro.org/people/kieran.bingham/linux.git gdb-scripts-2016-03-03-lkml-submission Patchset Changelog: v3: - Radix Tree parser introduced - cpu_list mask iterators added - lx-interrupts command implemented - dentry_name function moved to utils - lx-meminfo command PEP8 warnings fixed - lx_thread_info_by_pid introduced v2: - Reworked iterators with improved versions from Jeff Mahoney - Fixed !CONFIG_MODULES and !CONFIG_MMU support - Improvements on lx-meminfo - constants.py generated by Kbuild - IS_BUILTIN facility used to provide LX_CONFIG values v1: - Introduced lx-iomem, lx-ioports, lx-mounts, lx-meminfo Kieran Bingham (13): scripts/gdb: Provide linux constants scripts/gdb: Provide kernel list item generators scripts/gdb: Convert modules usage to lists functions scripts/gdb: Provide exception catching parser scripts/gdb: Support !CONFIG_MODULES gracefully scripts/gdb: Provide a dentry_name VFS path helper scripts/gdb: Add io resource readers scripts/gdb: Add mount point list command scripts/gdb: Add meminfo command scripts/gdb: Add cpu iterators scripts/gdb: Add a Radix Tree Parser scripts/gdb: Add interrupts command scripts/gdb: Add lx_thread_info_by_pid helper Kbuild | 10 + scripts/gdb/linux/Makefile | 12 +- scripts/gdb/linux/constants.py.in | 93 ++++++++ scripts/gdb/linux/cpus.py | 21 ++ scripts/gdb/linux/lists.py | 20 ++ scripts/gdb/linux/modules.py | 22 +- scripts/gdb/linux/proc.py | 449 ++++++++++++++++++++++++++++++++++++++ scripts/gdb/linux/radixtree.py | 74 +++++++ scripts/gdb/linux/tasks.py | 19 ++ scripts/gdb/linux/utils.py | 15 ++ scripts/gdb/vmlinux-gdb.py | 2 + 11 files changed, 724 insertions(+), 13 deletions(-) create mode 100644 scripts/gdb/linux/constants.py.in create mode 100644 scripts/gdb/linux/radixtree.py -- 2.5.0
[toc] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 11/13] scripts/gdb: Add a Radix Tree Parser |
| Message-ID | <r8zVx-6xi-31@gated-at.bofh.it> |
| In reply to | #1349015 |
Linux makes use of the Radix Tree data structure to store pointers indexed
by integer values. This structure is utilised across many structures in
the kernel including the IRQ descriptor tables, and several filesystems.
This module provides a method to lookup values from a structure given
its head node.
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/constants.py.in | 7 +++-
scripts/gdb/linux/radixtree.py | 74 +++++++++++++++++++++++++++++++++++++++
scripts/gdb/vmlinux-gdb.py | 1 +
3 files changed, 81 insertions(+), 1 deletion(-)
create mode 100644 scripts/gdb/linux/radixtree.py
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 66562a8242bd..b38b9085c702 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -21,7 +21,7 @@
#include <linux/mount.h>
#include <linux/huge_mm.h>
#include <linux/vmalloc.h>
-
+#include <linux/radix-tree.h>
/* We need to stringify expanded macros so that they can be parsed */
@@ -71,6 +71,11 @@ LX_GDBPARSED(VMALLOC_TOTAL)
/* linux/swap.h */
LX_GDBPARSED(MAX_SWAPFILES)
+/* linux/radix-tree.h */
+LX_VALUE(RADIX_TREE_INDIRECT_PTR)
+LX_GDBPARSED(RADIX_TREE_HEIGHT_MASK)
+LX_GDBPARSED(RADIX_TREE_MAP_SHIFT)
+LX_GDBPARSED(RADIX_TREE_MAP_MASK)
/* Kernel Configs */
LX_CONFIG(CONFIG_HIGHMEM)
diff --git a/scripts/gdb/linux/radixtree.py b/scripts/gdb/linux/radixtree.py
new file mode 100644
index 000000000000..299d171e3571
--- /dev/null
+++ b/scripts/gdb/linux/radixtree.py
@@ -0,0 +1,74 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+# Radix Tree Parser
+#
+# Copyright (c) 2016 Linaro Ltd
+#
+# Authors:
+# Kieran Bingham <kieran.bingham@linaro.org>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import utils
+from linux import constants
+
+radix_tree_root_type = utils.CachedType("struct radix_tree_root")
+radix_tree_node_type = utils.CachedType("struct radix_tree_node")
+
+
+def is_indirect_ptr(node):
+ long_type = utils.get_long_type()
+ return (node.cast(long_type) & constants.LX_RADIX_TREE_INDIRECT_PTR)
+
+
+def indirect_to_ptr(node):
+ long_type = utils.get_long_type()
+ node_type = node.type
+ indirect_ptr = node.cast(long_type) & ~constants.LX_RADIX_TREE_INDIRECT_PTR
+ return indirect_ptr.cast(node_type)
+
+
+def maxindex(height):
+ height = height & constants.LX_RADIX_TREE_HEIGHT_MASK
+ return gdb.parse_and_eval("height_to_maxindex["+str(height)+"]")
+
+
+def lookup(root, index):
+ node = root['rnode']
+ if node is 0:
+ return None
+
+ if not (is_indirect_ptr(node)):
+ if (index > 0):
+ return None
+ return node
+
+ node = indirect_to_ptr(node)
+
+ height = node['path'] & constants.LX_RADIX_TREE_HEIGHT_MASK
+ if (index > maxindex(height)):
+ return None
+
+ shift = (height-1) * constants.LX_RADIX_TREE_MAP_SHIFT
+
+ while True:
+ new_index = (index >> shift) & constants.LX_RADIX_TREE_MAP_MASK
+ slot = node['slots'][new_index]
+
+ # Below needs a bit more verification ...
+ # node = rcu_dereference_raw(*slot);
+ node = slot.cast(node.type.pointer()).dereference()
+ if node is 0:
+ return None
+
+ shift -= constants.LX_RADIX_TREE_MAP_SHIFT
+ height -= 1
+
+ if (height <= 0):
+ break
+
+ return node
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 6e0b0afd888a..3a80ad6eecad 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -31,3 +31,4 @@ else:
import linux.lists
import linux.proc
import linux.constants
+ import linux.radixtree
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 02/13] scripts/gdb: Provide kernel list item generators |
| Message-ID | <r8zVx-6xi-37@gated-at.bofh.it> |
| In reply to | #1349015 |
Facilitate linked-list items by providing a generator to return
the dereferenced, and type-cast objects from a kernel linked list
CC: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes since v1:
* items function removed, and replaced with Jeff Mahoney's cleaner
implementations of list_for_each, and list_for_each_entry
---
scripts/gdb/linux/lists.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py
index 3a3775bc162b..9f4503738e26 100644
--- a/scripts/gdb/linux/lists.py
+++ b/scripts/gdb/linux/lists.py
@@ -18,6 +18,26 @@ from linux import utils
list_head = utils.CachedType("struct list_head")
+def list_for_each(head):
+ if head.type == list_head.get_type().pointer():
+ head = head.dereference()
+ elif head.type != list_head.get_type():
+ raise gdb.GdbError("Must be struct list_head not %s" % list_head.type)
+
+ node = head['next'].dereference()
+ while node.address != head.address:
+ yield node.address
+ node = node['next'].dereference()
+
+
+def list_for_each_entry(head, gdbtype, member):
+ for node in list_for_each(head):
+ if node.type != list_head.get_type().pointer():
+ raise TypeError("Type %s found. "
+ "Expected struct list_head *." % node.type)
+ yield utils.container_of(node, gdbtype, member)
+
+
def list_check(head):
nb = 0
if (head.type == list_head.get_type().pointer()):
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 05/13] scripts/gdb: Support !CONFIG_MODULES gracefully |
| Message-ID | <r8zVx-6xi-39@gated-at.bofh.it> |
| In reply to | #1349015 |
If CONFIG_MODULES is not enabled, lx-lsmod tries to find
a non-existent symbol and generates an unfriendly traceback:
(gdb) lx-lsmod
Address Module Size Used by
Traceback (most recent call last):
File "scripts/gdb/linux/modules.py", line 75, in invoke
for module in module_list():
File "scripts/gdb/linux/modules.py", line 24, in module_list
module_ptr_type = module_type.get_type().pointer()
File "scripts/gdb/linux/utils.py", line 28, in get_type
self._type = gdb.lookup_type(self._name)
gdb.error: No struct type named module.
Error occurred in Python command: No struct type named module.
Catch the error and return an empty module_list() for a clean command
output as follows:
(gdb) lx-lsmod
Address Module Size Used by
(gdb)
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/modules.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 571489b3b9c2..60224d8bbfb2 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -21,8 +21,11 @@ module_type = utils.CachedType("struct module")
def module_list():
global module_type
+ modules = utils.gdb_eval_or_none("modules")
+ if modules is None:
+ return
+
module_ptr_type = module_type.get_type().pointer()
- modules = gdb.parse_and_eval("modules")
for module in lists.list_for_each_entry(modules, module_ptr_type, "list"):
yield module
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 01/13] scripts/gdb: Provide linux constants |
| Message-ID | <r8zVx-6xi-43@gated-at.bofh.it> |
| In reply to | #1349015 |
Some macro's and defines are needed when parsing memory, and without
compiling the kernel as -g3 they are not available in the debug-symbols.
We use the pre-processor here to extract constants to a dedicated module
for the linux debugger extensions
Top level Kbuild is used to call in and generate the constants file,
while maintaining dependencies on autogenerated files in
include/generated
CC: mmarek@suse.com
CC: linux-kbuild@vger.kernel.org
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes since v1:
Kbuild:
- Call to generate constants_py with dependancy on generated files
scripts/gdb/linux/Makefile:
- Use call if_changed, and correct quiet invocation
- Annouce "GEN $@" instead of GDB PP
scripts/gdb/linux/constants.py.in:
- Updated to use better macro implementations for one line defines
---
Kbuild | 10 ++++++++++
scripts/gdb/linux/Makefile | 12 +++++++++++-
scripts/gdb/linux/constants.py.in | 32 ++++++++++++++++++++++++++++++++
scripts/gdb/vmlinux-gdb.py | 1 +
4 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 scripts/gdb/linux/constants.py.in
diff --git a/Kbuild b/Kbuild
index f55cefd9bf29..3d0ae152af7c 100644
--- a/Kbuild
+++ b/Kbuild
@@ -5,6 +5,7 @@
# 2) Generate timeconst.h
# 3) Generate asm-offsets.h (may need bounds.h and timeconst.h)
# 4) Check for missing system calls
+# 5) Generate constants.py (may need bounds.h)
# Default sed regexp - multiline due to syntax constraints
define sed-y
@@ -96,5 +97,14 @@ quiet_cmd_syscalls = CALL $<
missing-syscalls: scripts/checksyscalls.sh $(offsets-file) FORCE
$(call cmd,syscalls)
+#####
+# 5) Generate constants for Python GDB integration
+#
+
+extra-$(CONFIG_GDB_SCRIPTS) += build_constants_py
+
+build_constants_py: $(obj)/$(timeconst-file) $(obj)/$(bounds-file)
+ @$(MAKE) $(build)=scripts/gdb/linux $@
+
# Keep these three files during make clean
no-clean-files := $(bounds-file) $(offsets-file) $(timeconst-file)
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
index 6cf1ecf61057..cd129e65d1ff 100644
--- a/scripts/gdb/linux/Makefile
+++ b/scripts/gdb/linux/Makefile
@@ -8,4 +8,14 @@ ifneq ($(KBUILD_SRC),)
endif
@:
-clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py)
+quiet_cmd_gen_constants_py = GEN $@
+ cmd_gen_constants_py = \
+ $(CPP) -E -x c -P $(c_flags) $< > $@ ;\
+ sed -i '1,/<!-- end-c-headers -->/d;' $@
+
+$(obj)/constants.py: $(SRCTREE)/$(obj)/constants.py.in
+ $(call if_changed,gen_constants_py)
+
+build_constants_py: $(obj)/constants.py
+
+clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py) $(obj)/constants.py
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
new file mode 100644
index 000000000000..79d9d0092452
--- /dev/null
+++ b/scripts/gdb/linux/constants.py.in
@@ -0,0 +1,32 @@
+/*
+ * gdb helper commands and functions for Linux kernel debugging
+ *
+ * Kernel constants derived from include files.
+ *
+ * Copyright (c) 2016 Linaro Ltd
+ *
+ * Authors:
+ * Kieran Bingham <kieran.bingham@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ *
+ */
+
+/* We need to stringify expanded macros so that they can be parsed */
+#define STRING(x) #x
+#define XSTRING(x) STRING(x)
+
+#define LX_VALUE(x) LX_##x = x
+#define LX_GDBPARSED(x) LX_##x = gdb.parse_and_eval(XSTRING(x))
+
+/*
+ * IS_ENABLED generates (a || b) which is not compatible with python
+ * We can only switch on configuration items we know are available
+ * Therefore - IS_BUILTIN() is more appropriate
+ */
+#define LX_CONFIG(x) LX_##x = IS_BUILTIN(x)
+
+/* The build system will take care of deleting everything above this marker */
+<!-- end-c-headers -->
+
+import gdb
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index d5943eca19cd..6e0b0afd888a 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -30,3 +30,4 @@ else:
import linux.cpus
import linux.lists
import linux.proc
+ import linux.constants
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 04/13] scripts/gdb: Provide exception catching parser |
| Message-ID | <r8zVx-6xi-47@gated-at.bofh.it> |
| In reply to | #1349015 |
If we attempt to read a value that is not available to GDB, an exception
is raised. Most of the time, this is a good thing; however on occasion
we will want to be able to determine if a symbol is available.
By catching the exception to simply return None, we can determine if we
tried to read an invalid value, without the exception taking our execution
context away from us
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/utils.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 0893b326a28b..dbe2ad78048c 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -154,3 +154,10 @@ def get_gdbserver_type():
if gdbserver_type is not None and hasattr(gdb, 'events'):
gdb.events.exited.connect(exit_handler)
return gdbserver_type
+
+
+def gdb_eval_or_none(expresssion):
+ try:
+ return gdb.parse_and_eval(expresssion)
+ except:
+ return None
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 13/13] scripts/gdb: Add lx_thread_info_by_pid helper |
| Message-ID | <r8zVy-6xi-53@gated-at.bofh.it> |
| In reply to | #1349015 |
The tasks module already provides helpers to find the task struct by
pid, and the thread_info by task struct; however this is cumbersome to
utilise on the gdb commandline.
Wrap these two functionalities together in an extra single helper to
allow exploring the thread info, from a PID value
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/tasks.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index 862a4ae24d49..1bf949c43b76 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -114,3 +114,22 @@ variable."""
LxThreadInfoFunc()
+
+
+class LxThreadInfoByPidFunc (gdb.Function):
+ """Calculate Linux thread_info from task variable found by pid
+
+$lx_thread_info_by_pid(PID): Given PID, return the corresponding thread_info
+variable."""
+
+ def __init__(self):
+ super(LxThreadInfoByPidFunc, self).__init__("lx_thread_info_by_pid")
+
+ def invoke(self, pid):
+ task = get_task_by_pid(pid)
+ if task:
+ return get_thread_info(task.dereference())
+ else:
+ raise gdb.GdbError("No task of PID " + str(pid))
+
+LxThreadInfoByPidFunc()
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 10/13] scripts/gdb: Add cpu iterators |
| Message-ID | <r8zVy-6xi-65@gated-at.bofh.it> |
| In reply to | #1349015 |
The linux kernel provides macro's for iterating against values from the
cpu_list masks. By providing some commonly used masks, we can mirror the
kernels helper macros with easy to use generators.
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/cpus.py | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index 4297b83fedef..59e24472c507 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -100,6 +100,27 @@ def cpu_list(mask_name):
yield cpu
+def each_online_cpu():
+ for cpu in cpu_list("cpu_online_mask"):
+ yield cpu
+
+
+def each_present_cpu():
+ for cpu in cpu_list("cpu_present_mask"):
+ yield cpu
+
+
+def each_possible_cpu():
+ for cpu in cpu_list("cpu_possible_mask"):
+ yield cpu
+
+
+def print_cpus():
+ gdb.write("Possible CPUS : {}\n".format(list(each_possible_cpu())))
+ gdb.write("Present CPUS : {}\n".format(list(each_present_cpu())))
+ gdb.write("Online CPUS : {}\n".format(list(each_online_cpu())))
+
+
class PerCpu(gdb.Function):
"""Return per-cpu variable.
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 12/13] scripts/gdb: Add interrupts command |
| Message-ID | <r8zVy-6xi-71@gated-at.bofh.it> |
| In reply to | #1349015 |
Allow the debugger to present a list of all interrupts and their
associated counts. This will allow developers of drivers to identify
hardware interactions in the event of crashed kernels and core dumps.
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/constants.py.in | 1 +
scripts/gdb/linux/proc.py | 65 +++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+)
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index b38b9085c702..17b719ead54f 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -84,6 +84,7 @@ LX_CONFIG(CONFIG_TRANSPARENT_HUGEPAGE)
LX_CONFIG(CONFIG_CMA)
LX_CONFIG(CONFIG_MMU)
LX_CONFIG(CONFIG_SWAP)
+LX_CONFIG(CONFIG_SPARSE_IRQ)
#ifndef CONFIG_NR_QUICK
#define CONFIG_NR_QUICK 0
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index e5a8dbe3aa3a..0676a14e8d48 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -16,6 +16,8 @@ from linux import constants
from linux import utils
from linux import tasks
from linux import lists
+from linux import cpus
+from linux import radixtree
class LxCmdLine(gdb.Command):
@@ -423,3 +425,66 @@ Equivalent to cat /proc/meminfo on a running target """
)
LxMeminfo()
+
+irq_desc = None
+irq_desc_type = utils.CachedType("struct irq_desc")
+
+
+class LxInterrupts(gdb.Command):
+ """ Report the interrupt counters of each CPU.
+ Equivalent to cat /proc/interrupts on a running target """
+
+ def __init__(self):
+ super(LxInterrupts, self).__init__("lx-interrupts", gdb.COMMAND_DATA)
+
+ def irq_to_desc(self, irq):
+ if constants.LX_CONFIG_SPARSE_IRQ:
+ irq_desc_tree = gdb.parse_and_eval("irq_desc_tree")
+ irq_desc_addr = radixtree.lookup(irq_desc_tree, irq)
+
+ if irq_desc_addr is None:
+ return None
+
+ if irq_desc_addr.address:
+ return irq_desc_addr.cast(irq_desc_type.get_type())
+ return None
+ else:
+ irq_desc_array = "irq_desc[{}]".format(irq)
+ return gdb.parse_and_eval(irq_desc_array)
+
+ def kstat_irqs_cpu(self, irq_desc, cpu):
+ return int(cpus.per_cpu(irq_desc['kstat_irqs'], cpu))
+
+ def invoke(self, arg, from_tty):
+ nr_irqs = int(gdb.parse_and_eval("nr_irqs"))
+
+ # Calculate the width of the first column
+ prec = 3
+ j = nr_irqs
+ while (j <= nr_irqs):
+ j *= 10
+ prec += 1
+
+ title = "{:{}}".format(" ", prec+8)
+ for cpu in cpus.each_online_cpu():
+ title += "CPU{:<8d}".format(cpu)
+ gdb.write(title + "\n")
+
+ for irq in range(0, nr_irqs):
+ desc = self.irq_to_desc(irq)
+ if desc is None:
+ continue
+
+ anycount = 0
+ for cpu in cpus.each_online_cpu():
+ anycount += self.kstat_irqs_cpu(desc, cpu)
+ if (anycount == 0):
+ continue
+
+ irq_line = "{:{}d}: ".format(irq, prec)
+ for cpu in cpus.each_online_cpu():
+ count = self.kstat_irqs_cpu(desc, cpu)
+ irq_line += "{:10d} ".format(count)
+ gdb.write(irq_line + "\n")
+
+LxInterrupts()
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 06/13] scripts/gdb: Provide a dentry_name VFS path helper |
| Message-ID | <r8zVy-6xi-73@gated-at.bofh.it> |
| In reply to | #1349015 |
Walk the VFS entries, pre-pending the iname strings to generate a full
VFS path name from a dentry.
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes since v2:
- dentry_name separated out from proc module for use elsewhere
---
scripts/gdb/linux/utils.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index dbe2ad78048c..de03a6b505bb 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -161,3 +161,11 @@ def gdb_eval_or_none(expresssion):
return gdb.parse_and_eval(expresssion)
except:
return None
+
+
+def dentry_name(d):
+ parent = d['d_parent']
+ if parent == d or parent == 0:
+ return ""
+ p = dentry_name(d['d_parent']) + "/"
+ return p + d['d_iname'].string()
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 08/13] scripts/gdb: Add mount point list command |
| Message-ID | <r8zVy-6xi-77@gated-at.bofh.it> |
| In reply to | #1349015 |
lx-mounts will identify current mount points based on the 'init_task'
namespace by default, as we do not yet have a kernel thread list
implementation to select the current running thread.
Optionally, a user can specify a PID to list from that process'
namespace
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes from v1:
- Updated to use LX_ constant macros
- Adjusted for new list_for_each_item() function
- Removed unnessary Null check in vfs['mnt_parent']
- Tested and not needed. It probably occured in early testing
with a bad iterator
Changes since v2:
- dentry path helper moved to utils module
---
scripts/gdb/linux/constants.py.in | 21 +++++++++
scripts/gdb/linux/proc.py | 99 +++++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+)
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 79d9d0092452..57213ad8cf75 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -12,7 +12,11 @@
*
*/
+#include <linux/fs.h>
+#include <linux/mount.h>
+
/* We need to stringify expanded macros so that they can be parsed */
+
#define STRING(x) #x
#define XSTRING(x) STRING(x)
@@ -30,3 +34,20 @@
<!-- end-c-headers -->
import gdb
+
+/* linux/fs.h */
+LX_VALUE(MS_RDONLY)
+LX_VALUE(MS_SYNCHRONOUS)
+LX_VALUE(MS_MANDLOCK)
+LX_VALUE(MS_DIRSYNC)
+LX_VALUE(MS_NOATIME)
+LX_VALUE(MS_NODIRATIME)
+
+/* linux/mount.h */
+LX_VALUE(MNT_NOSUID)
+LX_VALUE(MNT_NODEV)
+LX_VALUE(MNT_NOEXEC)
+LX_VALUE(MNT_NOATIME)
+LX_VALUE(MNT_NODIRATIME)
+LX_VALUE(MNT_RELATIME)
+
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index d855b2fd9a06..115f20b07a54 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -12,6 +12,10 @@
#
import gdb
+from linux import constants
+from linux import utils
+from linux import tasks
+from linux import lists
class LxCmdLine(gdb.Command):
@@ -96,3 +100,98 @@ Equivalent to cat /proc/ioports on a running target"""
return show_lx_resources("ioport_resource")
LxIOPorts()
+
+
+# Mount namespace viewer
+# /proc/mounts
+
+def info_opts(lst, opt):
+ opts = ""
+ for key, string in lst.items():
+ if opt & key:
+ opts += string
+ return opts
+
+
+FS_INFO = {constants.LX_MS_SYNCHRONOUS: ",sync",
+ constants.LX_MS_MANDLOCK: ",mand",
+ constants.LX_MS_DIRSYNC: ",dirsync",
+ constants.LX_MS_NOATIME: ",noatime",
+ constants.LX_MS_NODIRATIME: ",nodiratime"}
+
+MNT_INFO = {constants.LX_MNT_NOSUID: ",nosuid",
+ constants.LX_MNT_NODEV: ",nodev",
+ constants.LX_MNT_NOEXEC: ",noexec",
+ constants.LX_MNT_NOATIME: ",noatime",
+ constants.LX_MNT_NODIRATIME: ",nodiratime",
+ constants.LX_MNT_RELATIME: ",relatime"}
+
+mount_type = utils.CachedType("struct mount")
+mount_ptr_type = mount_type.get_type().pointer()
+
+
+class LxMounts(gdb.Command):
+ """Report the VFS mounts of the current process namespace.
+
+Equivalent to cat /proc/mounts on a running target
+An integer value can be supplied to display the mount
+values of that process namespace"""
+
+ def __init__(self):
+ super(LxMounts, self).__init__("lx-mounts", gdb.COMMAND_DATA)
+
+ # Equivalent to proc_namespace.c:show_vfsmnt
+ # However, that has the ability to call into s_op functions
+ # whereas we cannot and must make do with the information we can obtain.
+ def invoke(self, arg, from_tty):
+ argv = gdb.string_to_argv(arg)
+ if len(argv) >= 1:
+ try:
+ pid = int(argv[0])
+ except:
+ raise gdb.GdbError("Provide a PID as integer value")
+ else:
+ pid = 1
+
+ task = tasks.get_task_by_pid(pid)
+ if not task:
+ raise gdb.GdbError("Couldn't find a process with PID {}"
+ .format(pid))
+
+ namespace = task['nsproxy']['mnt_ns']
+ if not namespace:
+ raise gdb.GdbError("No namespace for current process")
+
+ for vfs in lists.list_for_each_entry(
+ namespace['list'], mount_ptr_type, "mnt_list"):
+ devname = vfs['mnt_devname'].string()
+ devname = devname if devname else "none"
+
+ pathname = ""
+ parent = vfs
+ while True:
+ mntpoint = parent['mnt_mountpoint']
+ pathname = utils.dentry_name(mntpoint) + pathname
+ if (parent == parent['mnt_parent']):
+ break
+ parent = parent['mnt_parent']
+
+ if (pathname == ""):
+ pathname = "/"
+
+ superblock = vfs['mnt']['mnt_sb']
+ fstype = superblock['s_type']['name'].string()
+ s_flags = int(superblock['s_flags'])
+ m_flags = int(vfs['mnt']['mnt_flags'])
+ rd = "ro" if (s_flags & constants.LX_MS_RDONLY) else "rw"
+
+ gdb.write(
+ "{} {} {} {}{}{} 0 0\n"
+ .format(devname,
+ pathname,
+ fstype,
+ rd,
+ info_opts(FS_INFO, s_flags),
+ info_opts(MNT_INFO, m_flags)))
+
+LxMounts()
--
2.5.0
[toc] | [prev] | [next] | [standalone]
| From | Kieran Bingham <kieran.bingham@linaro.org> |
|---|---|
| Date | 2016-03-03 12:50 +0100 |
| Subject | [PATCHv3 03/13] scripts/gdb: Convert modules usage to lists functions |
| Message-ID | <r8zVz-6xi-85@gated-at.bofh.it> |
| In reply to | #1349015 |
Simplify the module list functions with the new list_for_each_entry
abstractions
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/modules.py | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 25db8cff44a2..571489b3b9c2 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -13,7 +13,7 @@
import gdb
-from linux import cpus, utils
+from linux import cpus, utils, lists
module_type = utils.CachedType("struct module")
@@ -23,12 +23,9 @@ def module_list():
global module_type
module_ptr_type = module_type.get_type().pointer()
modules = gdb.parse_and_eval("modules")
- entry = modules['next']
- end_of_list = modules.address
- while entry != end_of_list:
- yield utils.container_of(entry, module_ptr_type, "list")
- entry = entry['next']
+ for module in lists.list_for_each_entry(modules, module_ptr_type, "list"):
+ yield module
def find_module_by_name(name):
@@ -79,17 +76,15 @@ class LxLsmod(gdb.Command):
size=str(module['core_size']),
ref=str(module['refcnt']['counter'])))
- source_list = module['source_list']
t = self._module_use_type.get_type().pointer()
- entry = source_list['next']
first = True
- while entry != source_list.address:
- use = utils.container_of(entry, t, "source_list")
+ sources = module['source_list']
+ for use in lists.list_for_each_entry(sources, t, "source_list"):
gdb.write("{separator}{name}".format(
separator=" " if first else ",",
name=use['source']['name'].string()))
first = False
- entry = entry['next']
+
gdb.write("\n")
--
2.5.0
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web