Bug Summary

File:tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
Location:line 789, column 21
Description:Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file. Use 'mkstemp' instead

Annotated Source Code

1//===-- GDBRemoteCommunication.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
11#include "GDBRemoteCommunication.h"
12
13// C Includes
14#include <limits.h>
15#include <string.h>
16#include <sys/stat.h>
17
18// C++ Includes
19// Other libraries and framework includes
20#include "lldb/Core/Log.h"
21#include "lldb/Core/StreamFile.h"
22#include "lldb/Core/StreamString.h"
23#include "lldb/Host/ConnectionFileDescriptor.h"
24#include "lldb/Host/FileSpec.h"
25#include "lldb/Host/FileSystem.h"
26#include "lldb/Host/Host.h"
27#include "lldb/Host/HostInfo.h"
28#include "lldb/Host/Socket.h"
29#include "lldb/Host/ThreadLauncher.h"
30#include "lldb/Host/TimeValue.h"
31#include "lldb/Target/Process.h"
32
33// Project includes
34#include "ProcessGDBRemoteLog.h"
35
36#if defined(__APPLE__)
37# define DEBUGSERVER_BASENAME"lldb-gdbserver" "debugserver"
38#else
39# define DEBUGSERVER_BASENAME"lldb-gdbserver" "lldb-gdbserver"
40#endif
41
42using namespace lldb;
43using namespace lldb_private;
44
45GDBRemoteCommunication::History::History (uint32_t size) :
46 m_packets(),
47 m_curr_idx (0),
48 m_total_packet_count (0),
49 m_dumped_to_log (false)
50{
51 m_packets.resize(size);
52}
53
54GDBRemoteCommunication::History::~History ()
55{
56}
57
58void
59GDBRemoteCommunication::History::AddPacket (char packet_char,
60 PacketType type,
61 uint32_t bytes_transmitted)
62{
63 const size_t size = m_packets.size();
64 if (size > 0)
65 {
66 const uint32_t idx = GetNextIndex();
67 m_packets[idx].packet.assign (1, packet_char);
68 m_packets[idx].type = type;
69 m_packets[idx].bytes_transmitted = bytes_transmitted;
70 m_packets[idx].packet_idx = m_total_packet_count;
71 m_packets[idx].tid = Host::GetCurrentThreadID();
72 }
73}
74
75void
76GDBRemoteCommunication::History::AddPacket (const std::string &src,
77 uint32_t src_len,
78 PacketType type,
79 uint32_t bytes_transmitted)
80{
81 const size_t size = m_packets.size();
82 if (size > 0)
83 {
84 const uint32_t idx = GetNextIndex();
85 m_packets[idx].packet.assign (src, 0, src_len);
86 m_packets[idx].type = type;
87 m_packets[idx].bytes_transmitted = bytes_transmitted;
88 m_packets[idx].packet_idx = m_total_packet_count;
89 m_packets[idx].tid = Host::GetCurrentThreadID();
90 }
91}
92
93void
94GDBRemoteCommunication::History::Dump (lldb_private::Stream &strm) const
95{
96 const uint32_t size = GetNumPacketsInHistory ();
97 const uint32_t first_idx = GetFirstSavedPacketIndex ();
98 const uint32_t stop_idx = m_curr_idx + size;
99 for (uint32_t i = first_idx; i < stop_idx; ++i)
100 {
101 const uint32_t idx = NormalizeIndex (i);
102 const Entry &entry = m_packets[idx];
103 if (entry.type == ePacketTypeInvalid || entry.packet.empty())
104 break;
105 strm.Printf ("history[%u] tid=0x%4.4" PRIx64"l" "x" " <%4u> %s packet: %s\n",
106 entry.packet_idx,
107 entry.tid,
108 entry.bytes_transmitted,
109 (entry.type == ePacketTypeSend) ? "send" : "read",
110 entry.packet.c_str());
111 }
112}
113
114void
115GDBRemoteCommunication::History::Dump (lldb_private::Log *log) const
116{
117 if (log && !m_dumped_to_log)
118 {
119 m_dumped_to_log = true;
120 const uint32_t size = GetNumPacketsInHistory ();
121 const uint32_t first_idx = GetFirstSavedPacketIndex ();
122 const uint32_t stop_idx = m_curr_idx + size;
123 for (uint32_t i = first_idx; i < stop_idx; ++i)
124 {
125 const uint32_t idx = NormalizeIndex (i);
126 const Entry &entry = m_packets[idx];
127 if (entry.type == ePacketTypeInvalid || entry.packet.empty())
128 break;
129 log->Printf ("history[%u] tid=0x%4.4" PRIx64"l" "x" " <%4u> %s packet: %s",
130 entry.packet_idx,
131 entry.tid,
132 entry.bytes_transmitted,
133 (entry.type == ePacketTypeSend) ? "send" : "read",
134 entry.packet.c_str());
135 }
136 }
137}
138
139//----------------------------------------------------------------------
140// GDBRemoteCommunication constructor
141//----------------------------------------------------------------------
142GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
143 const char *listener_name,
144 bool is_platform) :
145 Communication(comm_name),
146#ifdef LLDB_CONFIGURATION_DEBUG
147 m_packet_timeout (1000),
148#else
149 m_packet_timeout (1),
150#endif
151 m_sequence_mutex (Mutex::eMutexTypeRecursive),
152 m_public_is_running (false),
153 m_private_is_running (false),
154 m_history (512),
155 m_send_acks (true),
156 m_is_platform (is_platform),
157 m_listen_url ()
158{
159}
160
161//----------------------------------------------------------------------
162// Destructor
163//----------------------------------------------------------------------
164GDBRemoteCommunication::~GDBRemoteCommunication()
165{
166 if (IsConnected())
167 {
168 Disconnect();
169 }
170}
171
172char
173GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
174{
175 int checksum = 0;
176
177 for (size_t i = 0; i < payload_length; ++i)
178 checksum += payload[i];
179
180 return checksum & 255;
181}
182
183size_t
184GDBRemoteCommunication::SendAck ()
185{
186 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS(1u << 3)));
187 ConnectionStatus status = eConnectionStatusSuccess;
188 char ch = '+';
189 const size_t bytes_written = Write (&ch, 1, status, NULL__null);
190 if (log)
191 log->Printf ("<%4" PRIu64"l" "u" "> send packet: %c", (uint64_t)bytes_written, ch);
192 m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
193 return bytes_written;
194}
195
196size_t
197GDBRemoteCommunication::SendNack ()
198{
199 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS(1u << 3)));
200 ConnectionStatus status = eConnectionStatusSuccess;
201 char ch = '-';
202 const size_t bytes_written = Write (&ch, 1, status, NULL__null);
203 if (log)
204 log->Printf("<%4" PRIu64"l" "u" "> send packet: %c", (uint64_t)bytes_written, ch);
205 m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
206 return bytes_written;
207}
208
209GDBRemoteCommunication::PacketResult
210GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
211{
212 Mutex::Locker locker(m_sequence_mutex);
213 return SendPacketNoLock (payload, payload_length);
214}
215
216GDBRemoteCommunication::PacketResult
217GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
218{
219 if (IsConnected())
220 {
221 StreamString packet(0, 4, eByteOrderBig);
222
223 packet.PutChar('$');
224 packet.Write (payload, payload_length);
225 packet.PutChar('#');
226 packet.PutHex8(CalculcateChecksum (payload, payload_length));
227
228 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS(1u << 3)));
229 ConnectionStatus status = eConnectionStatusSuccess;
230 const char *packet_data = packet.GetData();
231 const size_t packet_length = packet.GetSize();
232 size_t bytes_written = Write (packet_data, packet_length, status, NULL__null);
233 if (log)
234 {
235 size_t binary_start_offset = 0;
236 if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == 0)
237 {
238 const char *first_comma = strchr(packet_data, ',');
239 if (first_comma)
240 {
241 const char *second_comma = strchr(first_comma + 1, ',');
242 if (second_comma)
243 binary_start_offset = second_comma - packet_data + 1;
244 }
245 }
246
247 // If logging was just enabled and we have history, then dump out what
248 // we have to the log so we get the historical context. The Dump() call that
249 // logs all of the packet will set a boolean so that we don't dump this more
250 // than once
251 if (!m_history.DidDumpToLog ())
252 m_history.Dump (log);
253
254 if (binary_start_offset)
255 {
256 StreamString strm;
257 // Print non binary data header
258 strm.Printf("<%4" PRIu64"l" "u" "> send packet: %.*s", (uint64_t)bytes_written, (int)binary_start_offset, packet_data);
259 const uint8_t *p;
260 // Print binary data exactly as sent
261 for (p = (uint8_t*)packet_data + binary_start_offset; *p != '#'; ++p)
262 strm.Printf("\\x%2.2x", *p);
263 // Print the checksum
264 strm.Printf("%*s", (int)3, p);
265 log->PutCString(strm.GetString().c_str());
266 }
267 else
268 log->Printf("<%4" PRIu64"l" "u" "> send packet: %.*s", (uint64_t)bytes_written, (int)packet_length, packet_data);
269 }
270
271 m_history.AddPacket (packet.GetString(), packet_length, History::ePacketTypeSend, bytes_written);
272
273
274 if (bytes_written == packet_length)
275 {
276 if (GetSendAcks ())
277 return GetAck ();
278 else
279 return PacketResult::Success;
280 }
281 else
282 {
283 if (log)
284 log->Printf ("error: failed to send packet: %.*s", (int)packet_length, packet_data);
285 }
286 }
287 return PacketResult::ErrorSendFailed;
288}
289
290GDBRemoteCommunication::PacketResult
291GDBRemoteCommunication::GetAck ()
292{
293 StringExtractorGDBRemote packet;
294 PacketResult result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ());
295 if (result == PacketResult::Success)
296 {
297 if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck)
298 return PacketResult::Success;
299 else
300 return PacketResult::ErrorSendAck;
301 }
302 return result;
303}
304
305bool
306GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message)
307{
308 if (IsRunning())
309 return locker.TryLock (m_sequence_mutex, failure_message);
310
311 locker.Lock (m_sequence_mutex);
312 return true;
313}
314
315
316bool
317GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
318{
319 return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL__null);
320}
321
322GDBRemoteCommunication::PacketResult
323GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
324{
325 uint8_t buffer[8192];
326 Error error;
327
328 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS(1u << 3) | GDBR_LOG_VERBOSE(1u << 0)));
329
330 // Check for a packet from our cache first without trying any reading...
331 if (CheckForPacket (NULL__null, 0, packet))
332 return PacketResult::Success;
333
334 bool timed_out = false;
335 bool disconnected = false;
336 while (IsConnected() && !timed_out)
337 {
338 lldb::ConnectionStatus status = eConnectionStatusNoConnection;
339 size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
340
341 if (log)
342 log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64"l" "u",
343 __PRETTY_FUNCTION__,
344 timeout_usec,
345 Communication::ConnectionStatusAsCString (status),
346 error.AsCString(),
347 (uint64_t)bytes_read);
348
349 if (bytes_read > 0)
350 {
351 if (CheckForPacket (buffer, bytes_read, packet))
352 return PacketResult::Success;
353 }
354 else
355 {
356 switch (status)
357 {
358 case eConnectionStatusTimedOut:
359 case eConnectionStatusInterrupted:
360 timed_out = true;
361 break;
362 case eConnectionStatusSuccess:
363 //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
364 break;
365
366 case eConnectionStatusEndOfFile:
367 case eConnectionStatusNoConnection:
368 case eConnectionStatusLostConnection:
369 case eConnectionStatusError:
370 disconnected = true;
371 Disconnect();
372 break;
373 }
374 }
375 }
376 packet.Clear ();
377 if (disconnected)
378 return PacketResult::ErrorDisconnected;
379 if (timed_out)
380 return PacketResult::ErrorReplyTimeout;
381 else
382 return PacketResult::ErrorReplyFailed;
383}
384
385bool
386GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet)
387{
388 // Put the packet data into the buffer in a thread safe fashion
389 Mutex::Locker locker(m_bytes_mutex);
390
391 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS(1u << 3)));
392
393 if (src && src_len > 0)
394 {
395 if (log && log->GetVerbose())
396 {
397 StreamString s;
398 log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s",
399 __FUNCTION__,
400 (uint32_t)src_len,
401 (uint32_t)src_len,
402 src);
403 }
404 m_bytes.append ((const char *)src, src_len);
405 }
406
407 // Parse up the packets into gdb remote packets
408 if (!m_bytes.empty())
409 {
410 // end_idx must be one past the last valid packet byte. Start
411 // it off with an invalid value that is the same as the current
412 // index.
413 size_t content_start = 0;
414 size_t content_length = 0;
415 size_t total_length = 0;
416 size_t checksum_idx = std::string::npos;
417
418 switch (m_bytes[0])
419 {
420 case '+': // Look for ack
421 case '-': // Look for cancel
422 case '\x03': // ^C to halt target
423 content_length = total_length = 1; // The command is one byte long...
424 break;
425
426 case '$':
427 // Look for a standard gdb packet?
428 {
429 size_t hash_pos = m_bytes.find('#');
430 if (hash_pos != std::string::npos)
431 {
432 if (hash_pos + 2 < m_bytes.size())
433 {
434 checksum_idx = hash_pos + 1;
435 // Skip the dollar sign
436 content_start = 1;
437 // Don't include the # in the content or the $ in the content length
438 content_length = hash_pos - 1;
439
440 total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
441 }
442 else
443 {
444 // Checksum bytes aren't all here yet
445 content_length = std::string::npos;
446 }
447 }
448 }
449 break;
450
451 default:
452 {
453 // We have an unexpected byte and we need to flush all bad
454 // data that is in m_bytes, so we need to find the first
455 // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
456 // or '$' character (start of packet header) or of course,
457 // the end of the data in m_bytes...
458 const size_t bytes_len = m_bytes.size();
459 bool done = false;
460 uint32_t idx;
461 for (idx = 1; !done && idx < bytes_len; ++idx)
462 {
463 switch (m_bytes[idx])
464 {
465 case '+':
466 case '-':
467 case '\x03':
468 case '$':
469 done = true;
470 break;
471
472 default:
473 break;
474 }
475 }
476 if (log)
477 log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'",
478 __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str());
479 m_bytes.erase(0, idx - 1);
480 }
481 break;
482 }
483
484 if (content_length == std::string::npos)
485 {
486 packet.Clear();
487 return false;
488 }
489 else if (total_length > 0)
490 {
491
492 // We have a valid packet...
493 assert (content_length <= m_bytes.size())((content_length <= m_bytes.size()) ? static_cast<void>
(0) : __assert_fail ("content_length <= m_bytes.size()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn225828/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"
, 493, __PRETTY_FUNCTION__))
;
494 assert (total_length <= m_bytes.size())((total_length <= m_bytes.size()) ? static_cast<void>
(0) : __assert_fail ("total_length <= m_bytes.size()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn225828/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"
, 494, __PRETTY_FUNCTION__))
;
495 assert (content_length <= total_length)((content_length <= total_length) ? static_cast<void>
(0) : __assert_fail ("content_length <= total_length", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn225828/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"
, 495, __PRETTY_FUNCTION__))
;
496 const size_t content_end = content_start + content_length;
497
498 bool success = true;
499 std::string &packet_str = packet.GetStringRef();
500
501
502 if (log)
503 {
504 // If logging was just enabled and we have history, then dump out what
505 // we have to the log so we get the historical context. The Dump() call that
506 // logs all of the packet will set a boolean so that we don't dump this more
507 // than once
508 if (!m_history.DidDumpToLog ())
509 m_history.Dump (log);
510
511 bool binary = false;
512 // Only detect binary for packets that start with a '$' and have a '#CC' checksum
513 if (m_bytes[0] == '$' && total_length > 4)
514 {
515 for (size_t i=0; !binary && i<total_length; ++i)
516 {
517 if (isprint(m_bytes[i]) == 0)
518 binary = true;
519 }
520 }
521 if (binary)
522 {
523 StreamString strm;
524 // Packet header...
525 strm.Printf("<%4" PRIu64"l" "u" "> read packet: %c", (uint64_t)total_length, m_bytes[0]);
526 for (size_t i=content_start; i<content_end; ++i)
527 {
528 // Remove binary escaped bytes when displaying the packet...
529 const char ch = m_bytes[i];
530 if (ch == 0x7d)
531 {
532 // 0x7d is the escape character. The next character is to
533 // be XOR'd with 0x20.
534 const char escapee = m_bytes[++i] ^ 0x20;
535 strm.Printf("%2.2x", escapee);
536 }
537 else
538 {
539 strm.Printf("%2.2x", (uint8_t)ch);
540 }
541 }
542 // Packet footer...
543 strm.Printf("%c%c%c", m_bytes[total_length-3], m_bytes[total_length-2], m_bytes[total_length-1]);
544 log->PutCString(strm.GetString().c_str());
545 }
546 else
547 {
548 log->Printf("<%4" PRIu64"l" "u" "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
549 }
550 }
551
552 m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
553
554 // Clear packet_str in case there is some existing data in it.
555 packet_str.clear();
556 // Copy the packet from m_bytes to packet_str expanding the
557 // run-length encoding in the process.
558 // Reserve enough byte for the most common case (no RLE used)
559 packet_str.reserve(m_bytes.length());
560 for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_end; ++c)
561 {
562 if (*c == '*')
563 {
564 // '*' indicates RLE. Next character will give us the
565 // repeat count and previous character is what is to be
566 // repeated.
567 char char_to_repeat = packet_str.back();
568 // Number of time the previous character is repeated
569 int repeat_count = *++c + 3 - ' ';
570 // We have the char_to_repeat and repeat_count. Now push
571 // it in the packet.
572 for (int i = 0; i < repeat_count; ++i)
573 packet_str.push_back(char_to_repeat);
574 }
575 else if (*c == 0x7d)
576 {
577 // 0x7d is the escape character. The next character is to
578 // be XOR'd with 0x20.
579 char escapee = *++c ^ 0x20;
580 packet_str.push_back(escapee);
581 }
582 else
583 {
584 packet_str.push_back(*c);
585 }
586 }
587
588 if (m_bytes[0] == '$')
589 {
590 assert (checksum_idx < m_bytes.size())((checksum_idx < m_bytes.size()) ? static_cast<void>
(0) : __assert_fail ("checksum_idx < m_bytes.size()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn225828/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"
, 590, __PRETTY_FUNCTION__))
;
591 if (::isxdigit (m_bytes[checksum_idx+0]) ||
592 ::isxdigit (m_bytes[checksum_idx+1]))
593 {
594 if (GetSendAcks ())
595 {
596 const char *packet_checksum_cstr = &m_bytes[checksum_idx];
597 char packet_checksum = strtol (packet_checksum_cstr, NULL__null, 16);
598 char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
599 success = packet_checksum == actual_checksum;
600 if (!success)
601 {
602 if (log)
603 log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
604 (int)(total_length),
605 m_bytes.c_str(),
606 (uint8_t)packet_checksum,
607 (uint8_t)actual_checksum);
608 }
609 // Send the ack or nack if needed
610 if (!success)
611 SendNack();
612 else
613 SendAck();
614 }
615 }
616 else
617 {
618 success = false;
619 if (log)
620 log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str());
621 }
622 }
623
624 m_bytes.erase(0, total_length);
625 packet.SetFilePos(0);
626 return success;
627 }
628 }
629 packet.Clear();
630 return false;
631}
632
633Error
634GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port)
635{
636 Error error;
637 if (m_listen_thread.IsJoinable())
638 {
639 error.SetErrorString("listen thread already running");
640 }
641 else
642 {
643 char listen_url[512];
644 if (hostname && hostname[0])
645 snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port);
646 else
647 snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
648 m_listen_url = listen_url;
649 SetConnection(new ConnectionFileDescriptor());
650 m_listen_thread = ThreadLauncher::LaunchThread(listen_url, GDBRemoteCommunication::ListenThread, this, &error);
651 }
652 return error;
653}
654
655bool
656GDBRemoteCommunication::JoinListenThread ()
657{
658 if (m_listen_thread.IsJoinable())
659 m_listen_thread.Join(nullptr);
660 return true;
661}
662
663lldb::thread_result_t
664GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
665{
666 GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
667 Error error;
668 ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection ();
669
670 if (connection)
671 {
672 // Do the listen on another thread so we can continue on...
673 if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess)
674 comm->SetConnection(NULL__null);
675 }
676 return NULL__null;
677}
678
679Error
680GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
681 uint16_t in_port,
682 lldb_private::ProcessLaunchInfo &launch_info,
683 uint16_t &out_port)
684{
685 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS(1u << 1)));
686 if (log)
687 log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16"u" ", out_port=%" PRIu16"u", __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port);
688
689 out_port = in_port;
690 Error error;
691 // If we locate debugserver, keep that located version around
692 static FileSpec g_debugserver_file_spec;
693
694 char debugserver_path[PATH_MAX4096];
695 FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
696
697 // Always check to see if we have an environment override for the path
698 // to the debugserver to use and use it if we do.
699 const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
700 if (env_debugserver_path)
701 {
702 debugserver_file_spec.SetFile (env_debugserver_path, false);
703 if (log)
704 log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path);
705 }
706 else
707 debugserver_file_spec = g_debugserver_file_spec;
708 bool debugserver_exists = debugserver_file_spec.Exists();
709 if (!debugserver_exists)
710 {
711 // The debugserver binary is in the LLDB.framework/Resources
712 // directory.
713 if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec))
714 {
715 debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME"lldb-gdbserver");
716 debugserver_exists = debugserver_file_spec.Exists();
717 if (debugserver_exists)
718 {
719 if (log)
720 log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
721
722 g_debugserver_file_spec = debugserver_file_spec;
723 }
724 else
725 {
726 if (log)
727 log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
728
729 g_debugserver_file_spec.Clear();
730 debugserver_file_spec.Clear();
731 }
732 }
733 }
734
735 if (debugserver_exists)
736 {
737 debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
738
739 Args &debugserver_args = launch_info.GetArguments();
740 debugserver_args.Clear();
741 char arg_cstr[PATH_MAX4096];
742
743 // Start args with "debugserver /file/path -r --"
744 debugserver_args.AppendArgument(debugserver_path);
745
746 // If a host and port is supplied then use it
747 char host_and_port[128];
748 if (hostname)
749 {
750 snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
751 debugserver_args.AppendArgument(host_and_port);
752 }
753 else
754 {
755 host_and_port[0] = '\0';
756 }
757
758 // use native registers, not the GDB registers
759 debugserver_args.AppendArgument("--native-regs");
760 // make debugserver run in its own session so signals generated by
761 // special terminal key sequences (^C) don't affect debugserver
762 debugserver_args.AppendArgument("--setsid");
763
764 char named_pipe_path[PATH_MAX4096];
765 named_pipe_path[0] = '\0';
766
767 bool listen = false;
768 if (host_and_port[0])
769 {
770 // Create a temporary file to get the stdout/stderr and redirect the
771 // output of the command into this file. We will later read this file
772 // if all goes well and fill the data into "command_output_ptr"
773
774 if (in_port == 0)
775 {
776 // Binding to port zero, we need to figure out what port it ends up
777 // using using a named pipe...
778 FileSpec tmpdir_file_spec;
779 if (HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
780 {
781 tmpdir_file_spec.AppendPathComponent("debugserver-named-pipe.XXXXXX");
782 strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
783 }
784 else
785 {
786 strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
787 }
788
789 if (::mktemp (named_pipe_path))
Call to function 'mktemp' is insecure as it always creates or uses insecure temporary file. Use 'mkstemp' instead
790 {
791#if defined(_WIN32)
792 if ( false )
793#else
794 if (::mkfifo(named_pipe_path, 0600) == 0)
795#endif
796 {
797 debugserver_args.AppendArgument("--named-pipe");
798 debugserver_args.AppendArgument(named_pipe_path);
799 }
800 }
801 }
802 else
803 {
804 listen = true;
805 }
806 }
807 else
808 {
809 // No host and port given, so lets listen on our end and make the debugserver
810 // connect to us..
811 error = StartListenThread ("127.0.0.1", 0);
812 if (error.Fail())
813 return error;
814
815 ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
816 // Wait for 10 seconds to resolve the bound port
817 out_port = connection->GetListeningPort(10);
818 if (out_port > 0)
819 {
820 char port_cstr[32];
821 snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port);
822 // Send the host and port down that debugserver and specify an option
823 // so that it connects back to the port we are listening to in this process
824 debugserver_args.AppendArgument("--reverse-connect");
825 debugserver_args.AppendArgument(port_cstr);
826 }
827 else
828 {
829 error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
830 return error;
831 }
832 }
833
834 const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
835 if (env_debugserver_log_file)
836 {
837 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
838 debugserver_args.AppendArgument(arg_cstr);
839 }
840
841 const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
842 if (env_debugserver_log_flags)
843 {
844 ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
845 debugserver_args.AppendArgument(arg_cstr);
846 }
847
848 // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back.
849 uint32_t env_var_index = 1;
850 bool has_env_var;
851 do
852 {
853 char env_var_name[64];
854 snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32"u", env_var_index++);
855 const char *extra_arg = getenv(env_var_name);
856 has_env_var = extra_arg != nullptr;
857
858 if (has_env_var)
859 {
860 debugserver_args.AppendArgument (extra_arg);
861 if (log)
862 log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg);
863 }
864 } while (has_env_var);
865
866 // Close STDIN, STDOUT and STDERR.
867 launch_info.AppendCloseFileAction (STDIN_FILENO0);
868 launch_info.AppendCloseFileAction (STDOUT_FILENO1);
869 launch_info.AppendCloseFileAction (STDERR_FILENO2);
870
871 // Redirect STDIN, STDOUT and STDERR to "/dev/null".
872 launch_info.AppendSuppressFileAction (STDIN_FILENO0, true, false);
873 launch_info.AppendSuppressFileAction (STDOUT_FILENO1, false, true);
874 launch_info.AppendSuppressFileAction (STDERR_FILENO2, false, true);
875
876 error = Host::LaunchProcess(launch_info);
877
878 if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID0)
879 {
880 if (named_pipe_path[0])
881 {
882 File name_pipe_file;
883 error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
884 if (error.Success())
885 {
886 char port_cstr[256];
887 port_cstr[0] = '\0';
888 size_t num_bytes = sizeof(port_cstr);
889 error = name_pipe_file.Read(port_cstr, num_bytes);
890 assert (error.Success())((error.Success()) ? static_cast<void> (0) : __assert_fail
("error.Success()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn225828/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"
, 890, __PRETTY_FUNCTION__))
;
891 assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0')((num_bytes > 0 && port_cstr[num_bytes-1] == '\0')
? static_cast<void> (0) : __assert_fail ("num_bytes > 0 && port_cstr[num_bytes-1] == '\\0'"
, "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn225828/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp"
, 891, __PRETTY_FUNCTION__))
;
892 out_port = Args::StringToUInt32(port_cstr, 0);
893 name_pipe_file.Close();
894 }
895 FileSystem::Unlink(named_pipe_path);
896 }
897 else if (listen)
898 {
899
900 }
901 else
902 {
903 // Make sure we actually connect with the debugserver...
904 JoinListenThread();
905 }
906 }
907 }
908 else
909 {
910 error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME"lldb-gdbserver" );
911 }
912 return error;
913}
914
915void
916GDBRemoteCommunication::DumpHistory(Stream &strm)
917{
918 m_history.Dump (strm);
919}