diff options
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.cpp | 229 |
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) { |