All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v12 00/28] Add gdb python scripts as kernel debugging helpers
@ 2015-01-30  7:24 ` Jan Kiszka
  0 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Daniel Thompson, Daniel Wagner,
	David S. Miller, Fenghua Yu, Kay Sievers, linux-doc, linux-ia64,
	linux-kbuild, Michal Marek, Pantelis Koukousoulas, Rob Landley,
	Rusty Russell, sparclinux, Tony Luck

Hi Andrew,

this is an update to address the review comments provided by Michal
Marek on v11.

Changes since v11:
 - drop redundant subdir rule
 - fold *.pyo into existing clean-files rules

See http://lkml.indiana.edu/hypermail/linux/kernel/1210.0/01598.html for
the original description and

    git://git.kiszka.org/linux.git queues/gdb-scripts

for the latest version.

Jan

CC: Daniel Thompson <daniel.thompson@linaro.org>
CC: Daniel Wagner <daniel.wagner@bmw-carit.de>
CC: "David S. Miller" <davem@davemloft.net>
CC: Fenghua Yu <fenghua.yu@intel.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
CC: Kay Sievers <kay@vrfy.org>
CC: linux-doc@vger.kernel.org
CC: linux-ia64@vger.kernel.org
Cc: linux-kbuild@vger.kernel.org
CC: linux-kbuild@vger.kernel.org
Cc: Michal Marek <mmarek@suse.cz>
CC: Michal Marek <mmarek@suse.cz>
CC: Pantelis Koukousoulas <pktoss@gmail.com>
CC: Rob Landley <rob@landley.net>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: sparclinux@vger.kernel.org
CC: Tony Luck <tony.luck@intel.com>

Daniel Thompson (1):
  scripts/gdb: Ignore byte-compiled python files

Daniel Wagner (1):
  scripts/gdb: Use a generator instead of iterator for task list

Jan Kiszka (25):
  scripts/gdb: Add infrastructure
  scripts/gdb: Add cache for type objects
  scripts/gdb: Add container_of helper and convenience function
  scripts/gdb: Add module iteration class
  scripts/gdb: Add lx-symbols command
  module: Do not inline do_init_module
  scripts/gdb: Add automatic symbol reloading on module insertion
  scripts/gdb: Add internal helper and convenience function to look up a
    module
  scripts/gdb: Add get_target_endianness helper
  scripts/gdb: Add read_u16/32/64 helpers
  scripts/gdb: Add lx-dmesg command
  scripts/gdb: Add task iteration class
  scripts/gdb: Add helper and convenience function to look up tasks
  scripts/gdb: Add is_target_arch helper
  scripts/gdb: Add internal helper and convenience function to retrieve
    thread_info
  scripts/gdb: Add get_gdbserver_type helper
  scripts/gdb: Add internal helper and convenience function for per-cpu
    lookup
  scripts/gdb: Add lx_current convenience function
  scripts/gdb: Add class to iterate over CPU masks
  scripts/gdb: Add lx-lsmod command
  scripts/gdb: Add basic documentation
  scripts/gdb: Convert ModuleList to generator function
  scripts/gdb: Convert CpuList to generator function
  scripts/gdb: Define maintainer
  scripts/gdb: Disable pagination while printing from breakpoint handler

Pantelis Koukousoulas (1):
  scripts/gdb: Port to python3 / gdb7.7

 .gitignore                             |   1 +
 Documentation/gdb-kernel-debugging.txt | 160 +++++++++++++++++++++++++++++
 MAINTAINERS                            |   5 +
 Makefile                               |   5 +-
 kernel/module.c                        |   9 +-
 lib/Kconfig.debug                      |  11 ++
 scripts/Makefile                       |   1 +
 scripts/gdb/Makefile                   |   1 +
 scripts/gdb/linux/.gitignore           |   2 +
 scripts/gdb/linux/Makefile             |  11 ++
 scripts/gdb/linux/__init__.py          |   0
 scripts/gdb/linux/cpus.py              | 135 +++++++++++++++++++++++++
 scripts/gdb/linux/dmesg.py             |  65 ++++++++++++
 scripts/gdb/linux/modules.py           | 103 +++++++++++++++++++
 scripts/gdb/linux/symbols.py           | 177 +++++++++++++++++++++++++++++++++
 scripts/gdb/linux/tasks.py             | 100 +++++++++++++++++++
 scripts/gdb/linux/utils.py             | 156 +++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py             |  30 ++++++
 18 files changed, 969 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/gdb-kernel-debugging.txt
 create mode 100644 scripts/gdb/Makefile
 create mode 100644 scripts/gdb/linux/.gitignore
 create mode 100644 scripts/gdb/linux/Makefile
 create mode 100644 scripts/gdb/linux/__init__.py
 create mode 100644 scripts/gdb/linux/cpus.py
 create mode 100644 scripts/gdb/linux/dmesg.py
 create mode 100644 scripts/gdb/linux/modules.py
 create mode 100644 scripts/gdb/linux/symbols.py
 create mode 100644 scripts/gdb/linux/tasks.py
 create mode 100644 scripts/gdb/linux/utils.py
 create mode 100644 scripts/gdb/vmlinux-gdb.py

-- 
2.1.4


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v12 00/28] Add gdb python scripts as kernel debugging helpers
@ 2015-01-30  7:24 ` Jan Kiszka
  0 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Daniel Thompson, Daniel Wagner,
	David S. Miller, Fenghua Yu, Kay Sievers, linux-doc, linux-ia64,
	linux-kbuild, Michal Marek, Pantelis Koukousoulas, Rob Landley,
	Rusty Russell, sparclinux, Tony Luck

Hi Andrew,

this is an update to address the review comments provided by Michal
Marek on v11.

Changes since v11:
 - drop redundant subdir rule
 - fold *.pyo into existing clean-files rules

See http://lkml.indiana.edu/hypermail/linux/kernel/1210.0/01598.html for
the original description and

    git://git.kiszka.org/linux.git queues/gdb-scripts

for the latest version.

Jan

CC: Daniel Thompson <daniel.thompson@linaro.org>
CC: Daniel Wagner <daniel.wagner@bmw-carit.de>
CC: "David S. Miller" <davem@davemloft.net>
CC: Fenghua Yu <fenghua.yu@intel.com>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
CC: Kay Sievers <kay@vrfy.org>
CC: linux-doc@vger.kernel.org
CC: linux-ia64@vger.kernel.org
Cc: linux-kbuild@vger.kernel.org
CC: linux-kbuild@vger.kernel.org
Cc: Michal Marek <mmarek@suse.cz>
CC: Michal Marek <mmarek@suse.cz>
CC: Pantelis Koukousoulas <pktoss@gmail.com>
CC: Rob Landley <rob@landley.net>
CC: Rusty Russell <rusty@rustcorp.com.au>
CC: sparclinux@vger.kernel.org
CC: Tony Luck <tony.luck@intel.com>

Daniel Thompson (1):
  scripts/gdb: Ignore byte-compiled python files

Daniel Wagner (1):
  scripts/gdb: Use a generator instead of iterator for task list

Jan Kiszka (25):
  scripts/gdb: Add infrastructure
  scripts/gdb: Add cache for type objects
  scripts/gdb: Add container_of helper and convenience function
  scripts/gdb: Add module iteration class
  scripts/gdb: Add lx-symbols command
  module: Do not inline do_init_module
  scripts/gdb: Add automatic symbol reloading on module insertion
  scripts/gdb: Add internal helper and convenience function to look up a
    module
  scripts/gdb: Add get_target_endianness helper
  scripts/gdb: Add read_u16/32/64 helpers
  scripts/gdb: Add lx-dmesg command
  scripts/gdb: Add task iteration class
  scripts/gdb: Add helper and convenience function to look up tasks
  scripts/gdb: Add is_target_arch helper
  scripts/gdb: Add internal helper and convenience function to retrieve
    thread_info
  scripts/gdb: Add get_gdbserver_type helper
  scripts/gdb: Add internal helper and convenience function for per-cpu
    lookup
  scripts/gdb: Add lx_current convenience function
  scripts/gdb: Add class to iterate over CPU masks
  scripts/gdb: Add lx-lsmod command
  scripts/gdb: Add basic documentation
  scripts/gdb: Convert ModuleList to generator function
  scripts/gdb: Convert CpuList to generator function
  scripts/gdb: Define maintainer
  scripts/gdb: Disable pagination while printing from breakpoint handler

Pantelis Koukousoulas (1):
  scripts/gdb: Port to python3 / gdb7.7

 .gitignore                             |   1 +
 Documentation/gdb-kernel-debugging.txt | 160 +++++++++++++++++++++++++++++
 MAINTAINERS                            |   5 +
 Makefile                               |   5 +-
 kernel/module.c                        |   9 +-
 lib/Kconfig.debug                      |  11 ++
 scripts/Makefile                       |   1 +
 scripts/gdb/Makefile                   |   1 +
 scripts/gdb/linux/.gitignore           |   2 +
 scripts/gdb/linux/Makefile             |  11 ++
 scripts/gdb/linux/__init__.py          |   0
 scripts/gdb/linux/cpus.py              | 135 +++++++++++++++++++++++++
 scripts/gdb/linux/dmesg.py             |  65 ++++++++++++
 scripts/gdb/linux/modules.py           | 103 +++++++++++++++++++
 scripts/gdb/linux/symbols.py           | 177 +++++++++++++++++++++++++++++++++
 scripts/gdb/linux/tasks.py             | 100 +++++++++++++++++++
 scripts/gdb/linux/utils.py             | 156 +++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py             |  30 ++++++
 18 files changed, 969 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/gdb-kernel-debugging.txt
 create mode 100644 scripts/gdb/Makefile
 create mode 100644 scripts/gdb/linux/.gitignore
 create mode 100644 scripts/gdb/linux/Makefile
 create mode 100644 scripts/gdb/linux/__init__.py
 create mode 100644 scripts/gdb/linux/cpus.py
 create mode 100644 scripts/gdb/linux/dmesg.py
 create mode 100644 scripts/gdb/linux/modules.py
 create mode 100644 scripts/gdb/linux/symbols.py
 create mode 100644 scripts/gdb/linux/tasks.py
 create mode 100644 scripts/gdb/linux/utils.py
 create mode 100644 scripts/gdb/vmlinux-gdb.py

-- 
2.1.4


