varunkumare99 created this revision. varunkumare99 added a reviewer: DavidSpickett. Herald added a project: All. varunkumare99 requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
added support for colored output for the commands 1. image lookup -r -s <func-regex> 2. image lookup -r -n <func-regex> For option (1) lookupSymbolInModule(CommandObjectTarget.cpp) is called. We first match the regex against the symbol names. Then update the name(Symbol Demangled name) with colored matches. So that the symbol when displayed down the line(in SymbolContext.DumpStopContext) is printed with colored text. Once the symbols are displayed, we restore the original symbols names.(Symbol Demangled name) For option (2) lookupfunctionInModule(CommandObjectTarget.cpp) is called. As the symbol names are accessed in Module.cpp we repeat the above process in it. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D136462 Files: lldb/include/lldb/Core/Module.h lldb/include/lldb/Symbol/Symbol.h lldb/include/lldb/Symbol/Symtab.h lldb/source/Commands/CommandObjectTarget.cpp lldb/source/Core/Module.cpp lldb/source/Symbol/Symbol.cpp lldb/source/Symbol/Symtab.cpp
Index: lldb/source/Symbol/Symtab.cpp =================================================================== --- lldb/source/Symbol/Symtab.cpp +++ lldb/source/Symbol/Symtab.cpp @@ -742,6 +742,34 @@ return indexes.size(); } +uint32_t Symtab::AppendSymbolIndexesMatchingRegExWithMatchesAndType( + Stream &strm, const RegularExpression ®exp, SymbolType symbol_type, + std::vector<uint32_t> &indexes, + llvm::SmallVector< + std::pair<const char *, llvm::SmallVector<llvm::StringRef>>> + &allMatches, + Mangled::NamePreference name_preference) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + uint32_t prev_size = indexes.size(); + uint32_t sym_end = m_symbols.size(); + + for (uint32_t i = 0; i < sym_end; i++) { + llvm::SmallVector<llvm::StringRef> matches; + if (symbol_type == eSymbolTypeAny || + m_symbols[i].GetType() == symbol_type) { + const char *name = + m_symbols[i].GetMangled().GetName(name_preference).AsCString(); + if (name) { + if (regexp.Execute(name, &matches)) { + allMatches.push_back(std::make_pair(name, matches)); + indexes.push_back(i); + } + } + } + } + return indexes.size() - prev_size; +} + uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, std::vector<uint32_t> &indexes, Mangled::NamePreference name_preference) { @@ -764,6 +792,39 @@ return indexes.size() - prev_size; } +uint32_t Symtab::AppendSymbolIndexesMatchingRegExWithMatchesAndType( + const RegularExpression ®exp, SymbolType symbol_type, + Debug symbol_debug_type, Visibility symbol_visibility, + std::vector<uint32_t> &indexes, + llvm::SmallVector< + std::pair<const char *, llvm::SmallVector<llvm::StringRef>>> + &allMatches, + Mangled::NamePreference name_preference) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + uint32_t prev_size = indexes.size(); + uint32_t sym_end = m_symbols.size(); + + for (uint32_t i = 0; i < sym_end; i++) { + llvm::SmallVector<llvm::StringRef> matches; + if (symbol_type == eSymbolTypeAny || + m_symbols[i].GetType() == symbol_type) { + if (!CheckSymbolAtIndex(i, symbol_debug_type, symbol_visibility)) + continue; + + const char *name = + m_symbols[i].GetMangled().GetName(name_preference).AsCString(); + if (name) { + if (regexp.Execute(name, &matches)) { + indexes.push_back(i); + allMatches.push_back(std::make_pair(name, matches)); + } + } + } + } + return indexes.size() - prev_size; +} + uint32_t Symtab::AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®exp, SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, Index: lldb/source/Symbol/Symbol.cpp =================================================================== --- lldb/source/Symbol/Symbol.cpp +++ lldb/source/Symbol/Symbol.cpp @@ -122,6 +122,10 @@ return GetMangled().GetDisplayDemangledName(); } +void Symbol::SetName(llvm::StringRef name) { + m_mangled.SetDemangledName(ConstString(name)); +} + ConstString Symbol::GetReExportedSymbolName() const { if (m_type == eSymbolTypeReExported) { // For eSymbolTypeReExported, the "const char *" from a ConstString is used Index: lldb/source/Core/Module.cpp =================================================================== --- lldb/source/Core/Module.cpp +++ lldb/source/Core/Module.cpp @@ -38,6 +38,7 @@ #include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" @@ -856,6 +857,135 @@ } } +bool Module::isColor(size_t pos, + llvm::SmallVector<std::pair<size_t, size_t>> &positions) { + for (size_t i = 0; i < positions.size(); ++i) { + if (pos >= positions[i].first && pos <= positions[i].second) { + return true; + } + } + return false; +} + +void Module::RestoreOriginalFunctionNames( + llvm::SmallVector<std::pair<int, llvm::StringRef>> &origNames) { + if (SymbolFile *symbols = GetSymbolFile()) { + Symtab *symtab = symbols->GetSymtab(); + if (symtab) { + for (size_t i = 0; i < origNames.size(); ++i) { + symtab->SymbolAtIndex(origNames[i].first)->SetName(origNames[i].second); + } + } + } +} + +void Module::FindFunctionsAndSaveNames( + const RegularExpression ®ex, const ModuleFunctionSearchOptions &options, + SymbolContextList &sc_list, + llvm::SmallVector<std::pair<int, llvm::StringRef>> &origNames) { + const size_t start_size = sc_list.GetSize(); + + if (SymbolFile *symbols = GetSymbolFile()) { + symbols->FindFunctions(regex, options.include_inlines, sc_list); + + // Now check our symbol table for symbols that are code symbols if + // requested + if (options.include_symbols) { + Symtab *symtab = symbols->GetSymtab(); + if (symtab) { + std::vector<uint32_t> symbol_indexes; + llvm::SmallVector< + std::pair<const char *, llvm::SmallVector<llvm::StringRef>>> + allMatches; + symtab->AppendSymbolIndexesMatchingRegExWithMatchesAndType( + regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, + symbol_indexes, allMatches); + const size_t num_matches = symbol_indexes.size(); + if (num_matches) { + for (uint32_t i = 0; i < num_matches; ++i) { + Symbol *symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + // save original symbol name + origNames.push_back(std::make_pair( + symbol_indexes[i], symbol->GetDisplayName().GetStringRef())); + + // find the positions of substring matches in symbol name + llvm::SmallVector<std::pair<size_t, size_t>> positions; + for (size_t j = 0; j < allMatches[i].second.size(); ++j) { + size_t pos = symbol->GetDisplayName().GetStringRef().find( + allMatches[i].second[j]); + if (pos != std::string::npos) { + positions.push_back(std::make_pair( + pos, pos + allMatches[i].second[j].size() - 1)); + } + } + + llvm::StringRef displayName = symbol->GetDisplayName().GetCString(); + std::string coloredName; + for (size_t j = 0; + j < symbol->GetDisplayName().GetStringRef().size(); ++j) { + if (isColor(j, positions)) { + coloredName += ANSI_ESCAPE1(ANSI_FG_COLOR_RED); + coloredName += displayName[j]; + coloredName += ANSI_ESCAPE1(ANSI_CTRL_NORMAL); + } else + coloredName += displayName[j]; + } + // set colored name + symbol->SetName(llvm::StringRef(coloredName)); + } + } + if (num_matches) { + SymbolContext sc(this); + const size_t end_functions_added_index = sc_list.GetSize(); + size_t num_functions_added_to_sc_list = + end_functions_added_index - start_size; + if (num_functions_added_to_sc_list == 0) { + // No functions were added, just symbols, so we can just append + // them + for (size_t i = 0; i < num_matches; ++i) { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) + sc_list.Append(sc); + } + } else { + typedef std::map<lldb::addr_t, uint32_t> FileAddrToIndexMap; + FileAddrToIndexMap file_addr_to_index; + for (size_t i = start_size; i < end_functions_added_index; ++i) { + const SymbolContext &sc = sc_list[i]; + if (sc.block) + continue; + file_addr_to_index[sc.function->GetAddressRange() + .GetBaseAddress() + .GetFileAddress()] = i; + } + + FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); + // Functions were added so we need to merge symbols into any + // existing function symbol contexts + for (size_t i = start_size; i < num_matches; ++i) { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && sc.symbol->ValueIsAddress() && + (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) { + FileAddrToIndexMap::const_iterator pos = + file_addr_to_index.find( + sc.symbol->GetAddressRef().GetFileAddress()); + if (pos == end) + sc_list.Append(sc); + else + sc_list[pos->second].symbol = sc.symbol; + } + } + } + } + } + } + } +} + void Module::FindFunctions(const RegularExpression ®ex, const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list) { Index: lldb/source/Commands/CommandObjectTarget.cpp =================================================================== --- lldb/source/Commands/CommandObjectTarget.cpp +++ lldb/source/Commands/CommandObjectTarget.cpp @@ -47,6 +47,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" +#include "lldb/Utility/AnsiTerminal.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/FileSpec.h" @@ -64,7 +65,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatAdapters.h" - using namespace lldb; using namespace lldb_private; @@ -1508,6 +1508,16 @@ return false; } +static bool isColor(size_t pos, + llvm::SmallVector<std::pair<size_t, size_t>> &positions) { + for (size_t i = 0; i < positions.size(); ++i) { + if (pos >= positions[i].first && pos <= positions[i].second) { + return true; + } + } + return false; +} + static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, @@ -1523,16 +1533,20 @@ std::vector<uint32_t> match_indexes; ConstString symbol_name(name); uint32_t num_matches = 0; + llvm::SmallVector<std::pair<const char *, llvm::SmallVector<llvm::StringRef>>> + allMatches; + if (name_is_regex) { RegularExpression name_regexp(symbol_name.GetStringRef()); - num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( - name_regexp, eSymbolTypeAny, match_indexes); + num_matches = symtab->AppendSymbolIndexesMatchingRegExWithMatchesAndType( + strm, name_regexp, eSymbolTypeAny, match_indexes, allMatches); } else { num_matches = symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); } if (num_matches > 0) { + std::vector<std::pair<int, llvm::StringRef>> origNames; strm.Indent(); strm.Printf("%u symbols match %s'%s' in ", num_matches, name_is_regex ? "the regular expression " : "", name); @@ -1541,6 +1555,36 @@ strm.IndentMore(); for (uint32_t i = 0; i < num_matches; ++i) { Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); + + // save original symbol names + origNames.push_back(std::make_pair( + match_indexes[i], symbol->GetDisplayName().GetStringRef())); + + // find the positions of substring matches in symbol name + llvm::SmallVector<std::pair<size_t, size_t>> positions; + for (size_t j = 0; j < allMatches[i].second.size(); ++j) { + size_t pos = symbol->GetDisplayName().GetStringRef().find( + allMatches[i].second[j]); + if (pos != std::string::npos) { + positions.push_back( + std::make_pair(pos, pos + allMatches[i].second[j].size() - 1)); + } + } + + llvm::StringRef displayName = symbol->GetDisplayName().GetCString(); + std::string coloredName; + for (size_t j = 0; j < symbol->GetDisplayName().GetStringRef().size(); + ++j) { + if (isColor(j, positions)) { + coloredName += ANSI_ESCAPE1(ANSI_FG_COLOR_RED); + coloredName += displayName[j]; + coloredName += ANSI_ESCAPE1(ANSI_CTRL_NORMAL); + } else + coloredName += displayName[j]; + } + // set colored name + symbol->SetName(llvm::StringRef(coloredName)); + if (symbol) { if (symbol->ValueIsAddress()) { DumpAddress( @@ -1552,6 +1596,7 @@ strm.Indent(" Name: "); strm.PutCString(symbol->GetDisplayName().GetStringRef()); strm.EOL(); + strm.Indent(" Value: "); strm.Printf("0x%16.16" PRIx64 "\n", symbol->GetRawValue()); if (symbol->GetByteSizeIsValid()) { @@ -1563,6 +1608,10 @@ } } strm.IndentLess(); + // set back to original names + for (size_t i = 0; i < origNames.size(); ++i) { + symtab->SymbolAtIndex(origNames[i].first)->SetName(origNames[i].second); + } } return num_matches; } @@ -1580,7 +1629,6 @@ AddressRange range; sc.GetAddressRange(eSymbolContextEverything, 0, true, range); - DumpAddress(exe_scope, range.GetBaseAddress(), verbose, all_ranges, strm); } } @@ -1593,11 +1641,14 @@ const ModuleFunctionSearchOptions &options, bool verbose, bool all_ranges) { if (module && name && name[0]) { + llvm::SmallVector<std::pair<int, llvm::StringRef>> origNames; SymbolContextList sc_list; size_t num_matches = 0; if (name_is_regex) { RegularExpression function_name_regex((llvm::StringRef(name))); - module->FindFunctions(function_name_regex, options, sc_list); + module->FindFunctionsAndSaveNames(function_name_regex, options, sc_list, + origNames); + } else { ConstString function_name(name); module->FindFunctions(function_name, CompilerDeclContext(), @@ -1613,6 +1664,7 @@ DumpSymbolContextList( interpreter.GetExecutionContext().GetBestExecutionContextScope(), strm, sc_list, verbose, all_ranges); + module->RestoreOriginalFunctionNames(origNames); } return num_matches; } Index: lldb/include/lldb/Symbol/Symtab.h =================================================================== --- lldb/include/lldb/Symbol/Symtab.h +++ lldb/include/lldb/Symbol/Symtab.h @@ -89,10 +89,27 @@ Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t> &matches); + uint32_t AppendSymbolIndexesMatchingRegExWithMatchesAndType( + Stream &strm, const RegularExpression ®ex, + lldb::SymbolType symbol_type, std::vector<uint32_t> &indexes, + llvm::SmallVector< + std::pair<const char *, llvm::SmallVector<llvm::StringRef>>> + &allMatches, + Mangled::NamePreference name_preference = + Mangled::ePreferDemangled) const; uint32_t AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, std::vector<uint32_t> &indexes, Mangled::NamePreference name_preference = Mangled::ePreferDemangled); + uint32_t AppendSymbolIndexesMatchingRegExWithMatchesAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + Debug symbol_debug_type, Visibility symbol_visibility, + std::vector<uint32_t> &indexes, + llvm::SmallVector< + std::pair<const char *, llvm::SmallVector<llvm::StringRef>>> + &allMatches, + Mangled::NamePreference name_preference = + Mangled::NamePreference::ePreferDemangled); uint32_t AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, Index: lldb/include/lldb/Symbol/Symbol.h =================================================================== --- lldb/include/lldb/Symbol/Symbol.h +++ lldb/include/lldb/Symbol/Symbol.h @@ -114,6 +114,8 @@ ConstString GetName() const; + void SetName(llvm::StringRef name); + ConstString GetNameNoArguments() const; ConstString GetDisplayName() const; Index: lldb/include/lldb/Core/Module.h =================================================================== --- lldb/include/lldb/Core/Module.h +++ lldb/include/lldb/Core/Module.h @@ -352,6 +352,43 @@ const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list); + /// Find functions by name, save their orignal names. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will be NULL. + /// + /// \param[in] regex + /// A regular expression to use when matching the name and modify the name + /// with the colored match. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// \param[out] origNames + // A vector that gets filled in with all the orignal symbol names. + + void FindFunctionsAndSaveNames( + const RegularExpression ®ex, + const ModuleFunctionSearchOptions &options, SymbolContextList &sc_list, + llvm::SmallVector<std::pair<int, llvm::StringRef>> &origNames); + + /// Restore back the original function names. + /// + /// \param[in] origNames + /// A vector of orignal names of symbols. + /// + void RestoreOriginalFunctionNames( + llvm::SmallVector<std::pair<int, llvm::StringRef>> &origNames); + + /// Helper function used by FindFunctionsAndSaveNames + /// \param[in] pos + /// current index of symbol name character + /// \param[i] positions + /// A vector of ranges over the symbol name, where it needs to be colored + static bool isColor(size_t pos, + llvm::SmallVector<std::pair<size_t, size_t>> &positions); + /// Find addresses by file/line /// /// \param[in] target_sp
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits