[Lldb-commits] [lldb] [lldb] colorize symbols in image lookup with a regex pattern (PR #69422)

José Lira Junior via lldb-commits lldb-commits at lists.llvm.org
Mon Dec 4 15:41:47 PST 2023


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

>From c416443a93f7113a7f57d337682ec4862438522d 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 1/7] [lldb] colorize symbols in image lookup

This creates the method PutCStringColorHighlighted for Stream class,
which highlights searched symbols in red color for the image lookup command.

A new shell test was added to verify functionality. Relevant methods were
updated to accept the searched pattern/symbol as a parameter.

Co-authored-by: Talha <talha.tahir at 10xengineers.ai>
---
 lldb/include/lldb/Core/Address.h              |  4 +-
 lldb/include/lldb/Symbol/Symbol.h             |  4 +-
 lldb/include/lldb/Symbol/SymbolContext.h      |  8 ++--
 lldb/include/lldb/Utility/Stream.h            | 16 ++++++++
 lldb/source/Commands/CommandObjectTarget.cpp  | 16 +++++---
 lldb/source/Core/Address.cpp                  | 21 ++++++----
 lldb/source/Symbol/Symbol.cpp                 | 18 ++++++---
 lldb/source/Symbol/SymbolContext.cpp          | 16 +++++---
 lldb/source/Utility/Stream.cpp                | 28 +++++++++++++
 .../Commands/command-image-lookup-color.test  | 39 +++++++++++++++++++
 10 files changed, 138 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 b19e694427546..c3f2832be424e 100644
--- a/lldb/include/lldb/Core/Address.h
+++ b/lldb/include/lldb/Core/Address.h
@@ -246,8 +246,8 @@ 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;
 
   AddressClass GetAddressClass() const;
 
diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h
index 44a2d560010fe..0e41cd95e0ef1 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 b0f5ffead2a16..9567c3f4384c1 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/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h
index 1a5fd343e4df0..8e3fd48dfe705 100644
--- a/lldb/include/lldb/Utility/Stream.h
+++ b/lldb/include/lldb/Utility/Stream.h
@@ -231,6 +231,22 @@ class Stream {
   ///     The string to be output to the stream.
   size_t PutCString(llvm::StringRef cstr);
 
+  /// Output a C string to the stream with color highlighting.
+  ///
+  /// Print a C string \a text to the stream, applying red color highlighting to
+  /// the portions of the string that match the regex pattern \a pattern. The
+  /// pattern is matched as many times as possible throughout the string. If \a
+  /// pattern is nullptr, then no highlighting is applied.
+  ///
+  /// \param[in] text
+  ///     The string to be output to the stream.
+  ///
+  /// \param[in] pattern
+  ///     The regex pattern to match against the \a text string. Portions of \a
+  ///     text matching this pattern will be colorized. If this parameter is
+  ///     nullptr, highlighting is not performed.
+  void PutCStringColorHighlighted(llvm::StringRef text, const char *pattern);
+
   /// Output and End of Line character to the stream.
   size_t EOL();
 
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 58785cde3ec7c..991194972e024 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"
@@ -1532,7 +1533,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);
@@ -1542,13 +1543,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();
 }
