[Lldb-commits] [lldb] Colorize output when searching for symbols in lldb (PR #69422)

José Lira Junior via lldb-commits lldb-commits at lists.llvm.org
Mon Nov 13 09:41:29 PST 2023


https://github.com/junior-jl updated https://github.com/llvm/llvm-project/pull/69422

>From 2c23aaf231beef11d3e0db6506fe82323a0be6a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20L=2E=20Junior?= <josejunior at 10xengineers.ai>
Date: Tue, 7 Nov 2023 16:57:18 -0300
Subject: [PATCH] [lldb] colorize symbols in image lookup

---
 lldb/include/lldb/Core/Address.h              |  7 ++-
 lldb/include/lldb/Symbol/Symbol.h             |  4 +-
 lldb/include/lldb/Symbol/SymbolContext.h      |  8 +--
 lldb/source/Commands/CommandObjectTarget.cpp  | 15 ++++--
 lldb/source/Core/Address.cpp                  | 53 ++++++++++++++++---
 lldb/source/Symbol/Symbol.cpp                 | 18 ++++---
 lldb/source/Symbol/SymbolContext.cpp          | 16 ++++--
 .../Commands/command-image-lookup-color.test  | 25 +++++++++
 8 files changed, 114 insertions(+), 32 deletions(-)
 create mode 100644 lldb/test/Shell/Commands/command-image-lookup-color.test

diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h
index b19e694427546f8..fac0ced910a11d4 100644
--- a/lldb/include/lldb/Core/Address.h
+++ b/lldb/include/lldb/Core/Address.h
@@ -246,8 +246,11 @@ class Address {
   /// \see Address::DumpStyle
   bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
             DumpStyle fallback_style = DumpStyleInvalid,
-            uint32_t addr_byte_size = UINT32_MAX,
-            bool all_ranges = false) const;
+            uint32_t addr_byte_size = UINT32_MAX, bool all_ranges = false,
+            const char *pattern = nullptr) const;
+
+  static void DumpName(Stream *strm, llvm::StringRef text,
+                       const char *pattern = nullptr);
 
   AddressClass GetAddressClass() const;
 
diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h
index 44a2d560010fe40..0e41cd95e0ef17d 100644
--- a/lldb/include/lldb/Symbol/Symbol.h
+++ b/lldb/include/lldb/Symbol/Symbol.h
@@ -174,8 +174,8 @@ class Symbol : public SymbolContextScope {
 
   void SetFlags(uint32_t flags) { m_flags = flags; }
 
-  void GetDescription(Stream *s, lldb::DescriptionLevel level,
-                      Target *target) const;
+  void GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target,
+                      const char *pattern = nullptr) const;
 
   bool IsSynthetic() const { return m_is_synthetic; }
 
diff --git a/lldb/include/lldb/Symbol/SymbolContext.h b/lldb/include/lldb/Symbol/SymbolContext.h
index b0f5ffead2a1656..9567c3f4384c175 100644
--- a/lldb/include/lldb/Symbol/SymbolContext.h
+++ b/lldb/include/lldb/Symbol/SymbolContext.h
@@ -150,8 +150,8 @@ class SymbolContext {
   bool DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
                        const Address &so_addr, bool show_fullpaths,
                        bool show_module, bool show_inlined_frames,
-                       bool show_function_arguments,
-                       bool show_function_name) const;
+                       bool show_function_arguments, bool show_function_name,
+                       const char *pattern = nullptr) const;
 
   /// Get the address range contained within a symbol context.
   ///
@@ -217,8 +217,8 @@ class SymbolContext {
   ///     The symbol that was found, or \b nullptr if none was found.
   const Symbol *FindBestGlobalDataSymbol(ConstString name, Status &error);
 
-  void GetDescription(Stream *s, lldb::DescriptionLevel level,
-                      Target *target) const;
+  void GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target,
+                      const char *pattern = nullptr) const;
 
   uint32_t GetResolvedMask() const;
 
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 8f052d0a7b837e2..a83575ad82d6909 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -8,6 +8,7 @@
 
 #include "CommandObjectTarget.h"
 
