[Lldb-commits] [lldb] [lldb] colorize symbols in image lookup (PR #69422)
José Lira Junior via lldb-commits
lldb-commits at lists.llvm.org
Mon Nov 27 09:57:52 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/2] [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 b19e694427546f8b..c3f2832be424efd8 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 44a2d560010fe403..0e41cd95e0ef17d2 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 b0f5ffead2a16569..9567c3f4384c1752 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 1a5fd343e4df0dc9..8e3fd48dfe705799 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 58785cde3ec7c63c..991194972e02442b 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 189d50fe962a651c..4a05a744e02300f4 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 26b4c4d62ad9c246..af47dc51d9ee9cd5 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 63968ec2d1506705..21064b1fd1b3838d 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 af28a49a1f0c2b5a..04679d9b017b117b 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 0000000000000000..a58f05680762b671
--- /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/2] 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 21064b1fd1b3838d..b70e02743cec6f3c 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()) {
More information about the lldb-commits
mailing list