@@ -1593,6 +1595,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;
@@ -1618,12 +1621,15 @@ 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());
+          strm.PutCStringColorHighlighted(
+              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 189d50fe962a6..4a05a744e0230 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"
@@ -405,7 +406,7 @@ bool Address::GetDescription(Stream &s, Target &target,
 
 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 +516,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);
+                  s->PutCStringColorHighlighted(symbol_name, pattern);
                   addr_t delta =
                       file_Addr - symbol->GetAddressRef().GetFileAddress();
                   if (delta)
@@ -643,7 +644,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 +683,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 +719,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 +767,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 26b4c4d62ad9c..af47dc51d9ee9 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 demangled = m_mangled.GetDemangledName()) {
+    s->Printf(", name=\"");
+    s->PutCStringColorHighlighted(demangled.GetStringRef(), pattern);
+    s->Printf("\"");
+  }
+  if (ConstString mangled_name = m_mangled.GetMangledName()) {
+    s->Printf(", mangled=\"");
+    s->PutCStringColorHighlighted(mangled_name.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 63968ec2d1506..21064b1fd1b38 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,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
       if (!name)
         name = function->GetName();
       if (name)
-        name.Dump(s);
+        s->PutCStringColorHighlighted(name.GetStringRef(), pattern);
     }
 
     if (addr.IsValid()) {
@@ -163,7 +165,11 @@ 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)
+        s->PutCStringColorHighlighted(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/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index af28a49a1f0c2..04679d9b017b1 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -8,11 +8,13 @@
 
 #include "lldb/Utility/Stream.h"
 
+#include "lldb/Utility/AnsiTerminal.h"
 #include "lldb/Utility/Endian.h"
 #include "lldb/Utility/VASPrintf.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/LEB128.h"
+#include "llvm/Support/Regex.h"
 
 #include <string>
 
@@ -70,6 +72,32 @@ size_t Stream::PutCString(llvm::StringRef str) {
   return bytes_written;
 }
 
+void Stream::PutCStringColorHighlighted(llvm::StringRef text,
+                                        const char *pattern) {
+  if (!pattern) {
+    PutCString(text);
+    return;
+  }
+
+  // If pattern is not nullptr, we should use color
+  llvm::Regex reg_pattern(pattern);
+  llvm::SmallVector<llvm::StringRef, 1> matches;
+  llvm::StringRef remaining = text;
+  std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes(
+      "${ansi.fg.red}%s${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() - remaining.data();
+    Write(remaining.data(), match_start_pos);
+    Printf(format_str.c_str(), match.str().c_str());
+    last_pos = match_start_pos + match.size();
+    remaining = remaining.drop_front(last_pos);
+  }
+  if (remaining.size())
+    PutCString(remaining);
+}
+
 // Print a double quoted NULL terminated C string to the stream using the
 // printf format in "format".
 void Stream::QuotedCString(const char *cstr, const char *format) {
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 0000000000000..a58f05680762b
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-image-lookup-color.test
@@ -0,0 +1,39 @@
+# RUN: %clang_host -g %S/Inputs/main.c -o %t
+
+# Checking simple regex 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 complex 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
+
+# Checking to ensure that no attempt is made to color anything when there are no matching symbols found
+
+# 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
+
+# Checking search which find more than 1 symbol
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s foo|main' | FileCheck %s --check-prefix CHECK6
+# CHECK6:         Name: {{.+}}31mmain{{.+}}0m.c
+# CHECK6:         Summary: {{.+}}`{{.+}}31mfoo{{.+}}0m at main.c:1
+# CHECK6:         Summary: {{.+}}`{{.+}}31mmain{{.+}}0m at main.c:2
+
+# Checking multiple matches on same symbol
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s (ma|n$)' | FileCheck %s --check-prefix CHECK7
+# CHECK7:         Summary: {{.+}}`{{.+}}31mma{{.+}}0mi{{.+}}31mn{{.+}}0m at main.c:2
\ No newline at end of file

>From c6b19ad628b6d51607a6d5428688fc3a443b5629 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20L=2E=20Junior?= <josejunior at 10xengineers.ai>
Date: Mon, 27 Nov 2023 14:44:00 -0300
Subject: [PATCH 2/7] remove unnecessary condition

---
 lldb/source/Symbol/SymbolContext.cpp | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index 21064b1fd1b38..b70e02743cec6 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -165,11 +165,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
       dumped_something = true;
       if (symbol->GetType() == eSymbolTypeTrampoline)
         s->PutCString("symbol stub for: ");
-      if (pattern)
-        s->PutCStringColorHighlighted(symbol->GetName().GetStringRef(),
-                                      pattern);
-      else
-        symbol->GetName().Dump(s);
+      s->PutCStringColorHighlighted(symbol->GetName().GetStringRef(), pattern);
     }
 
     if (addr.IsValid() && symbol->ValueIsAddress()) {

>From fa6540729a98077966bb0f65e85894a9f1926f30 Mon Sep 17 00:00:00 2001
From: taalhaataahir0102 <23100293 at lums.edu.pk>
Date: Wed, 29 Nov 2023 16:01:49 +0500
Subject: [PATCH 3/7] colorize only with regex flag

---
 lldb/source/Commands/CommandObjectTarget.cpp             | 2 +-
 lldb/source/Utility/Stream.cpp                           | 4 ++--
 lldb/test/Shell/Commands/command-image-lookup-color.test | 7 ++++++-
 3 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 991194972e024..2b888530534b1 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -1622,7 +1622,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
           DumpAddress(
               interpreter.GetExecutionContext().GetBestExecutionContextScope(),
               symbol->GetAddressRef(), verbose, all_ranges, strm,
-              use_color ? name : nullptr);
+              use_color && name_is_regex ? name : nullptr);
           strm.EOL();
         } else {
           strm.IndentMore();
diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index 04679d9b017b1..8560186561c0e 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -85,13 +85,13 @@ void Stream::PutCStringColorHighlighted(llvm::StringRef text,
   llvm::StringRef remaining = text;
   std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes(
       "${ansi.fg.red}%s${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() - remaining.data();
     Write(remaining.data(), match_start_pos);
+    size_t last_pos = match_start_pos;
     Printf(format_str.c_str(), match.str().c_str());
-    last_pos = match_start_pos + match.size();
+    last_pos += match.size();
     remaining = remaining.drop_front(last_pos);
   }
   if (remaining.size())
diff --git a/lldb/test/Shell/Commands/command-image-lookup-color.test b/lldb/test/Shell/Commands/command-image-lookup-color.test
index a58f05680762b..d19e002c87e6f 100644
--- a/lldb/test/Shell/Commands/command-image-lookup-color.test
+++ b/lldb/test/Shell/Commands/command-image-lookup-color.test
@@ -36,4 +36,9 @@
 # Checking multiple matches on same symbol
 
 # RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -r -s (ma|n$)' | FileCheck %s --check-prefix CHECK7
-# CHECK7:         Summary: {{.+}}`{{.+}}31mma{{.+}}0mi{{.+}}31mn{{.+}}0m at main.c:2
\ No newline at end of file
+# CHECK7:         Summary: {{.+}}`{{.+}}31mma{{.+}}0mi{{.+}}31mn{{.+}}0m at main.c:2
+
+# Checking no colorization without regex search
+
+# RUN: %lldb %t -b -o 'settings set use-color true' -o 'image lookup -s main' | FileCheck %s --check-prefix CHECK8
+# CHECK8:        Summary: {{.+}}`main at main.c:2
\ No newline at end of file

>From 8bd5846ab7f1b62f2332fedfd09f4fef9b274120 Mon Sep 17 00:00:00 2001
From: taalhaataahir0102 <23100293 at lums.edu.pk>
Date: Thu, 30 Nov 2023 11:43:55 +0500
Subject: [PATCH 4/7] Print function updated

---
 lldb/source/Utility/Stream.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index 8560186561c0e..363b01cf96a0c 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -84,15 +84,13 @@ void Stream::PutCStringColorHighlighted(llvm::StringRef text,
   llvm::SmallVector<llvm::StringRef, 1> matches;
   llvm::StringRef remaining = text;
   std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes(
-      "${ansi.fg.red}%s${ansi.normal}");
+      "${ansi.fg.red}%.*s${ansi.normal}");
   while (reg_pattern.match(remaining, &matches)) {
     llvm::StringRef match = matches[0];
     size_t match_start_pos = match.data() - remaining.data();
-    Write(remaining.data(), match_start_pos);
-    size_t last_pos = match_start_pos;
-    Printf(format_str.c_str(), match.str().c_str());
-    last_pos += match.size();
-    remaining = remaining.drop_front(last_pos);
+    PutCString(remaining.take_front(match_start_pos));
+    Printf(format_str.c_str(), match.size(), match.data());
+    remaining = remaining.drop_front(match_start_pos + match.size());
   }
   if (remaining.size())
     PutCString(remaining);

>From 4ad89ab48b4d50ec5cb01e8f48ec3573083d17b0 Mon Sep 17 00:00:00 2001
From: taalhaataahir0102 <23100293 at lums.edu.pk>
Date: Thu, 30 Nov 2023 11:47:24 +0500
Subject: [PATCH 5/7] Print function updated

---
 lldb/source/Utility/Stream.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index 363b01cf96a0c..2ff13c7cca134 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -85,6 +85,7 @@ void Stream::PutCStringColorHighlighted(llvm::StringRef text,
   llvm::StringRef remaining = text;
   std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes(
       "${ansi.fg.red}%.*s${ansi.normal}");
+
   while (reg_pattern.match(remaining, &matches)) {
     llvm::StringRef match = matches[0];
     size_t match_start_pos = match.data() - remaining.data();

>From 938b6da0a94b55c02c776e47999bff039bbc6321 Mon Sep 17 00:00:00 2001
From: taalhaataahir0102 <23100293 at lums.edu.pk>
Date: Mon, 4 Dec 2023 12:11:02 +0500
Subject: [PATCH 6/7] Using PutCString instead of Printf

---
 lldb/source/Symbol/Symbol.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index af47dc51d9ee9..0a2bb01d5e05a 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -254,14 +254,14 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
                 m_addr_range.GetBaseAddress().GetOffset());
   }
   if (ConstString demangled = m_mangled.GetDemangledName()) {
-    s->Printf(", name=\"");
+    s->PutCString(", name=\"");
     s->PutCStringColorHighlighted(demangled.GetStringRef(), pattern);
-    s->Printf("\"");
+    s->PutCString("\"");
   }
   if (ConstString mangled_name = m_mangled.GetMangledName()) {
-    s->Printf(", mangled=\"");
+    s->PutCString(", mangled=\"");
     s->PutCStringColorHighlighted(mangled_name.GetStringRef(), pattern);
-    s->Printf("\"");
+    s->PutCString("\"");
   }
 }
 

>From 9d910d39ef974655b4a68bcf1915a80161315209 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jos=C3=A9=20L=2E=20Junior?= <josejunior at 10xengineers.ai>
Date: Mon, 4 Dec 2023 20:41:25 -0300
Subject: [PATCH 7/7] add option for custom color | use StringRef instead of
 const char *

---
 lldb/include/lldb/Core/Address.h             |  4 +++-
 lldb/include/lldb/Core/Debugger.h            |  4 ++++
 lldb/include/lldb/Symbol/Symbol.h            |  2 +-
 lldb/include/lldb/Symbol/SymbolContext.h     |  4 ++--
 lldb/include/lldb/Utility/Stream.h           |  5 ++++-
 lldb/source/Commands/CommandObjectTarget.cpp | 10 +++++++---
 lldb/source/Core/Address.cpp                 | 11 ++++++++---
 lldb/source/Core/CoreProperties.td           |  8 ++++++++
 lldb/source/Core/Debugger.cpp                | 12 ++++++++++++
 lldb/source/Symbol/Symbol.cpp                | 11 ++++++++---
 lldb/source/Symbol/SymbolContext.cpp         | 14 +++++++++-----
 lldb/source/Utility/Stream.cpp               | 11 ++++++-----
 12 files changed, 72 insertions(+), 24 deletions(-)

diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h
index c3f2832be424e..9e7b0616509d6 100644
--- a/lldb/include/lldb/Core/Address.h
+++ b/lldb/include/lldb/Core/Address.h
@@ -14,6 +14,8 @@
 #include "lldb/lldb-private-enumerations.h"
 #include "lldb/lldb-types.h"
 
+#include "llvm/ADT/StringRef.h"
+
 #include <cstddef>
 #include <cstdint>
 
@@ -247,7 +249,7 @@ class Address {
   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 char *pattern = nullptr) const;
+            llvm::StringRef pattern = "") const;
 
   AddressClass GetAddressClass() const;
 
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index e4ee94809cf1a..c6d603ca5dcde 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -321,6 +321,10 @@ class Debugger : public std::enable_shared_from_this<Debugger>,
 
   llvm::StringRef GetAutosuggestionAnsiSuffix() const;
 
+  llvm::StringRef GetRegexMatchAnsiPrefix() const;
+
+  llvm::StringRef GetRegexMatchAnsiSuffix() const;
+
   bool GetShowDontUsePoHint() const;
 
   bool GetUseSourceCache() const;
diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h
index 0e41cd95e0ef1..e6c0b495bcf28 100644
--- a/lldb/include/lldb/Symbol/Symbol.h
+++ b/lldb/include/lldb/Symbol/Symbol.h
@@ -175,7 +175,7 @@ class Symbol : public SymbolContextScope {
   void SetFlags(uint32_t flags) { m_flags = flags; }
 
   void GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target,
-                      const char *pattern = nullptr) const;
+                      llvm::StringRef pattern = "") 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 9567c3f4384c1..d1201d1634803 100644
--- a/lldb/include/lldb/Symbol/SymbolContext.h
+++ b/lldb/include/lldb/Symbol/SymbolContext.h
@@ -151,7 +151,7 @@ class SymbolContext {
                        const Address &so_addr, bool show_fullpaths,
                        bool show_module, bool show_inlined_frames,
                        bool show_function_arguments, bool show_function_name,
-                       const char *pattern = nullptr) const;
+                       llvm::StringRef pattern = "") const;
 
   /// Get the address range contained within a symbol context.
   ///