+#include "lldb/Core/Address.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/IOHandler.h"
 #include "lldb/Core/Module.h"
@@ -1534,7 +1535,7 @@ static void DumpOsoFilesTable(Stream &strm,
 
 static void DumpAddress(ExecutionContextScope *exe_scope,
                         const Address &so_addr, bool verbose, bool all_ranges,
-                        Stream &strm) {
+                        Stream &strm, const char *pattern = nullptr) {
   strm.IndentMore();
   strm.Indent("    Address: ");
   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
@@ -1544,13 +1545,14 @@ static void DumpAddress(ExecutionContextScope *exe_scope,
   strm.Indent("    Summary: ");
   const uint32_t save_indent = strm.GetIndentLevel();
   strm.SetIndentLevel(save_indent + 13);
-  so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription);
+  so_addr.Dump(&strm, exe_scope, Address::DumpStyleResolvedDescription,
+               Address::DumpStyleInvalid, UINT32_MAX, false, pattern);
   strm.SetIndentLevel(save_indent);
   // Print out detailed address information when verbose is enabled
   if (verbose) {
     strm.EOL();
     so_addr.Dump(&strm, exe_scope, Address::DumpStyleDetailedSymbolContext,
-                 Address::DumpStyleInvalid, UINT32_MAX, all_ranges);
+                 Address::DumpStyleInvalid, UINT32_MAX, all_ranges, pattern);
   }
   strm.IndentLess();
 }
@@ -1595,6 +1597,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
     return 0;
 
   SymbolContext sc;
+  bool use_color = interpreter.GetDebugger().GetUseColor();
   std::vector<uint32_t> match_indexes;
   ConstString symbol_name(name);
   uint32_t num_matches = 0;
@@ -1620,12 +1623,14 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
         if (symbol->ValueIsAddress()) {
           DumpAddress(
               interpreter.GetExecutionContext().GetBestExecutionContextScope(),
-              symbol->GetAddressRef(), verbose, all_ranges, strm);
+              symbol->GetAddressRef(), verbose, all_ranges, strm,
+              use_color ? name : nullptr);
           strm.EOL();
         } else {
           strm.IndentMore();
           strm.Indent("    Name: ");
-          strm.PutCString(symbol->GetDisplayName().GetStringRef());
+          Address::DumpName(&strm, symbol->GetDisplayName().GetStringRef(),
+                            use_color ? name : nullptr);
           strm.EOL();
           strm.Indent("    Value: ");
           strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue());
diff --git a/lldb/source/Core/Address.cpp b/lldb/source/Core/Address.cpp
index 189d50fe962a651..7e3ab36c238eabb 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -28,6 +28,7 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/AnsiTerminal.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/DataExtractor.h"
 #include "lldb/Utility/Endian.h"
@@ -403,9 +404,41 @@ bool Address::GetDescription(Stream &s, Target &target,
   return false;
 }
 
+void Address::DumpName(Stream *strm, llvm::StringRef text,
+                       const char *pattern) {
+  if (!pattern) {
+    strm->PutCString(text.data());
+    return;
+  }
+
+  llvm::Regex reg_pattern(pattern);
+  llvm::SmallVector<llvm::StringRef, 1> matches;
+  llvm::StringRef remaining = text;
+  std::string red_start =
+      lldb_private::ansi::FormatAnsiTerminalCodes("${ansi.fg.red}");
+  std::string reset_color =
+      lldb_private::ansi::FormatAnsiTerminalCodes("${ansi.normal}");
+
+  size_t last_pos = 0;
+  while (reg_pattern.match(remaining, &matches)) {
+    llvm::StringRef match = matches[0];
+    size_t match_start_pos = match.data() - text.data();
+    size_t match_end_pos = match_start_pos + match.size();
+
+    strm->Write(text.data() + last_pos, match_start_pos - last_pos);
+    strm->PutCString(red_start.c_str());
+    strm->Write(text.data() + match_start_pos, match.size());
+    strm->PutCString(reset_color.c_str());
+    last_pos = match_end_pos;
+    remaining = text.substr(last_pos);
+  }
+  if (last_pos < text.size())
+    strm->PutCString(text.data() + last_pos);
+}
+
 bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
                    DumpStyle fallback_style, uint32_t addr_size,
