Skip to content

Commit 180e736

Browse files
committed
[lldb] Expose the Target API lock through the SB API
1 parent 029cb8a commit 180e736

File tree

13 files changed

+241
-22
lines changed

13 files changed

+241
-22
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
%extend lldb::SBLock {
2+
#ifdef SWIGPYTHON
3+
%pythoncode %{
4+
def __enter__(self):
5+
return self
6+
7+
def __exit__(self, exc_type, exc_value, traceback):
8+
self.Unlock()
9+
%}
10+
#endif
11+
}

lldb/bindings/interfaces.swig

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
%include "./interface/SBLaunchInfoDocstrings.i"
4848
%include "./interface/SBLineEntryDocstrings.i"
4949
%include "./interface/SBListenerDocstrings.i"
50+
%include "./interface/SBLockExtensions.i"
5051
%include "./interface/SBMemoryRegionInfoDocstrings.i"
5152
%include "./interface/SBMemoryRegionInfoListDocstrings.i"
5253
%include "./interface/SBModuleDocstrings.i"
@@ -121,11 +122,12 @@
121122
%include "lldb/API/SBHostOS.h"
122123
%include "lldb/API/SBInstruction.h"
123124
%include "lldb/API/SBInstructionList.h"
124-
%include "lldb/API/SBLanguages.h"
125125
%include "lldb/API/SBLanguageRuntime.h"
126+
%include "lldb/API/SBLanguages.h"
126127
%include "lldb/API/SBLaunchInfo.h"
127128
%include "lldb/API/SBLineEntry.h"
128129
%include "lldb/API/SBListener.h"
130+
%include "lldb/API/SBLock.h"
129131
%include "lldb/API/SBMemoryRegionInfo.h"
130132
%include "lldb/API/SBMemoryRegionInfoList.h"
131133
%include "lldb/API/SBModule.h"

lldb/include/lldb/API/LLDB.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
#include "lldb/API/SBLaunchInfo.h"
4747
#include "lldb/API/SBLineEntry.h"
4848
#include "lldb/API/SBListener.h"
49+
#include "lldb/API/SBLock.h"
4950
#include "lldb/API/SBMemoryRegionInfo.h"
5051
#include "lldb/API/SBMemoryRegionInfoList.h"
5152
#include "lldb/API/SBModule.h"

lldb/include/lldb/API/SBDefines.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ class LLDB_API SBLanguageRuntime;
8484
class LLDB_API SBLaunchInfo;
8585
class LLDB_API SBLineEntry;
8686
class LLDB_API SBListener;
87+
class LLDB_API SBLock;
8788
class LLDB_API SBMemoryRegionInfo;
8889
class LLDB_API SBMemoryRegionInfoList;
8990
class LLDB_API SBModule;

lldb/include/lldb/API/SBLock.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===-- SBLock.h ----------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_API_SBLOCK_H
10+
#define LLDB_API_SBLOCK_H
11+
12+
#include "lldb/API/SBDefines.h"
13+
#include "lldb/lldb-forward.h"
14+
#include <mutex>
15+
16+
namespace lldb_private {
17+
class APILock;
18+
}
19+
20+
namespace lldb {
21+
22+
class LLDB_API SBLock {
23+
public:
24+
SBLock();
25+
SBLock(SBLock &&rhs);
26+
SBLock &operator=(SBLock &&rhs);
27+
~SBLock();
28+
29+
bool IsValid() const;
30+
31+
void Unlock() const;
32+
33+
private:
34+
// Private constructor used by SBTarget to create the Target API lock.
35+
// Requires a friend declaration.
36+
SBLock(lldb::TargetSP target_sp);
37+
friend class SBTarget;
38+
39+
SBLock(const SBLock &rhs) = delete;
40+
const SBLock &operator=(const SBLock &rhs) = delete;
41+
42+
std::unique_ptr<lldb_private::APILock> m_opaque_up;
43+
};
44+
#endif
45+
46+
} // namespace lldb

lldb/include/lldb/API/SBTarget.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ class LLDB_API SBTarget {
342342
uint32_t GetAddressByteSize();
343343

344344
const char *GetTriple();
345-
345+
346346
const char *GetABIName();
347347

348348
const char *GetLabel() const;
@@ -946,6 +946,8 @@ class LLDB_API SBTarget {
946946
/// An error if a Trace already exists or the trace couldn't be created.
947947
lldb::SBTrace CreateTrace(SBError &error);
948948

949+
lldb::SBLock AcquireAPILock() const;
950+
949951
protected:
950952
friend class SBAddress;
951953
friend class SBAddressRange;

lldb/include/lldb/Target/Target.h

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1327,7 +1327,7 @@ class Target : public std::enable_shared_from_this<Target>,
13271327
StopHook(const StopHook &rhs);
13281328
virtual ~StopHook() = default;
13291329

1330-
enum class StopHookKind : uint32_t { CommandBased = 0, ScriptBased };
1330+
enum class StopHookKind : uint32_t { CommandBased = 0, ScriptBased };
13311331
enum class StopHookResult : uint32_t {
13321332
KeepStopped = 0,
13331333
RequestContinue,
@@ -1692,6 +1692,21 @@ class Target : public std::enable_shared_from_this<Target>,
16921692
}
16931693
};
16941694

1695+
/// The private implementation backing SBLock.
1696+
class APILock {
1697+
public:
1698+
APILock(std::shared_ptr<std::recursive_mutex> mutex_sp)
1699+
: m_mutex(std::move(mutex_sp)), m_lock(*m_mutex) {}
1700+
1701+
void Unlock() { m_lock.unlock(); }
1702+
1703+
operator bool() const { return static_cast<bool>(m_lock); }
1704+
1705+
private:
1706+
std::shared_ptr<std::recursive_mutex> m_mutex;
1707+
std::unique_lock<std::recursive_mutex> m_lock;
1708+
};
1709+
16951710
} // namespace lldb_private
16961711

