Skip to content

Commit 096db03

Browse files
authored
Merge pull request #6316 from jasonmolenda/r101426626-watchpoint-behavior-in-lldb-now
[LLDB] add arch-specific watchpoint behavior defaults to lldb
2 parents b4b2e26 + 944ca8c commit 096db03

File tree

13 files changed

+108
-104
lines changed

13 files changed

+108
-104
lines changed

lldb/include/lldb/Target/Process.h

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <list>
1818
#include <memory>
1919
#include <mutex>
20+
#include <optional>
2021
#include <string>
2122
#include <unordered_set>
2223
#include <vector>
@@ -1834,20 +1835,35 @@ class Process : public std::enable_shared_from_this<Process>,
18341835
virtual Status
18351836
GetMemoryRegions(lldb_private::MemoryRegionInfos &region_list);
18361837

1837-
virtual Status GetWatchpointSupportInfo(uint32_t &num) {
1838-
Status error;
1839-
num = 0;
1840-
error.SetErrorString("Process::GetWatchpointSupportInfo() not supported");
1841-
return error;
1838+
/// Get the number of watchpoints supported by this target.
1839+
///
1840+
/// We may be able to determine the number of watchpoints available
1841+
/// on this target; retrieve this value if possible.
1842+
///
1843+
/// This number may be less than the number of watchpoints a user
1844+
/// can specify. This is because a single user watchpoint may require
1845+
/// multiple watchpoint slots to implement. Due to the size
1846+
/// and/or alignment of objects.
1847+
///
1848+
/// \return
1849+
/// Returns the number of watchpoints, if available.
1850+
virtual std::optional<uint32_t> GetWatchpointSlotCount() {
1851+
return std::nullopt;
18421852
}
18431853

1844-
virtual Status GetWatchpointSupportInfo(uint32_t &num, bool &after) {
1845-
Status error;
1846-
num = 0;
1847-
after = true;
1848-
error.SetErrorString("Process::GetWatchpointSupportInfo() not supported");
1849-
return error;
1850-
}
1854+
/// Whether lldb will be notified about watchpoints after
1855+
/// the instruction has completed executing, or if the
1856+
/// instruction is rolled back and it is notified before it
1857+
/// executes.
1858+
/// The default behavior is "exceptions received after instruction
1859+
/// has executed", except for certain CPU architectures.
1860+
/// Process subclasses may override this if they have additional
1861+
/// information.
1862+
///
1863+
/// \return
1864+
/// Returns true for targets where lldb is notified after
1865+
/// the instruction has completed executing.
1866+
bool GetWatchpointReportedAfter();
18511867

18521868
lldb::ModuleSP ReadModuleFromMemory(const FileSpec &file_spec,
18531869
lldb::addr_t header_addr,
@@ -2698,6 +2714,24 @@ void PruneThreadPlans();
26982714
return Status("Process::DoGetMemoryRegionInfo() not supported");
26992715
}
27002716

2717+
/// Provide an override value in the subclass for lldb's
2718+
/// CPU-based logic for whether watchpoint exceptions are
2719+
/// received before or after an instruction executes.
2720+
///
2721+
/// If a Process subclass needs to override this architecture-based
2722+
/// result, it may do so by overriding this method.
2723+
///
2724+
/// \return
2725+
/// No boolean returned means there is no override of the
2726+
/// default architecture-based behavior.
2727+
/// true is returned for targets where watchpoints are reported
2728+
/// after the instruction has completed.
2729+
/// false is returned for targets where watchpoints are reported
2730+
/// before the instruction executes.
2731+
virtual std::optional<bool> DoGetWatchpointReportedAfter() {
2732+
return std::nullopt;
2733+
}
2734+
27012735
lldb::StateType GetPrivateState();
27022736

27032737
/// The "private" side of resuming a process. This doesn't alter the state

lldb/source/API/SBProcess.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,12 @@ SBProcess::GetNumSupportedHardwareWatchpoints(lldb::SBError &sb_error) const {
967967
if (process_sp) {
968968
std::lock_guard<std::recursive_mutex> guard(
969969
process_sp->GetTarget().GetAPIMutex());
970-
sb_error.SetError(process_sp->GetWatchpointSupportInfo(num));
970+
std::optional<uint32_t> actual_num = process_sp->GetWatchpointSlotCount();
971+
if (actual_num) {
972+
num = *actual_num;
973+
} else {
974+
sb_error.SetErrorString("Unable to determine number of watchpoints");
975+
}
971976
} else {
972977
sb_error.SetErrorString("SBProcess is invalid");
973978
}

lldb/source/Commands/CommandObjectWatchpoint.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,13 @@ class CommandObjectWatchpointList : public CommandObjectParsed {
209209
Target *target = &GetSelectedTarget();
210210

211211
if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) {
212-
uint32_t num_supported_hardware_watchpoints;
213-
Status error = target->GetProcessSP()->GetWatchpointSupportInfo(
214-
num_supported_hardware_watchpoints);
215-
if (error.Success())
212+
std::optional<uint32_t> num_supported_hardware_watchpoints =
213+
target->GetProcessSP()->GetWatchpointSlotCount();
214+
215+
if (num_supported_hardware_watchpoints)
216216
result.AppendMessageWithFormat(
217217
"Number of supported hardware watchpoints: %u\n",
218-
num_supported_hardware_watchpoints);
218+
*num_supported_hardware_watchpoints);
219219
}
220220

221221
const WatchpointList &watchpoints = target->GetWatchpointList();

lldb/source/Plugins/Process/Windows/Common/ProcessWindows.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -835,15 +835,8 @@ void ProcessWindows::OnDebuggerError(const Status &error, uint32_t type) {
835835
}
836836
}
837837

