forked from nuttx/nuttx-update
tools/gdb/fs.py: add print fdinfo,modify the print format
Execute fdinfo or fdinfo -p pid. (gdb) fdinfo PID: 0 FD OFLAGS POS PATH BACKTRACE 0 3 0 /dev/console 0x4028ff0c <sched_backtrace+48> /home/neo/projects/vela2/nuttx/sched/sched/sched_backtrace.c:105 0x402888f8 <file_allocate_from_tcb+236> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:615 0x402979d0 <nx_vopen+104> /home/neo/projects/vela2/nuttx/fs/vfs/fs_open.c:326 0x40297ad4 <nx_open+116> /home/neo/projects/vela2/nuttx/fs/vfs/fs_open.c:449 0x40291eb4 <group_setupidlefiles+28> /home/neo/projects/vela2/nuttx/sched/group/group_setupidlefiles.c:75 0x4028df94 <nx_start+628> /home/neo/projects/vela2/nuttx/sched/init/nx_start.c:651 0x4028119c <arm64_boot_primary_c_routine+16> /home/neo/projects/vela2/nuttx/arch/arm64/src/common/arm64_boot.c:205 1 3 0 /dev/console 0x4028ff0c <sched_backtrace+48> /home/neo/projects/vela2/nuttx/sched/sched/sched_backtrace.c:105 0x40289574 <file_dup3+248> /home/neo/projects/vela2/nuttx/fs/vfs/fs_dup2.c:177 0x40288b88 <nx_dup3_from_tcb+176> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:314 0x40288c64 <nx_dup2_from_tcb+16> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:901 0x40288c88 <nx_dup2+28> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:924 0x40291ec4 <group_setupidlefiles+44> /home/neo/projects/vela2/nuttx/sched/group/group_setupidlefiles.c:84 0x4028df94 <nx_start+628> /home/neo/projects/vela2/nuttx/sched/init/nx_start.c:651 0x4028119c <arm64_boot_primary_c_routine+16> /home/neo/projects/vela2/nuttx/arch/arm64/src/common/arm64_boot.c:205 2 3 0 /dev/console 0x4028ff0c <sched_backtrace+48> /home/neo/projects/vela2/nuttx/sched/sched/sched_backtrace.c:105 0x40289574 <file_dup3+248> /home/neo/projects/vela2/nuttx/fs/vfs/fs_dup2.c:177 0x40288b88 <nx_dup3_from_tcb+176> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:314 0x40288c64 <nx_dup2_from_tcb+16> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:901 0x40288c88 <nx_dup2+28> /home/neo/projects/vela2/nuttx/fs/inode/fs_files.c:924 0x40291ed0 <group_setupidlefiles+56> /home/neo/projects/vela2/nuttx/sched/group/group_setupidlefiles.c:117 0x4028df94 <nx_start+628> /home/neo/projects/vela2/nuttx/sched/init/nx_start.c:651 0x4028119c <arm64_boot_primary_c_routine+16> /home/neo/projects/vela2/nuttx/arch/arm64/src/common/arm64_boot.c:205 Signed-off-by: yangao1 <yangao1@xiaomi.com>
This commit is contained in:
parent
136b7065b7
commit
ab3aa41f39
2 changed files with 150 additions and 0 deletions
133
tools/gdb/fs.py
133
tools/gdb/fs.py
|
@ -29,6 +29,11 @@ FSNODEFLAG_TYPE_MOUNTPT = utils.get_symbol_value("FSNODEFLAG_TYPE_MOUNTPT")
|
|||
CONFIG_PSEUDOFS_FILE = utils.get_symbol_value("CONFIG_PSEUDOFS_FILE")
|
||||
CONFIG_PSEUDOFS_ATTRIBUTES = utils.get_symbol_value("CONFIG_PSEUDOFS_ATTRIBUTES")
|
||||
|
||||
CONFIG_FS_BACKTRACE = utils.get_symbol_value("CONFIG_FS_BACKTRACE")
|
||||
CONFIG_NFILE_DESCRIPTORS_PER_BLOCK = int(
|
||||
utils.get_symbol_value("CONFIG_NFILE_DESCRIPTORS_PER_BLOCK")
|
||||
)
|
||||
|
||||
|
||||
def get_inode_name(inode):
|
||||
if not inode:
|
||||
|
@ -37,6 +42,34 @@ def get_inode_name(inode):
|
|||
return ptr.string()
|
||||
|
||||
|
||||
def inode_getpath(inode):
|
||||
"""get path fron inode"""
|
||||
if not inode:
|
||||
return ""
|
||||
|
||||
name = get_inode_name(inode)
|
||||
|
||||
if inode["i_parent"]:
|
||||
return inode_getpath(inode["i_parent"]) + "/" + name
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def get_file(tcb, fd):
|
||||
group = tcb["group"]
|
||||
filelist = group["tg_filelist"]
|
||||
fl_files = filelist["fl_files"]
|
||||
fl_rows = filelist["fl_rows"]
|
||||
|
||||
row = fd // CONFIG_NFILE_DESCRIPTORS_PER_BLOCK
|
||||
col = fd % CONFIG_NFILE_DESCRIPTORS_PER_BLOCK
|
||||
|
||||
if row >= fl_rows:
|
||||
return None
|
||||
|
||||
return fl_files[row][col]
|
||||
|
||||
|
||||
def foreach_inode(handler, root=None, path=""):
|
||||
node = root if root else gdb.parse_and_eval("g_root_inode")["i_child"]
|
||||
while node:
|
||||
|
@ -47,6 +80,104 @@ def foreach_inode(handler, root=None, path=""):
|
|||
node = node["i_peer"]
|
||||
|
||||
|
||||
def foreach_file(tcb):
|
||||
"""Iterate over all file descriptors in a tcb"""
|
||||
group = tcb["group"]
|
||||
filelist = group["tg_filelist"]
|
||||
fl_files = filelist["fl_files"]
|
||||
fl_rows = filelist["fl_rows"]
|
||||
|
||||
for row in range(fl_rows):
|
||||
for col in range(CONFIG_NFILE_DESCRIPTORS_PER_BLOCK):
|
||||
file = fl_files[row][col]
|
||||
|
||||
if not file or not file["f_inode"]:
|
||||
continue
|
||||
|
||||
fd = row * CONFIG_NFILE_DESCRIPTORS_PER_BLOCK + col
|
||||
|
||||
yield fd, file
|
||||
|
||||
|
||||
class Fdinfo(gdb.Command):
|
||||
"""Dump fd info information of process"""
|
||||
|
||||
def __init__(self):
|
||||
super(Fdinfo, self).__init__(
|
||||
"fdinfo", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION
|
||||
)
|
||||
|
||||
def print_file_info(self, fd, file, formatter):
|
||||
backtrace_formatter = "{0:<5} {1:<36} {2}"
|
||||
|
||||
oflags = int(file["f_oflags"])
|
||||
pos = int(file["f_pos"])
|
||||
path = inode_getpath(file["f_inode"])
|
||||
|
||||
output = []
|
||||
if CONFIG_FS_BACKTRACE:
|
||||
backtrace = utils.backtrace(
|
||||
[file["f_backtrace"][i] for i in range(CONFIG_FS_BACKTRACE)]
|
||||
)
|
||||
|
||||
backtrace = [
|
||||
backtrace_formatter.format(
|
||||
hex(addr),
|
||||
func,
|
||||
source,
|
||||
)
|
||||
for addr, func, source in backtrace
|
||||
]
|
||||
|
||||
output.append(formatter.format(fd, oflags, pos, path, backtrace[0]))
|
||||
output.extend(formatter.format("", "", "", "", bt) for bt in backtrace[1:])
|
||||
output.append("") # separate each backtrace
|
||||
else:
|
||||
output = [formatter.format(fd, oflags, pos, path, "")]
|
||||
|
||||
gdb.write("\n".join(output))
|
||||
gdb.write("\n")
|
||||
|
||||
def print_fdinfo_by_tcb(self, tcb):
|
||||
"""print fdlist from tcb"""
|
||||
gdb.write(f"PID: {tcb['pid']}\n")
|
||||
group = tcb["group"]
|
||||
|
||||
if not group:
|
||||
return
|
||||
|
||||
if group in self.processed_groups:
|
||||
return
|
||||
|
||||
self.processed_groups.add(group)
|
||||
|
||||
headers = ["FD", "OFLAGS", "POS", "PATH", "BACKTRACE"]
|
||||
formatter = "{:<4}{:<8}{:<6}{:<22}{:<50}"
|
||||
gdb.write(formatter.format(*headers) + "\n")
|
||||
|
||||
for fd, file in foreach_file(tcb):
|
||||
self.print_file_info(fd, file, formatter)
|
||||
|
||||
gdb.write("\n")
|
||||
|
||||
def invoke(self, arg, from_tty):
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Get fdinfo for a process or all processes."
|
||||
)
|
||||
parser.add_argument("-p", "--pid", type=int, help="Optional process ID")
|
||||
|
||||
try:
|
||||
args = parser.parse_args(gdb.string_to_argv(arg))
|
||||
except SystemExit:
|
||||
gdb.write("Invalid arguments.\n")
|
||||
return
|
||||
|
||||
self.processed_groups = set()
|
||||
tcbs = [utils.get_tcb(args.pid)] if args.pid else utils.get_tcbs()
|
||||
for tcb in tcbs:
|
||||
self.print_fdinfo_by_tcb(tcb)
|
||||
|
||||
|
||||
class Mount(gdb.Command):
|
||||
def __init__(self):
|
||||
super(Mount, self).__init__("mount", gdb.COMMAND_USER)
|
||||
|
@ -164,6 +295,8 @@ class ForeachInode(gdb.Command):
|
|||
self.print_inode_info(arg["root_inode"], 1, "")
|
||||
|
||||
|
||||
Fdinfo()
|
||||
|
||||
if not utils.get_symbol_value("CONFIG_DISABLE_MOUNTPOINT"):
|
||||
Mount()
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
############################################################################
|
||||
|
||||
import re
|
||||
from typing import List
|
||||
|
||||
import gdb
|
||||
|
||||
|
@ -28,6 +29,22 @@ g_symbol_cache = {}
|
|||
g_type_cache = {}
|
||||
|
||||
|
||||
def backtrace(addresses: List[gdb.Value]) -> List[str]:
|
||||
"""Convert addresses to backtrace"""
|
||||
backtrace = []
|
||||
|
||||
for addr in addresses:
|
||||
if not addr:
|
||||
break
|
||||
|
||||
func = addr.format_string(symbols=True, address=False)
|
||||
sym = gdb.find_pc_line(int(addr))
|
||||
source = str(sym.symtab) + ":" + str(sym.line)
|
||||
backtrace.append((int(addr), func, source))
|
||||
|
||||
return backtrace
|
||||
|
||||
|
||||
def lookup_type(name, block=None) -> gdb.Type:
|
||||
"""Return the type object of a type name"""
|
||||
global g_type_cache
|
||||
|
|
Loading…
Reference in a new issue