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 ||
235 response.
Printf(
"watchpoint_exceptions_received:before;");
237 response.
Printf(
"watchpoint_exceptions_received:after;");
255 llvm::VersionTuple version = HostInfo::GetOSVersion();
256 if (!version.empty()) {
257 response.
Format(
"os_version:{0}", version.getAsString());
261#if defined(__APPLE__)
262 llvm::VersionTuple maccatalyst_version = HostInfo::GetMacCatalystVersion();
263 if (!maccatalyst_version.empty()) {
264 response.
Format(
"maccatalyst_version:{0}",
265 maccatalyst_version.getAsString());
270 if (std::optional<std::string> s = HostInfo::GetOSBuildString()) {
275 if (std::optional<std::string> s = HostInfo::GetOSKernelDescription()) {
282#if defined(__APPLE__)
284#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
292 if (HostInfo::GetHostname(s)) {
300 if (HostInfo::GetHostname(s)) {
317 packet.
SetFilePos(::strlen(
"qProcessInfoPID:"));
340 llvm::StringRef value;
348 file, FileSpec::Style::native);
349 }
else if (key ==
"name_match") {
350 NameMatch name_match = llvm::StringSwitch<NameMatch>(value)
360 }
else if (key ==
"pid") {
362 if (value.getAsInteger(0, pid))
365 }
else if (key ==
"parent_pid") {
367 if (value.getAsInteger(0, pid))
370 }
else if (key ==
"uid") {
372 if (value.getAsInteger(0, uid))
375 }
else if (key ==
"gid") {
377 if (value.getAsInteger(0, gid))
380 }
else if (key ==
"euid") {
382 if (value.getAsInteger(0, uid))
385 }
else if (key ==
"egid") {
387 if (value.getAsInteger(0, gid))
390 }
else if (key ==
"all_users") {
393 }
else if (key ==
"triple") {
395 HostInfo::GetAugmentedArchSpec(value);
430 LLDB_LOGF(log,
"GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
436 if (std::optional<llvm::StringRef> name =
437 HostInfo::GetUserIDResolver().GetUserName(uid)) {
443 LLDB_LOGF(log,
"GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
456 if (std::optional<llvm::StringRef> name =
457 HostInfo::GetUserIDResolver().GetGroupName(gid)) {
473 llvm::StringRef value;
475 if (success && key ==
"response_size") {
476 uint32_t response_size = 0;
477 if (!value.getAsInteger(0, response_size)) {
478 if (response_size == 0)
481 uint32_t bytes_left = response_size;
483 while (bytes_left > 0) {
484 if (bytes_left >= 26) {
485 response.
PutCString(
"ABCDEFGHIJKLMNOPQRSTUVWXYZ");
488 response.
Printf(
"%*.*s;", bytes_left, bytes_left,
489 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
520 descriptor = file.get()->GetDescriptor();
521 response.
Printf(
"%x", descriptor);
524 std::error_code code = errorToErrorCode(file.takeError());
525 if (code.category() == std::system_category()) {
526 response.
Printf(
",%x", code.value());
539#define HANDLE_ERRNO(name, value) \
542#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
552 int fd = packet.
GetS32(-1, 16);
559 save_errno =
error.GetError();
565 response.
Printf(
"%x", err);
576 int fd = packet.
GetS32(-1, 16);
581 if (count == SIZE_MAX) {
582 response.
Printf(
"F-1:%x", EINVAL);
586 std::string buffer(count, 0);
588 Status error = file.
Read(
static_cast<void *
>(&buffer[0]), count, offset);
589 const int save_errno =
error.GetError();
591 if (
error.Success()) {
592 response.
Printf(
"%zx", count);
614 int fd = packet.
GetS32(-1, 16);
621 size_t count = buffer.size();
623 file.
Write(
static_cast<const void *
>(&buffer[0]), count, offset);
624 const int save_errno =
error.GetError();
626 response.
Printf(
"%zx", count);
633 response.
Printf(
"-1,%x", EINVAL);
649 if (llvm::sys::fs::file_size(path, Size))
675 if (mode != llvm::sys::fs::perms_not_known)
676 response.
Printf(
"F%x", mode);
691 bool retcode = llvm::sys::fs::exists(path);
707 packet.
SetFilePos(::strlen(
"vFile:symlink:"));
708 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