Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1349015 > unrolled thread

[PATCHv3 00/13] scripts/gdb: Linux awareness debug commands

Started byKieran Bingham <kieran.bingham@linaro.org>
First post2016-03-03 12:50 +0100
Last post2016-03-03 12:50 +0100
Articles 12 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [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

#1349015 — [PATCHv3 00/13] scripts/gdb: Linux awareness debug commands

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349020 — [PATCHv3 11/13] scripts/gdb: Add a Radix Tree Parser

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349021 — [PATCHv3 02/13] scripts/gdb: Provide kernel list item generators

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349022 — [PATCHv3 05/13] scripts/gdb: Support !CONFIG_MODULES gracefully

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349024 — [PATCHv3 01/13] scripts/gdb: Provide linux constants

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349026 — [PATCHv3 04/13] scripts/gdb: Provide exception catching parser

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349030 — [PATCHv3 13/13] scripts/gdb: Add lx_thread_info_by_pid helper

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349034 — [PATCHv3 10/13] scripts/gdb: Add cpu iterators

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349038 — [PATCHv3 12/13] scripts/gdb: Add interrupts command

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349039 — [PATCHv3 06/13] scripts/gdb: Provide a dentry_name VFS path helper

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349041 — [PATCHv3 08/13] scripts/gdb: Add mount point list command

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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]


#1349045 — [PATCHv3 03/13] scripts/gdb: Convert modules usage to lists functions

FromKieran Bingham <kieran.bingham@linaro.org>
Date2016-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