Coverage Report

Created: 2023-11-11 10:31

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- GDBRemoteCommunicationServerPlatform.cpp --------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "GDBRemoteCommunicationServerPlatform.h"
10
11
#include <cerrno>
12
13
#include <chrono>
14
#include <csignal>
15
#include <cstring>
16
#include <mutex>
17
#include <optional>
18
#include <sstream>
19
#include <thread>
20
21
#include "llvm/Support/FileSystem.h"
22
#include "llvm/Support/JSON.h"
23
#include "llvm/Support/Threading.h"
24
25
#include "lldb/Host/Config.h"
26
#include "lldb/Host/ConnectionFileDescriptor.h"
27
#include "lldb/Host/FileAction.h"
28
#include "lldb/Host/Host.h"
29
#include "lldb/Host/HostInfo.h"
30
#include "lldb/Interpreter/CommandCompletions.h"
31
#include "lldb/Target/Platform.h"
32
#include "lldb/Target/UnixSignals.h"
33
#include "lldb/Utility/GDBRemote.h"
34
#include "lldb/Utility/LLDBLog.h"
35
#include "lldb/Utility/Log.h"
36
#include "lldb/Utility/StreamString.h"
37
#include "lldb/Utility/StructuredData.h"
38
#include "lldb/Utility/TildeExpressionResolver.h"
39
#include "lldb/Utility/UriParser.h"
40
41
#include "lldb/Utility/StringExtractorGDBRemote.h"
42
43
using namespace lldb;
44
using namespace lldb_private::process_gdb_remote;
45
using namespace lldb_private;
46
47
GDBRemoteCommunicationServerPlatform::PortMap::PortMap(uint16_t min_port,
48
2
                                                       uint16_t max_port) {
49
8
  for (; min_port < max_port; 
++min_port6
)
50
6
    m_port_map[min_port] = LLDB_INVALID_PROCESS_ID;
51
2
}
52
53
6
void GDBRemoteCommunicationServerPlatform::PortMap::AllowPort(uint16_t port) {
54
  // Do not modify existing mappings
55
6
  m_port_map.insert({port, LLDB_INVALID_PROCESS_ID});
56
6
}
57
58
llvm::Expected<uint16_t>
59
12
GDBRemoteCommunicationServerPlatform::PortMap::GetNextAvailablePort() {
60
12
  if (m_port_map.empty())
61
1
    return 0; // Bind to port zero and get a port, we didn't have any
62
              // limitations
63
64
22
  
for (auto &pair : m_port_map)11
{
65
22
    if (pair.second == LLDB_INVALID_PROCESS_ID) {
66
7
      pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
67
7
      return pair.first;
68
7
    }
69
22
  }
70
4
  return llvm::createStringError(llvm::inconvertibleErrorCode(),
71
4
                                 "No free port found in port map");
72
11
}
73
74
bool GDBRemoteCommunicationServerPlatform::PortMap::AssociatePortWithProcess(
75
10
    uint16_t port, lldb::pid_t pid) {
76
10
  auto pos = m_port_map.find(port);
77
10
  if (pos != m_port_map.end()) {
78
10
    pos->second = pid;
79
10
    return true;
80
10
  }
81
0
  return false;
82
10
}
83
84
3
bool GDBRemoteCommunicationServerPlatform::PortMap::FreePort(uint16_t port) {
85
3
  std::map<uint16_t, lldb::pid_t>::iterator pos = m_port_map.find(port);
86
3
  if (pos != m_port_map.end()) {
87
1
    pos->second = LLDB_INVALID_PROCESS_ID;
88
1
    return true;
89
1
  }
90
2
  return false;
91
3
}
92
93
bool GDBRemoteCommunicationServerPlatform::PortMap::FreePortForProcess(
94
4
    lldb::pid_t pid) {
95
4
  if (!m_port_map.empty()) {
96
7
    for (auto &pair : m_port_map) {
97
7
      if (pair.second == pid) {
98
2
        pair.second = LLDB_INVALID_PROCESS_ID;
99
2
        return true;
100
2
      }
101
7
    }
102
4
  }
103
2
  return false;
104
4
}
105
106
3
bool GDBRemoteCommunicationServerPlatform::PortMap::empty() const {
107
3
  return m_port_map.empty();
108
3
}
109
110
// GDBRemoteCommunicationServerPlatform constructor
111
GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
112
    const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
113
0
    : GDBRemoteCommunicationServerCommon(),
114
0
      m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
115
0
      m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
116
0
  m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
117
0
  m_pending_gdb_server.port = 0;
