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 f5371e92f3d0734eaa45312f2667cd4bbbb7b491
Author: xuxingliang <[email protected]>
AuthorDate: Wed Oct 30 12:51:23 2024 +0800

    gdb/backtrace: optimize backtrace formatting
    
    Use a class Bactrace to support convert address to backtrace, format to 
string, accessing element and iterate though them.
    Adjust usage in fs and addr2line to make full use of it.
    
    Signed-off-by: xuxingliang <[email protected]>
---
 tools/gdb/nuttxgdb/fs.py    | 21 +++++-------
 tools/gdb/nuttxgdb/utils.py | 83 +++++++++++++++++++++++++++++++++++++++------
 2 files changed, 81 insertions(+), 23 deletions(-)

diff --git a/tools/gdb/nuttxgdb/fs.py b/tools/gdb/nuttxgdb/fs.py
index dd3a793c91..16375cd9bf 100644
--- a/tools/gdb/nuttxgdb/fs.py
+++ b/tools/gdb/nuttxgdb/fs.py
@@ -159,19 +159,16 @@ class Fdinfo(gdb.Command):
 
         output = []
         if CONFIG_FS_BACKTRACE:
-            backtrace = 
utils.backtrace(utils.ArrayIterator(file["f_backtrace"]))
-
-            backtrace = [
-                backtrace_formatter.format(
-                    hex(addr),
-                    func,
-                    source,
-                )
-                for addr, func, source in backtrace
-            ]
+            backtrace = utils.Backtrace(
+                utils.ArrayIterator(file["f_backtrace"]), 
formatter=backtrace_formatter
+            )
 
-            output.append(formatter.format(fd, oflags, pos, path, 
backtrace[0]))
-            output.extend(formatter.format("", "", "", "", bt) for bt in 
backtrace[1:])
+            output.append(
+                formatter.format(fd, oflags, pos, path, backtrace.formatted[0])
+            )
+            output.extend(
+                formatter.format("", "", "", "", bt) for bt in 
backtrace.formatted[1:]
+            )
             output.append("")  # separate each backtrace
         else:
             output = [formatter.format(fd, oflags, pos, path, "")]
diff --git a/tools/gdb/nuttxgdb/utils.py b/tools/gdb/nuttxgdb/utils.py
index 4595495162..daa40c3e3a 100644
--- a/tools/gdb/nuttxgdb/utils.py
+++ b/tools/gdb/nuttxgdb/utils.py
@@ -19,6 +19,7 @@
 # under the License.
 #
 ############################################################################
+from __future__ import annotations
 
 import argparse
 import importlib
@@ -38,13 +39,52 @@ g_type_cache = {}
 g_macro_ctx = None
 
 
-def backtrace(addresses: List[Union[gdb.Value, int]]) -> List[Tuple[int, str, 
str]]:
-    """Convert addresses to backtrace"""
-    backtrace = []
+class Backtrace:
+    """
+    Convert addresses to backtrace
+    Usage:
+    backtrace = Backtrace(addresses=[0x4001, 0x4002, 0x4003])
+
+    # Access converted backtrace
+    addr, func, source = backtrace[0]
+    remaining = backtrace[1:]  # Return list of (addr, func, source)
+
+    # Iterate over backtrace
+    for addr, func, source in backtrace:
+        print(addr, func, source)
+
+    # Append more addresses to convert
+    backtrace.append(0x40001234)
+
+    # Print backtrace
+    print(str(backtrace))
+
+    # Format backtrace to string
+    print("\n".join(backtrace.formatted))
+
+    # Custom formatter
+    backtrace = Backtrace(addresses=[0x4001, 0x4002, 0x4003], formatter="{:<6} 
{:<20} {}")
+    """
 
-    for addr in addresses:
+    def __init__(
+        self,
+        address: List[Union[gdb.Value, int]] = [],
+        formatter="{:<5} {:<36} {}\n",
+    ):
+        self.formatter = formatter  # Address, Function, Source
+        self._formatted = None  # Cached formatted backtrace
+        self.backtrace = [res for addr in address if (res := 
self.convert(addr))]
+
+    def append(self, addr: Union[gdb.Value, int]) -> None:
+        """Append an address to the backtrace"""
+        if result := self.convert(addr):
+            self.backtrace.append(result)
+            self._formatted = None  # Clear cached result
+
+    def convert(self, addr: Union[gdb.Value, int]) -> Tuple[int, str, str]:
+        """Convert an address to function and source"""
         if not addr:
-            continue
+            return
 
         if type(addr) is int:
             addr = gdb.Value(addr)
@@ -55,9 +95,31 @@ def backtrace(addresses: List[Union[gdb.Value, int]]) -> 
List[Tuple[int, str, st
         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 (int(addr), func, source)
+
+    @property
+    def formatted(self):
+        """Return the formatted backtrace string list"""
+        if not self._formatted:
+            self._formatted = [
+                self.formatter.format(hex(addr), func, source)
+                for addr, func, source in self.backtrace
+            ]
+
+        return self._formatted
+
+    def __repr__(self) -> str:
+        return f"Backtrace: {len(self.backtrace)} items"
+
+    def __str__(self) -> str:
+        return "".join(self.formatted)
+
+    def __iter__(self):
+        for item in self.backtrace:
+            yield item
 
-    return backtrace
+    def __getitem__(self, index):
+        return self.backtrace.__getitem__(index)
 
 
 def lookup_type(name, block=None) -> gdb.Type:
@@ -822,9 +884,8 @@ class Addr2Line(gdb.Command):
     def print_backtrace(self, addresses, pid=None):
         if pid:
             gdb.write(f"\nBacktrace of {pid}\n")
-        backtraces = backtrace(addresses)
-        for addr, func, source in backtraces:
-            gdb.write(self.formatter.format(hex(addr), func, source))
+        backtraces = Backtrace(addresses, formatter=self.formatter)
+        gdb.write(str(backtraces))
 
     def invoke(self, args, from_tty):
         if not args:
@@ -844,7 +905,7 @@ class Addr2Line(gdb.Command):
 
         pargs = None
         try:
-            pargs = parser.parse_args(gdb.string_to_argv(args))
+            pargs, _ = parser.parse_known_args(gdb.string_to_argv(args))
         except SystemExit:
             pass
 

Reply via email to