^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v12 01/28] scripts/gdb: Add infrastructure
  2015-01-30  7:24 ` Jan Kiszka
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  2015-01-30 10:59   ` Michal Marek
  2015-02-04  6:49   ` [PATCH v13 " Jan Kiszka
  -1 siblings, 2 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Michal Marek, linux-kbuild

This provides the basic infrastructure to load kernel-specific python
helper scripts when debugging the kernel in gdb.

The loading mechanism is based on gdb loading for <objfile>-gdb.py when
opening <objfile>. Therefore, this places a corresponding link to the
main helper script into the output directory that contains vmlinux.

The main scripts will pull in submodules containing Linux specific gdb
commands and functions. To avoid polluting the source directory with
compiled python modules, we link to them from the object directory.

Due to gdb.parse_and_eval and string redirection for gdb.execute, we
depend on gdb >= 7.2.

This feature is enabled via CONFIG_GDB_SCRIPTS.

CC: Michal Marek <mmarek@suse.cz>
CC: linux-kbuild@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 Makefile                      |  5 ++++-
 lib/Kconfig.debug             | 11 +++++++++++
 scripts/Makefile              |  1 +
 scripts/gdb/Makefile          |  1 +
 scripts/gdb/linux/Makefile    | 11 +++++++++++
 scripts/gdb/linux/__init__.py |  0
 scripts/gdb/vmlinux-gdb.py    | 23 +++++++++++++++++++++++
 7 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 scripts/gdb/Makefile
 create mode 100644 scripts/gdb/linux/Makefile
 create mode 100644 scripts/gdb/linux/__init__.py
 create mode 100644 scripts/gdb/vmlinux-gdb.py

diff --git a/Makefile b/Makefile
index 95a0e82..6881ddf 100644
--- a/Makefile
+++ b/Makefile
@@ -922,6 +922,9 @@ endif
 ifdef CONFIG_BUILD_DOCSRC
 	$(Q)$(MAKE) $(build)=Documentation
 endif
+ifdef CONFIG_GDB_SCRIPTS
+	$(Q)ln -fsn `cd $(srctree) && /bin/pwd`/scripts/gdb/vmlinux-gdb.py
+endif
 	+$(call if_changed,link-vmlinux)
 
 # The actual objects are generated when descending,
@@ -1176,7 +1179,7 @@ MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \
 		  Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
 		  signing_key.priv signing_key.x509 x509.genkey		\
 		  extra_certificates signing_key.x509.keyid		\
-		  signing_key.x509.signer
+		  signing_key.x509.signer vmlinux-gdb.py
 
 # clean - Delete most, but leave enough to build external modules
 #
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5f2ce61..74984af 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -167,6 +167,17 @@ config DEBUG_INFO_DWARF4
 	  But it significantly improves the success of resolving
 	  variables in gdb on optimized code.
 
+config GDB_SCRIPTS
+	bool "Provide GDB scripts for kernel debugging"
+	select DEBUG_INFO
+	help
+	  This creates the required links to GDB helper scripts in the
+	  build directory. If you load vmlinux into gdb, the helper
+	  scripts will be automatically imported by gdb as well, and
+	  additional functions are available to analyze a Linux kernel
+	  instance. See Documentation/gdb-kernel-debugging.txt for further
+	  details.
+
 config ENABLE_WARN_DEPRECATED
 	bool "Enable __deprecated logic"
 	default y
diff --git a/scripts/Makefile b/scripts/Makefile
index 72902b5..2016a64 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -36,6 +36,7 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms
 subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
 subdir-$(CONFIG_DTC)         += dtc
+subdir-$(CONFIG_GDB_SCRIPTS) += gdb
 
 # Let clean descend into subdirs
 subdir-	+= basic kconfig package
diff --git a/scripts/gdb/Makefile b/scripts/gdb/Makefile
new file mode 100644
index 0000000..62f5f65
--- /dev/null
+++ b/scripts/gdb/Makefile
@@ -0,0 +1 @@
+subdir-y := linux
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
new file mode 100644
index 0000000..6cf1ecf
--- /dev/null
+++ b/scripts/gdb/linux/Makefile
@@ -0,0 +1,11 @@
+always := gdb-scripts
+
+SRCTREE := $(shell cd $(srctree) && /bin/pwd)
+
+$(obj)/gdb-scripts:
+ifneq ($(KBUILD_SRC),)
+	$(Q)ln -fsn $(SRCTREE)/$(obj)/*.py $(objtree)/$(obj)
+endif
+	@:
+
+clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py)
diff --git a/scripts/gdb/linux/__init__.py b/scripts/gdb/linux/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
new file mode 100644
index 0000000..c1d90ce
--- /dev/null
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -0,0 +1,23 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  loader module
+#
+# Copyright (c) Siemens AG, 2012, 2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import os
+
+sys.path.insert(0, os.path.dirname(__file__) + "/scripts/gdb")
+
+try:
+    gdb.parse_and_eval("0")
+    gdb.execute("", to_string=True)
+except:
+    gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to "
+              "work.\n")
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 02/28] scripts/gdb: Add cache for type objects
  2015-01-30  7:24 ` Jan Kiszka
  (?)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Type lookups are very slow in gdb-python which is often noticeable when
iterating over a number of objects. Introduce the helper class
CachedType that keeps a reference to a gdb.Type object but also
refreshes it after an object file has been loaded.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/utils.py | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)
 create mode 100644 scripts/gdb/linux/utils.py

diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
new file mode 100644
index 0000000..f883611
--- /dev/null
+++ b/scripts/gdb/linux/utils.py
@@ -0,0 +1,34 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  common utilities
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+
+class CachedType:
+    def __init__(self, name):
+        self._type = None
+        self._name = name
+
+    def _new_objfile_handler(self, event):
+        self._type = None
+        gdb.events.new_objfile.disconnect(self._new_objfile_handler)
+
+    def get_type(self):
+        if self._type is None:
+            self._type = gdb.lookup_type(self._name)
+            if self._type is None:
+                raise gdb.GdbError(
+                    "cannot resolve type '{0}'".format(self._name))
+            if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'):
+                gdb.events.new_objfile.connect(self._new_objfile_handler)
+        return self._type
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 03/28] scripts/gdb: Add container_of helper and convenience function
  2015-01-30  7:24 ` Jan Kiszka
                   ` (2 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Provide an internal helper with container_of semantics. As type lookups
are very slow in gdb-python and we need a type "long" for this, cache
the reference to this type object. Then export the helper also as a
convenience function form use at the gdb command line.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/utils.py | 35 +++++++++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py |  2 ++
 2 files changed, 37 insertions(+)

diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index f883611..c9d705b 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -32,3 +32,38 @@ class CachedType:
             if hasattr(gdb, 'events') and hasattr(gdb.events, 'new_objfile'):
                 gdb.events.new_objfile.connect(self._new_objfile_handler)
         return self._type
+
+
+long_type = CachedType("long")
+
+
+def get_long_type():
+    global long_type
+    return long_type.get_type()
+
+
+def offset_of(typeobj, field):
+    element = gdb.Value(0).cast(typeobj)
+    return int(str(element[field].address).split()[0], 16)
+
+
+def container_of(ptr, typeobj, member):
+    return (ptr.cast(get_long_type()) -
+            offset_of(typeobj, member)).cast(typeobj)
+
+
+class ContainerOf(gdb.Function):
+    """Return pointer to containing data structure.
+
+$container_of(PTR, "TYPE", "ELEMENT"): Given PTR, return a pointer to the
+data structure of the type TYPE in which PTR is the address of ELEMENT.
+Note that TYPE and ELEMENT have to be quoted as strings."""
+
+    def __init__(self):
+        super(ContainerOf, self).__init__("container_of")
+
+    def invoke(self, ptr, typename, elementname):
+        return container_of(ptr, gdb.lookup_type(typename.string()).pointer(),
+                            elementname.string())
+
+ContainerOf()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index c1d90ce..6495841 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -21,3 +21,5 @@ try:
 except:
     gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to "
               "work.\n")
+else:
+    import linux.utils
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 04/28] scripts/gdb: Add module iteration class
  2015-01-30  7:24 ` Jan Kiszka
                   ` (3 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Will soon be used for loading symbols, printing global variables or
listing modules.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/modules.py | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
 create mode 100644 scripts/gdb/linux/modules.py

diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
new file mode 100644
index 0000000..8a65c3d
--- /dev/null
+++ b/scripts/gdb/linux/modules.py
@@ -0,0 +1,39 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  module tools
+#
+# Copyright (c) Siemens AG, 2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import utils
+
+
+module_type = utils.CachedType("struct module")
+
+
+class ModuleList:
+    def __init__(self):
+        global module_type
+        self.module_ptr_type = module_type.get_type().pointer()
+        modules = gdb.parse_and_eval("modules")
+        self.curr_entry = modules['next']
+        self.end_of_list = modules.address
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        entry = self.curr_entry
+        if entry != self.end_of_list:
+            self.curr_entry = entry['next']
+            return utils.container_of(entry, self.module_ptr_type, "list")
+        else:
+            raise StopIteration
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 05/28] scripts/gdb: Add lx-symbols command
  2015-01-30  7:24 ` Jan Kiszka
                   ` (4 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This is probably the most useful helper when debugging kernel modules:
lx-symbols first reloads vmlinux. Then it searches recursively for *.ko
files in the specified paths and the current directory. Finally it walks
the kernel's module list, issuing the necessary add-symbol-file command
for each loaded module so that gdb knows which module symbol corresponds
to which address. It also looks up variable sections (bss, data, rodata)
and appends their address to the add-symbole-file command line. This
allows to access global module variables just like any other variable.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/symbols.py | 127 +++++++++++++++++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py   |   1 +
 2 files changed, 128 insertions(+)
 create mode 100644 scripts/gdb/linux/symbols.py

diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
new file mode 100644
index 0000000..bd21a96
--- /dev/null
+++ b/scripts/gdb/linux/symbols.py
@@ -0,0 +1,127 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  load kernel and module symbols
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+import os
+import re
+import string
+
+from linux import modules, utils
+
+
+class LxSymbols(gdb.Command):
+    """(Re-)load symbols of Linux kernel and currently loaded modules.
+
+The kernel (vmlinux) is taken from the current working directly. Modules (.ko)
+are scanned recursively, starting in the same directory. Optionally, the module
+search path can be extended by a space separated list of paths passed to the
+lx-symbols command."""
+
+    module_paths = []
+    module_files = []
+    module_files_updated = False
+
+    def __init__(self):
+        super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
+                                        gdb.COMPLETE_FILENAME)
+
+    def _update_module_files(self):
+        self.module_files = []
+        for path in self.module_paths:
+            gdb.write("scanning for modules in {0}\n".format(path))
+            for root, dirs, files in os.walk(path):
+                for name in files:
+                    if name.endswith(".ko"):
+                        self.module_files.append(root + "/" + name)
+        self.module_files_updated = True
+
+    def _get_module_file(self, module_name):
+        module_pattern = ".*/{0}\.ko$".format(
+            string.replace(module_name, "_", r"[_\-]"))
+        for name in self.module_files:
+            if re.match(module_pattern, name) and os.path.exists(name):
+                return name
+        return None
+
+    def _section_arguments(self, module):
+        try:
+            sect_attrs = module['sect_attrs'].dereference()
+        except gdb.error:
+            return ""
+        attrs = sect_attrs['attrs']
+        section_name_to_address = {
+            attrs[n]['name'].string() : attrs[n]['address']
+            for n in range(sect_attrs['nsections'])}
+        args = []
+        for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
+            address = section_name_to_address.get(section_name)
+            if address:
+                args.append(" -s {name} {addr}".format(
+                    name=section_name, addr=str(address)))
+        return "".join(args)
+
+    def load_module_symbols(self, module):
+        module_name = module['name'].string()
+        module_addr = str(module['module_core']).split()[0]
+
+        module_file = self._get_module_file(module_name)
+        if not module_file and not self.module_files_updated:
+            self._update_module_files()
+            module_file = self._get_module_file(module_name)
+
+        if module_file:
+            gdb.write("loading @{addr}: {filename}\n".format(
+                addr=module_addr, filename=module_file))
+            cmdline = "add-symbol-file {filename} {addr}{sections}".format(
+                filename=module_file,
+                addr=module_addr,
+                sections=self._section_arguments(module))
+            gdb.execute(cmdline, to_string=True)
+        else:
+            gdb.write("no module object found for '{0}'\n".format(module_name))
+
+    def load_all_symbols(self):
+        gdb.write("loading vmlinux\n")
+
+        # Dropping symbols will disable all breakpoints. So save their states
+        # and restore them afterward.
+        saved_states = []
+        if hasattr(gdb, 'breakpoints') and not gdb.breakpoints() is None:
+            for bp in gdb.breakpoints():
+                saved_states.append({'breakpoint': bp, 'enabled': bp.enabled})
+
+        # drop all current symbols and reload vmlinux
+        gdb.execute("symbol-file", to_string=True)
+        gdb.execute("symbol-file vmlinux")
+
+        module_list = modules.ModuleList()
+        if not module_list:
+            gdb.write("no modules found\n")
+        else:
+            [self.load_module_symbols(module) for module in module_list]
+
+        for saved_state in saved_states:
+            saved_state['breakpoint'].enabled = saved_state['enabled']
+
+    def invoke(self, arg, from_tty):
+        self.module_paths = arg.split()
+        self.module_paths.append(os.getcwd())
+
+        # enforce update
+        self.module_files = []
+        self.module_files_updated = False
+
+        self.load_all_symbols()
+
+
+LxSymbols()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 6495841..0b0faa4 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -23,3 +23,4 @@ except:
               "work.\n")
 else:
     import linux.utils
+    import linux.symbols
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 06/28] module: Do not inline do_init_module
  2015-01-30  7:24 ` Jan Kiszka
                   ` (5 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  2015-02-10 23:59   ` Rusty Russell
  -1 siblings, 1 reply; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Rusty Russell

This provides a reliable breakpoint target, required for automatic
symbol loading via the gdb helper command 'lx-symbols'.

CC: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 kernel/module.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/kernel/module.c b/kernel/module.c
index d856e96..2df6cec 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3011,8 +3011,13 @@ static void do_free_init(struct rcu_head *head)
 	kfree(m);
 }
 
-/* This is where the real work happens */
-static int do_init_module(struct module *mod)
+/*
+ * This is where the real work happens.
+ *
+ * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb
+ * helper command 'lx-symbols'.
+ */
+static noinline int do_init_module(struct module *mod)
 {
 	int ret = 0;
 	struct mod_initfree *freeinit;
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 07/28] scripts/gdb: Add automatic symbol reloading on module insertion
  2015-01-30  7:24 ` Jan Kiszka
                   ` (6 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This installs a silent breakpoint on the do_init_module function. The
breakpoint handler will try to load symbols from the module files found
during lx-symbols execution. This way, breakpoints can be set to module
initialization functions, and there is no need to explicitly call
lx-symbols after (re-)loading a module.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/symbols.py | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index bd21a96..139841f 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -19,6 +19,30 @@ import string
 from linux import modules, utils
 
 
+if hasattr(gdb, 'Breakpoint'):
+    class LoadModuleBreakpoint(gdb.Breakpoint):
+        def __init__(self, spec, gdb_command):
+            super(LoadModuleBreakpoint, self).__init__(spec, internal=True)
+            self.silent = True
+            self.gdb_command = gdb_command
+
+        def stop(self):
+            module = gdb.parse_and_eval("mod")
+            module_name = module['name'].string()
+            cmd = self.gdb_command
+
+            # enforce update if object file is not found
+            cmd.module_files_updated = False
+
+            if module_name in cmd.loaded_modules:
+                gdb.write("refreshing all symbols to reload module "
+                          "'{0}'\n".format(module_name))
+                cmd.load_all_symbols()
+            else:
+                cmd.load_module_symbols(module)
+            return False
+
+
 class LxSymbols(gdb.Command):
     """(Re-)load symbols of Linux kernel and currently loaded modules.
 
@@ -30,6 +54,8 @@ lx-symbols command."""
     module_paths = []
     module_files = []
     module_files_updated = False
+    loaded_modules = []
+    breakpoint = None
 
     def __init__(self):
         super(LxSymbols, self).__init__("lx-symbols", gdb.COMMAND_FILES,
@@ -87,6 +113,8 @@ lx-symbols command."""
                 addr=module_addr,
                 sections=self._section_arguments(module))
             gdb.execute(cmdline, to_string=True)
+            if not module_name in self.loaded_modules:
+                self.loaded_modules.append(module_name)
         else:
             gdb.write("no module object found for '{0}'\n".format(module_name))
 
@@ -104,6 +132,7 @@ lx-symbols command."""
         gdb.execute("symbol-file", to_string=True)
         gdb.execute("symbol-file vmlinux")
 
+        self.loaded_modules = []
         module_list = modules.ModuleList()
         if not module_list:
             gdb.write("no modules found\n")
@@ -123,5 +152,15 @@ lx-symbols command."""
 
         self.load_all_symbols()
 
+        if hasattr(gdb, 'Breakpoint'):
+            if not self.breakpoint is None:
+                self.breakpoint.delete()
+                self.breakpoint = None
+            self.breakpoint = LoadModuleBreakpoint(
+                "kernel/module.c:do_init_module", self)
+        else:
+            gdb.write("Note: symbol update on module loading not supported "
+                      "with this gdb version\n")
+
 
 LxSymbols()
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 08/28] scripts/gdb: Add internal helper and convenience function to look up a module
  2015-01-30  7:24 ` Jan Kiszka
                   ` (7 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Add the internal helper get_module_by_name to obtain the module
structure corresponding to the given name. Also export this service as a
convenience function.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/modules.py | 28 ++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py   |  1 +
 2 files changed, 29 insertions(+)

diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 8a65c3d..531f763 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -37,3 +37,31 @@ class ModuleList:
             return utils.container_of(entry, self.module_ptr_type, "list")
         else:
             raise StopIteration
+
+
+def find_module_by_name(name):
+    for module in ModuleList():
+        if module['name'].string() == name:
+            return module
+    return None
+
+
+class LxModule(gdb.Function):
+    """Find module by name and return the module variable.
+
+$lx_module("MODULE"): Given the name MODULE, iterate over all loaded modules
+of the target and return that module variable which MODULE matches."""
+
+    def __init__(self):
+        super(LxModule, self).__init__("lx_module")
+
+    def invoke(self, mod_name):
+        mod_name = mod_name.string()
+        module = find_module_by_name(mod_name)
+        if module:
+            return module.dereference()
+        else:
+            raise gdb.GdbError("Unable to find MODULE " + mod_name)
+
+
+LxModule()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 0b0faa4..cf2e716 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -24,3 +24,4 @@ except:
 else:
     import linux.utils
     import linux.symbols
+    import linux.modules
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 09/28] scripts/gdb: Add get_target_endianness helper
  2015-01-30  7:24 ` Jan Kiszka
                   ` (8 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Parse the target endianness from the output of "show endian" and cache
the result to return it via the new helper get_target_endiannes. We will
need it for reading integers from buffers that contain target memory.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/utils.py | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index c9d705b..10a227b 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -67,3 +67,21 @@ Note that TYPE and ELEMENT have to be quoted as strings."""
                             elementname.string())
 
 ContainerOf()
+
+
+BIG_ENDIAN = 0
+LITTLE_ENDIAN = 1
+target_endianness = None
+
+
+def get_target_endianness():
+    global target_endianness
+    if target_endianness is None:
+        endian = gdb.execute("show endian", to_string=True)
+        if "little endian" in endian:
+            target_endianness = LITTLE_ENDIAN
+        elif "big endian" in endian:
+            target_endianness = BIG_ENDIAN
+        else:
+            raise gdb.GdgError("unknown endianness '{0}'".format(endian))
+    return target_endianness
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 10/28] scripts/gdb: Add read_u16/32/64 helpers
  2015-01-30  7:24 ` Jan Kiszka
                   ` (9 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Add helpers for reading integers from target memory buffers. Required
when caching the memory access is more efficient than reading individual
values via gdb.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/utils.py | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 10a227b..808a265 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -85,3 +85,24 @@ def get_target_endianness():
         else:
             raise gdb.GdgError("unknown endianness '{0}'".format(endian))
     return target_endianness
+
+
+def read_u16(buffer):
+    if get_target_endianness() == LITTLE_ENDIAN:
+        return ord(buffer[0]) + (ord(buffer[1]) << 8)
+    else:
+        return ord(buffer[1]) + (ord(buffer[0]) << 8)
+
+
+def read_u32(buffer):
+    if get_target_endianness() == LITTLE_ENDIAN:
+        return read_u16(buffer[0:2]) + (read_u16(buffer[2:4]) << 16)
+    else:
+        return read_u16(buffer[2:4]) + (read_u16(buffer[0:2]) << 16)
+
+
+def read_u64(buffer):
+    if get_target_endianness() == LITTLE_ENDIAN:
+        return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32)
+    else:
+        return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32)
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 11/28] scripts/gdb: Add lx-dmesg command
  2015-01-30  7:24 ` Jan Kiszka
                   ` (10 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Kay Sievers

This pokes into the log buffer of the debugged kernel, dumping it to the
gdb console. Helping in case the target should or can no longer execute
dmesg itself.

CC: Kay Sievers <kay@vrfy.org>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/dmesg.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py |  1 +
 2 files changed, 65 insertions(+)
 create mode 100644 scripts/gdb/linux/dmesg.py

diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py
new file mode 100644
index 0000000..7650f24
--- /dev/null
+++ b/scripts/gdb/linux/dmesg.py
@@ -0,0 +1,64 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  kernel log buffer dump
+#
+# Copyright (c) Siemens AG, 2011, 2012
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+import string
+
+from linux import utils
+
+
+class LxDmesg(gdb.Command):
+    """Print Linux kernel log buffer."""
+
+    def __init__(self):
+        super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        log_buf_addr = int(str(gdb.parse_and_eval("log_buf")).split()[0], 16)
+        log_first_idx = int(gdb.parse_and_eval("log_first_idx"))
+        log_next_idx = int(gdb.parse_and_eval("log_next_idx"))
+        log_buf_len = int(gdb.parse_and_eval("log_buf_len"))
+
+        inf = gdb.inferiors()[0]
+        start = log_buf_addr + log_first_idx
+        if log_first_idx < log_next_idx:
+            log_buf_2nd_half = -1
+            length = log_next_idx - log_first_idx
+            log_buf = inf.read_memory(start, length)
+        else:
+            log_buf_2nd_half = log_buf_len - log_first_idx
+            log_buf = inf.read_memory(start, log_buf_2nd_half) + \
+                inf.read_memory(log_buf_addr, log_next_idx)
+
+        pos = 0
+        while pos < log_buf.__len__():
+            length = utils.read_u16(log_buf[pos + 8:pos + 10])
+            if length == 0:
+                if log_buf_2nd_half == -1:
+                    gdb.write("Corrupted log buffer!\n")
+                    break
+                pos = log_buf_2nd_half
+                continue
+
+            text_len = utils.read_u16(log_buf[pos + 10:pos + 12])
+            time_stamp = utils.read_u64(log_buf[pos:pos + 8])
+
+            for line in log_buf[pos + 16:pos + 16 + text_len].splitlines():
+                gdb.write("[{time:12.6f}] {line}\n".format(
+                    time=time_stamp / 1000000000.0,
+                    line=line))
+
+            pos += length
+
+
+LxDmesg()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index cf2e716..fa66d23 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -25,3 +25,4 @@ else:
     import linux.utils
     import linux.symbols
     import linux.modules
+    import linux.dmesg
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 12/28] scripts/gdb: Add task iteration class
  2015-01-30  7:24 ` Jan Kiszka
                   ` (11 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This class allows to iterate over all tasks of the target.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/tasks.py | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)
 create mode 100644 scripts/gdb/linux/tasks.py

diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
new file mode 100644
index 0000000..cd25984
--- /dev/null
+++ b/scripts/gdb/linux/tasks.py
@@ -0,0 +1,46 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  task & thread tools
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import utils
+
+
+task_type = utils.CachedType("struct task_struct")
+
+
+class TaskList:
+    def __init__(self):
+        global task_type
+        self.task_ptr_type = task_type.get_type().pointer()
+        self.init_task = gdb.parse_and_eval("init_task")
+        self.curr_group = self.init_task.address
+        self.curr_task = None
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        t = self.curr_task
+        if not t or t == self.curr_group:
+            self.curr_group = \
+                utils.container_of(self.curr_group['tasks']['next'],
+                                   self.task_ptr_type, "tasks")
+            if self.curr_group == self.init_task.address:
+                raise StopIteration
+            t = self.curr_task = self.curr_group
+        else:
+            self.curr_task = \
+                utils.container_of(t['thread_group']['next'],
+                                   self.task_ptr_type, "thread_group")
+        return t
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 13/28] scripts/gdb: Add helper and convenience function to look up tasks
  2015-01-30  7:24 ` Jan Kiszka
                   ` (12 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Add the helper task_by_pid that can look up a task by its PID. Also
export it as a convenience function.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/tasks.py | 27 +++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py |  1 +
 2 files changed, 28 insertions(+)

diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index cd25984..13bb97c 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -44,3 +44,30 @@ class TaskList:
                 utils.container_of(t['thread_group']['next'],
                                    self.task_ptr_type, "thread_group")
         return t
+
+
+def get_task_by_pid(pid):
+    for task in TaskList():
+        if int(task['pid']) == pid:
+            return task
+    return None
+
+
+class LxTaskByPidFunc(gdb.Function):
+    """Find Linux task by PID and return the task_struct variable.
+
+$lx_task_by_pid(PID): Given PID, iterate over all tasks of the target and
+return that task_struct variable which PID matches."""
+
+    def __init__(self):
+        super(LxTaskByPidFunc, self).__init__("lx_task_by_pid")
+
+    def invoke(self, pid):
+        task = get_task_by_pid(pid)
+        if task:
+            return task.dereference()
+        else:
+            raise gdb.GdbError("No task of PID " + str(pid))
+
+
+LxTaskByPidFunc()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index fa66d23..4d7eb2c 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -26,3 +26,4 @@ else:
     import linux.symbols
     import linux.modules
     import linux.dmesg
+    import linux.tasks
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 14/28] scripts/gdb: Add is_target_arch helper
  2015-01-30  7:24 ` Jan Kiszka
                   ` (13 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This helper caches to result of "show architecture" and matches the
provided arch (sub-)string against that output.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/utils.py | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 808a265..71ee48c 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -106,3 +106,16 @@ def read_u64(buffer):
         return read_u32(buffer[0:4]) + (read_u32(buffer[4:8]) << 32)
     else:
         return read_u32(buffer[4:8]) + (read_u32(buffer[0:4]) << 32)
+
+
+target_arch = None
+
+
+def is_target_arch(arch):
+    if hasattr(gdb.Frame, 'architecture'):
+        return arch in gdb.newest_frame().architecture().name()
+    else:
+        global target_arch
+        if target_arch is None:
+            target_arch = gdb.execute("show architecture", to_string=True)
+        return arch in target_arch
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 15/28] scripts/gdb: Add internal helper and convenience function to retrieve thread_info
  2015-01-30  7:24 ` Jan Kiszka
@ 2015-01-30  7:24   ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Tony Luck, Fenghua Yu, linux-ia64

Add the internal helper get_thread_info that calculates the thread_info
from a given task variable. Also export this service as a convenience
function.

Note: ia64 version is untested.

CC: Tony Luck <tony.luck@intel.com>
CC: Fenghua Yu <fenghua.yu@intel.com>
CC: linux-ia64@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/tasks.py | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index 13bb97c..63cd6c5 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -71,3 +71,38 @@ return that task_struct variable which PID matches."""
 
 
 LxTaskByPidFunc()
+
+
+thread_info_type = utils.CachedType("struct thread_info")
+
+ia64_task_size = None
+
+
+def get_thread_info(task):
+    global thread_info_type
+    thread_info_ptr_type = thread_info_type.get_type().pointer()
+    if utils.is_target_arch("ia64"):
+        global ia64_task_size
+        if ia64_task_size is None:
+            ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
+        thread_info_addr = task.address + ia64_task_size
+        thread_info = thread_info_addr.cast(thread_info_ptr_type)
+    else:
+        thread_info = task['stack'].cast(thread_info_ptr_type)
+    return thread_info.dereference()
+
+
+class LxThreadInfoFunc (gdb.Function):
+    """Calculate Linux thread_info from task variable.
+
+$lx_thread_info(TASK): Given TASK, return the corresponding thread_info
+variable."""
+
+    def __init__(self):
+        super(LxThreadInfoFunc, self).__init__("lx_thread_info")
+
+    def invoke(self, task):
+        return get_thread_info(task)
+
+
+LxThreadInfoFunc()
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 15/28] scripts/gdb: Add internal helper and convenience function to retrieve thread_info
@ 2015-01-30  7:24   ` Jan Kiszka
  0 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Tony Luck, Fenghua Yu, linux-ia64

Add the internal helper get_thread_info that calculates the thread_info
from a given task variable. Also export this service as a convenience
function.

Note: ia64 version is untested.

CC: Tony Luck <tony.luck@intel.com>
CC: Fenghua Yu <fenghua.yu@intel.com>
CC: linux-ia64@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/tasks.py | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index 13bb97c..63cd6c5 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -71,3 +71,38 @@ return that task_struct variable which PID matches."""
 
 
 LxTaskByPidFunc()
+
+
+thread_info_type = utils.CachedType("struct thread_info")
+
+ia64_task_size = None
+
+
+def get_thread_info(task):
+    global thread_info_type
+    thread_info_ptr_type = thread_info_type.get_type().pointer()
+    if utils.is_target_arch("ia64"):
+        global ia64_task_size
+        if ia64_task_size is None:
+            ia64_task_size = gdb.parse_and_eval("sizeof(struct task_struct)")
+        thread_info_addr = task.address + ia64_task_size
+        thread_info = thread_info_addr.cast(thread_info_ptr_type)
+    else:
+        thread_info = task['stack'].cast(thread_info_ptr_type)
+    return thread_info.dereference()
+
+
+class LxThreadInfoFunc (gdb.Function):
+    """Calculate Linux thread_info from task variable.
+
+$lx_thread_info(TASK): Given TASK, return the corresponding thread_info
+variable."""
+
+    def __init__(self):
+        super(LxThreadInfoFunc, self).__init__("lx_thread_info")
+
+    def invoke(self, task):
+        return get_thread_info(task)
+
+
+LxThreadInfoFunc()
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 16/28] scripts/gdb: Add get_gdbserver_type helper
  2015-01-30  7:24 ` Jan Kiszka
                   ` (15 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This helper probes the type of the gdb server. Supported are QEMU and
KGDB so far. Knowledge about the gdb server is required e.g. to retrieve
the current CPU or current task.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/utils.py | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 71ee48c..a4a1640 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -119,3 +119,38 @@ def is_target_arch(arch):
         if target_arch is None:
             target_arch = gdb.execute("show architecture", to_string=True)
         return arch in target_arch
+
+
+GDBSERVER_QEMU = 0
+GDBSERVER_KGDB = 1
+gdbserver_type = None
+
+
+def get_gdbserver_type():
+    def exit_handler(event):
+        global gdbserver_type
+        gdbserver_type = None
+        gdb.events.exited.disconnect(exit_handler)
+
+    def probe_qemu():
+        try:
+            return gdb.execute("monitor info version", to_string=True) != ""
+        except:
+            return False
+
+    def probe_kgdb():
+        try:
+            thread_info = gdb.execute("info thread 2", to_string=True)
+            return "shadowCPU0" in thread_info
+        except:
+            return False
+
+    global gdbserver_type
+    if gdbserver_type is None:
+        if probe_qemu():
+            gdbserver_type = GDBSERVER_QEMU
+        elif probe_kgdb():
+            gdbserver_type = GDBSERVER_KGDB
+        if not gdbserver_type is None and hasattr(gdb, 'events'):
+            gdb.events.exited.connect(exit_handler)
+    return gdbserver_type
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 17/28] scripts/gdb: Add internal helper and convenience function for per-cpu lookup
  2015-01-30  7:24 ` Jan Kiszka
@ 2015-01-30  7:24   ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, David S. Miller, sparclinux

This function allows to obtain a per-cpu variable, either of the current
or an explicitly specified CPU.

Note: sparc64 version is untested.

CC: "David S. Miller" <davem@davemloft.net>
CC: sparclinux@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/cpus.py  | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py |  1 +
 2 files changed, 69 insertions(+)
 create mode 100644 scripts/gdb/linux/cpus.py

diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
new file mode 100644
index 0000000..18337e0
--- /dev/null
+++ b/scripts/gdb/linux/cpus.py
@@ -0,0 +1,68 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  per-cpu tools
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import tasks, utils
+
+
+MAX_CPUS = 4096
+
+
+def get_current_cpu():
+    if utils.get_gdbserver_type() == utils.GDBSERVER_QEMU:
+        return gdb.selected_thread().num - 1
+    elif utils.get_gdbserver_type() == utils.GDBSERVER_KGDB:
+        tid = gdb.selected_thread().ptid[2]
+        if tid > (0x100000000 - MAX_CPUS - 2):
+            return 0x100000000 - tid - 2
+        else:
+            return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
+    else:
+        raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
+                           "supported with this gdb server.")
+
+
+def per_cpu(var_ptr, cpu):
+    if cpu == -1:
+        cpu = get_current_cpu()
+    if utils.is_target_arch("sparc:v9"):
+        offset = gdb.parse_and_eval(
+            "trap_block[{0}].__per_cpu_base".format(str(cpu)))
+    else:
+        try:
+            offset = gdb.parse_and_eval(
+                "__per_cpu_offset[{0}]".format(str(cpu)))
+        except gdb.error:
+            # !CONFIG_SMP case
+            offset = 0
+    pointer = var_ptr.cast(utils.get_long_type()) + offset
+    return pointer.cast(var_ptr.type).dereference()
+
+
+class PerCpu(gdb.Function):
+    """Return per-cpu variable.
+
+$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
+given CPU number. If CPU is omitted, the CPU of the current context is used.
+Note that VAR has to be quoted as string."""
+
+    def __init__(self):
+        super(PerCpu, self).__init__("lx_per_cpu")
+
+    def invoke(self, var_name, cpu=-1):
+        var_ptr = gdb.parse_and_eval("&" + var_name.string())
+        return per_cpu(var_ptr, cpu)
+
+
+PerCpu()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 4d7eb2c..4848928 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -27,3 +27,4 @@ else:
     import linux.modules
     import linux.dmesg
     import linux.tasks
+    import linux.cpus
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 17/28] scripts/gdb: Add internal helper and convenience function for per-cpu lookup
@ 2015-01-30  7:24   ` Jan Kiszka
  0 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, David S. Miller, sparclinux

