diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h --- a/lldb/include/lldb/Core/Module.h +++ b/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> &origNames); + + /// Restore back the original function names. + /// + /// \param[in] origNames + /// A vector of orignal names of symbols. + /// + void RestoreOriginalFunctionNames( + llvm::SmallVector> &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> &positions); + /// Find addresses by file/line /// /// \param[in] target_sp diff --git a/lldb/include/lldb/Symbol/Symbol.h b/lldb/include/lldb/Symbol/Symbol.h --- a/lldb/include/lldb/Symbol/Symbol.h +++ b/lldb/include/lldb/Symbol/Symbol.h @@ -114,6 +114,8 @@ ConstString GetName() const; + void SetName(llvm::StringRef name); + ConstString GetNameNoArguments() const; ConstString GetDisplayName() const; diff --git a/lldb/include/lldb/Symbol/Symtab.h b/lldb/include/lldb/Symbol/Symtab.h --- a/lldb/include/lldb/Symbol/Symtab.h +++ b/lldb/include/lldb/Symbol/Symtab.h @@ -89,10 +89,27 @@ Debug symbol_debug_type, Visibility symbol_visibility, std::vector &matches); + uint32_t AppendSymbolIndexesMatchingRegExWithMatchesAndType( + Stream &strm, const RegularExpression ®ex, + lldb::SymbolType symbol_type, std::vector &indexes, + llvm::SmallVector< + std::pair>> + &allMatches, + Mangled::NamePreference name_preference = + Mangled::ePreferDemangled) const; uint32_t AppendSymbolIndexesMatchingRegExAndType( const RegularExpression ®ex, lldb::SymbolType symbol_type, std::vector &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 &indexes, + llvm::SmallVector< + std::pair>> + &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, diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/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> &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 match_indexes; ConstString symbol_name(name); uint32_t num_matches = 0; + llvm::SmallVector>> + 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> 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> 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> 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; } diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp --- a/lldb/source/Core/Module.cpp +++ b/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> &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> &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> &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 symbol_indexes; + llvm::SmallVector< + std::pair>> + 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> 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 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) { diff --git a/lldb/source/Symbol/Symbol.cpp b/lldb/source/Symbol/Symbol.cpp --- a/lldb/source/Symbol/Symbol.cpp +++ b/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 diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp --- a/lldb/source/Symbol/Symtab.cpp +++ b/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 &indexes, + llvm::SmallVector< + std::pair>> + &allMatches, + Mangled::NamePreference name_preference) const { + std::lock_guard 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 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 &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 &indexes, + llvm::SmallVector< + std::pair>> + &allMatches, + Mangled::NamePreference name_preference) { + std::lock_guard 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 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,