1//===-- GDBRemoteCommunication.h --------------------------------*- C++ -*-===//
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#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H
10#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H
11
12#include "GDBRemoteCommunicationHistory.h"
13#include "lldb/Core/Communication.h"
14#include "lldb/Host/Config.h"
15#include "lldb/Host/Socket.h"
16#include "lldb/Utility/Args.h"
17#include "lldb/Utility/StringExtractorGDBRemote.h"
18#include <mutex>
19#include <string>
20
21namespace lldb_private {
22namespace process_gdb_remote {
23
24enum GDBStoppointType {
25 eStoppointInvalid = -1,
26 eBreakpointSoftware = 0,
27 eBreakpointHardware,
28 eWatchpointWrite,
29 eWatchpointRead,
30 eWatchpointReadWrite
31};
32
33enum class CompressionType {
34 None = 0, // no compression
35 ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's
36 // libcompression
37 LZFSE, // an Apple compression scheme, requires Apple's libcompression
38 LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with
39 // https://code.google.com/p/lz4/
40 LZMA, // Lempel–Ziv–Markov chain algorithm
41};
42
43// Data included in the vFile:fstat packet.
44// https://sourceware.org/gdb/onlinedocs/gdb/struct-stat.html#struct-stat
45struct GDBRemoteFStatData {
46 llvm::support::ubig32_t gdb_st_dev;
47 llvm::support::ubig32_t gdb_st_ino;
48 llvm::support::ubig32_t gdb_st_mode;
49 llvm::support::ubig32_t gdb_st_nlink;
50 llvm::support::ubig32_t gdb_st_uid;
51 llvm::support::ubig32_t gdb_st_gid;
52 llvm::support::ubig32_t gdb_st_rdev;
53 llvm::support::ubig64_t gdb_st_size;
54 llvm::support::ubig64_t gdb_st_blksize;
55 llvm::support::ubig64_t gdb_st_blocks;
56 llvm::support::ubig32_t gdb_st_atime;
57 llvm::support::ubig32_t gdb_st_mtime;
58 llvm::support::ubig32_t gdb_st_ctime;
59};
60static_assert(sizeof(GDBRemoteFStatData) == 64,
61 "size of GDBRemoteFStatData is not 64");
62
63enum GDBErrno {
64#define HANDLE_ERRNO(name, value) GDB_##name = value,
65#include "Plugins/Process/gdb-remote/GDBRemoteErrno.def"
66 GDB_EUNKNOWN = 9999
67};
68
69class ProcessGDBRemote;
70
71class GDBRemoteCommunication : public Communication {
72public:
73 enum class PacketType { Invalid = 0, Standard, Notify };
74
75 enum class PacketResult {
76 Success = 0, // Success
77 ErrorSendFailed, // Status sending the packet
78 ErrorSendAck, // Didn't get an ack back after sending a packet
79 ErrorReplyFailed, // Status getting the reply
80 ErrorReplyTimeout, // Timed out waiting for reply
81 ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that
82 // was sent
83 ErrorReplyAck, // Sending reply ack failed
84 ErrorDisconnected, // We were disconnected
85 ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet
86 // request
87 };
88
89 // Class to change the timeout for a given scope and restore it to the
90 // original value when the
91 // created ScopedTimeout object got out of scope
92 class ScopedTimeout {
93 public:
94 ScopedTimeout(GDBRemoteCommunication &gdb_comm,
95 std::chrono::seconds timeout);
96 ~ScopedTimeout();
97
98 private:
99 GDBRemoteCommunication &m_gdb_comm;
100 std::chrono::seconds m_saved_timeout;
101 // Don't ever reduce the timeout for a packet, only increase it. If the
102 // requested timeout if less than the current timeout, we don't set it
103 // and won't need to restore it.
104 bool m_timeout_modified;
105 };
106
107 GDBRemoteCommunication();
108
109 ~GDBRemoteCommunication() override;
110
111 PacketResult GetAck();
112
113 size_t SendAck();
114
115 size_t SendNack();
116
117 char CalculcateChecksum(llvm::StringRef payload);
118
119 PacketType CheckForPacket(const uint8_t *src, size_t src_len,
120 StringExtractorGDBRemote &packet);
121
122 bool GetSendAcks() { return m_send_acks; }
123
124 // Set the global packet timeout.
125 //
126 // For clients, this is the timeout that gets used when sending
127 // packets and waiting for responses. For servers, this is used when waiting
128 // for ACKs.
129 std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {
130 const auto old_packet_timeout = m_packet_timeout;
131 m_packet_timeout = packet_timeout;
132 return old_packet_timeout;
133 }
134
135 std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
136
137 // Get the debugserver path and check that it exist.
138 FileSpec GetDebugserverPath(Platform *platform);
139
140 // Start a debugserver instance on the current host using the
141 // supplied connection URL.
142 Status StartDebugserverProcess(
143 const char *url,
144 Platform *platform, // If non nullptr, then check with the platform for
145 // the GDB server binary if it can't be located
146 ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
147 shared_fd_t pass_comm_fd); // Communication file descriptor to pass during
148 // fork/exec to avoid having to connect/accept
149
150 void DumpHistory(Stream &strm);
151
152 static llvm::Error ConnectLocally(GDBRemoteCommunication &client,
153 GDBRemoteCommunication &server);
154
155 /// Expand GDB run-length encoding.
156 static std::optional<std::string> ExpandRLE(std::string);
157
158protected:
159 std::chrono::seconds m_packet_timeout;
160 uint32_t m_echo_number;
161 LazyBool m_supports_qEcho;
162 GDBRemoteCommunicationHistory m_history;
163 bool m_send_acks;
164 bool m_is_platform; // Set to true if this class represents a platform,
165 // false if this class represents a debug session for
166 // a single process
167
168 std::string m_bytes;
169 std::recursive_mutex m_bytes_mutex;
170 CompressionType m_compression_type;
171
172 PacketResult SendPacketNoLock(llvm::StringRef payload);
173 PacketResult SendNotificationPacketNoLock(llvm::StringRef notify_type,
174 std::deque<std::string>& queue,
175 llvm::StringRef payload);
176 PacketResult SendRawPacketNoLock(llvm::StringRef payload,
177 bool skip_ack = false);
178
179 PacketResult ReadPacket(StringExtractorGDBRemote &response,
180 Timeout<std::micro> timeout, bool sync_on_timeout);
181
182 PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response,
183 Timeout<std::micro> timeout,
184 bool sync_on_timeout);
185
186 bool CompressionIsEnabled() {
187 return m_compression_type != CompressionType::None;
188 }
189
190 // If compression is enabled, decompress the packet in m_bytes and update
191 // m_bytes with the uncompressed version.
192 // Returns 'true' packet was decompressed and m_bytes is the now-decompressed
193 // text.
194 // Returns 'false' if unable to decompress or if the checksum was invalid.
195 //
196 // NB: Once the packet has been decompressed, checksum cannot be computed
197 // based
198 // on m_bytes. The checksum was for the compressed packet.
199 bool DecompressPacket();
200
201private:
202#if HAVE_LIBCOMPRESSION
203 CompressionType m_decompression_scratch_type = CompressionType::None;
204 void *m_decompression_scratch = nullptr;
205#endif
206
207 GDBRemoteCommunication(const GDBRemoteCommunication &) = delete;
208 const GDBRemoteCommunication &
209 operator=(const GDBRemoteCommunication &) = delete;
210};
211
212} // namespace process_gdb_remote
213} // namespace lldb_private
214
215namespace llvm {
216template <>
217struct format_provider<
218 lldb_private::process_gdb_remote::GDBRemoteCommunication::PacketResult> {
219 static void format(const lldb_private::process_gdb_remote::
220 GDBRemoteCommunication::PacketResult &state,
221 raw_ostream &Stream, StringRef Style);
222};
223} // namespace llvm
224
225#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATION_H
226

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h