aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
diff options
context:
space:
mode:
authorJason Molenda <jason@molenda.com>2023-02-14 11:29:19 -0800
committerJason Molenda <jason@molenda.com>2023-02-14 11:35:39 -0800
commiteaeb8ddd4a9d3799470479a532e721d017f22a70 (patch)
treec952096c2fd0940738e304fda69bbabef0814a07 /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
parent8198f30f7e756e3368c3eda62ecc3d0cc62d1570 (diff)
downloadllvm-eaeb8ddd4a9d3799470479a532e721d017f22a70.zip
llvm-eaeb8ddd4a9d3799470479a532e721d017f22a70.tar.gz
llvm-eaeb8ddd4a9d3799470479a532e721d017f22a70.tar.bz2
[LLDB] add arch-specific watchpoint behavior defaults to lldb
lldb was originally designed to get the watchpoint exception behavior from the gdb remote serial protocol stub -- exceptions are either received before the instruction executes, or after the instruction has executed. This behavior was reported via two lldb extensions to gdb RSP, so generic remote stubs like gdbserver or a JTAG stub, would not tell lldb which behavior was correct, and it would default to "exceptions are received after the instruction has executed". Two architectures hard coded their correct "exceptions before instruction" behavior, to work around this issue. Most architectures have a fixed behavior of watchpoint exceptions, and we can center that information in lldb. We can allow a remote stub to override the default behavior via our packet extensions if it's needed on a specific target. This patch also separates the fetching of the number of watchpoints from whether exceptions are before/after the insn. Currently if lldb couldn't fetch the number of watchpoints (not really needed), it also wouldn't get when exceptions are received, and watchpoint handling would fail. lldb doesn't actually use the number of watchpoints for anything beyond printing it to the user. Differential Revision: https://reviews.llvm.org/D143215 rdar://101426626
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp62
1 files changed, 18 insertions, 44 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 6e47e5b..a1c1aa5 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -1780,16 +1780,12 @@ Status GDBRemoteCommunicationClient::LoadQXferMemoryMap() {
return error;
}
-Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
- Status error;
-
+std::optional<uint32_t> GDBRemoteCommunicationClient::GetWatchpointSlotCount() {
if (m_supports_watchpoint_support_info == eLazyBoolYes) {
- num = m_num_supported_hardware_watchpoints;
- return error;
+ return m_num_supported_hardware_watchpoints;
}
- // Set num to 0 first.
- num = 0;
+ std::optional<uint32_t> num;
if (m_supports_watchpoint_support_info != eLazyBoolNo) {
StringExtractorGDBRemote response;
if (SendPacketAndWaitForResponse("qWatchpointSupportInfo:", response) ==
@@ -1797,15 +1793,13 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
m_supports_watchpoint_support_info = eLazyBoolYes;
llvm::StringRef name;
llvm::StringRef value;
- bool found_num_field = false;
while (response.GetNameColonValue(name, value)) {
if (name.equals("num")) {
value.getAsInteger(0, m_num_supported_hardware_watchpoints);
num = m_num_supported_hardware_watchpoints;
- found_num_field = true;
}
}
- if (!found_num_field) {
+ if (!num) {
m_supports_watchpoint_support_info = eLazyBoolNo;
}
} else {
@@ -1813,44 +1807,24 @@ Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
}
}
- if (m_supports_watchpoint_support_info == eLazyBoolNo) {
- error.SetErrorString("qWatchpointSupportInfo is not supported");
- }
- return error;
+ return num;
}
-lldb_private::Status GDBRemoteCommunicationClient::GetWatchpointSupportInfo(
- uint32_t &num, bool &after, const ArchSpec &arch) {
- Status error(GetWatchpointSupportInfo(num));
- if (error.Success())
- error = GetWatchpointsTriggerAfterInstruction(after, arch);
- return error;
-}
-
-lldb_private::Status
-GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
- bool &after, const ArchSpec &arch) {
- Status error;
- llvm::Triple triple = arch.GetTriple();
-
- // we assume watchpoints will happen after running the relevant opcode and we
- // only want to override this behavior if we have explicitly received a
- // qHostInfo telling us otherwise
- if (m_qHostInfo_is_valid != eLazyBoolYes) {
- // On targets like MIPS and ppc64, watchpoint exceptions are always
- // generated before the instruction is executed. The connected target may
- // not support qHostInfo or qWatchpointSupportInfo packets.
- after = !(triple.isMIPS() || triple.isPPC64());
- } else {
- // For MIPS and ppc64, set m_watchpoints_trigger_after_instruction to
- // eLazyBoolNo if it is not calculated before.
- if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
- (triple.isMIPS() || triple.isPPC64()))
- m_watchpoints_trigger_after_instruction = eLazyBoolNo;
+std::optional<bool> GDBRemoteCommunicationClient::GetWatchpointReportedAfter() {
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo();
- after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
+ // Process determines this by target CPU, but allow for the
+ // remote stub to override it via the qHostInfo
+ // watchpoint_exceptions_received key, if it is present.
+ if (m_qHostInfo_is_valid == eLazyBoolYes) {
+ if (m_watchpoints_trigger_after_instruction == eLazyBoolNo)
+ return false;
+ if (m_watchpoints_trigger_after_instruction == eLazyBoolYes)
+ return true;
}
- return error;
+
+ return std::nullopt;
}
int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {