1 //===-- PlatformRemoteGDBServer.cpp -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "PlatformRemoteGDBServer.h"
11 #include "lldb/Host/Config.h"
12 
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Error.h"
19 #include "lldb/Core/Log.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/ModuleList.h"
22 #include "lldb/Core/ModuleSpec.h"
23 #include "lldb/Core/PluginManager.h"
24 #include "lldb/Core/StreamFile.h"
25 #include "lldb/Core/StreamString.h"
26 #include "lldb/Host/ConnectionFileDescriptor.h"
27 #include "lldb/Host/FileSpec.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Host/HostInfo.h"
30 #include "lldb/Host/StringConvert.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Target/Target.h"
33 
34 #include "Utility/UriParser.h"
35 
36 #include "Plugins/Process/Utility/GDBRemoteSignals.h"
37 
38 using namespace lldb;
39 using namespace lldb_private;
40 using namespace lldb_private::platform_gdb_server;
41 
42 static bool g_initialized = false;
43 
44 void PlatformRemoteGDBServer::Initialize() {
45   Platform::Initialize();
46 
47   if (g_initialized == false) {
48     g_initialized = true;
49     PluginManager::RegisterPlugin(
50         PlatformRemoteGDBServer::GetPluginNameStatic(),
51         PlatformRemoteGDBServer::GetDescriptionStatic(),
52         PlatformRemoteGDBServer::CreateInstance);
53   }
54 }
55 
56 void PlatformRemoteGDBServer::Terminate() {
57   if (g_initialized) {
58     g_initialized = false;
59     PluginManager::UnregisterPlugin(PlatformRemoteGDBServer::CreateInstance);
60   }
61 
62   Platform::Terminate();
63 }
64 
65 PlatformSP PlatformRemoteGDBServer::CreateInstance(bool force,
66                                                    const ArchSpec *arch) {
67   bool create = force;
68   if (!create) {
69     create = !arch->TripleVendorWasSpecified() && !arch->TripleOSWasSpecified();
70   }
71   if (create)
72     return PlatformSP(new PlatformRemoteGDBServer());
73   return PlatformSP();
74 }
75 
76 ConstString PlatformRemoteGDBServer::GetPluginNameStatic() {
77   static ConstString g_name("remote-gdb-server");
78   return g_name;
79 }
80 
81 const char *PlatformRemoteGDBServer::GetDescriptionStatic() {
82   return "A platform that uses the GDB remote protocol as the communication "
83          "transport.";
84 }
85 
86 const char *PlatformRemoteGDBServer::GetDescription() {
87   if (m_platform_description.empty()) {
88     if (IsConnected()) {
89       // Send the get description packet
90     }
91   }
92 
93   if (!m_platform_description.empty())
94     return m_platform_description.c_str();
95   return GetDescriptionStatic();
96 }
97 
98 Error PlatformRemoteGDBServer::ResolveExecutable(
99     const ModuleSpec &module_spec, lldb::ModuleSP &exe_module_sp,
100     const FileSpecList *module_search_paths_ptr) {
101   // copied from PlatformRemoteiOS
102 
103   Error error;
104   // Nothing special to do here, just use the actual file and architecture
105 
106   ModuleSpec resolved_module_spec(module_spec);
107 
108   // Resolve any executable within an apk on Android?
109   // Host::ResolveExecutableInBundle (resolved_module_spec.GetFileSpec());
110 
111   if (resolved_module_spec.GetFileSpec().Exists() ||
112       module_spec.GetUUID().IsValid()) {
113     if (resolved_module_spec.GetArchitecture().IsValid() ||
114         resolved_module_spec.GetUUID().IsValid()) {
115       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
116                                           module_search_paths_ptr, NULL, NULL);
117 
118       if (exe_module_sp && exe_module_sp->GetObjectFile())
119         return error;
120       exe_module_sp.reset();
121     }
122     // No valid architecture was specified or the exact arch wasn't
123     // found so ask the platform for the architectures that we should be
124     // using (in the correct order) and see if we can find a match that way
125     StreamString arch_names;
126     for (uint32_t idx = 0; GetSupportedArchitectureAtIndex(
127              idx, resolved_module_spec.GetArchitecture());
128          ++idx) {
129       error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
130                                           module_search_paths_ptr, NULL, NULL);
131       // Did we find an executable using one of the
132       if (error.Success()) {
133         if (exe_module_sp && exe_module_sp->GetObjectFile())
134           break;
135         else
136           error.SetErrorToGenericError();
137       }
138 
139       if (idx > 0)
140         arch_names.PutCString(", ");
141       arch_names.PutCString(
142           resolved_module_spec.GetArchitecture().GetArchitectureName());
143     }
144 
145     if (error.Fail() || !exe_module_sp) {
146       if (resolved_module_spec.GetFileSpec().Readable()) {
147         error.SetErrorStringWithFormat(
148             "'%s' doesn't contain any '%s' platform architectures: %s",
149             resolved_module_spec.GetFileSpec().GetPath().c_str(),
150             GetPluginName().GetCString(), arch_names.GetString().c_str());
151       } else {
152         error.SetErrorStringWithFormat(
153             "'%s' is not readable",
154             resolved_module_spec.GetFileSpec().GetPath().c_str());
155       }
156     }
157   } else {
158     error.SetErrorStringWithFormat(
159         "'%s' does not exist",
160         resolved_module_spec.GetFileSpec().GetPath().c_str());
161   }
162 
163   return error;
164 }
165 
166 bool PlatformRemoteGDBServer::GetModuleSpec(const FileSpec &module_file_spec,
167                                             const ArchSpec &arch,
168                                             ModuleSpec &module_spec) {
169   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
170 
171   const auto module_path = module_file_spec.GetPath(false);
172 
173   if (!m_gdb_client.GetModuleInfo(module_file_spec, arch, module_spec)) {
174     if (log)
175       log->Printf(
176           "PlatformRemoteGDBServer::%s - failed to get module info for %s:%s",
177           __FUNCTION__, module_path.c_str(),
178           arch.GetTriple().getTriple().c_str());
179     return false;
180   }
181 
182   if (log) {
183     StreamString stream;
184     module_spec.Dump(stream);
185     log->Printf(
186         "PlatformRemoteGDBServer::%s - got module info for (%s:%s) : %s",
187         __FUNCTION__, module_path.c_str(), arch.GetTriple().getTriple().c_str(),
188         stream.GetString().c_str());
189   }
190 
191   return true;
192 }
193 
194 Error PlatformRemoteGDBServer::GetFileWithUUID(const FileSpec &platform_file,
195                                                const UUID *uuid_ptr,
196                                                FileSpec &local_file) {
197   // Default to the local case
198   local_file = platform_file;
199   return Error();
200 }
201 
202 //------------------------------------------------------------------
203 /// Default Constructor
204 //------------------------------------------------------------------
205 PlatformRemoteGDBServer::PlatformRemoteGDBServer()
206     : Platform(false), // This is a remote platform
207       m_gdb_client() {}
208 
209 //------------------------------------------------------------------
210 /// Destructor.
211 ///
212 /// The destructor is virtual since this class is designed to be
213 /// inherited from by the plug-in instance.
214 //------------------------------------------------------------------
215 PlatformRemoteGDBServer::~PlatformRemoteGDBServer() {}
216 
217 bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx,
218                                                               ArchSpec &arch) {
219   ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture();
220 
221   if (idx == 0) {
222     arch = remote_arch;
223     return arch.IsValid();
224   } else if (idx == 1 && remote_arch.IsValid() &&
225              remote_arch.GetTriple().isArch64Bit()) {
226     arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant());
227     return arch.IsValid();
228   }
229   return false;
230 }
231 
232 size_t PlatformRemoteGDBServer::GetSoftwareBreakpointTrapOpcode(
233     Target &target, BreakpointSite *bp_site) {
234   // This isn't needed if the z/Z packets are supported in the GDB remote
235   // server. But we might need a packet to detect this.
236   return 0;
237 }
238 
239 bool PlatformRemoteGDBServer::GetRemoteOSVersion() {
240   uint32_t major, minor, update;
241   if (m_gdb_client.GetOSVersion(major, minor, update)) {
242     m_major_os_version = major;
243     m_minor_os_version = minor;
244     m_update_os_version = update;
245     return true;
246   }
247   return false;
248 }
249 
250 bool PlatformRemoteGDBServer::GetRemoteOSBuildString(std::string &s) {
251   return m_gdb_client.GetOSBuildString(s);
252 }
253 
254 bool PlatformRemoteGDBServer::GetRemoteOSKernelDescription(std::string &s) {
255   return m_gdb_client.GetOSKernelDescription(s);
256 }
257 
258 // Remote Platform subclasses need to override this function
259 ArchSpec PlatformRemoteGDBServer::GetRemoteSystemArchitecture() {
260   return m_gdb_client.GetSystemArchitecture();
261 }
262 
263 FileSpec PlatformRemoteGDBServer::GetRemoteWorkingDirectory() {
264   if (IsConnected()) {
265     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
266     FileSpec working_dir;
267     if (m_gdb_client.GetWorkingDir(working_dir) && log)
268       log->Printf(
269           "PlatformRemoteGDBServer::GetRemoteWorkingDirectory() -> '%s'",
270           working_dir.GetCString());
271     return working_dir;
272   } else {
273     return Platform::GetRemoteWorkingDirectory();
274   }
275 }
276 
277 bool PlatformRemoteGDBServer::SetRemoteWorkingDirectory(
278     const FileSpec &working_dir) {
279   if (IsConnected()) {
280     // Clear the working directory it case it doesn't get set correctly. This
281     // will
282     // for use to re-read it
283     Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
284     if (log)
285       log->Printf("PlatformRemoteGDBServer::SetRemoteWorkingDirectory('%s')",
286                   working_dir.GetCString());
287     return m_gdb_client.SetWorkingDir(working_dir) == 0;
288   } else
289     return Platform::SetRemoteWorkingDirectory(working_dir);
290 }
291 
292 bool PlatformRemoteGDBServer::IsConnected() const {
293   return m_gdb_client.IsConnected();
294 }
295 
296 Error PlatformRemoteGDBServer::ConnectRemote(Args &args) {
297   Error error;
298   if (IsConnected()) {
299     error.SetErrorStringWithFormat("the platform is already connected to '%s', "
300                                    "execute 'platform disconnect' to close the "
301                                    "current connection",
302                                    GetHostname());
303   } else {
304     if (args.GetArgumentCount() == 1) {
305       m_gdb_client.SetConnection(new ConnectionFileDescriptor());
306       // we're going to reuse the hostname when we connect to the debugserver
307       int port;
308       std::string path;
309       const char *url = args.GetArgumentAtIndex(0);
310       if (!url)
311         return Error("URL is null.");
312       if (!UriParser::Parse(url, m_platform_scheme, m_platform_hostname, port,
313                             path))
314         return Error("Invalid URL: %s", url);
315 
316       const ConnectionStatus status = m_gdb_client.Connect(url, &error);
317       if (status == eConnectionStatusSuccess) {
318         if (m_gdb_client.HandshakeWithServer(&error)) {
319           m_gdb_client.GetHostInfo();
320           // If a working directory was set prior to connecting, send it down
321           // now
322           if (m_working_dir)
323             m_gdb_client.SetWorkingDir(m_working_dir);
324         } else {
325           m_gdb_client.Disconnect();
326           if (error.Success())
327             error.SetErrorString("handshake failed");
328         }
329       }
330     } else {
331       error.SetErrorString(
332           "\"platform connect\" takes a single argument: <connect-url>");
333     }
334   }
335   return error;
336 }
337 
338 Error PlatformRemoteGDBServer::DisconnectRemote() {
339   Error error;
340   m_gdb_client.Disconnect(&error);
341   m_remote_signals_sp.reset();
342   return error;
343 }
344 
345 const char *PlatformRemoteGDBServer::GetHostname() {
346   m_gdb_client.GetHostname(m_name);
347   if (m_name.empty())
348     return NULL;
349   return m_name.c_str();
350 }
351 
352 const char *PlatformRemoteGDBServer::GetUserName(uint32_t uid) {
353   // Try and get a cache user name first
354   const char *cached_user_name = Platform::GetUserName(uid);
355   if (cached_user_name)
356     return cached_user_name;
357   std::string name;
358   if (m_gdb_client.GetUserName(uid, name))
359     return SetCachedUserName(uid, name.c_str(), name.size());
360 
361   SetUserNameNotFound(uid); // Negative cache so we don't keep sending packets
362   return NULL;
363 }
364 
365 const char *PlatformRemoteGDBServer::GetGroupName(uint32_t gid) {
366   const char *cached_group_name = Platform::GetGroupName(gid);
367   if (cached_group_name)
368     return cached_group_name;
369   std::string name;
370   if (m_gdb_client.GetGroupName(gid, name))
371     return SetCachedGroupName(gid, name.c_str(), name.size());
372 
373   SetGroupNameNotFound(gid); // Negative cache so we don't keep sending packets
374   return NULL;
375 }
376 
377 uint32_t PlatformRemoteGDBServer::FindProcesses(
378     const ProcessInstanceInfoMatch &match_info,
379     ProcessInstanceInfoList &process_infos) {
380   return m_gdb_client.FindProcesses(match_info, process_infos);
381 }
382 
383 bool PlatformRemoteGDBServer::GetProcessInfo(
384     lldb::pid_t pid, ProcessInstanceInfo &process_info) {
385   return m_gdb_client.GetProcessInfo(pid, process_info);
386 }
387 
388 Error PlatformRemoteGDBServer::LaunchProcess(ProcessLaunchInfo &launch_info) {
389   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
390   Error error;
391 
392   if (log)
393     log->Printf("PlatformRemoteGDBServer::%s() called", __FUNCTION__);
394 
395   auto num_file_actions = launch_info.GetNumFileActions();
396   for (decltype(num_file_actions) i = 0; i < num_file_actions; ++i) {
397     const auto file_action = launch_info.GetFileActionAtIndex(i);
398     if (file_action->GetAction() != FileAction::eFileActionOpen)
399       continue;
400     switch (file_action->GetFD()) {
401     case STDIN_FILENO:
402       m_gdb_client.SetSTDIN(file_action->GetFileSpec());
403       break;
404     case STDOUT_FILENO:
405       m_gdb_client.SetSTDOUT(file_action->GetFileSpec());
406       break;
407     case STDERR_FILENO:
408       m_gdb_client.SetSTDERR(file_action->GetFileSpec());
409       break;
410     }
411   }
412 
413   m_gdb_client.SetDisableASLR(
414       launch_info.GetFlags().Test(eLaunchFlagDisableASLR));
415   m_gdb_client.SetDetachOnError(
416       launch_info.GetFlags().Test(eLaunchFlagDetachOnError));
417 
418   FileSpec working_dir = launch_info.GetWorkingDirectory();
419   if (working_dir) {
420     m_gdb_client.SetWorkingDir(working_dir);
421   }
422 
423   // Send the environment and the program + arguments after we connect
424   const char **envp =
425       launch_info.GetEnvironmentEntries().GetConstArgumentVector();
426 
427   if (envp) {
428     const char *env_entry;
429     for (int i = 0; (env_entry = envp[i]); ++i) {
430       if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0)
431         break;
432     }
433   }
434 
435   ArchSpec arch_spec = launch_info.GetArchitecture();
436   const char *arch_triple = arch_spec.GetTriple().str().c_str();
437 
438   m_gdb_client.SendLaunchArchPacket(arch_triple);
439   if (log)
440     log->Printf(
441         "PlatformRemoteGDBServer::%s() set launch architecture triple to '%s'",
442         __FUNCTION__, arch_triple ? arch_triple : "<NULL>");
443 
444   int arg_packet_err;
445   {
446     // Scope for the scoped timeout object
447     process_gdb_remote::GDBRemoteCommunication::ScopedTimeout timeout(
448         m_gdb_client, 5);
449     arg_packet_err = m_gdb_client.SendArgumentsPacket(launch_info);
450   }
451 
452   if (arg_packet_err == 0) {
453     std::string error_str;
454     if (m_gdb_client.GetLaunchSuccess(error_str)) {
455       const auto pid = m_gdb_client.GetCurrentProcessID(false);
456       if (pid != LLDB_INVALID_PROCESS_ID) {
457         launch_info.SetProcessID(pid);
458         if (log)
459           log->Printf("PlatformRemoteGDBServer::%s() pid %" PRIu64
460                       " launched successfully",
461                       __FUNCTION__, pid);
462       } else {
463         if (log)
464           log->Printf("PlatformRemoteGDBServer::%s() launch succeeded but we "
465                       "didn't get a valid process id back!",
466                       __FUNCTION__);
467         error.SetErrorString("failed to get PID");
468       }
469     } else {
470       error.SetErrorString(error_str.c_str());
471       if (log)
472         log->Printf("PlatformRemoteGDBServer::%s() launch failed: %s",
473                     __FUNCTION__, error.AsCString());
474     }
475   } else {
476     error.SetErrorStringWithFormat("'A' packet returned an error: %i",
477                                    arg_packet_err);
478   }
479   return error;
480 }
481 
482 Error PlatformRemoteGDBServer::KillProcess(const lldb::pid_t pid) {
483   if (!KillSpawnedProcess(pid))
484     return Error("failed to kill remote spawned process");
485   return Error();
486 }
487 
488 lldb::ProcessSP PlatformRemoteGDBServer::DebugProcess(
489     ProcessLaunchInfo &launch_info, Debugger &debugger,
490     Target *target, // Can be NULL, if NULL create a new target, else use
491                     // existing one
492     Error &error) {
493   lldb::ProcessSP process_sp;
494   if (IsRemote()) {
495     if (IsConnected()) {
496       lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
497       std::string connect_url;
498       if (!LaunchGDBServer(debugserver_pid, connect_url)) {
499         error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'",
500                                        GetHostname());
501       } else {
502         if (target == NULL) {
503           TargetSP new_target_sp;
504 
505           error = debugger.GetTargetList().CreateTarget(
506               debugger, NULL, NULL, false, NULL, new_target_sp);
507           target = new_target_sp.get();
508         } else
509           error.Clear();
510 
511         if (target && error.Success()) {
512           debugger.GetTargetList().SetSelectedTarget(target);
513 
514           // The darwin always currently uses the GDB remote debugger plug-in
515           // so even when debugging locally we are debugging remotely!
516           process_sp = target->CreateProcess(
517               launch_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
518 
519           if (process_sp) {
520             error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
521             // Retry the connect remote one time...
522             if (error.Fail())
523               error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
524             if (error.Success())
525               error = process_sp->Launch(launch_info);
526             else if (debugserver_pid != LLDB_INVALID_PROCESS_ID) {
527               printf("error: connect remote failed (%s)\n", error.AsCString());
528               KillSpawnedProcess(debugserver_pid);
529             }
530           }
531         }
532       }
533     } else {
534       error.SetErrorString("not connected to remote gdb server");
535     }
536   }
537   return process_sp;
538 }
539 
540 bool PlatformRemoteGDBServer::LaunchGDBServer(lldb::pid_t &pid,
541                                               std::string &connect_url) {
542   ArchSpec remote_arch = GetRemoteSystemArchitecture();
543   llvm::Triple &remote_triple = remote_arch.GetTriple();
544 
545   uint16_t port = 0;
546   std::string socket_name;
547   bool launch_result = false;
548   if (remote_triple.getVendor() == llvm::Triple::Apple &&
549       remote_triple.getOS() == llvm::Triple::IOS) {
550     // When remote debugging to iOS, we use a USB mux that always talks
551     // to localhost, so we will need the remote debugserver to accept
552     // connections
553     // only from localhost, no matter what our current hostname is
554     launch_result =
555         m_gdb_client.LaunchGDBServer("127.0.0.1", pid, port, socket_name);
556   } else {
557     // All other hosts should use their actual hostname
558     launch_result =
559         m_gdb_client.LaunchGDBServer(nullptr, pid, port, socket_name);
560   }
561 
562   if (!launch_result)
563     return false;
564 
565   connect_url =
566       MakeGdbServerUrl(m_platform_scheme, m_platform_hostname, port,
567                        (socket_name.empty()) ? nullptr : socket_name.c_str());
568   return true;
569 }
570 
571 bool PlatformRemoteGDBServer::KillSpawnedProcess(lldb::pid_t pid) {
572   return m_gdb_client.KillSpawnedProcess(pid);
573 }
574 
575 lldb::ProcessSP PlatformRemoteGDBServer::Attach(
576     ProcessAttachInfo &attach_info, Debugger &debugger,
577     Target *target, // Can be NULL, if NULL create a new target, else use
578                     // existing one
579     Error &error) {
580   lldb::ProcessSP process_sp;
581   if (IsRemote()) {
582     if (IsConnected()) {
583       lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
584       std::string connect_url;
585       if (!LaunchGDBServer(debugserver_pid, connect_url)) {
586         error.SetErrorStringWithFormat("unable to launch a GDB server on '%s'",
587                                        GetHostname());
588       } else {
589         if (target == NULL) {
590           TargetSP new_target_sp;
591 
592           error = debugger.GetTargetList().CreateTarget(
593               debugger, NULL, NULL, false, NULL, new_target_sp);
594           target = new_target_sp.get();
595         } else
596           error.Clear();
597 
598         if (target && error.Success()) {
599           debugger.GetTargetList().SetSelectedTarget(target);
600 
601           // The darwin always currently uses the GDB remote debugger plug-in
602           // so even when debugging locally we are debugging remotely!
603           process_sp = target->CreateProcess(
604               attach_info.GetListenerForProcess(debugger), "gdb-remote", NULL);
605           if (process_sp) {
606             error = process_sp->ConnectRemote(nullptr, connect_url.c_str());
607             if (error.Success()) {
608               ListenerSP listener_sp = attach_info.GetHijackListener();
609               if (listener_sp)
610                 process_sp->HijackProcessEvents(listener_sp);
611               error = process_sp->Attach(attach_info);
612             }
613 
614             if (error.Fail() && debugserver_pid != LLDB_INVALID_PROCESS_ID) {
615               KillSpawnedProcess(debugserver_pid);
616             }
617           }
618         }
619       }
620     } else {
621       error.SetErrorString("not connected to remote gdb server");
622     }
623   }
624   return process_sp;
625 }
626 
627 Error PlatformRemoteGDBServer::MakeDirectory(const FileSpec &file_spec,
628                                              uint32_t mode) {
629   Error error = m_gdb_client.MakeDirectory(file_spec, mode);
630   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
631   if (log)
632     log->Printf("PlatformRemoteGDBServer::MakeDirectory(path='%s', mode=%o) "
633                 "error = %u (%s)",
634                 file_spec.GetCString(), mode, error.GetError(),
635                 error.AsCString());
636   return error;
637 }
638 
639 Error PlatformRemoteGDBServer::GetFilePermissions(const FileSpec &file_spec,
640                                                   uint32_t &file_permissions) {
641   Error error = m_gdb_client.GetFilePermissions(file_spec, file_permissions);
642   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
643   if (log)
644     log->Printf("PlatformRemoteGDBServer::GetFilePermissions(path='%s', "
645                 "file_permissions=%o) error = %u (%s)",
646                 file_spec.GetCString(), file_permissions, error.GetError(),
647                 error.AsCString());
648   return error;
649 }
650 
651 Error PlatformRemoteGDBServer::SetFilePermissions(const FileSpec &file_spec,
652                                                   uint32_t file_permissions) {
653   Error error = m_gdb_client.SetFilePermissions(file_spec, file_permissions);
654   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
655   if (log)
656     log->Printf("PlatformRemoteGDBServer::SetFilePermissions(path='%s', "
657                 "file_permissions=%o) error = %u (%s)",
658                 file_spec.GetCString(), file_permissions, error.GetError(),
659                 error.AsCString());
660   return error;
661 }
662 
663 lldb::user_id_t PlatformRemoteGDBServer::OpenFile(const FileSpec &file_spec,
664                                                   uint32_t flags, uint32_t mode,
665                                                   Error &error) {
666   return m_gdb_client.OpenFile(file_spec, flags, mode, error);
667 }
668 
669 bool PlatformRemoteGDBServer::CloseFile(lldb::user_id_t fd, Error &error) {
670   return m_gdb_client.CloseFile(fd, error);
671 }
672 
673 lldb::user_id_t
674 PlatformRemoteGDBServer::GetFileSize(const FileSpec &file_spec) {
675   return m_gdb_client.GetFileSize(file_spec);
676 }
677 
678 uint64_t PlatformRemoteGDBServer::ReadFile(lldb::user_id_t fd, uint64_t offset,
679                                            void *dst, uint64_t dst_len,
680                                            Error &error) {
681   return m_gdb_client.ReadFile(fd, offset, dst, dst_len, error);
682 }
683 
684 uint64_t PlatformRemoteGDBServer::WriteFile(lldb::user_id_t fd, uint64_t offset,
685                                             const void *src, uint64_t src_len,
686                                             Error &error) {
687   return m_gdb_client.WriteFile(fd, offset, src, src_len, error);
688 }
689 
690 Error PlatformRemoteGDBServer::PutFile(const FileSpec &source,
691                                        const FileSpec &destination,
692                                        uint32_t uid, uint32_t gid) {
693   return Platform::PutFile(source, destination, uid, gid);
694 }
695 
696 Error PlatformRemoteGDBServer::CreateSymlink(
697     const FileSpec &src, // The name of the link is in src
698     const FileSpec &dst) // The symlink points to dst
699 {
700   Error error = m_gdb_client.CreateSymlink(src, dst);
701   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
702   if (log)
703     log->Printf("PlatformRemoteGDBServer::CreateSymlink(src='%s', dst='%s') "
704                 "error = %u (%s)",
705                 src.GetCString(), dst.GetCString(), error.GetError(),
706                 error.AsCString());
707   return error;
708 }
709 
710 Error PlatformRemoteGDBServer::Unlink(const FileSpec &file_spec) {
711   Error error = m_gdb_client.Unlink(file_spec);
712   Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
713   if (log)
714     log->Printf("PlatformRemoteGDBServer::Unlink(path='%s') error = %u (%s)",
715                 file_spec.GetCString(), error.GetError(), error.AsCString());
716   return error;
717 }
718 
719 bool PlatformRemoteGDBServer::GetFileExists(const FileSpec &file_spec) {
720   return m_gdb_client.GetFileExists(file_spec);
721 }
722 
723 Error PlatformRemoteGDBServer::RunShellCommand(
724     const char *command, // Shouldn't be NULL
725     const FileSpec &
726         working_dir, // Pass empty FileSpec to use the current working directory
727     int *status_ptr, // Pass NULL if you don't want the process exit status
728     int *signo_ptr,  // Pass NULL if you don't want the signal that caused the
729                      // process to exit
730     std::string
731         *command_output, // Pass NULL if you don't want the command output
732     uint32_t
733         timeout_sec) // Timeout in seconds to wait for shell program to finish
734 {
735   return m_gdb_client.RunShellCommand(command, working_dir, status_ptr,
736                                       signo_ptr, command_output, timeout_sec);
737 }
738 
739 void PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames() {
740   m_trap_handlers.push_back(ConstString("_sigtramp"));
741 }
742 
743 const UnixSignalsSP &PlatformRemoteGDBServer::GetRemoteUnixSignals() {
744   if (!IsConnected())
745     return Platform::GetRemoteUnixSignals();
746 
747   if (m_remote_signals_sp)
748     return m_remote_signals_sp;
749 
750   // If packet not implemented or JSON failed to parse,
751   // we'll guess the signal set based on the remote architecture.
752   m_remote_signals_sp = UnixSignals::Create(GetRemoteSystemArchitecture());
753 
754   StringExtractorGDBRemote response;
755   auto result = m_gdb_client.SendPacketAndWaitForResponse("jSignalsInfo",
756                                                           response, false);
757 
758   if (result != decltype(result)::Success ||
759       response.GetResponseType() != response.eResponse)
760     return m_remote_signals_sp;
761 
762   auto object_sp = StructuredData::ParseJSON(response.GetStringRef());
763   if (!object_sp || !object_sp->IsValid())
764     return m_remote_signals_sp;
765 
766   auto array_sp = object_sp->GetAsArray();
767   if (!array_sp || !array_sp->IsValid())
768     return m_remote_signals_sp;
769 
770   auto remote_signals_sp = std::make_shared<lldb_private::GDBRemoteSignals>();
771 
772   bool done = array_sp->ForEach(
773       [&remote_signals_sp](StructuredData::Object *object) -> bool {
774         if (!object || !object->IsValid())
775           return false;
776 
777         auto dict = object->GetAsDictionary();
778         if (!dict || !dict->IsValid())
779           return false;
780 
781         // Signal number and signal name are required.
782         int signo;
783         if (!dict->GetValueForKeyAsInteger("signo", signo))
784           return false;
785 
786         std::string name;
787         if (!dict->GetValueForKeyAsString("name", name))
788           return false;
789 
790         // We can live without short_name, description, etc.
791         bool suppress{false};
792         auto object_sp = dict->GetValueForKey("suppress");
793         if (object_sp && object_sp->IsValid())
794           suppress = object_sp->GetBooleanValue();
795 
796         bool stop{false};
797         object_sp = dict->GetValueForKey("stop");
798         if (object_sp && object_sp->IsValid())
799           stop = object_sp->GetBooleanValue();
800 
801         bool notify{false};
802         object_sp = dict->GetValueForKey("notify");
803         if (object_sp && object_sp->IsValid())
804           notify = object_sp->GetBooleanValue();
805 
806         std::string description{""};
807         object_sp = dict->GetValueForKey("description");
808         if (object_sp && object_sp->IsValid())
809           description = object_sp->GetStringValue();
810 
811         remote_signals_sp->AddSignal(signo, name.c_str(), suppress, stop,
812                                      notify, description.c_str());
813         return true;
814       });
815 
816   if (done)
817     m_remote_signals_sp = std::move(remote_signals_sp);
818 
819   return m_remote_signals_sp;
820 }
821 
822 std::string PlatformRemoteGDBServer::MakeGdbServerUrl(
823     const std::string &platform_scheme, const std::string &platform_hostname,
824     uint16_t port, const char *socket_name) {
825   const char *override_scheme =
826       getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_SCHEME");
827   const char *override_hostname =
828       getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_HOSTNAME");
829   const char *port_offset_c_str =
830       getenv("LLDB_PLATFORM_REMOTE_GDB_SERVER_PORT_OFFSET");
831   int port_offset = port_offset_c_str ? ::atoi(port_offset_c_str) : 0;
832 
833   return MakeUrl(override_scheme ? override_scheme : platform_scheme.c_str(),
834                  override_hostname ? override_hostname
835                                    : platform_hostname.c_str(),
836                  port + port_offset, socket_name);
837 }
838 
839 std::string PlatformRemoteGDBServer::MakeUrl(const char *scheme,
840                                              const char *hostname,
841                                              uint16_t port, const char *path) {
842   StreamString result;
843   result.Printf("%s://%s", scheme, hostname);
844   if (port != 0)
845     result.Printf(":%u", port);
846   if (path)
847     result.Write(path, strlen(path));
848   return result.GetString();
849 }
850 
851 lldb::ProcessSP PlatformRemoteGDBServer::ConnectProcess(
852     const char *connect_url, const char *plugin_name,
853     lldb_private::Debugger &debugger, lldb_private::Target *target,
854     lldb_private::Error &error) {
855   if (!IsRemote() || !IsConnected()) {
856     error.SetErrorString("Not connected to remote gdb server");
857     return nullptr;
858   }
859   return Platform::ConnectProcess(connect_url, plugin_name, debugger, target,
860                                   error);
861 }
862 
863 size_t PlatformRemoteGDBServer::ConnectToWaitingProcesses(Debugger &debugger,
864                                                           Error &error) {
865   std::vector<std::string> connection_urls;
866   GetPendingGdbServerList(connection_urls);
867 
868   for (size_t i = 0; i < connection_urls.size(); ++i) {
869     ConnectProcess(connection_urls[i].c_str(), nullptr, debugger, nullptr,
870                    error);
871     if (error.Fail())
872       return i; // We already connected to i process succsessfully
873   }
874   return connection_urls.size();
875 }
876 
877 size_t PlatformRemoteGDBServer::GetPendingGdbServerList(
878     std::vector<std::string> &connection_urls) {
879   std::vector<std::pair<uint16_t, std::string>> remote_servers;
880   m_gdb_client.QueryGDBServer(remote_servers);
881   for (const auto &gdbserver : remote_servers) {
882     const char *socket_name_cstr =
883         gdbserver.second.empty() ? nullptr : gdbserver.second.c_str();
884     connection_urls.emplace_back(
885         MakeGdbServerUrl(m_platform_scheme, m_platform_hostname,
886                          gdbserver.first, socket_name_cstr));
887   }
888   return connection_urls.size();
889 }
890