118
119
0
  RegisterMemberFunctionHandler(
120
0
      StringExtractorGDBRemote::eServerPacketType_qC,
121
0
      &GDBRemoteCommunicationServerPlatform::Handle_qC);
122
0
  RegisterMemberFunctionHandler(
123
0
      StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
124
0
      &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
125
0
  RegisterMemberFunctionHandler(
126
0
      StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
127
0
      &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
128
0
  RegisterMemberFunctionHandler(
129
0
      StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
130
0
      &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
131
0
  RegisterMemberFunctionHandler(
132
0
      StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
133
0
      &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
134
0
  RegisterMemberFunctionHandler(
135
0
      StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
136
0
      &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
137
0
  RegisterMemberFunctionHandler(
138
0
      StringExtractorGDBRemote::eServerPacketType_qPathComplete,
139
0
      &GDBRemoteCommunicationServerPlatform::Handle_qPathComplete);
140
0
  RegisterMemberFunctionHandler(
141
0
      StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
142
0
      &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
143
0
  RegisterMemberFunctionHandler(
144
0
      StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
145
0
      &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
146
147
0
  RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
148
0
                        [](StringExtractorGDBRemote packet, Status &error,
149
0
                           bool &interrupt, bool &quit) {
150
0
                          error.SetErrorString("interrupt received");
151
0
                          interrupt = true;
152
0
                          return PacketResult::Success;
153
0
                        });
154
0
}
155
156
// Destructor
157
0
GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() =
158
    default;
159
160
Status GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
161
    const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
162
0
    std::optional<uint16_t> &port, std::string &socket_name) {
163
0
  if (!port) {
164
0
    llvm::Expected<uint16_t> available_port = m_port_map.GetNextAvailablePort();
165
0
    if (available_port)
166
0
      port = *available_port;
167
0
    else
168
0
      return Status(available_port.takeError());
169
0
  }
170
171
  // Spawn a new thread to accept the port that gets bound after binding to
172
  // port 0 (zero).
173
174
  // ignore the hostname send from the remote end, just use the ip address that
175
  // we're currently communicating with as the hostname
176
177
  // Spawn a debugserver and try to get the port it listens to.
178
0
  ProcessLaunchInfo debugserver_launch_info;
179
0
  if (hostname.empty())
180
0
    hostname = "127.0.0.1";
181
182
0
  Log *log = GetLog(LLDBLog::Platform);
183
0
  LLDB_LOGF(log, "Launching debugserver with: %s:%u...", hostname.c_str(),
184
0
            *port);
185
186
  // Do not run in a new session so that it can not linger after the platform
187
  // closes.
188
0
  debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
189
0
  debugserver_launch_info.SetMonitorProcessCallback(
190
0
      std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
191
0
                this, std::placeholders::_1));
192
193
0
  std::ostringstream url;
194
// debugserver does not accept the URL scheme prefix.
195
#if !defined(__APPLE__)
196
  url << m_socket_scheme << "://";
197
#endif
198
0
  uint16_t *port_ptr = &*port;
199
0
  if (m_socket_protocol == Socket::ProtocolTcp) {
200
0
    std::string platform_uri = GetConnection()->GetURI();
201
0
    std::optional<URI> parsed_uri = URI::Parse(platform_uri);
202
0
    url << '[' << parsed_uri->hostname.str() << "]:" << *port;
203
0
  } else {
204
0
    socket_name = GetDomainSocketPath("gdbserver").GetPath();
205
0
    url << socket_name;
206
0
    port_ptr = nullptr;
207
0
  }
208
209
0
  Status error = StartDebugserverProcess(
210
0
      url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
211
212
0
  pid = debugserver_launch_info.GetProcessID();
213
0
  if (pid != LLDB_INVALID_PROCESS_ID) {
214
0
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
215
0
    m_spawned_pids.insert(pid);
216
0
    if (*port > 0)
217
0
      m_port_map.AssociatePortWithProcess(*port, pid);
218
0
  } else {
219
0
    if (*port > 0)
220
0
      m_port_map.FreePort(*port);
221
0
  }
222
0
  return error;
223
0
}
224
225
GDBRemoteCommunication::PacketResult
226
GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
227
0
    StringExtractorGDBRemote &packet) {
228
  // Spawn a local debugserver as a platform so we can then attach or launch a
229
  // process...
230
231
0
  Log *log = GetLog(LLDBLog::Platform);
232
0
  LLDB_LOGF(log, "GDBRemoteCommunicationServerPlatform::%s() called",
233
0
            __FUNCTION__);
234
235
0
  ConnectionFileDescriptor file_conn;
236
0
  std::string hostname;
237
0
  packet.SetFilePos(::strlen("qLaunchGDBServer;"));
238
0
  llvm::StringRef name;
239
0
  llvm::StringRef value;
240
0
  std::optional<uint16_t> port;
241
0
  while (packet.GetNameColonValue(name, value)) {
242
0
    if (name.equals("host"))
243
0
      hostname = std::string(value);
244
0
    else if (name.equals("port")) {
245
      // Make the Optional valid so we can use its value
246
0
      port = 0;
247
0
      value.getAsInteger(0, *port);
248
0
    }
249
0
  }
250
251
0
  lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
252
0
  std::string socket_name;
253
0
  Status error =
254
0
      LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
255
0
  if (error.Fail()) {
256
0
    LLDB_LOGF(log,
257
0
              "GDBRemoteCommunicationServerPlatform::%s() debugserver "
258
0
              "launch failed: %s",
259
0
              __FUNCTION__, error.AsCString());
260
0
    return SendErrorResponse(9);
261
0
  }
262
263
0
  LLDB_LOGF(log,
264
0
            "GDBRemoteCommunicationServerPlatform::%s() debugserver "
265
0
            "launched successfully as pid %" PRIu64,
266
0
            __FUNCTION__, debugserver_pid);
267
268
0
  StreamGDBRemote response;
269
0
  assert(port);
270
0
  response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
271
0
                  *port + m_port_offset);
272
0
  if (!socket_name.empty()) {
273
0
    response.PutCString("socket_name:");
274
0
    response.PutStringAsRawHex8(socket_name);
275
0
    response.PutChar(';');
276
0
  }
277
278
0
  PacketResult packet_result = SendPacketNoLock(response.GetString());
279
0
  if (packet_result != PacketResult::Success) {
280
0
    if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
281
0
      Host::Kill(debugserver_pid, SIGINT);
282
0
  }
283
0
  return packet_result;
284
0
}
285
286
GDBRemoteCommunication::PacketResult
287
GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
288
0
    StringExtractorGDBRemote &packet) {
289
0
  namespace json = llvm::json;
290
291
0
  if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
292
0
    return SendErrorResponse(4);
293
294
0
  json::Object server{{"port", m_pending_gdb_server.port}};
295
296
0
  if (!m_pending_gdb_server.socket_name.empty())
297
0
    server.try_emplace("socket_name", m_pending_gdb_server.socket_name);
298
299
0
  json::Array server_list;
300
0
  server_list.push_back(std::move(server));
301
302
0
  StreamGDBRemote response;
303
0
  response.AsRawOstream() << std::move(server_list);
304
305
0
  StreamGDBRemote escaped_response;
306
0
  escaped_response.PutEscapedBytes(response.GetString().data(),
307
0
                                   response.GetSize());
308
0
  return SendPacketNoLock(escaped_response.GetString());
309
0
}
310
311
GDBRemoteCommunication::PacketResult
312
GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
313
0
    StringExtractorGDBRemote &packet) {
314
0
  packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
315
316
0
  lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
317
318
  // verify that we know anything about this pid. Scope for locker
319
0
  {
320
0
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
321
0
    if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
322
      // not a pid we know about
323
0
      return SendErrorResponse(10);
324
0
    }
325
0
  }
