You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by "xiaoxiang781216 (via GitHub)" <gi...@apache.org> on 2023/06/22 08:05:13 UTC

[GitHub] [nuttx] xiaoxiang781216 commented on a diff in pull request #9568: Debug:support python script auto debug nuttx kernel

xiaoxiang781216 commented on code in PR #9568:
URL: https://github.com/apache/nuttx/pull/9568#discussion_r1238134731


##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4

Review Comment:
   ```
   PID_MM_FREE = -4
   PID_MM_ALLOC = -3
   PID_MM_LEAK = -2
   PID_MM_MEMPOOL = -1
   ```



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:

Review Comment:
   ```
   if next >= heap["mm_heapend"].dereference() or next == node:
   ```



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:
+                    dump = sq_for_every(pool["queue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+                if sq_is_empty(pool["iqueue"]) is False:
+                    dump = sq_for_every(pool["iqueue"], entry)

Review Comment:
   ditto



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:
+                    dump = sq_for_every(pool["queue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+                if sq_is_empty(pool["iqueue"]) is False:
+                    dump = sq_for_every(pool["iqueue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+            else:
+                for node in list_for_each_entry(
+                    pool["alist"], mempool_backtrace.get_type().pointer(), "node"
+                ):
+                    if (pid == node["pid"] or pid == MM_BACKTRACE_ALLOC_PID) and (
+                        node["seqno"] >= seqmin and node["seqno"] < seqmax
+                    ):
+                        charnode = gdb.Value(node).cast(
+                            gdb.lookup_type("char").pointer()
+                        )
+                        if node.type.has_key("backtrace"):
+                            max = node["backtrace"].type.range()[1]
+                            gdb.write(
+                                "%6d%12u%12u%#*x"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                            if node["backtrace"][0] != 0x0:
+                                for x in range(0, max):
+                                    gdb.write(" ")
+                                    gdb.write(
+                                        node["backtrace"][x].format_string(
+                                            raw=False, symbols=True, address=False
+                                        )
+                                    )
+
+                            gdb.write("\n")
+                        else:
+                            gdb.write(
+                                "%6d%12u%12u%#*x\n"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+    def memdump(self, pid, seqmin, seqmax):
+        """Dump the heap memory"""
+        if pid >= MM_BACKTRACE_ALLOC_PID:
+            gdb.write("Dump all used memory node info:\n")
+            gdb.write(
+                "%6s%12s%12s%*s %s\n"
+                % ("PID", "Size", "Sequence", self.align, "Address", "Callstack")
+            )
+        else:
+            gdb.write("Dump all free memory node info:\n")
+            gdb.write("%12s%*s\n" % ("Size", self.align, "Address"))
+
+        heap = gdb.parse_and_eval("g_mmheap")
+        if heap.type.has_key("mm_mpool"):
+            self.mempool_dump(heap["mm_mpool"], pid, seqmin, seqmax)
+
+        for node in mm_foreach(heap):
+            if node["size"] & MM_ALLOC_BIT != 0:
+                # skip mempool alloc node, we will dump it mempool dump
+                if (
+                    node["pid"] == MM_BACKTRACE_MEMPOOL_PID
+                    and pid != MM_BACKTRACE_MEMPOOL_PID
+                ):
+                    next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+                    next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+                        gdb.lookup_type("struct mm_allocnode_s").pointer()
+                    )
+                    if next > heap["mm_heapend"].dereference() or next == node:

Review Comment:
   >  to >=



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:
+                    dump = sq_for_every(pool["queue"], entry)
+                    for entry in dump:

Review Comment:
   for entry in sq_for_every(pool["queue"], entry)



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:

Review Comment:
   remove the empty check



##########
tools/gdb/lists.py:
##########
@@ -0,0 +1,252 @@
+############################################################################
+# tools/gdb/lists.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+
+list_node = utils.CachedType("struct list_node")
+sq_queue = utils.CachedType("sq_queue_t")
+dq_queue = utils.CachedType("dq_queue_t")
+
+
+def list_for_each(head):
+    """Iterate over a list"""
+    if head.type == list_node.get_type().pointer():
+        head = head.dereference()
+    elif head.type != list_node.get_type():
+        raise TypeError("Must be struct list_node not {}".format(head.type))
+
+    if head["next"] == 0:
+        gdb.write(
+            "list_for_each: Uninitialized list '{}' treated as empty\n".format(
+                head.address
+            )
+        )
+        return
+
+    node = head["next"].dereference()
+    while node.address != head.address:
+        yield node.address
+        node = node["next"].dereference()
+
+
+def list_for_each_entry(head, gdbtype, member):
+    """Iterate over a list of structs"""
+    for node in list_for_each(head):
+        yield utils.container_of(node, gdbtype, member)
+
+
+def list_check(head):
+    """Check the consistency of a list"""
+    nb = 0
+
+    if head.type == list_node.get_type().pointer():
+        head = head.dereference()
+    elif head.type != list_node.get_type():
+        raise gdb.GdbError("argument must be of type (struct list_node [*])")
+    c = head
+    try:
+        gdb.write("Starting with: {}\n".format(c))
+    except gdb.MemoryError:
+        gdb.write("head is not accessible\n")
+        return
+    while True:
+        p = c["prev"].dereference()
+        n = c["next"].dereference()
+        try:
+            if p["next"] != c.address:
+                gdb.write(
+                    "prev.next != current: "
+                    "current@{current_addr}={current} "
+                    "prev@{p_addr}={p}\n".format(
+                        current_addr=c.address,
+                        current=c,
+                        p_addr=p.address,
+                        p=p,
+                    )
+                )
+                return
+        except gdb.MemoryError:
+            gdb.write(
+                "prev is not accessible: "
+                "current@{current_addr}={current}\n".format(
+                    current_addr=c.address, current=c
+                )
+            )
+            return
+        try:
+            if n["prev"] != c.address:
+                gdb.write(
+                    "next.prev != current: "
+                    "current@{current_addr}={current} "
+                    "next@{n_addr}={n}\n".format(
+                        current_addr=c.address,
+                        current=c,
+                        n_addr=n.address,
+                        n=n,
+                    )
+                )
+                return
+        except gdb.MemoryError:
+            gdb.write(
+                "next is not accessible: "
+                "current@{current_addr}={current}\n".format(
+                    current_addr=c.address, current=c
+                )
+            )
+            return
+        c = n
+        nb += 1
+        if c == head:
+            gdb.write("list is consistent: {} node(s)\n".format(nb))
+            return
+
+
+def sq_for_every(sq, entry):
+    """Iterate over a singly linked list"""
+    if sq.type == sq_queue.get_type().pointer():
+        sq = sq.dereference()
+    elif sq.type != sq_queue.get_type():
+        gdb.write("Must be struct sq_queue not {}".format(sq.type))
+        return
+
+    if sq["head"] == 0:
+        gdb.write(
+            "sq_for_every: Uninitialized queue '{}' treated as empty\n".format(
+                sq.address
+            )
+        )
+
+        return
+
+    entry = sq["head"].dereference()
+
+    while entry.address:
+        yield entry.address
+        entry = entry["flink"].dereference()
+
+
+def sq_is_empty(sq):
+    """Check if a singly linked list is empty"""
+    if sq.type == sq_queue.get_type().pointer():
+        sq = sq.dereference()
+    elif sq.type != sq_queue.get_type():
+        return False
+
+    if sq["head"] == 0:
+        return True
+    else:
+        return False
+
+
+def sq_check(sq):
+    """Check the consistency of a singly linked list"""
+    nb = 0
+    if sq.type == sq_queue.get_type().pointer():
+        sq = sq.dereference()
+    elif sq.type != sq_queue.get_type():
+        gdb.write("Must be struct sq_queue not {}".format(sq.type))
+        return
+
+    if sq["head"] == 0:
+        gdb.write("sq_queue head is empty {}\n".format(sq.address))
+        return
+
+    entry = sq["head"].dereference()
+    try:
+        while entry.address:
+            nb += 1
+            entry = entry["flink"].dereference()
+    except gdb.MemoryError:
+        gdb.write("entry address is unaccessible {}\n".format(entry.address))
+        return
+
+    gdb.write("sq_queue is consistent: {} node(s)\n".format(nb))
+
+
+def dq_for_every(dq, entry):
+    """Iterate over a doubly linked list"""
+    if dq.type == dq_queue.get_type().pointer():
+        dq = dq.dereference()
+    elif dq.type != dq_queue.get_type():
+        gdb.write("Must be struct dq_queue not {}".format(dq.type))
+        return
+
+    if dq["head"] == 0:
+        gdb.write(
+            "dq_for_every: Uninitialized queue '{}' treated as empty\n".format(
+                dq.address
+            )
+        )
+
+        return
+    entry = dq["head"].dereference()
+    while entry.address:
+        yield entry.address
+        entry = entry["flink"].dereference()
+
+
+def dq_check(dq):
+    """Check the consistency of a doubly linked list"""
+    nb = 0
+    if dq.type == dq_queue.get_type().pointer():
+        dq = dq.dereference()
+    elif dq.type != dq_queue.get_type():
+        gdb.write("Must be struct dq_queue not {}".format(dq.type))
+        return
+
+    if dq["head"] == 0:
+        gdb.write("dq_queue head is empty {}\n".format(dq.address))
+        return
+    entry = dq["head"].dereference()
+    try:
+        while entry.address:
+            nb += 1
+            entry = entry["flink"].dereference()
+    except gdb.MemoryError:
+        gdb.write("entry address is unaccessible {}\n".format(entry.address))
+        return
+
+    gdb.write("dq_queue is consistent: {} node(s)\n".format(nb))
+
+
+class NxListChk(gdb.Command):

Review Comment:
   NxListChk->Nxlistcheck



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:
+                    dump = sq_for_every(pool["queue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+                if sq_is_empty(pool["iqueue"]) is False:
+                    dump = sq_for_every(pool["iqueue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+            else:
+                for node in list_for_each_entry(
+                    pool["alist"], mempool_backtrace.get_type().pointer(), "node"
+                ):
+                    if (pid == node["pid"] or pid == MM_BACKTRACE_ALLOC_PID) and (
+                        node["seqno"] >= seqmin and node["seqno"] < seqmax
+                    ):
+                        charnode = gdb.Value(node).cast(
+                            gdb.lookup_type("char").pointer()
+                        )
+                        if node.type.has_key("backtrace"):
+                            max = node["backtrace"].type.range()[1]
+                            gdb.write(
+                                "%6d%12u%12u%#*x"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                            if node["backtrace"][0] != 0x0:

Review Comment:
   remove the check



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:
+                    dump = sq_for_every(pool["queue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+                if sq_is_empty(pool["iqueue"]) is False:
+                    dump = sq_for_every(pool["iqueue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+            else:
+                for node in list_for_each_entry(
+                    pool["alist"], mempool_backtrace.get_type().pointer(), "node"
+                ):
+                    if (pid == node["pid"] or pid == MM_BACKTRACE_ALLOC_PID) and (
+                        node["seqno"] >= seqmin and node["seqno"] < seqmax
+                    ):
+                        charnode = gdb.Value(node).cast(
+                            gdb.lookup_type("char").pointer()
+                        )
+                        if node.type.has_key("backtrace"):
+                            max = node["backtrace"].type.range()[1]
+                            gdb.write(
+                                "%6d%12u%12u%#*x"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                            if node["backtrace"][0] != 0x0:
+                                for x in range(0, max):
+                                    gdb.write(" ")
+                                    gdb.write(
+                                        node["backtrace"][x].format_string(
+                                            raw=False, symbols=True, address=False
+                                        )
+                                    )
+
+                            gdb.write("\n")
+                        else:
+                            gdb.write(
+                                "%6d%12u%12u%#*x\n"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]

Review Comment:
   need ensure gdb command output the same result as nsh command



##########
tools/gdb/memdump.py:
##########
@@ -0,0 +1,269 @@
+############################################################################
+# tools/gdb/memdump.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+from lists import list_for_each_entry, sq_for_every, sq_is_empty, sq_queue
+
+mempool_backtrace = utils.CachedType("struct mempool_backtrace_s")
+
+MM_ALLOC_BIT = 0x1
+MM_PREVFREE_BIT = 0x2
+MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
+
+
+MM_BACKTRACE_INVALID_PID = -4
+MM_BACKTRACE_MEMPOOL_PID = -3
+MM_BACKTRACE_FREE_PID = -2
+MM_BACKTRACE_ALLOC_PID = -1
+
+
+def mm_foreach(heap):
+    """Iterate over a heap, yielding each node"""
+    node = gdb.Value(heap["mm_heapstart"][0]).cast(
+        gdb.lookup_type("struct mm_allocnode_s").pointer()
+    )
+    while 1:
+        yield node
+        next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+        next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+            gdb.lookup_type("struct mm_allocnode_s").pointer()
+        )
+        if next > heap["mm_heapend"].dereference() or next == node:
+            break
+        node = next
+
+
+def mempool_multiple_foreach(mpool):
+    """Iterate over all pools in a mempool, yielding each pool"""
+    i = 0
+    while i < mpool["npools"]:
+        pool = mpool["pools"] + i
+        yield pool
+        i += 1
+
+
+class Nxmemdump(gdb.Command):
+    """Dump the heap and mempool memory"""
+
+    def __init__(self):
+        super(Nxmemdump, self).__init__("memdump", gdb.COMMAND_USER)
+
+    def mempool_dump(self, mpool, pid, seqmin, seqmax):
+        """Dump the mempool memory"""
+        for pool in mempool_multiple_foreach(mpool):
+            if pid == MM_BACKTRACE_FREE_PID:
+                entry = sq_queue.get_type().pointer()
+
+                if sq_is_empty(pool["queue"]) is False:
+                    dump = sq_for_every(pool["queue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+                if sq_is_empty(pool["iqueue"]) is False:
+                    dump = sq_for_every(pool["iqueue"], entry)
+                    for entry in dump:
+                        gdb.write("%12u%#*x\n" % (pool["blocksize"], self.align, entry))
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+            else:
+                for node in list_for_each_entry(
+                    pool["alist"], mempool_backtrace.get_type().pointer(), "node"
+                ):
+                    if (pid == node["pid"] or pid == MM_BACKTRACE_ALLOC_PID) and (
+                        node["seqno"] >= seqmin and node["seqno"] < seqmax
+                    ):
+                        charnode = gdb.Value(node).cast(
+                            gdb.lookup_type("char").pointer()
+                        )
+                        if node.type.has_key("backtrace"):
+                            max = node["backtrace"].type.range()[1]
+                            gdb.write(
+                                "%6d%12u%12u%#*x"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                            if node["backtrace"][0] != 0x0:
+                                for x in range(0, max):
+                                    gdb.write(" ")
+                                    gdb.write(
+                                        node["backtrace"][x].format_string(
+                                            raw=False, symbols=True, address=False
+                                        )
+                                    )
+
+                            gdb.write("\n")
+                        else:
+                            gdb.write(
+                                "%6d%12u%12u%#*x\n"
+                                % (
+                                    node["pid"],
+                                    pool["blocksize"] & ~MM_MASK_BIT,
+                                    node["seqno"],
+                                    self.align,
+                                    (int)(charnode - pool["blocksize"]),
+                                )
+                            )
+                        self.aordblks += 1
+                        self.uordblks += pool["blocksize"]
+
+    def memdump(self, pid, seqmin, seqmax):
+        """Dump the heap memory"""
+        if pid >= MM_BACKTRACE_ALLOC_PID:
+            gdb.write("Dump all used memory node info:\n")
+            gdb.write(
+                "%6s%12s%12s%*s %s\n"
+                % ("PID", "Size", "Sequence", self.align, "Address", "Callstack")
+            )
+        else:
+            gdb.write("Dump all free memory node info:\n")
+            gdb.write("%12s%*s\n" % ("Size", self.align, "Address"))
+
+        heap = gdb.parse_and_eval("g_mmheap")
+        if heap.type.has_key("mm_mpool"):
+            self.mempool_dump(heap["mm_mpool"], pid, seqmin, seqmax)
+
+        for node in mm_foreach(heap):
+            if node["size"] & MM_ALLOC_BIT != 0:
+                # skip mempool alloc node, we will dump it mempool dump
+                if (
+                    node["pid"] == MM_BACKTRACE_MEMPOOL_PID
+                    and pid != MM_BACKTRACE_MEMPOOL_PID
+                ):
+                    next = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+                    next = gdb.Value(next + (node["size"] & ~MM_MASK_BIT)).cast(
+                        gdb.lookup_type("struct mm_allocnode_s").pointer()
+                    )
+                    if next > heap["mm_heapend"].dereference() or next == node:
+                        break
+                    node = next
+                    continue
+
+                if (pid == node["pid"] or pid == MM_BACKTRACE_ALLOC_PID) and (
+                    node["seqno"] >= seqmin and node["seqno"] < seqmax
+                ):
+                    charnode = gdb.Value(node).cast(gdb.lookup_type("char").pointer())
+                    if node.type.has_key("backtrace"):

Review Comment:
   merge backtrace check with line 186



##########
tools/gdb/lists.py:
##########
@@ -0,0 +1,252 @@
+############################################################################
+# tools/gdb/lists.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+import gdb
+import utils
+
+list_node = utils.CachedType("struct list_node")
+sq_queue = utils.CachedType("sq_queue_t")
+dq_queue = utils.CachedType("dq_queue_t")
+
+
+def list_for_each(head):
+    """Iterate over a list"""
+    if head.type == list_node.get_type().pointer():
+        head = head.dereference()
+    elif head.type != list_node.get_type():
+        raise TypeError("Must be struct list_node not {}".format(head.type))
+
+    if head["next"] == 0:
+        gdb.write(
+            "list_for_each: Uninitialized list '{}' treated as empty\n".format(
+                head.address
+            )
+        )
+        return
+
+    node = head["next"].dereference()
+    while node.address != head.address:
+        yield node.address
+        node = node["next"].dereference()
+
+
+def list_for_each_entry(head, gdbtype, member):
+    """Iterate over a list of structs"""
+    for node in list_for_each(head):
+        yield utils.container_of(node, gdbtype, member)
+
+
+def list_check(head):
+    """Check the consistency of a list"""
+    nb = 0
+
+    if head.type == list_node.get_type().pointer():
+        head = head.dereference()
+    elif head.type != list_node.get_type():
+        raise gdb.GdbError("argument must be of type (struct list_node [*])")
+    c = head
+    try:
+        gdb.write("Starting with: {}\n".format(c))
+    except gdb.MemoryError:
+        gdb.write("head is not accessible\n")
+        return
+    while True:
+        p = c["prev"].dereference()
+        n = c["next"].dereference()
+        try:
+            if p["next"] != c.address:
+                gdb.write(
+                    "prev.next != current: "
+                    "current@{current_addr}={current} "
+                    "prev@{p_addr}={p}\n".format(
+                        current_addr=c.address,
+                        current=c,
+                        p_addr=p.address,
+                        p=p,
+                    )
+                )
+                return
+        except gdb.MemoryError:
+            gdb.write(
+                "prev is not accessible: "
+                "current@{current_addr}={current}\n".format(
+                    current_addr=c.address, current=c
+                )
+            )
+            return
+        try:
+            if n["prev"] != c.address:
+                gdb.write(
+                    "next.prev != current: "
+                    "current@{current_addr}={current} "
+                    "next@{n_addr}={n}\n".format(
+                        current_addr=c.address,
+                        current=c,
+                        n_addr=n.address,
+                        n=n,
+                    )
+                )
+                return
+        except gdb.MemoryError:
+            gdb.write(
+                "next is not accessible: "
+                "current@{current_addr}={current}\n".format(
+                    current_addr=c.address, current=c
+                )
+            )
+            return
+        c = n
+        nb += 1
+        if c == head:
+            gdb.write("list is consistent: {} node(s)\n".format(nb))
+            return
+
+
+def sq_for_every(sq, entry):
+    """Iterate over a singly linked list"""
+    if sq.type == sq_queue.get_type().pointer():
+        sq = sq.dereference()
+    elif sq.type != sq_queue.get_type():
+        gdb.write("Must be struct sq_queue not {}".format(sq.type))
+        return
+
+    if sq["head"] == 0:
+        gdb.write(
+            "sq_for_every: Uninitialized queue '{}' treated as empty\n".format(
+                sq.address
+            )
+        )
+
+        return
+
+    entry = sq["head"].dereference()
+
+    while entry.address:
+        yield entry.address
+        entry = entry["flink"].dereference()
+
+
+def sq_is_empty(sq):
+    """Check if a singly linked list is empty"""
+    if sq.type == sq_queue.get_type().pointer():
+        sq = sq.dereference()
+    elif sq.type != sq_queue.get_type():
+        return False
+
+    if sq["head"] == 0:
+        return True
+    else:
+        return False
+
+
+def sq_check(sq):
+    """Check the consistency of a singly linked list"""
+    nb = 0
+    if sq.type == sq_queue.get_type().pointer():
+        sq = sq.dereference()
+    elif sq.type != sq_queue.get_type():
+        gdb.write("Must be struct sq_queue not {}".format(sq.type))
+        return
+
+    if sq["head"] == 0:
+        gdb.write("sq_queue head is empty {}\n".format(sq.address))
+        return
+
+    entry = sq["head"].dereference()
+    try:
+        while entry.address:
+            nb += 1
+            entry = entry["flink"].dereference()
+    except gdb.MemoryError:
+        gdb.write("entry address is unaccessible {}\n".format(entry.address))
+        return
+
+    gdb.write("sq_queue is consistent: {} node(s)\n".format(nb))
+
+
+def dq_for_every(dq, entry):
+    """Iterate over a doubly linked list"""
+    if dq.type == dq_queue.get_type().pointer():
+        dq = dq.dereference()
+    elif dq.type != dq_queue.get_type():
+        gdb.write("Must be struct dq_queue not {}".format(dq.type))
+        return
+
+    if dq["head"] == 0:
+        gdb.write(
+            "dq_for_every: Uninitialized queue '{}' treated as empty\n".format(
+                dq.address
+            )
+        )
+
+        return
+    entry = dq["head"].dereference()
+    while entry.address:
+        yield entry.address
+        entry = entry["flink"].dereference()
+
+
+def dq_check(dq):
+    """Check the consistency of a doubly linked list"""
+    nb = 0
+    if dq.type == dq_queue.get_type().pointer():
+        dq = dq.dereference()
+    elif dq.type != dq_queue.get_type():
+        gdb.write("Must be struct dq_queue not {}".format(dq.type))
+        return
+
+    if dq["head"] == 0:
+        gdb.write("dq_queue head is empty {}\n".format(dq.address))
+        return
+    entry = dq["head"].dereference()
+    try:
+        while entry.address:
+            nb += 1
+            entry = entry["flink"].dereference()
+    except gdb.MemoryError:
+        gdb.write("entry address is unaccessible {}\n".format(entry.address))
+        return
+
+    gdb.write("dq_queue is consistent: {} node(s)\n".format(nb))
+
+
+class NxListChk(gdb.Command):
+    """Verify a list consistency"""
+
+    def __init__(self):
+        super(NxListChk, self).__init__(
+            "nx-list-check", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION

Review Comment:
   nx-list-check->listcheck



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org