aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r--contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp229
1 files changed, 151 insertions, 78 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 7bb449841851..74e392249a94 100644
--- a/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Host/HostInfo.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Host/XML.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
@@ -403,6 +404,18 @@ void GDBRemoteCommunicationClient::GetRemoteQSupported() {
x.split(compressions, ',');
if (!compressions.empty())
MaybeEnableCompression(compressions);
+ } else if (x.consume_front("SupportedWatchpointTypes=")) {
+ llvm::SmallVector<llvm::StringRef, 4> watchpoint_types;
+ x.split(watchpoint_types, ',');
+ m_watchpoint_types = eWatchpointHardwareFeatureUnknown;
+ for (auto wp_type : watchpoint_types) {
+ if (wp_type == "x86_64")
+ m_watchpoint_types |= eWatchpointHardwareX86;
+ if (wp_type == "aarch64-mask")
+ m_watchpoint_types |= eWatchpointHardwareArmMASK;
+ if (wp_type == "aarch64-bas")
+ m_watchpoint_types |= eWatchpointHardwareArmBAS;
+ }
} else if (x.consume_front("PacketSize=")) {
StringExtractorGDBRemote packet_response(x);
m_max_packet_size =
@@ -1039,10 +1052,10 @@ bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
llvm::StringRef name, value;
bool success = false;
while (response.GetNameColonValue(name, value)) {
- if (name.equals("name")) {
+ if (name == "name") {
success = true;
m_gdb_server_name = std::string(value);
- } else if (name.equals("version")) {
+ } else if (name == "version") {
llvm::StringRef major, minor;
std::tie(major, minor) = value.split('.');
if (!major.getAsInteger(0, m_gdb_server_version))
@@ -1179,12 +1192,12 @@ bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
static void ParseOSType(llvm::StringRef value, std::string &os_name,
std::string &environment) {
- if (value.equals("iossimulator") || value.equals("tvossimulator") ||
- value.equals("watchossimulator") || value.equals("xrossimulator") ||
- value.equals("visionossimulator")) {
+ if (value == "iossimulator" || value == "tvossimulator" ||
+ value == "watchossimulator" || value == "xrossimulator" ||
+ value == "visionossimulator") {
environment = "simulator";
os_name = value.drop_back(environment.size()).str();
- } else if (value.equals("maccatalyst")) {
+ } else if (value == "maccatalyst") {
os_name = "ios";
environment = "macabi";
} else {
@@ -1217,44 +1230,44 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
ByteOrder byte_order = eByteOrderInvalid;
uint32_t num_keys_decoded = 0;
while (response.GetNameColonValue(name, value)) {
- if (name.equals("cputype")) {
+ if (name == "cputype") {
// exception type in big endian hex
if (!value.getAsInteger(0, cpu))
++num_keys_decoded;
- } else if (name.equals("cpusubtype")) {
+ } else if (name == "cpusubtype") {
// exception count in big endian hex
if (!value.getAsInteger(0, sub))
++num_keys_decoded;
- } else if (name.equals("arch")) {
+ } else if (name == "arch") {
arch_name = std::string(value);
++num_keys_decoded;
- } else if (name.equals("triple")) {
+ } else if (name == "triple") {
StringExtractor extractor(value);
extractor.GetHexByteString(triple);
++num_keys_decoded;
- } else if (name.equals("distribution_id")) {
+ } else if (name == "distribution_id") {
StringExtractor extractor(value);
extractor.GetHexByteString(m_host_distribution_id);
++num_keys_decoded;
- } else if (name.equals("os_build")) {
+ } else if (name == "os_build") {
StringExtractor extractor(value);
extractor.GetHexByteString(m_os_build);
++num_keys_decoded;
- } else if (name.equals("hostname")) {
+ } else if (name == "hostname") {
StringExtractor extractor(value);
extractor.GetHexByteString(m_hostname);
++num_keys_decoded;
- } else if (name.equals("os_kernel")) {
+ } else if (name == "os_kernel") {
StringExtractor extractor(value);
extractor.GetHexByteString(m_os_kernel);
++num_keys_decoded;
- } else if (name.equals("ostype")) {
+ } else if (name == "ostype") {
ParseOSType(value, os_name, environment);
++num_keys_decoded;
- } else if (name.equals("vendor")) {
+ } else if (name == "vendor") {
vendor_name = std::string(value);
++num_keys_decoded;
- } else if (name.equals("endian")) {
+ } else if (name == "endian") {
byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
.Case("little", eByteOrderLittle)
.Case("big", eByteOrderBig)
@@ -1262,30 +1275,30 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
.Default(eByteOrderInvalid);
if (byte_order != eByteOrderInvalid)
++num_keys_decoded;
- } else if (name.equals("ptrsize")) {
+ } else if (name == "ptrsize") {
if (!value.getAsInteger(0, pointer_byte_size))
++num_keys_decoded;
- } else if (name.equals("addressing_bits")) {
+ } else if (name == "addressing_bits") {
if (!value.getAsInteger(0, m_low_mem_addressing_bits)) {
++num_keys_decoded;
}
- } else if (name.equals("high_mem_addressing_bits")) {
+ } else if (name == "high_mem_addressing_bits") {
if (!value.getAsInteger(0, m_high_mem_addressing_bits))
++num_keys_decoded;
- } else if (name.equals("low_mem_addressing_bits")) {
+ } else if (name == "low_mem_addressing_bits") {
if (!value.getAsInteger(0, m_low_mem_addressing_bits))
++num_keys_decoded;
- } else if (name.equals("os_version") ||
- name.equals("version")) // Older debugserver binaries used
- // the "version" key instead of
- // "os_version"...
+ } else if (name == "os_version" ||
+ name == "version") // Older debugserver binaries used
+ // the "version" key instead of
+ // "os_version"...
{
if (!m_os_version.tryParse(value))
++num_keys_decoded;
- } else if (name.equals("maccatalyst_version")) {
+ } else if (name == "maccatalyst_version") {
if (!m_maccatalyst_version.tryParse(value))
++num_keys_decoded;
- } else if (name.equals("watchpoint_exceptions_received")) {
+ } else if (name == "watchpoint_exceptions_received") {
m_watchpoints_trigger_after_instruction =
llvm::StringSwitch<LazyBool>(value)
.Case("before", eLazyBoolNo)
@@ -1293,14 +1306,14 @@ bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
.Default(eLazyBoolCalculate);
if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate)
++num_keys_decoded;
- } else if (name.equals("default_packet_timeout")) {
+ } else if (name == "default_packet_timeout") {
uint32_t timeout_seconds;
if (!value.getAsInteger(0, timeout_seconds)) {
m_default_packet_timeout = seconds(timeout_seconds);
SetPacketTimeout(m_default_packet_timeout);
++num_keys_decoded;
}
- } else if (name.equals("vm-page-size")) {
+ } else if (name == "vm-page-size") {
int page_size;
if (!value.getAsInteger(0, page_size)) {
m_target_vm_page_size = page_size;
@@ -1555,10 +1568,10 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
bool success = true;
bool saw_permissions = false;
while (success && response.GetNameColonValue(name, value)) {
- if (name.equals("start")) {
+ if (name == "start") {
if (!value.getAsInteger(16, addr_value))
region_info.GetRange().SetRangeBase(addr_value);
- } else if (name.equals("size")) {
+ } else if (name == "size") {
if (!value.getAsInteger(16, addr_value)) {
region_info.GetRange().SetByteSize(addr_value);
if (region_info.GetRange().GetRangeEnd() <
@@ -1567,8 +1580,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
}
}
- } else if (name.equals("permissions") &&
- region_info.GetRange().IsValid()) {
+ } else if (name == "permissions" && region_info.GetRange().IsValid()) {
saw_permissions = true;
if (region_info.GetRange().Contains(addr)) {
if (value.contains('r'))
@@ -1595,12 +1607,12 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
region_info.SetExecutable(MemoryRegionInfo::eNo);
region_info.SetMapped(MemoryRegionInfo::eNo);
}
- } else if (name.equals("name")) {
+ } else if (name == "name") {
StringExtractorGDBRemote name_extractor(value);
std::string name;
name_extractor.GetHexByteString(name);
region_info.SetName(name.c_str());
- } else if (name.equals("flags")) {
+ } else if (name == "flags") {
region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
llvm::StringRef flags = value;
@@ -1616,7 +1628,7 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
}
}
}
- } else if (name.equals("type")) {
+ } else if (name == "type") {
std::string comma_sep_str = value.str();
size_t comma_pos;
while ((comma_pos = comma_sep_str.find(',')) != std::string::npos) {
@@ -1629,13 +1641,13 @@ Status GDBRemoteCommunicationClient::GetMemoryRegionInfo(
if (comma_sep_str == "stack") {
region_info.SetIsStackMemory(MemoryRegionInfo::eYes);
}
- } else if (name.equals("error")) {
+ } else if (name == "error") {
StringExtractorGDBRemote error_extractor(value);
std::string error_string;
// Now convert the HEX bytes into a string value
error_extractor.GetHexByteString(error_string);
error.SetErrorString(error_string.c_str());
- } else if (name.equals("dirty-pages")) {
+ } else if (name == "dirty-pages") {
std::vector<addr_t> dirty_page_list;
for (llvm::StringRef x : llvm::split(value, ',')) {
addr_t page;
@@ -1812,7 +1824,7 @@ std::optional<uint32_t> GDBRemoteCommunicationClient::GetWatchpointSlotCount() {
llvm::StringRef name;
llvm::StringRef value;
while (response.GetNameColonValue(name, value)) {
- if (name.equals("num")) {
+ if (name == "num") {
value.getAsInteger(0, m_num_supported_hardware_watchpoints);
num = m_num_supported_hardware_watchpoints;
}
@@ -1828,6 +1840,11 @@ std::optional<uint32_t> GDBRemoteCommunicationClient::GetWatchpointSlotCount() {
return num;
}
+WatchpointHardwareFeature
+GDBRemoteCommunicationClient::GetSupportedWatchpointTypes() {
+ return m_watchpoint_types;
+}
+
std::optional<bool> GDBRemoteCommunicationClient::GetWatchpointReportedAfter() {
if (m_qHostInfo_is_valid == eLazyBoolCalculate)
GetHostInfo();
@@ -1988,43 +2005,43 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
std::string os_type;
while (response.GetNameColonValue(name, value)) {
- if (name.equals("pid")) {
+ if (name == "pid") {
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
value.getAsInteger(0, pid);
process_info.SetProcessID(pid);
- } else if (name.equals("ppid")) {
+ } else if (name == "ppid") {
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
value.getAsInteger(0, pid);
process_info.SetParentProcessID(pid);
- } else if (name.equals("uid")) {
+ } else if (name == "uid") {
uint32_t uid = UINT32_MAX;
value.getAsInteger(0, uid);
process_info.SetUserID(uid);
- } else if (name.equals("euid")) {
+ } else if (name == "euid") {
uint32_t uid = UINT32_MAX;
value.getAsInteger(0, uid);
process_info.SetEffectiveUserID(uid);
- } else if (name.equals("gid")) {
+ } else if (name == "gid") {
uint32_t gid = UINT32_MAX;
value.getAsInteger(0, gid);
process_info.SetGroupID(gid);
- } else if (name.equals("egid")) {
+ } else if (name == "egid") {
uint32_t gid = UINT32_MAX;
value.getAsInteger(0, gid);
process_info.SetEffectiveGroupID(gid);
- } else if (name.equals("triple")) {
+ } else if (name == "triple") {
StringExtractor extractor(value);
std::string triple;
extractor.GetHexByteString(triple);
process_info.GetArchitecture().SetTriple(triple.c_str());
- } else if (name.equals("name")) {
+ } else if (name == "name") {
StringExtractor extractor(value);
// The process name from ASCII hex bytes since we can't control the
// characters in a process name
std::string name;
extractor.GetHexByteString(name);
process_info.GetExecutableFile().SetFile(name, FileSpec::Style::native);
- } else if (name.equals("args")) {
+ } else if (name == "args") {
llvm::StringRef encoded_args(value), hex_arg;
bool is_arg0 = true;
@@ -2044,13 +2061,13 @@ bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
process_info.GetArguments().AppendArgument(arg);
is_arg0 = false;
}
- } else if (name.equals("cputype")) {
+ } else if (name == "cputype") {
value.getAsInteger(0, cpu);
- } else if (name.equals("cpusubtype")) {
+ } else if (name == "cpusubtype") {
value.getAsInteger(0, sub);
- } else if (name.equals("vendor")) {
+ } else if (name == "vendor") {
vendor = std::string(value);
- } else if (name.equals("ostype")) {
+ } else if (name == "ostype") {
os_type = std::string(value);
}
}
@@ -2126,23 +2143,35 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
uint32_t num_keys_decoded = 0;
lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
while (response.GetNameColonValue(name, value)) {
- if (name.equals("cputype")) {
+ if (name == "cputype") {
if (!value.getAsInteger(16, cpu))
++num_keys_decoded;
- } else if (name.equals("cpusubtype")) {
- if (!value.getAsInteger(16, sub))
+ } else if (name == "cpusubtype") {
+ if (!value.getAsInteger(16, sub)) {
++num_keys_decoded;
- } else if (name.equals("triple")) {
+ // Workaround for pre-2024 Apple debugserver, which always
+ // returns arm64e on arm64e-capable hardware regardless of
+ // what the process is. This can be deleted at some point
+ // in the future.
+ if (cpu == llvm::MachO::CPU_TYPE_ARM64 &&
+ sub == llvm::MachO::CPU_SUBTYPE_ARM64E) {
+ if (GetGDBServerVersion())
+ if (m_gdb_server_version >= 1000 &&
+ m_gdb_server_version <= 1504)
+ sub = 0;
+ }
+ }
+ } else if (name == "triple") {
StringExtractor extractor(value);
extractor.GetHexByteString(triple);
++num_keys_decoded;
- } else if (name.equals("ostype")) {
+ } else if (name == "ostype") {
ParseOSType(value, os_name, environment);
++num_keys_decoded;
- } else if (name.equals("vendor")) {
+ } else if (name == "vendor") {
vendor_name = std::string(value);
++num_keys_decoded;
- } else if (name.equals("endian")) {
+ } else if (name == "endian") {
byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
.Case("little", eByteOrderLittle)
.Case("big", eByteOrderBig)
@@ -2150,19 +2179,19 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
.Default(eByteOrderInvalid);
if (byte_order != eByteOrderInvalid)
++num_keys_decoded;
- } else if (name.equals("ptrsize")) {
+ } else if (name == "ptrsize") {
if (!value.getAsInteger(16, pointer_byte_size))
++num_keys_decoded;
- } else if (name.equals("pid")) {
+ } else if (name == "pid") {
if (!value.getAsInteger(16, pid))
++num_keys_decoded;
- } else if (name.equals("elf_abi")) {
+ } else if (name == "elf_abi") {
elf_abi = std::string(value);
++num_keys_decoded;
- } else if (name.equals("main-binary-uuid")) {
+ } else if (name == "main-binary-uuid") {
m_process_standalone_uuid.SetFromStringRef(value);
++num_keys_decoded;
- } else if (name.equals("main-binary-slide")) {
+ } else if (name == "main-binary-slide") {
StringExtractor extractor(value);
m_process_standalone_value =
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
@@ -2170,7 +2199,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
m_process_standalone_value_is_offset = true;
++num_keys_decoded;
}
- } else if (name.equals("main-binary-address")) {
+ } else if (name == "main-binary-address") {
StringExtractor extractor(value);
m_process_standalone_value =
extractor.GetU64(LLDB_INVALID_ADDRESS, 16);
@@ -2178,7 +2207,7 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
m_process_standalone_value_is_offset = false;
++num_keys_decoded;
}
- } else if (name.equals("binary-addresses")) {
+ } else if (name == "binary-addresses") {
m_binary_addresses.clear();
++num_keys_decoded;
for (llvm::StringRef x : llvm::split(value, ',')) {
@@ -2617,9 +2646,9 @@ bool GDBRemoteCommunicationClient::LaunchGDBServer(
llvm::StringRef name;
llvm::StringRef value;
while (response.GetNameColonValue(name, value)) {
- if (name.equals("port"))
+ if (name == "port")
value.getAsInteger(0, port);
- else if (name.equals("pid"))
+ else if (name == "pid")
value.getAsInteger(0, pid);
else if (name.compare("socket_name") == 0) {
StringExtractor extractor(value);
@@ -3388,8 +3417,8 @@ bool GDBRemoteCommunicationClient::GetFileExists(
return true;
}
-bool GDBRemoteCommunicationClient::CalculateMD5(
- const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) {
+llvm::ErrorOr<llvm::MD5::MD5Result> GDBRemoteCommunicationClient::CalculateMD5(
+ const lldb_private::FileSpec &file_spec) {
std::string path(file_spec.GetPath(false));
lldb_private::StreamString stream;
stream.PutCString("vFile:MD5:");
@@ -3398,16 +3427,60 @@ bool GDBRemoteCommunicationClient::CalculateMD5(
if (SendPacketAndWaitForResponse(stream.GetString(), response) ==
PacketResult::Success) {
if (response.GetChar() != 'F')
- return false;
+ return std::make_error_code(std::errc::illegal_byte_sequence);
if (response.GetChar() != ',')
- return false;
+ return std::make_error_code(std::errc::illegal_byte_sequence);
if (response.Peek() && *response.Peek() == 'x')
- return false;
- low = response.GetHexMaxU64(false, UINT64_MAX);
- high = response.GetHexMaxU64(false, UINT64_MAX);
- return true;
- }
- return false;
+ return std::make_error_code(std::errc::no_such_file_or_directory);
+
+ // GDBRemoteCommunicationServerCommon::Handle_vFile_MD5 concatenates low and
+ // high hex strings. We can't use response.GetHexMaxU64 because that can't
+ // handle the concatenated hex string. What would happen is parsing the low
+ // would consume the whole response packet which would give incorrect
+ // results. Instead, we get the byte string for each low and high hex
+ // separately, and parse them.
+ //
+ // An alternate way to handle this is to change the server to put a
+ // delimiter between the low/high parts, and change the client to parse the
+ // delimiter. However, we choose not to do this so existing lldb-servers
+ // don't have to be patched
+
+ // The checksum is 128 bits encoded as hex
+ // This means low/high are halves of 64 bits each, in otherwords, 8 bytes.
+ // Each byte takes 2 hex characters in the response.
+ const size_t MD5_HALF_LENGTH = sizeof(uint64_t) * 2;
+
+ // Get low part
+ auto part =
+ response.GetStringRef().substr(response.GetFilePos(), MD5_HALF_LENGTH);
+ if (part.size() != MD5_HALF_LENGTH)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ response.SetFilePos(response.GetFilePos() + part.size());
+
+ uint64_t low;
+ if (part.getAsInteger(/*radix=*/16, low))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ // Get high part
+ part =
+ response.GetStringRef().substr(response.GetFilePos(), MD5_HALF_LENGTH);
+ if (part.size() != MD5_HALF_LENGTH)
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+ response.SetFilePos(response.GetFilePos() + part.size());
+
+ uint64_t high;
+ if (part.getAsInteger(/*radix=*/16, high))
+ return std::make_error_code(std::errc::illegal_byte_sequence);
+
+ llvm::MD5::MD5Result result;
+ llvm::support::endian::write<uint64_t, llvm::endianness::little>(
+ result.data(), low);
+ llvm::support::endian::write<uint64_t, llvm::endianness::little>(
+ result.data() + 8, high);
+
+ return result;
+ }
+ return std::make_error_code(std::errc::operation_canceled);
}
bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) {