This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit ab3aa41f3970e2bc255857e82ca06a2aded11762 Author: yangao1 <yang...@xiaomi.com> AuthorDate: Tue Jul 30 19:13:51 2024 +0800 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 <yang...@xiaomi.com> --- tools/gdb/fs.py | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/gdb/utils.py | 17 +++++++ 2 files changed, 150 insertions(+) diff --git a/tools/gdb/fs.py b/tools/gdb/fs.py index 2a39a16f23..c523c45e02 100644 --- a/tools/gdb/fs.py +++ b/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() diff --git a/tools/gdb/utils.py b/tools/gdb/utils.py index bc506f3607..51dbd01958 100644 --- a/tools/gdb/utils.py +++ b/tools/gdb/utils.py @@ -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