326
327
  // go ahead and attempt to kill the spawned process
328
0
  if (KillSpawnedProcess(pid))
329
0
    return SendOKResponse();
330
0
  else
331
0
    return SendErrorResponse(11);
332
0
}
333
334
0
bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
335
  // make sure we know about this process
336
0
  {
337
0
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
338
0
    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
339
0
      return false;
340
0
  }
341
342
  // first try a SIGTERM (standard kill)
343
0
  Host::Kill(pid, SIGTERM);
344
345
  // check if that worked
346
0
  for (size_t i = 0; i < 10; ++i) {
347
0
    {
348
0
      std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
349
0
      if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
350
        // it is now killed
351
0
        return true;
352
0
      }
353
0
    }
354
0
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
355
0
  }
356
357
0
  {
358
0
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
359
0
    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
360
0
      return true;
361
0
  }
362
363
  // the launched process still lives.  Now try killing it again, this time
364
  // with an unblockable signal.
365
0
  Host::Kill(pid, SIGKILL);
366
367
0
  for (size_t i = 0; i < 10; ++i) {
368
0
    {
369
0
      std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
370
0
      if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
371
        // it is now killed
372
0
        return true;
373
0
      }
374
0
    }
375
0
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
376
0
  }
377
378
  // check one more time after the final sleep
