diff options
32 files changed, 1155 insertions, 206 deletions
diff --git a/lldb/include/lldb/API/SBCommandInterpreter.h b/lldb/include/lldb/API/SBCommandInterpreter.h index c3bda082478..71a157de3a5 100644 --- a/lldb/include/lldb/API/SBCommandInterpreter.h +++ b/lldb/include/lldb/API/SBCommandInterpreter.h @@ -80,6 +80,9 @@ public: lldb::ReturnStatus HandleCommand (const char *command_line, lldb::SBCommandReturnObject &result, bool add_to_history = false); +#ifndef SWIG + // This interface is not useful in SWIG, since the cursor & last_char arguments are string pointers INTO current_line + // and you can't do that in a scripting language interface in general... int HandleCompletion (const char *current_line, const char *cursor, @@ -87,6 +90,13 @@ public: int match_start_point, int max_return_elements, lldb::SBStringList &matches); +#endif + int + HandleCompletion (const char *current_line, + uint32_t cursor_pos, + int match_start_point, + int max_return_elements, + lldb::SBStringList &matches); protected: diff --git a/lldb/include/lldb/API/SBFileSpec.h b/lldb/include/lldb/API/SBFileSpec.h index 9890d59fc33..e3a6ce2d424 100644 --- a/lldb/include/lldb/API/SBFileSpec.h +++ b/lldb/include/lldb/API/SBFileSpec.h @@ -59,6 +59,7 @@ public: private: friend class SBBlock; friend class SBCompileUnit; + friend class SBFileSpecList; friend class SBHostOS; friend class SBLineEntry; friend class SBModule; diff --git a/lldb/include/lldb/API/SBFileSpecList.h b/lldb/include/lldb/API/SBFileSpecList.h new file mode 100644 index 00000000000..720c07822b6 --- /dev/null +++ b/lldb/include/lldb/API/SBFileSpecList.h @@ -0,0 +1,76 @@ +//===-- SBFileSpecList.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SBFileSpecList_h_ +#define LLDB_SBFileSpecList_h_ + +#include "lldb/API/SBDefines.h" + +namespace lldb { + +class SBFileSpecList +{ +public: + SBFileSpecList (); + + SBFileSpecList (const lldb::SBFileSpecList &rhs); + + ~SBFileSpecList (); + +#ifndef SWIG + const SBFileSpecList & + operator = (const lldb::SBFileSpecList &rhs); +#endif + + uint32_t + GetSize () const; + + bool + GetDescription (SBStream &description) const; + + void + Append (const SBFileSpec &sb_file); + + bool + AppendIfUnique (const SBFileSpec &sb_file); + + void + Clear(); + + uint32_t + FindFileIndex (uint32_t idx, const SBFileSpec &sb_file); + + const SBFileSpec + GetFileSpecAtIndex (uint32_t idx) const; + +private: + +#ifndef SWIG + + const lldb_private::FileSpecList * + operator->() const; + + const lldb_private::FileSpecList * + get() const; + + const lldb_private::FileSpecList & + operator*() const; + + const lldb_private::FileSpecList & + ref() const; + +#endif + + std::auto_ptr <lldb_private::FileSpecList> m_opaque_ap; +}; + + +} // namespace lldb + +#endif // LLDB_SBFileSpecList_h_ diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 4349e21e5b0..3c95969bfb6 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -316,6 +316,9 @@ public: 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); lldb::SBBreakpoint BreakpointCreateByAddress (addr_t address); diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolver.h b/lldb/include/lldb/Breakpoint/BreakpointResolver.h index 0c74dae4d1a..b05b8c57299 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolver.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolver.h @@ -120,7 +120,8 @@ public: enum ResolverTy { FileLineResolver, // This is an instance of BreakpointResolverFileLine AddressResolver, // This is an instance of BreakpointResolverAddress - NameResolver // This is an instance of BreakpointResolverName + NameResolver, // This is an instance of BreakpointResolverName + FileRegexResolver }; //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h b/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h new file mode 100644 index 00000000000..22321677b59 --- /dev/null +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverFileRegex.h @@ -0,0 +1,70 @@ +//===-- BreakpointResolverFileRegex.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_BreakpointResolverFileRegex_h_ +#define liblldb_BreakpointResolverFileRegex_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointResolver.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class BreakpointResolverFileRegex BreakpointResolverFileRegex.h "lldb/Breakpoint/BreakpointResolverFileRegex.h" +/// @brief This class sets breakpoints by file and line. Optionally, it will look for inlined +/// instances of the file and line specification. +//---------------------------------------------------------------------- + +class BreakpointResolverFileRegex : + public BreakpointResolver +{ +public: + BreakpointResolverFileRegex (Breakpoint *bkpt, + const FileSpec &resolver, + RegularExpression ®ex); + + virtual + ~BreakpointResolverFileRegex (); + + virtual Searcher::CallbackReturn + SearchCallback (SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing); + + virtual Searcher::Depth + GetDepth (); + + virtual void + GetDescription (Stream *s); + + virtual void + Dump (Stream *s) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BreakpointResolverFileRegex *) { return true; } + static inline bool classof(const BreakpointResolver *V) { + return V->getResolverID() == BreakpointResolver::FileRegexResolver; + } + +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. + +private: + DISALLOW_COPY_AND_ASSIGN(BreakpointResolverFileRegex); +}; + +} // namespace lldb_private + +#endif // liblldb_BreakpointResolverFileRegex_h_ diff --git a/lldb/include/lldb/Core/RegularExpression.h b/lldb/include/lldb/Core/RegularExpression.h index b73a9d65f83..4d269a160a8 100644 --- a/lldb/include/lldb/Core/RegularExpression.h +++ b/lldb/include/lldb/Core/RegularExpression.h @@ -52,7 +52,11 @@ public: /// Flags that are passed the the \c regcomp() function. //------------------------------------------------------------------ explicit - RegularExpression (const char* re, int flags = REG_EXTENDED); + RegularExpression (const char* re, int flags); + + // This one uses flags = REG_EXTENDED. + explicit + RegularExpression (const char* re); //------------------------------------------------------------------ /// Destructor. @@ -61,6 +65,10 @@ public: /// object will be freed. //------------------------------------------------------------------ ~RegularExpression (); + + RegularExpression (const RegularExpression &rhs); + + const RegularExpression & operator=(const RegularExpression &rhs); //------------------------------------------------------------------ /// Compile a regular expression. @@ -84,7 +92,10 @@ public: /// \b false otherwise. //------------------------------------------------------------------ bool - Compile (const char* re, int flags = REG_EXTENDED); + Compile (const char* re); + + bool + Compile (const char* re, int flags); //------------------------------------------------------------------ /// Executes a regular expression. @@ -138,6 +149,12 @@ public: //------------------------------------------------------------------ const char* GetText () const; + + int + GetCompileFlags () const + { + return m_compile_flags; + } //------------------------------------------------------------------ /// Test if valid. @@ -161,7 +178,9 @@ private: std::string m_re; ///< A copy of the original regular expression text int m_comp_err; ///< Error code for the regular expression compilation regex_t m_preg; ///< The compiled regular expression + int m_compile_flags; ///< Stores the flags from the last compile. mutable std::vector<regmatch_t> m_matches; ///< Where parenthesized subexpressions results are stored + }; } // namespace lldb_private diff --git a/lldb/include/lldb/Core/SearchFilter.h b/lldb/include/lldb/Core/SearchFilter.h index c651b40cbda..c359cb33aa7 100644 --- a/lldb/include/lldb/Core/SearchFilter.h +++ b/lldb/include/lldb/Core/SearchFilter.h @@ -321,6 +321,64 @@ private: FileSpec m_module_spec; }; +class SearchFilterByModuleList : + public SearchFilter +{ +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. + //------------------------------------------------------------------ + SearchFilterByModuleList (lldb::TargetSP &targetSP, + const FileSpecList &module_list); + + SearchFilterByModuleList (const SearchFilterByModuleList& rhs); + + virtual + ~SearchFilterByModuleList (); + + const SearchFilterByModuleList& + operator=(const SearchFilterByModuleList& rhs); + + virtual bool + ModulePasses (const lldb::ModuleSP &module_sp); + + virtual bool + ModulePasses (const FileSpec &spec); + + 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 void + Dump (Stream *s) const; + + virtual void + Search (Searcher &searcher); + +private: + FileSpecList m_module_spec_list; +}; + } // namespace lldb_private #endif // liblldb_SearchFilter_h_ diff --git a/lldb/include/lldb/Core/SourceManager.h b/lldb/include/lldb/Core/SourceManager.h index fd8a4ddb5c7..64f5743306c 100644 --- a/lldb/include/lldb/Core/SourceManager.h +++ b/lldb/include/lldb/Core/SourceManager.h @@ -40,7 +40,15 @@ public: uint32_t context_before, uint32_t context_after, Stream *s); + void + FindLinesMatchingRegex (RegularExpression& regex, + uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines); + bool + GetLine (uint32_t line_no, std::string &buffer); + uint32_t GetLineOffset (uint32_t line); @@ -151,6 +159,13 @@ public: return (m_last_file_sp.get() != NULL); } + void + FindLinesMatchingRegex (FileSpec &file_spec, + RegularExpression& regex, + uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines); + protected: FileSP diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 617285b152b..81b1ec99424 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -214,7 +214,7 @@ public: // This handles command line completion. You are given a pointer to the command string buffer, to the current cursor, // and to the end of the string (in case it is not NULL terminated). - // You also passed in an Args object to fill with the returns. + // You also passed in an StringList object to fill with the returns. // The first element of the array will be filled with the string that you would need to insert at // the cursor point to complete the cursor point to the longest common matching prefix. // If you want to limit the number of elements returned, set max_return_elements to the number of elements diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 0defa9dd310..c7696b8c514 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -244,12 +244,19 @@ public: // Use this to create a file and line breakpoint to a given module or all module it is NULL lldb::BreakpointSP - CreateBreakpoint (const FileSpec *containingModule, + CreateBreakpoint (const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal = false); + // Use this to create breakpoint that matches regex against the source lines in file: + lldb::BreakpointSP + CreateBreakpoint (const FileSpecList *containingModules, + const FileSpec &file, + RegularExpression &source_regex, + bool internal = false); + // Use this to create a breakpoint from a load address lldb::BreakpointSP CreateBreakpoint (lldb::addr_t load_addr, @@ -264,7 +271,7 @@ public: // When "skip_prologue is set to eLazyBoolCalculate, we use the current target // setting, else we use the values passed in lldb::BreakpointSP - CreateBreakpoint (const FileSpec *containingModule, + CreateBreakpoint (const FileSpecList *containingModules, RegularExpression &func_regexp, bool internal = false, LazyBool skip_prologue = eLazyBoolCalculate); @@ -273,7 +280,7 @@ public: // When "skip_prologue is set to eLazyBoolCalculate, we use the current target // setting, else we use the values passed in lldb::BreakpointSP - CreateBreakpoint (const FileSpec *containingModule, + CreateBreakpoint (const FileSpecList *containingModules, const char *func_name, uint32_t func_name_type_mask, bool internal = false, @@ -880,6 +887,9 @@ protected: lldb::SearchFilterSP GetSearchFilterForModule (const FileSpec *containingModule); + lldb::SearchFilterSP + GetSearchFilterForModuleList (const FileSpecList *containingModuleList); + static void ImageSearchPathsChanged (const PathMappingList &path_list, void *baton); diff --git a/lldb/include/lldb/lldb-defines.h b/lldb/include/lldb/lldb-defines.h index 5e089d54425..d9db639be44 100644 --- a/lldb/include/lldb/lldb-defines.h +++ b/lldb/include/lldb/lldb-defines.h @@ -101,6 +101,7 @@ #define LLDB_OPT_SET_6 (1 << 5) #define LLDB_OPT_SET_7 (1 << 6) #define LLDB_OPT_SET_8 (1 << 7) +#define LLDB_OPT_SET_9 (1 << 8) #if defined(__cplusplus) diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 0a57b329df5..28b0c4f893a 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -400,6 +400,8 @@ 49C8507C1384A786007DB519 /* ProcessDataAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49C850781384A0CA007DB519 /* ProcessDataAllocator.cpp */; }; 49D8FB3913B5598F00411094 /* ClangASTImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D8FB3513B558DE00411094 /* ClangASTImporter.cpp */; }; 4C74CB6312288704006A8171 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4C74CB6212288704006A8171 /* Carbon.framework */; }; + 4CAA56131422D96A001FFA01 /* BreakpointResolverFileRegex.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */; }; + 4CAA56151422D986001FFA01 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; }; 4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; }; 4CCA644D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA643D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp */; }; 4CCA645013B40B82003BDF98 /* AppleObjCRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */; }; @@ -408,6 +410,8 @@ 4CCA645613B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644813B40B82003BDF98 /* AppleObjCTrampolineHandler.cpp */; }; 4CCA645813B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644A13B40B82003BDF98 /* AppleThreadPlanStepThroughObjCTrampoline.cpp */; }; 4CD0BD0F134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */; }; + 4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */ = {isa = PBXBuildFile; fileRef = 4CF52AF41428291E0051E832 /* SBFileSpecList.h */; }; + 4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */; }; 94031A9E13CF486700DCFF3C /* InputReaderEZ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 94031A9D13CF486600DCFF3C /* InputReaderEZ.cpp */; }; 9415F61813B2C0EF00A52B36 /* FormatManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9415F61713B2C0EF00A52B36 /* FormatManager.cpp */; }; 9443B122140C18C40013457C /* SBData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9443B121140C18C10013457C /* SBData.cpp */; }; @@ -1159,6 +1163,8 @@ 4C98D3E1118FB98F00E575D0 /* RecordingMemoryManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RecordingMemoryManager.h; path = include/lldb/Expression/RecordingMemoryManager.h; sourceTree = "<group>"; }; 4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectApropos.cpp; path = source/Commands/CommandObjectApropos.cpp; sourceTree = "<group>"; }; 4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectApropos.h; path = source/Commands/CommandObjectApropos.h; sourceTree = "<group>"; }; + 4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BreakpointResolverFileRegex.h; path = include/lldb/Breakpoint/BreakpointResolverFileRegex.h; sourceTree = "<group>"; }; + 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BreakpointResolverFileRegex.cpp; path = source/Breakpoint/BreakpointResolverFileRegex.cpp; sourceTree = "<group>"; }; 4CABA9DC134A8BA700539BDD /* ValueObjectMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectMemory.h; path = include/lldb/Core/ValueObjectMemory.h; sourceTree = "<group>"; }; 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectMemory.cpp; path = source/Core/ValueObjectMemory.cpp; sourceTree = "<group>"; }; 4CAFCE001101216B00CA63DB /* ThreadPlanRunToAddress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanRunToAddress.h; path = include/lldb/Target/ThreadPlanRunToAddress.h; sourceTree = "<group>"; }; @@ -1186,6 +1192,8 @@ 4CD0BD0C134BFAB600CB44D4 /* ValueObjectDynamicValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectDynamicValue.h; path = include/lldb/Core/ValueObjectDynamicValue.h; sourceTree = "<group>"; }; 4CD0BD0E134BFADF00CB44D4 /* ValueObjectDynamicValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValueObjectDynamicValue.cpp; path = source/Core/ValueObjectDynamicValue.cpp; sourceTree = "<group>"; }; 4CEDAED311754F5E00E875A6 /* ThreadPlanStepUntil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanStepUntil.h; path = include/lldb/Target/ThreadPlanStepUntil.h; sourceTree = "<group>"; }; + 4CF52AF41428291E0051E832 /* SBFileSpecList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBFileSpecList.h; path = include/lldb/API/SBFileSpecList.h; sourceTree = "<group>"; }; + 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBFileSpecList.cpp; path = source/API/SBFileSpecList.cpp; sourceTree = "<group>"; }; 69A01E1B1236C5D400C660B5 /* Condition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Condition.cpp; sourceTree = "<group>"; }; 69A01E1C1236C5D400C660B5 /* Host.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Host.cpp; sourceTree = "<group>"; }; 69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; }; @@ -1685,6 +1693,8 @@ 9A9830FD1125FC5800A56CB0 /* SBEvent.cpp */, 26022531115F27FA00A601A2 /* SBFileSpec.h */, 26022532115F281400A601A2 /* SBFileSpec.cpp */, + 4CF52AF41428291E0051E832 /* SBFileSpecList.h */, + 4CF52AF7142829390051E832 /* SBFileSpecList.cpp */, 9A633FE8112DCE3C001A7E43 /* SBFrame.h */, 9A633FE7112DCE3C001A7E43 /* SBFrame.cpp */, 26DE205211618FAC00A093E2 /* SBFunction.h */, @@ -2176,6 +2186,8 @@ 26D0DD5310FE555900271C65 /* BreakpointResolverAddress.cpp */, 26D0DD5110FE554D00271C65 /* BreakpointResolverFileLine.h */, 26D0DD5410FE555900271C65 /* BreakpointResolverFileLine.cpp */, + 4CAA56121422D96A001FFA01 /* BreakpointResolverFileRegex.h */, + 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */, 26D0DD5210FE554D00271C65 /* BreakpointResolverName.h */, 26D0DD5510FE555900271C65 /* BreakpointResolverName.cpp */, 26BC7CF710F1B71400F91463 /* BreakpointSite.h */, @@ -2754,6 +2766,8 @@ 9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */, 26D265A2136B40EE002EEE45 /* SharingPtr.h in Headers */, 26D265BC136B4269002EEE45 /* lldb-public.h in Headers */, + 4CAA56131422D96A001FFA01 /* BreakpointResolverFileRegex.h in Headers */, + 4CF52AF51428291E0051E832 /* SBFileSpecList.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3037,6 +3051,8 @@ 26C72C961243229A0068DC16 /* SBStream.cpp in Sources */, 26B1FA1413380E61002886E2 /* LLDBWrapPython.cpp in Sources */, 9443B122140C18C40013457C /* SBData.cpp in Sources */, + 4CAA56151422D986001FFA01 /* BreakpointResolverFileRegex.cpp in Sources */, + 4CF52AF8142829390051E832 /* SBFileSpecList.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/scripts/Python/interface/SBCommandInterpreter.i b/lldb/scripts/Python/interface/SBCommandInterpreter.i index 81e515830ec..6a5ee2466b0 100644 --- a/lldb/scripts/Python/interface/SBCommandInterpreter.i +++ b/lldb/scripts/Python/interface/SBCommandInterpreter.i @@ -116,8 +116,7 @@ public: int HandleCompletion (const char *current_line, - const char *cursor, - const char *last_char, + uint32_t cursor_pos, int match_start_point, int max_return_elements, lldb::SBStringList &matches); diff --git a/lldb/scripts/Python/interface/SBFileSpecList.i b/lldb/scripts/Python/interface/SBFileSpecList.i new file mode 100644 index 00000000000..5ad4742d687 --- /dev/null +++ b/lldb/scripts/Python/interface/SBFileSpecList.i @@ -0,0 +1,45 @@ +//===-- SWIG Interface for SBFileSpecList -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +namespace lldb { + +class SBFileSpecList +{ +public: + SBFileSpecList (); + + SBFileSpecList (const lldb::SBFileSpecList &rhs); + + ~SBFileSpecList (); + + uint32_t + GetSize () const; + + bool + GetDescription (SBStream &description) const; + + void + Append (const SBFileSpec &sb_file); + + bool + AppendIfUnique (const SBFileSpec &sb_file); + + void + Clear(); + + uint32_t + FindFileIndex (uint32_t idx, const SBFileSpec &sb_file); + + const SBFileSpec + GetFileSpecAtIndex (uint32_t idx) const; + +}; + + +} // namespace lldb diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i index baa151c0101..aafc80bea39 100644 --- a/lldb/scripts/Python/interface/SBTarget.i +++ b/lldb/scripts/Python/interface/SBTarget.i @@ -372,6 +372,9 @@ public: 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); + + lldb::SBBreakpoint BreakpointCreateByAddress (addr_t address); uint32_t diff --git a/lldb/scripts/lldb.swig b/lldb/scripts/lldb.swig index 66ac7b67fd7..7c7d3b011f6 100644 --- a/lldb/scripts/lldb.swig +++ b/lldb/scripts/lldb.swig @@ -56,6 +56,7 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions #include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFileSpecList.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBFunction.h" #include "lldb/API/SBHostOS.h" @@ -106,6 +107,7 @@ o SBLineEntry: Specifies an association with a contiguous range of instructions %include "./Python/interface/SBError.i" %include "./Python/interface/SBEvent.i" %include "./Python/interface/SBFileSpec.i" +%include "./Python/interface/SBFileSpecList.i" %include "./Python/interface/SBFrame.i" %include "./Python/interface/SBFunction.i" %include "./Python/interface/SBHostOS.i" diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 61d0a99f975..8a15423c324 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -136,6 +136,18 @@ SBCommandInterpreter::HandleCompletion (const char *current_line, return num_completions; } +int +SBCommandInterpreter::HandleCompletion (const char *current_line, + uint32_t cursor_pos, + int match_start_point, + int max_return_elements, + lldb::SBStringList &matches) +{ + const char *cursor = current_line + cursor_pos; + const char *last_char = current_line + strlen (current_line); + return HandleCompletion (current_line, cursor, last_char, match_start_point, max_return_elements, matches); +} + bool SBCommandInterpreter::HasCommands () { diff --git a/lldb/source/API/SBFileSpecList.cpp b/lldb/source/API/SBFileSpecList.cpp new file mode 100644 index 00000000000..3abb4fc135b --- /dev/null +++ b/lldb/source/API/SBFileSpecList.cpp @@ -0,0 +1,139 @@ +//===-- SBFileSpecListList.cpp ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <limits.h> + +#include "lldb/API/SBFileSpec.h" +#include "lldb/API/SBFileSpecList.h" +#include "lldb/API/SBStream.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/Log.h" +#include "lldb/Host/FileSpec.h" + +using namespace lldb; +using namespace lldb_private; + + + +SBFileSpecList::SBFileSpecList () : + m_opaque_ap(new FileSpecList()) +{ +} + +SBFileSpecList::SBFileSpecList (const SBFileSpecList &rhs) : + m_opaque_ap() +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (rhs.m_opaque_ap.get()) + m_opaque_ap.reset (new FileSpecList (*(rhs.get()))); + + if (log) + { + log->Printf ("SBFileSpecList::SBFileSpecList (const SBFileSpecList rhs.ap=%p) => SBFileSpecList(%p): %s", + rhs.m_opaque_ap.get(), m_opaque_ap.get()); + } +} + +SBFileSpecList::~SBFileSpecList () +{ +} + +const SBFileSpecList & +SBFileSpecList::operator = (const SBFileSpecList &rhs) +{ + if (this != &rhs) + { + m_opaque_ap.reset (new lldb_private::FileSpecList(*(rhs.get()))); + } + return *this; +} + +uint32_t +SBFileSpecList::GetSize () const +{ + return m_opaque_ap->GetSize(); +} + +void +SBFileSpecList::Append (const SBFileSpec &sb_file) +{ + m_opaque_ap->Append (sb_file.ref()); +} + +bool +SBFileSpecList::AppendIfUnique (const SBFileSpec &sb_file) +{ + return m_opaque_ap->AppendIfUnique (sb_file.ref()); +} + +void +SBFileSpecList::Clear() +{ + m_opaque_ap->Clear(); +} + +uint32_t +SBFileSpecList::FindFileIndex (uint32_t idx, const SBFileSpec &sb_file) +{ + return m_opaque_ap->FindFileIndex (idx, sb_file.ref()); +} + +const SBFileSpec +SBFileSpecList::GetFileSpecAtIndex (uint32_t idx) const +{ + SBFileSpec new_spec; + new_spec.SetFileSpec(m_opaque_ap->GetFileSpecAtIndex(idx)); + return new_spec; +} + +const lldb_private::FileSpecList * +SBFileSpecList::operator->() const +{ + return m_opaque_ap.get(); +} + +const lldb_private::FileSpecList * +SBFileSpecList::get() const +{ + return m_opaque_ap.get(); +} + + +const lldb_private::FileSpecList & +SBFileSpecList::operator*() const +{ + return *m_opaque_ap.get(); +} + +const lldb_private::FileSpecList & +SBFileSpecList::ref() const +{ + return *m_opaque_ap.get(); +} + +bool +SBFileSpecList::GetDescription (SBStream &description) const +{ + if (m_opaque_ap.get()) + { + uint32_t num_files = m_opaque_ap->GetSize(); + description.Printf ("%d files: ", num_files); + for (uint32_t i = 0; i < num_files; i++) + { + char path[PATH_MAX]; + if (m_opaque_ap->GetFileSpecAtIndex(i).GetPath(path, sizeof(path))) + description.Printf ("\n %s", path); + } + } + else + description.Printf ("No value"); + + return true; +} diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 5f3716c4e1a..4e0dac4e907 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -580,8 +580,9 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na Mutex::Locker api_locker (m_opaque_sp->GetAPIMutex()); if (module_name && module_name[0]) { - FileSpec module_file_spec(module_name, false); - *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false); + 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); } else { @@ -611,9 +612,10 @@ SBTarget::BreakpointCreateByRegex (const char *symbol_name_regex, const char *mo if (module_name && module_name[0]) { - FileSpec module_file_spec(module_name, false); + FileSpecList module_spec_list; + module_spec_list.Append (FileSpec (module_name, false)); - *sb_bp = m_opaque_sp->CreateBreakpoint (&module_file_spec, regexp, false); + *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, regexp, false); } else { @@ -652,6 +654,42 @@ SBTarget::BreakpointCreateByAddress (addr_t address) return sb_bp; } +lldb::SBBreakpoint +SBTarget::BreakpointCreateBySourceRegex (const char *source_regex, const lldb::SBFileSpec &source_file, const char *module_name) +{ + 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); + + 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); + } + else + { + *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, source_file.ref(), regexp, false); + } + } + + if (log) + { + char path[PATH_MAX]; + source_file->GetPath (path, sizeof(path)); + log->Printf ("SBTarget(%p)::BreakpointCreateByRegex (source_regex=\"%s\", file=\"%s\", module_name=\"%s\") => SBBreakpoint(%p)", + m_opaque_sp.get(), source_regex, path, sb_bp.get()); + } + + return sb_bp; +} + + SBBreakpoint SBTarget::FindBreakpointByID (break_id_t bp_id) { diff --git a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp index 13eda3c5d64..224dd158f67 100644 --- a/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverFileLine.cpp @@ -67,12 +67,22 @@ BreakpointResolverFileLine::SearchCallback Address line_start = sc.line_entry.range.GetBaseAddress(); if (line_start.IsValid()) { - BreakpointLocationSP bp_loc_sp (m_breakpoint->AddLocation(line_start)); - if (log && bp_loc_sp && !m_breakpoint->IsInternal()) + if (filter.AddressPasses(line_start)) { - StreamString s; - bp_loc_sp->GetDescription (&s, lldb::eDescriptionLevelVerbose); - log->Printf ("Added location: %s\n", s.GetData()); + 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 the filter.\n", + line_start.GetFileAddress(), + m_file_spec.GetFilename().AsCString("<Unknown>"), + m_line_number); } } else diff --git a/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp new file mode 100644 index 00000000000..238c3709354 --- /dev/null +++ b/lldb/source/Breakpoint/BreakpointResolverFileRegex.cpp @@ -0,0 +1,139 @@ +//===-- BreakpointResolverFileRegex.cpp --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Breakpoint/BreakpointResolverFileRegex.h" + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/SourceManager.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" +#include "lldb/Target/Target.h" +#include "lldb/lldb-private-log.h" + +using namespace lldb; +using namespace lldb_private; + +//---------------------------------------------------------------------- +// BreakpointResolverFileRegex: +//---------------------------------------------------------------------- +BreakpointResolverFileRegex::BreakpointResolverFileRegex +( + Breakpoint *bkpt, + const FileSpec &file_spec, + RegularExpression ®ex +) : + BreakpointResolver (bkpt, BreakpointResolver::FileLineResolver), + m_file_spec (file_spec), + m_regex (regex) +{ +} + +BreakpointResolverFileRegex::~BreakpointResolverFileRegex () +{ +} + +Searcher::CallbackReturn +BreakpointResolverFileRegex::SearchCallback +( + SearchFilter &filter, + SymbolContext &context, + Address *addr, + bool containing +) +{ + + assert (m_breakpoint != NULL); + if (!context.target_sp) + return eCallbackReturnContinue; + + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + + CompileUnit *cu = context.comp_unit; + FileSpec cu_file_spec = *(static_cast<FileSpec *>(cu)); + if (cu_file_spec == m_file_spec + || (!m_file_spec.GetDirectory() && cu_file_spec.GetFilename() == m_file_spec.GetFilename())) + { + std::vector<uint32_t> 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; + while (1) + { + LineEntry line_entry; + + // 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()) + { + if (filter.AddressPasses(line_start)) + { + 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("<Unknown>"), + 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(), + m_file_spec.GetFilename().AsCString("<Unknown>"), + line_matches[i]); + } + + } + } + assert (m_breakpoint != NULL); + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + + + } + return Searcher::eCallbackReturnContinue; +} + +Searcher::Depth +BreakpointResolverFileRegex::GetDepth() +{ + return Searcher::eDepthCompUnit; +} + +void +BreakpointResolverFileRegex::GetDescription (Stream *s) +{ + s->Printf ("file ='%s', regular expression = \"%s\"", m_file_spec.GetFilename().AsCString(), m_regex.GetText()); +} + +void +BreakpointResolverFileRegex::Dump (Stream *s) const +{ + +} + diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp index 60547c6bd78..141a15bef7d 100644 --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -104,7 +104,6 @@ BreakpointResolverName::BreakpointResolverName m_match_type (Breakpoint::Regexp), m_skip_prologue (skip_prologue) { - } BreakpointResolverName::BreakpointResolverName diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 5c96a7f6d92..cc2051d3184 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -56,6 +56,7 @@ CommandObjectBreakpointSet::CommandOptions::CommandOptions(CommandInterpreter &i m_func_name (), m_func_name_type_mask (0), m_func_regexp (), + m_source_text_regexp(), m_modules (), m_load_addr(), m_ignore_count (0), @@ -91,7 +92,7 @@ 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, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, + { 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_SET_1, true, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, @@ -124,6 +125,10 @@ CommandObjectBreakpointSet::CommandOptions::g_option_table[] = { LLDB_OPT_SET_8, true, "basename", 'b', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored)." }, + { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', required_argument, NULL, 0, eArgTypeRegularExpression, + "Set the breakpoint specifying a regular expression to match a pattern in the source text in a given source file." }, + + { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } }; @@ -187,6 +192,10 @@ CommandObjectBreakpointSet::CommandOptions::SetOptionValue (uint32_t option_idx, m_func_name_type_mask |= eFunctionNameTypeMethod; break; + case 'p': + m_source_text_regexp.assign (option_arg); + break; + case 'r': m_func_regexp.assign (option_arg); break; @@ -275,6 +284,52 @@ CommandObjectBreakpointSet::GetOptions () } bool +CommandObjectBreakpointSet::ChooseFile (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)) + { + StackFrame *cur_frame = m_interpreter.GetExecutionContext().frame; + if (cur_frame == NULL) + { + 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; + } + 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; + } + } + } + } + else + { + file.SetFile(m_options.m_filename.c_str(), false); + } + return true; +} + +bool CommandObjectBreakpointSet::Execute ( Args& command, @@ -294,6 +349,7 @@ CommandObjectBreakpointSet::Execute // 2). -a [-s -g] (setting breakpoint by address) // 3). -n [-s -g] (setting breakpoint by function name) // 4). -r [-s -g] (setting breakpoint by function name regular expression) + // 5). -p -f (setting a breakpoint by comparing a reg-exp to source text) BreakpointSetType break_type = eSetTypeInvalid; @@ -305,94 +361,42 @@ CommandObjectBreakpointSet::Execute break_type = eSetTypeFunctionName; else if (!m_options.m_func_regexp.empty()) break_type = eSetTypeFunctionRegexp; + else if (!m_options.m_source_text_regexp.empty()) + break_type = eSetTypeSourceRegexp; 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; + 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 (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)) - { - StackFrame *cur_frame = m_interpreter.GetExecutionContext().frame; - if (cur_frame == NULL) - { - result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame."); - result.SetStatus (eReturnStatusFailed); - break; - } - 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); - break; - } - 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); - break; - } - } - } - } - else - { - file.SetFile(m_options.m_filename.c_str(), false); - } - - if (use_module) - { - for (int i = 0; i < num_modules; ++i) - { - module_spec.SetFile(m_options.m_modules[i].c_str(), false); - bp = target->CreateBreakpoint (&module_spec, - file, - m_options.m_line_num, - m_options.m_check_inlines).get(); - if (bp) - { - Stream &output_stream = result.GetOutputStream(); - result.AppendMessage ("Breakpoint created: "); - bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); - output_stream.EOL(); - if (bp->GetNumLocations() == 0) - output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual" - " locations.\n"); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n", - m_options.m_modules[i].c_str()); - result.SetStatus (eReturnStatusFailed); - } - } - } - else - bp = target->CreateBreakpoint (NULL, - file, - m_options.m_line_num, - m_options.m_check_inlines).get(); + if (!ChooseFile (target, file, result)) + break; + + bp = target->CreateBreakpoint (module_spec_list_ptr, + file, + m_options.m_line_num, + m_options.m_check_inlines).get(); } break; @@ -407,72 +411,47 @@ CommandObjectBreakpointSet::Execute if (name_type_mask == 0) name_type_mask = eFunctionNameTypeAuto; - if (use_module) - { - for (int i = 0; i < num_modules; ++i) - { - module_spec.SetFile(m_options.m_modules[i].c_str(), false); - bp = target->CreateBreakpoint (&module_spec, - m_options.m_func_name.c_str(), - name_type_mask, - Breakpoint::Exact).get(); - if (bp) - { - Stream &output_stream = result.GetOutputStream(); - output_stream.Printf ("Breakpoint created: "); - bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); - output_stream.EOL(); - if (bp->GetNumLocations() == 0) - output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual" - " locations.\n"); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n", - m_options.m_modules[i].c_str()); - result.SetStatus (eReturnStatusFailed); - } - } - } - else - bp = target->CreateBreakpoint (NULL, m_options.m_func_name.c_str(), name_type_mask, Breakpoint::Exact).get(); + bp = target->CreateBreakpoint (module_spec_list_ptr, + m_options.m_func_name.c_str(), + name_type_mask, + Breakpoint::Exact).get(); } break; case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name { RegularExpression regexp(m_options.m_func_regexp.c_str()); - if (use_module) + if (!regexp.IsValid()) { - for (int i = 0; i < num_modules; ++i) - { - module_spec.SetFile(m_options.m_modules[i].c_str(), false); - bp = target->CreateBreakpoint (&module_spec, regexp).get(); - if (bp) - { - Stream &output_stream = result.GetOutputStream(); - output_stream.Printf ("Breakpoint created: "); - bp->GetDescription(&output_stream, lldb::eDescriptionLevelBrief); - output_stream.EOL(); - if (bp->GetNumLocations() == 0) - output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual" - " locations.\n"); - result.SetStatus (eReturnStatusSuccessFinishResult); - } - else - { - result.AppendErrorWithFormat("Breakpoint creation failed: No breakpoint created in module '%s'.\n", - m_options.m_modules[i].c_str()); - result.SetStatus (eReturnStatusFailed); - } - } + char err_str[1024]; + regexp.GetErrorAsCString(err_str, sizeof(err_str)); + result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"", + err_str); + result.SetStatus (eReturnStatusFailed); + return false; } - else - bp = target->CreateBreakpoint (NULL, regexp).get(); + bp = target->CreateBreakpoint (module_spec_list_ptr, regexp).get(); } break; + case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. + { + FileSpec file; + if (!ChooseFile (target, file, result)) + break; + RegularExpression regexp(m_options.m_source_text_regexp.c_str()); + if (!regexp.IsValid()) + { + char err_str[1024]; + regexp.GetErrorAsCString(err_str, sizeof(err_str)); + result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"", + err_str); + result.SetStatus (eReturnStatusFailed); + return false; + } + bp = target->CreateBreakpoint (module_spec_list_ptr, file, regexp).get(); + } + break; default: break; } @@ -496,7 +475,7 @@ CommandObjectBreakpointSet::Execute bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); } - if (bp && !use_module) + if (bp) { Stream &output_stream = result.GetOutputStream(); output_stream.Printf ("Breakpoint created: "); diff --git a/lldb/source/Commands/CommandObjectBreakpoint.h b/lldb/source/Commands/CommandObjectBreakpoint.h index d8382a75c0b..9df14dafad4 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.h +++ b/lldb/source/Commands/CommandObjectBreakpoint.h @@ -57,7 +57,8 @@ public: eSetTypeFileAndLine, eSetTypeAddress, eSetTypeFunctionName, - eSetTypeFunctionRegexp + eSetTypeFunctionRegexp, + eSetTypeSourceRegexp } BreakpointSetType; CommandObjectBreakpointSet (CommandInterpreter &interpreter); @@ -103,6 +104,7 @@ public: std::string m_func_name; uint32_t m_func_name_type_mask; std::string m_func_regexp; + std::string m_source_text_regexp; STLStringArray m_modules; lldb::addr_t m_load_addr; uint32_t m_ignore_count; @@ -114,6 +116,9 @@ public: }; private: + bool + ChooseFile (Target *target, FileSpec &file, CommandReturnObject &result); + CommandOptions m_options; }; diff --git a/lldb/source/Core/RegularExpression.cpp b/lldb/source/Core/RegularExpression.cpp index 6fb94d98bb5..c3953aae068 100644 --- a/lldb/source/Core/RegularExpression.cpp +++ b/lldb/source/Core/RegularExpression.cpp @@ -19,6 +19,7 @@ RegularExpression::RegularExpression() : m_re(), m_comp_err (1), m_preg(), + m_compile_flags(REG_EXTENDED), m_matches() { memset(&m_preg,0,sizeof(m_preg)); @@ -31,13 +32,43 @@ RegularExpression::RegularExpression() : RegularExpression::RegularExpression(const char* re, int flags) : m_re(), m_comp_err (1), + m_compile_flags(flags), m_preg() { memset(&m_preg,0,sizeof(m_preg)); - Compile(re, flags); + Compile(re); } //---------------------------------------------------------------------- +// Constructor that compiles "re" using "flags" and stores the +// resulting compiled regular expression into this object. +//---------------------------------------------------------------------- +RegularExpression::RegularExpression(const char* re) : + m_re(), + m_comp_err (1), + m_compile_flags(REG_EXTENDED), + m_preg() +{ + memset(&m_preg,0,sizeof(m_preg)); + Compile(re); +} + +RegularExpression::RegularExpression(const RegularExpression &rhs) +{ + memset(&m_preg,0,sizeof(m_preg)); + Compile(rhs.GetText(), rhs.GetCompileFlags()); +} + +const RegularExpression & +RegularExpression::operator= (const RegularExpression &rhs) +{ + if (&rhs != this) + { + Compile (rhs.GetText(), rhs.GetCompileFlags()); + } + return *this; +} +//---------------------------------------------------------------------- // Destructor // // Any previosuly compiled regular expression contained in this @@ -61,9 +92,17 @@ RegularExpression::~RegularExpression() // otherwise. //---------------------------------------------------------------------- bool +RegularExpression::Compile(const char* re) +{ + return Compile (re, m_compile_flags); +} + +bool RegularExpression::Compile(const char* re, int flags) { Free(); + m_compile_flags = flags; + if (re && re[0]) { m_re = re; diff --git a/lldb/source/Core/SearchFilter.cpp b/lldb/source/Core/SearchFilter.cpp index 8a9140df50d..e0521aa70e2 100644 --- a/lldb/source/Core/SearchFilter.cpp +++ b/lldb/source/Core/SearchFilter.cpp @@ -432,3 +432,178 @@ SearchFilterByModule::Dump (Stream *s) const { } +//---------------------------------------------------------------------- +// SearchFilterByModuleList: +// Selects a shared library matching a given file spec +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- +// SearchFilterByModuleList constructors +//---------------------------------------------------------------------- + +SearchFilterByModuleList::SearchFilterByModuleList (lldb::TargetSP &target_sp, const FileSpecList &module_list) : + SearchFilter (target_sp), + m_module_spec_list (module_list) +{ +} + + +//---------------------------------------------------------------------- +// SearchFilterByModuleList copy constructor +//---------------------------------------------------------------------- +SearchFilterByModuleList::SearchFilterByModuleList(const SearchFilterByModuleList& rhs) : + SearchFilter (rhs), + m_module_spec_list (rhs.m_module_spec_list) +{ +} + +//---------------------------------------------------------------------- +// SearchFilterByModuleList assignment operator +//---------------------------------------------------------------------- +const SearchFilterByModuleList& +SearchFilterByModuleList::operator=(const SearchFilterByModuleList& rhs) +{ + m_target_sp = rhs.m_target_sp; + m_module_spec_list = rhs.m_module_spec_list; + return *this; +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +SearchFilterByModuleList::~SearchFilterByModuleList() +{ +} + +bool +SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp) +{ + if (module_sp && m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec()) != UINT32_MAX) + return true; + else + return false; +} + +bool +SearchFilterByModuleList::ModulePasses (const FileSpec &spec) +{ + if (m_module_spec_list.FindFileIndex(0, spec) != UINT32_MAX) + return true; + else + return false; +} + +bool +SearchFilterByModuleList::SymbolContextPasses +( + const SymbolContext &context, + lldb::SymbolContextItem scope + ) +{ + if (!(scope & eSymbolContextModule)) + return false; + + if (context.module_sp && m_module_spec_list.FindFileIndex(0, context.module_sp->GetFileSpec()) != UINT32_MAX) + return true; + else + return false; +} + +bool +SearchFilterByModuleList::AddressPasses (Address &address) +{ + // FIXME: Not yet implemented + return true; +} + + +bool +SearchFilterByModuleList::CompUnitPasses (FileSpec &fileSpec) +{ + return true; +} + +bool +SearchFilterByModuleList::CompUnitPasses (CompileUnit &compUnit) +{ + return true; +} + +void +SearchFilterByModuleList::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 (); + 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) + { + SymbolContext matchingContext(m_target_sp, ModuleSP(module)); + Searcher::CallbackReturn shouldContinue; + + shouldContinue = DoModuleIteration(matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; + } + } +} + +void +SearchFilterByModuleList::GetDescription (Stream *s) +{ + uint32_t num_modules = m_module_spec_list.GetSize(); + if (num_modules == 1) + { + s->Printf (", module = ", num_modules); + 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("<unknown>")); + } + } + else + { + 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("<unknown>")); + } + if (i != num_modules - 1) + s->PutCString (", "); + } + } +} + +void +SearchFilterByModuleList::Dump (Stream *s) const +{ + +} diff --git a/lldb/source/Core/SourceManager.cpp b/lldb/source/Core/SourceManager.cpp index 708bf89bd99..6b0670f31b4 100644 --- a/lldb/source/Core/SourceManager.cpp +++ b/lldb/source/Core/SourceManager.cpp @@ -231,6 +231,19 @@ SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line) return false; } +void +SourceManager::FindLinesMatchingRegex (FileSpec &file_spec, + RegularExpression& regex, + uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines) +{ + match_lines.clear(); + FileSP file_sp = GetFile (file_spec); + if (!file_sp) + return; + return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines); +} SourceManager::File::File(const FileSpec &file_spec, Target *target) : m_file_spec_orig (file_spec), @@ -368,6 +381,36 @@ SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, return 0; } +void +SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines) +{ + TimeValue curr_mod_time (m_file_spec.GetModificationTime()); + if (m_mod_time != curr_mod_time) + { + m_mod_time = curr_mod_time; + m_data_sp = m_file_spec.ReadFileContents (); + m_offsets.clear(); + } + + match_lines.clear(); + + if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) + return; + if (start_line > end_line) + return; + + for (uint32_t line_no = start_line; line_no < end_line; line_no++) + { + std::string buffer; + if (!GetLine (line_no, buffer)) + break; + if (regex.Execute(buffer.c_str())) + { + match_lines.push_back(line_no); + } + } +} + bool SourceManager::File::FileSpecMatches (const FileSpec &file_spec) { @@ -457,6 +500,23 @@ SourceManager::File::CalculateLineOffsets (uint32_t line) return false; } +bool +SourceManager::File::GetLine (uint32_t line_no, std::string &buffer) +{ + if (!LineIsValid(line_no)) + return false; + + uint32_t start_offset = GetLineOffset (line_no); + uint32_t end_offset = GetLineOffset (line_no + 1); + if (end_offset == UINT32_MAX) + { + end_offset = m_data_sp->GetByteSize(); + } + buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset); + + return true; +} + void SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp) { diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index 6628f92a10f..55e0af68cb8 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -985,7 +985,9 @@ DynamicLoaderDarwinKernel::SetNotificationBreakpointIfNeeded () const bool internal_bp = false; const LazyBool skip_prologue = eLazyBoolNo; - Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&m_kernel.module_sp->GetFileSpec(), + FileSpecList module_spec_list; + module_spec_list.Append (m_kernel.module_sp->GetFileSpec()); + Breakpoint *bp = m_process->GetTarget().CreateBreakpoint (&module_spec_list, "OSKextLoadedKextSummariesUpdated", eFunctionNameTypeFull, internal_bp, diff --git a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp index 5148751755d..14517e605ee 100644 --- a/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp +++ b/lldb/source/Plugins/SymbolFile/Symtab/SymbolFileSymtab.cpp @@ -124,7 +124,7 @@ SymbolFileSymtab::GetNumCompileUnits() // If we don't have any source file symbols we will just have one compile unit for // the entire object file if (m_source_indexes.empty()) - return 1; + return 0; // If we have any source file symbols we will logically orgnize the object symbols // using these. @@ -138,14 +138,14 @@ SymbolFileSymtab::ParseCompileUnitAtIndex(uint32_t idx) // If we don't have any source file symbols we will just have one compile unit for // the entire object file - if (m_source_indexes.empty()) - { - const FileSpec &obj_file_spec = m_obj_file->GetFileSpec(); - if (obj_file_spec) - cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown)); - - } - else if (idx < m_source_indexes.size()) +// if (m_source_indexes.empty()) +// { +// const FileSpec &obj_file_spec = m_obj_file->GetFileSpec(); +// if (obj_file_spec) +// cu_sp.reset(new CompileUnit(m_obj_file->GetModule(), NULL, obj_file_spec, 0, eLanguageTypeUnknown)); +// +// } + /* else */ if (idx < m_source_indexes.size()) { const Symbol *cu_symbol = m_obj_file->GetSymtab()->SymbolAtIndex(m_source_indexes[idx]); if (cu_symbol) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 154946206d9..5fdc2333eb8 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -16,6 +16,7 @@ #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Breakpoint/BreakpointResolverAddress.h" #include "lldb/Breakpoint/BreakpointResolverFileLine.h" +#include "lldb/Breakpoint/BreakpointResolverFileRegex.h" #include "lldb/Breakpoint/BreakpointResolverName.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Event.h" @@ -206,9 +207,21 @@ Target::GetBreakpointByID (break_id_t break_id) } BreakpointSP -Target::CreateBreakpoint (const FileSpec *containingModule, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal) +Target::CreateBreakpoint (const FileSpecList *containingModules, + const FileSpec &file, + RegularExpression &source_regex, + bool internal) { - SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule)); + SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); + BreakpointResolverSP resolver_sp(new BreakpointResolverFileRegex (NULL, file, source_regex)); + return CreateBreakpoint (filter_sp, resolver_sp, internal); +} + + +BreakpointSP +Target::CreateBreakpoint (const FileSpecList *containingModules, const FileSpec &file, uint32_t line_no, bool check_inlines, bool internal) +{ + SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); BreakpointResolverSP resolver_sp(new BreakpointResolverFileLine (NULL, file, line_no, check_inlines)); return CreateBreakpoint (filter_sp, resolver_sp, internal); } @@ -242,7 +255,7 @@ Target::CreateBreakpoint (Address &addr, bool internal) } BreakpointSP -Target::CreateBreakpoint (const FileSpec *containingModule, +Target::CreateBreakpoint (const FileSpecList *containingModules, const char *func_name, uint32_t func_name_type_mask, bool internal, @@ -251,7 +264,7 @@ Target::CreateBreakpoint (const FileSpec *containingModule, BreakpointSP bp_sp; if (func_name) { - SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule)); + SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); BreakpointResolverSP resolver_sp (new BreakpointResolverName (NULL, func_name, @@ -284,13 +297,33 @@ Target::GetSearchFilterForModule (const FileSpec *containingModule) return filter_sp; } +SearchFilterSP +Target::GetSearchFilterForModuleList (const FileSpecList *containingModules) +{ + SearchFilterSP filter_sp; + lldb::TargetSP target_sp = this->GetSP(); + if (containingModules && containingModules->GetSize() != 0) + { + // TODO: We should look into sharing module based search filters + // across many breakpoints like we do for the simple target based one + filter_sp.reset (new SearchFilterByModuleList (target_sp, *containingModules)); + } + else + { + if (m_search_filter_sp.get() == NULL) + m_search_filter_sp.reset (new SearchFilter (target_sp)); + filter_sp = m_search_filter_sp; + } + return filter_sp; +} + BreakpointSP -Target::CreateBreakpoint (const FileSpec *containingModule, +Target::CreateBreakpoint (const FileSpecList *containingModules, RegularExpression &func_regex, bool internal, LazyBool skip_prologue) { - SearchFilterSP filter_sp(GetSearchFilterForModule (containingModule)); + SearchFilterSP filter_sp(GetSearchFilterForModuleList (containingModules)); BreakpointResolverSP resolver_sp(new BreakpointResolverName (NULL, func_regex, skip_prologue == eLazyBoolCalculate ? GetSkipPrologue() : skip_prologue)); diff --git a/lldb/test/lang/objc/objc-stepping/TestObjCStepping.py b/lldb/test/lang/objc/objc-stepping/TestObjCStepping.py index 67482e5256c..426f719c456 100644 --- a/lldb/test/lang/objc/objc-stepping/TestObjCStepping.py +++ b/lldb/test/lang/objc/objc-stepping/TestObjCStepping.py @@ -3,6 +3,7 @@ import os, time import unittest2 import lldb +import lldbutil from lldbtest import * class TestObjCStepping(TestBase): @@ -25,17 +26,11 @@ class TestObjCStepping(TestBase): def setUp(self): # Call super's setUp(). TestBase.setUp(self) - # Find the line numbers to break inside main(). + # Find the line numbers that we will step to in main: self.main_source = "stepping-tests.m" - self.line1 = line_number(self.main_source, '// Set first breakpoint here.') - self.line2 = line_number(self.main_source, '// Set second breakpoint here.') - self.line3 = line_number(self.main_source, '// Set third breakpoint here.') - self.line4 = line_number(self.main_source, '// Set fourth breakpoint here.') - self.line5 = line_number(self.main_source, '// Set fifth breakpoint here.') self.source_randomMethod_line = line_number (self.main_source, '// Source randomMethod start line.') self.sourceBase_randomMethod_line = line_number (self.main_source, '// SourceBase randomMethod start line.') self.source_returnsStruct_start_line = line_number (self.main_source, '// Source returnsStruct start line.') - self.source_returnsStruct_call_line = line_number (self.main_source, '// Source returnsStruct call line.') self.sourceBase_returnsStruct_start_line = line_number (self.main_source, '// SourceBase returnsStruct start line.') def objc_stepping(self): @@ -45,22 +40,23 @@ class TestObjCStepping(TestBase): target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) - break1 = target.BreakpointCreateByLocation(self.main_source, self.line1) + self.main_source_spec = lldb.SBFileSpec (self.main_source) + break1 = target.BreakpointCreateBySourceRegex ("// Set first breakpoint here.", self.main_source_spec) self.assertTrue(break1, VALID_BREAKPOINT) - break2 = target.BreakpointCreateByLocation(self.main_source, self.line2) + break2 = target.BreakpointCreateBySourceRegex ("// Set second breakpoint here.", self.main_source_spec) self.assertTrue(break2, VALID_BREAKPOINT) - break3 = target.BreakpointCreateByLocation(self.main_source, self.line3) + break3 = target.BreakpointCreateBySourceRegex ('// Set third breakpoint here.', self.main_source_spec) self.assertTrue(break3, VALID_BREAKPOINT) - break4 = target.BreakpointCreateByLocation(self.main_source, self.line4) + break4 = target.BreakpointCreateBySourceRegex ('// Set fourth breakpoint here.', self.main_source_spec) self.assertTrue(break4, VALID_BREAKPOINT) - break5 = target.BreakpointCreateByLocation(self.main_source, self.line5) + break5 = target.BreakpointCreateBySourceRegex ('// Set fifth breakpoint here.', self.main_source_spec) self.assertTrue(break5, VALID_BREAKPOINT) - break_returnStruct_call_super = target.BreakpointCreateByLocation(self.main_source, self.source_returnsStruct_call_line) + break_returnStruct_call_super = target.BreakpointCreateBySourceRegex ('// Source returnsStruct call line.', self.main_source_spec) self.assertTrue(break_returnStruct_call_super, VALID_BREAKPOINT) # Now launch the process, and do not stop at entry point. @@ -69,16 +65,11 @@ class TestObjCStepping(TestBase): self.assertTrue(process, PROCESS_IS_VALID) # The stop reason of the thread should be breakpoint. - thread = process.GetThreadAtIndex(0) - if thread.GetStopReason() != lldb.eStopReasonBreakpoint: - from lldbutil import stop_reason_to_str - self.fail(STOPPED_DUE_TO_BREAKPOINT_WITH_STOP_REASON_AS % - stop_reason_to_str(thread.GetStopReason())) + threads = lldbutil.get_threads_stopped_at_breakpoint (process, break1) + if len(threads) != 1: + self.fail ("Failed to stop at breakpoint 1.") - # Make sure we stopped at the first breakpoint. - - line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() - self.assertTrue (line_number == self.line1, "Hit the first breakpoint.") + thread = threads[0] mySource = thread.GetFrameAtIndex(0).FindVariable("mySource") self.assertTrue(mySource, "Found mySource local variable.") @@ -100,18 +91,18 @@ class TestObjCStepping(TestBase): line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() self.assertTrue (line_number == self.sourceBase_randomMethod_line, "Stepped through super into SourceBase randomMethod.") - process.Continue() - line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() - self.assertTrue (line_number == self.line2, "Continued to second breakpoint in main.") + threads = lldbutil.continue_to_breakpoint (process, break2) + self.assertTrue (len(threads) == 1, "Continued to second breakpoint in main.") # Again, step in twice gets us to a stret method and a stret super call: + thread = threads[0] thread.StepInto() line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() self.assertTrue (line_number == self.source_returnsStruct_start_line, "Stepped into Source returnsStruct.") - process.Continue() - line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() - self.assertTrue (line_number == self.source_returnsStruct_call_line, "Stepped to the call super line in Source returnsStruct.") + threads = lldbutil.continue_to_breakpoint (process, break_returnStruct_call_super) + self.assertTrue (len(threads) == 1, "Stepped to the call super line in Source returnsStruct.") + thread = threads[0] thread.StepInto() line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() @@ -120,10 +111,8 @@ class TestObjCStepping(TestBase): # Cool now continue to get past the call that intializes the Observer, and then do our steps in again to see that # we can find our way when we're stepping through a KVO swizzled object. - process.Continue() - frame = thread.GetFrameAtIndex(0) - line_number = frame.GetLineEntry().GetLine() - self.assertTrue (line_number == self.line3, "Continued to third breakpoint in main, our object should now be swizzled.") + threads = lldbutil.continue_to_breakpoint (process, break3) + self.assertTrue (len(threads) == 1, "Continued to third breakpoint in main, our object should now be swizzled.") mySource_isa.GetValue () did_change = mySource_isa.GetValueDidChange () @@ -131,6 +120,7 @@ class TestObjCStepping(TestBase): self.assertTrue (did_change, "The isa did indeed change, swizzled!") # Now step in, that should leave us in the Source randomMethod: + thread = threads[0] thread.StepInto() line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() self.assertTrue (line_number == self.source_randomMethod_line, "Stepped into Source randomMethod in swizzled object.") @@ -140,18 +130,18 @@ class TestObjCStepping(TestBase): line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() self.assertTrue (line_number == self.sourceBase_randomMethod_line, "Stepped through super into SourceBase randomMethod in swizzled object.") - process.Continue() - line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() - self.assertTrue (line_number == self.line4, "Continued to fourth breakpoint in main.") + threads = lldbutil.continue_to_breakpoint (process, break4) + self.assertTrue (len(threads) == 1, "Continued to fourth breakpoint in main.") + thread = threads[0] # Again, step in twice gets us to a stret method and a stret super call: thread.StepInto() line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() self.assertTrue (line_number == self.source_returnsStruct_start_line, "Stepped into Source returnsStruct in swizzled object.") - process.Continue() - line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() - self.assertTrue (line_number == self.source_returnsStruct_call_line, "Stepped to the call super line in Source returnsStruct - second time.") + threads = lldbutil.continue_to_breakpoint(process, break_returnStruct_call_super) + self.assertTrue (len(threads) == 1, "Stepped to the call super line in Source returnsStruct - second time.") + thread = threads[0] thread.StepInto() line_number = thread.GetFrameAtIndex(0).GetLineEntry().GetLine() |