838-
Status ProcessWindows::GetWatchpointSupportInfo(uint32_t &num) {
839-
num = RegisterContextWindows::GetNumHardwareBreakpointSlots();
840-
return {};
841-
}
842-
843-
Status ProcessWindows::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
844-
num = RegisterContextWindows::GetNumHardwareBreakpointSlots();
845-
after = RegisterContextWindows::DoHardwareBreakpointsTriggerAfter();
846-
return {};
838+
std::optional<uint32_t> ProcessWindows::GetWatchpointSlotCount() {
839+
return RegisterContextWindows::GetNumHardwareBreakpointSlots();
847840
}
848841

849842
Status ProcessWindows::EnableWatchpoint(Watchpoint *wp, bool notify) {

lldb/source/Plugins/Process/Windows/Common/ProcessWindows.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ class ProcessWindows : public Process, public ProcessDebugger {
9595
void OnDebugString(const std::string &string) override;
9696
void OnDebuggerError(const Status &error, uint32_t type) override;
9797

98-
Status GetWatchpointSupportInfo(uint32_t &num) override;
99-
Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
98+
std::optional<uint32_t> GetWatchpointSlotCount() override;
10099
Status EnableWatchpoint(Watchpoint *wp, bool notify = true) override;
101100
Status DisableWatchpoint(Watchpoint *wp, bool notify = true) override;
102101

lldb/source/Plugins/Process/Windows/Common/RegisterContextWindows.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ class RegisterContextWindows : public lldb_private::RegisterContext {
3838
static constexpr uint32_t GetNumHardwareBreakpointSlots() {
3939
return NUM_HARDWARE_BREAKPOINT_SLOTS;
4040
}
41-
static constexpr bool DoHardwareBreakpointsTriggerAfter() { return true; }
4241

4342
bool AddHardwareBreakpoint(uint32_t slot, lldb::addr_t address, uint32_t size,
4443
bool read, bool write);

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp

Lines changed: 18 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,77 +1773,51 @@ Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
17731773
return error;
17741774
}
17751775

1776-
Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
1777-
Status error;
1778-
1776+
std::optional<uint32_t> GDBRemoteCommunicationClient::GetWatchpointSlotCount() {
17791777
if (m_supports_watchpoint_support_info == eLazyBoolYes) {
1780-
num = m_num_supported_hardware_watchpoints;
1781-
return error;
1778+
return m_num_supported_hardware_watchpoints;
17821779
}
17831780

1784-
// Set num to 0 first.
1785-
num = 0;
1781+
std::optional<uint32_t> num;
17861782
if (m_supports_watchpoint_support_info != eLazyBoolNo) {
17871783
StringExtractorGDBRemote response;
17881784
if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
17891785
PacketResult::Success) {
17901786
m_supports_watchpoint_support_info = eLazyBoolYes;
17911787
llvm::StringRef name;
17921788
llvm::StringRef value;
1793-
bool found_num_field = false;
17941789
while (response.GetNameColonValue(name, value)) {
17951790
if (name.equals("num")) {
17961791
value.getAsInteger(0, m_num_supported_hardware_watchpoints);
17971792
num = m_num_supported_hardware_watchpoints;
1798-
found_num_field = true;
17991793
}
18001794
}
1801-
if (!found_num_field) {
1795+
if (!num) {
18021796
m_supports_watchpoint_support_info = eLazyBoolNo;
18031797
}
18041798
} else {
18051799
m_supports_watchpoint_support_info = eLazyBoolNo;
18061800
}
18071801
}
18081802

1809-
if (m_supports_watchpoint_support_info == eLazyBoolNo) {
1810-
error.SetErrorString("qWatchpointSupportInfo is not supported");
1811-
}
1812-
return error;
1813-
}
1814-
1815-
lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(
1816-
uint32_t &num, bool &after, const ArchSpec &arch) {
1817-
Status error(GetWatchpointSupportInfo(num));
1818-
if (error.Success())
1819-
error = GetWatchpointsTriggerAfterInstruction(after, arch);
1820-
return error;
1803+
return num;
18211804
}
18221805

1823-
lldb_private::Status
1824-
GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
1825-
bool &after, const ArchSpec &arch) {
1826-
Status error;
1827-
llvm::Triple triple = arch.GetTriple();
1828-
1829-
// we assume watchpoints will happen after running the relevant opcode and we
1830-
// only want to override this behavior if we have explicitly received a
1831-
// qHostInfo telling us otherwise
1832-
if (m_qHostInfo_is_valid != eLazyBoolYes) {
1833-
// On targets like MIPS and ppc64, watchpoint exceptions are always
1834-
// generated before the instruction is executed. The connected target may
1835-
// not support qHostInfo or qWatchpointSupportInfo packets.
1836-
after = !(triple.isMIPS() || triple.isPPC64());
1837-
} else {
1838-
// For MIPS and ppc64, set m_watchpoints_trigger_after_instruction to
1839-
// eLazyBoolNo if it is not calculated before.
1840-
if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
1841-
(triple.isMIPS() || triple.isPPC64()))
1842-
m_watchpoints_trigger_after_instruction = eLazyBoolNo;
1806+
std::optional<bool> GDBRemoteCommunicationClient::GetWatchpointReportedAfter() {
1807+
if (m_qHostInfo_is_valid == eLazyBoolCalculate)
1808+
GetHostInfo();
18431809

1844-
after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
1810+
// Process determines this by target CPU, but allow for the
1811+
// remote stub to override it via the qHostInfo
1812+
// watchpoint_exceptions_received key, if it is present.
1813+
if (m_qHostInfo_is_valid == eLazyBoolYes) {
1814+
if (m_watchpoints_trigger_after_instruction == eLazyBoolNo)
1815+
return false;
1816+
if (m_watchpoints_trigger_after_instruction == eLazyBoolYes)
1817+
return true;
18451818
}
1846-
return error;
1819+
1820+
return std::nullopt;
18471821
}
18481822

18491823
int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {

lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
194194

195195
Status GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info);
196196

197-
Status GetWatchpointSupportInfo(uint32_t &num);
197+
std::optional<uint32_t> GetWatchpointSlotCount();
198198

199-
Status GetWatchpointSupportInfo(uint32_t &num, bool &after,
200-
const ArchSpec &arch);
201-
202-
Status GetWatchpointsTriggerAfterInstruction(bool &after,
203-
const ArchSpec &arch);
199+
std::optional<bool> GetWatchpointReportedAfter();
204200

205201
const ArchSpec &GetHostArchitecture();
206202

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,16 +2830,12 @@ Status ProcessGDBRemote::DoGetMemoryRegionInfo(addr_t load_addr,
28302830
return error;
28312831
}
28322832

2833-
Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) {
2834-
2835-
Status error(m_gdb_comm.GetWatchpointSupportInfo(num));
2836-
return error;
2833+
std::optional<uint32_t> ProcessGDBRemote::GetWatchpointSlotCount() {
2834+
return m_gdb_comm.GetWatchpointSlotCount();
28372835
}
28382836

2839-
Status ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
2840-
Status error(m_gdb_comm.GetWatchpointSupportInfo(
2841-
num, after, GetTarget().GetArchitecture()));
2842-
return error;
2837+
std::optional<bool> ProcessGDBRemote::DoGetWatchpointReportedAfter() {
2838+
return m_gdb_comm.GetWatchpointReportedAfter();
28432839
}
28442840

28452841
Status ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class ProcessGDBRemote : public Process,
158158

159159
Status DisableWatchpoint(Watchpoint *wp, bool notify = true) override;
160160

161-
Status GetWatchpointSupportInfo(uint32_t &num) override;
161+
std::optional<uint32_t> GetWatchpointSlotCount() override;
162162

163163
llvm::Expected<TraceSupportedResponse> TraceSupported() override;
164164

@@ -171,7 +171,7 @@ class ProcessGDBRemote : public Process,
171171
llvm::Expected<std::vector<uint8_t>>
172172
TraceGetBinaryData(const TraceGetBinaryDataRequest &request) override;
173173

174-
Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
174+
std::optional<bool> DoGetWatchpointReportedAfter() override;
175175

176176
bool StartNoticingNewThreads() override;
177177

0 commit comments

Comments
 (0)