379
0
  {
380
0
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
381
0
    if (m_spawned_pids.find(pid) == m_spawned_pids.end())
382
0
      return true;
383
0
  }
384
385
  // no luck - the process still lives
386
0
  return false;
387
0
}
388
389
GDBRemoteCommunication::PacketResult
390
GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
391
0
    StringExtractorGDBRemote &packet) {
392
0
  lldb::pid_t pid = m_process_launch_info.GetProcessID();
393
0
  m_process_launch_info.Clear();
394
395
0
  if (pid == LLDB_INVALID_PROCESS_ID)
396
0
    return SendErrorResponse(1);
397
398
0
  ProcessInstanceInfo proc_info;
399
0
  if (!Host::GetProcessInfo(pid, proc_info))
400
0
    return SendErrorResponse(1);
401
402
0
  StreamString response;
403
0
  CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
404
0
  return SendPacketNoLock(response.GetString());
405
0
}
406
407
GDBRemoteCommunication::PacketResult
408
GDBRemoteCommunicationServerPlatform::Handle_qPathComplete(
409
0
    StringExtractorGDBRemote &packet) {
410
0
  packet.SetFilePos(::strlen("qPathComplete:"));
411
0
  const bool only_dir = (packet.GetHexMaxU32(false, 0) == 1);
412
0
  if (packet.GetChar() != ',')
413
0
    return SendErrorResponse(85);
414
0
  std::string path;
415
0
  packet.GetHexByteString(path);
416
417
0
  StringList matches;
418
0
  StandardTildeExpressionResolver resolver;
419
0
  if (only_dir)
420
0
    CommandCompletions::DiskDirectories(path, matches, resolver);
421
0
  else
422
0
    CommandCompletions::DiskFiles(path, matches, resolver);
423
424
0
  StreamString response;
425
0
  response.PutChar('M');
426
0
  llvm::StringRef separator;
427
0
  std::sort(matches.begin(), matches.end());
428
0
  for (const auto &match : matches) {
429
0
    response << separator;
430
0
    separator = ",";
431
    // encode result strings into hex bytes to avoid unexpected error caused by
432
    // special characters like '$'.
433
0
    response.PutStringAsRawHex8(match.c_str());
434
0
  }
435
436
0
  return SendPacketNoLock(response.GetString());
437
0
}
438
439
GDBRemoteCommunication::PacketResult
440
GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
441
0
    StringExtractorGDBRemote &packet) {
442
443
0
  llvm::SmallString<64> cwd;
444
0
  if (std::error_code ec = llvm::sys::fs::current_path(cwd))
445
0
    return SendErrorResponse(ec.value());
446
447
0
  StreamString response;
448
0
  response.PutBytesAsRawHex8(cwd.data(), cwd.size());
449
0
  return SendPacketNoLock(response.GetString());
450
0
}
451
452
GDBRemoteCommunication::PacketResult
453
GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
454
0
    StringExtractorGDBRemote &packet) {
455
0
  packet.SetFilePos(::strlen("QSetWorkingDir:"));
456
0
  std::string path;
457
0
  packet.GetHexByteString(path);
458
459
0
  if (std::error_code ec = llvm::sys::fs::set_current_path(path))
460
0
    return SendErrorResponse(ec.value());
461
0
  return SendOKResponse();
462
0
}
463
464
GDBRemoteCommunication::PacketResult
465
GDBRemoteCommunicationServerPlatform::Handle_qC(
466
0
    StringExtractorGDBRemote &packet) {
467
  // NOTE: lldb should now be using qProcessInfo for process IDs.  This path
468
  // here
469
  // should not be used.  It is reporting process id instead of thread id.  The
470
  // correct answer doesn't seem to make much sense for lldb-platform.
471
  // CONSIDER: flip to "unsupported".
472
0
  lldb::pid_t pid = m_process_launch_info.GetProcessID();
473
474
0
  StreamString response;
475
0
  response.Printf("QC%" PRIx64, pid);
476
477
  // If we launch a process and this GDB server is acting as a platform, then
478
  // we need to clear the process launch state so we can start launching
479
  // another process. In order to launch a process a bunch or packets need to
480
  // be sent: environment packets, working directory, disable ASLR, and many
481
  // more settings. When we launch a process we then need to know when to clear
482
  // this information. Currently we are selecting the 'qC' packet as that
483
  // packet which seems to make the most sense.
484
0
  if (pid != LLDB_INVALID_PROCESS_ID) {
485
0
    m_process_launch_info.Clear();
486
0
  }
487
488
0
  return SendPacketNoLock(response.GetString());
489
0
}
490
491
GDBRemoteCommunication::PacketResult
492
GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
493
0
    StringExtractorGDBRemote &packet) {
494
0
  StructuredData::Array signal_array;
495
496
0
  lldb::UnixSignalsSP signals = UnixSignals::CreateForHost();
497
0
  for (auto signo = signals->GetFirstSignalNumber();
498
0
       signo != LLDB_INVALID_SIGNAL_NUMBER;
499
0
       signo = signals->GetNextSignalNumber(signo)) {
500
0
    auto dictionary = std::make_shared<StructuredData::Dictionary>();
501
502
0
    dictionary->AddIntegerItem("signo", signo);
503
0
    dictionary->AddStringItem("name", signals->GetSignalAsStringRef(signo));
504
505
0
    bool suppress, stop, notify;
506
0
    signals->GetSignalInfo(signo, suppress, stop, notify);
507
0
    dictionary->AddBooleanItem("suppress", suppress);
508
0
    dictionary->AddBooleanItem("stop", stop);
509
0
    dictionary->AddBooleanItem("notify", notify);
510
511
0
    signal_array.Push(dictionary);
512
0
  }
513
514
0
  StreamString response;
515
0
  signal_array.Dump(response);
516
0
  return SendPacketNoLock(response.GetString());
517
0
}
518
519
void GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
520
0
    lldb::pid_t pid) {
521
0
  std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
522
0
  m_port_map.FreePortForProcess(pid);
523
0
  m_spawned_pids.erase(pid);
524
0
}
525
526
0
Status GDBRemoteCommunicationServerPlatform::LaunchProcess() {
527
0
  if (!m_process_launch_info.GetArguments().GetArgumentCount())
528
0
    return Status("%s: no process command line specified to launch",
529
0
                  __FUNCTION__);
530
531
  // specify the process monitor if not already set.  This should generally be
532
  // what happens since we need to reap started processes.
533
0
  if (!m_process_launch_info.GetMonitorProcessCallback())
534
0
    m_process_launch_info.SetMonitorProcessCallback(std::bind(
535
0
        &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this,
536
0
        std::placeholders::_1));
537
538
0
  Status error = Host::LaunchProcess(m_process_launch_info);
539
0
  if (!error.Success()) {
540
0
    fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
541
0
            m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
542
0
    return error;
543
0
  }
544
545
0
  printf("Launched '%s' as process %" PRIu64 "...\n",
546
0
         m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
547
0
         m_process_launch_info.GetProcessID());
548
549
  // add to list of spawned processes.  On an lldb-gdbserver, we would expect
550
  // there to be only one.
551
0
  const auto pid = m_process_launch_info.GetProcessID();
552
0
  if (pid != LLDB_INVALID_PROCESS_ID) {
553
    // add to spawned pids
554
0
    std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
555
0
    m_spawned_pids.insert(pid);
556
0
  }
557
558
0
  return error;
559
0
}
560
561
0
void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
562
0
  m_port_map = std::move(port_map);