16971712
#endif // LLDB_TARGET_TARGET_H

lldb/source/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ add_lldb_library(liblldb SHARED ${option_framework}
7777
SBLaunchInfo.cpp
7878
SBLineEntry.cpp
7979
SBListener.cpp
80+
SBLock.cpp
8081
SBMemoryRegionInfo.cpp
8182
SBMemoryRegionInfoList.cpp
8283
SBModule.cpp

lldb/source/API/SBLock.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===-- SBLock.cpp --------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "lldb/API/SBLock.h"
10+
#include "lldb/Target/Target.h"
11+
#include "lldb/Utility/Instrumentation.h"
12+
#include "lldb/lldb-forward.h"
13+
#include <memory>
14+
#include <mutex>
15+
16+
using namespace lldb;
17+
using namespace lldb_private;
18+
19+
SBLock::SBLock() { LLDB_INSTRUMENT_VA(this); }
20+
21+
SBLock::SBLock(SBLock &&rhs) : m_opaque_up(std::move(rhs.m_opaque_up)) {
22+
LLDB_INSTRUMENT_VA(this);
23+
}
24+
25+
SBLock &SBLock::operator=(SBLock &&rhs) {
26+
LLDB_INSTRUMENT_VA(this);
27+
28+
m_opaque_up = std::move(rhs.m_opaque_up);
29+
return *this;
30+
}
31+
32+
SBLock::SBLock(lldb::TargetSP target_sp)
33+
: m_opaque_up(
34+
std::make_unique<APILock>(std::shared_ptr<std::recursive_mutex>(
35+
target_sp, &target_sp->GetAPIMutex()))) {
36+
LLDB_INSTRUMENT_VA(this, target_sp);
37+
}
38+
39+
SBLock::~SBLock() { LLDB_INSTRUMENT_VA(this); }
40+
41+
bool SBLock::IsValid() const {
42+
LLDB_INSTRUMENT_VA(this);
43+
44+
return static_cast<bool>(m_opaque_up) && static_cast<bool>(*m_opaque_up);
45+
}
46+
47+
void SBLock::Unlock() const {
48+
LLDB_INSTRUMENT_VA(this);
49+
50+
if (m_opaque_up)
51+
m_opaque_up->Unlock();
52+
}

lldb/source/API/SBTarget.cpp

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "lldb/API/SBTarget.h"
10-
#include "lldb/Utility/Instrumentation.h"
11-
#include "lldb/Utility/LLDBLog.h"
12-
#include "lldb/lldb-public.h"
13-
1410
#include "lldb/API/SBBreakpoint.h"
1511
#include "lldb/API/SBDebugger.h"
1612
#include "lldb/API/SBEnvironment.h"
1713
#include "lldb/API/SBEvent.h"
1814
#include "lldb/API/SBExpressionOptions.h"
1915
#include "lldb/API/SBFileSpec.h"
2016
#include "lldb/API/SBListener.h"
17+
#include "lldb/API/SBLock.h"
2118
#include "lldb/API/SBModule.h"
2219
#include "lldb/API/SBModuleSpec.h"
2320
#include "lldb/API/SBProcess.h"
@@ -58,11 +55,14 @@
5855
#include "lldb/Utility/ArchSpec.h"
5956
#include "lldb/Utility/Args.h"
6057
#include "lldb/Utility/FileSpec.h"
58+
#include "lldb/Utility/Instrumentation.h"
59+
#include "lldb/Utility/LLDBLog.h"
6160
#include "lldb/Utility/ProcessInfo.h"
6261
#include "lldb/Utility/RegularExpression.h"
6362
#include "lldb/ValueObject/ValueObjectConstResult.h"
6463
#include "lldb/ValueObject/ValueObjectList.h"
6564
#include "lldb/ValueObject/ValueObjectVariable.h"
65+
#include "lldb/lldb-public.h"
6666

6767
#include "Commands/CommandObjectBreakpoint.h"
6868
#include "lldb/Interpreter/CommandReturnObject.h"
@@ -544,9 +544,8 @@ lldb::SBProcess SBTarget::ConnectRemote(SBListener &listener, const char *url,
544544
if (target_sp) {
545545
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
546546
if (listener.IsValid())
547-
process_sp =
548-
target_sp->CreateProcess(listener.m_opaque_sp, plugin_name, nullptr,
549-
true);
547+
process_sp = target_sp->CreateProcess(listener.m_opaque_sp, plugin_name,
548+
nullptr, true);
550549
else
551550
process_sp = target_sp->CreateProcess(
552551
target_sp->GetDebugger().GetListener(), plugin_name, nullptr, true);
@@ -1040,7 +1039,7 @@ SBTarget::BreakpointCreateForException(lldb::LanguageType language,
10401039
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
10411040
const bool hardware = false;
10421041
sb_bp = target_sp->CreateExceptionBreakpoint(language, catch_bp, throw_bp,
1043-
hardware);
1042+
hardware);
10441043
}
10451044

10461045
return sb_bp;
@@ -1060,14 +1059,9 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateFromScript(
10601059
Status error;
10611060

10621061
StructuredData::ObjectSP obj_sp = extra_args.m_impl_up->GetObjectSP();
1063-
sb_bp =
1064-
target_sp->CreateScriptedBreakpoint(class_name,
1065-
module_list.get(),
1066-
file_list.get(),
1067-
false, /* internal */
1068-
request_hardware,
1069-
obj_sp,
1070-
&error);
1062+
sb_bp = target_sp->CreateScriptedBreakpoint(
1063+
class_name, module_list.get(), file_list.get(), false, /* internal */
1064+
request_hardware, obj_sp, &error);
10711065
}
10721066

10731067
return sb_bp;
@@ -1692,8 +1686,8 @@ uint32_t SBTarget::GetMaximumNumberOfChildrenToDisplay() const {
16921686
LLDB_INSTRUMENT_VA(this);
16931687

16941688
TargetSP target_sp(GetSP());
1695-
if(target_sp){
1696-
return target_sp->GetMaximumNumberOfChildrenToDisplay();
1689+
if (target_sp) {
1690+
return target_sp->GetMaximumNumberOfChildrenToDisplay();
16971691
}
16981692
return 0;
16991693
}
@@ -2193,7 +2187,7 @@ SBError SBTarget::SetModuleLoadAddress(lldb::SBModule module,
21932187
}
21942188

21952189
SBError SBTarget::SetModuleLoadAddress(lldb::SBModule module,
2196-
uint64_t slide_offset) {
2190+
uint64_t slide_offset) {
21972191

21982192
SBError sb_error;
21992193

@@ -2439,3 +2433,11 @@ lldb::SBTrace SBTarget::CreateTrace(lldb::SBError &error) {
24392433
}
24402434
return SBTrace();
24412435
}
2436+
2437+
lldb::SBLock SBTarget::AcquireAPILock() const {
2438+
LLDB_INSTRUMENT_VA(this);
2439+
2440+
if (TargetSP target_sp = GetSP())
2441+
return lldb::SBLock(target_sp);
2442+
return lldb::SBLock();
2443+
}

lldb/test/API/python_api/target/TestTargetAPI.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,3 +537,31 @@ def test_setting_selected_target_with_invalid_target(self):
537537
"""Make sure we don't crash when trying to select invalid target."""
538538
target = lldb.SBTarget()
539539
self.dbg.SetSelectedTarget(target)
540+
541+
@no_debug_info_test
542+
def test_acquire_sblock(self):
543+
"""Make sure we can acquire the API lock from Python."""
544+
target = self.dbg.GetDummyTarget()
545+
546+
lock = target.AcquireAPILock()
547+
self.assertTrue(lock.IsValid())
548+
# The API call below doesn't actually matter, it's just there to
549+
# confirm we don't block on the API lock.
550+
target.BreakpointCreateByName("foo", "bar")
551+
lock.Unlock()
552+
self.assertFalse(lock.IsValid())
553+
554+
@no_debug_info_test
555+
def test_acquire_sblock_with_statement(self):
556+
"""Make sure we can acquire the API lock using a with-statement from Python."""
557+
target = self.dbg.GetDummyTarget()
558+
559+
lock_copy = None
560+
with target.AcquireAPILock() as lock:
561+
self.assertTrue(lock.IsValid())
562+
# The API call below doesn't actually matter, it's just there to
563+
# confirm we don't block on the API lock.
564+
target.BreakpointCreateByName("foo", "bar")
565+
lock_copy = lock
566+
self.assertTrue(lock.IsValid())
567+
self.assertFalse(lock_copy.IsValid())

lldb/unittests/API/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
add_lldb_unittest(APITests
22
SBCommandInterpreterTest.cpp
33
SBLineEntryTest.cpp
4+
SBLockTest.cpp
45

56
LINK_LIBS
67
liblldb

0 commit comments

Comments
 (0)