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

Reply via email to