563
0
}
564
565
0
const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
566
0
  static FileSpec g_domainsocket_dir;
567
0
  static llvm::once_flag g_once_flag;
568
569
0
  llvm::call_once(g_once_flag, []() {
570
0
    const char *domainsocket_dir_env =
571
0
        ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
572
0
    if (domainsocket_dir_env != nullptr)
573
0
      g_domainsocket_dir = FileSpec(domainsocket_dir_env);
574
0
    else
575
0
      g_domainsocket_dir = HostInfo::GetProcessTempDir();
576
0
  });
577
578
0
  return g_domainsocket_dir;
579
0
}
580
581
FileSpec
582
0
GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
583
0
  llvm::SmallString<128> socket_path;
584
0
  llvm::SmallString<128> socket_name(
585
0
      (llvm::StringRef(prefix) + ".%%%%%%").str());
586
587
0
  FileSpec socket_path_spec(GetDomainSocketDir());
588
0
  socket_path_spec.AppendPathComponent(socket_name.c_str());
589
590
0
  llvm::sys::fs::createUniqueFile(socket_path_spec.GetPath().c_str(),
591
0
                                  socket_path);
592
0
  return FileSpec(socket_path.c_str());
593
0
}
594
595
0
void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
596
0
  m_port_offset = port_offset;
597
0
}
598
599
void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
600
0
    lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
601
0
  m_pending_gdb_server.pid = pid;
602
0
  m_pending_gdb_server.port = port;
603
0
  m_pending_gdb_server.socket_name = socket_name;
604
0
}