1
0
Fork 0
forked from nuttx/nuttx-update

tools/gdb: remove 'Nx' prefix for unique commands

1. Remove Nx prefix for nuttx unique commands.
2. Add docstring for most of the commands in order to show help message.
3. Add 'init_once' method for Memmap command. The prerequisite is checked the moment it's used.

Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
xuxingliang 2024-08-14 13:49:56 +08:00 committed by Xiang Xiao
parent 3a46b6e6af
commit de5f70b3c8
3 changed files with 84 additions and 55 deletions

View file

@ -218,12 +218,12 @@ def dq_check(dq):
gdb.write("dq_queue is consistent: {} node(s)\n".format(nb))
class Nxlistcheck(gdb.Command):
class ListCheck(gdb.Command):
"""Verify a list consistency"""
def __init__(self):
super(Nxlistcheck, self).__init__(
"listcheck", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION
super(ListCheck, self).__init__(
"list_check", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION
)
def invoke(self, arg, from_tty):
@ -240,23 +240,22 @@ class Nxlistcheck(gdb.Command):
raise gdb.GdbError("Invalid argument type: {}".format(obj.type))
Nxlistcheck()
class Nxlistforentry(gdb.Command):
class ListForEveryEntry(gdb.Command):
"""Dump list members for a given list"""
def __init__(self):
super(Nxlistforentry, self).__init__(
"listforentry", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION
super(ListForEveryEntry, self).__init__(
"list_for_every_entry", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION
)
def invoke(self, arg, from_tty):
argv = gdb.string_to_argv(arg)
if len(argv) != 3:
gdb.write("listforentry takes three arguments" "head, type, member\n")
gdb.write("eg: listforentry &g_list 'struct type' 'node '\n")
gdb.write(
"list_for_every_entry takes three arguments" "head, type, member\n"
)
gdb.write("eg: list_for_every_entry &g_list 'struct type' 'node '\n")
return
i = 0
@ -268,4 +267,5 @@ class Nxlistforentry(gdb.Command):
i += 1
Nxlistforentry()
ListCheck()
ListForEveryEntry()

View file

@ -27,13 +27,6 @@ import gdb
from lists import sq_for_every, sq_queue_type
from utils import get_long_type, get_symbol_value, lookup_type, read_ulong
try:
import numpy as np
from matplotlib import pyplot as plt
except ImportError:
print("Please install matplotlib and numpy to use this command")
print("pip install matplotlib numpy")
MM_ALLOC_BIT = 0x1
MM_PREVFREE_BIT = 0x2
MM_MASK_BIT = MM_ALLOC_BIT | MM_PREVFREE_BIT
@ -784,6 +777,27 @@ have {i} some backtrace leak, total leak memory is {int(leaksize)} bytes\n"
class Memmap(gdb.Command):
def __init__(self):
super(Memmap, self).__init__("memmap", gdb.COMMAND_USER)
self.initialized = False
def init_once(self) -> bool:
"""
Return True if all prerequisites are met and perform one-time initialization.
"""
if self.initialized:
return True
try:
import numpy as np
from matplotlib import pyplot as plt
except ImportError:
print("Please install matplotlib and numpy to use this command")
print("pip install matplotlib numpy")
return False
self.np = np
self.plt = plt
self.initialized = True
return True
def save_memory_map(self, mallinfo, output_file):
mallinfo = sorted(mallinfo, key=lambda item: item["addr"])
@ -791,7 +805,7 @@ class Memmap(gdb.Command):
size = mallinfo[-1]["addr"] - start
order = math.ceil(size**0.5)
img = np.zeros([order, order])
img = self.np.zeros([order, order])
for node in mallinfo:
addr = node["addr"]
@ -800,7 +814,7 @@ class Memmap(gdb.Command):
end_index = start_index + size
img.flat[start_index:end_index] = 1 + math.log2(node["sequence"] + 1)
plt.imsave(output_file, img, cmap=plt.get_cmap("Greens"))
self.plt.imsave(output_file, img, cmap=self.plt.get_cmap("Greens"))
def allocinfo(self):
info = []
@ -831,16 +845,13 @@ class Memmap(gdb.Command):
return args.output
def invoke(self, args, from_tty):
if not self.init_once():
return
output_file = self.parse_arguments(args.split(" "))
meminfo = self.allocinfo()
self.save_memory_map(meminfo, output_file + ".png")
Memdump()
Memleak()
Memmap()
class Memfrag(gdb.Command):
def __init__(self):
super(Memfrag, self).__init__("memfrag", gdb.COMMAND_USER)
@ -899,3 +910,6 @@ class Memfrag(gdb.Command):
Memfrag()
Memdump()
Memleak()
Memmap()

View file

@ -1,8 +1,6 @@
############################################################################
# tools/gdb/thread.py
#
# SPDX-License-Identifier: Apache-2.0
#
# 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
@ -20,6 +18,7 @@
#
############################################################################
import argparse
from enum import Enum, auto
import gdb
@ -36,7 +35,7 @@ def save_regs():
global saved_regs
tcbinfo = gdb.parse_and_eval("g_tcbinfo")
if saved_regs is not None:
if saved_regs:
return
arch = gdb.selected_frame().architecture()
saved_regs = []
@ -53,7 +52,7 @@ def restore_regs():
tcbinfo = gdb.parse_and_eval("g_tcbinfo")
global saved_regs
if saved_regs is None:
if not saved_regs:
return
arch = gdb.selected_frame().architecture()
@ -68,42 +67,50 @@ def restore_regs():
saved_regs = None
class Nxsetregs(gdb.Command):
"""
Set registers to the specified values.
Usage: nxsetregs [regs]
class SetRegs(gdb.Command):
"""Set registers to the specified values.
Usage: setregs [regs]
Etc: nxsetregs
nxsetregs g_current_regs[0]
nxsetregs tcb->xcp.regs
Nxsetregs g_pidhash[0].tcb->xcp.regs
Default regs is g_current_regs[0],if regs is NULL, it will not set registers.
Etc: setregs
setregs tcb->xcp.regs
setregs g_pidhash[0]->xcp.regs
Default regs is tcbinfo_current_regs(),if regs is NULL, it will not set registers.
"""
def __init__(self):
super(Nxsetregs, self).__init__("nxsetregs", gdb.COMMAND_USER)
super(SetRegs, self).__init__("setregs", gdb.COMMAND_USER)
def invoke(self, args, from_tty):
gdb.execute("set $_current_regs=tcbinfo_running_regs()")
current_regs = gdb.parse_and_eval("$_current_regs")
tcbinfo = gdb.parse_and_eval("g_tcbinfo")
arg = args.split(" ")
def invoke(self, arg, from_tty):
parser = argparse.ArgumentParser(
description="Set registers to the specified values"
)
if arg[0] != "":
regs = gdb.parse_and_eval(f"{arg[0]}").cast(
parser.add_argument(
"regs",
nargs="?",
default="",
help="The registers to set, use tcbinfo_current_regs() if not specified",
)
try:
args = parser.parse_args(gdb.string_to_argv(arg))
except SystemExit:
return
if args and args.regs:
regs = gdb.parse_and_eval(f"{args.regs}").cast(
utils.lookup_type("char").pointer()
)
else:
gdb.execute("set $_current_regs=tcbinfo_current_regs()")
current_regs = gdb.parse_and_eval("$_current_regs")
current_regs = gdb.parse_and_eval("tcbinfo_current_regs()")
regs = current_regs.cast(utils.lookup_type("char").pointer())
if regs == 0:
gdb.write("regs is NULL\n")
return
tcbinfo = gdb.parse_and_eval("g_tcbinfo")
save_regs()
arch = gdb.selected_frame().architecture()
i = 0
@ -122,6 +129,8 @@ class Nxsetregs(gdb.Command):
class Nxinfothreads(gdb.Command):
"""Display information of all threads"""
def __init__(self):
super(Nxinfothreads, self).__init__("info threads", gdb.COMMAND_USER)
@ -211,6 +220,8 @@ class Nxinfothreads(gdb.Command):
class Nxthread(gdb.Command):
"""Switch to a specified thread"""
def __init__(self):
super(Nxthread, self).__init__("thread", gdb.COMMAND_USER)
@ -237,7 +248,7 @@ class Nxthread(gdb.Command):
except gdb.error and UnicodeDecodeError:
gdb.write(f"Thread {i}\n")
gdb.execute(f"nxsetregs g_pidhash[{i}]->xcp.regs")
gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs")
cmd_arg = ""
for cmd in arg[2:]:
cmd_arg += cmd + " "
@ -269,7 +280,7 @@ class Nxthread(gdb.Command):
except gdb.error and UnicodeDecodeError:
gdb.write(f"Thread {i}\n")
gdb.execute(f"nxsetregs g_pidhash[{i}]->xcp.regs")
gdb.execute(f"setregs g_pidhash[{i}]->xcp.regs")
gdb.execute(f"{cmd}\n")
restore_regs()
@ -280,12 +291,14 @@ class Nxthread(gdb.Command):
):
restore_regs()
else:
gdb.execute("nxsetregs g_pidhash[%s]->xcp.regs" % arg[0])
gdb.execute("setregs g_pidhash[%s]->xcp.regs" % arg[0])
else:
gdb.write(f"Invalid thread id {arg[0]}\n")
class Nxcontinue(gdb.Command):
"""Restore the registers and continue the execution"""
def __init__(self):
super(Nxcontinue, self).__init__("nxcontinue", gdb.COMMAND_USER)
@ -295,6 +308,8 @@ class Nxcontinue(gdb.Command):
class Nxstep(gdb.Command):
"""Restore the registers and step the execution"""
def __init__(self):
super(Nxstep, self).__init__("nxstep", gdb.COMMAND_USER)
@ -500,7 +515,7 @@ class Ps(gdb.Command):
def register_commands():
Nxsetregs()
SetRegs()
Ps()
# Disable thread commands for core dump and gdb-stub.
@ -508,7 +523,7 @@ def register_commands():
ncpus = utils.get_symbol_value("CONFIG_SMP_NCPUS") or 1
nthreads = len(gdb.selected_inferior().threads())
if nthreads <= ncpus:
Nxsetregs()
SetRegs()
Nxinfothreads()
Nxthread()
Nxcontinue()