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"
63 m_process_launch_error(), m_proc_infos(), m_proc_infos_index(0) {
184 ArchSpec host_arch(HostInfo::GetArchitecture());
185 const llvm::Triple &host_triple = host_arch.
GetTriple();
190 llvm::StringRef distribution_id = HostInfo::GetDistributionId();
191 if (!distribution_id.empty()) {
197#if defined(__APPLE__)
205 response.
Printf(
"cputype:%u;", cpu);
207 response.
Printf(
"cpusubtype:%u;", sub);
209 if (cpu == llvm::MachO::CPU_TYPE_ARM || cpu == llvm::MachO::CPU_TYPE_ARM64) {
211#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
213#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
215#elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
223 response.
PutCString(
"watchpoint_exceptions_received:before;");
226 response.
Printf(
"watchpoint_exceptions_received:after;");
230 if (host_arch.
GetMachine() == llvm::Triple::aarch64 ||
231 host_arch.
GetMachine() == llvm::Triple::aarch64_32 ||
232 host_arch.
GetMachine() == llvm::Triple::aarch64_be ||
233 host_arch.
GetMachine() == llvm::Triple::arm ||
236 response.
Printf(
"watchpoint_exceptions_received:before;");
238 response.
Printf(
"watchpoint_exceptions_received:after;");
256 llvm::VersionTuple version = HostInfo::GetOSVersion();
257 if (!version.empty()) {
258 response.
Format(
"os_version:{0}", version.getAsString());
262#if defined(__APPLE__)
263 llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion();
264 if (!maccatalyst_version.empty()) {
265 response.
Format(
"maccatalyst_version:{0}",
266 maccatalyst_version.getAsString());
271 if (std::optional<std::string> s = HostInfo::GetOSBuildString()) {
276 if (std::optional<std::string> s = HostInfo::GetOSKernelDescription()) {
283#if defined(__APPLE__)
285#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
293 if (HostInfo::GetHostname(s)) {
301 if (HostInfo::GetHostname(s)) {
318 packet.
SetFilePos(::strlen(
"qProcessInfoPID:"));
341 llvm::StringRef value;
349 file, FileSpec::Style::native);
350 }
else if (key ==
"name_match") {
351 NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
361 }
else if (key ==
"pid") {
363 if (value.getAsInteger(0, pid))
366 }
else if (key ==
"parent_pid") {
368 if (value.getAsInteger(0, pid))
371 }
else if (key ==
"uid") {
373 if (value.getAsInteger(0, uid))
376 }
else if (key ==
"gid") {
378 if (value.getAsInteger(0, gid))
381 }
else if (key ==
"euid") {
383 if (value.getAsInteger(0, uid))
386 }
else if (key ==
"egid") {
388 if (value.getAsInteger(0, gid))
391 }
else if (key ==
"all_users") {
394 }
else if (key ==
"triple") {
396 HostInfo::GetAugmentedArchSpec(value);
431 LLDB_LOGF(log,
"GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
437 if (std::optional<llvm::StringRef> name =
438 HostInfo::GetUserIDResolver().GetUserName(uid)) {
444 LLDB_LOGF(log,
"GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
457 if (std::optional<llvm::StringRef> name =
458 HostInfo::GetUserIDResolver().GetGroupName(gid)) {
474 llvm::StringRef value;
476 if (success && key ==
"response_size") {
477 uint32_t response_size = 0;
478 if (!value.getAsInteger(0, response_size)) {
479 if (response_size == 0)
482 uint32_t bytes_left = response_size;
484 while (bytes_left > 0) {
485 if (bytes_left >= 26) {
486 response.
PutCString(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
489 response.
Printf(
"%*.*s;", bytes_left, bytes_left,
490 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
502#define HANDLE_ERRNO(name, value) \
505#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
532 descriptor = file.get()->GetDescriptor();
533 response.
Printf(
"%x", descriptor);
536 std::error_code code = errorToErrorCode(file.takeError());
551 int fd = packet.
GetS32(-1, 16);
558 save_errno =
error.GetError();
564 response.
Printf(
"%x", err);
575 int fd = packet.
GetS32(-1, 16);
580 if (count == SIZE_MAX) {
581 response.
Printf(
"F-1:%x", EINVAL);
585 std::string buffer(count, 0);
587 Status error = file.
Read(
static_cast<void *
>(&buffer[0]), count, offset);
588 const int save_errno =
error.GetError();
590 if (
error.Success()) {
591 response.
Printf(
"%zx", count);
613 int fd = packet.
GetS32(-1, 16);
620 size_t count = buffer.size();
622 file.
Write(
static_cast<const void *
>(&buffer[0]), count, offset);
623 const int save_errno =
error.GetError();
625 response.
Printf(
"%zx", count);
632 response.
Printf(
"-1,%x", EINVAL);
648 if (llvm::sys::fs::file_size(path, Size))
674 if (mode != llvm::sys::fs::perms_not_known)
675 response.
Printf(
"F%x", mode);
690 bool retcode = llvm::sys::fs::exists(path);
706 packet.
SetFilePos(::strlen(
"vFile:symlink:"));
707 std::string dst, src;
737 packet.
SetFilePos(::strlen(
"qPlatform_shell:"));
739 std::string working_dir;
753 &output, std::chrono::seconds(10));
772template <
typename T,
typename U>
773static void fill_clamp(T &dest, U src,
typename T::value_type fallback) {
774 static_assert(std::is_unsigned<typename T::value_type>::value,
775 "Destination type must be unsigned.");
776 using UU = std::make_unsigned_t<U>;
777 constexpr auto T_max = std::numeric_limits<typename T::value_type>::max();
778 dest = src >= 0 &&
static_cast<UU
>(src) <= T_max ? src : fallback;
786 int fd = packet.
GetS32(-1, 16);
788 struct stat file_stats;
789 if (::fstat(fd, &file_stats) == -1) {
790 const int save_errno = errno;
815 response.
Printf(
"F%zx;",
sizeof(data));
824 "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
835 auto Result = llvm::sys::fs::md5_contents(path);
852 packet.
SetFilePos(::strlen(
"qPlatform_mkdir:"));
857 Status error(llvm::sys::fs::create_directory(path, mode));
870 packet.
SetFilePos(::strlen(
"qPlatform_chmod:"));
877 Status error(llvm::sys::fs::setPermissions(path, perms));
891 llvm::SmallVector<llvm::StringRef, 4> client_features;
899 packet.
SetFilePos(::strlen(
"QSetDetachOnError:"));
913 return packet_result;
923 const bool read =
true;
924 const bool write =
false;
925 if (file_action.
Open(STDIN_FILENO,
FileSpec(path), read, write)) {
939 const bool read =
false;
940 const bool write =
true;
941 if (file_action.
Open(STDOUT_FILENO,
FileSpec(path), read, write)) {
955 const bool read =
false;
956 const bool write =
true;
957 if (file_action.
Open(STDERR_FILENO,
FileSpec(path), read, write)) {
980 if (bytes_left > 0) {
990 packet.
SetFilePos(::strlen(
"QEnvironmentHexEncoded:"));
992 if (bytes_left > 0) {
1006 if (bytes_left > 0) {
1007 const char *arch_triple = packet.
Peek();
1009 HostInfo::GetAugmentedArchSpec(arch_triple));
1024 int actual_arg_index = 0;
1027 bool success =
true;
1066 arg, FileSpec::Style::native);
1068 LLDB_LOGF(log,
"LLGSPacketHandler::%s added arg %d: \"%s\"",
1069 __FUNCTION__, actual_arg_index, arg.c_str());
1100 std::string module_path;
1102 if (module_path.empty())
1121 if (uuid_str.empty()) {
1122 auto Result = llvm::sys::fs::md5_contents(
1158 packet.
SetFilePos(::strlen(
"jModulesInfo:"));
1168 json::Array response_array;
1169 for (
size_t i = 0; i < packet_array->
GetSize(); ++i) {
1174 llvm::StringRef file, triple;
1186 if (uuid_str.empty())
1188 const auto triple_str =
1192 json::Object response{{
"uuid", uuid_str},
1193 {
"triple", triple_str},
1194 {
"file_path", file_path},
1195 {
"file_offset",
static_cast<int64_t
>(file_offset)},
1196 {
"file_size",
static_cast<int64_t
>(file_size)}};
1197 response_array.push_back(std::move(response));
1211 "pid:%" PRIu64
";ppid:%" PRIu64
";uid:%i;gid:%i;euid:%i;egid:%i;",
1229 const llvm::Triple &proc_triple = proc_arch.
GetTriple();
1239 response.
Printf(
"pid:%" PRIx64
";parent-pid:%" PRIx64
1240 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
1248 const llvm::Triple &proc_triple = proc_arch.
GetTriple();
1249#if defined(__APPLE__)
1253 response.
Printf(
"cputype:%" PRIx32
";", cpu_type);
1256 if (cpu_subtype != 0)
1257 response.
Printf(
"cpusubtype:%" PRIx32
";", cpu_subtype);
1259 const std::string vendor = proc_triple.getVendorName().str();
1260 if (!vendor.empty())
1261 response.
Printf(
"vendor:%s;", vendor.c_str());
1268 std::string ostype = std::string(proc_triple.getOSName());
1270 if (proc_triple.getVendor() == llvm::Triple::Apple) {
1271 switch (proc_triple.getArch()) {
1272 case llvm::Triple::arm:
1273 case llvm::Triple::thumb:
1274 case llvm::Triple::aarch64:
1275 case llvm::Triple::aarch64_32:
1283 response.
Printf(
"ostype:%s;", ostype.c_str());
1303 response.
Printf(
"elf_abi:%s;", abi.c_str());
1309 const std::string &module_path,
const ArchSpec &arch) {
1321 llvm::StringRef triple) {
1324 FileSpec req_module_path_spec(module_path);
1337 std::string file_path;
1339 module_path_spec, file_kind, file_path, file_offset, file_size)) {
1346 const FileSpec actual_module_path_spec(file_path);
1349 const FileSpec &actual_module_path_spec = module_path_spec;
1352 const ModuleSpec module_spec(actual_module_path_spec, arch);
1356 file_size, module_specs))
1373 return matched_module_spec;
1377 const llvm::ArrayRef<llvm::StringRef> client_features) {
1379 constexpr uint32_t max_packet_size = 128 * 1024;
1383 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.
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
std::pair< iterator, bool > insert(llvm::StringRef KeyEqValue)
bool Open(int fd, const FileSpec &file_spec, bool read, bool write)
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.
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
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()
static int kInvalidDescriptor
ValueType Clear(ValueType mask=~static_cast< ValueType >(0))
Clear one or more flags.
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
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, const Timeout< std::micro > &timeout, bool run_in_shell=true, bool hide_stderr=false)
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 Write(const void *buf, size_t &num_bytes) override
Write bytes from buf to a file at the current file position.
Status Read(void *buf, size_t &num_bytes) override
Read bytes from a file from the current file position into buf.
static size_t GetModuleSpecifications(const FileSpec &file, lldb::offset_t file_offset, lldb::offset_t file_size, ModuleSpecList &specs, lldb::DataBufferSP data_sp=lldb::DataBufferSP())
void SetGroupID(uint32_t gid)
void SetArchitecture(const ArchSpec &arch)
lldb::pid_t GetProcessID() const
llvm::StringRef GetArg0() const
void SetProcessID(lldb::pid_t pid)
FileSpec & GetExecutableFile()
uint32_t GetUserID() const
Environment & GetEnvironment()
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)
void AppendFileAction(const FileAction &info)
bool Fail() const
Test for error condition.
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
bool Success() const
Test for success 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)
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 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.
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