@@ -218,7 +218,7 @@ class SymbolContext {
   const Symbol *FindBestGlobalDataSymbol(ConstString name, Status &error);
 
   void GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target,
-                      const char *pattern = nullptr) const;
+                      llvm::StringRef pattern = "") const;
 
   uint32_t GetResolvedMask() const;
 
diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h
index 8e3fd48dfe705..352a594576afd 100644
--- a/lldb/include/lldb/Utility/Stream.h
+++ b/lldb/include/lldb/Utility/Stream.h
@@ -245,7 +245,10 @@ class Stream {
   ///     The regex pattern to match against the \a text string. Portions of \a
   ///     text matching this pattern will be colorized. If this parameter is
   ///     nullptr, highlighting is not performed.
-  void PutCStringColorHighlighted(llvm::StringRef text, const char *pattern);
+  void PutCStringColorHighlighted(llvm::StringRef text,
+                                  llvm::StringRef pattern = "",
+                                  llvm::StringRef prefix = "",
+                                  llvm::StringRef suffix = "");
 
   /// Output and End of Line character to the stream.
   size_t EOL();
diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp
index 2b888530534b1..63232c221ad1d 100644
--- a/lldb/source/Commands/CommandObjectTarget.cpp
+++ b/lldb/source/Commands/CommandObjectTarget.cpp
@@ -1533,7 +1533,7 @@ static void DumpOsoFilesTable(Stream &strm,
 
 static void DumpAddress(ExecutionContextScope *exe_scope,
                         const Address &so_addr, bool verbose, bool all_ranges,
-                        Stream &strm, const char *pattern = nullptr) {
+                        Stream &strm, llvm::StringRef pattern = "") {
   strm.IndentMore();
   strm.Indent("    Address: ");
   so_addr.Dump(&strm, exe_scope, Address::DumpStyleModuleWithFileAddress);
@@ -1595,7 +1595,7 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
     return 0;
 
   SymbolContext sc;
-  bool use_color = interpreter.GetDebugger().GetUseColor();
+  const bool use_color = interpreter.GetDebugger().GetUseColor();
   std::vector<uint32_t> match_indexes;
   ConstString symbol_name(name);
   uint32_t num_matches = 0;
@@ -1627,9 +1627,13 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter,
         } else {
           strm.IndentMore();
           strm.Indent("    Name: ");
+          llvm::StringRef ansi_prefix =
+              interpreter.GetDebugger().GetRegexMatchAnsiPrefix();
+          llvm::StringRef ansi_suffix =
+              interpreter.GetDebugger().GetRegexMatchAnsiSuffix();
           strm.PutCStringColorHighlighted(
               symbol->GetDisplayName().GetStringRef(),
-              use_color ? name : nullptr);
+              use_color ? name : nullptr, ansi_prefix, ansi_suffix);
           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 4a05a744e0230..d86fb1520a896 100644
--- a/lldb/source/Core/Address.cpp
+++ b/lldb/source/Core/Address.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/Core/Address.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/Declaration.h"
 #include "lldb/Core/DumpDataExtractor.h"
 #include "lldb/Core/Module.h"
@@ -406,7 +407,7 @@ bool Address::GetDescription(Stream &s, Target &target,
 
 bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
                    DumpStyle fallback_style, uint32_t addr_size,
-                   bool all_ranges, const char *pattern) const {
+                   bool all_ranges, llvm::StringRef 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());
@@ -502,7 +503,6 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
         pointer_size = target->GetArchitecture().GetAddressByteSize();
       else if (module_sp)
         pointer_size = module_sp->GetArchitecture().GetAddressByteSize();
-
       bool showed_info = false;
       if (section_sp) {
         SectionType sect_type = section_sp->GetType();
@@ -516,7 +516,12 @@ bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style,
               if (symbol) {
                 const char *symbol_name = symbol->GetName().AsCString();
                 if (symbol_name) {
-                  s->PutCStringColorHighlighted(symbol_name, pattern);
+                  llvm::StringRef ansi_prefix =
+                      target->GetDebugger().GetRegexMatchAnsiPrefix();
+                  llvm::StringRef ansi_suffix =
+                      target->GetDebugger().GetRegexMatchAnsiSuffix();
+                  s->PutCStringColorHighlighted(symbol_name, pattern,
+                                                ansi_prefix, ansi_suffix);
                   addr_t delta =
                       file_Addr - symbol->GetAddressRef().GetFileAddress();
                   if (delta)
diff --git a/lldb/source/Core/CoreProperties.td b/lldb/source/Core/CoreProperties.td
index 92884258347e9..797f80a4d8de5 100644
--- a/lldb/source/Core/CoreProperties.td
+++ b/lldb/source/Core/CoreProperties.td
@@ -203,6 +203,14 @@ let Definition = "debugger" in {
     Global,
     DefaultStringValue<"${ansi.normal}">,
     Desc<"When displaying suggestion in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the suggestion.">;
+  def ShowRegexMatchAnsiPrefix: Property<"show-regex-match-ansi-prefix", "String">,
+    Global,
+    DefaultStringValue<"${ansi.fg.red}">,
+    Desc<"When displaying a regex match in a color-enabled terminal, use the ANSI terminal code specified in this format immediately before the match.">;
+  def ShowRegexMatchAnsiSuffix: Property<"show-regex-match-ansi-suffix", "String">,
+    Global,
+    DefaultStringValue<"${ansi.normal}">,
+    Desc<"When displaying a regex match in a color-enabled terminal, use the ANSI terminal code specified in this format immediately after the match.">;
   def ShowDontUsePoHint: Property<"show-dont-use-po-hint", "Boolean">,
     Global,
     DefaultTrue,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index 21f71e449ca5e..bacaa9950e649 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -453,6 +453,18 @@ llvm::StringRef Debugger::GetAutosuggestionAnsiSuffix() const {
       idx, g_debugger_properties[idx].default_cstr_value);
 }
 
+llvm::StringRef Debugger::GetRegexMatchAnsiPrefix() const {
+  const uint32_t idx = ePropertyShowRegexMatchAnsiPrefix;
+  return GetPropertyAtIndexAs<llvm::StringRef>(
+      idx, g_debugger_properties[idx].default_cstr_value);
+}
+
+llvm::StringRef Debugger::GetRegexMatchAnsiSuffix() const {
+  const uint32_t idx = ePropertyShowRegexMatchAnsiSuffix;
+  return GetPropertyAtIndexAs<llvm::StringRef>(
+      idx, g_debugger_properties[idx].default_cstr_value);
+}
+
 bool Debugger::GetShowDontUsePoHint() const {
   const uint32_t idx = ePropertyShowDontUsePoHint;
   return GetPropertyAtIndexAs<bool>(
diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp
index 0a2bb01d5e05a..0d20d11b8c4ff 100644
--- a/lldb/source/Symbol/Symbol.cpp
+++ b/lldb/source/Symbol/Symbol.cpp
@@ -9,6 +9,7 @@
 #include "lldb/Symbol/Symbol.h"
 
 #include "lldb/Core/Address.h"
+#include "lldb/Core/Debugger.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/Section.h"
@@ -226,7 +227,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 char *pattern) const {
+                            Target *target, llvm::StringRef pattern) const {
   s->Printf("id = {0x%8.8x}", m_uid);
 
   if (m_addr_range.GetBaseAddress().GetSection()) {
@@ -253,14 +254,18 @@ void Symbol::GetDescription(Stream *s, lldb::DescriptionLevel level,
       s->Printf(", value = 0x%16.16" PRIx64,
                 m_addr_range.GetBaseAddress().GetOffset());
   }
+  llvm::StringRef ansi_prefix = target->GetDebugger().GetRegexMatchAnsiPrefix();
+  llvm::StringRef ansi_suffix = target->GetDebugger().GetRegexMatchAnsiSuffix();
   if (ConstString demangled = m_mangled.GetDemangledName()) {
     s->PutCString(", name=\"");
-    s->PutCStringColorHighlighted(demangled.GetStringRef(), pattern);
+    s->PutCStringColorHighlighted(demangled.GetStringRef(), pattern,
+                                  ansi_prefix, ansi_suffix);
     s->PutCString("\"");
   }
   if (ConstString mangled_name = m_mangled.GetMangledName()) {
     s->PutCString(", mangled=\"");
-    s->PutCStringColorHighlighted(mangled_name.GetStringRef(), pattern);
+    s->PutCStringColorHighlighted(mangled_name.GetStringRef(), pattern,
+                                  ansi_prefix, ansi_suffix);
     s->PutCString("\"");
   }
 }
diff --git a/lldb/source/Symbol/SymbolContext.cpp b/lldb/source/Symbol/SymbolContext.cpp
index b70e02743cec6..844fe19437160 100644
--- a/lldb/source/Symbol/SymbolContext.cpp
+++ b/lldb/source/Symbol/SymbolContext.cpp
@@ -73,7 +73,7 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
                                     bool show_module, bool show_inlined_frames,
                                     bool show_function_arguments,
                                     bool show_function_name,
-                                    const char *pattern) const {
+                                    llvm::StringRef pattern) const {
   bool dumped_something = false;
   if (show_module && module_sp) {
     if (show_fullpaths)
@@ -83,7 +83,6 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
     s->PutChar('`');
     dumped_something = true;
   }
-
   if (function != nullptr) {
     SymbolContext inline_parent_sc;
     Address inline_parent_addr;
@@ -96,8 +95,12 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
         name = function->GetNameNoArguments();
       if (!name)
         name = function->GetName();
-      if (name)
-        s->PutCStringColorHighlighted(name.GetStringRef(), pattern);
+      if (name) {
+        llvm::StringRef ansi_prefix = "${ansi.fg.red}";
+        llvm::StringRef ansi_suffix = "${ansi.normal}";
+        s->PutCStringColorHighlighted(name.GetStringRef(), pattern, ansi_prefix,
+                                      ansi_suffix);
+      }
     }
 
     if (addr.IsValid()) {
@@ -188,7 +191,8 @@ bool SymbolContext::DumpStopContext(Stream *s, ExecutionContextScope *exe_scope,
 }
 
 void SymbolContext::GetDescription(Stream *s, lldb::DescriptionLevel level,
-                                   Target *target, const char *pattern) const {
+                                   Target *target,
+                                   llvm::StringRef pattern) const {
   if (module_sp) {
     s->Indent("     Module: file = \"");
     module_sp->GetFileSpec().Dump(s->AsRawOstream());
diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index 2ff13c7cca134..a40fd448b567a 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -73,19 +73,20 @@ size_t Stream::PutCString(llvm::StringRef str) {
 }
 
 void Stream::PutCStringColorHighlighted(llvm::StringRef text,
-                                        const char *pattern) {
-  if (!pattern) {
+                                        llvm::StringRef pattern,
+                                        llvm::StringRef prefix,
+                                        llvm::StringRef suffix) {
+  // If there is no pattern to match, we should not use color
+  if (pattern.empty()) {
     PutCString(text);
     return;
   }
 
-  // If pattern is not nullptr, we should use color
   llvm::Regex reg_pattern(pattern);
   llvm::SmallVector<llvm::StringRef, 1> matches;
   llvm::StringRef remaining = text;
   std::string format_str = lldb_private::ansi::FormatAnsiTerminalCodes(
-      "${ansi.fg.red}%.*s${ansi.normal}");
-
+      prefix.str() + "%.*s" + suffix.str());
   while (reg_pattern.match(remaining, &matches)) {
     llvm::StringRef match = matches[0];
     size_t match_start_pos = match.data() - remaining.data();



More information about the lldb-commits mailing list