From 87df91b8661737980b58f7d1d05c27534c57f490 Mon Sep 17 00:00:00 2001 From: Jim Ingham Date: Fri, 23 Sep 2011 00:54:11 +0000 Subject: [PATCH] Added the ability to restrict breakpoints by function name, function regexp, selector etc to specific source files. Added SB API's to specify these source files & also more than one module. Added an "exact" option to CompileUnit's FindLineEntry API. llvm-svn: 140362 --- lldb/include/lldb/API/SBCompileUnit.h | 6 + lldb/include/lldb/API/SBFileSpecList.h | 4 +- lldb/include/lldb/API/SBTarget.h | 20 +- .../Breakpoint/BreakpointResolverFileRegex.h | 4 +- lldb/include/lldb/Core/FileSpecList.h | 5 +- lldb/include/lldb/Core/SearchFilter.h | 78 ++++++ lldb/include/lldb/Symbol/CompileUnit.h | 5 + lldb/include/lldb/Target/Target.h | 16 +- lldb/scripts/Python/interface/SBCompileUnit.i | 6 + .../scripts/Python/interface/SBFileSpecList.i | 2 +- lldb/source/API/SBCompileUnit.cpp | 8 + lldb/source/API/SBFileSpecList.cpp | 4 +- lldb/source/API/SBTarget.cpp | 90 ++++++- .../BreakpointResolverFileRegex.cpp | 88 ++++--- .../Breakpoint/BreakpointResolverName.cpp | 34 ++- .../Commands/CommandObjectBreakpoint.cpp | 143 ++++++----- .../source/Commands/CommandObjectBreakpoint.h | 6 +- lldb/source/Commands/CommandObjectThread.cpp | 3 +- lldb/source/Core/FileLineResolver.cpp | 4 +- lldb/source/Core/FileSpecList.cpp | 4 +- lldb/source/Core/SearchFilter.cpp | 222 +++++++++++++++++- lldb/source/Host/common/FileSpec.cpp | 6 +- .../DynamicLoaderDarwinKernel.cpp | 1 + .../ItaniumABI/ItaniumABILanguageRuntime.cpp | 2 + .../AppleObjCRuntime/AppleObjCRuntimeV1.cpp | 1 + .../AppleObjCRuntime/AppleObjCRuntimeV2.cpp | 1 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 2 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 4 +- lldb/source/Symbol/CompileUnit.cpp | 13 +- lldb/source/Target/Target.cpp | 40 +++- .../breakpoint/breakpoint_command/Makefile | 2 +- .../TestBreakpointCommand.py | 19 ++ .../breakpoint/breakpoint_command/a.c | 9 + .../breakpoint/breakpoint_command/b.c | 9 + 34 files changed, 691 insertions(+), 170 deletions(-) create mode 100644 lldb/test/functionalities/breakpoint/breakpoint_command/a.c create mode 100644 lldb/test/functionalities/breakpoint/breakpoint_command/b.c diff --git a/lldb/include/lldb/API/SBCompileUnit.h b/lldb/include/lldb/API/SBCompileUnit.h index 8d67e19e4018..1312458b1cfd 100644 --- a/lldb/include/lldb/API/SBCompileUnit.h +++ b/lldb/include/lldb/API/SBCompileUnit.h @@ -47,6 +47,12 @@ public: uint32_t line, lldb::SBFileSpec *inline_file_spec) const; + uint32_t + FindLineEntryIndex (uint32_t start_idx, + uint32_t line, + lldb::SBFileSpec *inline_file_spec, + bool exact) const; + #ifndef SWIG bool diff --git a/lldb/include/lldb/API/SBFileSpecList.h b/lldb/include/lldb/API/SBFileSpecList.h index 720c07822b69..90b6798fb566 100644 --- a/lldb/include/lldb/API/SBFileSpecList.h +++ b/lldb/include/lldb/API/SBFileSpecList.h @@ -44,13 +44,15 @@ public: Clear(); uint32_t - FindFileIndex (uint32_t idx, const SBFileSpec &sb_file); + FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full); const SBFileSpec GetFileSpecAtIndex (uint32_t idx) const; private: +friend class SBTarget; + #ifndef SWIG const lldb_private::FileSpecList * diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 3c95969bfb68..2aadbd1afe6c 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -14,6 +14,7 @@ #include "lldb/API/SBAddress.h" #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFileSpecList.h" #include "lldb/API/SBType.h" namespace lldb { @@ -314,11 +315,28 @@ public: lldb::SBBreakpoint BreakpointCreateByName (const char *symbol_name, const char *module_name = NULL); + lldb::SBBreakpoint + BreakpointCreateByName (const char *symbol_name, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + lldb::SBBreakpoint BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name = NULL); lldb::SBBreakpoint - BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name = NULL); + BreakpointCreateByRegex (const char *symbol_name_regex, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list); + + lldb::SBBreakpoint + BreakpointCreateBySourceRegex (const char *source_regex, + const lldb::SBFileSpec &source_file, + const char *module_name = NULL); + + lldb::SBBreakpoint + BreakpointCreateBySourceRegex (const char *source_regex, + const SBFileSpecList &module_list, + const lldb::SBFileSpecList &source_file); lldb::SBBreakpoint BreakpointCreateByAddress (addr_t address); diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h index 22321677b59e..f1c2b1409e92 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -29,7 +29,6 @@ class BreakpointResolverFileRegex : { public: BreakpointResolverFileRegex (Breakpoint *bkpt, - const FileSpec &resolver, RegularExpression ®ex); virtual @@ -58,8 +57,7 @@ public: protected: friend class Breakpoint; - FileSpec m_file_spec; // This is the file spec we are looking for. - RegularExpression m_regex; // This is the line number that we are looking for. + RegularExpression m_regex; // This is the line expression that we are looking for. private: DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex); diff --git a/lldb/include/lldb/Core/FileSpecList.h b/lldb/include/lldb/Core/FileSpecList.h index ab0e5af77eb7..a8be828cd38c 100644 --- a/lldb/include/lldb/Core/FileSpecList.h +++ b/lldb/include/lldb/Core/FileSpecList.h @@ -116,12 +116,15 @@ public: /// @param[in] file /// The file specification to search for. /// + /// @param[in] full + /// Should FileSpec::Equal be called with "full" true or false. + /// /// @return /// The index of the file that matches \a file if it is found, /// else UINT32_MAX is returned. //------------------------------------------------------------------ uint32_t - FindFileIndex (uint32_t idx, const FileSpec &file) const; + FindFileIndex (uint32_t idx, const FileSpec &file, bool full) const; //------------------------------------------------------------------ /// Get file at index. diff --git a/lldb/include/lldb/Core/SearchFilter.h b/lldb/include/lldb/Core/SearchFilter.h index c359cb33aa79..715acf3971b4 100644 --- a/lldb/include/lldb/Core/SearchFilter.h +++ b/lldb/include/lldb/Core/SearchFilter.h @@ -216,6 +216,21 @@ public: virtual void SearchInModuleList (Searcher &searcher, ModuleList &modules); + //------------------------------------------------------------------ + /// This determines which items are REQUIRED for the filter to pass. + /// For instance, if you are filtering by Compilation Unit, obviously + /// symbols that have no compilation unit can't pass So return eSymbolContextCU + /// and search callbacks can then short cut the search to avoid looking at + /// things that obviously won't pass. + /// + /// @return + /// The required elements for the search, which is an or'ed together + /// set of lldb:SearchContextItem enum's. + /// + //------------------------------------------------------------------ + virtual uint32_t + GetFilterRequiredItems (); + //------------------------------------------------------------------ /// Prints a canonical description for the search filter to the stream \a s. /// @@ -311,6 +326,9 @@ public: virtual void GetDescription(Stream *s); + virtual uint32_t + GetFilterRequiredItems (); + virtual void Dump (Stream *s) const; @@ -369,6 +387,65 @@ public: virtual void GetDescription(Stream *s); + virtual uint32_t + GetFilterRequiredItems (); + + virtual void + Dump (Stream *s) const; + + virtual void + Search (Searcher &searcher); + +private: + FileSpecList m_module_spec_list; +}; + +class SearchFilterByModuleListAndCU : + public SearchFilterByModuleList +{ +public: + + //------------------------------------------------------------------ + /// The basic constructor takes a Target, which gives the space to search, + /// and the module list to restrict the search to. + /// + /// @param[in] target + /// The Target that provides the module list to search. + /// + /// @param[in] module + /// The Module that limits the search. + //------------------------------------------------------------------ + SearchFilterByModuleListAndCU (lldb::TargetSP &targetSP, + const FileSpecList &module_list, + const FileSpecList &cu_list); + + SearchFilterByModuleListAndCU (const SearchFilterByModuleListAndCU& rhs); + + virtual + ~SearchFilterByModuleListAndCU (); + + const SearchFilterByModuleListAndCU& + operator=(const SearchFilterByModuleListAndCU& rhs); + + virtual bool + SymbolContextPasses (const SymbolContext &context, + lldb::SymbolContextItem scope); + + virtual bool + AddressPasses (Address &address); + + virtual bool + CompUnitPasses (FileSpec &fileSpec); + + virtual bool + CompUnitPasses (CompileUnit &compUnit); + + virtual void + GetDescription(Stream *s); + + virtual uint32_t + GetFilterRequiredItems (); + virtual void Dump (Stream *s) const; @@ -377,6 +454,7 @@ public: private: FileSpecList m_module_spec_list; + FileSpecList m_cu_spec_list; }; } // namespace lldb_private diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index 98a245aa8e3f..9767ff1ac8dc 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -202,6 +202,10 @@ public: /// else if NULL, search for line entries that match the compile /// unit file. /// + /// @param[in] exact + /// If \btrue match only if there is a line table entry for this line number. + /// If \bfalse, find the line table entry equal to or after this line number. + /// /// @param[out] line_entry /// If non-NULL, a copy of the line entry that was found. /// @@ -213,6 +217,7 @@ public: FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, + bool exact, LineEntry *line_entry); //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index c7696b8c514c..22340ab035e1 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -250,10 +250,10 @@ public: bool check_inlines, bool internal = false); - // Use this to create breakpoint that matches regex against the source lines in file: + // Use this to create breakpoint that matches regex against the source lines in files given in source_file_list: lldb::BreakpointSP - CreateBreakpoint (const FileSpecList *containingModules, - const FileSpec &file, + CreateSourceRegexBreakpoint (const FileSpecList *containingModules, + const FileSpecList *source_file_list, RegularExpression &source_regex, bool internal = false); @@ -267,11 +267,12 @@ public: CreateBreakpoint (Address &addr, bool internal = false); - // Use this to create a function breakpoint by regexp in containingModule, or all modules if it is NULL + // Use this to create a function breakpoint by regexp in containingModule/containingSourceFiles, or all modules if it is NULL // When "skip_prologue is set to eLazyBoolCalculate, we use the current target // setting, else we use the values passed in lldb::BreakpointSP - CreateBreakpoint (const FileSpecList *containingModules, + CreateFuncRegexBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, RegularExpression &func_regexp, bool internal = false, LazyBool skip_prologue = eLazyBoolCalculate); @@ -281,6 +282,7 @@ public: // setting, else we use the values passed in lldb::BreakpointSP CreateBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, const char *func_name, uint32_t func_name_type_mask, bool internal = false, @@ -889,6 +891,10 @@ protected: lldb::SearchFilterSP GetSearchFilterForModuleList (const FileSpecList *containingModuleList); + + lldb::SearchFilterSP + GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles); + static void ImageSearchPathsChanged (const PathMappingList &path_list, diff --git a/lldb/scripts/Python/interface/SBCompileUnit.i b/lldb/scripts/Python/interface/SBCompileUnit.i index a9294ec5d976..6b37d1d2afbe 100644 --- a/lldb/scripts/Python/interface/SBCompileUnit.i +++ b/lldb/scripts/Python/interface/SBCompileUnit.i @@ -71,6 +71,12 @@ public: uint32_t line, lldb::SBFileSpec *inline_file_spec) const; + uint32_t + FindLineEntryIndex (uint32_t start_idx, + uint32_t line, + lldb::SBFileSpec *inline_file_spec, + bool exact) const; + bool GetDescription (lldb::SBStream &description); }; diff --git a/lldb/scripts/Python/interface/SBFileSpecList.i b/lldb/scripts/Python/interface/SBFileSpecList.i index 5ad4742d6873..38a6f43bdc76 100644 --- a/lldb/scripts/Python/interface/SBFileSpecList.i +++ b/lldb/scripts/Python/interface/SBFileSpecList.i @@ -34,7 +34,7 @@ public: Clear(); uint32_t - FindFileIndex (uint32_t idx, const SBFileSpec &sb_file); + FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full); const SBFileSpec GetFileSpecAtIndex (uint32_t idx) const; diff --git a/lldb/source/API/SBCompileUnit.cpp b/lldb/source/API/SBCompileUnit.cpp index 4ff799afd10c..58723e5a394f 100644 --- a/lldb/source/API/SBCompileUnit.cpp +++ b/lldb/source/API/SBCompileUnit.cpp @@ -98,6 +98,13 @@ SBCompileUnit::GetLineEntryAtIndex (uint32_t idx) const uint32_t SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec *inline_file_spec) const +{ + const bool exact = true; + return FindLineEntryIndex (start_idx, line, inline_file_spec, exact); +} + +uint32_t +SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec *inline_file_spec, bool exact) const { LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); @@ -114,6 +121,7 @@ SBCompileUnit::FindLineEntryIndex (uint32_t start_idx, uint32_t line, SBFileSpec index = m_opaque_ptr->FindLineEntry (start_idx, line, inline_file_spec ? inline_file_spec->get() : NULL, + exact, NULL); } diff --git a/lldb/source/API/SBFileSpecList.cpp b/lldb/source/API/SBFileSpecList.cpp index af7621864368..a4250bc4c59b 100644 --- a/lldb/source/API/SBFileSpecList.cpp +++ b/lldb/source/API/SBFileSpecList.cpp @@ -80,9 +80,9 @@ SBFileSpecList::Clear() } uint32_t -SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file) +SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file, bool full) { - return m_opaque_ap->FindFileIndex (idx, sb_file.ref()); + return m_opaque_ap->FindFileIndex (idx, sb_file.ref(), full); } const SBFileSpec diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index e3743e5ab511..e17f258ab0ae 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -575,18 +575,18 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); SBBreakpoint sb_bp; - if (m_opaque_sp.get() && symbol_name && symbol_name[0]) + if (m_opaque_sp.get()) { Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex()); if (module_name && module_name[0]) { FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false); + *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false); } else { - *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false); + *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false); } } @@ -599,6 +599,34 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na return sb_bp; } +lldb::SBBreakpoint +SBTarget::BreakpointCreateByName (const char *symbol_name, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBBreakpoint sb_bp; + if (m_opaque_sp.get() && symbol_name && symbol_name[0]) + { + Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex()); + *sb_bp = m_opaque_sp->CreateBreakpoint (module_list.get(), + comp_unit_list.get(), + symbol_name, + eFunctionNameTypeFull | eFunctionNameTypeBase, + false); + } + + if (log) + { + log->Printf ("SBTarget(%p)::BreakpointCreateByName (symbol=\"%s\") => SBBreakpoint(%p)", + m_opaque_sp.get(), symbol_name, sb_bp.get()); + } + + return sb_bp; +} + + SBBreakpoint SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *module_name) { @@ -615,11 +643,11 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, regexp, false); + *sb_bp = m_opaque_sp->CreateFuncRegexBreakpoint (&module_spec_list, NULL, regexp, false); } else { - *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, regexp, false); + *sb_bp = m_opaque_sp->CreateFuncRegexBreakpoint (NULL, NULL, regexp, false); } } @@ -632,7 +660,30 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo return sb_bp; } +lldb::SBBreakpoint +SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, + const SBFileSpecList &module_list, + const SBFileSpecList &comp_unit_list) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + SBBreakpoint sb_bp; + if (m_opaque_sp.get() && symbol_name_regex && symbol_name_regex[0]) + { + Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex()); + RegularExpression regexp(symbol_name_regex); + + *sb_bp = m_opaque_sp->CreateFuncRegexBreakpoint (module_list.get(), comp_unit_list.get(), regexp, false); + } + + if (log) + { + log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (symbol_regex=\"%s\") => SBBreakpoint(%p)", + m_opaque_sp.get(), symbol_name_regex, sb_bp.get()); + } + + return sb_bp; +} SBBreakpoint SBTarget::BreakpointCreateByAddress (addr_t address) @@ -664,17 +715,19 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S { Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex()); RegularExpression regexp(source_regex); + FileSpecList source_file_spec_list; + source_file_spec_list.Append (source_file.ref()); if (module_name && module_name[0]) { FileSpecList module_spec_list; module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, source_file.ref(), regexp, false); + *sb_bp = m_opaque_sp->CreateSourceRegexBreakpoint (&module_spec_list, &source_file_spec_list, regexp, false); } else { - *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, source_file.ref(), regexp, false); + *sb_bp = m_opaque_sp->CreateSourceRegexBreakpoint (NULL, &source_file_spec_list, regexp, false); } } @@ -689,6 +742,29 @@ SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::S return sb_bp; } +lldb::SBBreakpoint +SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, + const SBFileSpecList &module_list, + const lldb::SBFileSpecList &source_file_list) +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBBreakpoint sb_bp; + if (m_opaque_sp.get() && source_regex && source_regex[0]) + { + Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex()); + RegularExpression regexp(source_regex); + *sb_bp = m_opaque_sp->CreateSourceRegexBreakpoint (module_list.get(), source_file_list.get(), regexp, false); + } + + if (log) + { + log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\") => SBBreakpoint(%p)", + m_opaque_sp.get(), source_regex, sb_bp.get()); + } + + return sb_bp; +} SBBreakpoint SBTarget::FindBreakpointByID (break_id_t bp_id) diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp index 238c3709354b..e4b596af55e6 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -29,11 +29,9 @@ using namespace lldb_private; BreakpointResolverFileRegex::BreakpointResolverFileRegex ( Breakpoint *bkpt, - const FileSpec &file_spec, RegularExpression ®ex ) : BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver), - m_file_spec (file_spec), m_regex (regex) { } @@ -60,62 +58,58 @@ BreakpointResolverFileRegex::SearchCallback CompileUnit *cu = context.comp_unit; FileSpec cu_file_spec = *(static_cast(cu)); - if (cu_file_spec == m_file_spec - || (!m_file_spec.GetDirectory() && cu_file_spec.GetFilename() == m_file_spec.GetFilename())) + std::vector line_matches; + context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); + uint32_t num_matches = line_matches.size(); + for (int i = 0; i < num_matches; i++) { - std::vector line_matches; - context.target_sp->GetSourceManager().FindLinesMatchingRegex(cu_file_spec, m_regex, 1, UINT32_MAX, line_matches); - uint32_t num_matches = line_matches.size(); - for (int i = 0; i < num_matches; i++) + uint32_t start_idx = 0; + bool exact = false; + while (1) { - uint32_t start_idx = 0; - while (1) - { - LineEntry line_entry; + LineEntry line_entry; + + // Cycle through all the line entries that might match this one: + start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, exact, &line_entry); + if (start_idx == UINT32_MAX) + break; + exact = true; + start_idx++; - // Cycle through all the line entries that might match this one: - start_idx = cu->FindLineEntry (start_idx, line_matches[i], NULL, &line_entry); - if (start_idx == UINT32_MAX) - break; - start_idx++; - - Address line_start = line_entry.range.GetBaseAddress(); - if (line_start.IsValid()) + Address line_start = line_entry.range.GetBaseAddress(); + if (line_start.IsValid()) + { + if (filter.AddressPasses(line_start)) { - if (filter.AddressPasses(line_start)) + BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); + if (log && bp_loc_sp && !m_breakpoint->IsInternal()) { - BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); - if (log && bp_loc_sp && !m_breakpoint->IsInternal()) - { - StreamString s; - bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); - log->Printf ("Added location: %s\n", s.GetData()); - } - } - else if (log) - { - log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n", - line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString(""), - line_matches[i]); + StreamString s; + bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); + log->Printf ("Added location: %s\n", s.GetData()); } } - else + else if (log) { - if (log) - log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n", - line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString(""), - line_matches[i]); + log->Printf ("Breakpoint at file address 0x%llx for %s:%d didn't pass filter.\n", + line_start.GetFileAddress(), + cu_file_spec.GetFilename().AsCString(""), + line_matches[i]); } - } + else + { + if (log) + log->Printf ("error: Unable to set breakpoint at file address 0x%llx for %s:%d\n", + line_start.GetFileAddress(), + cu_file_spec.GetFilename().AsCString(""), + line_matches[i]); + } + } - assert (m_breakpoint != NULL); - LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - - } + assert (m_breakpoint != NULL); + return Searcher::eCallbackReturnContinue; } @@ -128,7 +122,7 @@ BreakpointResolverFileRegex::GetDepth() void BreakpointResolverFileRegex::GetDescription (Stream *s) { - s->Printf ("file ='%s', regular expression = \"%s\"", m_file_spec.GetFilename().AsCString(), m_regex.GetText()); + s->Printf ("source regex = \"%s\"", m_regex.GetText()); } void diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp index 141a15bef7df..42889091a979 100644 --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -161,16 +161,22 @@ BreakpointResolverName::SearchCallback const bool include_symbols = false; const bool append = false; + bool filter_by_cu = (filter.GetFilterRequiredItems() & eSymbolContextCompUnit) != 0; + switch (m_match_type) { case Breakpoint::Exact: if (context.module_sp) { - if (context.module_sp->FindFunctions (m_func_name, + uint32_t num_functions = context.module_sp->FindFunctions (m_func_name, m_func_name_type_mask, include_symbols, append, - func_list) == 0) + func_list); + // If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain + // symbols, since all the ones from a set compilation unit will have been found above already. + + if (num_functions == 0 && !filter_by_cu) { if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull)) context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list); @@ -180,7 +186,8 @@ BreakpointResolverName::SearchCallback case Breakpoint::Regexp: if (context.module_sp) { - context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); + if (!filter_by_cu) + context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, eSymbolTypeCode, sym_list); context.module_sp->FindFunctions (m_regex, include_symbols, append, @@ -192,7 +199,26 @@ BreakpointResolverName::SearchCallback log->Warning ("glob is not supported yet."); break; } - + + // If the filter specifies a Compilation Unit, remove the ones that don't pass at this point. + if (filter_by_cu) + { + uint32_t num_functions = func_list.GetSize(); + + for (size_t idx = 0; idx < num_functions; idx++) + { + SymbolContext sc; + func_list.GetContextAtIndex(idx, sc); + if (!sc.comp_unit || !filter.CompUnitPasses(*sc.comp_unit)) + { + func_list.RemoveContextAtIndex(idx); + num_functions--; + idx--; + } + } + } + + if (!m_basename_filter.empty()) { // Filter out any matches whose names don't contain the basename filter diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 11e0fad2c38c..ffff9f63c8f5 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -49,7 +49,7 @@ AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel leve CommandObjectBreakpointSet::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : Options (interpreter), - m_filename (), + m_filenames (), m_line_num (0), m_column (0), m_check_inlines (true), @@ -71,6 +71,8 @@ CommandObjectBreakpointSet::CommandOptions::~CommandOptions () { } +#define LLDB_OPT_FILE (LLDB_OPT_SET_ALL & ~(LLDB_OPT_SET_2)) + OptionDefinition CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { @@ -92,11 +94,11 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."}, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_9, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, - "Set the breakpoint by source location in this particular file."}, + { LLDB_OPT_FILE, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + "Specifies the source file in which to set this breakpoint."}, { LLDB_OPT_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, - "Set the breakpoint by source location at this particular line."}, + "Specifies the line number on which to set this breakpoint."}, // Comment out this option for the moment, as we don't actually use it, but will in the future. // This way users won't see it, but the infrastructure is left in place. @@ -160,7 +162,7 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx, break; case 'f': - m_filename.assign (option_arg); + m_filenames.AppendIfUnique (FileSpec(option_arg, false)); break; case 'l': @@ -202,7 +204,7 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx, case 's': { - m_modules.push_back (std::string (option_arg)); + m_modules.AppendIfUnique (FileSpec (option_arg, false)); break; } case 'i': @@ -244,14 +246,14 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx, void CommandObjectBreakpointSet::CommandOptions::OptionParsingStarting () { - m_filename.clear(); + m_filenames.Clear(); m_line_num = 0; m_column = 0; m_func_name.clear(); m_func_name_type_mask = 0; m_func_regexp.clear(); m_load_addr = LLDB_INVALID_ADDRESS; - m_modules.clear(); + m_modules.Clear(); m_ignore_count = 0; m_thread_id = LLDB_INVALID_THREAD_ID; m_thread_index = UINT32_MAX; @@ -284,48 +286,41 @@ CommandObjectBreakpointSet::GetOptions () } bool -CommandObjectBreakpointSet::ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result) +CommandObjectBreakpointSet::GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result) { - if (m_options.m_filename.empty()) + uint32_t default_line; + // First use the Source Manager's default file. + // Then use the current stack frame's file. + if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { - uint32_t default_line; - // First use the Source Manager's default file. - // Then use the current stack frame's file. - if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) + StackFrame *cur_frame = m_interpreter.GetExecutionContext().GetFramePtr(); + if (cur_frame == NULL) { - StackFrame *cur_frame = m_interpreter.GetExecutionContext().GetFramePtr(); - if (cur_frame == NULL) + result.AppendError ("No selected frame to use to find the default file."); + result.SetStatus (eReturnStatusFailed); + return false; + } + else if (!cur_frame->HasDebugInformation()) + { + result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info."); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + { + const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry); + if (sc.line_entry.file) { - result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame."); - result.SetStatus (eReturnStatusFailed); - return false; - } - else if (!cur_frame->HasDebugInformation()) - { - result.AppendError ("Attempting to set breakpoint by line number alone but selected frame has no debug info."); - result.SetStatus (eReturnStatusFailed); - return false; + file = sc.line_entry.file; } else { - const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry); - if (sc.line_entry.file) - { - file = sc.line_entry.file; - } - else - { - result.AppendError ("Attempting to set breakpoint by line number alone but can't find the file for the selected frame."); - result.SetStatus (eReturnStatusFailed); - return false; - } + result.AppendError ("Can't find the file for the selected frame to use as the default file."); + result.SetStatus (eReturnStatusFailed); + return false; } } } - else - { - file.SetFile(m_options.m_filename.c_str(), false); - } return true; } @@ -367,33 +362,36 @@ CommandObjectBreakpointSet::Execute Breakpoint *bp = NULL; FileSpec module_spec; bool use_module = false; - int num_modules = m_options.m_modules.size(); - - FileSpecList module_spec_list; - FileSpecList *module_spec_list_ptr = NULL; + int num_modules = m_options.m_modules.GetSize(); if ((num_modules > 0) && (break_type != eSetTypeAddress)) use_module = true; - if (use_module) - { - module_spec_list_ptr = &module_spec_list; - for (int i = 0; i < num_modules; ++i) - { - module_spec.SetFile(m_options.m_modules[i].c_str(), false); - module_spec_list.AppendIfUnique (module_spec); - } - } - switch (break_type) { case eSetTypeFileAndLine: // Breakpoint by source position { FileSpec file; - if (!ChooseFile (target, file, result)) - break; + uint32_t num_files = m_options.m_filenames.GetSize(); + if (num_files == 0) + { + if (!GetDefaultFile (target, file, result)) + { + result.AppendError("No file supplied and no default file available."); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + else if (num_files > 1) + { + result.AppendError("Only one file at a time is allowed for file and line breakpoints."); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + file = m_options.m_filenames.GetFileSpecAtIndex(0); - bp = target->CreateBreakpoint (module_spec_list_ptr, + bp = target->CreateBreakpoint (&(m_options.m_modules), file, m_options.m_line_num, m_options.m_check_inlines).get(); @@ -410,8 +408,9 @@ CommandObjectBreakpointSet::Execute if (name_type_mask == 0) name_type_mask = eFunctionNameTypeAuto; - - bp = target->CreateBreakpoint (module_spec_list_ptr, + + bp = target->CreateBreakpoint (&(m_options.m_modules), + &(m_options.m_filenames), m_options.m_func_name.c_str(), name_type_mask, Breakpoint::Exact).get(); @@ -430,15 +429,29 @@ CommandObjectBreakpointSet::Execute result.SetStatus (eReturnStatusFailed); return false; } - bp = target->CreateBreakpoint (module_spec_list_ptr, regexp).get(); + + bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp).get(); } break; case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. { - FileSpec file; - if (!ChooseFile (target, file, result)) - break; - + int num_files = m_options.m_filenames.GetSize(); + + if (num_files == 0) + { + FileSpec file; + if (!GetDefaultFile (target, file, result)) + { + result.AppendError ("No files provided and could not find default file."); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + { + m_options.m_filenames.Append (file); + } + } + RegularExpression regexp(m_options.m_source_text_regexp.c_str()); if (!regexp.IsValid()) { @@ -449,7 +462,7 @@ CommandObjectBreakpointSet::Execute result.SetStatus (eReturnStatusFailed); return false; } - bp = target->CreateBreakpoint (module_spec_list_ptr, file, regexp).get(); + bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), &(m_options.m_filenames), regexp).get(); } break; default: diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index 9df14dafad4d..b032319d167f 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.h +++ b/lldb/source/Commands/CommandObjectBreakpoint.h @@ -97,7 +97,7 @@ public: // Instance variables to hold the values for command options. - std::string m_filename; + FileSpecList m_filenames; uint32_t m_line_num; uint32_t m_column; bool m_check_inlines; @@ -105,7 +105,7 @@ public: uint32_t m_func_name_type_mask; std::string m_func_regexp; std::string m_source_text_regexp; - STLStringArray m_modules; + FileSpecList m_modules; lldb::addr_t m_load_addr; uint32_t m_ignore_count; lldb::tid_t m_thread_id; @@ -117,7 +117,7 @@ public: private: bool - ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result); + GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result); CommandOptions m_options; }; diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 68de8724eb68..8e4ae8d469ec 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -999,7 +999,8 @@ public: while (index_ptr <= end_ptr) { LineEntry line_entry; - index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, &line_entry); + const bool exact = false; + index_ptr = sc.comp_unit->FindLineEntry(index_ptr, line_number, sc.comp_unit, exact, &line_entry); if (index_ptr == UINT32_MAX) break; diff --git a/lldb/source/Core/FileLineResolver.cpp b/lldb/source/Core/FileLineResolver.cpp index 9f5f3150a3d1..8d68df2929b8 100644 --- a/lldb/source/Core/FileLineResolver.cpp +++ b/lldb/source/Core/FileLineResolver.cpp @@ -52,7 +52,7 @@ FileLineResolver::SearchCallback if (m_inlines || m_file_spec.Compare(*cu, m_file_spec, m_file_spec.GetDirectory())) { uint32_t start_file_idx = 0; - uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec); + uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false); if (file_idx != UINT32_MAX) { LineTable *line_table = cu->GetLineTable(); @@ -67,7 +67,7 @@ FileLineResolver::SearchCallback line_table->FineLineEntriesForFileIndex (file_idx, append, m_sc_list); // Get the next file index in case we have multiple file // entries for the same file - file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, m_file_spec); + file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, m_file_spec, false); } } else diff --git a/lldb/source/Core/FileSpecList.cpp b/lldb/source/Core/FileSpecList.cpp index 3ad4c6b7923c..ba2e95ec1bbb 100644 --- a/lldb/source/Core/FileSpecList.cpp +++ b/lldb/source/Core/FileSpecList.cpp @@ -107,7 +107,7 @@ FileSpecList::Dump(Stream *s, const char *separator_cstr) const // it is found, else UINT32_MAX is returned. //------------------------------------------------------------------ uint32_t -FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec) const +FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec, bool full) const { const uint32_t num_files = m_files.size(); uint32_t idx; @@ -125,7 +125,7 @@ FileSpecList::FindFileIndex (uint32_t start_idx, const FileSpec &file_spec) cons } else { - if (m_files[idx] == file_spec) + if (FileSpec::Equal (m_files[idx], file_spec, full)) return idx; } } diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp index 835072ad3efe..1fdbefe8e595 100644 --- a/lldb/source/Core/SearchFilter.cpp +++ b/lldb/source/Core/SearchFilter.cpp @@ -110,6 +110,12 @@ SearchFilter::CompUnitPasses (CompileUnit &compUnit) return true; } +uint32_t +SearchFilter::GetFilterRequiredItems() +{ + return (lldb::SymbolContextItem) 0; +} + void SearchFilter::GetDescription (Stream *s) { @@ -427,6 +433,12 @@ SearchFilterByModule::GetDescription (Stream *s) } } +uint32_t +SearchFilterByModule::GetFilterRequiredItems() +{ + return eSymbolContextModule; +} + void SearchFilterByModule::Dump (Stream *s) const { @@ -478,7 +490,10 @@ SearchFilterByModuleList::~SearchFilterByModuleList() bool SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp) { - if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec()) != UINT32_MAX) + if (m_module_spec_list.GetSize() == 0) + return true; + + if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX) return true; else return false; @@ -487,7 +502,10 @@ SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp) bool SearchFilterByModuleList::ModulePasses (const FileSpec &spec) { - if (m_module_spec_list.FindFileIndex(0, spec) != UINT32_MAX) + if (m_module_spec_list.GetSize() == 0) + return true; + + if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX) return true; else return false; @@ -503,7 +521,7 @@ SearchFilterByModuleList::SymbolContextPasses if (!(scope & eSymbolContextModule)) return false; - if (context.module_sp && m_module_spec_list.FindFileIndex(0, context.module_sp->GetFileSpec()) != UINT32_MAX) + if (context.module_sp && m_module_spec_list.FindFileIndex(0, context.module_sp->GetFileSpec(), true) != UINT32_MAX) return true; else return false; @@ -551,7 +569,7 @@ SearchFilterByModuleList::Search (Searcher &searcher) for (size_t i = 0; i < num_modules; i++) { Module* module = m_target_sp->GetImages().GetModulePointerAtIndex(i); - if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec()) != UINT32_MAX) + if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) != UINT32_MAX) { SymbolContext matchingContext(m_target_sp, ModuleSP(module)); Searcher::CallbackReturn shouldContinue; @@ -602,8 +620,204 @@ SearchFilterByModuleList::GetDescription (Stream *s) } } +uint32_t +SearchFilterByModuleList::GetFilterRequiredItems() +{ + return eSymbolContextModule; +} + void SearchFilterByModuleList::Dump (Stream *s) const { } + +//---------------------------------------------------------------------- +// SearchFilterByModuleListAndCU: +// Selects a shared library matching a given file spec +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// SearchFilterByModuleListAndCU constructors +//---------------------------------------------------------------------- + +SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU (lldb::TargetSP &target_sp, + const FileSpecList &module_list, + const FileSpecList &cu_list) : + SearchFilterByModuleList (target_sp, module_list), + m_cu_spec_list (cu_list) +{ +} + + +//---------------------------------------------------------------------- +// SearchFilterByModuleListAndCU copy constructor +//---------------------------------------------------------------------- +SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(const SearchFilterByModuleListAndCU& rhs) : + SearchFilterByModuleList (rhs), + m_cu_spec_list (rhs.m_cu_spec_list) +{ +} + +//---------------------------------------------------------------------- +// SearchFilterByModuleListAndCU assignment operator +//---------------------------------------------------------------------- +const SearchFilterByModuleListAndCU& +SearchFilterByModuleListAndCU::operator=(const SearchFilterByModuleListAndCU& rhs) +{ + if (&rhs != this) + { + m_target_sp = rhs.m_target_sp; + m_module_spec_list = rhs.m_module_spec_list; + m_cu_spec_list = rhs.m_cu_spec_list; + } + return *this; +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() +{ +} + +bool +SearchFilterByModuleListAndCU::SymbolContextPasses +( + const SymbolContext &context, + lldb::SymbolContextItem scope + ) +{ + if (!SearchFilterByModuleList::SymbolContextPasses(context, scope)) + return false; + if (!(scope & eSymbolContextCompUnit)) + return false; + if (context.comp_unit && m_cu_spec_list.FindFileIndex(0, static_cast(context.comp_unit), false) == UINT32_MAX) + return false; + return true; +} + +bool +SearchFilterByModuleListAndCU::AddressPasses (Address &address) +{ + // FIXME: Not yet implemented + return true; +} + + +bool +SearchFilterByModuleListAndCU::CompUnitPasses (FileSpec &fileSpec) +{ + return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX; +} + +bool +SearchFilterByModuleListAndCU::CompUnitPasses (CompileUnit &compUnit) +{ + return m_cu_spec_list.FindFileIndex(0, static_cast(compUnit), false) != UINT32_MAX; +} + +void +SearchFilterByModuleListAndCU::Search (Searcher &searcher) +{ + if (!m_target_sp) + return; + + if (searcher.GetDepth() == Searcher::eDepthTarget) + { + SymbolContext empty_sc; + empty_sc.target_sp = m_target_sp; + searcher.SearchCallback (*this, empty_sc, NULL, false); + } + + // If the module file spec is a full path, then we can just find the one + // filespec that passes. Otherwise, we need to go through all modules and + // find the ones that match the file name. + + ModuleList matching_modules; + const size_t num_modules = m_target_sp->GetImages().GetSize (); + bool no_modules_in_filter = m_module_spec_list.GetSize() == 0; + for (size_t i = 0; i < num_modules; i++) + { + lldb::ModuleSP module_sp = m_target_sp->GetImages().GetModuleAtIndex(i); + if (no_modules_in_filter || m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX) + { + SymbolContext matchingContext(m_target_sp, module_sp); + Searcher::CallbackReturn shouldContinue; + + if (searcher.GetDepth() == Searcher::eDepthModule) + { + shouldContinue = DoModuleIteration(matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; + } + else + { + const size_t num_cu = module_sp->GetNumCompileUnits(); + for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) + { + CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx); + matchingContext.comp_unit = cu_sp.get(); + if (m_cu_spec_list.FindFileIndex(0, static_cast(matchingContext.comp_unit), false) != UINT32_MAX) + { + shouldContinue = DoCUIteration(module_sp, matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; + } + } + } + } + } +} + +void +SearchFilterByModuleListAndCU::GetDescription (Stream *s) +{ + uint32_t num_modules = m_module_spec_list.GetSize(); + if (num_modules == 1) + { + s->Printf (", module = "); + if (s->GetVerbose()) + { + char buffer[2048]; + m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); + s->PutCString(buffer); + } + else + { + s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("")); + } + } + else if (num_modules > 0) + { + s->Printf (", modules(%d) = ", num_modules); + for (uint32_t i = 0; i < num_modules; i++) + { + if (s->GetVerbose()) + { + char buffer[2048]; + m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); + s->PutCString(buffer); + } + else + { + s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("")); + } + if (i != num_modules - 1) + s->PutCString (", "); + } + } +} + +uint32_t +SearchFilterByModuleListAndCU::GetFilterRequiredItems() +{ + return eSymbolContextModule | eSymbolContextCompUnit; +} + +void +SearchFilterByModuleListAndCU::Dump (Stream *s) const +{ + +} + diff --git a/lldb/source/Host/common/FileSpec.cpp b/lldb/source/Host/common/FileSpec.cpp index 8f398e05adaa..5e034db6571e 100644 --- a/lldb/source/Host/common/FileSpec.cpp +++ b/lldb/source/Host/common/FileSpec.cpp @@ -506,10 +506,10 @@ FileSpec::Compare(const FileSpec& a, const FileSpec& b, bool full) bool FileSpec::Equal (const FileSpec& a, const FileSpec& b, bool full) { - if (full) - return a == b; - else + if (!full && (a.GetDirectory().IsEmpty() || b.GetDirectory().IsEmpty())) return a.m_filename == b.m_filename; + else + return a == b; } diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 55e0af68cb8a..a972a3dc4bef 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -988,6 +988,7 @@ DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded () FileSpecList module_spec_list; module_spec_list.Append (m_kernel.module_sp->GetFileSpec()); Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list, + NULL, "OSKextLoadedKextSummariesUpdated", eFunctionNameTypeFull, internal_bp, diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 90b17d1c084e..27f80cb3cb55 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -262,6 +262,7 @@ ItaniumABILanguageRuntime::SetExceptionBreakpoints () if (!m_cxx_exception_bp_sp) m_cxx_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL, + NULL, "__cxa_throw", eFunctionNameTypeBase, true); @@ -270,6 +271,7 @@ ItaniumABILanguageRuntime::SetExceptionBreakpoints () if (!m_cxx_exception_alloc_bp_sp) m_cxx_exception_alloc_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL, + NULL, "__cxa_allocate", eFunctionNameTypeBase, true); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index ae5cf922c394..6af8f2294d0f 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -114,6 +114,7 @@ AppleObjCRuntimeV1::SetExceptionBreakpoints () if (!m_objc_exception_bp_sp) { m_objc_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL, + NULL, "objc_exception_throw", eFunctionNameTypeBase, true); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index ef62462e7ad0..28c6f4b02284 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -480,6 +480,7 @@ AppleObjCRuntimeV2::SetExceptionBreakpoints () if (!m_objc_exception_bp_sp) { m_objc_exception_bp_sp = m_process->GetTarget().CreateBreakpoint (NULL, + NULL, "__cxa_throw", eFunctionNameTypeBase, true); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 8f09fcf9d8c5..3d263838d285 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -2534,7 +2534,7 @@ ProcessGDBRemote::StartNoticingNewThreads() { for (int i = 0; bp_names[i] != NULL; i++) { - Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, bp_names[i], eFunctionNameTypeFull, true).get(); + Breakpoint *breakpoint = m_target.CreateBreakpoint (NULL, NULL, bp_names[i], eFunctionNameTypeFull, true).get(); if (breakpoint) { if (log) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 9a2c10e26f5b..c10ffaad16a5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1804,7 +1804,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, // find it in the support files, we are done. if (check_inlines) { - file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec); + file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true); if (file_idx == UINT32_MAX) continue; } @@ -1818,7 +1818,7 @@ SymbolFileDWARF::ResolveSymbolContext(const FileSpec& file_spec, uint32_t line, // We will have already looked up the file index if // we are searching for inline entries. if (!check_inlines) - file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec); + file_idx = sc.comp_unit->GetSupportFiles().FindFileIndex (1, file_spec, true); if (file_idx != UINT32_MAX) { diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index d50ad99dc5eb..ec383eb59512 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -253,13 +253,13 @@ CompileUnit::GetVariableList(bool can_create) } uint32_t -CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, LineEntry *line_entry_ptr) +CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* file_spec_ptr, bool exact, LineEntry *line_entry_ptr) { uint32_t file_idx = 0; if (file_spec_ptr) { - file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr); + file_idx = GetSupportFiles().FindFileIndex (1, *file_spec_ptr, true); if (file_idx == UINT32_MAX) return UINT32_MAX; } @@ -269,13 +269,14 @@ CompileUnit::FindLineEntry (uint32_t start_idx, uint32_t line, const FileSpec* f // Unit that is in the support files (the one at 0 was artifically added.) // So prefer the one further on in the support files if it exists... FileSpecList &support_files = GetSupportFiles(); - file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0)); + const bool full = true; + file_idx = support_files.FindFileIndex (1, support_files.GetFileSpecAtIndex(0), full); if (file_idx == UINT32_MAX) file_idx = 0; } LineTable *line_table = GetLineTable(); if (line_table) - return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, true, line_entry_ptr); + return line_table->FindLineEntryIndexByFileIndex (start_idx, file_idx, line, exact, line_entry_ptr); return UINT32_MAX; } @@ -304,11 +305,11 @@ CompileUnit::ResolveSymbolContext if (file_spec_matches_cu_file_spec == false && check_inlines == false) return 0; - uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec); + uint32_t file_idx = GetSupportFiles().FindFileIndex (1, file_spec, true); while (file_idx != UINT32_MAX) { file_indexes.push_back (file_idx); - file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec); + file_idx = GetSupportFiles().FindFileIndex (file_idx + 1, file_spec, true); } const size_t num_file_indexes = file_indexes.size(); diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 19bd7f9a4eed..ebaab10b0ed6 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -207,13 +207,13 @@ Target::GetBreakpointByID (break_id_t break_id) } BreakpointSP -Target::CreateBreakpoint (const FileSpecList *containingModules, - const FileSpec &file, +Target::CreateSourceRegexBreakpoint (const FileSpecList *containingModules, + const FileSpecList *source_file_spec_list, RegularExpression &source_regex, bool internal) { - SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); - BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, file, source_regex)); + SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, source_file_spec_list)); + BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, source_regex)); return CreateBreakpoint (filter_sp, resolver_sp, internal); } @@ -255,7 +255,8 @@ Target::CreateBreakpoint (Address &addr, bool internal) } BreakpointSP -Target::CreateBreakpoint (const FileSpecList *containingModules, +Target::CreateBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, const char *func_name, uint32_t func_name_type_mask, bool internal, @@ -264,7 +265,7 @@ Target::CreateBreakpoint (const FileSpecList *containingModules, BreakpointSP bp_sp; if (func_name) { - SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); + SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles)); BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name, @@ -317,13 +318,36 @@ Target::GetSearchFilterForModuleList (const FileSpecList *containingModules) return filter_sp; } +SearchFilterSP +Target::GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, const FileSpecList *containingSourceFiles) +{ + if (containingSourceFiles == NULL || containingSourceFiles->GetSize() == 0) + return GetSearchFilterForModuleList(containingModules); + + SearchFilterSP filter_sp; + lldb::TargetSP target_sp = this->GetSP(); + if (containingModules == NULL) + { + // We could make a special "CU List only SearchFilter". Better yet was if these could be composable, + // but that will take a little reworking. + + filter_sp.reset (new SearchFilterByModuleListAndCU (target_sp, FileSpecList(), *containingSourceFiles)); + } + else + { + filter_sp.reset (new SearchFilterByModuleListAndCU (target_sp, *containingModules, *containingSourceFiles)); + } + return filter_sp; +} + BreakpointSP -Target::CreateBreakpoint (const FileSpecList *containingModules, +Target::CreateFuncRegexBreakpoint (const FileSpecList *containingModules, + const FileSpecList *containingSourceFiles, RegularExpression &func_regex, bool internal, LazyBool skip_prologue) { - SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); + SearchFilterSP filter_sp(GetSearchFilterForModuleAndCUList (containingModules, containingSourceFiles)); BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex, skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue)); diff --git a/lldb/test/functionalities/breakpoint/breakpoint_command/Makefile b/lldb/test/functionalities/breakpoint/breakpoint_command/Makefile index b09a579159d4..a6376f9b165d 100644 --- a/lldb/test/functionalities/breakpoint/breakpoint_command/Makefile +++ b/lldb/test/functionalities/breakpoint/breakpoint_command/Makefile @@ -1,5 +1,5 @@ LEVEL = ../../../make -C_SOURCES := main.c +C_SOURCES := main.c a.c b.c include $(LEVEL)/Makefile.rules diff --git a/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py b/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py index b96d20d37df9..616464e21040 100644 --- a/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py +++ b/lldb/test/functionalities/breakpoint/breakpoint_command/TestBreakpointCommand.py @@ -77,6 +77,25 @@ class BreakpointCommandTestCase(TestBase): "print >> here", "here.close()"]) + # Next lets try some other breakpoint kinds. First break with a regular expression + # and then specify only one file. The first time we should get two locations, + # the second time only one: + self.expect ("break set -r ._MyFunction", + patterns = ["Breakpoint created: [0-9]+: regex = '\._MyFunction', locations = 2"]) + + self.expect ("break set -r ._MyFunction -f a.c", + patterns = ["Breakpoint created: [0-9]+: regex = '\._MyFunction', locations = 1"]) + + self.expect ("break set -r ._MyFunction -f a.c -f b.c", + patterns = ["Breakpoint created: [0-9]+: regex = '\._MyFunction', locations = 2"]) + + # Now try a source regex breakpoint: + self.expect ("break set -p \"is about to return [12]0\" -f a.c -f b.c", + patterns = ["Breakpoint created: [0-9]+: source regex = \"is about to return \[12\]0\", locations = 2"]) + + self.expect ("break set -p \"is about to return [12]0\" -f a.c", + patterns = ["Breakpoint created: [0-9]+: source regex = \"is about to return \[12\]0\", locations = 1"]) + # Run the program. Remove 'output.txt' if it exists. if os.path.exists('output.txt'): os.remove('output.txt') diff --git a/lldb/test/functionalities/breakpoint/breakpoint_command/a.c b/lldb/test/functionalities/breakpoint/breakpoint_command/a.c new file mode 100644 index 000000000000..870e4a6ab166 --- /dev/null +++ b/lldb/test/functionalities/breakpoint/breakpoint_command/a.c @@ -0,0 +1,9 @@ +#include + +int +a_MyFunction () +{ + // Set a breakpoint here. + printf ("a is about to return 10.\n"); + return 10; +} diff --git a/lldb/test/functionalities/breakpoint/breakpoint_command/b.c b/lldb/test/functionalities/breakpoint/breakpoint_command/b.c new file mode 100644 index 000000000000..02b78e7bd855 --- /dev/null +++ b/lldb/test/functionalities/breakpoint/breakpoint_command/b.c @@ -0,0 +1,9 @@ +#include + +int +b_MyFunction () +{ + // Set a breakpoint here. + printf ("b is about to return 20.\n"); + return 20; +}