Thread (10 messages) 10 messages, 3 authors, 2016-10-18

[PATCH 1/2] scripts/gdb: add lx-fdtdump command

From: peter.griffin@linaro.org (Peter Griffin)
Date: 2016-10-18 16:32:22
Also in: linux-devicetree, lkml

Hi Kieran,

Thanks for reviewing.

On Tue, 18 Oct 2016, Kieran Bingham wrote:
Hi Pete,

Thanks for your patch.

On 18/10/16 16:07, Peter Griffin wrote:
quoted
lx-fdtdump dumps the flatenned device tree passed to the kernel
s/flatenned/flattened/
quoted
from the bootloader to a file called fdtdump.dtb to allow further
post processing on the machine running GDB. The fdt header is also
also printed in the GDB console. For example:
Excellent - I've been looking forward to this

General comment: It would be good to see the output filename
configurable as a parameter, defaulting to fdtdump.dtb if none provided.

Is this something you have time to add?
Have added this in v2 :)
quoted
(gdb) lx-fdtdump
fdt_magic:         0xD00DFEED
fdt_totalsize:     0xC108
off_dt_struct:     0x38
off_dt_strings:    0x3804
off_mem_rsvmap:    0x28
version:           17
last_comp_version: 16
Dumped fdt to fdtdump.dtb
quoted
fdtdump fdtdump.dtb | less
This command is useful as the bootloader can often re-write parts
of the device tree, and this can sometimes cause the kernel to not
boot.

Signed-off-by: Peter Griffin <peter.griffin@linaro.org>
---
 scripts/gdb/linux/constants.py.in |  8 +++++
 scripts/gdb/linux/proc.py         | 70 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in
index 7986f4e..43c6241 100644
--- a/scripts/gdb/linux/constants.py.in
+++ b/scripts/gdb/linux/constants.py.in
@@ -14,6 +14,7 @@
 
 #include <linux/fs.h>
 #include <linux/mount.h>
+#include <linux/of_fdt.h>
 
 /* We need to stringify expanded macros so that they can be parsed */
 
@@ -50,3 +51,10 @@ LX_VALUE(MNT_NOEXEC)
 LX_VALUE(MNT_NOATIME)
 LX_VALUE(MNT_NODIRATIME)
 LX_VALUE(MNT_RELATIME)
+
+/* linux/of_fdt.h> */
+LX_VALUE(OF_DT_HEADER)
+
+/* Kernel Configs */
+LX_CONFIG(CONFIG_OF)
+
diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py
index 38b1f09..f20fcfa 100644
--- a/scripts/gdb/linux/proc.py
+++ b/scripts/gdb/linux/proc.py
@@ -16,7 +16,7 @@ from linux import constants
 from linux import utils
 from linux import tasks
 from linux import lists
-
+from struct import *
 
 class LxCmdLine(gdb.Command):
     """ Report the Linux Commandline used in the current kernel.
@@ -195,3 +195,71 @@ values of that process namespace"""
                         info_opts(MNT_INFO, m_flags)))
 
 LxMounts()
+
+class LxFdtDump(gdb.Command):
+    """Output Flattened Device Tree header and dump FDT blob to a file
+       Equivalent to 'cat /proc/fdt > fdtdump.dtb' on a running target"""
+
+    def __init__(self):
+        super(LxFdtDump, self).__init__("lx-fdtdump", gdb.COMMAND_DATA)
+
+    def fdthdr_to_cpu(self, fdt_header):
+
+            fdt_header_be = ">IIIIIII"
+            fdt_header_le = "<IIIIIII"
+
+            if utils.get_target_endianness() == 1:
+                output_fmt = fdt_header_le
+            else:
+                output_fmt = fdt_header_be
+
+            return unpack(output_fmt, pack(fdt_header_be,
+                                           fdt_header['magic'],
+                                           fdt_header['totalsize'],
+                                           fdt_header['off_dt_struct'],
+                                           fdt_header['off_dt_strings'],
+                                           fdt_header['off_mem_rsvmap'],
+                                           fdt_header['version'],
+                                           fdt_header['last_comp_version']))
+
+    def invoke(self, arg, from_tty):
+
+        if constants.LX_CONFIG_OF:
+
+            filename = "fdtdump.dtb"
+
You could parse the arguments here to allow users to write to their own
file / path ... arg is just a string, so you can either parse it as such
or convert to argv with
	argv = gdb.string_to_argv(arg)


Aha - I see Jan beat me to it :)

quoted
+            py_fdt_header_ptr = gdb.parse_and_eval(
+                "(const struct fdt_header *) initial_boot_params")
+            py_fdt_header = py_fdt_header_ptr.dereference()
+
+            fdt_header = self.fdthdr_to_cpu(py_fdt_header)
+
+            if fdt_header[0] != constants.LX_OF_DT_HEADER:
+                raise gdb.GdbError("No flattened device tree magic found\n")
+
+            gdb.write("fdt_magic:         0x{:02X}\n".format(fdt_header[0]))
+            gdb.write("fdt_totalsize:     0x{:02X}\n".format(fdt_header[1]))
+            gdb.write("off_dt_struct:     0x{:02X}\n".format(fdt_header[2]))
+            gdb.write("off_dt_strings:    0x{:02X}\n".format(fdt_header[3]))
+            gdb.write("off_mem_rsvmap:    0x{:02X}\n".format(fdt_header[4]))
+            gdb.write("version:           {}\n".format(fdt_header[5]))
+            gdb.write("last_comp_version: {}\n".format(fdt_header[6]))
+
+            inf = gdb.inferiors()[0]
+            fdt_buf = utils.read_memoryview(inf, py_fdt_header_ptr,
+                                            fdt_header[1]).tobytes()
+
+            try:
+                f = open(filename, 'wb')
+            except:
+                raise gdb.GdbError("Could not open file to dump fdt")
+
+            f.write(fdt_buf)
+            f.close()
+
+            gdb.write("Dumped fdt to " + filename + "\n")
+
+        else:
+            gdb.write("Kernel not compiled with CONFIG_OF\n")
Would it be cleaner to write
  if not constants.LX_CONFIG_OF:
      raise gdb.GdbError("Kernel not compiled with CONFIG_OF\n")

at the beginning, and reduce the indentation level required ?
Good idea, have updated like you suggest in V2 and reduced the
indentation.

regards,

Peter
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help