This function allows to obtain a per-cpu variable, either of the current
or an explicitly specified CPU.

Note: sparc64 version is untested.

CC: "David S. Miller" <davem@davemloft.net>
CC: sparclinux@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/cpus.py  | 68 ++++++++++++++++++++++++++++++++++++++++++++++
 scripts/gdb/vmlinux-gdb.py |  1 +
 2 files changed, 69 insertions(+)
 create mode 100644 scripts/gdb/linux/cpus.py

diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
new file mode 100644
index 0000000..18337e0
--- /dev/null
+++ b/scripts/gdb/linux/cpus.py
@@ -0,0 +1,68 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  per-cpu tools
+#
+# Copyright (c) Siemens AG, 2011-2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import gdb
+
+from linux import tasks, utils
+
+
+MAX_CPUS = 4096
+
+
+def get_current_cpu():
+    if utils.get_gdbserver_type() = utils.GDBSERVER_QEMU:
+        return gdb.selected_thread().num - 1
+    elif utils.get_gdbserver_type() = utils.GDBSERVER_KGDB:
+        tid = gdb.selected_thread().ptid[2]
+        if tid > (0x100000000 - MAX_CPUS - 2):
+            return 0x100000000 - tid - 2
+        else:
+            return tasks.get_thread_info(tasks.get_task_by_pid(tid))['cpu']
+    else:
+        raise gdb.GdbError("Sorry, obtaining the current CPU is not yet "
+                           "supported with this gdb server.")
+
+
+def per_cpu(var_ptr, cpu):
+    if cpu = -1:
+        cpu = get_current_cpu()
+    if utils.is_target_arch("sparc:v9"):
+        offset = gdb.parse_and_eval(
+            "trap_block[{0}].__per_cpu_base".format(str(cpu)))
+    else:
+        try:
+            offset = gdb.parse_and_eval(
+                "__per_cpu_offset[{0}]".format(str(cpu)))
+        except gdb.error:
+            # !CONFIG_SMP case
+            offset = 0
+    pointer = var_ptr.cast(utils.get_long_type()) + offset
+    return pointer.cast(var_ptr.type).dereference()
+
+
+class PerCpu(gdb.Function):
+    """Return per-cpu variable.
+
+$lx_per_cpu("VAR"[, CPU]): Return the per-cpu variable called VAR for the
+given CPU number. If CPU is omitted, the CPU of the current context is used.
+Note that VAR has to be quoted as string."""
+
+    def __init__(self):
+        super(PerCpu, self).__init__("lx_per_cpu")
+
+    def invoke(self, var_name, cpu=-1):
+        var_ptr = gdb.parse_and_eval("&" + var_name.string())
+        return per_cpu(var_ptr, cpu)
+
+
+PerCpu()
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index 4d7eb2c..4848928 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -27,3 +27,4 @@ else:
     import linux.modules
     import linux.dmesg
     import linux.tasks