-                   bool all_ranges) const {
+                   bool all_ranges, const char *pattern) const {
   // If the section was nullptr, only load address is going to work unless we
   // are trying to deref a pointer
   SectionSP section_sp(GetSection());
@@ -515,7 +548,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
               if (symbol) {
                 const char *symbol_name = symbol->GetName().AsCString();
                 if (symbol_name) {
-                  s->PutCString(symbol_name);
+                  DumpName(s, symbol_name, pattern);
                   addr_t delta =
                       file_Addr - symbol->GetAddressRef().GetFileAddress();
                   if (delta)
@@ -643,7 +676,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
                     pointer_sc.symbol != nullptr) {
                   s->PutCString(": ");
                   pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false,
-                                             false, true, true);
+                                             false, true, true, pattern);
                 }
               }
             }
@@ -682,19 +715,22 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
               // address.
               sc.DumpStopContext(s, exe_scope, *this, show_fullpaths,
                                  show_module, show_inlined_frames,
-                                 show_function_arguments, show_function_name);
+                                 show_function_arguments, show_function_name,
+                                 pattern);
             } else {
               // We found a symbol but it was in a different section so it
               // isn't the symbol we should be showing, just show the section
               // name + offset
-              Dump(s, exe_scope, DumpStyleSectionNameOffset);
+              Dump(s, exe_scope, DumpStyleSectionNameOffset, DumpStyleInvalid,
+                   UINT32_MAX, false, pattern);
             }
           }
         }
       }
     } else {
       if (fallback_style != DumpStyleInvalid)
-        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
+        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,
+                    false, pattern);
       return false;
     }
     break;
@@ -715,7 +751,7 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
               sc.symbol->GetAddressRef().GetSection() != GetSection())
             sc.symbol = nullptr;
         }
-        sc.GetDescription(s, eDescriptionLevelBrief, target);
+        sc.GetDescription(s, eDescriptionLevelBrief, target, pattern);
 
         if (sc.block) {
           bool can_create = true;
@@ -763,7 +799,8 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
       }
     } else {
       if (fallback_style != DumpStyleInvalid)
-        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size);
+        return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size,
+                    false, pattern);
       return false;
     }
     break;
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 26b4c4d62ad9c24..1e113e59e53d895 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -8,6 +8,7 @@
 
 #include "lldb/Symbol/Symbol.h"
 
+#include "lldb/Core/Address.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/Section.h"
@@ -225,7 +226,7 @@ bool Symbol::IsTrampoline() const { return m_type == eSymbolTypeTrampoline; }
 bool Symbol::IsIndirect() const { return m_type == eSymbolTypeResolver; }
 
 void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
