14#include <TargetConditionals.h>
22#include "lldb/Host/Config.h"
38#include "llvm/ADT/StringSwitch.h"
39#include "llvm/Support/JSON.h"
40#include "llvm/TargetParser/Triple.h"
187 ArchSpec host_arch(HostInfo::GetArchitecture());
188 const llvm::Triple &host_triple = host_arch.
GetTriple();
193 llvm::StringRef distribution_id = HostInfo::GetDistributionId();
194 if (!distribution_id.empty()) {
200#if defined(__APPLE__)
208 response.
Printf(
"cputype:%u;", cpu);
210 response.
Printf(
"cpusubtype:%u;", sub);
212 if (cpu == llvm::MachO::CPU_TYPE_ARM || cpu == llvm::MachO::CPU_TYPE_ARM64) {
214#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
216#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
218#elif defined(TARGET_OS_XR) && TARGET_OS_XR == 1
220#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
228 response.
PutCString(
"watchpoint_exceptions_received:before;");
231 response.
Printf(
"watchpoint_exceptions_received:after;");
235 if (host_arch.
GetMachine() == llvm::Triple::aarch64 ||
236 host_arch.
GetMachine() == llvm::Triple::aarch64_32 ||
237 host_arch.
GetMachine() == llvm::Triple::aarch64_be ||
238 host_arch.
GetMachine() == llvm::Triple::arm ||
241 response.
Printf(
"watchpoint_exceptions_received:before;");
243 response.
Printf(
"watchpoint_exceptions_received:after;");
261 llvm::VersionTuple version = HostInfo::GetOSVersion();
262 if (!version.empty()) {
263 response.
Format(
"os_version:{0}", version.getAsString());
267#if defined(__APPLE__)
268 llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion();
269 if (!maccatalyst_version.empty()) {
270 response.
Format(
"maccatalyst_version:{0}",
271 maccatalyst_version.getAsString());
276 if (std::optional<std::string> s = HostInfo::GetOSBuildString()) {
281 if (std::optional<std::string> s = HostInfo::GetOSKernelDescription()) {
288#if defined(__APPLE__)
290#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
298 if (HostInfo::GetHostname(s)) {
306 if (HostInfo::GetHostname(s)) {
323 packet.
SetFilePos(::strlen(
"qProcessInfoPID:"));
346 llvm::StringRef value;
354 file, FileSpec::Style::native);
355 }
else if (key ==
"name_match") {
356 NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
366 }
else if (key ==
"pid") {
368 if (value.getAsInteger(0, pid))
371 }
else if (key ==
"parent_pid") {
373 if (value.getAsInteger(0, pid))
376 }
else if (key ==
"uid") {
378 if (value.getAsInteger(0, uid))
381 }
else if (key ==
"gid") {
383 if (value.getAsInteger(0, gid))
386 }
else if (key ==
"euid") {
388 if (value.getAsInteger(0, uid))
391 }
else if (key ==
"egid") {
393 if (value.getAsInteger(0, gid))
396 }
else if (key ==
"all_users") {
399 }
else if (key ==
"triple") {
401 HostInfo::GetAugmentedArchSpec(value);
436 LLDB_LOGF(log,
"GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
442 if (std::optional<llvm::StringRef> name =
443 HostInfo::GetUserIDResolver().GetUserName(uid)) {
449 LLDB_LOGF(log,
"GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
462 if (std::optional<llvm::StringRef> name =
463 HostInfo::GetUserIDResolver().GetGroupName(gid)) {
479 llvm::StringRef value;
481 if (success && key ==
"response_size") {
482 uint32_t response_size = 0;
483 if (!value.getAsInteger(0, response_size)) {
484 if (response_size == 0)
487 uint32_t bytes_left = response_size;
489 while (bytes_left > 0) {
490 if (bytes_left >= 26) {
491 response.
PutCString(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
494 response.
Printf(
"%*.*s;", bytes_left, bytes_left,
495 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
507#define HANDLE_ERRNO(name, value) \
510#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
537 descriptor = file.get()->GetDescriptor();
538 response.
Printf(
"%x", descriptor);
541 std::error_code code = errorToErrorCode(file.takeError());
556 int fd = packet.
GetS32(-1, 16);
563 save_errno =
error.GetError();
569 response.
Printf(
"%x", err);
580 int fd = packet.
GetS32(-1, 16);
585 if (count == SIZE_MAX) {
586 response.
Printf(
"F-1:%x", EINVAL);
590 std::string buffer(count, 0);
592 Status error = file.
Read(
static_cast<void *
>(&buffer[0]), count, offset);
593 const int save_errno =
error.GetError();
595 if (
error.Success()) {
596 response.
Printf(
"%zx", count);
618 int fd = packet.
GetS32(-1, 16);
625 size_t count = buffer.size();
627 file.
Write(
static_cast<const void *
>(&buffer[0]), count, offset);
628 const int save_errno =
error.GetError();
630 response.
Printf(
"%zx", count);
637 response.
Printf(
"-1,%x", EINVAL);
653 if (llvm::sys::fs::file_size(path, Size))
679 if (mode != llvm::sys::fs::perms_not_known)
680 response.
Printf(
"F%x", mode);
695 bool retcode = llvm::sys::fs::exists(path);
711 packet.
SetFilePos(::strlen(
"vFile:symlink:"));
712 std::string dst, src;
742 packet.
SetFilePos(::strlen(
"qPlatform_shell:"));
744 std::string working_dir;
758 &output,
nullptr, std::chrono::seconds(10));
777template <
typename T,
typename U>
778static void fill_clamp(T &dest, U src,
typename T::value_type fallback) {
779 static_assert(std::is_unsigned<typename T::value_type>::value,
780 "Destination type must be unsigned.");
781 using UU = std::make_unsigned_t<U>;
782 constexpr auto T_max = std::numeric_limits<typename T::value_type>::max();
783 dest = src >= 0 &&
static_cast<UU
>(src) <= T_max ? src : fallback;
791 int fd = packet.
GetS32(-1, 16);
793 struct stat file_stats;
794 if (::fstat(fd, &file_stats) == -1) {
795 const int save_errno = errno;
820 response.
Printf(
"F%zx;",
sizeof(data));
829 "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
840 auto Result = llvm::sys::fs::md5_contents(path);
857 packet.
SetFilePos(::strlen(
"qPlatform_mkdir:"));
862 Status error(llvm::sys::fs::create_directory(path, mode));
875 packet.
SetFilePos(::strlen(
"qPlatform_chmod:"));
882 Status error(llvm::sys::fs::setPermissions(path, perms));
896 llvm::SmallVector<llvm::StringRef, 4> client_features;
904 packet.
SetFilePos(::strlen(
"QSetDetachOnError:"));
918 return packet_result;
928 const bool read =
true;
929 const bool write =
false;
930 if (file_action.
Open(STDIN_FILENO,
FileSpec(path), read, write)) {
944 const bool read =
false;
945 const bool write =
true;
946 if (file_action.
Open(STDOUT_FILENO,
FileSpec(path), read, write)) {
960 const bool read =
false;
961 const bool write =
true;
962 if (file_action.
Open(STDERR_FILENO,
FileSpec(path), read, write)) {
973 packet.
SetFilePos(::strlen(
"QSetSTDIOWindowSize:"));
978 llvm::SmallVector<llvm::StringRef, 2> fields;
979 body.split(fields,
';');
980 for (llvm::StringRef field : fields) {
981 auto [key, value] = field.split(
'=');
985 else if (key ==
"rows")
990 if (value.empty() || value.getAsInteger(10, parsed) || parsed > UINT16_MAX)
992 *dest =
static_cast<uint16_t
>(parsed);
997 if ((cols == 0) != (rows == 0))
1018 packet.
SetFilePos(::strlen(
"QEnvironment:"));
1020 if (bytes_left > 0) {
1030 packet.
SetFilePos(::strlen(
"QEnvironmentHexEncoded:"));
1032 if (bytes_left > 0) {
1046 if (bytes_left > 0) {
1047 const char *arch_triple = packet.
Peek();
1049 HostInfo::GetAugmentedArchSpec(arch_triple));
1064 int actual_arg_index = 0;
1067 bool success =
true;
1106 arg, FileSpec::Style::native);
1108 LLDB_LOGF(log,
"LLGSPacketHandler::%s added arg %d: \"%s\"",
1109 __FUNCTION__, actual_arg_index, arg.c_str());
1140 std::string module_path;
1142 if (module_path.empty())
1161 if (uuid_str.empty()) {
1162 auto Result = llvm::sys::fs::md5_contents(
1198 packet.
SetFilePos(::strlen(
"jModulesInfo:"));
1208 json::Array response_array;
1209 for (
size_t i = 0; i < packet_array->
GetSize(); ++i) {
1214 llvm::StringRef file, triple;
1226 if (uuid_str.empty())
1228 const auto triple_str =
1232 json::Object response{{
"uuid", uuid_str},
1233 {
"triple", triple_str},
1234 {
"file_path", file_path},
1235 {
"file_offset",
static_cast<int64_t
>(file_offset)},
1236 {
"file_size",
static_cast<int64_t
>(file_size)}};
1237 response_array.push_back(std::move(response));
1251 "pid:%" PRIu64
";ppid:%" PRIu64
";uid:%i;gid:%i;euid:%i;egid:%i;",
1269 const llvm::Triple &proc_triple = proc_arch.
GetTriple();
1279 response.
Printf(
"pid:%" PRIx64
";parent-pid:%" PRIx64
1280 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
1288 const llvm::Triple &proc_triple = proc_arch.
GetTriple();
1289#if defined(__APPLE__)
1293 response.
Printf(
"cputype:%" PRIx32
";", cpu_type);
1296 if (cpu_subtype != 0)
1297 response.
Printf(
"cpusubtype:%" PRIx32
";", cpu_subtype);
1299 const std::string vendor = proc_triple.getVendorName().str();
1300 if (!vendor.empty())
1301 response.
Printf(
"vendor:%s;", vendor.c_str());
1308 std::string ostype = std::string(proc_triple.getOSName());
1310 if (proc_triple.getVendor() == llvm::Triple::Apple) {
1311 switch (proc_triple.getArch()) {
1312 case llvm::Triple::arm:
1313 case llvm::Triple::thumb:
1314 case llvm::Triple::aarch64:
1315 case llvm::Triple::aarch64_32:
1323 response.
Printf(
"ostype:%s;", ostype.c_str());
1343 response.
Printf(
"elf_abi:%s;", abi.c_str());
1349 const std::string &module_path,
const ArchSpec &arch) {
1361 llvm::StringRef triple) {
1364 FileSpec req_module_path_spec(module_path);
1377 std::string file_path;
1379 module_path_spec, file_kind, file_path, file_offset, file_size)) {
1386 const FileSpec actual_module_path_spec(file_path);
1389 const FileSpec &actual_module_path_spec = module_path_spec;
1392 const ModuleSpec module_spec(actual_module_path_spec, arch);
1395 actual_module_path_spec, file_offset, file_size);
1396 if (module_specs.
GetSize() == 0)
1413 return matched_module_spec;
1417 const llvm::ArrayRef<llvm::StringRef> client_features) {
1419 constexpr uint32_t max_packet_size = 128 * 1024;
1423 llvm::formatv(
"PacketSize={0}", max_packet_size),
static llvm::raw_ostream & error(Stream &strm)
static const uint32_t g_default_packet_timeout_sec
static void fill_clamp(T &dest, U src, typename T::value_type fallback)
static GDBErrno system_errno_to_gdb(int err)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_LOGF(log,...)
An architecture specification class.
uint32_t GetAddressByteSize() const
Returns the size in bytes of an address of the current architecture.
bool IsValid() const
Tests if this ArchSpec is valid.
llvm::Triple & GetTriple()
Architecture triple accessor.
uint32_t GetMachOCPUSubType() const
bool IsMIPS() const
if MIPS architecture return true.
uint32_t GetMachOCPUType() const
std::string GetTargetABI() const
Return a string representing target application ABI.
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Represents a file descriptor action to be performed during process launch.
bool Open(int fd, const FileSpec &file_spec, bool read, bool write)
Configure this action to open a file.
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Status Symlink(const FileSpec &src, const FileSpec &dst)
int Open(const char *path, int flags, int mode=0600)
Wraps open in a platform-independent way.
uint32_t GetPermissions(const FileSpec &file_spec) const
Return the current permissions of the given file.
static FileSystem & Instance()
void Resolve(llvm::SmallVectorImpl< char > &path, bool force_make_absolute=false)
Resolve path to make it canonical.
static int kInvalidDescriptor
static FileSpec ResolveLibraryPath(const std::string &path, const ArchSpec &arch)
static Status RunShellCommand(llvm::StringRef command, const FileSpec &working_dir, int *status_ptr, int *signo_ptr, std::string *command_output, std::string *error_output, const Timeout< std::micro > &timeout, bool run_in_shell=true)
Run a shell command.
static bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &proc_info)
static uint32_t FindProcesses(const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &proc_infos)
bool FindMatchingModuleSpec(const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const
uint64_t GetObjectOffset() const
ArchSpec & GetArchitecture()
FileSpec * GetFileSpecPtr()
uint64_t GetObjectSize() const
Status Close() override
Flush any buffers and release any resources owned by the file.
Status Read(void *dst, size_t &num_bytes, off_t &offset) override
Read bytes from a file from the specified file offset.
Status Write(const void *src, size_t &num_bytes, off_t &offset) override
Write bytes to a file at the specified file offset.
static ModuleSpecList GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset, lldb::offset_t file_size, lldb::DataExtractorSP=lldb::DataExtractorSP())
void SetGroupID(uint32_t gid)
lldb::pid_t GetProcessID() const
llvm::StringRef GetArg0() const
void SetProcessID(lldb::pid_t pid)
FileSpec & GetExecutableFile()
uint32_t GetUserID() const
uint32_t GetGroupID() const
void SetUserID(uint32_t uid)
ArchSpec & GetArchitecture()
void SetNameMatchType(NameMatch name_match_type)
void SetMatchAllUsers(bool b)
ProcessInstanceInfo & GetProcessInfo()
uint32_t GetEffectiveUserID() const
void SetEffectiveGroupID(uint32_t gid)
lldb::pid_t GetParentProcessID() const
uint32_t GetEffectiveGroupID() const
void SetParentProcessID(lldb::pid_t pid)
void SetEffectiveUserID(uint32_t uid)
bool Fail() const
Test for error condition.
int PutEscapedBytes(const void *s, size_t src_len)
Output a block of data to the stream performing GDB-remote escaping.
llvm::StringRef GetString() const
void Format(const char *format, Args &&... args)
Forwards the arguments to llvm::formatv and writes to the stream.
llvm::raw_ostream & AsRawOstream()
Returns a raw_ostream that forwards the data to this Stream object.
size_t PutStringAsRawHex8(llvm::StringRef s)
size_t PutHex64(uint64_t uvalue, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
size_t PutHex32(uint32_t uvalue, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
ObjectSP GetItemAtIndex(size_t idx) const
bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result) const
std::shared_ptr< Object > ObjectSP
static ObjectSP ParseJSON(llvm::StringRef json_text)
std::string GetAsString(llvm::StringRef separator="-") const
static bool ResolveSharedLibraryPath(const FileSpec &file_spec, FileKind &file_kind, std::string &file_path, lldb::offset_t &so_file_offset, lldb::offset_t &so_file_size)
PacketResult Handle_vFile_MD5(StringExtractorGDBRemote &packet)
PacketResult Handle_qEcho(StringExtractorGDBRemote &packet)
PacketResult Handle_qProcessInfoPID(StringExtractorGDBRemote &packet)
PacketResult Handle_qHostInfo(StringExtractorGDBRemote &packet)
virtual Status LaunchProcess()=0
Launch a process with the current launch settings.
GDBRemoteCommunicationServerCommon()
PacketResult Handle_qModuleInfo(StringExtractorGDBRemote &packet)
PacketResult Handle_QSetSTDERR(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_Close(StringExtractorGDBRemote &packet)
ModuleSpec GetModuleInfo(llvm::StringRef module_path, llvm::StringRef triple)
PacketResult Handle_QSetDetachOnError(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_pWrite(StringExtractorGDBRemote &packet)
PacketResult Handle_qUserName(StringExtractorGDBRemote &packet)
PacketResult Handle_qLaunchSuccess(StringExtractorGDBRemote &packet)
PacketResult Handle_QEnvironmentHexEncoded(StringExtractorGDBRemote &packet)
PacketResult Handle_qfProcessInfo(StringExtractorGDBRemote &packet)
virtual FileSpec FindModuleFile(const std::string &module_path, const ArchSpec &arch)
PacketResult Handle_vFile_Exists(StringExtractorGDBRemote &packet)
uint32_t m_proc_infos_index
PacketResult Handle_vFile_Mode(StringExtractorGDBRemote &packet)
~GDBRemoteCommunicationServerCommon() override
void RegisterMemberFunctionHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketResult(T::*handler)(StringExtractorGDBRemote &packet))
PacketResult Handle_QEnvironment(StringExtractorGDBRemote &packet)
PacketResult Handle_QSetSTDIN(StringExtractorGDBRemote &packet)
PacketResult Handle_qSpeedTest(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_FStat(StringExtractorGDBRemote &packet)
static void CreateProcessInfoResponse_DebugServerStyle(const ProcessInstanceInfo &proc_info, StreamString &response)
Status m_process_launch_error
PacketResult Handle_qPlatform_mkdir(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_symlink(StringExtractorGDBRemote &packet)
ProcessLaunchInfo m_process_launch_info
PacketResult Handle_qSupported(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_pRead(StringExtractorGDBRemote &packet)
virtual std::vector< std::string > HandleFeatures(llvm::ArrayRef< llvm::StringRef > client_features)
PacketResult Handle_QStartNoAckMode(StringExtractorGDBRemote &packet)
ProcessInstanceInfoList m_proc_infos
static void CreateProcessInfoResponse(const ProcessInstanceInfo &proc_info, StreamString &response)
PacketResult Handle_QLaunchArch(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_unlink(StringExtractorGDBRemote &packet)
PacketResult Handle_jModulesInfo(StringExtractorGDBRemote &packet)
PacketResult Handle_qPlatform_shell(StringExtractorGDBRemote &packet)
PacketResult Handle_qPlatform_chmod(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_Size(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_Open(StringExtractorGDBRemote &packet)
PacketResult Handle_QSetSTDOUT(StringExtractorGDBRemote &packet)
PacketResult Handle_qsProcessInfo(StringExtractorGDBRemote &packet)
PacketResult Handle_A(StringExtractorGDBRemote &packet)
PacketResult Handle_vFile_Stat(StringExtractorGDBRemote &packet)
PacketResult Handle_qGroupName(StringExtractorGDBRemote &packet)
PacketResult Handle_QSetSTDIOWindowSize(StringExtractorGDBRemote &packet)
GDBRemoteCommunicationServer()
PacketResult SendErrorResponse(const Status &error)
PacketResult SendUnimplementedResponse(const char *packet)
PacketResult SendOKResponse()
PacketResult SendPacketNoLock(llvm::StringRef payload)
#define LLDB_INVALID_CPUTYPE
#define LLDB_INVALID_PROCESS_ID
lldb::ByteOrder InlHostByteOrder()
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
NativeFilePosix NativeFile
static bool ToBoolean(llvm::StringRef s, bool fail_value, bool *success_ptr)
llvm::support::ubig32_t gdb_st_ctime
llvm::support::ubig32_t gdb_st_dev
llvm::support::ubig64_t gdb_st_blksize
llvm::support::ubig64_t gdb_st_blocks
llvm::support::ubig32_t gdb_st_ino
llvm::support::ubig32_t gdb_st_gid
llvm::support::ubig32_t gdb_st_mtime
llvm::support::ubig32_t gdb_st_atime
llvm::support::ubig32_t gdb_st_uid
llvm::support::ubig32_t gdb_st_nlink
llvm::support::ubig32_t gdb_st_rdev
llvm::support::ubig64_t gdb_st_size
llvm::support::ubig32_t gdb_st_mode