+    import linux.cpus
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 18/28] scripts/gdb: Add lx_current convenience function
  2015-01-30  7:24 ` Jan Kiszka
                   ` (17 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This is a shorthand for *$lx_per_cpu("current_task"), i.e. a convenience
function to retrieve the currently running task of the active context.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/cpus.py | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index 18337e0..b683da9 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -66,3 +66,20 @@ Note that VAR has to be quoted as string."""
 
 
 PerCpu()
+
+
+class LxCurrentFunc(gdb.Function):
+    """Return current task.
+
+$lx_current([CPU]): Return the per-cpu task variable for the given CPU
+number. If CPU is omitted, the CPU of the current context is used."""
+
+    def __init__(self):
+        super(LxCurrentFunc, self).__init__("lx_current")
+
+    def invoke(self, cpu=-1):
+        var_ptr = gdb.parse_and_eval("&current_task")
+        return per_cpu(var_ptr, cpu).dereference()
+
+
+LxCurrentFunc()
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 19/28] scripts/gdb: Add class to iterate over CPU masks
  2015-01-30  7:24 ` Jan Kiszka
                   ` (18 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Will be used first to count module references. It is optimized to read
the mask only once per stop.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/cpus.py | 54 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 54 insertions(+)

diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index b683da9..c1441f2 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -50,6 +50,60 @@ def per_cpu(var_ptr, cpu):
     return pointer.cast(var_ptr.type).dereference()
 
 
+cpu_mask = {}
+
+
+def cpu_mask_invalidate(event):
+    global cpu_mask
+    cpu_mask = {}
+    gdb.events.stop.disconnect(cpu_mask_invalidate)
+    if hasattr(gdb.events, 'new_objfile'):
+        gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
+
+
+class CpuList():
+    def __init__(self, mask_name):
+        global cpu_mask
+        self.mask = None
+        if mask_name in cpu_mask:
+            self.mask = cpu_mask[mask_name]
+        if self.mask is None:
+            self.mask = gdb.parse_and_eval(mask_name + ".bits")
+            if hasattr(gdb, 'events'):
+                cpu_mask[mask_name] = self.mask
+                gdb.events.stop.connect(cpu_mask_invalidate)
+                if hasattr(gdb.events, 'new_objfile'):
+                    gdb.events.new_objfile.connect(cpu_mask_invalidate)
+        self.bits_per_entry = self.mask[0].type.sizeof * 8
+        self.num_entries = self.mask.type.sizeof * 8 / self.bits_per_entry
+        self.entry = -1
+        self.bits = 0
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        while self.bits == 0:
+            self.entry += 1
+            if self.entry == self.num_entries:
+                raise StopIteration
+            self.bits = self.mask[self.entry]
+            if self.bits != 0:
+                self.bit = 0
+                break
+
+        while self.bits & 1 == 0:
+            self.bits >>= 1
+            self.bit += 1
+
+        cpu = self.entry * self.bits_per_entry + self.bit
+
+        self.bits >>= 1
+        self.bit += 1
+
+        return cpu
+
+
 class PerCpu(gdb.Function):
     """Return per-cpu variable.
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 20/28] scripts/gdb: Add lx-lsmod command
  2015-01-30  7:24 ` Jan Kiszka
                   ` (19 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

This adds a lsmod-like command to list all currently loaded modules of
the target.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/modules.py | 46 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 531f763..e7c99e9 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -13,7 +13,7 @@
 
 import gdb
 
-from linux import utils
+from linux import cpus, utils
 
 
 module_type = utils.CachedType("struct module")
@@ -65,3 +65,47 @@ of the target and return that module variable which MODULE matches."""
 
 
 LxModule()
+
+
+class LxLsmod(gdb.Command):
+    """List currently loaded modules."""
+
+    _module_use_type = utils.CachedType("struct module_use")
+
+    def __init__(self):
+        super(LxLsmod, self).__init__("lx-lsmod", gdb.COMMAND_DATA)
+
+    def invoke(self, arg, from_tty):
+        gdb.write(
+            "Address{0}    Module                  Size  Used by\n".format(
+                "        " if utils.get_long_type().sizeof == 8 else ""))
+
+        for module in ModuleList():
+            ref = 0
+            module_refptr = module['refptr']
+            for cpu in cpus.CpuList("cpu_possible_mask"):
+                refptr = cpus.per_cpu(module_refptr, cpu)
+                ref += refptr['incs']
+                ref -= refptr['decs']
+
+            gdb.write("{address} {name:<19} {size:>8}  {ref}".format(
+                address=str(module['module_core']).split()[0],
+                name=module['name'].string(),
+                size=module['core_size'],
+                ref=ref))
+
+            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")
+                gdb.write("{separator}{name}".format(
+                    separator=" " if first else ",",
+                    name=use['source']['name'].string()))
+                first = False
+                entry = entry['next']
+            gdb.write("\n")
+
+
+LxLsmod()
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 21/28] scripts/gdb: Add basic documentation
  2015-01-30  7:24 ` Jan Kiszka
                   ` (20 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Rob Landley, linux-doc

CC: Rob Landley <rob@landley.net>
CC: linux-doc@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 Documentation/gdb-kernel-debugging.txt | 160 +++++++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)
 create mode 100644 Documentation/gdb-kernel-debugging.txt

diff --git a/Documentation/gdb-kernel-debugging.txt b/Documentation/gdb-kernel-debugging.txt
new file mode 100644
index 0000000..7050ce8
--- /dev/null
+++ b/Documentation/gdb-kernel-debugging.txt
@@ -0,0 +1,160 @@
+Debugging kernel and modules via gdb
+====================================
+
+The kernel debugger kgdb, hypervisors like QEMU or JTAG-based hardware
+interfaces allow to debug the Linux kernel and its modules during runtime
+using gdb. Gdb comes with a powerful scripting interface for python. The
+kernel provides a collection of helper scripts that can simplify typical
+kernel debugging steps. This is a short tutorial about how to enable and use
+them. It focuses on QEMU/KVM virtual machines as target, but the examples can
+be transferred to the other gdb stubs as well.
+
+
+Requirements
+------------
+
+ o gdb 7.2+ (recommended: 7.4+) with python support enabled (typically true
+   for distributions)
+
+
+Setup
+-----
+
+ o Create a virtual Linux machine for QEMU/KVM (see www.linux-kvm.org and
+   www.qemu.org for more details). For cross-development,
+   http://landley.net/aboriginal/bin keeps a pool of machine images and
+   toolchains that can be helpful to start from.
+
+ o Build the kernel with CONFIG_GDB_SCRIPTS enabled, but leave
+   CONFIG_DEBUG_INFO_REDUCED off. If your architecture supports
+   CONFIG_FRAME_POINTER, keep it enabled.
+
+ o Install that kernel on the guest.
+
+   Alternatively, QEMU allows to boot the kernel directly using -kernel,
+   -append, -initrd command line switches. This is generally only useful if
+   you do not depend on modules. See QEMU documentation for more details on
+   this mode.
+
+ o Enable the gdb stub of QEMU/KVM, either
+    - at VM startup time by appending "-s" to the QEMU command line
+   or
+    - during runtime by issuing "gdbserver" from the QEMU monitor
+      console
+
+ o cd /path/to/linux-build
+
+ o Start gdb: gdb vmlinux
+
+   Note: Some distros may restrict auto-loading of gdb scripts to known safe
+   directories. In case gdb reports to refuse loading vmlinux-gdb.py, add
+
+    add-auto-load-safe-path /path/to/linux-build
+
+   to ~/.gdbinit. See gdb help for more details.
+
+ o Attach to the booted guest:
+    (gdb) target remote :1234
+
+
+Examples of using the Linux-provided gdb helpers
+------------------------------------------------
+
+ o Load module (and main kernel) symbols:
+    (gdb) lx-symbols
+    loading vmlinux
+    scanning for modules in /home/user/linux/build
+    loading @0xffffffffa0020000: /home/user/linux/build/net/netfilter/xt_tcpudp.ko
+    loading @0xffffffffa0016000: /home/user/linux/build/net/netfilter/xt_pkttype.ko
+    loading @0xffffffffa0002000: /home/user/linux/build/net/netfilter/xt_limit.ko
+    loading @0xffffffffa00ca000: /home/user/linux/build/net/packet/af_packet.ko
+    loading @0xffffffffa003c000: /home/user/linux/build/fs/fuse/fuse.ko
+    ...
+    loading @0xffffffffa0000000: /home/user/linux/build/drivers/ata/ata_generic.ko
+
+ o Set a breakpoint on some not yet loaded module function, e.g.:
+    (gdb) b btrfs_init_sysfs
+    Function "btrfs_init_sysfs" not defined.
+    Make breakpoint pending on future shared library load? (y or [n]) y
+    Breakpoint 1 (btrfs_init_sysfs) pending.
+
+ o Continue the target
+    (gdb) c
+
+ o Load the module on the target and watch the symbols being loaded as well as
+   the breakpoint hit:
+    loading @0xffffffffa0034000: /home/user/linux/build/lib/libcrc32c.ko
+    loading @0xffffffffa0050000: /home/user/linux/build/lib/lzo/lzo_compress.ko
+    loading @0xffffffffa006e000: /home/user/linux/build/lib/zlib_deflate/zlib_deflate.ko
+    loading @0xffffffffa01b1000: /home/user/linux/build/fs/btrfs/btrfs.ko
+
+    Breakpoint 1, btrfs_init_sysfs () at /home/user/linux/fs/btrfs/sysfs.c:36
+    36              btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
+
+ o Dump the log buffer of the target kernel:
+    (gdb) lx-dmesg
+    [     0.000000] Initializing cgroup subsys cpuset
+    [     0.000000] Initializing cgroup subsys cpu
+    [     0.000000] Linux version 3.8.0-rc4-dbg+ (...
+    [     0.000000] Command line: root=/dev/sda2 resume=/dev/sda1 vga=0x314
+    [     0.000000] e820: BIOS-provided physical RAM map:
+    [     0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
+    [     0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
+    ....
+
+ o Examine fields of the current task struct:
+    (gdb) p $lx_current().pid
+    $1 = 4998
+    (gdb) p $lx_current().comm
+    $2 = "modprobe\000\000\000\000\000\000\000"
+
+ o Make use of the per-cpu function for the current or a specified CPU:
+    (gdb) p $lx_per_cpu("runqueues").nr_running
+    $3 = 1
+    (gdb) p $lx_per_cpu("runqueues", 2).nr_running
+    $4 = 0
+
+ o Dig into hrtimers using the container_of helper:
+    (gdb) set $next = $lx_per_cpu("hrtimer_bases").clock_base[0].active.next
+    (gdb) p *$container_of($next, "struct hrtimer", "node")
+    $5 = {
+      node = {
+        node = {
+          __rb_parent_color = 18446612133355256072,
+          rb_right = 0x0 <irq_stack_union>,
+          rb_left = 0x0 <irq_stack_union>
+        },
+        expires = {
+          tv64 = 1835268000000
+        }
+      },
+      _softexpires = {
+        tv64 = 1835268000000
+      },
+      function = 0xffffffff81078232 <tick_sched_timer>,
+      base = 0xffff88003fd0d6f0,
+      state = 1,
+      start_pid = 0,
+      start_site = 0xffffffff81055c1f <hrtimer_start_range_ns+20>,
+      start_comm = "swapper/2\000\000\000\000\000\000"
+    }
+
+
+List of commands and functions
+------------------------------
+
+The number of commands and convenience functions may evolve over the time,
+this is just a snapshot of the initial version:
+
+ (gdb) apropos lx
+ function lx_current -- Return current task
+ function lx_module -- Find module by name and return the module variable
+ function lx_per_cpu -- Return per-cpu variable
+ function lx_task_by_pid -- Find Linux task by PID and return the task_struct variable
+ function lx_thread_info -- Calculate Linux thread_info from task variable
+ lx-dmesg -- Print Linux kernel log buffer
+ lx-lsmod -- List currently loaded modules
+ lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules
+
+Detailed help can be obtained via "help <command-name>" for commands and "help
+function <function-name>" for convenience functions.
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 22/28] scripts/gdb: Port to python3 / gdb7.7
  2015-01-30  7:24 ` Jan Kiszka
                   ` (21 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Pantelis Koukousoulas

From: Pantelis Koukousoulas <pktoss@gmail.com>

I tried to use these scripts in an ubuntu 14.04 host (gdb 7.7 compiled
against python 3.3) but there were several errors.

I believe this patch fixes these issues so that the commands
now work (I tested lx-symbols, lx-dmesg, lx-lsmod).

Main issues that needed to be resolved:

  * In python 2 iterators have a "next()" method. In python 3 it is
    __next__() instead (so let's just add both).

  * In older python versions there was an implicit conversion
    in object.__format__() (used when an object is in string.format())
    where it was converting the object to str first and then
    calling str's __format__(). This has now been removed so
    we must explicitly convert to str the objects for which
    we need to keep this behavior.

  * In dmesg.py: in python 3 log_buf is now a "memoryview" object
    which needs to be converted to a string in order to use string
    methods like "splitlines()". Luckily memoryview exists in
    python 2.7.6 as well, so we can convert log_buf to memoryview
    and use the same code in both python 2 and python 3.

This version of the patch has now been tested with gdb 7.7 and
both python 3.4 and python 2.7.6 (I think asking for at least
python 2.7.6 is a reasonable requirement instead of complicating
the code with version checks etc).

Signed-off-by: Pantelis Koukousoulas <pktoss@gmail.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/cpus.py    | 5 ++++-
 scripts/gdb/linux/dmesg.py   | 3 ++-
 scripts/gdb/linux/modules.py | 9 ++++++---
 scripts/gdb/linux/symbols.py | 4 ++--
 scripts/gdb/linux/tasks.py   | 4 +++-
 scripts/gdb/linux/utils.py   | 2 +-
 6 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index c1441f2..8045871 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -82,7 +82,7 @@ class CpuList():
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         while self.bits == 0:
             self.entry += 1
             if self.entry == self.num_entries:
@@ -103,6 +103,9 @@ class CpuList():
 
         return cpu
 
+    def next(self):
+        return self.__next__()
+
 
 class PerCpu(gdb.Function):
     """Return per-cpu variable.
diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py
index 7650f24..3c947f0 100644
--- a/scripts/gdb/linux/dmesg.py
+++ b/scripts/gdb/linux/dmesg.py
@@ -51,9 +51,10 @@ class LxDmesg(gdb.Command):
                 continue
 
             text_len = utils.read_u16(log_buf[pos + 10:pos + 12])
+            text = log_buf[pos + 16:pos + 16 + text_len]
             time_stamp = utils.read_u64(log_buf[pos:pos + 8])
 
-            for line in log_buf[pos + 16:pos + 16 + text_len].splitlines():
+            for line in memoryview(text).tobytes().splitlines():
                 gdb.write("[{time:12.6f}] {line}\n".format(
                     time=time_stamp / 1000000000.0,
                     line=line))
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index e7c99e9..2dbf679 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -30,7 +30,7 @@ class ModuleList:
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         entry = self.curr_entry
         if entry != self.end_of_list:
             self.curr_entry = entry['next']
@@ -38,6 +38,9 @@ class ModuleList:
         else:
             raise StopIteration
 
+    def next(self):
+        return self.__next__()
+
 
 def find_module_by_name(name):
     for module in ModuleList():
@@ -91,8 +94,8 @@ class LxLsmod(gdb.Command):
             gdb.write("{address} {name:<19} {size:>8}  {ref}".format(
                 address=str(module['module_core']).split()[0],
                 name=module['name'].string(),
-                size=module['core_size'],
-                ref=ref))
+                size=str(module['core_size']),
+                ref=str(ref)))
 
             source_list = module['source_list']
             t = self._module_use_type.get_type().pointer()
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index 139841f..ae757fd 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -73,7 +73,7 @@ lx-symbols command."""
 
     def _get_module_file(self, module_name):
         module_pattern = ".*/{0}\.ko$".format(
-            string.replace(module_name, "_", r"[_\-]"))
+            module_name.replace("_", r"[_\-]"))
         for name in self.module_files:
             if re.match(module_pattern, name) and os.path.exists(name):
                 return name
@@ -87,7 +87,7 @@ lx-symbols command."""
         attrs = sect_attrs['attrs']
         section_name_to_address = {
             attrs[n]['name'].string() : attrs[n]['address']
-            for n in range(sect_attrs['nsections'])}
+            for n in range(int(sect_attrs['nsections']))}
         args = []
         for section_name in [".data", ".data..read_mostly", ".rodata", ".bss"]:
             address = section_name_to_address.get(section_name)
diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index 63cd6c5..0008e75 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -30,7 +30,7 @@ class TaskList:
     def __iter__(self):
         return self
 
-    def next(self):
+    def __next__(self):
         t = self.curr_task
         if not t or t == self.curr_group:
             self.curr_group = \
@@ -45,6 +45,8 @@ class TaskList:
                                    self.task_ptr_type, "thread_group")
         return t
 
+    def next(self):
+        return self.__next__()
 
 def get_task_by_pid(pid):
     for task in TaskList():
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index a4a1640..128c306 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -83,7 +83,7 @@ def get_target_endianness():
         elif "big endian" in endian:
             target_endianness = BIG_ENDIAN
         else:
-            raise gdb.GdgError("unknown endianness '{0}'".format(endian))
+            raise gdb.GdgError("unknown endianness '{0}'".format(str(endian)))
     return target_endianness
 
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 23/28] scripts/gdb: Ignore byte-compiled python files
  2015-01-30  7:24 ` Jan Kiszka
                   ` (22 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Daniel Thompson, Michal Marek,
	linux-kbuild

From: Daniel Thompson <daniel.thompson@linaro.org>

Using the gdb scripts leaves byte-compiled python files in the scripts/
directory. These should be ignored by git.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Cc: Michal Marek <mmarek@suse.cz>
Cc: linux-kbuild@vger.kernel.org
[Jan: drop redundant mrproper rule as suggested by Michal]
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 .gitignore                   | 1 +
 scripts/gdb/linux/.gitignore | 2 ++
 2 files changed, 3 insertions(+)
 create mode 100644 scripts/gdb/linux/.gitignore

diff --git a/.gitignore b/.gitignore
index ce57b79..ecb89e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,7 @@ Module.symvers
 /TAGS
 /linux
 /vmlinux
+/vmlinux-gdb.py
 /vmlinuz
 /System.map
 /Module.markers
diff --git a/scripts/gdb/linux/.gitignore b/scripts/gdb/linux/.gitignore
new file mode 100644
index 0000000..52e4e61
--- /dev/null
+++ b/scripts/gdb/linux/.gitignore
@@ -0,0 +1,2 @@
+*.pyc
+*.pyo
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 24/28] scripts/gdb: Use a generator instead of iterator for task list
  2015-01-30  7:24 ` Jan Kiszka
                   ` (23 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Daniel Wagner

From: Daniel Wagner <daniel.wagner@bmw-carit.de>

The iterator does not return any task_struct from the thread_group list
because the first condition in the 'if not t or ...' will only be the
first time None.

Instead of keeping track of the state ourself in the next() function,
we fall back using Python's generator.

Signed-off-by: Daniel Wagner <daniel.wagner@bmw-carit.de>
Cc: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/tasks.py | 50 +++++++++++++++++++---------------------------
 1 file changed, 20 insertions(+), 30 deletions(-)

diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py
index 0008e75..e2037d9 100644
--- a/scripts/gdb/linux/tasks.py
+++ b/scripts/gdb/linux/tasks.py
@@ -18,38 +18,28 @@ from linux import utils
 
 task_type = utils.CachedType("struct task_struct")
 
-
-class TaskList:
-    def __init__(self):
-        global task_type
-        self.task_ptr_type = task_type.get_type().pointer()
-        self.init_task = gdb.parse_and_eval("init_task")
-        self.curr_group = self.init_task.address
-        self.curr_task = None
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        t = self.curr_task
-        if not t or t == self.curr_group:
-            self.curr_group = \
-                utils.container_of(self.curr_group['tasks']['next'],
-                                   self.task_ptr_type, "tasks")
-            if self.curr_group == self.init_task.address:
-                raise StopIteration
-            t = self.curr_task = self.curr_group
-        else:
-            self.curr_task = \
-                utils.container_of(t['thread_group']['next'],
-                                   self.task_ptr_type, "thread_group")
-        return t
-
-    def next(self):
-        return self.__next__()
+def task_lists():
+    global task_type
+    task_ptr_type = task_type.get_type().pointer()
+    init_task = gdb.parse_and_eval("init_task").address
+    t = g = init_task
+
+    while True:
+        while True:
+            yield t
+
+            t = utils.container_of(t['thread_group']['next'],
+                                   task_ptr_type, "thread_group")
+            if t == g:
+                break
+
+        t = g = utils.container_of(g['tasks']['next'],
+                                   task_ptr_type, "tasks")
+        if t == init_task:
+            return
 
 def get_task_by_pid(pid):
-    for task in TaskList():
+    for task in task_lists():
         if int(task['pid']) == pid:
             return task
     return None
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 25/28] scripts/gdb: Convert ModuleList to generator function
  2015-01-30  7:24 ` Jan Kiszka
                   ` (24 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Analogously to the task list, convert the module list to a generator
function. It noticeably simplifies the code.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/modules.py | 33 +++++++++++----------------------
 scripts/gdb/linux/symbols.py |  2 +-
 2 files changed, 12 insertions(+), 23 deletions(-)

diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 2dbf679..6d49722 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -19,31 +19,20 @@ from linux import cpus, utils
 module_type = utils.CachedType("struct module")
 
 
-class ModuleList:
-    def __init__(self):
-        global module_type
-        self.module_ptr_type = module_type.get_type().pointer()
-        modules = gdb.parse_and_eval("modules")
-        self.curr_entry = modules['next']
-        self.end_of_list = modules.address
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        entry = self.curr_entry
-        if entry != self.end_of_list:
-            self.curr_entry = entry['next']
-            return utils.container_of(entry, self.module_ptr_type, "list")
-        else:
-            raise StopIteration
+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
 
-    def next(self):
-        return self.__next__()
+    while entry != end_of_list:
+        yield utils.container_of(entry, module_ptr_type, "list")
+        entry = entry['next']
 
 
 def find_module_by_name(name):
-    for module in ModuleList():
+    for module in module_list():
         if module['name'].string() == name:
             return module
     return None
@@ -83,7 +72,7 @@ class LxLsmod(gdb.Command):
             "Address{0}    Module                  Size  Used by\n".format(
                 "        " if utils.get_long_type().sizeof == 8 else ""))
 
