diff --git a/lldb/bindings/interface/SBBreakpoint.i b/lldb/bindings/interface/SBBreakpoint.i index 20354346be90..a2d747db0bf6 100644 --- a/lldb/bindings/interface/SBBreakpoint.i +++ b/lldb/bindings/interface/SBBreakpoint.i @@ -1,334 +1,337 @@ //===-- SWIG Interface for SBBreakpoint -------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// namespace lldb { %feature("docstring", "Represents a logical breakpoint and its associated settings. For example (from test/functionalities/breakpoint/breakpoint_ignore_count/ TestBreakpointIgnoreCount.py), def breakpoint_ignore_count_python(self): '''Use Python APIs to set breakpoint ignore count.''' exe = os.path.join(os.getcwd(), 'a.out') # Create a target by the debugger. target = self.dbg.CreateTarget(exe) self.assertTrue(target, VALID_TARGET) # Now create a breakpoint on main.c by name 'c'. breakpoint = target.BreakpointCreateByName('c', 'a.out') self.assertTrue(breakpoint and breakpoint.GetNumLocations() == 1, VALID_BREAKPOINT) # Get the breakpoint location from breakpoint after we verified that, # indeed, it has one location. location = breakpoint.GetLocationAtIndex(0) self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION) # Set the ignore count on the breakpoint location. location.SetIgnoreCount(2) self.assertTrue(location.GetIgnoreCount() == 2, 'SetIgnoreCount() works correctly') # Now launch the process, and do not stop at entry point. process = target.LaunchSimple(None, None, os.getcwd()) self.assertTrue(process, PROCESS_IS_VALID) # Frame#0 should be on main.c:37, frame#1 should be on main.c:25, and # frame#2 should be on main.c:48. #lldbutil.print_stacktraces(process) from lldbutil import get_stopped_thread thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) self.assertTrue(thread != None, 'There should be a thread stopped due to breakpoint') frame0 = thread.GetFrameAtIndex(0) frame1 = thread.GetFrameAtIndex(1) frame2 = thread.GetFrameAtIndex(2) self.assertTrue(frame0.GetLineEntry().GetLine() == self.line1 and frame1.GetLineEntry().GetLine() == self.line3 and frame2.GetLineEntry().GetLine() == self.line4, STOPPED_DUE_TO_BREAKPOINT_IGNORE_COUNT) # The hit count for the breakpoint should be 3. self.assertTrue(breakpoint.GetHitCount() == 3) process.Continue() SBBreakpoint supports breakpoint location iteration, for example, for bl in breakpoint: print('breakpoint location load addr: %s' % hex(bl.GetLoadAddress())) print('breakpoint location condition: %s' % hex(bl.GetCondition())) and rich comparison methods which allow the API program to use, if aBreakpoint == bBreakpoint: ... to compare two breakpoints for equality." ) SBBreakpoint; class SBBreakpoint { public: SBBreakpoint (); SBBreakpoint (const lldb::SBBreakpoint& rhs); ~SBBreakpoint(); bool operator==(const lldb::SBBreakpoint &rhs); bool operator!=(const lldb::SBBreakpoint &rhs); break_id_t GetID () const; bool IsValid() const; explicit operator bool() const; void ClearAllBreakpointSites (); lldb::SBBreakpointLocation FindLocationByAddress (lldb::addr_t vm_addr); lldb::break_id_t FindLocationIDByAddress (lldb::addr_t vm_addr); lldb::SBBreakpointLocation FindLocationByID (lldb::break_id_t bp_loc_id); lldb::SBBreakpointLocation GetLocationAtIndex (uint32_t index); void SetEnabled (bool enable); bool IsEnabled (); void SetOneShot (bool one_shot); bool IsOneShot (); bool IsInternal (); uint32_t GetHitCount () const; void SetIgnoreCount (uint32_t count); uint32_t GetIgnoreCount () const; %feature("docstring", " The breakpoint stops only if the condition expression evaluates to true.") SetCondition; void SetCondition (const char *condition); %feature("docstring", " Get the condition expression for the breakpoint.") GetCondition; const char * GetCondition (); void SetAutoContinue(bool auto_continue); bool GetAutoContinue(); void SetThreadID (lldb::tid_t sb_thread_id); lldb::tid_t GetThreadID (); void SetThreadIndex (uint32_t index); uint32_t GetThreadIndex() const; void SetThreadName (const char *thread_name); const char * GetThreadName () const; void SetQueueName (const char *queue_name); const char * GetQueueName () const; %feature("docstring", " Set the name of the script function to be called when the breakpoint is hit.") SetScriptCallbackFunction; void SetScriptCallbackFunction (const char *callback_function_name); %feature("docstring", " Set the name of the script function to be called when the breakpoint is hit. To use this variant, the function should take (frame, bp_loc, extra_args, dict) and when the breakpoint is hit the extra_args will be passed to the callback function.") SetScriptCallbackFunction; SBError SetScriptCallbackFunction (const char *callback_function_name, SBStructuredData &extra_args); %feature("docstring", " Provide the body for the script function to be called when the breakpoint is hit. The body will be wrapped in a function, which be passed two arguments: 'frame' - which holds the bottom-most SBFrame of the thread that hit the breakpoint 'bpno' - which is the SBBreakpointLocation to which the callback was attached. The error parameter is currently ignored, but will at some point hold the Python compilation diagnostics. Returns true if the body compiles successfully, false if not.") SetScriptCallbackBody; SBError SetScriptCallbackBody (const char *script_body_text); void SetCommandLineCommands(SBStringList &commands); bool GetCommandLineCommands(SBStringList &commands); bool AddName (const char *new_name); + SBError + AddNameWithErrorHandling (const char *new_name); + void RemoveName (const char *name_to_remove); bool MatchesName (const char *name); void GetNames (SBStringList &names); size_t GetNumResolvedLocations() const; size_t GetNumLocations() const; bool GetDescription (lldb::SBStream &description); bool GetDescription(lldb::SBStream &description, bool include_locations); // Can only be called from a ScriptedBreakpointResolver... SBError AddLocation(SBAddress &address); static bool EventIsBreakpointEvent (const lldb::SBEvent &event); static lldb::BreakpointEventType GetBreakpointEventTypeFromEvent (const lldb::SBEvent& event); static lldb::SBBreakpoint GetBreakpointFromEvent (const lldb::SBEvent& event); static lldb::SBBreakpointLocation GetBreakpointLocationAtIndexFromEvent (const lldb::SBEvent& event, uint32_t loc_idx); static uint32_t GetNumBreakpointLocationsFromEvent (const lldb::SBEvent &event_sp); bool IsHardware (); STRING_EXTENSION(SBBreakpoint) #ifdef SWIGPYTHON %pythoncode %{ class locations_access(object): '''A helper object that will lazily hand out locations for a breakpoint when supplied an index.''' def __init__(self, sbbreakpoint): self.sbbreakpoint = sbbreakpoint def __len__(self): if self.sbbreakpoint: return int(self.sbbreakpoint.GetNumLocations()) return 0 def __getitem__(self, key): if type(key) is int and key < len(self): return self.sbbreakpoint.GetLocationAtIndex(key) return None def get_locations_access_object(self): '''An accessor function that returns a locations_access() object which allows lazy location access from a lldb.SBBreakpoint object.''' return self.locations_access (self) def get_breakpoint_location_list(self): '''An accessor function that returns a list() that contains all locations in a lldb.SBBreakpoint object.''' locations = [] accessor = self.get_locations_access_object() for idx in range(len(accessor)): locations.append(accessor[idx]) return locations def __iter__(self): '''Iterate over all breakpoint locations in a lldb.SBBreakpoint object.''' return lldb_iter(self, 'GetNumLocations', 'GetLocationAtIndex') def __len__(self): '''Return the number of breakpoint locations in a lldb.SBBreakpoint object.''' return self.GetNumLocations() locations = property(get_breakpoint_location_list, None, doc='''A read only property that returns a list() of lldb.SBBreakpointLocation objects for this breakpoint.''') location = property(get_locations_access_object, None, doc='''A read only property that returns an object that can access locations by index (not location ID) (location = bkpt.location[12]).''') id = property(GetID, None, doc='''A read only property that returns the ID of this breakpoint.''') enabled = property(IsEnabled, SetEnabled, doc='''A read/write property that configures whether this breakpoint is enabled or not.''') one_shot = property(IsOneShot, SetOneShot, doc='''A read/write property that configures whether this breakpoint is one-shot (deleted when hit) or not.''') num_locations = property(GetNumLocations, None, doc='''A read only property that returns the count of locations of this breakpoint.''') %} #endif }; class SBBreakpointListImpl; class LLDB_API SBBreakpointList { public: SBBreakpointList(SBTarget &target); ~SBBreakpointList(); size_t GetSize() const; SBBreakpoint GetBreakpointAtIndex(size_t idx); SBBreakpoint FindBreakpointByID(lldb::break_id_t); void Append(const SBBreakpoint &sb_bkpt); bool AppendIfUnique(const SBBreakpoint &sb_bkpt); void AppendByID (lldb::break_id_t id); void Clear(); private: std::shared_ptr m_opaque_sp; }; } // namespace lldb diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h index a5ce91d95089..3ec5b49cff3c 100644 --- a/lldb/include/lldb/API/SBBreakpoint.h +++ b/lldb/include/lldb/API/SBBreakpoint.h @@ -1,184 +1,186 @@ //===-- SBBreakpoint.h ------------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef LLDB_SBBreakpoint_h_ #define LLDB_SBBreakpoint_h_ #include "lldb/API/SBDefines.h" class SBBreakpointListImpl; namespace lldb { class LLDB_API SBBreakpoint { public: SBBreakpoint(); SBBreakpoint(const lldb::SBBreakpoint &rhs); SBBreakpoint(const lldb::BreakpointSP &bp_sp); ~SBBreakpoint(); const lldb::SBBreakpoint &operator=(const lldb::SBBreakpoint &rhs); // Tests to see if the opaque breakpoint object in this object matches the // opaque breakpoint object in "rhs". bool operator==(const lldb::SBBreakpoint &rhs); bool operator!=(const lldb::SBBreakpoint &rhs); break_id_t GetID() const; explicit operator bool() const; bool IsValid() const; void ClearAllBreakpointSites(); lldb::SBBreakpointLocation FindLocationByAddress(lldb::addr_t vm_addr); lldb::break_id_t FindLocationIDByAddress(lldb::addr_t vm_addr); lldb::SBBreakpointLocation FindLocationByID(lldb::break_id_t bp_loc_id); lldb::SBBreakpointLocation GetLocationAtIndex(uint32_t index); void SetEnabled(bool enable); bool IsEnabled(); void SetOneShot(bool one_shot); bool IsOneShot() const; bool IsInternal(); uint32_t GetHitCount() const; void SetIgnoreCount(uint32_t count); uint32_t GetIgnoreCount() const; void SetCondition(const char *condition); const char *GetCondition(); void SetAutoContinue(bool auto_continue); bool GetAutoContinue(); void SetThreadID(lldb::tid_t sb_thread_id); lldb::tid_t GetThreadID(); void SetThreadIndex(uint32_t index); uint32_t GetThreadIndex() const; void SetThreadName(const char *thread_name); const char *GetThreadName() const; void SetQueueName(const char *queue_name); const char *GetQueueName() const; void SetCallback(SBBreakpointHitCallback callback, void *baton); void SetScriptCallbackFunction(const char *callback_function_name); SBError SetScriptCallbackFunction(const char *callback_function_name, SBStructuredData &extra_args); void SetCommandLineCommands(SBStringList &commands); bool GetCommandLineCommands(SBStringList &commands); SBError SetScriptCallbackBody(const char *script_body_text); bool AddName(const char *new_name); + SBError AddNameWithErrorHandling(const char *new_name); + void RemoveName(const char *name_to_remove); bool MatchesName(const char *name); void GetNames(SBStringList &names); size_t GetNumResolvedLocations() const; size_t GetNumLocations() const; bool GetDescription(lldb::SBStream &description); bool GetDescription(lldb::SBStream &description, bool include_locations); static bool EventIsBreakpointEvent(const lldb::SBEvent &event); static lldb::BreakpointEventType GetBreakpointEventTypeFromEvent(const lldb::SBEvent &event); static lldb::SBBreakpoint GetBreakpointFromEvent(const lldb::SBEvent &event); static lldb::SBBreakpointLocation GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event, uint32_t loc_idx); static uint32_t GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event_sp); bool IsHardware() const; // Can only be called from a ScriptedBreakpointResolver... SBError AddLocation(SBAddress &address); private: friend class SBBreakpointList; friend class SBBreakpointLocation; friend class SBBreakpointName; friend class SBTarget; lldb::BreakpointSP GetSP() const; lldb::BreakpointWP m_opaque_wp; }; class LLDB_API SBBreakpointList { public: SBBreakpointList(SBTarget &target); ~SBBreakpointList(); size_t GetSize() const; SBBreakpoint GetBreakpointAtIndex(size_t idx); SBBreakpoint FindBreakpointByID(lldb::break_id_t); void Append(const SBBreakpoint &sb_bkpt); bool AppendIfUnique(const SBBreakpoint &sb_bkpt); void AppendByID(lldb::break_id_t id); void Clear(); protected: friend class SBTarget; void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_id_list); private: std::shared_ptr m_opaque_sp; }; } // namespace lldb #endif // LLDB_SBBreakpoint_h_ diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index 8159b851d58c..673714546ffd 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -1,1056 +1,1067 @@ //===-- SBBreakpoint.cpp ----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "lldb/API/SBBreakpoint.h" #include "SBReproducerPrivate.h" #include "lldb/API/SBBreakpointLocation.h" #include "lldb/API/SBDebugger.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBStringList.h" #include "lldb/API/SBStructuredData.h" #include "lldb/API/SBThread.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointIDList.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointResolver.h" #include "lldb/Breakpoint/BreakpointResolverScripted.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" #include "lldb/Core/Address.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StructuredDataImpl.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/ScriptInterpreter.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" #include "lldb/Utility/Stream.h" #include "SBBreakpointOptionCommon.h" #include "lldb/lldb-enumerations.h" #include "llvm/ADT/STLExtras.h" using namespace lldb; using namespace lldb_private; SBBreakpoint::SBBreakpoint() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBBreakpoint); } SBBreakpoint::SBBreakpoint(const SBBreakpoint &rhs) : m_opaque_wp(rhs.m_opaque_wp) { LLDB_RECORD_CONSTRUCTOR(SBBreakpoint, (const lldb::SBBreakpoint &), rhs); } SBBreakpoint::SBBreakpoint(const lldb::BreakpointSP &bp_sp) : m_opaque_wp(bp_sp) { LLDB_RECORD_CONSTRUCTOR(SBBreakpoint, (const lldb::BreakpointSP &), bp_sp); } SBBreakpoint::~SBBreakpoint() = default; const SBBreakpoint &SBBreakpoint::operator=(const SBBreakpoint &rhs) { LLDB_RECORD_METHOD(const lldb::SBBreakpoint &, SBBreakpoint, operator=,(const lldb::SBBreakpoint &), rhs); m_opaque_wp = rhs.m_opaque_wp; return LLDB_RECORD_RESULT(*this); } bool SBBreakpoint::operator==(const lldb::SBBreakpoint &rhs) { LLDB_RECORD_METHOD( bool, SBBreakpoint, operator==,(const lldb::SBBreakpoint &), rhs); return m_opaque_wp.lock() == rhs.m_opaque_wp.lock(); } bool SBBreakpoint::operator!=(const lldb::SBBreakpoint &rhs) { LLDB_RECORD_METHOD( bool, SBBreakpoint, operator!=,(const lldb::SBBreakpoint &), rhs); return m_opaque_wp.lock() != rhs.m_opaque_wp.lock(); } break_id_t SBBreakpoint::GetID() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::break_id_t, SBBreakpoint, GetID); break_id_t break_id = LLDB_INVALID_BREAK_ID; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) break_id = bkpt_sp->GetID(); return break_id; } bool SBBreakpoint::IsValid() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, IsValid); return this->operator bool(); } SBBreakpoint::operator bool() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, operator bool); BreakpointSP bkpt_sp = GetSP(); if (!bkpt_sp) return false; else if (bkpt_sp->GetTarget().GetBreakpointByID(bkpt_sp->GetID())) return true; else return false; } void SBBreakpoint::ClearAllBreakpointSites() { LLDB_RECORD_METHOD_NO_ARGS(void, SBBreakpoint, ClearAllBreakpointSites); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->ClearAllBreakpointSites(); } } SBBreakpointLocation SBBreakpoint::FindLocationByAddress(addr_t vm_addr) { LLDB_RECORD_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, FindLocationByAddress, (lldb::addr_t), vm_addr); SBBreakpointLocation sb_bp_location; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { if (vm_addr != LLDB_INVALID_ADDRESS) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); Address address; Target &target = bkpt_sp->GetTarget(); if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) { address.SetRawAddress(vm_addr); } sb_bp_location.SetLocation(bkpt_sp->FindLocationByAddress(address)); } } return LLDB_RECORD_RESULT(sb_bp_location); } break_id_t SBBreakpoint::FindLocationIDByAddress(addr_t vm_addr) { LLDB_RECORD_METHOD(lldb::break_id_t, SBBreakpoint, FindLocationIDByAddress, (lldb::addr_t), vm_addr); break_id_t break_id = LLDB_INVALID_BREAK_ID; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp && vm_addr != LLDB_INVALID_ADDRESS) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); Address address; Target &target = bkpt_sp->GetTarget(); if (!target.GetSectionLoadList().ResolveLoadAddress(vm_addr, address)) { address.SetRawAddress(vm_addr); } break_id = bkpt_sp->FindLocationIDByAddress(address); } return break_id; } SBBreakpointLocation SBBreakpoint::FindLocationByID(break_id_t bp_loc_id) { LLDB_RECORD_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, FindLocationByID, (lldb::break_id_t), bp_loc_id); SBBreakpointLocation sb_bp_location; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); sb_bp_location.SetLocation(bkpt_sp->FindLocationByID(bp_loc_id)); } return LLDB_RECORD_RESULT(sb_bp_location); } SBBreakpointLocation SBBreakpoint::GetLocationAtIndex(uint32_t index) { LLDB_RECORD_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, GetLocationAtIndex, (uint32_t), index); SBBreakpointLocation sb_bp_location; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); sb_bp_location.SetLocation(bkpt_sp->GetLocationAtIndex(index)); } return LLDB_RECORD_RESULT(sb_bp_location); } void SBBreakpoint::SetEnabled(bool enable) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetEnabled, (bool), enable); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->SetEnabled(enable); } } bool SBBreakpoint::IsEnabled() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpoint, IsEnabled); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); return bkpt_sp->IsEnabled(); } else return false; } void SBBreakpoint::SetOneShot(bool one_shot) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetOneShot, (bool), one_shot); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->SetOneShot(one_shot); } } bool SBBreakpoint::IsOneShot() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, IsOneShot); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); return bkpt_sp->IsOneShot(); } else return false; } bool SBBreakpoint::IsInternal() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpoint, IsInternal); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); return bkpt_sp->IsInternal(); } else return false; } void SBBreakpoint::SetIgnoreCount(uint32_t count) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetIgnoreCount, (uint32_t), count); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->SetIgnoreCount(count); } } void SBBreakpoint::SetCondition(const char *condition) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetCondition, (const char *), condition); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->SetCondition(condition); } } const char *SBBreakpoint::GetCondition() { LLDB_RECORD_METHOD_NO_ARGS(const char *, SBBreakpoint, GetCondition); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); return bkpt_sp->GetConditionText(); } return nullptr; } void SBBreakpoint::SetAutoContinue(bool auto_continue) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetAutoContinue, (bool), auto_continue); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->SetAutoContinue(auto_continue); } } bool SBBreakpoint::GetAutoContinue() { LLDB_RECORD_METHOD_NO_ARGS(bool, SBBreakpoint, GetAutoContinue); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); return bkpt_sp->IsAutoContinue(); } return false; } uint32_t SBBreakpoint::GetHitCount() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBreakpoint, GetHitCount); uint32_t count = 0; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); count = bkpt_sp->GetHitCount(); } return count; } uint32_t SBBreakpoint::GetIgnoreCount() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBreakpoint, GetIgnoreCount); uint32_t count = 0; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); count = bkpt_sp->GetIgnoreCount(); } return count; } void SBBreakpoint::SetThreadID(tid_t tid) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetThreadID, (lldb::tid_t), tid); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->SetThreadID(tid); } } tid_t SBBreakpoint::GetThreadID() { LLDB_RECORD_METHOD_NO_ARGS(lldb::tid_t, SBBreakpoint, GetThreadID); tid_t tid = LLDB_INVALID_THREAD_ID; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); tid = bkpt_sp->GetThreadID(); } return tid; } void SBBreakpoint::SetThreadIndex(uint32_t index) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetThreadIndex, (uint32_t), index); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->GetOptions()->GetThreadSpec()->SetIndex(index); } } uint32_t SBBreakpoint::GetThreadIndex() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(uint32_t, SBBreakpoint, GetThreadIndex); uint32_t thread_idx = UINT32_MAX; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); const ThreadSpec *thread_spec = bkpt_sp->GetOptions()->GetThreadSpecNoCreate(); if (thread_spec != nullptr) thread_idx = thread_spec->GetIndex(); } return thread_idx; } void SBBreakpoint::SetThreadName(const char *thread_name) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetThreadName, (const char *), thread_name); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->GetOptions()->GetThreadSpec()->SetName(thread_name); } } const char *SBBreakpoint::GetThreadName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBreakpoint, GetThreadName); const char *name = nullptr; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); const ThreadSpec *thread_spec = bkpt_sp->GetOptions()->GetThreadSpecNoCreate(); if (thread_spec != nullptr) name = thread_spec->GetName(); } return name; } void SBBreakpoint::SetQueueName(const char *queue_name) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetQueueName, (const char *), queue_name); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->GetOptions()->GetThreadSpec()->SetQueueName(queue_name); } } const char *SBBreakpoint::GetQueueName() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(const char *, SBBreakpoint, GetQueueName); const char *name = nullptr; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); const ThreadSpec *thread_spec = bkpt_sp->GetOptions()->GetThreadSpecNoCreate(); if (thread_spec) name = thread_spec->GetQueueName(); } return name; } size_t SBBreakpoint::GetNumResolvedLocations() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(size_t, SBBreakpoint, GetNumResolvedLocations); size_t num_resolved = 0; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); num_resolved = bkpt_sp->GetNumResolvedLocations(); } return num_resolved; } size_t SBBreakpoint::GetNumLocations() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(size_t, SBBreakpoint, GetNumLocations); BreakpointSP bkpt_sp = GetSP(); size_t num_locs = 0; if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); num_locs = bkpt_sp->GetNumLocations(); } return num_locs; } void SBBreakpoint::SetCommandLineCommands(SBStringList &commands) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetCommandLineCommands, (lldb::SBStringList &), commands); BreakpointSP bkpt_sp = GetSP(); if (!bkpt_sp) return; if (commands.GetSize() == 0) return; std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); std::unique_ptr cmd_data_up( new BreakpointOptions::CommandData(*commands, eScriptLanguageNone)); bkpt_sp->GetOptions()->SetCommandDataCallback(cmd_data_up); } bool SBBreakpoint::GetCommandLineCommands(SBStringList &commands) { LLDB_RECORD_METHOD(bool, SBBreakpoint, GetCommandLineCommands, (lldb::SBStringList &), commands); BreakpointSP bkpt_sp = GetSP(); if (!bkpt_sp) return false; StringList command_list; bool has_commands = bkpt_sp->GetOptions()->GetCommandLineCallbacks(command_list); if (has_commands) commands.AppendList(command_list); return has_commands; } bool SBBreakpoint::GetDescription(SBStream &s) { LLDB_RECORD_METHOD(bool, SBBreakpoint, GetDescription, (lldb::SBStream &), s); return GetDescription(s, true); } bool SBBreakpoint::GetDescription(SBStream &s, bool include_locations) { LLDB_RECORD_METHOD(bool, SBBreakpoint, GetDescription, (lldb::SBStream &, bool), s, include_locations); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); s.Printf("SBBreakpoint: id = %i, ", bkpt_sp->GetID()); bkpt_sp->GetResolverDescription(s.get()); bkpt_sp->GetFilterDescription(s.get()); if (include_locations) { const size_t num_locations = bkpt_sp->GetNumLocations(); s.Printf(", locations = %" PRIu64, (uint64_t)num_locations); } return true; } s.Printf("No value"); return false; } SBError SBBreakpoint::AddLocation(SBAddress &address) { LLDB_RECORD_METHOD(lldb::SBError, SBBreakpoint, AddLocation, (lldb::SBAddress &), address); BreakpointSP bkpt_sp = GetSP(); SBError error; if (!address.IsValid()) { error.SetErrorString("Can't add an invalid address."); return LLDB_RECORD_RESULT(error); } if (!bkpt_sp) { error.SetErrorString("No breakpoint to add a location to."); return LLDB_RECORD_RESULT(error); } if (!llvm::isa(bkpt_sp->GetResolver().get())) { error.SetErrorString("Only a scripted resolver can add locations."); return LLDB_RECORD_RESULT(error); } if (bkpt_sp->GetSearchFilter()->AddressPasses(address.ref())) bkpt_sp->AddLocation(address.ref()); else { StreamString s; address.get()->Dump(&s, &bkpt_sp->GetTarget(), Address::DumpStyleModuleWithFileAddress); error.SetErrorStringWithFormat("Address: %s didn't pass the filter.", s.GetData()); } return LLDB_RECORD_RESULT(error); } void SBBreakpoint ::SetCallback(SBBreakpointHitCallback callback, void *baton) { LLDB_RECORD_DUMMY(void, SBBreakpoint, SetCallback, (lldb::SBBreakpointHitCallback, void *), callback, baton); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); BatonSP baton_sp(new SBBreakpointCallbackBaton(callback, baton)); bkpt_sp->SetCallback(SBBreakpointCallbackBaton ::PrivateBreakpointHitCallback, baton_sp, false); } } void SBBreakpoint::SetScriptCallbackFunction( const char *callback_function_name) { LLDB_RECORD_METHOD(void, SBBreakpoint, SetScriptCallbackFunction, (const char *), callback_function_name); SBStructuredData empty_args; SetScriptCallbackFunction(callback_function_name, empty_args); } SBError SBBreakpoint::SetScriptCallbackFunction( const char *callback_function_name, SBStructuredData &extra_args) { LLDB_RECORD_METHOD(SBError, SBBreakpoint, SetScriptCallbackFunction, (const char *, SBStructuredData &), callback_function_name, extra_args); SBError sb_error; BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { Status error; std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); BreakpointOptions *bp_options = bkpt_sp->GetOptions(); error = bkpt_sp->GetTarget() .GetDebugger() .GetScriptInterpreter() ->SetBreakpointCommandCallbackFunction(bp_options, callback_function_name, extra_args.m_impl_up ->GetObjectSP()); sb_error.SetError(error); } else sb_error.SetErrorString("invalid breakpoint"); return LLDB_RECORD_RESULT(sb_error); } SBError SBBreakpoint::SetScriptCallbackBody(const char *callback_body_text) { LLDB_RECORD_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackBody, (const char *), callback_body_text); BreakpointSP bkpt_sp = GetSP(); SBError sb_error; if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); BreakpointOptions *bp_options = bkpt_sp->GetOptions(); Status error = bkpt_sp->GetTarget() .GetDebugger() .GetScriptInterpreter() ->SetBreakpointCommandCallback(bp_options, callback_body_text); sb_error.SetError(error); } else sb_error.SetErrorString("invalid breakpoint"); return LLDB_RECORD_RESULT(sb_error); } bool SBBreakpoint::AddName(const char *new_name) { LLDB_RECORD_METHOD(bool, SBBreakpoint, AddName, (const char *), new_name); + SBError status = AddNameWithErrorHandling(new_name); + return status.Success(); +} + +SBError SBBreakpoint::AddNameWithErrorHandling(const char *new_name) { + LLDB_RECORD_METHOD(SBError, SBBreakpoint, AddNameWithErrorHandling, + (const char *), new_name); + BreakpointSP bkpt_sp = GetSP(); + SBError status; if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); - Status error; // Think I'm just going to swallow the error here, it's - // probably more annoying to have to provide it. + Status error; bkpt_sp->GetTarget().AddNameToBreakpoint(bkpt_sp, new_name, error); - if (error.Fail()) - return false; + status.SetError(error); + } else { + status.SetErrorString("invalid breakpoint"); } - return true; + return status; } void SBBreakpoint::RemoveName(const char *name_to_remove) { LLDB_RECORD_METHOD(void, SBBreakpoint, RemoveName, (const char *), name_to_remove); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); bkpt_sp->GetTarget().RemoveNameFromBreakpoint(bkpt_sp, ConstString(name_to_remove)); } } bool SBBreakpoint::MatchesName(const char *name) { LLDB_RECORD_METHOD(bool, SBBreakpoint, MatchesName, (const char *), name); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); return bkpt_sp->MatchesName(name); } return false; } void SBBreakpoint::GetNames(SBStringList &names) { LLDB_RECORD_METHOD(void, SBBreakpoint, GetNames, (lldb::SBStringList &), names); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) { std::lock_guard guard( bkpt_sp->GetTarget().GetAPIMutex()); std::vector names_vec; bkpt_sp->GetNames(names_vec); for (std::string name : names_vec) { names.AppendString(name.c_str()); } } } bool SBBreakpoint::EventIsBreakpointEvent(const lldb::SBEvent &event) { LLDB_RECORD_STATIC_METHOD(bool, SBBreakpoint, EventIsBreakpointEvent, (const lldb::SBEvent &), event); return Breakpoint::BreakpointEventData::GetEventDataFromEvent(event.get()) != nullptr; } BreakpointEventType SBBreakpoint::GetBreakpointEventTypeFromEvent(const SBEvent &event) { LLDB_RECORD_STATIC_METHOD(lldb::BreakpointEventType, SBBreakpoint, GetBreakpointEventTypeFromEvent, (const lldb::SBEvent &), event); if (event.IsValid()) return Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( event.GetSP()); return eBreakpointEventTypeInvalidType; } SBBreakpoint SBBreakpoint::GetBreakpointFromEvent(const lldb::SBEvent &event) { LLDB_RECORD_STATIC_METHOD(lldb::SBBreakpoint, SBBreakpoint, GetBreakpointFromEvent, (const lldb::SBEvent &), event); if (event.IsValid()) return LLDB_RECORD_RESULT( SBBreakpoint(Breakpoint::BreakpointEventData::GetBreakpointFromEvent( event.GetSP()))); return LLDB_RECORD_RESULT(SBBreakpoint()); } SBBreakpointLocation SBBreakpoint::GetBreakpointLocationAtIndexFromEvent(const lldb::SBEvent &event, uint32_t loc_idx) { LLDB_RECORD_STATIC_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, GetBreakpointLocationAtIndexFromEvent, (const lldb::SBEvent &, uint32_t), event, loc_idx); SBBreakpointLocation sb_breakpoint_loc; if (event.IsValid()) sb_breakpoint_loc.SetLocation( Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent( event.GetSP(), loc_idx)); return LLDB_RECORD_RESULT(sb_breakpoint_loc); } uint32_t SBBreakpoint::GetNumBreakpointLocationsFromEvent(const lldb::SBEvent &event) { LLDB_RECORD_STATIC_METHOD(uint32_t, SBBreakpoint, GetNumBreakpointLocationsFromEvent, (const lldb::SBEvent &), event); uint32_t num_locations = 0; if (event.IsValid()) num_locations = (Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( event.GetSP())); return num_locations; } bool SBBreakpoint::IsHardware() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBBreakpoint, IsHardware); BreakpointSP bkpt_sp = GetSP(); if (bkpt_sp) return bkpt_sp->IsHardware(); return false; } BreakpointSP SBBreakpoint::GetSP() const { return m_opaque_wp.lock(); } // This is simple collection of breakpoint id's and their target. class SBBreakpointListImpl { public: SBBreakpointListImpl(lldb::TargetSP target_sp) : m_target_wp() { if (target_sp && target_sp->IsValid()) m_target_wp = target_sp; } ~SBBreakpointListImpl() = default; size_t GetSize() { return m_break_ids.size(); } BreakpointSP GetBreakpointAtIndex(size_t idx) { if (idx >= m_break_ids.size()) return BreakpointSP(); TargetSP target_sp = m_target_wp.lock(); if (!target_sp) return BreakpointSP(); lldb::break_id_t bp_id = m_break_ids[idx]; return target_sp->GetBreakpointList().FindBreakpointByID(bp_id); } BreakpointSP FindBreakpointByID(lldb::break_id_t desired_id) { TargetSP target_sp = m_target_wp.lock(); if (!target_sp) return BreakpointSP(); for (lldb::break_id_t &break_id : m_break_ids) { if (break_id == desired_id) return target_sp->GetBreakpointList().FindBreakpointByID(break_id); } return BreakpointSP(); } bool Append(BreakpointSP bkpt) { TargetSP target_sp = m_target_wp.lock(); if (!target_sp || !bkpt) return false; if (bkpt->GetTargetSP() != target_sp) return false; m_break_ids.push_back(bkpt->GetID()); return true; } bool AppendIfUnique(BreakpointSP bkpt) { TargetSP target_sp = m_target_wp.lock(); if (!target_sp || !bkpt) return false; if (bkpt->GetTargetSP() != target_sp) return false; lldb::break_id_t bp_id = bkpt->GetID(); if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) == m_break_ids.end()) return false; m_break_ids.push_back(bkpt->GetID()); return true; } bool AppendByID(lldb::break_id_t id) { TargetSP target_sp = m_target_wp.lock(); if (!target_sp) return false; if (id == LLDB_INVALID_BREAK_ID) return false; m_break_ids.push_back(id); return true; } void Clear() { m_break_ids.clear(); } void CopyToBreakpointIDList(lldb_private::BreakpointIDList &bp_list) { for (lldb::break_id_t id : m_break_ids) { bp_list.AddBreakpointID(BreakpointID(id)); } } TargetSP GetTarget() { return m_target_wp.lock(); } private: std::vector m_break_ids; TargetWP m_target_wp; }; SBBreakpointList::SBBreakpointList(SBTarget &target) : m_opaque_sp(new SBBreakpointListImpl(target.GetSP())) { LLDB_RECORD_CONSTRUCTOR(SBBreakpointList, (lldb::SBTarget &), target); } SBBreakpointList::~SBBreakpointList() {} size_t SBBreakpointList::GetSize() const { LLDB_RECORD_METHOD_CONST_NO_ARGS(size_t, SBBreakpointList, GetSize); if (!m_opaque_sp) return 0; else return m_opaque_sp->GetSize(); } SBBreakpoint SBBreakpointList::GetBreakpointAtIndex(size_t idx) { LLDB_RECORD_METHOD(lldb::SBBreakpoint, SBBreakpointList, GetBreakpointAtIndex, (size_t), idx); if (!m_opaque_sp) return LLDB_RECORD_RESULT(SBBreakpoint()); BreakpointSP bkpt_sp = m_opaque_sp->GetBreakpointAtIndex(idx); return LLDB_RECORD_RESULT(SBBreakpoint(bkpt_sp)); } SBBreakpoint SBBreakpointList::FindBreakpointByID(lldb::break_id_t id) { LLDB_RECORD_METHOD(lldb::SBBreakpoint, SBBreakpointList, FindBreakpointByID, (lldb::break_id_t), id); if (!m_opaque_sp) return LLDB_RECORD_RESULT(SBBreakpoint()); BreakpointSP bkpt_sp = m_opaque_sp->FindBreakpointByID(id); return LLDB_RECORD_RESULT(SBBreakpoint(bkpt_sp)); } void SBBreakpointList::Append(const SBBreakpoint &sb_bkpt) { LLDB_RECORD_METHOD(void, SBBreakpointList, Append, (const lldb::SBBreakpoint &), sb_bkpt); if (!sb_bkpt.IsValid()) return; if (!m_opaque_sp) return; m_opaque_sp->Append(sb_bkpt.m_opaque_wp.lock()); } void SBBreakpointList::AppendByID(lldb::break_id_t id) { LLDB_RECORD_METHOD(void, SBBreakpointList, AppendByID, (lldb::break_id_t), id); if (!m_opaque_sp) return; m_opaque_sp->AppendByID(id); } bool SBBreakpointList::AppendIfUnique(const SBBreakpoint &sb_bkpt) { LLDB_RECORD_METHOD(bool, SBBreakpointList, AppendIfUnique, (const lldb::SBBreakpoint &), sb_bkpt); if (!sb_bkpt.IsValid()) return false; if (!m_opaque_sp) return false; return m_opaque_sp->AppendIfUnique(sb_bkpt.GetSP()); } void SBBreakpointList::Clear() { LLDB_RECORD_METHOD_NO_ARGS(void, SBBreakpointList, Clear); if (m_opaque_sp) m_opaque_sp->Clear(); } void SBBreakpointList::CopyToBreakpointIDList( lldb_private::BreakpointIDList &bp_id_list) { if (m_opaque_sp) m_opaque_sp->CopyToBreakpointIDList(bp_id_list); } namespace lldb_private { namespace repro { template <> void RegisterMethods(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBBreakpoint, ()); LLDB_REGISTER_CONSTRUCTOR(SBBreakpoint, (const lldb::SBBreakpoint &)); LLDB_REGISTER_CONSTRUCTOR(SBBreakpoint, (const lldb::BreakpointSP &)); LLDB_REGISTER_METHOD(const lldb::SBBreakpoint &, SBBreakpoint, operator=,(const lldb::SBBreakpoint &)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, operator==,(const lldb::SBBreakpoint &)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, operator!=,(const lldb::SBBreakpoint &)); LLDB_REGISTER_METHOD_CONST(lldb::break_id_t, SBBreakpoint, GetID, ()); LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, IsValid, ()); LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, operator bool, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, ClearAllBreakpointSites, ()); LLDB_REGISTER_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, FindLocationByAddress, (lldb::addr_t)); LLDB_REGISTER_METHOD(lldb::break_id_t, SBBreakpoint, FindLocationIDByAddress, (lldb::addr_t)); LLDB_REGISTER_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, FindLocationByID, (lldb::break_id_t)); LLDB_REGISTER_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, GetLocationAtIndex, (uint32_t)); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetEnabled, (bool)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, IsEnabled, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetOneShot, (bool)); LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, IsOneShot, ()); LLDB_REGISTER_METHOD(bool, SBBreakpoint, IsInternal, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetIgnoreCount, (uint32_t)); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetCondition, (const char *)); LLDB_REGISTER_METHOD(const char *, SBBreakpoint, GetCondition, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetAutoContinue, (bool)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetAutoContinue, ()); LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetHitCount, ()); LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetIgnoreCount, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadID, (lldb::tid_t)); LLDB_REGISTER_METHOD(lldb::tid_t, SBBreakpoint, GetThreadID, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadIndex, (uint32_t)); LLDB_REGISTER_METHOD_CONST(uint32_t, SBBreakpoint, GetThreadIndex, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetThreadName, (const char *)); LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpoint, GetThreadName, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetQueueName, (const char *)); LLDB_REGISTER_METHOD_CONST(const char *, SBBreakpoint, GetQueueName, ()); LLDB_REGISTER_METHOD_CONST(size_t, SBBreakpoint, GetNumResolvedLocations, ()); LLDB_REGISTER_METHOD_CONST(size_t, SBBreakpoint, GetNumLocations, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetCommandLineCommands, (lldb::SBStringList &)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetCommandLineCommands, (lldb::SBStringList &)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetDescription, (lldb::SBStream &)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, GetDescription, (lldb::SBStream &, bool)); LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, AddLocation, (lldb::SBAddress &)); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetScriptCallbackFunction, (const char *)); LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackFunction, (const char *, SBStructuredData &)); LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackBody, (const char *)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, AddName, (const char *)); + LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, AddNameWithErrorHandling, + (const char *)); LLDB_REGISTER_METHOD(void, SBBreakpoint, RemoveName, (const char *)); LLDB_REGISTER_METHOD(bool, SBBreakpoint, MatchesName, (const char *)); LLDB_REGISTER_METHOD(void, SBBreakpoint, GetNames, (lldb::SBStringList &)); LLDB_REGISTER_STATIC_METHOD(bool, SBBreakpoint, EventIsBreakpointEvent, (const lldb::SBEvent &)); LLDB_REGISTER_STATIC_METHOD(lldb::BreakpointEventType, SBBreakpoint, GetBreakpointEventTypeFromEvent, (const lldb::SBEvent &)); LLDB_REGISTER_STATIC_METHOD(lldb::SBBreakpoint, SBBreakpoint, GetBreakpointFromEvent, (const lldb::SBEvent &)); LLDB_REGISTER_STATIC_METHOD(lldb::SBBreakpointLocation, SBBreakpoint, GetBreakpointLocationAtIndexFromEvent, (const lldb::SBEvent &, uint32_t)); LLDB_REGISTER_STATIC_METHOD(uint32_t, SBBreakpoint, GetNumBreakpointLocationsFromEvent, (const lldb::SBEvent &)); LLDB_REGISTER_METHOD_CONST(bool, SBBreakpoint, IsHardware, ()); } template <> void RegisterMethods(Registry &R) { LLDB_REGISTER_CONSTRUCTOR(SBBreakpointList, (lldb::SBTarget &)); LLDB_REGISTER_METHOD_CONST(size_t, SBBreakpointList, GetSize, ()); LLDB_REGISTER_METHOD(lldb::SBBreakpoint, SBBreakpointList, GetBreakpointAtIndex, (size_t)); LLDB_REGISTER_METHOD(lldb::SBBreakpoint, SBBreakpointList, FindBreakpointByID, (lldb::break_id_t)); LLDB_REGISTER_METHOD(void, SBBreakpointList, Append, (const lldb::SBBreakpoint &)); LLDB_REGISTER_METHOD(void, SBBreakpointList, AppendByID, (lldb::break_id_t)); LLDB_REGISTER_METHOD(bool, SBBreakpointList, AppendIfUnique, (const lldb::SBBreakpoint &)); LLDB_REGISTER_METHOD(void, SBBreakpointList, Clear, ()); } } } diff --git a/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py b/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py index 1212ad46d28f..2b37549249d9 100644 --- a/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py +++ b/lldb/test/API/functionalities/breakpoint/breakpoint_names/TestBreakpointNames.py @@ -1,370 +1,370 @@ """ Test breakpoint names. """ import os import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil class BreakpointNames(TestBase): mydir = TestBase.compute_mydir(__file__) NO_DEBUG_INFO_TESTCASE = True @add_test_categories(['pyapi']) def test_setting_names(self): """Use Python APIs to test that we can set breakpoint names.""" self.build() self.setup_target() self.do_check_names() def test_illegal_names(self): """Use Python APIs to test that we don't allow illegal names.""" self.build() self.setup_target() self.do_check_illegal_names() def test_using_names(self): """Use Python APIs to test that operations on names works correctly.""" self.build() self.setup_target() self.do_check_using_names() def test_configuring_names(self): """Use Python APIs to test that configuring options on breakpoint names works correctly.""" self.build() self.make_a_dummy_name() self.setup_target() self.do_check_configuring_names() def test_configuring_permissions_sb(self): """Use Python APIs to test that configuring permissions on names works correctly.""" self.build() self.setup_target() self.do_check_configuring_permissions_sb() def test_configuring_permissions_cli(self): """Use Python APIs to test that configuring permissions on names works correctly.""" self.build() self.setup_target() self.do_check_configuring_permissions_cli() def setup_target(self): exe = self.getBuildArtifact("a.out") # Create a targets we are making breakpoint in and copying to: self.target = self.dbg.CreateTarget(exe) self.assertTrue(self.target, VALID_TARGET) self.main_file_spec = lldb.SBFileSpec(os.path.join(self.getSourceDir(), "main.c")) def check_name_in_target(self, bkpt_name): name_list = lldb.SBStringList() self.target.GetBreakpointNames(name_list) found_it = False for name in name_list: if name == bkpt_name: found_it = True break self.assertTrue(found_it, "Didn't find the name %s in the target's name list:"%(bkpt_name)) def setUp(self): # Call super's setUp(). TestBase.setUp(self) # These are the settings we're going to be putting into names & breakpoints: self.bp_name_string = "ABreakpoint" self.is_one_shot = True self.ignore_count = 1000 self.condition = "1 == 2" self.auto_continue = True self.tid = 0xaaaa self.tidx = 10 self.thread_name = "Fooey" self.queue_name = "Blooey" self.cmd_list = lldb.SBStringList() self.cmd_list.AppendString("frame var") self.cmd_list.AppendString("bt") self.help_string = "I do something interesting" def do_check_names(self): """Use Python APIs to check that we can set & retrieve breakpoint names""" bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) bkpt_name = "ABreakpoint" other_bkpt_name = "_AnotherBreakpoint" # Add a name and make sure we match it: - success = bkpt.AddName(bkpt_name) - self.assertTrue(success, "We couldn't add a legal name to a breakpoint.") + success = bkpt.AddNameWithErrorHandling(bkpt_name) + self.assertSuccess(success, "We couldn't add a legal name to a breakpoint.") matches = bkpt.MatchesName(bkpt_name) self.assertTrue(matches, "We didn't match the name we just set") # Make sure we don't match irrelevant names: matches = bkpt.MatchesName("NotABreakpoint") self.assertTrue(not matches, "We matched a name we didn't set.") # Make sure the name is also in the target: self.check_name_in_target(bkpt_name) # Add another name, make sure that works too: - bkpt.AddName(other_bkpt_name) + bkpt.AddNameWithErrorHandling(other_bkpt_name) matches = bkpt.MatchesName(bkpt_name) self.assertTrue(matches, "Adding a name means we didn't match the name we just set") self.check_name_in_target(other_bkpt_name) # Remove the name and make sure we no longer match it: bkpt.RemoveName(bkpt_name) matches = bkpt.MatchesName(bkpt_name) self.assertTrue(not matches,"We still match a name after removing it.") # Make sure the name list has the remaining name: name_list = lldb.SBStringList() bkpt.GetNames(name_list) num_names = name_list.GetSize() self.assertTrue(num_names == 1, "Name list has %d items, expected 1."%(num_names)) name = name_list.GetStringAtIndex(0) self.assertTrue(name == other_bkpt_name, "Remaining name was: %s expected %s."%(name, other_bkpt_name)) def do_check_illegal_names(self): """Use Python APIs to check that we reject illegal names.""" bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) bad_names = ["-CantStartWithADash", "1CantStartWithANumber", "^CantStartWithNonAlpha", "CantHave-ADash", "Cant Have Spaces"] for bad_name in bad_names: - success = bkpt.AddName(bad_name) - self.assertTrue(not success,"We allowed an illegal name: %s"%(bad_name)) + success = bkpt.AddNameWithErrorHandling(bad_name) + self.assertTrue(success.Fail(), "We allowed an illegal name: %s"%(bad_name)) bp_name = lldb.SBBreakpointName(self.target, bad_name) self.assertFalse(bp_name.IsValid(), "We made a breakpoint name with an illegal name: %s"%(bad_name)); retval =lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand("break set -n whatever -N '%s'"%(bad_name), retval) self.assertTrue(not retval.Succeeded(), "break set succeeded with: illegal name: %s"%(bad_name)) def do_check_using_names(self): """Use Python APIs to check names work in place of breakpoint ID's.""" # Create a dummy breakpoint to use up ID 1 _ = self.target.BreakpointCreateByLocation(self.main_file_spec, 30) # Create a breakpiont to test with bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) bkpt_name = "ABreakpoint" bkpt_id = bkpt.GetID() other_bkpt_name= "_AnotherBreakpoint" # Add a name and make sure we match it: - success = bkpt.AddName(bkpt_name) - self.assertTrue(success, "We couldn't add a legal name to a breakpoint.") + success = bkpt.AddNameWithErrorHandling(bkpt_name) + self.assertSuccess(success, "We couldn't add a legal name to a breakpoint.") bkpts = lldb.SBBreakpointList(self.target) self.target.FindBreakpointsByName(bkpt_name, bkpts) self.assertTrue(bkpts.GetSize() == 1, "One breakpoint matched.") found_bkpt = bkpts.GetBreakpointAtIndex(0) self.assertTrue(bkpt.GetID() == found_bkpt.GetID(),"The right breakpoint.") self.assertTrue(bkpt.GetID() == bkpt_id,"With the same ID as before.") retval = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand("break disable %s"%(bkpt_name), retval) self.assertTrue(retval.Succeeded(), "break disable failed with: %s."%(retval.GetError())) self.assertTrue(not bkpt.IsEnabled(), "We didn't disable the breakpoint.") # Also make sure we don't apply commands to non-matching names: self.dbg.GetCommandInterpreter().HandleCommand("break modify --one-shot 1 %s"%(other_bkpt_name), retval) self.assertTrue(retval.Succeeded(), "break modify failed with: %s."%(retval.GetError())) self.assertTrue(not bkpt.IsOneShot(), "We applied one-shot to the wrong breakpoint.") def check_option_values(self, bp_object): self.assertEqual(bp_object.IsOneShot(), self.is_one_shot, "IsOneShot") self.assertEqual(bp_object.GetIgnoreCount(), self.ignore_count, "IgnoreCount") self.assertEqual(bp_object.GetCondition(), self.condition, "Condition") self.assertEqual(bp_object.GetAutoContinue(), self.auto_continue, "AutoContinue") self.assertEqual(bp_object.GetThreadID(), self.tid, "Thread ID") self.assertEqual(bp_object.GetThreadIndex(), self.tidx, "Thread Index") self.assertEqual(bp_object.GetThreadName(), self.thread_name, "Thread Name") self.assertEqual(bp_object.GetQueueName(), self.queue_name, "Queue Name") set_cmds = lldb.SBStringList() bp_object.GetCommandLineCommands(set_cmds) self.assertEqual(set_cmds.GetSize(), self.cmd_list.GetSize(), "Size of command line commands") for idx in range(0, set_cmds.GetSize()): self.assertEqual(self.cmd_list.GetStringAtIndex(idx), set_cmds.GetStringAtIndex(idx), "Command %d"%(idx)) def make_a_dummy_name(self): "This makes a breakpoint name in the dummy target to make sure it gets copied over" dummy_target = self.dbg.GetDummyTarget() self.assertTrue(dummy_target.IsValid(), "Dummy target was not valid.") def cleanup (): self.dbg.GetDummyTarget().DeleteBreakpointName(self.bp_name_string) # Execute the cleanup function during test case tear down. self.addTearDownHook(cleanup) # Now find it in the dummy target, and make sure these settings took: bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) # Make sure the name is right: self.assertTrue (bp_name.GetName() == self.bp_name_string, "Wrong bp_name: %s"%(bp_name.GetName())) bp_name.SetOneShot(self.is_one_shot) bp_name.SetIgnoreCount(self.ignore_count) bp_name.SetCondition(self.condition) bp_name.SetAutoContinue(self.auto_continue) bp_name.SetThreadID(self.tid) bp_name.SetThreadIndex(self.tidx) bp_name.SetThreadName(self.thread_name) bp_name.SetQueueName(self.queue_name) bp_name.SetCommandLineCommands(self.cmd_list) # Now look it up again, and make sure it got set correctly. bp_name = lldb.SBBreakpointName(dummy_target, self.bp_name_string) self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") self.check_option_values(bp_name) def do_check_configuring_names(self): """Use Python APIs to check that configuring breakpoint names works correctly.""" other_bp_name_string = "AnotherBreakpointName" cl_bp_name_string = "CLBreakpointName" # Now find the version copied in from the dummy target, and make sure these settings took: bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name.") self.check_option_values(bp_name) # Now add this name to a breakpoint, and make sure it gets configured properly bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) - success = bkpt.AddName(self.bp_name_string) - self.assertTrue(success, "Couldn't add this name to the breakpoint") + success = bkpt.AddNameWithErrorHandling(self.bp_name_string) + self.assertSuccess(success, "Couldn't add this name to the breakpoint") self.check_option_values(bkpt) # Now make a name from this breakpoint, and make sure the new name is properly configured: new_name = lldb.SBBreakpointName(bkpt, other_bp_name_string) self.assertTrue(new_name.IsValid(), "Couldn't make a valid bp_name from a breakpoint.") self.check_option_values(bkpt) # Now change the name's option and make sure it gets propagated to # the breakpoint: new_auto_continue = not self.auto_continue bp_name.SetAutoContinue(new_auto_continue) self.assertEqual(bp_name.GetAutoContinue(), new_auto_continue, "Couldn't change auto-continue on the name") self.assertEqual(bkpt.GetAutoContinue(), new_auto_continue, "Option didn't propagate to the breakpoint.") # Now make this same breakpoint name - but from the command line cmd_str = "breakpoint name configure %s -o %d -i %d -c '%s' -G %d -t %d -x %d -T '%s' -q '%s' -H '%s'"%(cl_bp_name_string, self.is_one_shot, self.ignore_count, self.condition, self.auto_continue, self.tid, self.tidx, self.thread_name, self.queue_name, self.help_string) for cmd in self.cmd_list: cmd_str += " -C '%s'"%(cmd) self.runCmd(cmd_str, check=True) # Now look up this name again and check its options: cl_name = lldb.SBBreakpointName(self.target, cl_bp_name_string) self.check_option_values(cl_name) # Also check the help string: self.assertEqual(self.help_string, cl_name.GetHelpString(), "Help string didn't match") # Change the name and make sure that works: new_help = "I do something even more interesting" cl_name.SetHelpString(new_help) self.assertEqual(new_help, cl_name.GetHelpString(), "SetHelpString didn't") # We should have three names now, make sure the target can list them: name_list = lldb.SBStringList() self.target.GetBreakpointNames(name_list) for name_string in [self.bp_name_string, other_bp_name_string, cl_bp_name_string]: self.assertTrue(name_string in name_list, "Didn't find %s in names"%(name_string)) # Delete the name from the current target. Make sure that works and deletes the # name from the breakpoint as well: self.target.DeleteBreakpointName(self.bp_name_string) name_list.Clear() self.target.GetBreakpointNames(name_list) self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from a real target"%(self.bp_name_string)) # Also make sure the name got removed from breakpoints holding it: self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") # Test that deleting the name we injected into the dummy target works (there's also a # cleanup that will do this, but that won't test the result... dummy_target = self.dbg.GetDummyTarget() dummy_target.DeleteBreakpointName(self.bp_name_string) name_list.Clear() dummy_target.GetBreakpointNames(name_list) self.assertTrue(self.bp_name_string not in name_list, "Didn't delete %s from the dummy target"%(self.bp_name_string)) # Also make sure the name got removed from breakpoints holding it: self.assertFalse(bkpt.MatchesName(self.bp_name_string), "Didn't remove the name from the breakpoint.") def check_permission_results(self, bp_name): self.assertEqual(bp_name.GetAllowDelete(), False, "Didn't set allow delete.") protected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) protected_id = protected_bkpt.GetID() unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) unprotected_id = unprotected_bkpt.GetID() - success = protected_bkpt.AddName(self.bp_name_string) - self.assertTrue(success, "Couldn't add this name to the breakpoint") + success = protected_bkpt.AddNameWithErrorHandling(self.bp_name_string) + self.assertSuccess(success, "Couldn't add this name to the breakpoint") self.target.DisableAllBreakpoints() self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") # Try from the command line too: unprotected_bkpt.SetEnabled(True) result = lldb.SBCommandReturnObject() self.dbg.GetCommandInterpreter().HandleCommand("break disable", result) self.assertTrue(result.Succeeded()) self.assertEqual(protected_bkpt.IsEnabled(), True, "Didnt' keep breakpoint from being disabled") self.assertEqual(unprotected_bkpt.IsEnabled(), False, "Protected too many breakpoints from disabling.") self.target.DeleteAllBreakpoints() bkpt = self.target.FindBreakpointByID(protected_id) self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") bkpt = self.target.FindBreakpointByID(unprotected_id) self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") # Remake the unprotected breakpoint and try again from the command line: unprotected_bkpt = self.target.BreakpointCreateByLocation(self.main_file_spec, 10) unprotected_id = unprotected_bkpt.GetID() self.dbg.GetCommandInterpreter().HandleCommand("break delete -f", result) self.assertTrue(result.Succeeded()) bkpt = self.target.FindBreakpointByID(protected_id) self.assertTrue(bkpt.IsValid(), "Didn't keep the breakpoint from being deleted.") bkpt = self.target.FindBreakpointByID(unprotected_id) self.assertFalse(bkpt.IsValid(), "Protected too many breakpoints from deletion.") def do_check_configuring_permissions_sb(self): bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) # Make a breakpoint name with delete disallowed: bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) self.assertTrue(bp_name.IsValid(), "Failed to make breakpoint name for valid name.") bp_name.SetAllowDelete(False) bp_name.SetAllowDisable(False) bp_name.SetAllowList(False) self.check_permission_results(bp_name) def do_check_configuring_permissions_cli(self): # Make the name with the right options using the command line: self.runCmd("breakpoint name configure -L 0 -D 0 -A 0 %s"%(self.bp_name_string), check=True) # Now look up the breakpoint we made, and check that it works. bp_name = lldb.SBBreakpointName(self.target, self.bp_name_string) self.assertTrue(bp_name.IsValid(), "Didn't make a breakpoint name we could find.") self.check_permission_results(bp_name)