* [PATCH 1/8] scripts/gdb: Provide linux constants
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 2/8] scripts/gdb: Provide a kernel list item generators Kieran Bingham
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham, mmarek,
linux-kbuild
Some macro's and defines are needed when parsing memory, and without
compiling the kernel as -g3 they are not available in the debug-symbols.
We use the pre-processor here to extract constants to a dedicated module
for the linux debugger extensions
Top level Kbuild is used to call in and generate the constants file,
while maintaining dependencies on autogenerated files in
include/generated
CC: mmarek@suse.com
CC: linux-kbuild@vger.kernel.org
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes since v1:
Kbuild:
- Call to generate constants_py with dependancy on generated files
scripts/gdb/linux/Makefile:
- Use call if_changed, and correct quiet invocation
- Annouce "GEN $@" instead of GDB PP
scripts/gdb/linux/constants.py.in:
- Updated to use better macro implementations for one line defines
---
Kbuild | 10 ++++++++++
scripts/gdb/linux/Makefile | 12 +++++++++++-
scripts/gdb/linux/constants.py.in | 32 ++++++++++++++++++++++++++++++++
scripts/gdb/vmlinux-gdb.py | 1 +
4 files changed, 54 insertions(+), 1 deletion(-)
create mode 100644 scripts/gdb/linux/constants.py.in
diff --git a/Kbuild b/Kbuild
index f55cefd9bf29..3d0ae152af7c 100644
--- a/Kbuild
+++ b/Kbuild
@@ -5,6 +5,7 @@
# 2) Generate timeconst.h
# 3) Generate asm-offsets.h (may need bounds.h and timeconst.h)
# 4) Check for missing system calls
+# 5) Generate constants.py (may need bounds.h)
# Default sed regexp - multiline due to syntax constraints
define sed-y
@@ -96,5 +97,14 @@ quiet_cmd_syscalls = CALL $<
missing-syscalls: scripts/checksyscalls.sh $(offsets-file) FORCE
$(call cmd,syscalls)
+#####
+# 5) Generate constants for Python GDB integration
+#
+
+extra-$(CONFIG_GDB_SCRIPTS) += build_constants_py
+
+build_constants_py: $(obj)/$(timeconst-file) $(obj)/$(bounds-file)
+ @$(MAKE) $(build)=scripts/gdb/linux $@
+
# Keep these three files during make clean
no-clean-files := $(bounds-file) $(offsets-file) $(timeconst-file)
diff --git a/scripts/gdb/linux/Makefile b/scripts/gdb/linux/Makefile
index 6cf1ecf61057..cd129e65d1ff 100644
--- a/scripts/gdb/linux/Makefile
+++ b/scripts/gdb/linux/Makefile
@@ -8,4 +8,14 @@ ifneq ($(KBUILD_SRC),)
endif
@:
-clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py)
+quiet_cmd_gen_constants_py = GEN $@
+ cmd_gen_constants_py = \
+ $(CPP) -E -x c -P $(c_flags) $< > $@ ;\
+ sed -i '1,/<!-- end-c-headers -->/d;' $@
+
+$(obj)/constants.py: $(SRCTREE)/$(obj)/constants.py.in
+ $(call if_changed,gen_constants_py)
+
+build_constants_py: $(obj)/constants.py
+
+clean-files := *.pyc *.pyo $(if $(KBUILD_SRC),*.py) $(obj)/constants.py
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
new file mode 100644
index 000000000000..79d9d0092452
--- /dev/null
+++ b/scripts/gdb/linux/constants.py.in
@@ -0,0 +1,32 @@
+/*
+ * gdb helper commands and functions for Linux kernel debugging
+ *
+ * Kernel constants derived from include files.
+ *
+ * Copyright (c) 2016 Linaro Ltd
+ *
+ * Authors:
+ * Kieran Bingham <kieran.bingham@linaro.org>
+ *
+ * This work is licensed under the terms of the GNU GPL version 2.
+ *
+ */
+
+/* We need to stringify expanded macros so that they can be parsed */
+#define STRING(x) #x
+#define XSTRING(x) STRING(x)
+
+#define LX_VALUE(x) LX_##x = x
+#define LX_GDBPARSED(x) LX_##x = gdb.parse_and_eval(XSTRING(x))
+
+/*
+ * IS_ENABLED generates (a || b) which is not compatible with python
+ * We can only switch on configuration items we know are available
+ * Therefore - IS_BUILTIN() is more appropriate
+ */
+#define LX_CONFIG(x) LX_##x = IS_BUILTIN(x)
+
+/* The build system will take care of deleting everything above this marker */
+<!-- end-c-headers -->
+
+import gdb
diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py
index d5943eca19cd..6e0b0afd888a 100644
--- a/scripts/gdb/vmlinux-gdb.py
+++ b/scripts/gdb/vmlinux-gdb.py
@@ -30,3 +30,4 @@ else:
import linux.cpus
import linux.lists
import linux.proc
+ import linux.constants
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 2/8] scripts/gdb: Provide a kernel list item generators
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
2016-02-22 15:24 ` [PATCH 1/8] scripts/gdb: Provide linux constants Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 3/8] scripts/gdb: Convert modules usage to lists functions Kieran Bingham
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham,
Jeff Mahoney
Facilitate linked-list items by providing a generator to return
the dereferenced, and type-cast objects from a kernel linked list
CC: Jeff Mahoney <jeffm@suse.com>
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes since v1:
* items function removed, and replaced with Jeff Mahoney's cleaner
implementations of list_for_each, and list_for_each_entry
---
scripts/gdb/linux/lists.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/scripts/gdb/linux/lists.py b/scripts/gdb/linux/lists.py
index 3a3775bc162b..9f4503738e26 100644
--- a/scripts/gdb/linux/lists.py
+++ b/scripts/gdb/linux/lists.py
@@ -18,6 +18,26 @@ from linux import utils
list_head = utils.CachedType("struct list_head")
+def list_for_each(head):
+ if head.type == list_head.get_type().pointer():
+ head = head.dereference()
+ elif head.type != list_head.get_type():
+ raise gdb.GdbError("Must be struct list_head not %s" % list_head.type)
+
+ node = head['next'].dereference()
+ while node.address != head.address:
+ yield node.address
+ node = node['next'].dereference()
+
+
+def list_for_each_entry(head, gdbtype, member):
+ for node in list_for_each(head):
+ if node.type != list_head.get_type().pointer():
+ raise TypeError("Type %s found. "
+ "Expected struct list_head *." % node.type)
+ yield utils.container_of(node, gdbtype, member)
+
+
def list_check(head):
nb = 0
if (head.type == list_head.get_type().pointer()):
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 3/8] scripts/gdb: Convert modules usage to lists functions
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
2016-02-22 15:24 ` [PATCH 1/8] scripts/gdb: Provide linux constants Kieran Bingham
2016-02-22 15:24 ` [PATCH 2/8] scripts/gdb: Provide a kernel list item generators Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 4/8] scripts/gdb: Provide exception catching parser Kieran Bingham
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham
Simplify the module list functions with the new list_for_each_entry
abstractions
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/modules.py | 17 ++++++-----------
1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 25db8cff44a2..571489b3b9c2 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -13,7 +13,7 @@
import gdb
-from linux import cpus, utils
+from linux import cpus, utils, lists
module_type = utils.CachedType("struct module")
@@ -23,12 +23,9 @@ def module_list():
global module_type
module_ptr_type = module_type.get_type().pointer()
modules = gdb.parse_and_eval("modules")
- entry = modules['next']
- end_of_list = modules.address
- while entry != end_of_list:
- yield utils.container_of(entry, module_ptr_type, "list")
- entry = entry['next']
+ for module in lists.list_for_each_entry(modules, module_ptr_type, "list"):
+ yield module
def find_module_by_name(name):
@@ -79,17 +76,15 @@ class LxLsmod(gdb.Command):
size=str(module['core_size']),
ref=str(module['refcnt']['counter'])))
- source_list = module['source_list']
t = self._module_use_type.get_type().pointer()
- entry = source_list['next']
first = True
- while entry != source_list.address:
- use = utils.container_of(entry, t, "source_list")
+ sources = module['source_list']
+ for use in lists.list_for_each_entry(sources, t, "source_list"):
gdb.write("{separator}{name}".format(
separator=" " if first else ",",
name=use['source']['name'].string()))
first = False
- entry = entry['next']
+
gdb.write("\n")
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 4/8] scripts/gdb: Provide exception catching parser
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
` (2 preceding siblings ...)
2016-02-22 15:24 ` [PATCH 3/8] scripts/gdb: Convert modules usage to lists functions Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 5/8] scripts/gdb: Support !CONFIG_MODULES gracefully Kieran Bingham
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham
If we attempt to read a value that is not available to GDB, an exception
is raised. Most of the time, this is a good thing; however on occasion
we will want to be able to determine if a symbol is available.
By catching the exception to simply return None, we can determine if we
tried to read an invalid value, without the exception taking our execution
context away from us
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/utils.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py
index 0893b326a28b..dbe2ad78048c 100644
--- a/scripts/gdb/linux/utils.py
+++ b/scripts/gdb/linux/utils.py
@@ -154,3 +154,10 @@ def get_gdbserver_type():
if gdbserver_type is not None and hasattr(gdb, 'events'):
gdb.events.exited.connect(exit_handler)
return gdbserver_type
+
+
+def gdb_eval_or_none(expresssion):
+ try:
+ return gdb.parse_and_eval(expresssion)
+ except:
+ return None
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 5/8] scripts/gdb: Support !CONFIG_MODULES gracefully
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
` (3 preceding siblings ...)
2016-02-22 15:24 ` [PATCH 4/8] scripts/gdb: Provide exception catching parser Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 6/8] scripts/gdb: Add io resource readers Kieran Bingham
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham
If CONFIG_MODULES is not enabled, lx-lsmod tries to find
a non-existent symbol and generates an unfriendly traceback:
(gdb) lx-lsmod
Address Module Size Used by
Traceback (most recent call last):
File "scripts/gdb/linux/modules.py", line 75, in invoke
for module in module_list():
File "scripts/gdb/linux/modules.py", line 24, in module_list
module_ptr_type = module_type.get_type().pointer()
File "scripts/gdb/linux/utils.py", line 28, in get_type
self._type = gdb.lookup_type(self._name)
gdb.error: No struct type named module.
Error occurred in Python command: No struct type named module.
Catch the error and return an empty module_list() for a clean command
output as follows:
(gdb) lx-lsmod
Address Module Size Used by
(gdb)
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
scripts/gdb/linux/modules.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/scripts/gdb/linux/modules.py b/scripts/gdb/linux/modules.py
index 571489b3b9c2..60224d8bbfb2 100644
--- a/scripts/gdb/linux/modules.py
+++ b/scripts/gdb/linux/modules.py
@@ -21,8 +21,11 @@ module_type = utils.CachedType("struct module")
def module_list():
global module_type
+ modules = utils.gdb_eval_or_none("modules")
+ if modules is None:
+ return
+
module_ptr_type = module_type.get_type().pointer()
- modules = gdb.parse_and_eval("modules")
for module in lists.list_for_each_entry(modules, module_ptr_type, "list"):
yield module
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 6/8] scripts/gdb: Add io resource readers
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
` (4 preceding siblings ...)
2016-02-22 15:24 ` [PATCH 5/8] scripts/gdb: Support !CONFIG_MODULES gracefully Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 7/8] scripts/gdb: Add mount point list command Kieran Bingham
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham
Provide iomem_resource and ioports_resource printers and command hooks
It can be quite interesting to halt the kernel as it's booting and check
to see this list as it is being populated.
It should be useful in the event that a kernel is not booting, you
can identify what memory resources have been registered
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes since v1:
Permenant commit message updated
---
scripts/gdb/linux/proc.py | 57 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 57 insertions(+)
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 6e6709c1830c..d855b2fd9a06 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -39,3 +39,60 @@ class LxVersion(gdb.Command):
gdb.write(gdb.parse_and_eval("linux_banner").string())
LxVersion()
+
+
+# Resource Structure Printers
+# /proc/iomem
+# /proc/ioports
+
+def get_resources(resource, depth):
+ while resource:
+ yield resource, depth
+
+ child = resource['child']
+ if child:
+ for res, deep in get_resources(child, depth + 1):
+ yield res, deep
+
+ resource = resource['sibling']
+
+
+def show_lx_resources(resource_str):
+ resource = gdb.parse_and_eval(resource_str)
+ width = 4 if resource['end'] < 0x10000 else 8
+ # Iterate straight to the first child
+ for res, depth in get_resources(resource['child'], 0):
+ start = int(res['start'])
+ end = int(res['end'])
+ gdb.write(" " * depth * 2 +
+ "{0:0{1}x}-".format(start, width) +
+ "{0:0{1}x} : ".format(end, width) +
+ res['name'].string() + "\n")
+
+
+class LxIOMem(gdb.Command):
+ """Identify the IO memory resource locations defined by the kernel
+
+Equivalent to cat /proc/iomem on a running target"""
+
+ def __init__(self):
+ super(LxIOMem, self).__init__("lx-iomem", gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ return show_lx_resources("iomem_resource")
+
+LxIOMem()
+
+
+class LxIOPorts(gdb.Command):
+ """Identify the IO port resource locations defined by the kernel
+
+Equivalent to cat /proc/ioports on a running target"""
+
+ def __init__(self):
+ super(LxIOPorts, self).__init__("lx-ioports", gdb.COMMAND_DATA)
+
+ def invoke(self, arg, from_tty):
+ return show_lx_resources("ioport_resource")
+
+LxIOPorts()
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 7/8] scripts/gdb: Add mount point list command
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
` (5 preceding siblings ...)
2016-02-22 15:24 ` [PATCH 6/8] scripts/gdb: Add io resource readers Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-22 15:24 ` [PATCH 8/8] scripts/gdb: Add meminfo command Kieran Bingham
2016-02-29 16:36 ` [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Jan Kiszka
8 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham
lx-mounts will identify current mount points based on the 'init_task'
namespace by default, as we do not yet have a kernel thread list
implementation to select the current running thread.
Optionally, a user can specify a PID to list from that process'
namespace
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes from v1:
- Updated to use LX_ constant macros
- Adjusted for new list_for_each_item() function
- Removed unnessary Null check in vfs['mnt_parent']
- Tested and not needed. It probably occured in early testing
with a bad iterator
---
scripts/gdb/linux/constants.py.in | 21 ++++++++
scripts/gdb/linux/proc.py | 108 ++++++++++++++++++++++++++++++++++++++
2 files changed, 129 insertions(+)
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 79d9d0092452..57213ad8cf75 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -12,7 +12,11 @@
*
*/
+#include <linux/fs.h>
+#include <linux/mount.h>
+
/* We need to stringify expanded macros so that they can be parsed */
+
#define STRING(x) #x
#define XSTRING(x) STRING(x)
@@ -30,3 +34,20 @@
<!-- end-c-headers -->
import gdb
+
+/* linux/fs.h */
+LX_VALUE(MS_RDONLY)
+LX_VALUE(MS_SYNCHRONOUS)
+LX_VALUE(MS_MANDLOCK)
+LX_VALUE(MS_DIRSYNC)
+LX_VALUE(MS_NOATIME)
+LX_VALUE(MS_NODIRATIME)
+
+/* linux/mount.h */
+LX_VALUE(MNT_NOSUID)
+LX_VALUE(MNT_NODEV)
+LX_VALUE(MNT_NOEXEC)
+LX_VALUE(MNT_NOATIME)
+LX_VALUE(MNT_NODIRATIME)
+LX_VALUE(MNT_RELATIME)
+
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index d855b2fd9a06..44804e10493e 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -12,6 +12,10 @@
#
import gdb
+from linux import constants
+from linux import utils
+from linux import tasks
+from linux import lists
class LxCmdLine(gdb.Command):
@@ -96,3 +100,107 @@ Equivalent to cat /proc/ioports on a running target"""
return show_lx_resources("ioport_resource")
LxIOPorts()
+
+
+# Mount namespace viewer
+# /proc/mounts
+
+
+def dentry_name(d):
+ parent = d['d_parent']
+ if parent == d or parent == 0:
+ return ""
+ p = dentry_name(d['d_parent']) + "/"
+ return p + d['d_iname'].string()
+
+
+def info_opts(lst, opt):
+ opts = ""
+ for key, string in lst.items():
+ if opt & key:
+ opts += string
+ return opts
+
+
+FS_INFO = {constants.LX_MS_SYNCHRONOUS: ",sync",
+ constants.LX_MS_MANDLOCK: ",mand",
+ constants.LX_MS_DIRSYNC: ",dirsync",
+ constants.LX_MS_NOATIME: ",noatime",
+ constants.LX_MS_NODIRATIME: ",nodiratime"}
+
+MNT_INFO = {constants.LX_MNT_NOSUID: ",nosuid",
+ constants.LX_MNT_NODEV: ",nodev",
+ constants.LX_MNT_NOEXEC: ",noexec",
+ constants.LX_MNT_NOATIME: ",noatime",
+ constants.LX_MNT_NODIRATIME: ",nodiratime",
+ constants.LX_MNT_RELATIME: ",relatime"}
+
+mount_type = utils.CachedType("struct mount")
+mount_ptr_type = mount_type.get_type().pointer()
+
+
+class LxMounts(gdb.Command):
+ """Report the VFS mounts of the current process namespace.
+
+Equivalent to cat /proc/mounts on a running target
+An integer value can be supplied to display the mount
+values of that process namespace"""
+
+ def __init__(self):
+ super(LxMounts, self).__init__("lx-mounts", gdb.COMMAND_DATA)
+
+ # Equivalent to proc_namespace.c:show_vfsmnt
+ # However, that has the ability to call into s_op functions
+ # whereas we cannot and must make do with the information we can obtain.
+ def invoke(self, arg, from_tty):
+ argv = gdb.string_to_argv(arg)
+ if len(argv) >= 1:
+ try:
+ pid = int(argv[0])
+ except:
+ raise gdb.GdbError("Provide a PID as integer value")
+ else:
+ pid = 1
+
+ task = tasks.get_task_by_pid(pid)
+ if not task:
+ raise gdb.GdbError("Couldn't find a process with PID {}"
+ .format(pid))
+
+ namespace = task['nsproxy']['mnt_ns']
+ if not namespace:
+ raise gdb.GdbError("No namespace for current process")
+
+ for vfs in lists.list_for_each_entry(
+ namespace['list'], mount_ptr_type, "mnt_list"):
+ devname = vfs['mnt_devname'].string()
+ devname = devname if devname else "none"
+
+ pathname = ""
+ parent = vfs
+ while True:
+ mntpoint = parent['mnt_mountpoint']
+ pathname = dentry_name(mntpoint) + pathname
+ if (parent == parent['mnt_parent']):
+ break
+ parent = parent['mnt_parent']
+
+ if (pathname == ""):
+ pathname = "/"
+
+ superblock = vfs['mnt']['mnt_sb']
+ fstype = superblock['s_type']['name'].string()
+ s_flags = int(superblock['s_flags'])
+ m_flags = int(vfs['mnt']['mnt_flags'])
+ rd = "ro" if (s_flags & constants.LX_MS_RDONLY) else "rw"
+
+ gdb.write(
+ "{} {} {} {}{}{} 0 0\n"
+ .format(devname,
+ pathname,
+ fstype,
+ rd,
+ info_opts(FS_INFO, s_flags),
+ info_opts(MNT_INFO, m_flags)))
+
+LxMounts()
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH 8/8] scripts/gdb: Add meminfo command
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
` (6 preceding siblings ...)
2016-02-22 15:24 ` [PATCH 7/8] scripts/gdb: Add mount point list command Kieran Bingham
@ 2016-02-22 15:24 ` Kieran Bingham
2016-02-24 9:44 ` Kieran Bingham
2016-02-29 16:36 ` [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Jan Kiszka
8 siblings, 1 reply; 12+ messages in thread
From: Kieran Bingham @ 2016-02-22 15:24 UTC (permalink / raw)
To: jan.kiszka, linux-kernel
Cc: lee.jones, peter.griffin, maxime.coquelin, Kieran Bingham
Provide an equivalent of /proc/meminfo which should be available from
core dumps, or crashed kernels. This should allow a debugger to identify
if memory pressures were applicable in the instance of their issue
Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
---
Changes from v1:
- Updated to use LX_ macros for constants
- Utilise the LX_CONFIG() options for conditional printing
- Fixed meminfo command on Jan's target .config
- Added missing segments to meminfo command (HUGEPAGE, QUICKLIST)
- Adjusted for new list_for_each_entry() function
- Fixed up for !CONFIG_SWAP and !CONFIG_MMU targets (Tested STM32)
---
scripts/gdb/linux/constants.py.in | 34 ++++++
scripts/gdb/linux/proc.py | 219 ++++++++++++++++++++++++++++++++++++++
2 files changed, 253 insertions(+)
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 57213ad8cf75..66562a8242bd 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -12,8 +12,16 @@
*
*/
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/thread_info.h>
+
#include <linux/fs.h>
+#include <linux/swap.h>
#include <linux/mount.h>
+#include <linux/huge_mm.h>
+#include <linux/vmalloc.h>
+
/* We need to stringify expanded macros so that they can be parsed */
@@ -51,3 +59,29 @@ LX_VALUE(MNT_NOATIME)
LX_VALUE(MNT_NODIRATIME)
LX_VALUE(MNT_RELATIME)
+/* asm/page.h */
+LX_GDBPARSED(PAGE_SHIFT)
+
+/* asm/thread_info.h */
+LX_GDBPARSED(THREAD_SIZE)
+
+/* linux/vmalloc.h */
+LX_GDBPARSED(VMALLOC_TOTAL)
+
+/* linux/swap.h */
+LX_GDBPARSED(MAX_SWAPFILES)
+
+
+/* Kernel Configs */
+LX_CONFIG(CONFIG_HIGHMEM)
+LX_CONFIG(CONFIG_MEMORY_FAILURE)
+LX_CONFIG(CONFIG_TRANSPARENT_HUGEPAGE)
+LX_CONFIG(CONFIG_CMA)
+LX_CONFIG(CONFIG_MMU)
+LX_CONFIG(CONFIG_SWAP)
+
+#ifndef CONFIG_NR_QUICK
+#define CONFIG_NR_QUICK 0
+#endif
+LX_VALUE(CONFIG_NR_QUICK)
+LX_CONFIG(CONFIG_QUICKLIST)
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 44804e10493e..95933f66ea3e 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -204,3 +204,222 @@ values of that process namespace"""
info_opts(MNT_INFO, m_flags)))
LxMounts()
+
+
+bdev_type = utils.CachedType("struct block_device")
+bdev_ptr_type = bdev_type.get_type().pointer()
+
+
+class LxMeminfo(gdb.Command):
+ """ Identify the memory usage, statistics, and availability
+
+Equivalent to cat /proc/meminfo on a running target """
+
+ def __init__(self):
+ super(LxMeminfo, self).__init__("lx-meminfo", gdb.COMMAND_DATA)
+
+ def K(self, val):
+ # Convert from PAGES to KB
+ return int(val << (constants.LX_PAGE_SHIFT - 10))
+
+ def page_K(self, remote_value):
+ # Obtain page value, and Convert from PAGES to KB
+ val = int(gdb.parse_and_eval(remote_value))
+ return self.K(val)
+
+ def gps(self, enum_zone_stat_item):
+ # Access the Global Page State structure
+ # I would prefer to read this structure in one go and then index
+ # from the enum. But we can't determine the enum values with out
+ # a call to GDB anyway so we may as well take the easy route and
+ # get the value.
+ remote_value = "vm_stat[" + enum_zone_stat_item + "].counter"
+ return int(gdb.parse_and_eval(remote_value))
+
+ def gps_K(self, enum_zone_stat_item):
+ return self.K(self.gps(enum_zone_stat_item))
+
+ def nr_blockdev_pages(self):
+ bdevs_head = gdb.parse_and_eval("all_bdevs")
+ pages = 0
+ for bdev in lists.list_for_each_entry(bdevs_head, bdev_ptr_type, "bd_list"):
+ try:
+ pages += bdev['bd_inode']['i_mapping']['nrpages']
+ except:
+ # Any memory read failures are simply not counted
+ pass
+ return pages
+
+ def total_swapcache_pages(self):
+ pages = 0
+ if not constants.LX_CONFIG_SWAP:
+ return 0
+
+ for i in range(0, int(constants.LX_MAX_SWAPFILES)):
+ swap_space = "swapper_spaces[" + str(i) + "].nrpages"
+ pages += int(gdb.parse_and_eval(swap_space))
+ return pages
+
+ def vm_commit_limit(self, totalram_pages):
+ total_swap_pages = 0
+ overcommit = int(gdb.parse_and_eval("sysctl_overcommit_kbytes"))
+ overcommit_ratio = int(gdb.parse_and_eval("sysctl_overcommit_ratio"))
+
+ if constants.LX_CONFIG_SWAP:
+ total_swap_pages = int(gdb.parse_and_eval("total_swap_pages"))
+
+ hugetlb_total_pages = 0 # hugetlb_total_pages()
+
+ if overcommit:
+ allowed = overcommit >> (constants.LX_PAGE_SHIFT - 10)
+ else:
+ allowed = ((totalram_pages - hugetlb_total_pages *
+ overcommit_ratio / 100))
+
+ allowed += total_swap_pages
+ return allowed
+
+ def quicklist_total_size(self):
+ count = 0
+ quicklist = utils.gdb_eval_or_none("quicklist")
+ if quicklist is None:
+ return 0
+
+ for cpu in cpus.each_online_cpu():
+ ql = cpus.per_cpu(quicklist, cpu)
+ for q in range(0, constants.LX_CONFIG_NR_QUICK):
+ # for (q = ql; q < ql + CONFIG_NR_QUICK; q++)
+ # count += q->nr_pages
+ count += ql[q]['nr_pages']
+
+ return count
+
+ # Main lx-meminfo command execution
+ # See fs/proc/meminfo.c:meminfo_proc_show()
+ def invoke(self, arg, from_tty):
+ totalram = int(gdb.parse_and_eval("totalram_pages"))
+ freeram = self.gps("NR_FREE_PAGES")
+ reclaimable = self.gps("NR_SLAB_RECLAIMABLE")
+ unreclaimable = self.gps("NR_SLAB_UNRECLAIMABLE")
+ slab = reclaimable + unreclaimable
+ # for_each_zone(zone)
+ # wmark_low += zone->watermark[WMARK_LOW];
+ wmark_low = 0 # Zone parsing is unimplemented
+
+ available = freeram - wmark_low
+ available += reclaimable - min(reclaimable / 2, wmark_low)
+
+ bufferram = self.nr_blockdev_pages()
+ total_swapcache_pages = self.total_swapcache_pages()
+
+ file_pages = self.gps("NR_FILE_PAGES")
+ cached = file_pages - total_swapcache_pages - bufferram
+
+ # LRU Pages
+ active_pages_anon = self.gps("NR_ACTIVE_ANON")
+ inactive_pages_anon = self.gps("NR_INACTIVE_ANON")
+ active_pages_file = self.gps("NR_ACTIVE_FILE")
+ inactive_pages_file = self.gps("NR_INACTIVE_FILE")
+ unevictable_pages = self.gps("NR_UNEVICTABLE")
+ active_pages = active_pages_anon + active_pages_file
+ inactive_pages = inactive_pages_anon + inactive_pages_file
+
+ kernelstack = int(self.gps("NR_KERNEL_STACK") *
+ constants.LX_THREAD_SIZE / 1024)
+
+ commitlimit = int(self.vm_commit_limit(totalram))
+ committed_as = int(gdb.parse_and_eval("vm_committed_as.count"))
+
+ vmalloc_total = int(constants.LX_VMALLOC_TOTAL >> 10)
+
+ gdb.write(
+ "MemTotal: {:8d} kB\n".format(self.K(totalram)) +
+ "MemFree: {:8d} kB\n".format(self.K(freeram)) +
+ "MemAvailable: {:8d} kB\n".format(self.K(available)) +
+ "Buffers: {:8d} kB\n".format(self.K(bufferram)) +
+ "Cached: {:8d} kB\n".format(self.K(cached)) +
+ "SwapCached: {:8d} kB\n".format(self.K(total_swapcache_pages)) +
+ "Active: {:8d} kB\n".format(self.K(active_pages)) +
+ "Inactive: {:8d} kB\n".format(self.K(inactive_pages)) +
+ "Active(anon): {:8d} kB\n".format(self.K(active_pages_anon)) +
+ "Inactive(anon): {:8d} kB\n".format(self.K(inactive_pages_anon)) +
+ "Active(file): {:8d} kB\n".format(self.K(active_pages_file)) +
+ "Inactive(file): {:8d} kB\n".format(self.K(inactive_pages_file)) +
+ "Unevictable: {:8d} kB\n".format(self.K(unevictable_pages)) +
+ "Mlocked: {:8d} kB\n".format(self.gps_K("NR_MLOCK"))
+ )
+ if constants.LX_CONFIG_HIGHMEM:
+ totalhigh = int(gdb.parse_and_eval("totalhigh_pages"))
+ freehigh = int(gdb.parse_and_eval("nr_free_highpages()"))
+ gdb.write(
+ "HighTotal: {:8d} kB\n".format(self.K(totalhigh)) +
+ "HighFree: {:8d} kB\n".format(self.K(freehigh)) +
+ "LowTotal: {:8d} kB\n".format(self.K(totalram-totalhigh)) +
+ "LowFree: {:8d} kB\n".format(self.K(freeram-freehigh))
+ )
+ if not constants.LX_CONFIG_MMU:
+ mmap_pages_allocated = gdb.parse_and_eval("mmap_pages_allocated.counter")
+ gdb.write(
+ "MmapCopy: {:8d} kB\n".format(self.K(mmap_pages_allocated))
+
+ )
+ pass
+
+ gdb.write(
+ "SwapTotal: {:8d} kB\n".format(self.K(0)) +
+ "SwapFree: {:8d} kB\n".format(self.K(0)) +
+ "Dirty: {:8d} kB\n".format(self.gps_K("NR_FILE_DIRTY")) +
+ "Writeback: {:8d} kB\n".format(self.gps_K("NR_WRITEBACK")) +
+ "AnonPages: {:8d} kB\n".format(self.gps_K("NR_ANON_PAGES")) +
+ "Mapped: {:8d} kB\n".format(self.gps_K("NR_FILE_MAPPED")) +
+ "Shmem: {:8d} kB\n".format(self.gps_K("NR_SHMEM")) +
+ "Slab: {:8d} kB\n".format(self.K(slab)) +
+ "SReclaimable: {:8d} kB\n".format(self.K(reclaimable)) +
+ "SUnreclaim: {:8d} kB\n".format(self.K(unreclaimable)) +
+ "KernelStack: {:8d} kB\n".format(kernelstack) +
+ "PageTables: {:8d} kB\n".format(self.gps_K("NR_PAGETABLE"))
+ )
+
+ if constants.LX_CONFIG_QUICKLIST:
+ quicklist = self.quicklist_total_size()
+ gdb.write(
+ "Quicklists: {:8d} kB\n".format(self.K(quicklist))
+ )
+
+ gdb.write(
+ "NFS_Unstable: {:8d} kB\n".format(self.gps_K("NR_UNSTABLE_NFS")) +
+ "Bounce: {:8d} kB\n".format(self.gps_K("NR_BOUNCE")) +
+ "WritebackTmp: {:8d} kB\n".format(self.gps_K("NR_WRITEBACK_TEMP"))
+ )
+
+ gdb.write(
+ "CommitLimit: {:8d} kB\n".format(self.K(commitlimit)) +
+ "Committed_AS: {:8d} kB\n".format(self.K(committed_as)) +
+ "VmallocTotal: {:8d} kB\n".format(vmalloc_total)
+ )
+
+ # These are always zero now
+ gdb.write(
+ "VmallocUsed: {:8d} kB\n".format(0) +
+ "VmallocChunk: {:8d} kB\n".format(0)
+ )
+
+ if constants.LX_CONFIG_MEMORY_FAILURE:
+ gdb.write(
+ "HardwareCorrupted: {:8d} kB\n"
+ )
+ if constants.LX_CONFIG_TRANSPARENT_HUGEPAGE:
+ huge = self.gps("NR_ANON_TRANSPARENT_HUGEPAGES")
+ # HPAGE_PMD_NR can not be determined in constants.py
+ gdb.write(
+ "AnonHugePages: {:8d} kB ( * HPAGE_PMD_NR )\n"
+ .format(self.K(huge))
+ )
+ if constants.LX_CONFIG_CMA:
+ totalcma_pages = int(gdb.parse_and_eval("totalcma_pages"))
+ gdb.write(
+ "CmaTotal: {:8d} kB\n".format(self.K(totalcma_pages)) +
+ "CmaFree: {:8d} kB\n".format(self.gps_K("NR_FREE_CMA_PAGES"))
+ )
+
+LxMeminfo()
--
2.5.0
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH 8/8] scripts/gdb: Add meminfo command
2016-02-22 15:24 ` [PATCH 8/8] scripts/gdb: Add meminfo command Kieran Bingham
@ 2016-02-24 9:44 ` Kieran Bingham
0 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-24 9:44 UTC (permalink / raw)
To: jan.kiszka, linux-kernel; +Cc: lee.jones, peter.griffin, maxime.coquelin
I had missed some PEP8 line length warnings on this patch - I've now
fixed them up. And a spurious 'pass' statement appeared (highlighted
inline), which I've removed.
--
Kieran
On 22/02/16 15:24, Kieran Bingham wrote:
> Provide an equivalent of /proc/meminfo which should be available from
> core dumps, or crashed kernels. This should allow a debugger to identify
> if memory pressures were applicable in the instance of their issue
>
> Signed-off-by: Kieran Bingham <kieran.bingham@linaro.org>
>
> ---
>
> Changes from v1:
> - Updated to use LX_ macros for constants
> - Utilise the LX_CONFIG() options for conditional printing
> - Fixed meminfo command on Jan's target .config
> - Added missing segments to meminfo command (HUGEPAGE, QUICKLIST)
> - Adjusted for new list_for_each_entry() function
> - Fixed up for !CONFIG_SWAP and !CONFIG_MMU targets (Tested STM32)
> ---
> scripts/gdb/linux/constants.py.in | 34 ++++++
> scripts/gdb/linux/proc.py | 219 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 253 insertions(+)
>
> diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
> index 57213ad8cf75..66562a8242bd 100644
> --- a/scripts/gdb/linux/constants.py.in
> +++ b/scripts/gdb/linux/constants.py.in
> @@ -12,8 +12,16 @@
> *
> */
>
> +#include <asm/page.h>
> +#include <asm/pgtable.h>
> +#include <asm/thread_info.h>
> +
> #include <linux/fs.h>
> +#include <linux/swap.h>
> #include <linux/mount.h>
> +#include <linux/huge_mm.h>
> +#include <linux/vmalloc.h>
> +
>
> /* We need to stringify expanded macros so that they can be parsed */
>
> @@ -51,3 +59,29 @@ LX_VALUE(MNT_NOATIME)
> LX_VALUE(MNT_NODIRATIME)
> LX_VALUE(MNT_RELATIME)
>
> +/* asm/page.h */
> +LX_GDBPARSED(PAGE_SHIFT)
> +
> +/* asm/thread_info.h */
> +LX_GDBPARSED(THREAD_SIZE)
> +
> +/* linux/vmalloc.h */
> +LX_GDBPARSED(VMALLOC_TOTAL)
> +
> +/* linux/swap.h */
> +LX_GDBPARSED(MAX_SWAPFILES)
> +
> +
> +/* Kernel Configs */
> +LX_CONFIG(CONFIG_HIGHMEM)
> +LX_CONFIG(CONFIG_MEMORY_FAILURE)
> +LX_CONFIG(CONFIG_TRANSPARENT_HUGEPAGE)
> +LX_CONFIG(CONFIG_CMA)
> +LX_CONFIG(CONFIG_MMU)
> +LX_CONFIG(CONFIG_SWAP)
> +
> +#ifndef CONFIG_NR_QUICK
> +#define CONFIG_NR_QUICK 0
> +#endif
> +LX_VALUE(CONFIG_NR_QUICK)
> +LX_CONFIG(CONFIG_QUICKLIST)
> diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
> index 44804e10493e..95933f66ea3e 100644
> --- a/scripts/gdb/linux/proc.py
> +++ b/scripts/gdb/linux/proc.py
> @@ -204,3 +204,222 @@ values of that process namespace"""
> info_opts(MNT_INFO, m_flags)))
>
> LxMounts()
> +
> +
> +bdev_type = utils.CachedType("struct block_device")
> +bdev_ptr_type = bdev_type.get_type().pointer()
> +
> +
> +class LxMeminfo(gdb.Command):
> + """ Identify the memory usage, statistics, and availability
> +
> +Equivalent to cat /proc/meminfo on a running target """
> +
> + def __init__(self):
> + super(LxMeminfo, self).__init__("lx-meminfo", gdb.COMMAND_DATA)
> +
> + def K(self, val):
> + # Convert from PAGES to KB
> + return int(val << (constants.LX_PAGE_SHIFT - 10))
> +
> + def page_K(self, remote_value):
> + # Obtain page value, and Convert from PAGES to KB
> + val = int(gdb.parse_and_eval(remote_value))
> + return self.K(val)
> +
> + def gps(self, enum_zone_stat_item):
> + # Access the Global Page State structure
> + # I would prefer to read this structure in one go and then index
> + # from the enum. But we can't determine the enum values with out
> + # a call to GDB anyway so we may as well take the easy route and
> + # get the value.
> + remote_value = "vm_stat[" + enum_zone_stat_item + "].counter"
> + return int(gdb.parse_and_eval(remote_value))
> +
> + def gps_K(self, enum_zone_stat_item):
> + return self.K(self.gps(enum_zone_stat_item))
> +
> + def nr_blockdev_pages(self):
> + bdevs_head = gdb.parse_and_eval("all_bdevs")
> + pages = 0
> + for bdev in lists.list_for_each_entry(bdevs_head, bdev_ptr_type, "bd_list"):
> + try:
> + pages += bdev['bd_inode']['i_mapping']['nrpages']
> + except:
> + # Any memory read failures are simply not counted
> + pass
> + return pages
> +
> + def total_swapcache_pages(self):
> + pages = 0
> + if not constants.LX_CONFIG_SWAP:
> + return 0
> +
> + for i in range(0, int(constants.LX_MAX_SWAPFILES)):
> + swap_space = "swapper_spaces[" + str(i) + "].nrpages"
> + pages += int(gdb.parse_and_eval(swap_space))
> + return pages
> +
> + def vm_commit_limit(self, totalram_pages):
> + total_swap_pages = 0
> + overcommit = int(gdb.parse_and_eval("sysctl_overcommit_kbytes"))
> + overcommit_ratio = int(gdb.parse_and_eval("sysctl_overcommit_ratio"))
> +
> + if constants.LX_CONFIG_SWAP:
> + total_swap_pages = int(gdb.parse_and_eval("total_swap_pages"))
> +
> + hugetlb_total_pages = 0 # hugetlb_total_pages()
> +
> + if overcommit:
> + allowed = overcommit >> (constants.LX_PAGE_SHIFT - 10)
> + else:
> + allowed = ((totalram_pages - hugetlb_total_pages *
> + overcommit_ratio / 100))
> +
> + allowed += total_swap_pages
> + return allowed
> +
> + def quicklist_total_size(self):
> + count = 0
> + quicklist = utils.gdb_eval_or_none("quicklist")
> + if quicklist is None:
> + return 0
> +
> + for cpu in cpus.each_online_cpu():
> + ql = cpus.per_cpu(quicklist, cpu)
> + for q in range(0, constants.LX_CONFIG_NR_QUICK):
> + # for (q = ql; q < ql + CONFIG_NR_QUICK; q++)
> + # count += q->nr_pages
> + count += ql[q]['nr_pages']
> +
> + return count
> +
> + # Main lx-meminfo command execution
> + # See fs/proc/meminfo.c:meminfo_proc_show()
> + def invoke(self, arg, from_tty):
> + totalram = int(gdb.parse_and_eval("totalram_pages"))
> + freeram = self.gps("NR_FREE_PAGES")
> + reclaimable = self.gps("NR_SLAB_RECLAIMABLE")
> + unreclaimable = self.gps("NR_SLAB_UNRECLAIMABLE")
> + slab = reclaimable + unreclaimable
> + # for_each_zone(zone)
> + # wmark_low += zone->watermark[WMARK_LOW];
> + wmark_low = 0 # Zone parsing is unimplemented
> +
> + available = freeram - wmark_low
> + available += reclaimable - min(reclaimable / 2, wmark_low)
> +
> + bufferram = self.nr_blockdev_pages()
> + total_swapcache_pages = self.total_swapcache_pages()
> +
> + file_pages = self.gps("NR_FILE_PAGES")
> + cached = file_pages - total_swapcache_pages - bufferram
> +
> + # LRU Pages
> + active_pages_anon = self.gps("NR_ACTIVE_ANON")
> + inactive_pages_anon = self.gps("NR_INACTIVE_ANON")
> + active_pages_file = self.gps("NR_ACTIVE_FILE")
> + inactive_pages_file = self.gps("NR_INACTIVE_FILE")
> + unevictable_pages = self.gps("NR_UNEVICTABLE")
> + active_pages = active_pages_anon + active_pages_file
> + inactive_pages = inactive_pages_anon + inactive_pages_file
> +
> + kernelstack = int(self.gps("NR_KERNEL_STACK") *
> + constants.LX_THREAD_SIZE / 1024)
> +
> + commitlimit = int(self.vm_commit_limit(totalram))
> + committed_as = int(gdb.parse_and_eval("vm_committed_as.count"))
> +
> + vmalloc_total = int(constants.LX_VMALLOC_TOTAL >> 10)
> +
> + gdb.write(
> + "MemTotal: {:8d} kB\n".format(self.K(totalram)) +
> + "MemFree: {:8d} kB\n".format(self.K(freeram)) +
> + "MemAvailable: {:8d} kB\n".format(self.K(available)) +
> + "Buffers: {:8d} kB\n".format(self.K(bufferram)) +
> + "Cached: {:8d} kB\n".format(self.K(cached)) +
> + "SwapCached: {:8d} kB\n".format(self.K(total_swapcache_pages)) +
> + "Active: {:8d} kB\n".format(self.K(active_pages)) +
> + "Inactive: {:8d} kB\n".format(self.K(inactive_pages)) +
> + "Active(anon): {:8d} kB\n".format(self.K(active_pages_anon)) +
> + "Inactive(anon): {:8d} kB\n".format(self.K(inactive_pages_anon)) +
> + "Active(file): {:8d} kB\n".format(self.K(active_pages_file)) +
> + "Inactive(file): {:8d} kB\n".format(self.K(inactive_pages_file)) +
> + "Unevictable: {:8d} kB\n".format(self.K(unevictable_pages)) +
> + "Mlocked: {:8d} kB\n".format(self.gps_K("NR_MLOCK"))
> + )
> + if constants.LX_CONFIG_HIGHMEM:
> + totalhigh = int(gdb.parse_and_eval("totalhigh_pages"))
> + freehigh = int(gdb.parse_and_eval("nr_free_highpages()"))
> + gdb.write(
> + "HighTotal: {:8d} kB\n".format(self.K(totalhigh)) +
> + "HighFree: {:8d} kB\n".format(self.K(freehigh)) +
> + "LowTotal: {:8d} kB\n".format(self.K(totalram-totalhigh)) +
> + "LowFree: {:8d} kB\n".format(self.K(freeram-freehigh))
> + )
> + if not constants.LX_CONFIG_MMU:
> + mmap_pages_allocated = gdb.parse_and_eval("mmap_pages_allocated.counter")
> + gdb.write(
> + "MmapCopy: {:8d} kB\n".format(self.K(mmap_pages_allocated))
> +
> + )
> + pass
Hrm ... No idea where this 'pass' statement crept in ... It has been
dropped for the next patch version.
> +
> + gdb.write(
> + "SwapTotal: {:8d} kB\n".format(self.K(0)) +
> + "SwapFree: {:8d} kB\n".format(self.K(0)) +
> + "Dirty: {:8d} kB\n".format(self.gps_K("NR_FILE_DIRTY")) +
> + "Writeback: {:8d} kB\n".format(self.gps_K("NR_WRITEBACK")) +
> + "AnonPages: {:8d} kB\n".format(self.gps_K("NR_ANON_PAGES")) +
> + "Mapped: {:8d} kB\n".format(self.gps_K("NR_FILE_MAPPED")) +
> + "Shmem: {:8d} kB\n".format(self.gps_K("NR_SHMEM")) +
> + "Slab: {:8d} kB\n".format(self.K(slab)) +
> + "SReclaimable: {:8d} kB\n".format(self.K(reclaimable)) +
> + "SUnreclaim: {:8d} kB\n".format(self.K(unreclaimable)) +
> + "KernelStack: {:8d} kB\n".format(kernelstack) +
> + "PageTables: {:8d} kB\n".format(self.gps_K("NR_PAGETABLE"))
> + )
> +
> + if constants.LX_CONFIG_QUICKLIST:
> + quicklist = self.quicklist_total_size()
> + gdb.write(
> + "Quicklists: {:8d} kB\n".format(self.K(quicklist))
> + )
> +
> + gdb.write(
> + "NFS_Unstable: {:8d} kB\n".format(self.gps_K("NR_UNSTABLE_NFS")) +
> + "Bounce: {:8d} kB\n".format(self.gps_K("NR_BOUNCE")) +
> + "WritebackTmp: {:8d} kB\n".format(self.gps_K("NR_WRITEBACK_TEMP"))
> + )
> +
> + gdb.write(
> + "CommitLimit: {:8d} kB\n".format(self.K(commitlimit)) +
> + "Committed_AS: {:8d} kB\n".format(self.K(committed_as)) +
> + "VmallocTotal: {:8d} kB\n".format(vmalloc_total)
> + )
> +
> + # These are always zero now
> + gdb.write(
> + "VmallocUsed: {:8d} kB\n".format(0) +
> + "VmallocChunk: {:8d} kB\n".format(0)
> + )
> +
> + if constants.LX_CONFIG_MEMORY_FAILURE:
> + gdb.write(
> + "HardwareCorrupted: {:8d} kB\n"
> + )
> + if constants.LX_CONFIG_TRANSPARENT_HUGEPAGE:
> + huge = self.gps("NR_ANON_TRANSPARENT_HUGEPAGES")
> + # HPAGE_PMD_NR can not be determined in constants.py
> + gdb.write(
> + "AnonHugePages: {:8d} kB ( * HPAGE_PMD_NR )\n"
> + .format(self.K(huge))
> + )
> + if constants.LX_CONFIG_CMA:
> + totalcma_pages = int(gdb.parse_and_eval("totalcma_pages"))
> + gdb.write(
> + "CmaTotal: {:8d} kB\n".format(self.K(totalcma_pages)) +
> + "CmaFree: {:8d} kB\n".format(self.gps_K("NR_FREE_CMA_PAGES"))
> + )
> +
> +LxMeminfo()
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands
2016-02-22 15:24 [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Kieran Bingham
` (7 preceding siblings ...)
2016-02-22 15:24 ` [PATCH 8/8] scripts/gdb: Add meminfo command Kieran Bingham
@ 2016-02-29 16:36 ` Jan Kiszka
2016-02-29 17:01 ` Kieran Bingham
8 siblings, 1 reply; 12+ messages in thread
From: Jan Kiszka @ 2016-02-29 16:36 UTC (permalink / raw)
To: Kieran Bingham, linux-kernel; +Cc: lee.jones, peter.griffin, maxime.coquelin
Hi Kieran,
On 2016-02-22 16:24, Kieran Bingham wrote:
> Sending this revised series, which now provides ability to transfer configured
> constants from the kernel to the python layer through the constants.py
> infrastructure.
>
> The iterators have been improved, in this instance thanks to the versions by
> Jeff Mahoney on his py-kdump work; (which were better than mine, so I dropped
> mine to replace with his)
>
> Testing on an STM32, brought up a couple of issues with !CONFIG_MMU and
> !CONFIG_MODULES which have been repaired, and further updates to both the
> lx-mounts and lx-meminfo commands for fixes and improvements.
>
> For convenience, this patch set submission can be found at
> http://git.linaro.org/people/kieran.bingham/linux.git gdb-scripts-2016-02-22-lkml-submission
Thanks for the updated patches! This is just a note that review and
testing are still in my queue...
Jan
--
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands
2016-02-29 16:36 ` [PATCHv2 0/8] gdb/scripts: Linux awareness debug commands Jan Kiszka
@ 2016-02-29 17:01 ` Kieran Bingham
0 siblings, 0 replies; 12+ messages in thread
From: Kieran Bingham @ 2016-02-29 17:01 UTC (permalink / raw)
To: Jan Kiszka, linux-kernel; +Cc: lee.jones, peter.griffin, maxime.coquelin
On 29/02/16 16:36, Jan Kiszka wrote:
> Hi Kieran,
>
> On 2016-02-22 16:24, Kieran Bingham wrote:
>> Sending this revised series, which now provides ability to transfer configured
>> constants from the kernel to the python layer through the constants.py
>> infrastructure.
>>
>> The iterators have been improved, in this instance thanks to the versions by
>> Jeff Mahoney on his py-kdump work; (which were better than mine, so I dropped
>> mine to replace with his)
>>
>> Testing on an STM32, brought up a couple of issues with !CONFIG_MMU and
>> !CONFIG_MODULES which have been repaired, and further updates to both the
>> lx-mounts and lx-meminfo commands for fixes and improvements.
>>
>> For convenience, this patch set submission can be found at
>> http://git.linaro.org/people/kieran.bingham/linux.git gdb-scripts-2016-02-22-lkml-submission
>
> Thanks for the updated patches! This is just a note that review and
> testing are still in my queue...
Not a problem,
Thanks for the update.
--
Kieran
> Jan
>
^ permalink raw reply [flat|nested] 12+ messages in thread