-                            Target *target) const {
+                            Target *target, const char *pattern) const {
   s->Printf("id = {0x%8.8x}", m_uid);
 
   if (m_addr_range.GetBaseAddress().GetSection()) {
@@ -252,11 +253,16 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
       s->Printf(", value = 0x%16.16" PRIx64,
                 m_addr_range.GetBaseAddress().GetOffset());
   }
-  ConstString demangled = GetMangled().GetDemangledName();
-  if (demangled)
-    s->Printf(", name=\"%s\"", demangled.AsCString());
-  if (m_mangled.GetMangledName())
-    s->Printf(", mangled=\"%s\"", m_mangled.GetMangledName().AsCString());
+  if (ConstString mangled_name = m_mangled.GetMangledName()) {
+    s->Printf(", mangled=\"");
+    Address::DumpName(s, mangled_name.GetStringRef(), pattern);
+    s->Printf("\"");
+  }
+  if (ConstString demangled = m_mangled.GetDemangledName()) {
+    s->Printf(", name=\"");
+    Address::DumpName(s, demangled.GetStringRef(), pattern);
+    s->Printf("\"");
+  }
 }
 
 void Symbol::Dump(Stream *s, Target *target, uint32_t index,
diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index 63968ec2d150670..d231432dfd7ae34 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -8,6 +8,7 @@
 
 #include "lldb/Symbol/SymbolContext.h"
 
+#include "lldb/Core/Address.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
@@ -71,7 +72,8 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
                                     const Address &addr, bool show_fullpaths,
                                     bool show_module, bool show_inlined_frames,
                                     bool show_function_arguments,
-                                    bool show_function_name) const {
+                                    bool show_function_name,
+                                    const char *pattern) const {
   bool dumped_something = false;
   if (show_module && module_sp) {
     if (show_fullpaths)
@@ -95,7 +97,8 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
       if (!name)
         name = function->GetName();
       if (name)
-        name.Dump(s);
+        pattern ? Address::DumpName(s, name.GetStringRef(), pattern)
+                : name.Dump(s);
     }
 
     if (addr.IsValid()) {
@@ -163,7 +166,10 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
       dumped_something = true;
       if (symbol->GetType() == eSymbolTypeTrampoline)
         s->PutCString("symbol stub for: ");
-      symbol->GetName().Dump(s);
+      if (pattern)
+        Address::DumpName(s, symbol->GetName().GetStringRef(), pattern);
+      else
+        symbol->GetName().Dump(s);
     }
 
     if (addr.IsValid() && symbol->ValueIsAddress()) {
@@ -186,7 +192,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
 }
 
 void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level,
-                                   Target *target) const {
+                                   Target *target, const char *pattern) const {
   if (module_sp) {
     s->Indent("     Module: file = \"");
     module_sp->GetFileSpec().Dump(s->AsRawOstream());
@@ -246,7 +252,7 @@ void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level,
 
   if (symbol != nullptr) {
     s->Indent("     Symbol: ");
-    symbol->GetDescription(s, level, target);
+    symbol->GetDescription(s, level, target, pattern);
     s->EOL();
   }
 
diff --git a/lldb/test/Shell/Commands/command-image-lookup-color.test b/lldb/test/Shell/Commands/command-image-lookup-color.test
new file mode 100644
index 000000000000000..754596e1c139850
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-image-lookup-color.test
@@ -0,0 +1,25 @@
+# RUN: %clang_host -g %S/Inputs/main.c -o %t
+
+# Checking simple search
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s ma' | FileCheck %s --check-prefix CHECK1
+# CHECK1:         Name: {{.+}}31mma{{.+}}0min.c
+# CHECK1:         Summary: {{.+}}`{{.+}}31mma{{.+}}0min at main.c:2
+
+# Checking for regex searches
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s main.c|foo' | FileCheck %s --check-prefix CHECK2
+# CHECK2:         Name: {{.+}}31mmain.c{{.+}}0m
+# CHECK2:         Summary: {{.+}}`{{.+}}31mfoo{{.+}}0m at main.c:1
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s m[abc]' | FileCheck %s --check-prefix CHECK3
+# CHECK3:         Name: {{.+}}31mma{{.+}}0min.c
+# CHECK3:         Summary: {{.+}}`{{.+}}31mma{{.+}}0min at main.c:2
+
+# Checking tail match
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s .*o$' | FileCheck %s --check-prefix CHECK4
+# CHECK4:         Summary: {{.+}}`{{.+}}31mfoo{{.+}}0m at main.c:1
+
+# RUN: %lldb %t -o 'settings set use-color true' -o 'image lookup -r -s IMPPATTERN123456' | FileCheck %s --check-prefix CHECK5
+# CHECK5-NOT: {{[0-9]+}} symbols match the regular expression



More information about the lldb-commits mailing list