-        for module in ModuleList():
+        for module in module_list():
             ref = 0
             module_refptr = module['refptr']
             for cpu in cpus.CpuList("cpu_possible_mask"):
diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index ae757fd..bf05e45 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -133,7 +133,7 @@ lx-symbols command."""
         gdb.execute("symbol-file vmlinux")
 
         self.loaded_modules = []
-        module_list = modules.ModuleList()
+        module_list = modules.module_list()
         if not module_list:
             gdb.write("no modules found\n")
         else:
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 26/28] scripts/gdb: Convert CpuList to generator function
  2015-01-30  7:24 ` Jan Kiszka
                   ` (25 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Yet another code simplification.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/cpus.py    | 71 ++++++++++++++++++++------------------------
 scripts/gdb/linux/modules.py |  2 +-
 2 files changed, 33 insertions(+), 40 deletions(-)

diff --git a/scripts/gdb/linux/cpus.py b/scripts/gdb/linux/cpus.py
index 8045871..4297b83 100644
--- a/scripts/gdb/linux/cpus.py
+++ b/scripts/gdb/linux/cpus.py
@@ -61,50 +61,43 @@ def cpu_mask_invalidate(event):
         gdb.events.new_objfile.disconnect(cpu_mask_invalidate)
 
 
-class CpuList():
-    def __init__(self, mask_name):
-        global cpu_mask
-        self.mask = None
-        if mask_name in cpu_mask:
-            self.mask = cpu_mask[mask_name]
-        if self.mask is None:
-            self.mask = gdb.parse_and_eval(mask_name + ".bits")
-            if hasattr(gdb, 'events'):
-                cpu_mask[mask_name] = self.mask
-                gdb.events.stop.connect(cpu_mask_invalidate)
-                if hasattr(gdb.events, 'new_objfile'):
-                    gdb.events.new_objfile.connect(cpu_mask_invalidate)
-        self.bits_per_entry = self.mask[0].type.sizeof * 8
-        self.num_entries = self.mask.type.sizeof * 8 / self.bits_per_entry
-        self.entry = -1
-        self.bits = 0
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        while self.bits == 0:
-            self.entry += 1
-            if self.entry == self.num_entries:
-                raise StopIteration
-            self.bits = self.mask[self.entry]
-            if self.bits != 0:
-                self.bit = 0
+def cpu_list(mask_name):
+    global cpu_mask
+    mask = None
+    if mask_name in cpu_mask:
+        mask = cpu_mask[mask_name]
+    if mask is None:
+        mask = gdb.parse_and_eval(mask_name + ".bits")
+        if hasattr(gdb, 'events'):
+            cpu_mask[mask_name] = mask
+            gdb.events.stop.connect(cpu_mask_invalidate)
+            if hasattr(gdb.events, 'new_objfile'):
+                gdb.events.new_objfile.connect(cpu_mask_invalidate)
+    bits_per_entry = mask[0].type.sizeof * 8
+    num_entries = mask.type.sizeof * 8 / bits_per_entry
+    entry = -1
+    bits = 0
+
+    while True:
+        while bits == 0:
+            entry += 1
+            if entry == num_entries:
+                return
+            bits = mask[entry]
+            if bits != 0:
+                bit = 0
                 break
 
-        while self.bits & 1 == 0:
-            self.bits >>= 1
-            self.bit += 1
-
-        cpu = self.entry * self.bits_per_entry + self.bit
+        while bits & 1 == 0:
+            bits >>= 1
+            bit += 1
 
-        self.bits >>= 1
-        self.bit += 1
+        cpu = entry * bits_per_entry + bit
 
-        return cpu
+        bits >>= 1
+        bit += 1
 
-    def next(self):
-        return self.__next__()
+        yield cpu
 
 
 class PerCpu(gdb.Function):
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 6d49722..a1504c4 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -75,7 +75,7 @@ class LxLsmod(gdb.Command):
         for module in module_list():
             ref = 0
             module_refptr = module['refptr']
-            for cpu in cpus.CpuList("cpu_possible_mask"):
+            for cpu in cpus.cpu_list("cpu_possible_mask"):
                 refptr = cpus.per_cpu(module_refptr, cpu)
                 ref += refptr['incs']
                 ref -= refptr['decs']
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 27/28] scripts/gdb: Define maintainer
  2015-01-30  7:24 ` Jan Kiszka
                   ` (26 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

I'm proposing myself for keeping an eye on these scripts and integrating
contributions.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 MAINTAINERS | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 2ebb056..3570313 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4164,6 +4164,11 @@ W:	http://www.icp-vortex.com/
 S:	Supported
 F:	drivers/scsi/gdt*
 
+GDB KERNEL DEBUGGING HELPER SCRIPTS
+M:	Jan Kiszka <jan.kiszka@siemens.com>
+S:	Supported
+F:	scripts/gdb/
+
 GEMTEK FM RADIO RECEIVER DRIVER
 M:	Hans Verkuil <hverkuil@xs4all.nl>
 L:	linux-media@vger.kernel.org
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* [PATCH v12 28/28] scripts/gdb: Disable pagination while printing from breakpoint handler
  2015-01-30  7:24 ` Jan Kiszka
                   ` (27 preceding siblings ...)
  (?)
@ 2015-01-30  7:24 ` Jan Kiszka
  -1 siblings, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-01-30  7:24 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

While reporting the (refreshed) list of modules on automatic updates we
may hit the page boundary of the output console and cause a stop if
pagination is enabled. However, gdb does not accept user input while
running over the breakpoint handler. So we get stuck, and the user is
forced to interrupt gdb.

Resolve this by disabling pagination during automatic symbol updates. We
restore the user's configuration once done.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 scripts/gdb/linux/symbols.py | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py
index bf05e45..cd5bea9 100644
--- a/scripts/gdb/linux/symbols.py
+++ b/scripts/gdb/linux/symbols.py
@@ -34,12 +34,23 @@ if hasattr(gdb, 'Breakpoint'):
             # enforce update if object file is not found
             cmd.module_files_updated = False
 
+            # Disable pagination while reporting symbol (re-)loading.
+            # The console input is blocked in this context so that we would
+            # get stuck waiting for the user to acknowledge paged output.
+            show_pagination = gdb.execute("show pagination", to_string=True)
+            pagination = show_pagination.endswith("on.\n")
+            gdb.execute("set pagination off")
+
             if module_name in cmd.loaded_modules:
                 gdb.write("refreshing all symbols to reload module "
                           "'{0}'\n".format(module_name))
                 cmd.load_all_symbols()
             else:
                 cmd.load_module_symbols(module)
+
+            # restore pagination state
+            gdb.execute("set pagination %s" % ("on" if pagination else "off"))
+
             return False
 
 
-- 
2.1.4


^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH v12 01/28] scripts/gdb: Add infrastructure
  2015-01-30  7:24 ` [PATCH v12 01/28] scripts/gdb: Add infrastructure Jan Kiszka
@ 2015-01-30 10:59   ` Michal Marek
  2015-02-04  6:49   ` [PATCH v13 " Jan Kiszka
  1 sibling, 0 replies; 35+ messages in thread
From: Michal Marek @ 2015-01-30 10:59 UTC (permalink / raw)
  To: Jan Kiszka, Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, linux-kbuild

On 2015-01-30 08:24, Jan Kiszka wrote:
> This provides the basic infrastructure to load kernel-specific python
> helper scripts when debugging the kernel in gdb.
> 
> The loading mechanism is based on gdb loading for <objfile>-gdb.py when
> opening <objfile>. Therefore, this places a corresponding link to the
> main helper script into the output directory that contains vmlinux.
> 
> The main scripts will pull in submodules containing Linux specific gdb
> commands and functions. To avoid polluting the source directory with
> compiled python modules, we link to them from the object directory.
> 
> Due to gdb.parse_and_eval and string redirection for gdb.execute, we
> depend on gdb >= 7.2.
> 
> This feature is enabled via CONFIG_GDB_SCRIPTS.
> 
> CC: Michal Marek <mmarek@suse.cz>
> CC: linux-kbuild@vger.kernel.org
> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>  Makefile                      |  5 ++++-
>  lib/Kconfig.debug             | 11 +++++++++++
>  scripts/Makefile              |  1 +
>  scripts/gdb/Makefile          |  1 +
>  scripts/gdb/linux/Makefile    | 11 +++++++++++

For the kbuild stuff:
Acked-by: Michal Marek <mmarek@suse.cz>

Michal

^ permalink raw reply	[flat|nested] 35+ messages in thread

* [PATCH v13 01/28] scripts/gdb: Add infrastructure
  2015-01-30  7:24 ` [PATCH v12 01/28] scripts/gdb: Add infrastructure Jan Kiszka
  2015-01-30 10:59   ` Michal Marek
@ 2015-02-04  6:49   ` Jan Kiszka
  1 sibling, 0 replies; 35+ messages in thread
From: Jan Kiszka @ 2015-02-04  6:49 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov, Michal Marek, linux-kbuild

This provides the basic infrastructure to load kernel-specific python
helper scripts when debugging the kernel in gdb.

The loading mechanism is based on gdb loading for <objfile>-gdb.py when
opening <objfile>. Therefore, this places a corresponding link to the
main helper script into the output directory that contains vmlinux.

The main scripts will pull in submodules containing Linux specific gdb
commands and functions. To avoid polluting the source directory with
compiled python modules, we link to them from the object directory.

Due to gdb.parse_and_eval and string redirection for gdb.execute, we
depend on gdb >= 7.2.

This feature is enabled via CONFIG_GDB_SCRIPTS.

CC: Michal Marek <mmarek@suse.cz>
CC: linux-kbuild@vger.kernel.org
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

Changes in v13:
 - Let CONFIG_GDB_SCRIPT depend on CONFIG_DEBUG_INFO, instead of
   selecting it. This addresses
 
   warning: (GDB_SCRIPTS) selects DEBUG_INFO which has unmet direct
   dependencies (DEBUG_KERNEL && !COMPILE_TEST)

   as found by the test robot.

This replaces v12 in -mm.

 Makefile                      |  5 ++++-
 lib/Kconfig.debug             | 11 +++++++++++
 scripts/Makefile              |  1 +
 scripts/gdb/Makefile          |  1 +
 scripts/gdb/linux/Makefile    | 11 +++++++++++
 scripts/gdb/linux/__init__.py |  0
 scripts/gdb/vmlinux-gdb.py    | 23 +++++++++++++++++++++++
 7 files changed, 51 insertions(+), 1 deletion(-)
 create mode 100644 scripts/gdb/Makefile
 create mode 100644 scripts/gdb/linux/Makefile
 create mode 100644 scripts/gdb/linux/__init__.py
 create mode 100644 scripts/gdb/vmlinux-gdb.py

diff --git a/Makefile b/Makefile
index c8e17c0..3f86eea 100644
--- a/Makefile
+++ b/Makefile
@@ -922,6 +922,9 @@ endif
 ifdef CONFIG_BUILD_DOCSRC
 	$(Q)$(MAKE) $(build)=Documentation
 endif
+ifdef CONFIG_GDB_SCRIPTS
+	$(Q)ln -fsn `cd $(srctree) && /bin/pwd`/scripts/gdb/vmlinux-gdb.py
+endif
 	+$(call if_changed,link-vmlinux)
 
 # The actual objects are generated when descending,
@@ -1176,7 +1179,7 @@ MRPROPER_FILES += .config .config.old .version .old_version $(version_h) \
 		  Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
 		  signing_key.priv signing_key.x509 x509.genkey		\
 		  extra_certificates signing_key.x509.keyid		\
-		  signing_key.x509.signer
+		  signing_key.x509.signer vmlinux-gdb.py
 
 # clean - Delete most, but leave enough to build external modules
 #
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 5f2ce61..6fd73c1 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -167,6 +167,17 @@ config DEBUG_INFO_DWARF4
 	  But it significantly improves the success of resolving
 	  variables in gdb on optimized code.
 
+config GDB_SCRIPTS
+	bool "Provide GDB scripts for kernel debugging"
+	depends on DEBUG_INFO
+	help
+	  This creates the required links to GDB helper scripts in the
+	  build directory. If you load vmlinux into gdb, the helper
+	  scripts will be automatically imported by gdb as well, and
+	  additional functions are available to analyze a Linux kernel
+	  instance. See Documentation/gdb-kernel-debugging.txt for further
+	  details.
+
 config ENABLE_WARN_DEPRECATED
 	bool "Enable __deprecated logic"
 	default y
diff --git a/scripts/Makefile b/scripts/Makefile
index 72902b5..2016a64 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -36,6 +36,7 @@ subdir-$(CONFIG_MODVERSIONS) += genksyms
 subdir-y                     += mod
 subdir-$(CONFIG_SECURITY_SELINUX) += selinux
 subdir-$(CONFIG_DTC)         += dtc
+subdir-$(CONFIG_GDB_SCRIPTS) += gdb
 
 # Let clean descend into subdirs
 subdir-	+= basic kconfig package
diff --git a/scripts/gdb/Makefile b/scripts/gdb/Makefile
new file mode 100644
index 0000000..62f5f65
--- /dev/null
+++ b/scripts/gdb/Makefile
@@ -0,0 +1 @@
+subdir-y := linux
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
new file mode 100644
index 0000000..6cf1ecf
--- /dev/null
+++ b/scripts/gdb/linux/Makefile
@@ -0,0 +1,11 @@
+always := gdb-scripts
+
+SRCTREE := $(shell cd $(srctree) && /bin/pwd)
+
+$(obj)/gdb-scripts:
+ifneq ($(KBUILD_SRC),)
+	$(Q)ln -fsn $(SRCTREE)/$(obj)/*.py $(objtree)/$(obj)
+endif
+	@:
+
+clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py)
diff --git a/scripts/gdb/linux/__init__.py b/scripts/gdb/linux/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
new file mode 100644
index 0000000..c1d90ce
--- /dev/null
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -0,0 +1,23 @@
+#
+# gdb helper commands and functions for Linux kernel debugging
+#
+#  loader module
+#
+# Copyright (c) Siemens AG, 2012, 2013
+#
+# Authors:
+#  Jan Kiszka <jan.kiszka@siemens.com>
+#
+# This work is licensed under the terms of the GNU GPL version 2.
+#
+
+import os
+
+sys.path.insert(0, os.path.dirname(__file__) + "/scripts/gdb")
+
+try:
+    gdb.parse_and_eval("0")
+    gdb.execute("", to_string=True)
+except:
+    gdb.write("NOTE: gdb 7.2 or later required for Linux helper scripts to "
+              "work.\n")
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 35+ messages in thread

* Re: [PATCH v12 06/28] module: Do not inline do_init_module
  2015-01-30  7:24 ` [PATCH v12 06/28] module: Do not inline do_init_module Jan Kiszka
@ 2015-02-10 23:59   ` Rusty Russell
  0 siblings, 0 replies; 35+ messages in thread
From: Rusty Russell @ 2015-02-10 23:59 UTC (permalink / raw)
  To: Jan Kiszka, Andrew Morton, linux-kernel
  Cc: Thomas Gleixner, Jason Wessel, kgdb-bugreport, Andi Kleen,
	Ben Widawsky, Borislav Petkov

Jan Kiszka <jan.kiszka@siemens.com> writes:
> This provides a reliable breakpoint target, required for automatic
> symbol loading via the gdb helper command 'lx-symbols'.
>
> CC: Rusty Russell <rusty@rustcorp.com.au>

Acked-by: Rusty Russell <rusty@rustcorp.com.au>

Thanks,
Rusty.

> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
> ---
>  kernel/module.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/kernel/module.c b/kernel/module.c
> index d856e96..2df6cec 100644
> --- a/kernel/module.c
> +++ b/kernel/module.c
> @@ -3011,8 +3011,13 @@ static void do_free_init(struct rcu_head *head)
>  	kfree(m);
>  }
>  
> -/* This is where the real work happens */
> -static int do_init_module(struct module *mod)
> +/*
> + * This is where the real work happens.
> + *
> + * Keep it uninlined to provide a reliable breakpoint target, e.g. for the gdb
> + * helper command 'lx-symbols'.
> + */
> +static noinline int do_init_module(struct module *mod)
>  {
>  	int ret = 0;
>  	struct mod_initfree *freeinit;
> -- 
> 2.1.4

^ permalink raw reply	[flat|nested] 35+ messages in thread

end of thread, other threads:[~2015-02-11  6:36 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-30  7:24 [PATCH v12 00/28] Add gdb python scripts as kernel debugging helpers Jan Kiszka
2015-01-30  7:24 ` Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 01/28] scripts/gdb: Add infrastructure Jan Kiszka
2015-01-30 10:59   ` Michal Marek
2015-02-04  6:49   ` [PATCH v13 " Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 02/28] scripts/gdb: Add cache for type objects Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 03/28] scripts/gdb: Add container_of helper and convenience function Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 04/28] scripts/gdb: Add module iteration class Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 05/28] scripts/gdb: Add lx-symbols command Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 06/28] module: Do not inline do_init_module Jan Kiszka
2015-02-10 23:59   ` Rusty Russell
2015-01-30  7:24 ` [PATCH v12 07/28] scripts/gdb: Add automatic symbol reloading on module insertion Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 08/28] scripts/gdb: Add internal helper and convenience function to look up a module Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 09/28] scripts/gdb: Add get_target_endianness helper Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 10/28] scripts/gdb: Add read_u16/32/64 helpers Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 11/28] scripts/gdb: Add lx-dmesg command Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 12/28] scripts/gdb: Add task iteration class Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 13/28] scripts/gdb: Add helper and convenience function to look up tasks Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 14/28] scripts/gdb: Add is_target_arch helper Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 15/28] scripts/gdb: Add internal helper and convenience function to retrieve thread_info Jan Kiszka
2015-01-30  7:24   ` Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 16/28] scripts/gdb: Add get_gdbserver_type helper Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 17/28] scripts/gdb: Add internal helper and convenience function for per-cpu lookup Jan Kiszka
2015-01-30  7:24   ` Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 18/28] scripts/gdb: Add lx_current convenience function Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 19/28] scripts/gdb: Add class to iterate over CPU masks Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 20/28] scripts/gdb: Add lx-lsmod command Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 21/28] scripts/gdb: Add basic documentation Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 22/28] scripts/gdb: Port to python3 / gdb7.7 Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 23/28] scripts/gdb: Ignore byte-compiled python files Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 24/28] scripts/gdb: Use a generator instead of iterator for task list Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 25/28] scripts/gdb: Convert ModuleList to generator function Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 26/28] scripts/gdb: Convert CpuList " Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 27/28] scripts/gdb: Define maintainer Jan Kiszka
2015-01-30  7:24 ` [PATCH v12 28/28] scripts/gdb: Disable pagination while printing from breakpoint handler Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.