mirror of
https://github.com/apache/nuttx.git
synced 2026-05-21 21:34:07 +08:00
nxgdb/fs: simplify inode print and add more options
Use Inode.__repr__ for print and use single line for all information.
Add 'verbose' and 'nodetype' option to show more details and only print specifiy node type like PIPE.
Add / to name for pseudodir.
Catch memory error when accessing node element.
E.g.
(gdb) foreach inode --nodetype pipe
├── run/ 0x41a27a50 PSEUDODIR
│ ├── bt:bluetoothCS1fd26 0x4530c510 PIPE
│ ├── bt:bluetoothCS20 0x42daae40 PIPE
│ ├── socketpair0x457fd2e0SC20540 0x44ea27b0 PIPE
│ └── tmp/ 0x42dd7cf0 PSEUDODIR
│ │ └── usock/ 0x42dd6c10 PSEUDODIR
│ │ └── speech.usockHD 0x42dc8270 PIPE
│ ├── central_lite.socketCS5e 0x42e1e7b0 PIPE
│ ├── central_service_lite.socketSC86 0x432ee6d0 PIPE
│ │ └── usock/ 0x43d6ed60 PSEUDODIR
│ │ └── speech.usockHD 0x43da2ba0 PIPE
│ ├── uv-feature-sockSC8d 0x43540430 PIPE
│ ├── uv-miot-sockCS54 0x42e272e0 PIPE
│ └── uv-miot-sockSC54 0x42e270b0 PIPE
Signed-off-by: xuxingliang <xuxingliang@xiaomi.com>
This commit is contained in:
committed by
Alin Jerpelea
parent
dc5251f9c8
commit
8995e5a66e
+116
-79
@@ -27,7 +27,7 @@ from typing import Generator, Tuple
|
||||
import gdb
|
||||
|
||||
from . import utils
|
||||
from .protocols.fs import File, Inode
|
||||
from .protocols import fs as p
|
||||
from .protocols.thread import Tcb
|
||||
|
||||
FSNODEFLAG_TYPE_MASK = utils.get_symbol_value("FSNODEFLAG_TYPE_MASK")
|
||||
@@ -72,55 +72,91 @@ class InodeType(enum.Enum):
|
||||
UNKNOWN = 12
|
||||
|
||||
|
||||
def get_inode_name(inode: Inode):
|
||||
if not inode:
|
||||
return ""
|
||||
class Inode(utils.Value, p.Inode):
|
||||
def __init__(self, obj: gdb.Value | utils.Value):
|
||||
super().__init__(obj)
|
||||
|
||||
def special_inode_name(inode):
|
||||
global g_special_inodes
|
||||
if not g_special_inodes:
|
||||
g_special_inodes = {}
|
||||
for special in (
|
||||
"perf",
|
||||
"timerfd",
|
||||
"signalfd",
|
||||
"dir",
|
||||
"inotify",
|
||||
"epoll",
|
||||
"eventfd",
|
||||
"sock",
|
||||
):
|
||||
value = utils.gdb_eval_or_none(f"g_{special}_inode")
|
||||
if value:
|
||||
g_special_inodes[special] = value.address
|
||||
def __str__(self) -> str:
|
||||
name = get_inode_name(self)
|
||||
type = inode_gettype(self)
|
||||
return f"{name}{'/' if type == InodeType.PSEUDODIR else ''}{int(self): #x} {type.name}"
|
||||
|
||||
for name, value in g_special_inodes.items():
|
||||
if value == inode:
|
||||
return name
|
||||
def __repr__(self) -> str:
|
||||
return self.__str__()
|
||||
|
||||
return None
|
||||
def details(self) -> str:
|
||||
details = (
|
||||
f"ino: {self.i_ino}, crefs: {self.i_crefs}"
|
||||
f", flags: {self.i_flags}, private: {self.i_private}"
|
||||
)
|
||||
|
||||
if name := special_inode_name(inode):
|
||||
return name
|
||||
if CONFIG_PSEUDOFS_FILE:
|
||||
details += f", i_size: {self.i_size}"
|
||||
if CONFIG_PSEUDOFS_ATTRIBUTES:
|
||||
details += f", i_mode: {self.i_mode}, i_owner: {self.i_owner}, i_group: {self.i_group}"
|
||||
details += f", i_atime: {self.i_atime}, i_mtime: {self.i_mtime}, i_ctime: {self.i_ctime}"
|
||||
return details
|
||||
|
||||
ptr = inode.i_name.cast(gdb.lookup_type("char").pointer())
|
||||
return ptr.string()
|
||||
@property
|
||||
def nodetype(self) -> InodeType:
|
||||
return inode_gettype(self)
|
||||
|
||||
|
||||
def inode_getpath(inode: Inode):
|
||||
def get_inode_name(inode: p.Inode):
|
||||
try:
|
||||
if not inode:
|
||||
return ""
|
||||
|
||||
def special_inode_name(inode):
|
||||
global g_special_inodes
|
||||
if not g_special_inodes:
|
||||
g_special_inodes = {}
|
||||
for special in (
|
||||
"perf",
|
||||
"timerfd",
|
||||
"signalfd",
|
||||
"dir",
|
||||
"inotify",
|
||||
"epoll",
|
||||
"eventfd",
|
||||
"sock",
|
||||
):
|
||||
value = utils.gdb_eval_or_none(f"g_{special}_inode")
|
||||
if value:
|
||||
g_special_inodes[special] = value.address
|
||||
|
||||
for name, value in g_special_inodes.items():
|
||||
if value == inode:
|
||||
return name
|
||||
|
||||
return None
|
||||
|
||||
if name := special_inode_name(inode):
|
||||
return name
|
||||
|
||||
ptr = inode.i_name.cast(gdb.lookup_type("char").pointer())
|
||||
return ptr.string()
|
||||
except gdb.MemoryError:
|
||||
return "<MemoryError>"
|
||||
|
||||
|
||||
def inode_getpath(inode: p.Inode):
|
||||
"""get path fron inode"""
|
||||
if not inode:
|
||||
return ""
|
||||
try:
|
||||
if not inode:
|
||||
return ""
|
||||
|
||||
name = get_inode_name(inode)
|
||||
name = get_inode_name(inode)
|
||||
|
||||
if inode.i_parent:
|
||||
return inode_getpath(inode.i_parent) + "/" + name
|
||||
if inode.i_parent:
|
||||
return inode_getpath(inode.i_parent) + "/" + name
|
||||
|
||||
return name
|
||||
return name
|
||||
except gdb.MemoryError:
|
||||
return "<MemoryError>"
|
||||
|
||||
|
||||
def inode_gettype(inode: Inode) -> InodeType:
|
||||
def inode_gettype(inode: p.Inode) -> InodeType:
|
||||
if not inode:
|
||||
return InodeType.UNKNOWN
|
||||
|
||||
@@ -148,8 +184,8 @@ def get_file(tcb: Tcb, fd):
|
||||
return fl_files[row][col]
|
||||
|
||||
|
||||
def foreach_inode(root=None, path="") -> Generator[Tuple[Inode, str], None, None]:
|
||||
node: Inode = root or utils.parse_and_eval("g_root_inode").i_child
|
||||
def foreach_inode(root=None, path="") -> Generator[Tuple[p.Inode, str], None, None]:
|
||||
node: p.Inode = root or utils.parse_and_eval("g_root_inode").i_child
|
||||
while node:
|
||||
newpath = path + "/" + get_inode_name(node)
|
||||
yield node, newpath
|
||||
@@ -184,7 +220,7 @@ class Fdinfo(gdb.Command):
|
||||
super().__init__("fdinfo", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)
|
||||
self.total_fd_count = 0
|
||||
|
||||
def print_file_info(self, fd, file: File, formatter: str):
|
||||
def print_file_info(self, fd, file: p.File, formatter: str):
|
||||
backtrace_formatter = "{0:<5} {1:<36} {2}"
|
||||
|
||||
oflags = int(file.f_oflags)
|
||||
@@ -323,6 +359,19 @@ class ForeachInode(gdb.Command):
|
||||
default=4096,
|
||||
help="Only render the tree to a specific depth",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--nodetype",
|
||||
type=str,
|
||||
choices=[e.name.lower() for e in InodeType],
|
||||
default=None,
|
||||
help="Only show the specific type of inode",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-v",
|
||||
"--verbose",
|
||||
action="store_true",
|
||||
help="Show more information",
|
||||
)
|
||||
parser.add_argument(
|
||||
"addr_or_expr",
|
||||
type=str,
|
||||
@@ -330,6 +379,7 @@ class ForeachInode(gdb.Command):
|
||||
default=None,
|
||||
help="set the start inode to be tranversed",
|
||||
)
|
||||
|
||||
try:
|
||||
args = parser.parse_args(argv)
|
||||
except SystemExit:
|
||||
@@ -337,56 +387,34 @@ class ForeachInode(gdb.Command):
|
||||
|
||||
return args
|
||||
|
||||
def print_inode_info(self, node: Inode, level=1, prefix="", maxlevel=4096):
|
||||
def print_inode_info(
|
||||
self, node: Inode, level=1, prefix="", maxlevel=4096, type=None, verbose=False
|
||||
):
|
||||
if level > maxlevel:
|
||||
return
|
||||
|
||||
while node:
|
||||
if node.i_peer:
|
||||
initial_indent = prefix + "├── "
|
||||
subsequent_indent = prefix + "│ "
|
||||
newprefix = prefix + "│ "
|
||||
else:
|
||||
initial_indent = prefix + "└── "
|
||||
subsequent_indent = prefix + " "
|
||||
newprefix = prefix + " "
|
||||
gdb.write(
|
||||
"%s [%s], %s, %s\n"
|
||||
% (initial_indent, get_inode_name(node), node.i_ino, node)
|
||||
)
|
||||
gdb.write(
|
||||
"%s i_crefs: %s, i_flags: %s, i_private: %s\n"
|
||||
% (
|
||||
subsequent_indent,
|
||||
node.i_crefs,
|
||||
node.i_flags,
|
||||
node.i_private,
|
||||
)
|
||||
)
|
||||
if CONFIG_PSEUDOFS_FILE:
|
||||
gdb.write("%s i_size: %s\n" % (subsequent_indent, node.i_size))
|
||||
if CONFIG_PSEUDOFS_ATTRIBUTES:
|
||||
|
||||
if (
|
||||
not type
|
||||
or node.nodetype == type
|
||||
or any(n.i_parent == node for n, _ in self.nodes)
|
||||
):
|
||||
gdb.write(
|
||||
"%s i_mode: %s, i_owner: %s, i_group: %s\n"
|
||||
% (
|
||||
subsequent_indent,
|
||||
node.i_mode,
|
||||
node.i_owner,
|
||||
node.i_group,
|
||||
)
|
||||
)
|
||||
gdb.write(
|
||||
"%s i_atime: %s, i_mtime: %s, i_ctime: %s\n"
|
||||
% (
|
||||
subsequent_indent,
|
||||
node.i_atime,
|
||||
node.i_mtime,
|
||||
node.i_ctime,
|
||||
)
|
||||
f"{initial_indent}{node} {node.details() if verbose else ''}\n"
|
||||
)
|
||||
|
||||
if node.i_child:
|
||||
self.print_inode_info(node.i_child, level + 1, newprefix, maxlevel)
|
||||
node = node.i_peer
|
||||
self.print_inode_info(
|
||||
Inode(node.i_child), level + 1, newprefix, maxlevel, type, verbose
|
||||
)
|
||||
node = Inode(node.i_peer)
|
||||
|
||||
def diagnose(self, *args, **kwargs):
|
||||
output = gdb.execute("foreach inode", to_string=True)
|
||||
@@ -409,7 +437,16 @@ class ForeachInode(gdb.Command):
|
||||
if args.addr_or_expr
|
||||
else utils.gdb_eval_or_none("g_root_inode")
|
||||
)
|
||||
self.print_inode_info(root, maxlevel=args.level)
|
||||
|
||||
nodetype = InodeType[args.nodetype.upper()] if args.nodetype else None
|
||||
if nodetype:
|
||||
self.nodes = list(
|
||||
filter(lambda x: inode_gettype(x[0]) == nodetype, foreach_inode(root))
|
||||
)
|
||||
|
||||
self.print_inode_info(
|
||||
Inode(root), maxlevel=args.level, type=nodetype, verbose=args.verbose
|
||||
)
|
||||
|
||||
|
||||
class InfoShmfs(gdb.Command):
|
||||
@@ -421,7 +458,7 @@ class InfoShmfs(gdb.Command):
|
||||
self.total_size = 0
|
||||
self.block_count = 0
|
||||
|
||||
def shm_filter(self, node: Inode, path):
|
||||
def shm_filter(self, node: p.Inode, path):
|
||||
if inode_gettype(node) != InodeType.SHM:
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user