File: | tools/lldb/include/lldb/Utility/TraceOptions.h |
Warning: | line 27, column 37 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- GDBRemoteCommunicationServerLLGS.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 <errno(*__errno_location ()).h> | |||
11 | ||||
12 | #include "lldb/Host/Config.h" | |||
13 | ||||
14 | #include "GDBRemoteCommunicationServerLLGS.h" | |||
15 | #include "lldb/Utility/StreamGDBRemote.h" | |||
16 | ||||
17 | // C Includes | |||
18 | // C++ Includes | |||
19 | #include <chrono> | |||
20 | #include <cstring> | |||
21 | #include <thread> | |||
22 | ||||
23 | // Other libraries and framework includes | |||
24 | #include "lldb/Host/ConnectionFileDescriptor.h" | |||
25 | #include "lldb/Host/Debug.h" | |||
26 | #include "lldb/Host/File.h" | |||
27 | #include "lldb/Host/FileSystem.h" | |||
28 | #include "lldb/Host/Host.h" | |||
29 | #include "lldb/Host/HostInfo.h" | |||
30 | #include "lldb/Host/PosixApi.h" | |||
31 | #include "lldb/Host/common/NativeProcessProtocol.h" | |||
32 | #include "lldb/Host/common/NativeRegisterContext.h" | |||
33 | #include "lldb/Host/common/NativeThreadProtocol.h" | |||
34 | #include "lldb/Target/FileAction.h" | |||
35 | #include "lldb/Target/MemoryRegionInfo.h" | |||
36 | #include "lldb/Utility/Args.h" | |||
37 | #include "lldb/Utility/DataBuffer.h" | |||
38 | #include "lldb/Utility/Endian.h" | |||
39 | #include "lldb/Utility/JSON.h" | |||
40 | #include "lldb/Utility/LLDBAssert.h" | |||
41 | #include "lldb/Utility/Log.h" | |||
42 | #include "lldb/Utility/RegisterValue.h" | |||
43 | #include "lldb/Utility/State.h" | |||
44 | #include "lldb/Utility/StreamString.h" | |||
45 | #include "lldb/Utility/UriParser.h" | |||
46 | #include "llvm/ADT/Triple.h" | |||
47 | #include "llvm/Support/ScopedPrinter.h" | |||
48 | ||||
49 | // Project includes | |||
50 | #include "ProcessGDBRemote.h" | |||
51 | #include "ProcessGDBRemoteLog.h" | |||
52 | #include "lldb/Utility/StringExtractorGDBRemote.h" | |||
53 | ||||
54 | using namespace lldb; | |||
55 | using namespace lldb_private; | |||
56 | using namespace lldb_private::process_gdb_remote; | |||
57 | using namespace llvm; | |||
58 | ||||
59 | //---------------------------------------------------------------------- | |||
60 | // GDBRemote Errors | |||
61 | //---------------------------------------------------------------------- | |||
62 | ||||
63 | namespace { | |||
64 | enum GDBRemoteServerError { | |||
65 | // Set to the first unused error number in literal form below | |||
66 | eErrorFirst = 29, | |||
67 | eErrorNoProcess = eErrorFirst, | |||
68 | eErrorResume, | |||
69 | eErrorExitStatus | |||
70 | }; | |||
71 | } | |||
72 | ||||
73 | //---------------------------------------------------------------------- | |||
74 | // GDBRemoteCommunicationServerLLGS constructor | |||
75 | //---------------------------------------------------------------------- | |||
76 | GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( | |||
77 | MainLoop &mainloop, const NativeProcessProtocol::Factory &process_factory) | |||
78 | : GDBRemoteCommunicationServerCommon("gdb-remote.server", | |||
79 | "gdb-remote.server.rx_packet"), | |||
80 | m_mainloop(mainloop), m_process_factory(process_factory), | |||
81 | m_stdio_communication("process.stdio") { | |||
82 | RegisterPacketHandlers(); | |||
83 | } | |||
84 | ||||
85 | void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { | |||
86 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C, | |||
87 | &GDBRemoteCommunicationServerLLGS::Handle_C); | |||
88 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c, | |||
89 | &GDBRemoteCommunicationServerLLGS::Handle_c); | |||
90 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D, | |||
91 | &GDBRemoteCommunicationServerLLGS::Handle_D); | |||
92 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H, | |||
93 | &GDBRemoteCommunicationServerLLGS::Handle_H); | |||
94 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I, | |||
95 | &GDBRemoteCommunicationServerLLGS::Handle_I); | |||
96 | RegisterMemberFunctionHandler( | |||
97 | StringExtractorGDBRemote::eServerPacketType_interrupt, | |||
98 | &GDBRemoteCommunicationServerLLGS::Handle_interrupt); | |||
99 | RegisterMemberFunctionHandler( | |||
100 | StringExtractorGDBRemote::eServerPacketType_m, | |||
101 | &GDBRemoteCommunicationServerLLGS::Handle_memory_read); | |||
102 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M, | |||
103 | &GDBRemoteCommunicationServerLLGS::Handle_M); | |||
104 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, | |||
105 | &GDBRemoteCommunicationServerLLGS::Handle_p); | |||
106 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P, | |||
107 | &GDBRemoteCommunicationServerLLGS::Handle_P); | |||
108 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC, | |||
109 | &GDBRemoteCommunicationServerLLGS::Handle_qC); | |||
110 | RegisterMemberFunctionHandler( | |||
111 | StringExtractorGDBRemote::eServerPacketType_qfThreadInfo, | |||
112 | &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo); | |||
113 | RegisterMemberFunctionHandler( | |||
114 | StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress, | |||
115 | &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress); | |||
116 | RegisterMemberFunctionHandler( | |||
117 | StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir, | |||
118 | &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir); | |||
119 | RegisterMemberFunctionHandler( | |||
120 | StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo, | |||
121 | &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo); | |||
122 | RegisterMemberFunctionHandler( | |||
123 | StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported, | |||
124 | &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported); | |||
125 | RegisterMemberFunctionHandler( | |||
126 | StringExtractorGDBRemote::eServerPacketType_qProcessInfo, | |||
127 | &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo); | |||
128 | RegisterMemberFunctionHandler( | |||
129 | StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, | |||
130 | &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); | |||
131 | RegisterMemberFunctionHandler( | |||
132 | StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, | |||
133 | &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); | |||
134 | RegisterMemberFunctionHandler( | |||
135 | StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState, | |||
136 | &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState); | |||
137 | RegisterMemberFunctionHandler( | |||
138 | StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR, | |||
139 | &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR); | |||
140 | RegisterMemberFunctionHandler( | |||
141 | StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, | |||
142 | &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir); | |||
143 | RegisterMemberFunctionHandler( | |||
144 | StringExtractorGDBRemote::eServerPacketType_qsThreadInfo, | |||
145 | &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo); | |||
146 | RegisterMemberFunctionHandler( | |||
147 | StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo, | |||
148 | &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); | |||
149 | RegisterMemberFunctionHandler( | |||
150 | StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, | |||
151 | &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo); | |||
152 | RegisterMemberFunctionHandler( | |||
153 | StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo, | |||
154 | &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo); | |||
155 | RegisterMemberFunctionHandler( | |||
156 | StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, | |||
157 | &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read); | |||
158 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s, | |||
159 | &GDBRemoteCommunicationServerLLGS::Handle_s); | |||
160 | RegisterMemberFunctionHandler( | |||
161 | StringExtractorGDBRemote::eServerPacketType_stop_reason, | |||
162 | &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ? | |||
163 | RegisterMemberFunctionHandler( | |||
164 | StringExtractorGDBRemote::eServerPacketType_vAttach, | |||
165 | &GDBRemoteCommunicationServerLLGS::Handle_vAttach); | |||
166 | RegisterMemberFunctionHandler( | |||
167 | StringExtractorGDBRemote::eServerPacketType_vCont, | |||
168 | &GDBRemoteCommunicationServerLLGS::Handle_vCont); | |||
169 | RegisterMemberFunctionHandler( | |||
170 | StringExtractorGDBRemote::eServerPacketType_vCont_actions, | |||
171 | &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); | |||
172 | RegisterMemberFunctionHandler( | |||
173 | StringExtractorGDBRemote::eServerPacketType_x, | |||
174 | &GDBRemoteCommunicationServerLLGS::Handle_memory_read); | |||
175 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z, | |||
176 | &GDBRemoteCommunicationServerLLGS::Handle_Z); | |||
177 | RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, | |||
178 | &GDBRemoteCommunicationServerLLGS::Handle_z); | |||
179 | RegisterMemberFunctionHandler( | |||
180 | StringExtractorGDBRemote::eServerPacketType_QPassSignals, | |||
181 | &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals); | |||
182 | ||||
183 | RegisterMemberFunctionHandler( | |||
184 | StringExtractorGDBRemote::eServerPacketType_jTraceStart, | |||
185 | &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart); | |||
186 | RegisterMemberFunctionHandler( | |||
187 | StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead, | |||
188 | &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); | |||
189 | RegisterMemberFunctionHandler( | |||
190 | StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead, | |||
191 | &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead); | |||
192 | RegisterMemberFunctionHandler( | |||
193 | StringExtractorGDBRemote::eServerPacketType_jTraceStop, | |||
194 | &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop); | |||
195 | RegisterMemberFunctionHandler( | |||
196 | StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, | |||
197 | &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); | |||
198 | ||||
199 | RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k, | |||
200 | [this](StringExtractorGDBRemote packet, Status &error, | |||
201 | bool &interrupt, bool &quit) { | |||
202 | quit = true; | |||
203 | return this->Handle_k(packet); | |||
204 | }); | |||
205 | } | |||
206 | ||||
207 | void GDBRemoteCommunicationServerLLGS::SetLaunchInfo(const ProcessLaunchInfo &info) { | |||
208 | m_process_launch_info = info; | |||
209 | } | |||
210 | ||||
211 | Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { | |||
212 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
213 | ||||
214 | if (!m_process_launch_info.GetArguments().GetArgumentCount()) | |||
215 | return Status("%s: no process command line specified to launch", | |||
216 | __FUNCTION__); | |||
217 | ||||
218 | const bool should_forward_stdio = | |||
219 | m_process_launch_info.GetFileActionForFD(STDIN_FILENO0) == nullptr || | |||
220 | m_process_launch_info.GetFileActionForFD(STDOUT_FILENO1) == nullptr || | |||
221 | m_process_launch_info.GetFileActionForFD(STDERR_FILENO2) == nullptr; | |||
222 | m_process_launch_info.SetLaunchInSeparateProcessGroup(true); | |||
223 | m_process_launch_info.GetFlags().Set(eLaunchFlagDebug); | |||
224 | ||||
225 | const bool default_to_use_pty = true; | |||
226 | m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty); | |||
227 | ||||
228 | { | |||
229 | std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); | |||
230 | assert(!m_debugged_process_up && "lldb-server creating debugged "((!m_debugged_process_up && "lldb-server creating debugged " "process but one already exists") ? static_cast<void> ( 0) : __assert_fail ("!m_debugged_process_up && \"lldb-server creating debugged \" \"process but one already exists\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 231, __PRETTY_FUNCTION__)) | |||
231 | "process but one already exists")((!m_debugged_process_up && "lldb-server creating debugged " "process but one already exists") ? static_cast<void> ( 0) : __assert_fail ("!m_debugged_process_up && \"lldb-server creating debugged \" \"process but one already exists\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 231, __PRETTY_FUNCTION__)); | |||
232 | auto process_or = | |||
233 | m_process_factory.Launch(m_process_launch_info, *this, m_mainloop); | |||
234 | if (!process_or) | |||
235 | return Status(process_or.takeError()); | |||
236 | m_debugged_process_up = std::move(*process_or); | |||
237 | } | |||
238 | ||||
239 | // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as | |||
240 | // needed. llgs local-process debugging may specify PTY paths, which will | |||
241 | // make these file actions non-null process launch -i/e/o will also make | |||
242 | // these file actions non-null nullptr means that the traffic is expected to | |||
243 | // flow over gdb-remote protocol | |||
244 | if (should_forward_stdio) { | |||
245 | // nullptr means it's not redirected to file or pty (in case of LLGS local) | |||
246 | // at least one of stdio will be transferred pty<->gdb-remote we need to | |||
247 | // give the pty master handle to this object to read and/or write | |||
248 | LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}: setting up stdout/stderr redirection via $O " "gdb-remote commands", m_debugged_process_up->GetID()); } while (0) | |||
249 | "pid = {0}: setting up stdout/stderr redirection via $O "do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}: setting up stdout/stderr redirection via $O " "gdb-remote commands", m_debugged_process_up->GetID()); } while (0) | |||
250 | "gdb-remote commands",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}: setting up stdout/stderr redirection via $O " "gdb-remote commands", m_debugged_process_up->GetID()); } while (0) | |||
251 | m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}: setting up stdout/stderr redirection via $O " "gdb-remote commands", m_debugged_process_up->GetID()); } while (0); | |||
252 | ||||
253 | // Setup stdout/stderr mapping from inferior to $O | |||
254 | auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); | |||
255 | if (terminal_fd >= 0) { | |||
256 | if (log) | |||
257 | log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " | |||
258 | "inferior STDIO fd to %d", | |||
259 | __FUNCTION__, terminal_fd); | |||
260 | Status status = SetSTDIOFileDescriptor(terminal_fd); | |||
261 | if (status.Fail()) | |||
262 | return status; | |||
263 | } else { | |||
264 | if (log) | |||
265 | log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " | |||
266 | "inferior STDIO since terminal fd reported as %d", | |||
267 | __FUNCTION__, terminal_fd); | |||
268 | } | |||
269 | } else { | |||
270 | LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0} skipping stdout/stderr redirection via $O: inferior " "will communicate over client-provided file descriptors", m_debugged_process_up ->GetID()); } while (0) | |||
271 | "pid = {0} skipping stdout/stderr redirection via $O: inferior "do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0} skipping stdout/stderr redirection via $O: inferior " "will communicate over client-provided file descriptors", m_debugged_process_up ->GetID()); } while (0) | |||
272 | "will communicate over client-provided file descriptors",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0} skipping stdout/stderr redirection via $O: inferior " "will communicate over client-provided file descriptors", m_debugged_process_up ->GetID()); } while (0) | |||
273 | m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0} skipping stdout/stderr redirection via $O: inferior " "will communicate over client-provided file descriptors", m_debugged_process_up ->GetID()); } while (0); | |||
274 | } | |||
275 | ||||
276 | printf("Launched '%s' as process %" PRIu64"l" "u" "...\n", | |||
277 | m_process_launch_info.GetArguments().GetArgumentAtIndex(0), | |||
278 | m_debugged_process_up->GetID()); | |||
279 | ||||
280 | return Status(); | |||
281 | } | |||
282 | ||||
283 | Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { | |||
284 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
285 | if (log) | |||
286 | log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64"l" "u", | |||
287 | __FUNCTION__, pid); | |||
288 | ||||
289 | // Before we try to attach, make sure we aren't already monitoring something | |||
290 | // else. | |||
291 | if (m_debugged_process_up && | |||
292 | m_debugged_process_up->GetID() != LLDB_INVALID_PROCESS_ID0) | |||
293 | return Status("cannot attach to process %" PRIu64"l" "u" | |||
294 | " when another process with pid %" PRIu64"l" "u" | |||
295 | " is being debugged.", | |||
296 | pid, m_debugged_process_up->GetID()); | |||
297 | ||||
298 | // Try to attach. | |||
299 | auto process_or = m_process_factory.Attach(pid, *this, m_mainloop); | |||
300 | if (!process_or) { | |||
301 | Status status(process_or.takeError()); | |||
302 | llvm::errs() << llvm::formatv("failed to attach to process {0}: {1}", pid, | |||
303 | status); | |||
304 | return status; | |||
305 | } | |||
306 | m_debugged_process_up = std::move(*process_or); | |||
307 | ||||
308 | // Setup stdout/stderr mapping from inferior. | |||
309 | auto terminal_fd = m_debugged_process_up->GetTerminalFileDescriptor(); | |||
310 | if (terminal_fd >= 0) { | |||
311 | if (log) | |||
312 | log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting " | |||
313 | "inferior STDIO fd to %d", | |||
314 | __FUNCTION__, terminal_fd); | |||
315 | Status status = SetSTDIOFileDescriptor(terminal_fd); | |||
316 | if (status.Fail()) | |||
317 | return status; | |||
318 | } else { | |||
319 | if (log) | |||
320 | log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring " | |||
321 | "inferior STDIO since terminal fd reported as %d", | |||
322 | __FUNCTION__, terminal_fd); | |||
323 | } | |||
324 | ||||
325 | printf("Attached to process %" PRIu64"l" "u" "...\n", pid); | |||
326 | return Status(); | |||
327 | } | |||
328 | ||||
329 | void GDBRemoteCommunicationServerLLGS::InitializeDelegate( | |||
330 | NativeProcessProtocol *process) { | |||
331 | assert(process && "process cannot be NULL")((process && "process cannot be NULL") ? static_cast< void> (0) : __assert_fail ("process && \"process cannot be NULL\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 331, __PRETTY_FUNCTION__)); | |||
332 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
333 | if (log) { | |||
334 | log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " | |||
335 | "NativeProcessProtocol pid %" PRIu64"l" "u" ", current state: %s", | |||
336 | __FUNCTION__, process->GetID(), | |||
337 | StateAsCString(process->GetState())); | |||
338 | } | |||
339 | } | |||
340 | ||||
341 | GDBRemoteCommunication::PacketResult | |||
342 | GDBRemoteCommunicationServerLLGS::SendWResponse( | |||
343 | NativeProcessProtocol *process) { | |||
344 | assert(process && "process cannot be NULL")((process && "process cannot be NULL") ? static_cast< void> (0) : __assert_fail ("process && \"process cannot be NULL\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 344, __PRETTY_FUNCTION__)); | |||
345 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
346 | ||||
347 | // send W notification | |||
348 | auto wait_status = process->GetExitStatus(); | |||
349 | if (!wait_status) { | |||
350 | LLDB_LOG(log, "pid = {0}, failed to retrieve process exit status",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}, failed to retrieve process exit status" , process->GetID()); } while (0) | |||
351 | process->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}, failed to retrieve process exit status" , process->GetID()); } while (0); | |||
352 | ||||
353 | StreamGDBRemote response; | |||
354 | response.PutChar('E'); | |||
355 | response.PutHex8(GDBRemoteServerError::eErrorExitStatus); | |||
356 | return SendPacketNoLock(response.GetString()); | |||
357 | } | |||
358 | ||||
359 | LLDB_LOG(log, "pid = {0}, returning exit type {1}", process->GetID(),do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}, returning exit type {1}", process-> GetID(), *wait_status); } while (0) | |||
360 | *wait_status)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid = {0}, returning exit type {1}", process-> GetID(), *wait_status); } while (0); | |||
361 | ||||
362 | StreamGDBRemote response; | |||
363 | response.Format("{0:g}", *wait_status); | |||
364 | return SendPacketNoLock(response.GetString()); | |||
365 | } | |||
366 | ||||
367 | static void AppendHexValue(StreamString &response, const uint8_t *buf, | |||
368 | uint32_t buf_size, bool swap) { | |||
369 | int64_t i; | |||
370 | if (swap) { | |||
371 | for (i = buf_size - 1; i >= 0; i--) | |||
372 | response.PutHex8(buf[i]); | |||
373 | } else { | |||
374 | for (i = 0; i < buf_size; i++) | |||
375 | response.PutHex8(buf[i]); | |||
376 | } | |||
377 | } | |||
378 | ||||
379 | static void WriteRegisterValueInHexFixedWidth( | |||
380 | StreamString &response, NativeRegisterContext ®_ctx, | |||
381 | const RegisterInfo ®_info, const RegisterValue *reg_value_p, | |||
382 | lldb::ByteOrder byte_order) { | |||
383 | RegisterValue reg_value; | |||
384 | if (!reg_value_p) { | |||
385 | Status error = reg_ctx.ReadRegister(®_info, reg_value); | |||
386 | if (error.Success()) | |||
387 | reg_value_p = ®_value; | |||
388 | // else log. | |||
389 | } | |||
390 | ||||
391 | if (reg_value_p) { | |||
392 | AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(), | |||
393 | reg_value_p->GetByteSize(), | |||
394 | byte_order == lldb::eByteOrderLittle); | |||
395 | } else { | |||
396 | // Zero-out any unreadable values. | |||
397 | if (reg_info.byte_size > 0) { | |||
398 | std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0'); | |||
399 | AppendHexValue(response, zeros.data(), zeros.size(), false); | |||
400 | } | |||
401 | } | |||
402 | } | |||
403 | ||||
404 | static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread) { | |||
405 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
406 | ||||
407 | NativeRegisterContext& reg_ctx = thread.GetRegisterContext(); | |||
408 | ||||
409 | JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); | |||
410 | ||||
411 | #ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET | |||
412 | // Expedite all registers in the first register set (i.e. should be GPRs) | |||
413 | // that are not contained in other registers. | |||
414 | const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); | |||
415 | if (!reg_set_p) | |||
416 | return nullptr; | |||
417 | for (const uint32_t *reg_num_p = reg_set_p->registers; | |||
418 | *reg_num_p != LLDB_INVALID_REGNUM(4294967295U); ++reg_num_p) { | |||
419 | uint32_t reg_num = *reg_num_p; | |||
420 | #else | |||
421 | // Expedite only a couple of registers until we figure out why sending | |||
422 | // registers is expensive. | |||
423 | static const uint32_t k_expedited_registers[] = { | |||
424 | LLDB_REGNUM_GENERIC_PC0, LLDB_REGNUM_GENERIC_SP1, LLDB_REGNUM_GENERIC_FP2, | |||
425 | LLDB_REGNUM_GENERIC_RA3, LLDB_INVALID_REGNUM(4294967295U)}; | |||
426 | ||||
427 | for (const uint32_t *generic_reg_p = k_expedited_registers; | |||
428 | *generic_reg_p != LLDB_INVALID_REGNUM(4294967295U); ++generic_reg_p) { | |||
429 | uint32_t reg_num = reg_ctx.ConvertRegisterKindToRegisterNumber( | |||
430 | eRegisterKindGeneric, *generic_reg_p); | |||
431 | if (reg_num == LLDB_INVALID_REGNUM(4294967295U)) | |||
432 | continue; // Target does not support the given register. | |||
433 | #endif | |||
434 | ||||
435 | const RegisterInfo *const reg_info_p = | |||
436 | reg_ctx.GetRegisterInfoAtIndex(reg_num); | |||
437 | if (reg_info_p == nullptr) { | |||
438 | if (log) | |||
439 | log->Printf( | |||
440 | "%s failed to get register info for register index %" PRIu32"u", | |||
441 | __FUNCTION__, reg_num); | |||
442 | continue; | |||
443 | } | |||
444 | ||||
445 | if (reg_info_p->value_regs != nullptr) | |||
446 | continue; // Only expedite registers that are not contained in other | |||
447 | // registers. | |||
448 | ||||
449 | RegisterValue reg_value; | |||
450 | Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); | |||
451 | if (error.Fail()) { | |||
452 | if (log) | |||
453 | log->Printf("%s failed to read register '%s' index %" PRIu32"u" ": %s", | |||
454 | __FUNCTION__, | |||
455 | reg_info_p->name ? reg_info_p->name : "<unnamed-register>", | |||
456 | reg_num, error.AsCString()); | |||
457 | continue; | |||
458 | } | |||
459 | ||||
460 | StreamString stream; | |||
461 | WriteRegisterValueInHexFixedWidth(stream, reg_ctx, *reg_info_p, | |||
462 | ®_value, lldb::eByteOrderBig); | |||
463 | ||||
464 | register_object_sp->SetObject( | |||
465 | llvm::to_string(reg_num), | |||
466 | std::make_shared<JSONString>(stream.GetString())); | |||
467 | } | |||
468 | ||||
469 | return register_object_sp; | |||
470 | } | |||
471 | ||||
472 | static const char *GetStopReasonString(StopReason stop_reason) { | |||
473 | switch (stop_reason) { | |||
474 | case eStopReasonTrace: | |||
475 | return "trace"; | |||
476 | case eStopReasonBreakpoint: | |||
477 | return "breakpoint"; | |||
478 | case eStopReasonWatchpoint: | |||
479 | return "watchpoint"; | |||
480 | case eStopReasonSignal: | |||
481 | return "signal"; | |||
482 | case eStopReasonException: | |||
483 | return "exception"; | |||
484 | case eStopReasonExec: | |||
485 | return "exec"; | |||
486 | case eStopReasonInstrumentation: | |||
487 | case eStopReasonInvalid: | |||
488 | case eStopReasonPlanComplete: | |||
489 | case eStopReasonThreadExiting: | |||
490 | case eStopReasonNone: | |||
491 | break; // ignored | |||
492 | } | |||
493 | return nullptr; | |||
494 | } | |||
495 | ||||
496 | static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process, | |||
497 | bool abridged) { | |||
498 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
499 | ||||
500 | JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); | |||
501 | ||||
502 | // Ensure we can get info on the given thread. | |||
503 | uint32_t thread_idx = 0; | |||
504 | for (NativeThreadProtocol *thread; | |||
505 | (thread = process.GetThreadAtIndex(thread_idx)) != nullptr; | |||
506 | ++thread_idx) { | |||
507 | ||||
508 | lldb::tid_t tid = thread->GetID(); | |||
509 | ||||
510 | // Grab the reason this thread stopped. | |||
511 | struct ThreadStopInfo tid_stop_info; | |||
512 | std::string description; | |||
513 | if (!thread->GetStopReason(tid_stop_info, description)) | |||
514 | return nullptr; | |||
515 | ||||
516 | const int signum = tid_stop_info.details.signal.signo; | |||
517 | if (log) { | |||
518 | log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64"l" "u" | |||
519 | " tid %" PRIu64"l" "u" | |||
520 | " got signal signo = %d, reason = %d, exc_type = %" PRIu64"l" "u", | |||
521 | __FUNCTION__, process.GetID(), tid, signum, | |||
522 | tid_stop_info.reason, tid_stop_info.details.exception.type); | |||
523 | } | |||
524 | ||||
525 | JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); | |||
526 | threads_array_sp->AppendObject(thread_obj_sp); | |||
527 | ||||
528 | if (!abridged) { | |||
529 | if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread)) | |||
530 | thread_obj_sp->SetObject("registers", registers_sp); | |||
531 | } | |||
532 | ||||
533 | thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); | |||
534 | if (signum != 0) | |||
535 | thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); | |||
536 | ||||
537 | const std::string thread_name = thread->GetName(); | |||
538 | if (!thread_name.empty()) | |||
539 | thread_obj_sp->SetObject("name", | |||
540 | std::make_shared<JSONString>(thread_name)); | |||
541 | ||||
542 | if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) | |||
543 | thread_obj_sp->SetObject("reason", | |||
544 | std::make_shared<JSONString>(stop_reason_str)); | |||
545 | ||||
546 | if (!description.empty()) | |||
547 | thread_obj_sp->SetObject("description", | |||
548 | std::make_shared<JSONString>(description)); | |||
549 | ||||
550 | if ((tid_stop_info.reason == eStopReasonException) && | |||
551 | tid_stop_info.details.exception.type) { | |||
552 | thread_obj_sp->SetObject( | |||
553 | "metype", | |||
554 | std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); | |||
555 | ||||
556 | JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); | |||
557 | for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; | |||
558 | ++i) { | |||
559 | medata_array_sp->AppendObject(std::make_shared<JSONNumber>( | |||
560 | tid_stop_info.details.exception.data[i])); | |||
561 | } | |||
562 | thread_obj_sp->SetObject("medata", medata_array_sp); | |||
563 | } | |||
564 | ||||
565 | // TODO: Expedite interesting regions of inferior memory | |||
566 | } | |||
567 | ||||
568 | return threads_array_sp; | |||
569 | } | |||
570 | ||||
571 | GDBRemoteCommunication::PacketResult | |||
572 | GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread( | |||
573 | lldb::tid_t tid) { | |||
574 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
575 | ||||
576 | // Ensure we have a debugged process. | |||
577 | if (!m_debugged_process_up || | |||
578 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
579 | return SendErrorResponse(50); | |||
580 | ||||
581 | LLDB_LOG(log, "preparing packet for pid {0} tid {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "preparing packet for pid {0} tid {1}", m_debugged_process_up ->GetID(), tid); } while (0) | |||
582 | m_debugged_process_up->GetID(), tid)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "preparing packet for pid {0} tid {1}", m_debugged_process_up ->GetID(), tid); } while (0); | |||
583 | ||||
584 | // Ensure we can get info on the given thread. | |||
585 | NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); | |||
586 | if (!thread) | |||
587 | return SendErrorResponse(51); | |||
588 | ||||
589 | // Grab the reason this thread stopped. | |||
590 | struct ThreadStopInfo tid_stop_info; | |||
591 | std::string description; | |||
592 | if (!thread->GetStopReason(tid_stop_info, description)) | |||
593 | return SendErrorResponse(52); | |||
594 | ||||
595 | // FIXME implement register handling for exec'd inferiors. | |||
596 | // if (tid_stop_info.reason == eStopReasonExec) { | |||
597 | // const bool force = true; | |||
598 | // InitializeRegisters(force); | |||
599 | // } | |||
600 | ||||
601 | StreamString response; | |||
602 | // Output the T packet with the thread | |||
603 | response.PutChar('T'); | |||
604 | int signum = tid_stop_info.details.signal.signo; | |||
605 | LLDB_LOG(do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}" , m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info .reason), tid_stop_info.details.exception.type); } while (0) | |||
606 | log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}" , m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info .reason), tid_stop_info.details.exception.type); } while (0) | |||
607 | "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}" , m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info .reason), tid_stop_info.details.exception.type); } while (0) | |||
608 | m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info.reason),do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}" , m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info .reason), tid_stop_info.details.exception.type); } while (0) | |||
609 | tid_stop_info.details.exception.type)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, tid {1}, got signal signo = {2}, reason = {3}, exc_type = {4}" , m_debugged_process_up->GetID(), tid, signum, int(tid_stop_info .reason), tid_stop_info.details.exception.type); } while (0); | |||
610 | ||||
611 | // Print the signal number. | |||
612 | response.PutHex8(signum & 0xff); | |||
613 | ||||
614 | // Include the tid. | |||
615 | response.Printf("thread:%" PRIx64"l" "x" ";", tid); | |||
616 | ||||
617 | // Include the thread name if there is one. | |||
618 | const std::string thread_name = thread->GetName(); | |||
619 | if (!thread_name.empty()) { | |||
620 | size_t thread_name_len = thread_name.length(); | |||
621 | ||||
622 | if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) { | |||
623 | response.PutCString("name:"); | |||
624 | response.PutCString(thread_name); | |||
625 | } else { | |||
626 | // The thread name contains special chars, send as hex bytes. | |||
627 | response.PutCString("hexname:"); | |||
628 | response.PutCStringAsRawHex8(thread_name.c_str()); | |||
629 | } | |||
630 | response.PutChar(';'); | |||
631 | } | |||
632 | ||||
633 | // If a 'QListThreadsInStopReply' was sent to enable this feature, we will | |||
634 | // send all thread IDs back in the "threads" key whose value is a list of hex | |||
635 | // thread IDs separated by commas: | |||
636 | // "threads:10a,10b,10c;" | |||
637 | // This will save the debugger from having to send a pair of qfThreadInfo and | |||
638 | // qsThreadInfo packets, but it also might take a lot of room in the stop | |||
639 | // reply packet, so it must be enabled only on systems where there are no | |||
640 | // limits on packet lengths. | |||
641 | if (m_list_threads_in_stop_reply) { | |||
642 | response.PutCString("threads:"); | |||
643 | ||||
644 | uint32_t thread_index = 0; | |||
645 | NativeThreadProtocol *listed_thread; | |||
646 | for (listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index); | |||
647 | listed_thread; ++thread_index, | |||
648 | listed_thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { | |||
649 | if (thread_index > 0) | |||
650 | response.PutChar(','); | |||
651 | response.Printf("%" PRIx64"l" "x", listed_thread->GetID()); | |||
652 | } | |||
653 | response.PutChar(';'); | |||
654 | ||||
655 | // Include JSON info that describes the stop reason for any threads that | |||
656 | // actually have stop reasons. We use the new "jstopinfo" key whose values | |||
657 | // is hex ascii JSON that contains the thread IDs thread stop info only for | |||
658 | // threads that have stop reasons. Only send this if we have more than one | |||
659 | // thread otherwise this packet has all the info it needs. | |||
660 | if (thread_index > 0) { | |||
661 | const bool threads_with_valid_stop_info_only = true; | |||
662 | JSONArray::SP threads_info_sp = GetJSONThreadsInfo( | |||
663 | *m_debugged_process_up, threads_with_valid_stop_info_only); | |||
664 | if (threads_info_sp) { | |||
665 | response.PutCString("jstopinfo:"); | |||
666 | StreamString unescaped_response; | |||
667 | threads_info_sp->Write(unescaped_response); | |||
668 | response.PutCStringAsRawHex8(unescaped_response.GetData()); | |||
669 | response.PutChar(';'); | |||
670 | } else | |||
671 | LLDB_LOG(log, "failed to prepare a jstopinfo field for pid {0}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to prepare a jstopinfo field for pid {0}" , m_debugged_process_up->GetID()); } while (0) | |||
672 | m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to prepare a jstopinfo field for pid {0}" , m_debugged_process_up->GetID()); } while (0); | |||
673 | } | |||
674 | ||||
675 | uint32_t i = 0; | |||
676 | response.PutCString("thread-pcs"); | |||
677 | char delimiter = ':'; | |||
678 | for (NativeThreadProtocol *thread; | |||
679 | (thread = m_debugged_process_up->GetThreadAtIndex(i)) != nullptr; | |||
680 | ++i) { | |||
681 | NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); | |||
682 | ||||
683 | uint32_t reg_to_read = reg_ctx.ConvertRegisterKindToRegisterNumber( | |||
684 | eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC0); | |||
685 | const RegisterInfo *const reg_info_p = | |||
686 | reg_ctx.GetRegisterInfoAtIndex(reg_to_read); | |||
687 | ||||
688 | RegisterValue reg_value; | |||
689 | Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); | |||
690 | if (error.Fail()) { | |||
691 | if (log) | |||
692 | log->Printf("%s failed to read register '%s' index %" PRIu32"u" ": %s", | |||
693 | __FUNCTION__, | |||
694 | reg_info_p->name ? reg_info_p->name | |||
695 | : "<unnamed-register>", | |||
696 | reg_to_read, error.AsCString()); | |||
697 | continue; | |||
698 | } | |||
699 | ||||
700 | response.PutChar(delimiter); | |||
701 | delimiter = ','; | |||
702 | WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, | |||
703 | ®_value, endian::InlHostByteOrder()); | |||
704 | } | |||
705 | ||||
706 | response.PutChar(';'); | |||
707 | } | |||
708 | ||||
709 | // | |||
710 | // Expedite registers. | |||
711 | // | |||
712 | ||||
713 | // Grab the register context. | |||
714 | NativeRegisterContext& reg_ctx = thread->GetRegisterContext(); | |||
715 | // Expedite all registers in the first register set (i.e. should be GPRs) | |||
716 | // that are not contained in other registers. | |||
717 | const RegisterSet *reg_set_p; | |||
718 | if (reg_ctx.GetRegisterSetCount() > 0 && | |||
719 | ((reg_set_p = reg_ctx.GetRegisterSet(0)) != nullptr)) { | |||
720 | if (log) | |||
721 | log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers " | |||
722 | "from set '%s' (registers set count: %zu)", | |||
723 | __FUNCTION__, | |||
724 | reg_set_p->name ? reg_set_p->name : "<unnamed-set>", | |||
725 | reg_set_p->num_registers); | |||
726 | ||||
727 | for (const uint32_t *reg_num_p = reg_set_p->registers; | |||
728 | *reg_num_p != LLDB_INVALID_REGNUM(4294967295U); ++reg_num_p) { | |||
729 | const RegisterInfo *const reg_info_p = | |||
730 | reg_ctx.GetRegisterInfoAtIndex(*reg_num_p); | |||
731 | if (reg_info_p == nullptr) { | |||
732 | if (log) | |||
733 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get " | |||
734 | "register info for register set '%s', register index " | |||
735 | "%" PRIu32"u", | |||
736 | __FUNCTION__, | |||
737 | reg_set_p->name ? reg_set_p->name : "<unnamed-set>", | |||
738 | *reg_num_p); | |||
739 | } else if (reg_info_p->value_regs == nullptr) { | |||
740 | // Only expediate registers that are not contained in other registers. | |||
741 | RegisterValue reg_value; | |||
742 | Status error = reg_ctx.ReadRegister(reg_info_p, reg_value); | |||
743 | if (error.Success()) { | |||
744 | response.Printf("%.02x:", *reg_num_p); | |||
745 | WriteRegisterValueInHexFixedWidth(response, reg_ctx, *reg_info_p, | |||
746 | ®_value, lldb::eByteOrderBig); | |||
747 | response.PutChar(';'); | |||
748 | } else { | |||
749 | if (log) | |||
750 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read " | |||
751 | "register '%s' index %" PRIu32"u" ": %s", | |||
752 | __FUNCTION__, | |||
753 | reg_info_p->name ? reg_info_p->name | |||
754 | : "<unnamed-register>", | |||
755 | *reg_num_p, error.AsCString()); | |||
756 | } | |||
757 | } | |||
758 | } | |||
759 | } | |||
760 | ||||
761 | const char *reason_str = GetStopReasonString(tid_stop_info.reason); | |||
762 | if (reason_str != nullptr) { | |||
763 | response.Printf("reason:%s;", reason_str); | |||
764 | } | |||
765 | ||||
766 | if (!description.empty()) { | |||
767 | // Description may contains special chars, send as hex bytes. | |||
768 | response.PutCString("description:"); | |||
769 | response.PutCStringAsRawHex8(description.c_str()); | |||
770 | response.PutChar(';'); | |||
771 | } else if ((tid_stop_info.reason == eStopReasonException) && | |||
772 | tid_stop_info.details.exception.type) { | |||
773 | response.PutCString("metype:"); | |||
774 | response.PutHex64(tid_stop_info.details.exception.type); | |||
775 | response.PutCString(";mecount:"); | |||
776 | response.PutHex32(tid_stop_info.details.exception.data_count); | |||
777 | response.PutChar(';'); | |||
778 | ||||
779 | for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) { | |||
780 | response.PutCString("medata:"); | |||
781 | response.PutHex64(tid_stop_info.details.exception.data[i]); | |||
782 | response.PutChar(';'); | |||
783 | } | |||
784 | } | |||
785 | ||||
786 | return SendPacketNoLock(response.GetString()); | |||
787 | } | |||
788 | ||||
789 | void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( | |||
790 | NativeProcessProtocol *process) { | |||
791 | assert(process && "process cannot be NULL")((process && "process cannot be NULL") ? static_cast< void> (0) : __assert_fail ("process && \"process cannot be NULL\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 791, __PRETTY_FUNCTION__)); | |||
792 | ||||
793 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
794 | if (log) | |||
795 | log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); | |||
796 | ||||
797 | PacketResult result = SendStopReasonForState(StateType::eStateExited); | |||
798 | if (result != PacketResult::Success) { | |||
799 | if (log) | |||
800 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " | |||
801 | "notification for PID %" PRIu64"l" "u" ", state: eStateExited", | |||
802 | __FUNCTION__, process->GetID()); | |||
803 | } | |||
804 | ||||
805 | // Close the pipe to the inferior terminal i/o if we launched it and set one | |||
806 | // up. | |||
807 | MaybeCloseInferiorTerminalConnection(); | |||
808 | ||||
809 | // We are ready to exit the debug monitor. | |||
810 | m_exit_now = true; | |||
811 | m_mainloop.RequestTermination(); | |||
812 | } | |||
813 | ||||
814 | void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( | |||
815 | NativeProcessProtocol *process) { | |||
816 | assert(process && "process cannot be NULL")((process && "process cannot be NULL") ? static_cast< void> (0) : __assert_fail ("process && \"process cannot be NULL\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 816, __PRETTY_FUNCTION__)); | |||
817 | ||||
818 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
819 | if (log) | |||
820 | log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); | |||
821 | ||||
822 | // Send the stop reason unless this is the stop after the launch or attach. | |||
823 | switch (m_inferior_prev_state) { | |||
824 | case eStateLaunching: | |||
825 | case eStateAttaching: | |||
826 | // Don't send anything per debugserver behavior. | |||
827 | break; | |||
828 | default: | |||
829 | // In all other cases, send the stop reason. | |||
830 | PacketResult result = SendStopReasonForState(StateType::eStateStopped); | |||
831 | if (result != PacketResult::Success) { | |||
832 | if (log) | |||
833 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop " | |||
834 | "notification for PID %" PRIu64"l" "u" ", state: eStateExited", | |||
835 | __FUNCTION__, process->GetID()); | |||
836 | } | |||
837 | break; | |||
838 | } | |||
839 | } | |||
840 | ||||
841 | void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( | |||
842 | NativeProcessProtocol *process, lldb::StateType state) { | |||
843 | assert(process && "process cannot be NULL")((process && "process cannot be NULL") ? static_cast< void> (0) : __assert_fail ("process && \"process cannot be NULL\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 843, __PRETTY_FUNCTION__)); | |||
844 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
845 | if (log) { | |||
846 | log->Printf("GDBRemoteCommunicationServerLLGS::%s called with " | |||
847 | "NativeProcessProtocol pid %" PRIu64"l" "u" ", state: %s", | |||
848 | __FUNCTION__, process->GetID(), StateAsCString(state)); | |||
849 | } | |||
850 | ||||
851 | switch (state) { | |||
852 | case StateType::eStateRunning: | |||
853 | StartSTDIOForwarding(); | |||
854 | break; | |||
855 | ||||
856 | case StateType::eStateStopped: | |||
857 | // Make sure we get all of the pending stdout/stderr from the inferior and | |||
858 | // send it to the lldb host before we send the state change notification | |||
859 | SendProcessOutput(); | |||
860 | // Then stop the forwarding, so that any late output (see llvm.org/pr25652) | |||
861 | // does not interfere with our protocol. | |||
862 | StopSTDIOForwarding(); | |||
863 | HandleInferiorState_Stopped(process); | |||
864 | break; | |||
865 | ||||
866 | case StateType::eStateExited: | |||
867 | // Same as above | |||
868 | SendProcessOutput(); | |||
869 | StopSTDIOForwarding(); | |||
870 | HandleInferiorState_Exited(process); | |||
871 | break; | |||
872 | ||||
873 | default: | |||
874 | if (log) { | |||
875 | log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state " | |||
876 | "change for pid %" PRIu64"l" "u" ", new state: %s", | |||
877 | __FUNCTION__, process->GetID(), StateAsCString(state)); | |||
878 | } | |||
879 | break; | |||
880 | } | |||
881 | ||||
882 | // Remember the previous state reported to us. | |||
883 | m_inferior_prev_state = state; | |||
884 | } | |||
885 | ||||
886 | void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) { | |||
887 | ClearProcessSpecificData(); | |||
888 | } | |||
889 | ||||
890 | void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { | |||
891 | Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM(1u << 10))); | |||
892 | ||||
893 | if (!m_handshake_completed) { | |||
894 | if (!HandshakeWithClient()) { | |||
895 | if (log) | |||
896 | log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with " | |||
897 | "client failed, exiting", | |||
898 | __FUNCTION__); | |||
899 | m_mainloop.RequestTermination(); | |||
900 | return; | |||
901 | } | |||
902 | m_handshake_completed = true; | |||
903 | } | |||
904 | ||||
905 | bool interrupt = false; | |||
906 | bool done = false; | |||
907 | Status error; | |||
908 | while (true) { | |||
909 | const PacketResult result = GetPacketAndSendResponse( | |||
910 | std::chrono::microseconds(0), error, interrupt, done); | |||
911 | if (result == PacketResult::ErrorReplyTimeout) | |||
912 | break; // No more packets in the queue | |||
913 | ||||
914 | if ((result != PacketResult::Success)) { | |||
915 | if (log) | |||
916 | log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet " | |||
917 | "failed: %s", | |||
918 | __FUNCTION__, error.AsCString()); | |||
919 | m_mainloop.RequestTermination(); | |||
920 | break; | |||
921 | } | |||
922 | } | |||
923 | } | |||
924 | ||||
925 | Status GDBRemoteCommunicationServerLLGS::InitializeConnection( | |||
926 | std::unique_ptr<Connection> &&connection) { | |||
927 | IOObjectSP read_object_sp = connection->GetReadObject(); | |||
928 | GDBRemoteCommunicationServer::SetConnection(connection.release()); | |||
929 | ||||
930 | Status error; | |||
931 | m_network_handle_up = m_mainloop.RegisterReadObject( | |||
932 | read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); }, | |||
933 | error); | |||
934 | return error; | |||
935 | } | |||
936 | ||||
937 | GDBRemoteCommunication::PacketResult | |||
938 | GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer, | |||
939 | uint32_t len) { | |||
940 | if ((buffer == nullptr) || (len == 0)) { | |||
941 | // Nothing to send. | |||
942 | return PacketResult::Success; | |||
943 | } | |||
944 | ||||
945 | StreamString response; | |||
946 | response.PutChar('O'); | |||
947 | response.PutBytesAsRawHex8(buffer, len); | |||
948 | ||||
949 | return SendPacketNoLock(response.GetString()); | |||
950 | } | |||
951 | ||||
952 | Status GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) { | |||
953 | Status error; | |||
954 | ||||
955 | // Set up the reading/handling of process I/O | |||
956 | std::unique_ptr<ConnectionFileDescriptor> conn_up( | |||
957 | new ConnectionFileDescriptor(fd, true)); | |||
958 | if (!conn_up) { | |||
959 | error.SetErrorString("failed to create ConnectionFileDescriptor"); | |||
960 | return error; | |||
961 | } | |||
962 | ||||
963 | m_stdio_communication.SetCloseOnEOF(false); | |||
964 | m_stdio_communication.SetConnection(conn_up.release()); | |||
965 | if (!m_stdio_communication.IsConnected()) { | |||
966 | error.SetErrorString( | |||
967 | "failed to set connection for inferior I/O communication"); | |||
968 | return error; | |||
969 | } | |||
970 | ||||
971 | return Status(); | |||
972 | } | |||
973 | ||||
974 | void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() { | |||
975 | // Don't forward if not connected (e.g. when attaching). | |||
976 | if (!m_stdio_communication.IsConnected()) | |||
977 | return; | |||
978 | ||||
979 | Status error; | |||
980 | lldbassert(!m_stdio_handle_up)lldb_private::lldb_assert(static_cast<bool>(!m_stdio_handle_up ), "!m_stdio_handle_up", __FUNCTION__, "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 980); | |||
981 | m_stdio_handle_up = m_mainloop.RegisterReadObject( | |||
982 | m_stdio_communication.GetConnection()->GetReadObject(), | |||
983 | [this](MainLoopBase &) { SendProcessOutput(); }, error); | |||
984 | ||||
985 | if (!m_stdio_handle_up) { | |||
986 | // Not much we can do about the failure. Log it and continue without | |||
987 | // forwarding. | |||
988 | if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))) | |||
989 | log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio " | |||
990 | "forwarding: %s", | |||
991 | __FUNCTION__, error.AsCString()); | |||
992 | } | |||
993 | } | |||
994 | ||||
995 | void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() { | |||
996 | m_stdio_handle_up.reset(); | |||
997 | } | |||
998 | ||||
999 | void GDBRemoteCommunicationServerLLGS::SendProcessOutput() { | |||
1000 | char buffer[1024]; | |||
1001 | ConnectionStatus status; | |||
1002 | Status error; | |||
1003 | while (true) { | |||
1004 | size_t bytes_read = m_stdio_communication.Read( | |||
1005 | buffer, sizeof buffer, std::chrono::microseconds(0), status, &error); | |||
1006 | switch (status) { | |||
1007 | case eConnectionStatusSuccess: | |||
1008 | SendONotification(buffer, bytes_read); | |||
1009 | break; | |||
1010 | case eConnectionStatusLostConnection: | |||
1011 | case eConnectionStatusEndOfFile: | |||
1012 | case eConnectionStatusError: | |||
1013 | case eConnectionStatusNoConnection: | |||
1014 | if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))) | |||
1015 | log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio " | |||
1016 | "forwarding as communication returned status %d (error: " | |||
1017 | "%s)", | |||
1018 | __FUNCTION__, status, error.AsCString()); | |||
1019 | m_stdio_handle_up.reset(); | |||
1020 | return; | |||
1021 | ||||
1022 | case eConnectionStatusInterrupted: | |||
1023 | case eConnectionStatusTimedOut: | |||
1024 | return; | |||
1025 | } | |||
1026 | } | |||
1027 | } | |||
1028 | ||||
1029 | GDBRemoteCommunication::PacketResult | |||
1030 | GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( | |||
1031 | StringExtractorGDBRemote &packet) { | |||
1032 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1033 | // Fail if we don't have a current process. | |||
1034 | if (!m_debugged_process_up || | |||
1035 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
1036 | return SendErrorResponse(68); | |||
1037 | ||||
1038 | if (!packet.ConsumeFront("jTraceStart:")) | |||
1039 | return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); | |||
1040 | ||||
1041 | TraceOptions options; | |||
1042 | uint64_t type = std::numeric_limits<uint64_t>::max(); | |||
1043 | uint64_t buffersize = std::numeric_limits<uint64_t>::max(); | |||
1044 | lldb::tid_t tid = LLDB_INVALID_THREAD_ID0; | |||
1045 | uint64_t metabuffersize = std::numeric_limits<uint64_t>::max(); | |||
1046 | ||||
1047 | auto json_object = StructuredData::ParseJSON(packet.Peek()); | |||
1048 | ||||
1049 | if (!json_object || | |||
1050 | json_object->GetType() != lldb::eStructuredDataTypeDictionary) | |||
1051 | return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); | |||
1052 | ||||
1053 | auto json_dict = json_object->GetAsDictionary(); | |||
1054 | ||||
1055 | json_dict->GetValueForKeyAsInteger("metabuffersize", metabuffersize); | |||
1056 | options.setMetaDataBufferSize(metabuffersize); | |||
1057 | ||||
1058 | json_dict->GetValueForKeyAsInteger("buffersize", buffersize); | |||
1059 | options.setTraceBufferSize(buffersize); | |||
1060 | ||||
1061 | json_dict->GetValueForKeyAsInteger("type", type); | |||
1062 | options.setType(static_cast<lldb::TraceType>(type)); | |||
1063 | ||||
1064 | json_dict->GetValueForKeyAsInteger("threadid", tid); | |||
1065 | options.setThreadID(tid); | |||
1066 | ||||
1067 | StructuredData::ObjectSP custom_params_sp = | |||
1068 | json_dict->GetValueForKey("params"); | |||
1069 | if (custom_params_sp && | |||
1070 | custom_params_sp->GetType() != lldb::eStructuredDataTypeDictionary) | |||
1071 | return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet "); | |||
1072 | ||||
1073 | options.setTraceParams( | |||
1074 | static_pointer_cast<StructuredData::Dictionary>(custom_params_sp)); | |||
1075 | ||||
1076 | if (buffersize == std::numeric_limits<uint64_t>::max() || | |||
1077 | type != lldb::TraceType::eTraceTypeProcessorTrace) { | |||
1078 | LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "Ill formed packet buffersize = {0} type = {1}", buffersize , type); } while (0) | |||
1079 | type)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "Ill formed packet buffersize = {0} type = {1}", buffersize , type); } while (0); | |||
1080 | return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet "); | |||
1081 | } | |||
1082 | ||||
1083 | Status error; | |||
1084 | lldb::user_id_t uid = LLDB_INVALID_UID(18446744073709551615UL); | |||
1085 | uid = m_debugged_process_up->StartTrace(options, error); | |||
1086 | LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "uid is {0} , error is {1}", uid, error.GetError( )); } while (0); | |||
1087 | if (error.Fail()) | |||
1088 | return SendErrorResponse(error); | |||
1089 | ||||
1090 | StreamGDBRemote response; | |||
1091 | response.Printf("%" PRIx64"l" "x", uid); | |||
1092 | return SendPacketNoLock(response.GetString()); | |||
1093 | } | |||
1094 | ||||
1095 | GDBRemoteCommunication::PacketResult | |||
1096 | GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( | |||
1097 | StringExtractorGDBRemote &packet) { | |||
1098 | // Fail if we don't have a current process. | |||
1099 | if (!m_debugged_process_up || | |||
1100 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
1101 | return SendErrorResponse(68); | |||
1102 | ||||
1103 | if (!packet.ConsumeFront("jTraceStop:")) | |||
1104 | return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); | |||
1105 | ||||
1106 | lldb::user_id_t uid = LLDB_INVALID_UID(18446744073709551615UL); | |||
1107 | lldb::tid_t tid = LLDB_INVALID_THREAD_ID0; | |||
1108 | ||||
1109 | auto json_object = StructuredData::ParseJSON(packet.Peek()); | |||
1110 | ||||
1111 | if (!json_object || | |||
1112 | json_object->GetType() != lldb::eStructuredDataTypeDictionary) | |||
1113 | return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); | |||
1114 | ||||
1115 | auto json_dict = json_object->GetAsDictionary(); | |||
1116 | ||||
1117 | if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) | |||
1118 | return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet "); | |||
1119 | ||||
1120 | json_dict->GetValueForKeyAsInteger("threadid", tid); | |||
1121 | ||||
1122 | Status error = m_debugged_process_up->StopTrace(uid, tid); | |||
1123 | ||||
1124 | if (error.Fail()) | |||
1125 | return SendErrorResponse(error); | |||
1126 | ||||
1127 | return SendOKResponse(); | |||
1128 | } | |||
1129 | ||||
1130 | GDBRemoteCommunication::PacketResult | |||
1131 | GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead( | |||
1132 | StringExtractorGDBRemote &packet) { | |||
1133 | ||||
1134 | // Fail if we don't have a current process. | |||
1135 | if (!m_debugged_process_up || | |||
1136 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
| ||||
1137 | return SendErrorResponse(68); | |||
1138 | ||||
1139 | if (!packet.ConsumeFront("jTraceConfigRead:")) | |||
1140 | return SendIllFormedResponse(packet, | |||
1141 | "jTraceConfigRead: Ill formed packet "); | |||
1142 | ||||
1143 | lldb::user_id_t uid = LLDB_INVALID_UID(18446744073709551615UL); | |||
1144 | lldb::tid_t threadid = LLDB_INVALID_THREAD_ID0; | |||
1145 | ||||
1146 | auto json_object = StructuredData::ParseJSON(packet.Peek()); | |||
1147 | ||||
1148 | if (!json_object || | |||
1149 | json_object->GetType() != lldb::eStructuredDataTypeDictionary) | |||
1150 | return SendIllFormedResponse(packet, | |||
1151 | "jTraceConfigRead: Ill formed packet "); | |||
1152 | ||||
1153 | auto json_dict = json_object->GetAsDictionary(); | |||
1154 | ||||
1155 | if (!json_dict->GetValueForKeyAsInteger("traceid", uid)) | |||
1156 | return SendIllFormedResponse(packet, | |||
1157 | "jTraceConfigRead: Ill formed packet "); | |||
1158 | ||||
1159 | json_dict->GetValueForKeyAsInteger("threadid", threadid); | |||
1160 | ||||
1161 | TraceOptions options; | |||
1162 | StreamGDBRemote response; | |||
1163 | ||||
1164 | options.setThreadID(threadid); | |||
1165 | Status error = m_debugged_process_up->GetTraceConfig(uid, options); | |||
1166 | ||||
1167 | if (error.Fail()) | |||
1168 | return SendErrorResponse(error); | |||
1169 | ||||
1170 | StreamGDBRemote escaped_response; | |||
1171 | StructuredData::Dictionary json_packet; | |||
1172 | ||||
1173 | json_packet.AddIntegerItem("type", options.getType()); | |||
1174 | json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize()); | |||
1175 | json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize()); | |||
1176 | ||||
1177 | StructuredData::DictionarySP custom_params = options.getTraceParams(); | |||
1178 | if (custom_params) | |||
1179 | json_packet.AddItem("params", custom_params); | |||
1180 | ||||
1181 | StreamString json_string; | |||
1182 | json_packet.Dump(json_string, false); | |||
1183 | escaped_response.PutEscapedBytes(json_string.GetData(), | |||
1184 | json_string.GetSize()); | |||
1185 | return SendPacketNoLock(escaped_response.GetString()); | |||
1186 | } | |||
1187 | ||||
1188 | GDBRemoteCommunication::PacketResult | |||
1189 | GDBRemoteCommunicationServerLLGS::Handle_jTraceRead( | |||
1190 | StringExtractorGDBRemote &packet) { | |||
1191 | ||||
1192 | // Fail if we don't have a current process. | |||
1193 | if (!m_debugged_process_up || | |||
1194 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
1195 | return SendErrorResponse(68); | |||
1196 | ||||
1197 | enum PacketType { MetaData, BufferData }; | |||
1198 | PacketType tracetype = MetaData; | |||
1199 | ||||
1200 | if (packet.ConsumeFront("jTraceBufferRead:")) | |||
1201 | tracetype = BufferData; | |||
1202 | else if (packet.ConsumeFront("jTraceMetaRead:")) | |||
1203 | tracetype = MetaData; | |||
1204 | else { | |||
1205 | return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); | |||
1206 | } | |||
1207 | ||||
1208 | lldb::user_id_t uid = LLDB_INVALID_UID(18446744073709551615UL); | |||
1209 | ||||
1210 | uint64_t byte_count = std::numeric_limits<uint64_t>::max(); | |||
1211 | lldb::tid_t tid = LLDB_INVALID_THREAD_ID0; | |||
1212 | uint64_t offset = std::numeric_limits<uint64_t>::max(); | |||
1213 | ||||
1214 | auto json_object = StructuredData::ParseJSON(packet.Peek()); | |||
1215 | ||||
1216 | if (!json_object || | |||
1217 | json_object->GetType() != lldb::eStructuredDataTypeDictionary) | |||
1218 | return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); | |||
1219 | ||||
1220 | auto json_dict = json_object->GetAsDictionary(); | |||
1221 | ||||
1222 | if (!json_dict->GetValueForKeyAsInteger("traceid", uid) || | |||
1223 | !json_dict->GetValueForKeyAsInteger("offset", offset) || | |||
1224 | !json_dict->GetValueForKeyAsInteger("buffersize", byte_count)) | |||
1225 | return SendIllFormedResponse(packet, "jTrace: Ill formed packet "); | |||
1226 | ||||
1227 | json_dict->GetValueForKeyAsInteger("threadid", tid); | |||
1228 | ||||
1229 | // Allocate the response buffer. | |||
1230 | std::unique_ptr<uint8_t[]> buffer (new (std::nothrow) uint8_t[byte_count]); | |||
1231 | if (!buffer) | |||
1232 | return SendErrorResponse(0x78); | |||
1233 | ||||
1234 | StreamGDBRemote response; | |||
1235 | Status error; | |||
1236 | llvm::MutableArrayRef<uint8_t> buf(buffer.get(), byte_count); | |||
1237 | ||||
1238 | if (tracetype == BufferData) | |||
1239 | error = m_debugged_process_up->GetData(uid, tid, buf, offset); | |||
1240 | else if (tracetype == MetaData) | |||
1241 | error = m_debugged_process_up->GetMetaData(uid, tid, buf, offset); | |||
1242 | ||||
1243 | if (error.Fail()) | |||
1244 | return SendErrorResponse(error); | |||
1245 | ||||
1246 | for (auto i : buf) | |||
1247 | response.PutHex8(i); | |||
1248 | ||||
1249 | StreamGDBRemote escaped_response; | |||
1250 | escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); | |||
1251 | return SendPacketNoLock(escaped_response.GetString()); | |||
1252 | } | |||
1253 | ||||
1254 | GDBRemoteCommunication::PacketResult | |||
1255 | GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo( | |||
1256 | StringExtractorGDBRemote &packet) { | |||
1257 | // Fail if we don't have a current process. | |||
1258 | if (!m_debugged_process_up || | |||
1259 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
1260 | return SendErrorResponse(68); | |||
1261 | ||||
1262 | lldb::pid_t pid = m_debugged_process_up->GetID(); | |||
1263 | ||||
1264 | if (pid == LLDB_INVALID_PROCESS_ID0) | |||
1265 | return SendErrorResponse(1); | |||
1266 | ||||
1267 | ProcessInstanceInfo proc_info; | |||
1268 | if (!Host::GetProcessInfo(pid, proc_info)) | |||
1269 | return SendErrorResponse(1); | |||
1270 | ||||
1271 | StreamString response; | |||
1272 | CreateProcessInfoResponse_DebugServerStyle(proc_info, response); | |||
1273 | return SendPacketNoLock(response.GetString()); | |||
1274 | } | |||
1275 | ||||
1276 | GDBRemoteCommunication::PacketResult | |||
1277 | GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) { | |||
1278 | // Fail if we don't have a current process. | |||
1279 | if (!m_debugged_process_up || | |||
1280 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
1281 | return SendErrorResponse(68); | |||
1282 | ||||
1283 | // Make sure we set the current thread so g and p packets return the data the | |||
1284 | // gdb will expect. | |||
1285 | lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); | |||
1286 | SetCurrentThreadID(tid); | |||
1287 | ||||
1288 | NativeThreadProtocol *thread = m_debugged_process_up->GetCurrentThread(); | |||
1289 | if (!thread) | |||
1290 | return SendErrorResponse(69); | |||
1291 | ||||
1292 | StreamString response; | |||
1293 | response.Printf("QC%" PRIx64"l" "x", thread->GetID()); | |||
1294 | ||||
1295 | return SendPacketNoLock(response.GetString()); | |||
1296 | } | |||
1297 | ||||
1298 | GDBRemoteCommunication::PacketResult | |||
1299 | GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { | |||
1300 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1301 | ||||
1302 | StopSTDIOForwarding(); | |||
1303 | ||||
1304 | if (!m_debugged_process_up) { | |||
1305 | LLDB_LOG(log, "No debugged process found.")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "No debugged process found."); } while (0); | |||
1306 | return PacketResult::Success; | |||
1307 | } | |||
1308 | ||||
1309 | Status error = m_debugged_process_up->Kill(); | |||
1310 | if (error.Fail()) | |||
1311 | LLDB_LOG(log, "Failed to kill debugged process {0}: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "Failed to kill debugged process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
1312 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "Failed to kill debugged process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
1313 | ||||
1314 | // No OK response for kill packet. | |||
1315 | // return SendOKResponse (); | |||
1316 | return PacketResult::Success; | |||
1317 | } | |||
1318 | ||||
1319 | GDBRemoteCommunication::PacketResult | |||
1320 | GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR( | |||
1321 | StringExtractorGDBRemote &packet) { | |||
1322 | packet.SetFilePos(::strlen("QSetDisableASLR:")); | |||
1323 | if (packet.GetU32(0)) | |||
1324 | m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR); | |||
1325 | else | |||
1326 | m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR); | |||
1327 | return SendOKResponse(); | |||
1328 | } | |||
1329 | ||||
1330 | GDBRemoteCommunication::PacketResult | |||
1331 | GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir( | |||
1332 | StringExtractorGDBRemote &packet) { | |||
1333 | packet.SetFilePos(::strlen("QSetWorkingDir:")); | |||
1334 | std::string path; | |||
1335 | packet.GetHexByteString(path); | |||
1336 | m_process_launch_info.SetWorkingDirectory(FileSpec{path, true}); | |||
1337 | return SendOKResponse(); | |||
1338 | } | |||
1339 | ||||
1340 | GDBRemoteCommunication::PacketResult | |||
1341 | GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir( | |||
1342 | StringExtractorGDBRemote &packet) { | |||
1343 | FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()}; | |||
1344 | if (working_dir) { | |||
1345 | StreamString response; | |||
1346 | response.PutCStringAsRawHex8(working_dir.GetCString()); | |||
1347 | return SendPacketNoLock(response.GetString()); | |||
1348 | } | |||
1349 | ||||
1350 | return SendErrorResponse(14); | |||
1351 | } | |||
1352 | ||||
1353 | GDBRemoteCommunication::PacketResult | |||
1354 | GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { | |||
1355 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
1356 | if (log) | |||
1357 | log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); | |||
1358 | ||||
1359 | // Ensure we have a native process. | |||
1360 | if (!m_debugged_process_up) { | |||
1361 | if (log) | |||
1362 | log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " | |||
1363 | "shared pointer", | |||
1364 | __FUNCTION__); | |||
1365 | return SendErrorResponse(0x36); | |||
1366 | } | |||
1367 | ||||
1368 | // Pull out the signal number. | |||
1369 | packet.SetFilePos(::strlen("C")); | |||
1370 | if (packet.GetBytesLeft() < 1) { | |||
1371 | // Shouldn't be using a C without a signal. | |||
1372 | return SendIllFormedResponse(packet, "C packet specified without signal."); | |||
1373 | } | |||
1374 | const uint32_t signo = | |||
1375 | packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); | |||
1376 | if (signo == std::numeric_limits<uint32_t>::max()) | |||
1377 | return SendIllFormedResponse(packet, "failed to parse signal number"); | |||
1378 | ||||
1379 | // Handle optional continue address. | |||
1380 | if (packet.GetBytesLeft() > 0) { | |||
1381 | // FIXME add continue at address support for $C{signo}[;{continue-address}]. | |||
1382 | if (*packet.Peek() == ';') | |||
1383 | return SendUnimplementedResponse(packet.GetStringRef().c_str()); | |||
1384 | else | |||
1385 | return SendIllFormedResponse( | |||
1386 | packet, "unexpected content after $C{signal-number}"); | |||
1387 | } | |||
1388 | ||||
1389 | ResumeActionList resume_actions(StateType::eStateRunning, 0); | |||
1390 | Status error; | |||
1391 | ||||
1392 | // We have two branches: what to do if a continue thread is specified (in | |||
1393 | // which case we target sending the signal to that thread), or when we don't | |||
1394 | // have a continue thread set (in which case we send a signal to the | |||
1395 | // process). | |||
1396 | ||||
1397 | // TODO discuss with Greg Clayton, make sure this makes sense. | |||
1398 | ||||
1399 | lldb::tid_t signal_tid = GetContinueThreadID(); | |||
1400 | if (signal_tid != LLDB_INVALID_THREAD_ID0) { | |||
1401 | // The resume action for the continue thread (or all threads if a continue | |||
1402 | // thread is not set). | |||
1403 | ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning, | |||
1404 | static_cast<int>(signo)}; | |||
1405 | ||||
1406 | // Add the action for the continue thread (or all threads when the continue | |||
1407 | // thread isn't present). | |||
1408 | resume_actions.Append(action); | |||
1409 | } else { | |||
1410 | // Send the signal to the process since we weren't targeting a specific | |||
1411 | // continue thread with the signal. | |||
1412 | error = m_debugged_process_up->Signal(signo); | |||
1413 | if (error.Fail()) { | |||
1414 | LLDB_LOG(log, "failed to send signal for process {0}: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to send signal for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
1415 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to send signal for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
1416 | ||||
1417 | return SendErrorResponse(0x52); | |||
1418 | } | |||
1419 | } | |||
1420 | ||||
1421 | // Resume the threads. | |||
1422 | error = m_debugged_process_up->Resume(resume_actions); | |||
1423 | if (error.Fail()) { | |||
1424 | LLDB_LOG(log, "failed to resume threads for process {0}: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to resume threads for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
1425 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to resume threads for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
1426 | ||||
1427 | return SendErrorResponse(0x38); | |||
1428 | } | |||
1429 | ||||
1430 | // Don't send an "OK" packet; response is the stopped/exited message. | |||
1431 | return PacketResult::Success; | |||
1432 | } | |||
1433 | ||||
1434 | GDBRemoteCommunication::PacketResult | |||
1435 | GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { | |||
1436 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
1437 | if (log) | |||
1438 | log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); | |||
1439 | ||||
1440 | packet.SetFilePos(packet.GetFilePos() + ::strlen("c")); | |||
1441 | ||||
1442 | // For now just support all continue. | |||
1443 | const bool has_continue_address = (packet.GetBytesLeft() > 0); | |||
1444 | if (has_continue_address) { | |||
1445 | LLDB_LOG(log, "not implemented for c[address] variant [{0} remains]",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "not implemented for c[address] variant [{0} remains]" , packet.Peek()); } while (0) | |||
1446 | packet.Peek())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "not implemented for c[address] variant [{0} remains]" , packet.Peek()); } while (0); | |||
1447 | return SendUnimplementedResponse(packet.GetStringRef().c_str()); | |||
1448 | } | |||
1449 | ||||
1450 | // Ensure we have a native process. | |||
1451 | if (!m_debugged_process_up) { | |||
1452 | if (log) | |||
1453 | log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process " | |||
1454 | "shared pointer", | |||
1455 | __FUNCTION__); | |||
1456 | return SendErrorResponse(0x36); | |||
1457 | } | |||
1458 | ||||
1459 | // Build the ResumeActionList | |||
1460 | ResumeActionList actions(StateType::eStateRunning, 0); | |||
1461 | ||||
1462 | Status error = m_debugged_process_up->Resume(actions); | |||
1463 | if (error.Fail()) { | |||
1464 | LLDB_LOG(log, "c failed for process {0}: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "c failed for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
1465 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "c failed for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
1466 | return SendErrorResponse(GDBRemoteServerError::eErrorResume); | |||
1467 | } | |||
1468 | ||||
1469 | LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "continued process {0}", m_debugged_process_up-> GetID()); } while (0); | |||
1470 | // No response required from continue. | |||
1471 | return PacketResult::Success; | |||
1472 | } | |||
1473 | ||||
1474 | GDBRemoteCommunication::PacketResult | |||
1475 | GDBRemoteCommunicationServerLLGS::Handle_vCont_actions( | |||
1476 | StringExtractorGDBRemote &packet) { | |||
1477 | StreamString response; | |||
1478 | response.Printf("vCont;c;C;s;S"); | |||
1479 | ||||
1480 | return SendPacketNoLock(response.GetString()); | |||
1481 | } | |||
1482 | ||||
1483 | GDBRemoteCommunication::PacketResult | |||
1484 | GDBRemoteCommunicationServerLLGS::Handle_vCont( | |||
1485 | StringExtractorGDBRemote &packet) { | |||
1486 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1487 | if (log) | |||
1488 | log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", | |||
1489 | __FUNCTION__); | |||
1490 | ||||
1491 | packet.SetFilePos(::strlen("vCont")); | |||
1492 | ||||
1493 | if (packet.GetBytesLeft() == 0) { | |||
1494 | if (log) | |||
1495 | log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from " | |||
1496 | "vCont package", | |||
1497 | __FUNCTION__); | |||
1498 | return SendIllFormedResponse(packet, "Missing action from vCont package"); | |||
1499 | } | |||
1500 | ||||
1501 | // Check if this is all continue (no options or ";c"). | |||
1502 | if (::strcmp(packet.Peek(), ";c") == 0) { | |||
1503 | // Move past the ';', then do a simple 'c'. | |||
1504 | packet.SetFilePos(packet.GetFilePos() + 1); | |||
1505 | return Handle_c(packet); | |||
1506 | } else if (::strcmp(packet.Peek(), ";s") == 0) { | |||
1507 | // Move past the ';', then do a simple 's'. | |||
1508 | packet.SetFilePos(packet.GetFilePos() + 1); | |||
1509 | return Handle_s(packet); | |||
1510 | } | |||
1511 | ||||
1512 | // Ensure we have a native process. | |||
1513 | if (!m_debugged_process_up) { | |||
1514 | LLDB_LOG(log, "no debugged process")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "no debugged process"); } while (0); | |||
1515 | return SendErrorResponse(0x36); | |||
1516 | } | |||
1517 | ||||
1518 | ResumeActionList thread_actions; | |||
1519 | ||||
1520 | while (packet.GetBytesLeft() && *packet.Peek() == ';') { | |||
1521 | // Skip the semi-colon. | |||
1522 | packet.GetChar(); | |||
1523 | ||||
1524 | // Build up the thread action. | |||
1525 | ResumeAction thread_action; | |||
1526 | thread_action.tid = LLDB_INVALID_THREAD_ID0; | |||
1527 | thread_action.state = eStateInvalid; | |||
1528 | thread_action.signal = 0; | |||
1529 | ||||
1530 | const char action = packet.GetChar(); | |||
1531 | switch (action) { | |||
1532 | case 'C': | |||
1533 | thread_action.signal = packet.GetHexMaxU32(false, 0); | |||
1534 | if (thread_action.signal == 0) | |||
1535 | return SendIllFormedResponse( | |||
1536 | packet, "Could not parse signal in vCont packet C action"); | |||
1537 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
1538 | ||||
1539 | case 'c': | |||
1540 | // Continue | |||
1541 | thread_action.state = eStateRunning; | |||
1542 | break; | |||
1543 | ||||
1544 | case 'S': | |||
1545 | thread_action.signal = packet.GetHexMaxU32(false, 0); | |||
1546 | if (thread_action.signal == 0) | |||
1547 | return SendIllFormedResponse( | |||
1548 | packet, "Could not parse signal in vCont packet S action"); | |||
1549 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
1550 | ||||
1551 | case 's': | |||
1552 | // Step | |||
1553 | thread_action.state = eStateStepping; | |||
1554 | break; | |||
1555 | ||||
1556 | default: | |||
1557 | return SendIllFormedResponse(packet, "Unsupported vCont action"); | |||
1558 | break; | |||
1559 | } | |||
1560 | ||||
1561 | // Parse out optional :{thread-id} value. | |||
1562 | if (packet.GetBytesLeft() && (*packet.Peek() == ':')) { | |||
1563 | // Consume the separator. | |||
1564 | packet.GetChar(); | |||
1565 | ||||
1566 | thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID0); | |||
1567 | if (thread_action.tid == LLDB_INVALID_THREAD_ID0) | |||
1568 | return SendIllFormedResponse( | |||
1569 | packet, "Could not parse thread number in vCont packet"); | |||
1570 | } | |||
1571 | ||||
1572 | thread_actions.Append(thread_action); | |||
1573 | } | |||
1574 | ||||
1575 | Status error = m_debugged_process_up->Resume(thread_actions); | |||
1576 | if (error.Fail()) { | |||
1577 | LLDB_LOG(log, "vCont failed for process {0}: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "vCont failed for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
1578 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "vCont failed for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
1579 | return SendErrorResponse(GDBRemoteServerError::eErrorResume); | |||
1580 | } | |||
1581 | ||||
1582 | LLDB_LOG(log, "continued process {0}", m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "continued process {0}", m_debugged_process_up-> GetID()); } while (0); | |||
1583 | // No response required from vCont. | |||
1584 | return PacketResult::Success; | |||
1585 | } | |||
1586 | ||||
1587 | void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) { | |||
1588 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
1589 | LLDB_LOG(log, "setting current thread id to {0}", tid)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "setting current thread id to {0}", tid); } while (0); | |||
1590 | ||||
1591 | m_current_tid = tid; | |||
1592 | if (m_debugged_process_up) | |||
1593 | m_debugged_process_up->SetCurrentThreadID(m_current_tid); | |||
1594 | } | |||
1595 | ||||
1596 | void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) { | |||
1597 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
1598 | LLDB_LOG(log, "setting continue thread id to {0}", tid)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "setting continue thread id to {0}", tid); } while (0); | |||
1599 | ||||
1600 | m_continue_tid = tid; | |||
1601 | } | |||
1602 | ||||
1603 | GDBRemoteCommunication::PacketResult | |||
1604 | GDBRemoteCommunicationServerLLGS::Handle_stop_reason( | |||
1605 | StringExtractorGDBRemote &packet) { | |||
1606 | // Handle the $? gdbremote command. | |||
1607 | ||||
1608 | // If no process, indicate error | |||
1609 | if (!m_debugged_process_up) | |||
1610 | return SendErrorResponse(02); | |||
1611 | ||||
1612 | return SendStopReasonForState(m_debugged_process_up->GetState()); | |||
1613 | } | |||
1614 | ||||
1615 | GDBRemoteCommunication::PacketResult | |||
1616 | GDBRemoteCommunicationServerLLGS::SendStopReasonForState( | |||
1617 | lldb::StateType process_state) { | |||
1618 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
1619 | ||||
1620 | switch (process_state) { | |||
1621 | case eStateAttaching: | |||
1622 | case eStateLaunching: | |||
1623 | case eStateRunning: | |||
1624 | case eStateStepping: | |||
1625 | case eStateDetached: | |||
1626 | // NOTE: gdb protocol doc looks like it should return $OK | |||
1627 | // when everything is running (i.e. no stopped result). | |||
1628 | return PacketResult::Success; // Ignore | |||
1629 | ||||
1630 | case eStateSuspended: | |||
1631 | case eStateStopped: | |||
1632 | case eStateCrashed: { | |||
1633 | lldb::tid_t tid = m_debugged_process_up->GetCurrentThreadID(); | |||
1634 | // Make sure we set the current thread so g and p packets return the data | |||
1635 | // the gdb will expect. | |||
1636 | SetCurrentThreadID(tid); | |||
1637 | return SendStopReplyPacketForThread(tid); | |||
1638 | } | |||
1639 | ||||
1640 | case eStateInvalid: | |||
1641 | case eStateUnloaded: | |||
1642 | case eStateExited: | |||
1643 | return SendWResponse(m_debugged_process_up.get()); | |||
1644 | ||||
1645 | default: | |||
1646 | LLDB_LOG(log, "pid {0}, current state reporting not handled: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, current state reporting not handled: {1}" , m_debugged_process_up->GetID(), process_state); } while ( 0) | |||
1647 | m_debugged_process_up->GetID(), process_state)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0}, current state reporting not handled: {1}" , m_debugged_process_up->GetID(), process_state); } while ( 0); | |||
1648 | break; | |||
1649 | } | |||
1650 | ||||
1651 | return SendErrorResponse(0); | |||
1652 | } | |||
1653 | ||||
1654 | GDBRemoteCommunication::PacketResult | |||
1655 | GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( | |||
1656 | StringExtractorGDBRemote &packet) { | |||
1657 | // Fail if we don't have a current process. | |||
1658 | if (!m_debugged_process_up || | |||
1659 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
1660 | return SendErrorResponse(68); | |||
1661 | ||||
1662 | // Ensure we have a thread. | |||
1663 | NativeThreadProtocol *thread = m_debugged_process_up->GetThreadAtIndex(0); | |||
1664 | if (!thread) | |||
1665 | return SendErrorResponse(69); | |||
1666 | ||||
1667 | // Get the register context for the first thread. | |||
1668 | NativeRegisterContext ®_context = thread->GetRegisterContext(); | |||
1669 | ||||
1670 | // Parse out the register number from the request. | |||
1671 | packet.SetFilePos(strlen("qRegisterInfo")); | |||
1672 | const uint32_t reg_index = | |||
1673 | packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); | |||
1674 | if (reg_index == std::numeric_limits<uint32_t>::max()) | |||
1675 | return SendErrorResponse(69); | |||
1676 | ||||
1677 | // Return the end of registers response if we've iterated one past the end of | |||
1678 | // the register set. | |||
1679 | if (reg_index >= reg_context.GetUserRegisterCount()) | |||
1680 | return SendErrorResponse(69); | |||
1681 | ||||
1682 | const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); | |||
1683 | if (!reg_info) | |||
1684 | return SendErrorResponse(69); | |||
1685 | ||||
1686 | // Build the reginfos response. | |||
1687 | StreamGDBRemote response; | |||
1688 | ||||
1689 | response.PutCString("name:"); | |||
1690 | response.PutCString(reg_info->name); | |||
1691 | response.PutChar(';'); | |||
1692 | ||||
1693 | if (reg_info->alt_name && reg_info->alt_name[0]) { | |||
1694 | response.PutCString("alt-name:"); | |||
1695 | response.PutCString(reg_info->alt_name); | |||
1696 | response.PutChar(';'); | |||
1697 | } | |||
1698 | ||||
1699 | response.Printf("bitsize:%" PRIu32"u" ";offset:%" PRIu32"u" ";", | |||
1700 | reg_info->byte_size * 8, reg_info->byte_offset); | |||
1701 | ||||
1702 | switch (reg_info->encoding) { | |||
1703 | case eEncodingUint: | |||
1704 | response.PutCString("encoding:uint;"); | |||
1705 | break; | |||
1706 | case eEncodingSint: | |||
1707 | response.PutCString("encoding:sint;"); | |||
1708 | break; | |||
1709 | case eEncodingIEEE754: | |||
1710 | response.PutCString("encoding:ieee754;"); | |||
1711 | break; | |||
1712 | case eEncodingVector: | |||
1713 | response.PutCString("encoding:vector;"); | |||
1714 | break; | |||
1715 | default: | |||
1716 | break; | |||
1717 | } | |||
1718 | ||||
1719 | switch (reg_info->format) { | |||
1720 | case eFormatBinary: | |||
1721 | response.PutCString("format:binary;"); | |||
1722 | break; | |||
1723 | case eFormatDecimal: | |||
1724 | response.PutCString("format:decimal;"); | |||
1725 | break; | |||
1726 | case eFormatHex: | |||
1727 | response.PutCString("format:hex;"); | |||
1728 | break; | |||
1729 | case eFormatFloat: | |||
1730 | response.PutCString("format:float;"); | |||
1731 | break; | |||
1732 | case eFormatVectorOfSInt8: | |||
1733 | response.PutCString("format:vector-sint8;"); | |||
1734 | break; | |||
1735 | case eFormatVectorOfUInt8: | |||
1736 | response.PutCString("format:vector-uint8;"); | |||
1737 | break; | |||
1738 | case eFormatVectorOfSInt16: | |||
1739 | response.PutCString("format:vector-sint16;"); | |||
1740 | break; | |||
1741 | case eFormatVectorOfUInt16: | |||
1742 | response.PutCString("format:vector-uint16;"); | |||
1743 | break; | |||
1744 | case eFormatVectorOfSInt32: | |||
1745 | response.PutCString("format:vector-sint32;"); | |||
1746 | break; | |||
1747 | case eFormatVectorOfUInt32: | |||
1748 | response.PutCString("format:vector-uint32;"); | |||
1749 | break; | |||
1750 | case eFormatVectorOfFloat32: | |||
1751 | response.PutCString("format:vector-float32;"); | |||
1752 | break; | |||
1753 | case eFormatVectorOfUInt64: | |||
1754 | response.PutCString("format:vector-uint64;"); | |||
1755 | break; | |||
1756 | case eFormatVectorOfUInt128: | |||
1757 | response.PutCString("format:vector-uint128;"); | |||
1758 | break; | |||
1759 | default: | |||
1760 | break; | |||
1761 | }; | |||
1762 | ||||
1763 | const char *const register_set_name = | |||
1764 | reg_context.GetRegisterSetNameForRegisterAtIndex(reg_index); | |||
1765 | if (register_set_name) { | |||
1766 | response.PutCString("set:"); | |||
1767 | response.PutCString(register_set_name); | |||
1768 | response.PutChar(';'); | |||
1769 | } | |||
1770 | ||||
1771 | if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != | |||
1772 | LLDB_INVALID_REGNUM(4294967295U)) | |||
1773 | response.Printf("ehframe:%" PRIu32"u" ";", | |||
1774 | reg_info->kinds[RegisterKind::eRegisterKindEHFrame]); | |||
1775 | ||||
1776 | if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM(4294967295U)) | |||
1777 | response.Printf("dwarf:%" PRIu32"u" ";", | |||
1778 | reg_info->kinds[RegisterKind::eRegisterKindDWARF]); | |||
1779 | ||||
1780 | switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric]) { | |||
1781 | case LLDB_REGNUM_GENERIC_PC0: | |||
1782 | response.PutCString("generic:pc;"); | |||
1783 | break; | |||
1784 | case LLDB_REGNUM_GENERIC_SP1: | |||
1785 | response.PutCString("generic:sp;"); | |||
1786 | break; | |||
1787 | case LLDB_REGNUM_GENERIC_FP2: | |||
1788 | response.PutCString("generic:fp;"); | |||
1789 | break; | |||
1790 | case LLDB_REGNUM_GENERIC_RA3: | |||
1791 | response.PutCString("generic:ra;"); | |||
1792 | break; | |||
1793 | case LLDB_REGNUM_GENERIC_FLAGS4: | |||
1794 | response.PutCString("generic:flags;"); | |||
1795 | break; | |||
1796 | case LLDB_REGNUM_GENERIC_ARG15: | |||
1797 | response.PutCString("generic:arg1;"); | |||
1798 | break; | |||
1799 | case LLDB_REGNUM_GENERIC_ARG26: | |||
1800 | response.PutCString("generic:arg2;"); | |||
1801 | break; | |||
1802 | case LLDB_REGNUM_GENERIC_ARG37: | |||
1803 | response.PutCString("generic:arg3;"); | |||
1804 | break; | |||
1805 | case LLDB_REGNUM_GENERIC_ARG48: | |||
1806 | response.PutCString("generic:arg4;"); | |||
1807 | break; | |||
1808 | case LLDB_REGNUM_GENERIC_ARG59: | |||
1809 | response.PutCString("generic:arg5;"); | |||
1810 | break; | |||
1811 | case LLDB_REGNUM_GENERIC_ARG610: | |||
1812 | response.PutCString("generic:arg6;"); | |||
1813 | break; | |||
1814 | case LLDB_REGNUM_GENERIC_ARG711: | |||
1815 | response.PutCString("generic:arg7;"); | |||
1816 | break; | |||
1817 | case LLDB_REGNUM_GENERIC_ARG812: | |||
1818 | response.PutCString("generic:arg8;"); | |||
1819 | break; | |||
1820 | default: | |||
1821 | break; | |||
1822 | } | |||
1823 | ||||
1824 | if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM(4294967295U)) { | |||
1825 | response.PutCString("container-regs:"); | |||
1826 | int i = 0; | |||
1827 | for (const uint32_t *reg_num = reg_info->value_regs; | |||
1828 | *reg_num != LLDB_INVALID_REGNUM(4294967295U); ++reg_num, ++i) { | |||
1829 | if (i > 0) | |||
1830 | response.PutChar(','); | |||
1831 | response.Printf("%" PRIx32"x", *reg_num); | |||
1832 | } | |||
1833 | response.PutChar(';'); | |||
1834 | } | |||
1835 | ||||
1836 | if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) { | |||
1837 | response.PutCString("invalidate-regs:"); | |||
1838 | int i = 0; | |||
1839 | for (const uint32_t *reg_num = reg_info->invalidate_regs; | |||
1840 | *reg_num != LLDB_INVALID_REGNUM(4294967295U); ++reg_num, ++i) { | |||
1841 | if (i > 0) | |||
1842 | response.PutChar(','); | |||
1843 | response.Printf("%" PRIx32"x", *reg_num); | |||
1844 | } | |||
1845 | response.PutChar(';'); | |||
1846 | } | |||
1847 | ||||
1848 | if (reg_info->dynamic_size_dwarf_expr_bytes) { | |||
1849 | const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len; | |||
1850 | response.PutCString("dynamic_size_dwarf_expr_bytes:"); | |||
1851 | for (uint32_t i = 0; i < dwarf_opcode_len; ++i) | |||
1852 | response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]); | |||
1853 | response.PutChar(';'); | |||
1854 | } | |||
1855 | return SendPacketNoLock(response.GetString()); | |||
1856 | } | |||
1857 | ||||
1858 | GDBRemoteCommunication::PacketResult | |||
1859 | GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( | |||
1860 | StringExtractorGDBRemote &packet) { | |||
1861 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
1862 | ||||
1863 | // Fail if we don't have a current process. | |||
1864 | if (!m_debugged_process_up || | |||
1865 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
1866 | LLDB_LOG(log, "no process ({0}), returning OK",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "no process ({0}), returning OK", m_debugged_process_up ? "invalid process id" : "null m_debugged_process_up"); } while (0) | |||
1867 | m_debugged_process_up ? "invalid process id"do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "no process ({0}), returning OK", m_debugged_process_up ? "invalid process id" : "null m_debugged_process_up"); } while (0) | |||
1868 | : "null m_debugged_process_up")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "no process ({0}), returning OK", m_debugged_process_up ? "invalid process id" : "null m_debugged_process_up"); } while (0); | |||
1869 | return SendOKResponse(); | |||
1870 | } | |||
1871 | ||||
1872 | StreamGDBRemote response; | |||
1873 | response.PutChar('m'); | |||
1874 | ||||
1875 | LLDB_LOG(log, "starting thread iteration")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "starting thread iteration"); } while (0); | |||
1876 | NativeThreadProtocol *thread; | |||
1877 | uint32_t thread_index; | |||
1878 | for (thread_index = 0, | |||
1879 | thread = m_debugged_process_up->GetThreadAtIndex(thread_index); | |||
1880 | thread; ++thread_index, | |||
1881 | thread = m_debugged_process_up->GetThreadAtIndex(thread_index)) { | |||
1882 | LLDB_LOG(log, "iterated thread {0}(tid={2})", thread_index,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "iterated thread {0}(tid={2})", thread_index, thread ->GetID()); } while (0) | |||
1883 | thread->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "iterated thread {0}(tid={2})", thread_index, thread ->GetID()); } while (0); | |||
1884 | if (thread_index > 0) | |||
1885 | response.PutChar(','); | |||
1886 | response.Printf("%" PRIx64"l" "x", thread->GetID()); | |||
1887 | } | |||
1888 | ||||
1889 | LLDB_LOG(log, "finished thread iteration")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "finished thread iteration"); } while (0); | |||
1890 | return SendPacketNoLock(response.GetString()); | |||
1891 | } | |||
1892 | ||||
1893 | GDBRemoteCommunication::PacketResult | |||
1894 | GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo( | |||
1895 | StringExtractorGDBRemote &packet) { | |||
1896 | // FIXME for now we return the full thread list in the initial packet and | |||
1897 | // always do nothing here. | |||
1898 | return SendPacketNoLock("l"); | |||
1899 | } | |||
1900 | ||||
1901 | GDBRemoteCommunication::PacketResult | |||
1902 | GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) { | |||
1903 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
1904 | ||||
1905 | // Parse out the register number from the request. | |||
1906 | packet.SetFilePos(strlen("p")); | |||
1907 | const uint32_t reg_index = | |||
1908 | packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); | |||
1909 | if (reg_index == std::numeric_limits<uint32_t>::max()) { | |||
1910 | if (log) | |||
1911 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " | |||
1912 | "parse register number from request \"%s\"", | |||
1913 | __FUNCTION__, packet.GetStringRef().c_str()); | |||
1914 | return SendErrorResponse(0x15); | |||
1915 | } | |||
1916 | ||||
1917 | // Get the thread to use. | |||
1918 | NativeThreadProtocol *thread = GetThreadFromSuffix(packet); | |||
1919 | if (!thread) { | |||
1920 | LLDB_LOG(log, "failed, no thread available")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed, no thread available"); } while (0); | |||
1921 | return SendErrorResponse(0x15); | |||
1922 | } | |||
1923 | ||||
1924 | // Get the thread's register context. | |||
1925 | NativeRegisterContext ®_context = thread->GetRegisterContext(); | |||
1926 | ||||
1927 | // Return the end of registers response if we've iterated one past the end of | |||
1928 | // the register set. | |||
1929 | if (reg_index >= reg_context.GetUserRegisterCount()) { | |||
1930 | if (log) | |||
1931 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " | |||
1932 | "register %" PRIu32"u" " beyond register count %" PRIu32"u", | |||
1933 | __FUNCTION__, reg_index, | |||
1934 | reg_context.GetUserRegisterCount()); | |||
1935 | return SendErrorResponse(0x15); | |||
1936 | } | |||
1937 | ||||
1938 | const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); | |||
1939 | if (!reg_info) { | |||
1940 | if (log) | |||
1941 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " | |||
1942 | "register %" PRIu32"u" " returned NULL", | |||
1943 | __FUNCTION__, reg_index); | |||
1944 | return SendErrorResponse(0x15); | |||
1945 | } | |||
1946 | ||||
1947 | // Build the reginfos response. | |||
1948 | StreamGDBRemote response; | |||
1949 | ||||
1950 | // Retrieve the value | |||
1951 | RegisterValue reg_value; | |||
1952 | Status error = reg_context.ReadRegister(reg_info, reg_value); | |||
1953 | if (error.Fail()) { | |||
1954 | if (log) | |||
1955 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of " | |||
1956 | "requested register %" PRIu32"u" " (%s) failed: %s", | |||
1957 | __FUNCTION__, reg_index, reg_info->name, error.AsCString()); | |||
1958 | return SendErrorResponse(0x15); | |||
1959 | } | |||
1960 | ||||
1961 | const uint8_t *const data = | |||
1962 | reinterpret_cast<const uint8_t *>(reg_value.GetBytes()); | |||
1963 | if (!data) { | |||
1964 | if (log) | |||
1965 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data " | |||
1966 | "bytes from requested register %" PRIu32"u", | |||
1967 | __FUNCTION__, reg_index); | |||
1968 | return SendErrorResponse(0x15); | |||
1969 | } | |||
1970 | ||||
1971 | // FIXME flip as needed to get data in big/little endian format for this host. | |||
1972 | for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i) | |||
1973 | response.PutHex8(data[i]); | |||
1974 | ||||
1975 | return SendPacketNoLock(response.GetString()); | |||
1976 | } | |||
1977 | ||||
1978 | GDBRemoteCommunication::PacketResult | |||
1979 | GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) { | |||
1980 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
1981 | ||||
1982 | // Ensure there is more content. | |||
1983 | if (packet.GetBytesLeft() < 1) | |||
1984 | return SendIllFormedResponse(packet, "Empty P packet"); | |||
1985 | ||||
1986 | // Parse out the register number from the request. | |||
1987 | packet.SetFilePos(strlen("P")); | |||
1988 | const uint32_t reg_index = | |||
1989 | packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); | |||
1990 | if (reg_index == std::numeric_limits<uint32_t>::max()) { | |||
1991 | if (log) | |||
1992 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " | |||
1993 | "parse register number from request \"%s\"", | |||
1994 | __FUNCTION__, packet.GetStringRef().c_str()); | |||
1995 | return SendErrorResponse(0x29); | |||
1996 | } | |||
1997 | ||||
1998 | // Note debugserver would send an E30 here. | |||
1999 | if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '=')) | |||
2000 | return SendIllFormedResponse( | |||
2001 | packet, "P packet missing '=' char after register number"); | |||
2002 | ||||
2003 | // Parse out the value. | |||
2004 | uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register | |||
2005 | size_t reg_size = packet.GetHexBytesAvail(reg_bytes); | |||
2006 | ||||
2007 | // Get the thread to use. | |||
2008 | NativeThreadProtocol *thread = GetThreadFromSuffix(packet); | |||
2009 | if (!thread) { | |||
2010 | if (log) | |||
2011 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread " | |||
2012 | "available (thread index 0)", | |||
2013 | __FUNCTION__); | |||
2014 | return SendErrorResponse(0x28); | |||
2015 | } | |||
2016 | ||||
2017 | // Get the thread's register context. | |||
2018 | NativeRegisterContext ®_context = thread->GetRegisterContext(); | |||
2019 | const RegisterInfo *reg_info = reg_context.GetRegisterInfoAtIndex(reg_index); | |||
2020 | if (!reg_info) { | |||
2021 | if (log) | |||
2022 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " | |||
2023 | "register %" PRIu32"u" " returned NULL", | |||
2024 | __FUNCTION__, reg_index); | |||
2025 | return SendErrorResponse(0x48); | |||
2026 | } | |||
2027 | ||||
2028 | // Return the end of registers response if we've iterated one past the end of | |||
2029 | // the register set. | |||
2030 | if (reg_index >= reg_context.GetUserRegisterCount()) { | |||
2031 | if (log) | |||
2032 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested " | |||
2033 | "register %" PRIu32"u" " beyond register count %" PRIu32"u", | |||
2034 | __FUNCTION__, reg_index, reg_context.GetUserRegisterCount()); | |||
2035 | return SendErrorResponse(0x47); | |||
2036 | } | |||
2037 | ||||
2038 | // The dwarf expression are evaluate on host site which may cause register | |||
2039 | // size to change Hence the reg_size may not be same as reg_info->bytes_size | |||
2040 | if ((reg_size != reg_info->byte_size) && | |||
2041 | !(reg_info->dynamic_size_dwarf_expr_bytes)) { | |||
2042 | return SendIllFormedResponse(packet, "P packet register size is incorrect"); | |||
2043 | } | |||
2044 | ||||
2045 | // Build the reginfos response. | |||
2046 | StreamGDBRemote response; | |||
2047 | ||||
2048 | RegisterValue reg_value( | |||
2049 | reg_bytes, reg_size, | |||
2050 | m_debugged_process_up->GetArchitecture().GetByteOrder()); | |||
2051 | Status error = reg_context.WriteRegister(reg_info, reg_value); | |||
2052 | if (error.Fail()) { | |||
2053 | if (log) | |||
2054 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of " | |||
2055 | "requested register %" PRIu32"u" " (%s) failed: %s", | |||
2056 | __FUNCTION__, reg_index, reg_info->name, error.AsCString()); | |||
2057 | return SendErrorResponse(0x32); | |||
2058 | } | |||
2059 | ||||
2060 | return SendOKResponse(); | |||
2061 | } | |||
2062 | ||||
2063 | GDBRemoteCommunication::PacketResult | |||
2064 | GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { | |||
2065 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
2066 | ||||
2067 | // Fail if we don't have a current process. | |||
2068 | if (!m_debugged_process_up || | |||
2069 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2070 | if (log) | |||
2071 | log->Printf( | |||
2072 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2073 | __FUNCTION__); | |||
2074 | return SendErrorResponse(0x15); | |||
2075 | } | |||
2076 | ||||
2077 | // Parse out which variant of $H is requested. | |||
2078 | packet.SetFilePos(strlen("H")); | |||
2079 | if (packet.GetBytesLeft() < 1) { | |||
2080 | if (log) | |||
2081 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command " | |||
2082 | "missing {g,c} variant", | |||
2083 | __FUNCTION__); | |||
2084 | return SendIllFormedResponse(packet, "H command missing {g,c} variant"); | |||
2085 | } | |||
2086 | ||||
2087 | const char h_variant = packet.GetChar(); | |||
2088 | switch (h_variant) { | |||
2089 | case 'g': | |||
2090 | break; | |||
2091 | ||||
2092 | case 'c': | |||
2093 | break; | |||
2094 | ||||
2095 | default: | |||
2096 | if (log) | |||
2097 | log->Printf( | |||
2098 | "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", | |||
2099 | __FUNCTION__, h_variant); | |||
2100 | return SendIllFormedResponse(packet, | |||
2101 | "H variant unsupported, should be c or g"); | |||
2102 | } | |||
2103 | ||||
2104 | // Parse out the thread number. | |||
2105 | // FIXME return a parse success/fail value. All values are valid here. | |||
2106 | const lldb::tid_t tid = | |||
2107 | packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max()); | |||
2108 | ||||
2109 | // Ensure we have the given thread when not specifying -1 (all threads) or 0 | |||
2110 | // (any thread). | |||
2111 | if (tid != LLDB_INVALID_THREAD_ID0 && tid != 0) { | |||
2112 | NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); | |||
2113 | if (!thread) { | |||
2114 | if (log) | |||
2115 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64"l" "u" | |||
2116 | " not found", | |||
2117 | __FUNCTION__, tid); | |||
2118 | return SendErrorResponse(0x15); | |||
2119 | } | |||
2120 | } | |||
2121 | ||||
2122 | // Now switch the given thread type. | |||
2123 | switch (h_variant) { | |||
2124 | case 'g': | |||
2125 | SetCurrentThreadID(tid); | |||
2126 | break; | |||
2127 | ||||
2128 | case 'c': | |||
2129 | SetContinueThreadID(tid); | |||
2130 | break; | |||
2131 | ||||
2132 | default: | |||
2133 | assert(false && "unsupported $H variant - shouldn't get here")((false && "unsupported $H variant - shouldn't get here" ) ? static_cast<void> (0) : __assert_fail ("false && \"unsupported $H variant - shouldn't get here\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 2133, __PRETTY_FUNCTION__)); | |||
2134 | return SendIllFormedResponse(packet, | |||
2135 | "H variant unsupported, should be c or g"); | |||
2136 | } | |||
2137 | ||||
2138 | return SendOKResponse(); | |||
2139 | } | |||
2140 | ||||
2141 | GDBRemoteCommunication::PacketResult | |||
2142 | GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) { | |||
2143 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
2144 | ||||
2145 | // Fail if we don't have a current process. | |||
2146 | if (!m_debugged_process_up || | |||
2147 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2148 | if (log) | |||
2149 | log->Printf( | |||
2150 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2151 | __FUNCTION__); | |||
2152 | return SendErrorResponse(0x15); | |||
2153 | } | |||
2154 | ||||
2155 | packet.SetFilePos(::strlen("I")); | |||
2156 | uint8_t tmp[4096]; | |||
2157 | for (;;) { | |||
2158 | size_t read = packet.GetHexBytesAvail(tmp); | |||
2159 | if (read == 0) { | |||
2160 | break; | |||
2161 | } | |||
2162 | // write directly to stdin *this might block if stdin buffer is full* | |||
2163 | // TODO: enqueue this block in circular buffer and send window size to | |||
2164 | // remote host | |||
2165 | ConnectionStatus status; | |||
2166 | Status error; | |||
2167 | m_stdio_communication.Write(tmp, read, status, &error); | |||
2168 | if (error.Fail()) { | |||
2169 | return SendErrorResponse(0x15); | |||
2170 | } | |||
2171 | } | |||
2172 | ||||
2173 | return SendOKResponse(); | |||
2174 | } | |||
2175 | ||||
2176 | GDBRemoteCommunication::PacketResult | |||
2177 | GDBRemoteCommunicationServerLLGS::Handle_interrupt( | |||
2178 | StringExtractorGDBRemote &packet) { | |||
2179 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
2180 | ||||
2181 | // Fail if we don't have a current process. | |||
2182 | if (!m_debugged_process_up || | |||
2183 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2184 | LLDB_LOG(log, "failed, no process available")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed, no process available"); } while (0); | |||
2185 | return SendErrorResponse(0x15); | |||
2186 | } | |||
2187 | ||||
2188 | // Interrupt the process. | |||
2189 | Status error = m_debugged_process_up->Interrupt(); | |||
2190 | if (error.Fail()) { | |||
2191 | LLDB_LOG(log, "failed for process {0}: {1}", m_debugged_process_up->GetID(),do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
2192 | error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed for process {0}: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
2193 | return SendErrorResponse(GDBRemoteServerError::eErrorResume); | |||
2194 | } | |||
2195 | ||||
2196 | LLDB_LOG(log, "stopped process {0}", m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "stopped process {0}", m_debugged_process_up-> GetID()); } while (0); | |||
2197 | ||||
2198 | // No response required from stop all. | |||
2199 | return PacketResult::Success; | |||
2200 | } | |||
2201 | ||||
2202 | GDBRemoteCommunication::PacketResult | |||
2203 | GDBRemoteCommunicationServerLLGS::Handle_memory_read( | |||
2204 | StringExtractorGDBRemote &packet) { | |||
2205 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2206 | ||||
2207 | if (!m_debugged_process_up || | |||
2208 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2209 | if (log) | |||
2210 | log->Printf( | |||
2211 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2212 | __FUNCTION__); | |||
2213 | return SendErrorResponse(0x15); | |||
2214 | } | |||
2215 | ||||
2216 | // Parse out the memory address. | |||
2217 | packet.SetFilePos(strlen("m")); | |||
2218 | if (packet.GetBytesLeft() < 1) | |||
2219 | return SendIllFormedResponse(packet, "Too short m packet"); | |||
2220 | ||||
2221 | // Read the address. Punting on validation. | |||
2222 | // FIXME replace with Hex U64 read with no default value that fails on failed | |||
2223 | // read. | |||
2224 | const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); | |||
2225 | ||||
2226 | // Validate comma. | |||
2227 | if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) | |||
2228 | return SendIllFormedResponse(packet, "Comma sep missing in m packet"); | |||
2229 | ||||
2230 | // Get # bytes to read. | |||
2231 | if (packet.GetBytesLeft() < 1) | |||
2232 | return SendIllFormedResponse(packet, "Length missing in m packet"); | |||
2233 | ||||
2234 | const uint64_t byte_count = packet.GetHexMaxU64(false, 0); | |||
2235 | if (byte_count == 0) { | |||
2236 | if (log) | |||
2237 | log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: " | |||
2238 | "zero-length packet", | |||
2239 | __FUNCTION__); | |||
2240 | return SendOKResponse(); | |||
2241 | } | |||
2242 | ||||
2243 | // Allocate the response buffer. | |||
2244 | std::string buf(byte_count, '\0'); | |||
2245 | if (buf.empty()) | |||
2246 | return SendErrorResponse(0x78); | |||
2247 | ||||
2248 | // Retrieve the process memory. | |||
2249 | size_t bytes_read = 0; | |||
2250 | Status error = m_debugged_process_up->ReadMemoryWithoutTrap( | |||
2251 | read_addr, &buf[0], byte_count, bytes_read); | |||
2252 | if (error.Fail()) { | |||
2253 | if (log) | |||
2254 | log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64"l" "u" | |||
2255 | " mem 0x%" PRIx64"l" "x" ": failed to read. Error: %s", | |||
2256 | __FUNCTION__, m_debugged_process_up->GetID(), read_addr, | |||
2257 | error.AsCString()); | |||
2258 | return SendErrorResponse(0x08); | |||
2259 | } | |||
2260 | ||||
2261 | if (bytes_read == 0) { | |||
2262 | if (log) | |||
2263 | log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64"l" "u" | |||
2264 | " mem 0x%" PRIx64"l" "x" ": read 0 of %" PRIu64"l" "u" " requested bytes", | |||
2265 | __FUNCTION__, m_debugged_process_up->GetID(), read_addr, | |||
2266 | byte_count); | |||
2267 | return SendErrorResponse(0x08); | |||
2268 | } | |||
2269 | ||||
2270 | StreamGDBRemote response; | |||
2271 | packet.SetFilePos(0); | |||
2272 | char kind = packet.GetChar('?'); | |||
2273 | if (kind == 'x') | |||
2274 | response.PutEscapedBytes(buf.data(), byte_count); | |||
2275 | else { | |||
2276 | assert(kind == 'm')((kind == 'm') ? static_cast<void> (0) : __assert_fail ( "kind == 'm'", "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 2276, __PRETTY_FUNCTION__)); | |||
2277 | for (size_t i = 0; i < bytes_read; ++i) | |||
2278 | response.PutHex8(buf[i]); | |||
2279 | } | |||
2280 | ||||
2281 | return SendPacketNoLock(response.GetString()); | |||
2282 | } | |||
2283 | ||||
2284 | GDBRemoteCommunication::PacketResult | |||
2285 | GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) { | |||
2286 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2287 | ||||
2288 | if (!m_debugged_process_up || | |||
2289 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2290 | if (log) | |||
2291 | log->Printf( | |||
2292 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2293 | __FUNCTION__); | |||
2294 | return SendErrorResponse(0x15); | |||
2295 | } | |||
2296 | ||||
2297 | // Parse out the memory address. | |||
2298 | packet.SetFilePos(strlen("M")); | |||
2299 | if (packet.GetBytesLeft() < 1) | |||
2300 | return SendIllFormedResponse(packet, "Too short M packet"); | |||
2301 | ||||
2302 | // Read the address. Punting on validation. | |||
2303 | // FIXME replace with Hex U64 read with no default value that fails on failed | |||
2304 | // read. | |||
2305 | const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0); | |||
2306 | ||||
2307 | // Validate comma. | |||
2308 | if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ',')) | |||
2309 | return SendIllFormedResponse(packet, "Comma sep missing in M packet"); | |||
2310 | ||||
2311 | // Get # bytes to read. | |||
2312 | if (packet.GetBytesLeft() < 1) | |||
2313 | return SendIllFormedResponse(packet, "Length missing in M packet"); | |||
2314 | ||||
2315 | const uint64_t byte_count = packet.GetHexMaxU64(false, 0); | |||
2316 | if (byte_count == 0) { | |||
2317 | LLDB_LOG(log, "nothing to write: zero-length packet")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "nothing to write: zero-length packet"); } while ( 0); | |||
2318 | return PacketResult::Success; | |||
2319 | } | |||
2320 | ||||
2321 | // Validate colon. | |||
2322 | if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':')) | |||
2323 | return SendIllFormedResponse( | |||
2324 | packet, "Comma sep missing in M packet after byte length"); | |||
2325 | ||||
2326 | // Allocate the conversion buffer. | |||
2327 | std::vector<uint8_t> buf(byte_count, 0); | |||
2328 | if (buf.empty()) | |||
2329 | return SendErrorResponse(0x78); | |||
2330 | ||||
2331 | // Convert the hex memory write contents to bytes. | |||
2332 | StreamGDBRemote response; | |||
2333 | const uint64_t convert_count = packet.GetHexBytes(buf, 0); | |||
2334 | if (convert_count != byte_count) { | |||
2335 | LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " "to convert.", m_debugged_process_up->GetID(), write_addr , byte_count, convert_count); } while (0) | |||
2336 | "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} "do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " "to convert.", m_debugged_process_up->GetID(), write_addr , byte_count, convert_count); } while (0) | |||
2337 | "to convert.",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " "to convert.", m_debugged_process_up->GetID(), write_addr , byte_count, convert_count); } while (0) | |||
2338 | m_debugged_process_up->GetID(), write_addr, byte_count,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " "to convert.", m_debugged_process_up->GetID(), write_addr , byte_count, convert_count); } while (0) | |||
2339 | convert_count)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: asked to write {2} bytes, but only found {3} " "to convert.", m_debugged_process_up->GetID(), write_addr , byte_count, convert_count); } while (0); | |||
2340 | return SendIllFormedResponse(packet, "M content byte length specified did " | |||
2341 | "not match hex-encoded content " | |||
2342 | "length"); | |||
2343 | } | |||
2344 | ||||
2345 | // Write the process memory. | |||
2346 | size_t bytes_written = 0; | |||
2347 | Status error = m_debugged_process_up->WriteMemory(write_addr, &buf[0], | |||
2348 | byte_count, bytes_written); | |||
2349 | if (error.Fail()) { | |||
2350 | LLDB_LOG(log, "pid {0} mem {1:x}: failed to write. Error: {2}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: failed to write. Error: {2}", m_debugged_process_up->GetID(), write_addr, error); } while (0) | |||
2351 | m_debugged_process_up->GetID(), write_addr, error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: failed to write. Error: {2}", m_debugged_process_up->GetID(), write_addr, error); } while (0); | |||
2352 | return SendErrorResponse(0x09); | |||
2353 | } | |||
2354 | ||||
2355 | if (bytes_written == 0) { | |||
2356 | LLDB_LOG(log, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes" , m_debugged_process_up->GetID(), write_addr, byte_count); } while (0) | |||
2357 | m_debugged_process_up->GetID(), write_addr, byte_count)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} mem {1:x}: wrote 0 of {2} requested bytes" , m_debugged_process_up->GetID(), write_addr, byte_count); } while (0); | |||
2358 | return SendErrorResponse(0x09); | |||
2359 | } | |||
2360 | ||||
2361 | return SendOKResponse(); | |||
2362 | } | |||
2363 | ||||
2364 | GDBRemoteCommunication::PacketResult | |||
2365 | GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported( | |||
2366 | StringExtractorGDBRemote &packet) { | |||
2367 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2368 | ||||
2369 | // Currently only the NativeProcessProtocol knows if it can handle a | |||
2370 | // qMemoryRegionInfoSupported request, but we're not guaranteed to be | |||
2371 | // attached to a process. For now we'll assume the client only asks this | |||
2372 | // when a process is being debugged. | |||
2373 | ||||
2374 | // Ensure we have a process running; otherwise, we can't figure this out | |||
2375 | // since we won't have a NativeProcessProtocol. | |||
2376 | if (!m_debugged_process_up || | |||
2377 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2378 | if (log) | |||
2379 | log->Printf( | |||
2380 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2381 | __FUNCTION__); | |||
2382 | return SendErrorResponse(0x15); | |||
2383 | } | |||
2384 | ||||
2385 | // Test if we can get any region back when asking for the region around NULL. | |||
2386 | MemoryRegionInfo region_info; | |||
2387 | const Status error = | |||
2388 | m_debugged_process_up->GetMemoryRegionInfo(0, region_info); | |||
2389 | if (error.Fail()) { | |||
2390 | // We don't support memory region info collection for this | |||
2391 | // NativeProcessProtocol. | |||
2392 | return SendUnimplementedResponse(""); | |||
2393 | } | |||
2394 | ||||
2395 | return SendOKResponse(); | |||
2396 | } | |||
2397 | ||||
2398 | GDBRemoteCommunication::PacketResult | |||
2399 | GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo( | |||
2400 | StringExtractorGDBRemote &packet) { | |||
2401 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2402 | ||||
2403 | // Ensure we have a process. | |||
2404 | if (!m_debugged_process_up || | |||
2405 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2406 | if (log) | |||
2407 | log->Printf( | |||
2408 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2409 | __FUNCTION__); | |||
2410 | return SendErrorResponse(0x15); | |||
2411 | } | |||
2412 | ||||
2413 | // Parse out the memory address. | |||
2414 | packet.SetFilePos(strlen("qMemoryRegionInfo:")); | |||
2415 | if (packet.GetBytesLeft() < 1) | |||
2416 | return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet"); | |||
2417 | ||||
2418 | // Read the address. Punting on validation. | |||
2419 | const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0); | |||
2420 | ||||
2421 | StreamGDBRemote response; | |||
2422 | ||||
2423 | // Get the memory region info for the target address. | |||
2424 | MemoryRegionInfo region_info; | |||
2425 | const Status error = | |||
2426 | m_debugged_process_up->GetMemoryRegionInfo(read_addr, region_info); | |||
2427 | if (error.Fail()) { | |||
2428 | // Return the error message. | |||
2429 | ||||
2430 | response.PutCString("error:"); | |||
2431 | response.PutCStringAsRawHex8(error.AsCString()); | |||
2432 | response.PutChar(';'); | |||
2433 | } else { | |||
2434 | // Range start and size. | |||
2435 | response.Printf("start:%" PRIx64"l" "x" ";size:%" PRIx64"l" "x" ";", | |||
2436 | region_info.GetRange().GetRangeBase(), | |||
2437 | region_info.GetRange().GetByteSize()); | |||
2438 | ||||
2439 | // Permissions. | |||
2440 | if (region_info.GetReadable() || region_info.GetWritable() || | |||
2441 | region_info.GetExecutable()) { | |||
2442 | // Write permissions info. | |||
2443 | response.PutCString("permissions:"); | |||
2444 | ||||
2445 | if (region_info.GetReadable()) | |||
2446 | response.PutChar('r'); | |||
2447 | if (region_info.GetWritable()) | |||
2448 | response.PutChar('w'); | |||
2449 | if (region_info.GetExecutable()) | |||
2450 | response.PutChar('x'); | |||
2451 | ||||
2452 | response.PutChar(';'); | |||
2453 | } | |||
2454 | ||||
2455 | // Name | |||
2456 | ConstString name = region_info.GetName(); | |||
2457 | if (name) { | |||
2458 | response.PutCString("name:"); | |||
2459 | response.PutCStringAsRawHex8(name.AsCString()); | |||
2460 | response.PutChar(';'); | |||
2461 | } | |||
2462 | } | |||
2463 | ||||
2464 | return SendPacketNoLock(response.GetString()); | |||
2465 | } | |||
2466 | ||||
2467 | GDBRemoteCommunication::PacketResult | |||
2468 | GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) { | |||
2469 | // Ensure we have a process. | |||
2470 | if (!m_debugged_process_up || | |||
2471 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2472 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2473 | LLDB_LOG(log, "failed, no process available")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed, no process available"); } while (0); | |||
2474 | return SendErrorResponse(0x15); | |||
2475 | } | |||
2476 | ||||
2477 | // Parse out software or hardware breakpoint or watchpoint requested. | |||
2478 | packet.SetFilePos(strlen("Z")); | |||
2479 | if (packet.GetBytesLeft() < 1) | |||
2480 | return SendIllFormedResponse( | |||
2481 | packet, "Too short Z packet, missing software/hardware specifier"); | |||
2482 | ||||
2483 | bool want_breakpoint = true; | |||
2484 | bool want_hardware = false; | |||
2485 | uint32_t watch_flags = 0; | |||
2486 | ||||
2487 | const GDBStoppointType stoppoint_type = | |||
2488 | GDBStoppointType(packet.GetS32(eStoppointInvalid)); | |||
2489 | switch (stoppoint_type) { | |||
2490 | case eBreakpointSoftware: | |||
2491 | want_hardware = false; | |||
2492 | want_breakpoint = true; | |||
2493 | break; | |||
2494 | case eBreakpointHardware: | |||
2495 | want_hardware = true; | |||
2496 | want_breakpoint = true; | |||
2497 | break; | |||
2498 | case eWatchpointWrite: | |||
2499 | watch_flags = 1; | |||
2500 | want_hardware = true; | |||
2501 | want_breakpoint = false; | |||
2502 | break; | |||
2503 | case eWatchpointRead: | |||
2504 | watch_flags = 2; | |||
2505 | want_hardware = true; | |||
2506 | want_breakpoint = false; | |||
2507 | break; | |||
2508 | case eWatchpointReadWrite: | |||
2509 | watch_flags = 3; | |||
2510 | want_hardware = true; | |||
2511 | want_breakpoint = false; | |||
2512 | break; | |||
2513 | case eStoppointInvalid: | |||
2514 | return SendIllFormedResponse( | |||
2515 | packet, "Z packet had invalid software/hardware specifier"); | |||
2516 | } | |||
2517 | ||||
2518 | if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') | |||
2519 | return SendIllFormedResponse( | |||
2520 | packet, "Malformed Z packet, expecting comma after stoppoint type"); | |||
2521 | ||||
2522 | // Parse out the stoppoint address. | |||
2523 | if (packet.GetBytesLeft() < 1) | |||
2524 | return SendIllFormedResponse(packet, "Too short Z packet, missing address"); | |||
2525 | const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); | |||
2526 | ||||
2527 | if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') | |||
2528 | return SendIllFormedResponse( | |||
2529 | packet, "Malformed Z packet, expecting comma after address"); | |||
2530 | ||||
2531 | // Parse out the stoppoint size (i.e. size hint for opcode size). | |||
2532 | const uint32_t size = | |||
2533 | packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max()); | |||
2534 | if (size == std::numeric_limits<uint32_t>::max()) | |||
2535 | return SendIllFormedResponse( | |||
2536 | packet, "Malformed Z packet, failed to parse size argument"); | |||
2537 | ||||
2538 | if (want_breakpoint) { | |||
2539 | // Try to set the breakpoint. | |||
2540 | const Status error = | |||
2541 | m_debugged_process_up->SetBreakpoint(addr, size, want_hardware); | |||
2542 | if (error.Success()) | |||
2543 | return SendOKResponse(); | |||
2544 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS(1u << 5))); | |||
2545 | LLDB_LOG(log, "pid {0} failed to set breakpoint: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to set breakpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
2546 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to set breakpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
2547 | return SendErrorResponse(0x09); | |||
2548 | } else { | |||
2549 | // Try to set the watchpoint. | |||
2550 | const Status error = m_debugged_process_up->SetWatchpoint( | |||
2551 | addr, size, watch_flags, want_hardware); | |||
2552 | if (error.Success()) | |||
2553 | return SendOKResponse(); | |||
2554 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS(1u << 6))); | |||
2555 | LLDB_LOG(log, "pid {0} failed to set watchpoint: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to set watchpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
2556 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to set watchpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
2557 | return SendErrorResponse(0x09); | |||
2558 | } | |||
2559 | } | |||
2560 | ||||
2561 | GDBRemoteCommunication::PacketResult | |||
2562 | GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) { | |||
2563 | // Ensure we have a process. | |||
2564 | if (!m_debugged_process_up || | |||
2565 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2566 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2567 | LLDB_LOG(log, "failed, no process available")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed, no process available"); } while (0); | |||
2568 | return SendErrorResponse(0x15); | |||
2569 | } | |||
2570 | ||||
2571 | // Parse out software or hardware breakpoint or watchpoint requested. | |||
2572 | packet.SetFilePos(strlen("z")); | |||
2573 | if (packet.GetBytesLeft() < 1) | |||
2574 | return SendIllFormedResponse( | |||
2575 | packet, "Too short z packet, missing software/hardware specifier"); | |||
2576 | ||||
2577 | bool want_breakpoint = true; | |||
2578 | bool want_hardware = false; | |||
2579 | ||||
2580 | const GDBStoppointType stoppoint_type = | |||
2581 | GDBStoppointType(packet.GetS32(eStoppointInvalid)); | |||
2582 | switch (stoppoint_type) { | |||
2583 | case eBreakpointHardware: | |||
2584 | want_breakpoint = true; | |||
2585 | want_hardware = true; | |||
2586 | break; | |||
2587 | case eBreakpointSoftware: | |||
2588 | want_breakpoint = true; | |||
2589 | break; | |||
2590 | case eWatchpointWrite: | |||
2591 | want_breakpoint = false; | |||
2592 | break; | |||
2593 | case eWatchpointRead: | |||
2594 | want_breakpoint = false; | |||
2595 | break; | |||
2596 | case eWatchpointReadWrite: | |||
2597 | want_breakpoint = false; | |||
2598 | break; | |||
2599 | default: | |||
2600 | return SendIllFormedResponse( | |||
2601 | packet, "z packet had invalid software/hardware specifier"); | |||
2602 | } | |||
2603 | ||||
2604 | if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') | |||
2605 | return SendIllFormedResponse( | |||
2606 | packet, "Malformed z packet, expecting comma after stoppoint type"); | |||
2607 | ||||
2608 | // Parse out the stoppoint address. | |||
2609 | if (packet.GetBytesLeft() < 1) | |||
2610 | return SendIllFormedResponse(packet, "Too short z packet, missing address"); | |||
2611 | const lldb::addr_t addr = packet.GetHexMaxU64(false, 0); | |||
2612 | ||||
2613 | if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',') | |||
2614 | return SendIllFormedResponse( | |||
2615 | packet, "Malformed z packet, expecting comma after address"); | |||
2616 | ||||
2617 | /* | |||
2618 | // Parse out the stoppoint size (i.e. size hint for opcode size). | |||
2619 | const uint32_t size = packet.GetHexMaxU32 (false, | |||
2620 | std::numeric_limits<uint32_t>::max ()); | |||
2621 | if (size == std::numeric_limits<uint32_t>::max ()) | |||
2622 | return SendIllFormedResponse(packet, "Malformed z packet, failed to parse | |||
2623 | size argument"); | |||
2624 | */ | |||
2625 | ||||
2626 | if (want_breakpoint) { | |||
2627 | // Try to clear the breakpoint. | |||
2628 | const Status error = | |||
2629 | m_debugged_process_up->RemoveBreakpoint(addr, want_hardware); | |||
2630 | if (error.Success()) | |||
2631 | return SendOKResponse(); | |||
2632 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS(1u << 5))); | |||
2633 | LLDB_LOG(log, "pid {0} failed to remove breakpoint: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to remove breakpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
2634 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to remove breakpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
2635 | return SendErrorResponse(0x09); | |||
2636 | } else { | |||
2637 | // Try to clear the watchpoint. | |||
2638 | const Status error = m_debugged_process_up->RemoveWatchpoint(addr); | |||
2639 | if (error.Success()) | |||
2640 | return SendOKResponse(); | |||
2641 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS(1u << 6))); | |||
2642 | LLDB_LOG(log, "pid {0} failed to remove watchpoint: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to remove watchpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0) | |||
2643 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to remove watchpoint: {1}", m_debugged_process_up ->GetID(), error); } while (0); | |||
2644 | return SendErrorResponse(0x09); | |||
2645 | } | |||
2646 | } | |||
2647 | ||||
2648 | GDBRemoteCommunication::PacketResult | |||
2649 | GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { | |||
2650 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
2651 | ||||
2652 | // Ensure we have a process. | |||
2653 | if (!m_debugged_process_up || | |||
2654 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2655 | if (log) | |||
2656 | log->Printf( | |||
2657 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2658 | __FUNCTION__); | |||
2659 | return SendErrorResponse(0x32); | |||
2660 | } | |||
2661 | ||||
2662 | // We first try to use a continue thread id. If any one or any all set, use | |||
2663 | // the current thread. Bail out if we don't have a thread id. | |||
2664 | lldb::tid_t tid = GetContinueThreadID(); | |||
2665 | if (tid == 0 || tid == LLDB_INVALID_THREAD_ID0) | |||
2666 | tid = GetCurrentThreadID(); | |||
2667 | if (tid == LLDB_INVALID_THREAD_ID0) | |||
2668 | return SendErrorResponse(0x33); | |||
2669 | ||||
2670 | // Double check that we have such a thread. | |||
2671 | // TODO investigate: on MacOSX we might need to do an UpdateThreads () here. | |||
2672 | NativeThreadProtocol *thread = m_debugged_process_up->GetThreadByID(tid); | |||
2673 | if (!thread) | |||
2674 | return SendErrorResponse(0x33); | |||
2675 | ||||
2676 | // Create the step action for the given thread. | |||
2677 | ResumeAction action = {tid, eStateStepping, 0}; | |||
2678 | ||||
2679 | // Setup the actions list. | |||
2680 | ResumeActionList actions; | |||
2681 | actions.Append(action); | |||
2682 | ||||
2683 | // All other threads stop while we're single stepping a thread. | |||
2684 | actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); | |||
2685 | Status error = m_debugged_process_up->Resume(actions); | |||
2686 | if (error.Fail()) { | |||
2687 | if (log) | |||
2688 | log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64"l" "u" | |||
2689 | " tid %" PRIu64"l" "u" " Resume() failed with error: %s", | |||
2690 | __FUNCTION__, m_debugged_process_up->GetID(), tid, | |||
2691 | error.AsCString()); | |||
2692 | return SendErrorResponse(0x49); | |||
2693 | } | |||
2694 | ||||
2695 | // No response here - the stop or exit will come from the resulting action. | |||
2696 | return PacketResult::Success; | |||
2697 | } | |||
2698 | ||||
2699 | GDBRemoteCommunication::PacketResult | |||
2700 | GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read( | |||
2701 | StringExtractorGDBRemote &packet) { | |||
2702 | // *BSD impls should be able to do this too. | |||
2703 | #if defined(__linux__1) || defined(__NetBSD__) | |||
2704 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2705 | ||||
2706 | // Parse out the offset. | |||
2707 | packet.SetFilePos(strlen("qXfer:auxv:read::")); | |||
2708 | if (packet.GetBytesLeft() < 1) | |||
2709 | return SendIllFormedResponse(packet, | |||
2710 | "qXfer:auxv:read:: packet missing offset"); | |||
2711 | ||||
2712 | const uint64_t auxv_offset = | |||
2713 | packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); | |||
2714 | if (auxv_offset == std::numeric_limits<uint64_t>::max()) | |||
2715 | return SendIllFormedResponse(packet, | |||
2716 | "qXfer:auxv:read:: packet missing offset"); | |||
2717 | ||||
2718 | // Parse out comma. | |||
2719 | if (packet.GetBytesLeft() < 1 || packet.GetChar() != ',') | |||
2720 | return SendIllFormedResponse( | |||
2721 | packet, "qXfer:auxv:read:: packet missing comma after offset"); | |||
2722 | ||||
2723 | // Parse out the length. | |||
2724 | const uint64_t auxv_length = | |||
2725 | packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max()); | |||
2726 | if (auxv_length == std::numeric_limits<uint64_t>::max()) | |||
2727 | return SendIllFormedResponse(packet, | |||
2728 | "qXfer:auxv:read:: packet missing length"); | |||
2729 | ||||
2730 | // Grab the auxv data if we need it. | |||
2731 | if (!m_active_auxv_buffer_up) { | |||
2732 | // Make sure we have a valid process. | |||
2733 | if (!m_debugged_process_up || | |||
2734 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2735 | if (log) | |||
2736 | log->Printf( | |||
2737 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2738 | __FUNCTION__); | |||
2739 | return SendErrorResponse(0x10); | |||
2740 | } | |||
2741 | ||||
2742 | // Grab the auxv data. | |||
2743 | auto buffer_or_error = m_debugged_process_up->GetAuxvData(); | |||
2744 | if (!buffer_or_error) { | |||
2745 | std::error_code ec = buffer_or_error.getError(); | |||
2746 | LLDB_LOG(log, "no auxv data retrieved: {0}", ec.message())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "no auxv data retrieved: {0}", ec.message()); } while (0); | |||
2747 | return SendErrorResponse(ec.value()); | |||
2748 | } | |||
2749 | m_active_auxv_buffer_up = std::move(*buffer_or_error); | |||
2750 | } | |||
2751 | ||||
2752 | StreamGDBRemote response; | |||
2753 | bool done_with_buffer = false; | |||
2754 | ||||
2755 | llvm::StringRef buffer = m_active_auxv_buffer_up->getBuffer(); | |||
2756 | if (auxv_offset >= buffer.size()) { | |||
2757 | // We have nothing left to send. Mark the buffer as complete. | |||
2758 | response.PutChar('l'); | |||
2759 | done_with_buffer = true; | |||
2760 | } else { | |||
2761 | // Figure out how many bytes are available starting at the given offset. | |||
2762 | buffer = buffer.drop_front(auxv_offset); | |||
2763 | ||||
2764 | // Mark the response type according to whether we're reading the remainder | |||
2765 | // of the auxv data. | |||
2766 | if (auxv_length >= buffer.size()) { | |||
2767 | // There will be nothing left to read after this | |||
2768 | response.PutChar('l'); | |||
2769 | done_with_buffer = true; | |||
2770 | } else { | |||
2771 | // There will still be bytes to read after this request. | |||
2772 | response.PutChar('m'); | |||
2773 | buffer = buffer.take_front(auxv_length); | |||
2774 | } | |||
2775 | ||||
2776 | // Now write the data in encoded binary form. | |||
2777 | response.PutEscapedBytes(buffer.data(), buffer.size()); | |||
2778 | } | |||
2779 | ||||
2780 | if (done_with_buffer) | |||
2781 | m_active_auxv_buffer_up.reset(); | |||
2782 | ||||
2783 | return SendPacketNoLock(response.GetString()); | |||
2784 | #else | |||
2785 | return SendUnimplementedResponse("not implemented on this platform"); | |||
2786 | #endif | |||
2787 | } | |||
2788 | ||||
2789 | GDBRemoteCommunication::PacketResult | |||
2790 | GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState( | |||
2791 | StringExtractorGDBRemote &packet) { | |||
2792 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
2793 | ||||
2794 | // Move past packet name. | |||
2795 | packet.SetFilePos(strlen("QSaveRegisterState")); | |||
2796 | ||||
2797 | // Get the thread to use. | |||
2798 | NativeThreadProtocol *thread = GetThreadFromSuffix(packet); | |||
2799 | if (!thread) { | |||
2800 | if (m_thread_suffix_supported) | |||
2801 | return SendIllFormedResponse( | |||
2802 | packet, "No thread specified in QSaveRegisterState packet"); | |||
2803 | else | |||
2804 | return SendIllFormedResponse(packet, | |||
2805 | "No thread was is set with the Hg packet"); | |||
2806 | } | |||
2807 | ||||
2808 | // Grab the register context for the thread. | |||
2809 | NativeRegisterContext& reg_context = thread->GetRegisterContext(); | |||
2810 | ||||
2811 | // Save registers to a buffer. | |||
2812 | DataBufferSP register_data_sp; | |||
2813 | Status error = reg_context.ReadAllRegisterValues(register_data_sp); | |||
2814 | if (error.Fail()) { | |||
2815 | LLDB_LOG(log, "pid {0} failed to save all register values: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to save all register values: {1}" , m_debugged_process_up->GetID(), error); } while (0) | |||
2816 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to save all register values: {1}" , m_debugged_process_up->GetID(), error); } while (0); | |||
2817 | return SendErrorResponse(0x75); | |||
2818 | } | |||
2819 | ||||
2820 | // Allocate a new save id. | |||
2821 | const uint32_t save_id = GetNextSavedRegistersID(); | |||
2822 | assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&(((m_saved_registers_map.find(save_id) == m_saved_registers_map .end()) && "GetNextRegisterSaveID() returned an existing register save id" ) ? static_cast<void> (0) : __assert_fail ("(m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) && \"GetNextRegisterSaveID() returned an existing register save id\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 2823, __PRETTY_FUNCTION__)) | |||
2823 | "GetNextRegisterSaveID() returned an existing register save id")(((m_saved_registers_map.find(save_id) == m_saved_registers_map .end()) && "GetNextRegisterSaveID() returned an existing register save id" ) ? static_cast<void> (0) : __assert_fail ("(m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) && \"GetNextRegisterSaveID() returned an existing register save id\"" , "/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , 2823, __PRETTY_FUNCTION__)); | |||
2824 | ||||
2825 | // Save the register data buffer under the save id. | |||
2826 | { | |||
2827 | std::lock_guard<std::mutex> guard(m_saved_registers_mutex); | |||
2828 | m_saved_registers_map[save_id] = register_data_sp; | |||
2829 | } | |||
2830 | ||||
2831 | // Write the response. | |||
2832 | StreamGDBRemote response; | |||
2833 | response.Printf("%" PRIu32"u", save_id); | |||
2834 | return SendPacketNoLock(response.GetString()); | |||
2835 | } | |||
2836 | ||||
2837 | GDBRemoteCommunication::PacketResult | |||
2838 | GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState( | |||
2839 | StringExtractorGDBRemote &packet) { | |||
2840 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
2841 | ||||
2842 | // Parse out save id. | |||
2843 | packet.SetFilePos(strlen("QRestoreRegisterState:")); | |||
2844 | if (packet.GetBytesLeft() < 1) | |||
2845 | return SendIllFormedResponse( | |||
2846 | packet, "QRestoreRegisterState packet missing register save id"); | |||
2847 | ||||
2848 | const uint32_t save_id = packet.GetU32(0); | |||
2849 | if (save_id == 0) { | |||
2850 | LLDB_LOG(log, "QRestoreRegisterState packet has malformed save id, "do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "QRestoreRegisterState packet has malformed save id, " "expecting decimal uint32_t"); } while (0) | |||
2851 | "expecting decimal uint32_t")do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "QRestoreRegisterState packet has malformed save id, " "expecting decimal uint32_t"); } while (0); | |||
2852 | return SendErrorResponse(0x76); | |||
2853 | } | |||
2854 | ||||
2855 | // Get the thread to use. | |||
2856 | NativeThreadProtocol *thread = GetThreadFromSuffix(packet); | |||
2857 | if (!thread) { | |||
2858 | if (m_thread_suffix_supported) | |||
2859 | return SendIllFormedResponse( | |||
2860 | packet, "No thread specified in QRestoreRegisterState packet"); | |||
2861 | else | |||
2862 | return SendIllFormedResponse(packet, | |||
2863 | "No thread was is set with the Hg packet"); | |||
2864 | } | |||
2865 | ||||
2866 | // Grab the register context for the thread. | |||
2867 | NativeRegisterContext ®_context = thread->GetRegisterContext(); | |||
2868 | ||||
2869 | // Retrieve register state buffer, then remove from the list. | |||
2870 | DataBufferSP register_data_sp; | |||
2871 | { | |||
2872 | std::lock_guard<std::mutex> guard(m_saved_registers_mutex); | |||
2873 | ||||
2874 | // Find the register set buffer for the given save id. | |||
2875 | auto it = m_saved_registers_map.find(save_id); | |||
2876 | if (it == m_saved_registers_map.end()) { | |||
2877 | LLDB_LOG(log,do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} does not have a register set save buffer for id {1}" , m_debugged_process_up->GetID(), save_id); } while (0) | |||
2878 | "pid {0} does not have a register set save buffer for id {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} does not have a register set save buffer for id {1}" , m_debugged_process_up->GetID(), save_id); } while (0) | |||
2879 | m_debugged_process_up->GetID(), save_id)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} does not have a register set save buffer for id {1}" , m_debugged_process_up->GetID(), save_id); } while (0); | |||
2880 | return SendErrorResponse(0x77); | |||
2881 | } | |||
2882 | register_data_sp = it->second; | |||
2883 | ||||
2884 | // Remove it from the map. | |||
2885 | m_saved_registers_map.erase(it); | |||
2886 | } | |||
2887 | ||||
2888 | Status error = reg_context.WriteAllRegisterValues(register_data_sp); | |||
2889 | if (error.Fail()) { | |||
2890 | LLDB_LOG(log, "pid {0} failed to restore all register values: {1}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to restore all register values: {1}" , m_debugged_process_up->GetID(), error); } while (0) | |||
2891 | m_debugged_process_up->GetID(), error)do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "pid {0} failed to restore all register values: {1}" , m_debugged_process_up->GetID(), error); } while (0); | |||
2892 | return SendErrorResponse(0x77); | |||
2893 | } | |||
2894 | ||||
2895 | return SendOKResponse(); | |||
2896 | } | |||
2897 | ||||
2898 | GDBRemoteCommunication::PacketResult | |||
2899 | GDBRemoteCommunicationServerLLGS::Handle_vAttach( | |||
2900 | StringExtractorGDBRemote &packet) { | |||
2901 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2902 | ||||
2903 | // Consume the ';' after vAttach. | |||
2904 | packet.SetFilePos(strlen("vAttach")); | |||
2905 | if (!packet.GetBytesLeft() || packet.GetChar() != ';') | |||
2906 | return SendIllFormedResponse(packet, "vAttach missing expected ';'"); | |||
2907 | ||||
2908 | // Grab the PID to which we will attach (assume hex encoding). | |||
2909 | lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID0, 16); | |||
2910 | if (pid == LLDB_INVALID_PROCESS_ID0) | |||
2911 | return SendIllFormedResponse(packet, | |||
2912 | "vAttach failed to parse the process id"); | |||
2913 | ||||
2914 | // Attempt to attach. | |||
2915 | if (log) | |||
2916 | log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to " | |||
2917 | "pid %" PRIu64"l" "u", | |||
2918 | __FUNCTION__, pid); | |||
2919 | ||||
2920 | Status error = AttachToProcess(pid); | |||
2921 | ||||
2922 | if (error.Fail()) { | |||
2923 | if (log) | |||
2924 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to " | |||
2925 | "pid %" PRIu64"l" "u" ": %s\n", | |||
2926 | __FUNCTION__, pid, error.AsCString()); | |||
2927 | return SendErrorResponse(error); | |||
2928 | } | |||
2929 | ||||
2930 | // Notify we attached by sending a stop packet. | |||
2931 | return SendStopReasonForState(m_debugged_process_up->GetState()); | |||
2932 | } | |||
2933 | ||||
2934 | GDBRemoteCommunication::PacketResult | |||
2935 | GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { | |||
2936 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
2937 | ||||
2938 | StopSTDIOForwarding(); | |||
2939 | ||||
2940 | // Fail if we don't have a current process. | |||
2941 | if (!m_debugged_process_up || | |||
2942 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) { | |||
2943 | if (log) | |||
2944 | log->Printf( | |||
2945 | "GDBRemoteCommunicationServerLLGS::%s failed, no process available", | |||
2946 | __FUNCTION__); | |||
2947 | return SendErrorResponse(0x15); | |||
2948 | } | |||
2949 | ||||
2950 | lldb::pid_t pid = LLDB_INVALID_PROCESS_ID0; | |||
2951 | ||||
2952 | // Consume the ';' after D. | |||
2953 | packet.SetFilePos(1); | |||
2954 | if (packet.GetBytesLeft()) { | |||
2955 | if (packet.GetChar() != ';') | |||
2956 | return SendIllFormedResponse(packet, "D missing expected ';'"); | |||
2957 | ||||
2958 | // Grab the PID from which we will detach (assume hex encoding). | |||
2959 | pid = packet.GetU32(LLDB_INVALID_PROCESS_ID0, 16); | |||
2960 | if (pid == LLDB_INVALID_PROCESS_ID0) | |||
2961 | return SendIllFormedResponse(packet, "D failed to parse the process id"); | |||
2962 | } | |||
2963 | ||||
2964 | if (pid != LLDB_INVALID_PROCESS_ID0 && m_debugged_process_up->GetID() != pid) { | |||
2965 | return SendIllFormedResponse(packet, "Invalid pid"); | |||
2966 | } | |||
2967 | ||||
2968 | const Status error = m_debugged_process_up->Detach(); | |||
2969 | if (error.Fail()) { | |||
2970 | if (log) | |||
2971 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from " | |||
2972 | "pid %" PRIu64"l" "u" ": %s\n", | |||
2973 | __FUNCTION__, m_debugged_process_up->GetID(), | |||
2974 | error.AsCString()); | |||
2975 | return SendErrorResponse(0x01); | |||
2976 | } | |||
2977 | ||||
2978 | return SendOKResponse(); | |||
2979 | } | |||
2980 | ||||
2981 | GDBRemoteCommunication::PacketResult | |||
2982 | GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo( | |||
2983 | StringExtractorGDBRemote &packet) { | |||
2984 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
2985 | ||||
2986 | packet.SetFilePos(strlen("qThreadStopInfo")); | |||
2987 | const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID0); | |||
2988 | if (tid == LLDB_INVALID_THREAD_ID0) { | |||
2989 | if (log) | |||
2990 | log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not " | |||
2991 | "parse thread id from request \"%s\"", | |||
2992 | __FUNCTION__, packet.GetStringRef().c_str()); | |||
2993 | return SendErrorResponse(0x15); | |||
2994 | } | |||
2995 | return SendStopReplyPacketForThread(tid); | |||
2996 | } | |||
2997 | ||||
2998 | GDBRemoteCommunication::PacketResult | |||
2999 | GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo( | |||
3000 | StringExtractorGDBRemote &) { | |||
3001 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1) | LIBLLDB_LOG_THREAD(1u << 2))); | |||
3002 | ||||
3003 | // Ensure we have a debugged process. | |||
3004 | if (!m_debugged_process_up || | |||
3005 | (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0)) | |||
3006 | return SendErrorResponse(50); | |||
3007 | LLDB_LOG(log, "preparing packet for pid {0}", m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "preparing packet for pid {0}", m_debugged_process_up ->GetID()); } while (0); | |||
3008 | ||||
3009 | StreamString response; | |||
3010 | const bool threads_with_valid_stop_info_only = false; | |||
3011 | JSONArray::SP threads_array_sp = GetJSONThreadsInfo( | |||
3012 | *m_debugged_process_up, threads_with_valid_stop_info_only); | |||
3013 | if (!threads_array_sp) { | |||
3014 | LLDB_LOG(log, "failed to prepare a packet for pid {0}",do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to prepare a packet for pid {0}", m_debugged_process_up ->GetID()); } while (0) | |||
3015 | m_debugged_process_up->GetID())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "failed to prepare a packet for pid {0}", m_debugged_process_up ->GetID()); } while (0); | |||
3016 | return SendErrorResponse(52); | |||
3017 | } | |||
3018 | ||||
3019 | threads_array_sp->Write(response); | |||
3020 | StreamGDBRemote escaped_response; | |||
3021 | escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); | |||
3022 | return SendPacketNoLock(escaped_response.GetString()); | |||
3023 | } | |||
3024 | ||||
3025 | GDBRemoteCommunication::PacketResult | |||
3026 | GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo( | |||
3027 | StringExtractorGDBRemote &packet) { | |||
3028 | // Fail if we don't have a current process. | |||
3029 | if (!m_debugged_process_up || | |||
3030 | m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0) | |||
3031 | return SendErrorResponse(68); | |||
3032 | ||||
3033 | packet.SetFilePos(strlen("qWatchpointSupportInfo")); | |||
3034 | if (packet.GetBytesLeft() == 0) | |||
3035 | return SendOKResponse(); | |||
3036 | if (packet.GetChar() != ':') | |||
3037 | return SendErrorResponse(67); | |||
3038 | ||||
3039 | auto hw_debug_cap = m_debugged_process_up->GetHardwareDebugSupportInfo(); | |||
3040 | ||||
3041 | StreamGDBRemote response; | |||
3042 | if (hw_debug_cap == llvm::None) | |||
3043 | response.Printf("num:0;"); | |||
3044 | else | |||
3045 | response.Printf("num:%d;", hw_debug_cap->second); | |||
3046 | ||||
3047 | return SendPacketNoLock(response.GetString()); | |||
3048 | } | |||
3049 | ||||
3050 | GDBRemoteCommunication::PacketResult | |||
3051 | GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress( | |||
3052 | StringExtractorGDBRemote &packet) { | |||
3053 | // Fail if we don't have a current process. | |||
3054 | if (!m_debugged_process_up || | |||
3055 | m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0) | |||
3056 | return SendErrorResponse(67); | |||
3057 | ||||
3058 | packet.SetFilePos(strlen("qFileLoadAddress:")); | |||
3059 | if (packet.GetBytesLeft() == 0) | |||
3060 | return SendErrorResponse(68); | |||
3061 | ||||
3062 | std::string file_name; | |||
3063 | packet.GetHexByteString(file_name); | |||
3064 | ||||
3065 | lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
3066 | Status error = | |||
3067 | m_debugged_process_up->GetFileLoadAddress(file_name, file_load_address); | |||
3068 | if (error.Fail()) | |||
3069 | return SendErrorResponse(69); | |||
3070 | ||||
3071 | if (file_load_address == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
3072 | return SendErrorResponse(1); // File not loaded | |||
3073 | ||||
3074 | StreamGDBRemote response; | |||
3075 | response.PutHex64(file_load_address); | |||
3076 | return SendPacketNoLock(response.GetString()); | |||
3077 | } | |||
3078 | ||||
3079 | GDBRemoteCommunication::PacketResult | |||
3080 | GDBRemoteCommunicationServerLLGS::Handle_QPassSignals( | |||
3081 | StringExtractorGDBRemote &packet) { | |||
3082 | std::vector<int> signals; | |||
3083 | packet.SetFilePos(strlen("QPassSignals:")); | |||
3084 | ||||
3085 | // Read sequence of hex signal numbers divided by a semicolon and optionally | |||
3086 | // spaces. | |||
3087 | while (packet.GetBytesLeft() > 0) { | |||
3088 | int signal = packet.GetS32(-1, 16); | |||
3089 | if (signal < 0) | |||
3090 | return SendIllFormedResponse(packet, "Failed to parse signal number."); | |||
3091 | signals.push_back(signal); | |||
3092 | ||||
3093 | packet.SkipSpaces(); | |||
3094 | char separator = packet.GetChar(); | |||
3095 | if (separator == '\0') | |||
3096 | break; // End of string | |||
3097 | if (separator != ';') | |||
3098 | return SendIllFormedResponse(packet, "Invalid separator," | |||
3099 | " expected semicolon."); | |||
3100 | } | |||
3101 | ||||
3102 | // Fail if we don't have a current process. | |||
3103 | if (!m_debugged_process_up) | |||
3104 | return SendErrorResponse(68); | |||
3105 | ||||
3106 | Status error = m_debugged_process_up->IgnoreSignals(signals); | |||
3107 | if (error.Fail()) | |||
3108 | return SendErrorResponse(69); | |||
3109 | ||||
3110 | return SendOKResponse(); | |||
3111 | } | |||
3112 | ||||
3113 | void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() { | |||
3114 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
3115 | ||||
3116 | // Tell the stdio connection to shut down. | |||
3117 | if (m_stdio_communication.IsConnected()) { | |||
3118 | auto connection = m_stdio_communication.GetConnection(); | |||
3119 | if (connection) { | |||
3120 | Status error; | |||
3121 | connection->Disconnect(&error); | |||
3122 | ||||
3123 | if (error.Success()) { | |||
3124 | if (log) | |||
3125 | log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " | |||
3126 | "terminal stdio - SUCCESS", | |||
3127 | __FUNCTION__); | |||
3128 | } else { | |||
3129 | if (log) | |||
3130 | log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process " | |||
3131 | "terminal stdio - FAIL: %s", | |||
3132 | __FUNCTION__, error.AsCString()); | |||
3133 | } | |||
3134 | } | |||
3135 | } | |||
3136 | } | |||
3137 | ||||
3138 | NativeThreadProtocol *GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix( | |||
3139 | StringExtractorGDBRemote &packet) { | |||
3140 | // We have no thread if we don't have a process. | |||
3141 | if (!m_debugged_process_up || | |||
3142 | m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID0) | |||
3143 | return nullptr; | |||
3144 | ||||
3145 | // If the client hasn't asked for thread suffix support, there will not be a | |||
3146 | // thread suffix. Use the current thread in that case. | |||
3147 | if (!m_thread_suffix_supported) { | |||
3148 | const lldb::tid_t current_tid = GetCurrentThreadID(); | |||
3149 | if (current_tid == LLDB_INVALID_THREAD_ID0) | |||
3150 | return nullptr; | |||
3151 | else if (current_tid == 0) { | |||
3152 | // Pick a thread. | |||
3153 | return m_debugged_process_up->GetThreadAtIndex(0); | |||
3154 | } else | |||
3155 | return m_debugged_process_up->GetThreadByID(current_tid); | |||
3156 | } | |||
3157 | ||||
3158 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD(1u << 2))); | |||
3159 | ||||
3160 | // Parse out the ';'. | |||
3161 | if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') { | |||
3162 | if (log) | |||
3163 | log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " | |||
3164 | "error: expected ';' prior to start of thread suffix: packet " | |||
3165 | "contents = '%s'", | |||
3166 | __FUNCTION__, packet.GetStringRef().c_str()); | |||
3167 | return nullptr; | |||
3168 | } | |||
3169 | ||||
3170 | if (!packet.GetBytesLeft()) | |||
3171 | return nullptr; | |||
3172 | ||||
3173 | // Parse out thread: portion. | |||
3174 | if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) { | |||
3175 | if (log) | |||
3176 | log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse " | |||
3177 | "error: expected 'thread:' but not found, packet contents = " | |||
3178 | "'%s'", | |||
3179 | __FUNCTION__, packet.GetStringRef().c_str()); | |||
3180 | return nullptr; | |||
3181 | } | |||
3182 | packet.SetFilePos(packet.GetFilePos() + strlen("thread:")); | |||
3183 | const lldb::tid_t tid = packet.GetHexMaxU64(false, 0); | |||
3184 | if (tid != 0) | |||
3185 | return m_debugged_process_up->GetThreadByID(tid); | |||
3186 | ||||
3187 | return nullptr; | |||
3188 | } | |||
3189 | ||||
3190 | lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const { | |||
3191 | if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID0) { | |||
3192 | // Use whatever the debug process says is the current thread id since the | |||
3193 | // protocol either didn't specify or specified we want any/all threads | |||
3194 | // marked as the current thread. | |||
3195 | if (!m_debugged_process_up) | |||
3196 | return LLDB_INVALID_THREAD_ID0; | |||
3197 | return m_debugged_process_up->GetCurrentThreadID(); | |||
3198 | } | |||
3199 | // Use the specific current thread id set by the gdb remote protocol. | |||
3200 | return m_current_tid; | |||
3201 | } | |||
3202 | ||||
3203 | uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() { | |||
3204 | std::lock_guard<std::mutex> guard(m_saved_registers_mutex); | |||
3205 | return m_next_saved_registers_id++; | |||
3206 | } | |||
3207 | ||||
3208 | void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() { | |||
3209 | Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS(1u << 1))); | |||
3210 | ||||
3211 | LLDB_LOG(log, "clearing auxv buffer: {0}", m_active_auxv_buffer_up.get())do { ::lldb_private::Log *log_private = (log); if (log_private ) log_private->Format("/build/llvm-toolchain-snapshot-8~svn345461/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp" , __func__, "clearing auxv buffer: {0}", m_active_auxv_buffer_up .get()); } while (0); | |||
3212 | m_active_auxv_buffer_up.reset(); | |||
3213 | } | |||
3214 | ||||
3215 | FileSpec | |||
3216 | GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path, | |||
3217 | const ArchSpec &arch) { | |||
3218 | if (m_debugged_process_up) { | |||
3219 | FileSpec file_spec; | |||
3220 | if (m_debugged_process_up | |||
3221 | ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec) | |||
3222 | .Success()) { | |||
3223 | if (file_spec.Exists()) | |||
3224 | return file_spec; | |||
3225 | } | |||
3226 | } | |||
3227 | ||||
3228 | return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch); | |||
3229 | } |
1 | //===-- TraceOptions.h ------------------------------------------*- 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 | #ifndef liblldb_TraceOptions_h_ | |||
11 | #define liblldb_TraceOptions_h_ | |||
12 | ||||
13 | #include "lldb/lldb-defines.h" | |||
14 | #include "lldb/lldb-enumerations.h" | |||
15 | ||||
16 | #include "lldb/Utility/StructuredData.h" | |||
17 | ||||
18 | namespace lldb_private { | |||
19 | class TraceOptions { | |||
20 | public: | |||
21 | TraceOptions() : m_trace_params(new StructuredData::Dictionary()) {} | |||
22 | ||||
23 | const StructuredData::DictionarySP &getTraceParams() const { | |||
24 | return m_trace_params; | |||
25 | } | |||
26 | ||||
27 | lldb::TraceType getType() const { return m_type; } | |||
| ||||
28 | ||||
29 | uint64_t getTraceBufferSize() const { return m_trace_buffer_size; } | |||
30 | ||||
31 | uint64_t getMetaDataBufferSize() const { return m_meta_data_buffer_size; } | |||
32 | ||||
33 | void setTraceParams(const StructuredData::DictionarySP &dict_obj) { | |||
34 | m_trace_params = dict_obj; | |||
35 | } | |||
36 | ||||
37 | void setType(lldb::TraceType type) { m_type = type; } | |||
38 | ||||
39 | void setTraceBufferSize(uint64_t size) { m_trace_buffer_size = size; } | |||
40 | ||||
41 | void setMetaDataBufferSize(uint64_t size) { m_meta_data_buffer_size = size; } | |||
42 | ||||
43 | void setThreadID(lldb::tid_t thread_id) { m_thread_id = thread_id; } | |||
44 | ||||
45 | lldb::tid_t getThreadID() const { return m_thread_id; } | |||
46 | ||||
47 | private: | |||
48 | lldb::TraceType m_type; | |||
49 | uint64_t m_trace_buffer_size; | |||
50 | uint64_t m_meta_data_buffer_size; | |||
51 | lldb::tid_t m_thread_id; | |||
52 | ||||
53 | /// m_trace_params is meant to hold any custom parameters | |||
54 | /// apart from meta buffer size and trace size. | |||
55 | /// The interpretation of such parameters is left to | |||
56 | /// the lldb-server. | |||
57 | StructuredData::DictionarySP m_trace_params; | |||
58 | }; | |||
59 | } | |||
60 | ||||
61 | #endif // liblldb_TraceOptions_h_ |
1 | //===-- NativeProcessProtocol.h ---------------------------------*- 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 | #ifndef liblldb_NativeProcessProtocol_h_ |
11 | #define liblldb_NativeProcessProtocol_h_ |
12 | |
13 | #include "NativeBreakpointList.h" |
14 | #include "NativeThreadProtocol.h" |
15 | #include "NativeWatchpointList.h" |
16 | #include "lldb/Host/Host.h" |
17 | #include "lldb/Host/MainLoop.h" |
18 | #include "lldb/Utility/ArchSpec.h" |
19 | #include "lldb/Utility/Status.h" |
20 | #include "lldb/Utility/TraceOptions.h" |
21 | #include "lldb/lldb-private-forward.h" |
22 | #include "lldb/lldb-types.h" |
23 | #include "llvm/ADT/ArrayRef.h" |
24 | #include "llvm/ADT/DenseSet.h" |
25 | #include "llvm/ADT/StringRef.h" |
26 | #include "llvm/Support/Error.h" |
27 | #include "llvm/Support/MemoryBuffer.h" |
28 | #include <vector> |
29 | |
30 | namespace lldb_private { |
31 | class MemoryRegionInfo; |
32 | class ResumeActionList; |
33 | |
34 | //------------------------------------------------------------------ |
35 | // NativeProcessProtocol |
36 | //------------------------------------------------------------------ |
37 | class NativeProcessProtocol { |
38 | friend class SoftwareBreakpoint; |
39 | |
40 | public: |
41 | virtual ~NativeProcessProtocol() {} |
42 | |
43 | virtual Status Resume(const ResumeActionList &resume_actions) = 0; |
44 | |
45 | virtual Status Halt() = 0; |
46 | |
47 | virtual Status Detach() = 0; |
48 | |
49 | //------------------------------------------------------------------ |
50 | /// Sends a process a UNIX signal \a signal. |
51 | /// |
52 | /// @return |
53 | /// Returns an error object. |
54 | //------------------------------------------------------------------ |
55 | virtual Status Signal(int signo) = 0; |
56 | |
57 | //------------------------------------------------------------------ |
58 | /// Tells a process to interrupt all operations as if by a Ctrl-C. |
59 | /// |
60 | /// The default implementation will send a local host's equivalent of |
61 | /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() |
62 | /// operation. |
63 | /// |
64 | /// @return |
65 | /// Returns an error object. |
66 | //------------------------------------------------------------------ |
67 | virtual Status Interrupt(); |
68 | |
69 | virtual Status Kill() = 0; |
70 | |
71 | //------------------------------------------------------------------ |
72 | // Tells a process not to stop the inferior on given signals and just |
73 | // reinject them back. |
74 | //------------------------------------------------------------------ |
75 | virtual Status IgnoreSignals(llvm::ArrayRef<int> signals); |
76 | |
77 | //---------------------------------------------------------------------- |
78 | // Memory and memory region functions |
79 | //---------------------------------------------------------------------- |
80 | |
81 | virtual Status GetMemoryRegionInfo(lldb::addr_t load_addr, |
82 | MemoryRegionInfo &range_info); |
83 | |
84 | virtual Status ReadMemory(lldb::addr_t addr, void *buf, size_t size, |
85 | size_t &bytes_read) = 0; |
86 | |
87 | Status ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf, size_t size, |
88 | size_t &bytes_read); |
89 | |
90 | virtual Status WriteMemory(lldb::addr_t addr, const void *buf, size_t size, |
91 | size_t &bytes_written) = 0; |
92 | |
93 | virtual Status AllocateMemory(size_t size, uint32_t permissions, |
94 | lldb::addr_t &addr) = 0; |
95 | |
96 | virtual Status DeallocateMemory(lldb::addr_t addr) = 0; |
97 | |
98 | virtual lldb::addr_t GetSharedLibraryInfoAddress() = 0; |
99 | |
100 | virtual bool IsAlive() const; |
101 | |
102 | virtual size_t UpdateThreads() = 0; |
103 | |
104 | virtual const ArchSpec &GetArchitecture() const = 0; |
105 | |
106 | //---------------------------------------------------------------------- |
107 | // Breakpoint functions |
108 | //---------------------------------------------------------------------- |
109 | virtual Status SetBreakpoint(lldb::addr_t addr, uint32_t size, |
110 | bool hardware) = 0; |
111 | |
112 | virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false); |
113 | |
114 | virtual Status EnableBreakpoint(lldb::addr_t addr); |
115 | |
116 | virtual Status DisableBreakpoint(lldb::addr_t addr); |
117 | |
118 | //---------------------------------------------------------------------- |
119 | // Hardware Breakpoint functions |
120 | //---------------------------------------------------------------------- |
121 | virtual const HardwareBreakpointMap &GetHardwareBreakpointMap() const; |
122 | |
123 | virtual Status SetHardwareBreakpoint(lldb::addr_t addr, size_t size); |
124 | |
125 | virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr); |
126 | |
127 | //---------------------------------------------------------------------- |
128 | // Watchpoint functions |
129 | //---------------------------------------------------------------------- |
130 | virtual const NativeWatchpointList::WatchpointMap &GetWatchpointMap() const; |
131 | |
132 | virtual llvm::Optional<std::pair<uint32_t, uint32_t>> |
133 | GetHardwareDebugSupportInfo() const; |
134 | |
135 | virtual Status SetWatchpoint(lldb::addr_t addr, size_t size, |
136 | uint32_t watch_flags, bool hardware); |
137 | |
138 | virtual Status RemoveWatchpoint(lldb::addr_t addr); |
139 | |
140 | //---------------------------------------------------------------------- |
141 | // Accessors |
142 | //---------------------------------------------------------------------- |
143 | lldb::pid_t GetID() const { return m_pid; } |
144 | |
145 | lldb::StateType GetState() const; |
146 | |
147 | bool IsRunning() const { |
148 | return m_state == lldb::eStateRunning || IsStepping(); |
149 | } |
150 | |
151 | bool IsStepping() const { return m_state == lldb::eStateStepping; } |
152 | |
153 | bool CanResume() const { return m_state == lldb::eStateStopped; } |
154 | |
155 | lldb::ByteOrder GetByteOrder() const { |
156 | return GetArchitecture().GetByteOrder(); |
157 | } |
158 | |
159 | virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> |
160 | GetAuxvData() const = 0; |
161 | |
162 | //---------------------------------------------------------------------- |
163 | // Exit Status |
164 | //---------------------------------------------------------------------- |
165 | virtual llvm::Optional<WaitStatus> GetExitStatus(); |
166 | |
167 | virtual bool SetExitStatus(WaitStatus status, bool bNotifyStateChange); |
168 | |
169 | //---------------------------------------------------------------------- |
170 | // Access to threads |
171 | //---------------------------------------------------------------------- |
172 | NativeThreadProtocol *GetThreadAtIndex(uint32_t idx); |
173 | |
174 | NativeThreadProtocol *GetThreadByID(lldb::tid_t tid); |
175 | |
176 | void SetCurrentThreadID(lldb::tid_t tid) { m_current_thread_id = tid; } |
177 | |
178 | lldb::tid_t GetCurrentThreadID() { return m_current_thread_id; } |
179 | |
180 | NativeThreadProtocol *GetCurrentThread() { |
181 | return GetThreadByID(m_current_thread_id); |
182 | } |
183 | |
184 | //---------------------------------------------------------------------- |
185 | // Access to inferior stdio |
186 | //---------------------------------------------------------------------- |
187 | virtual int GetTerminalFileDescriptor() { return m_terminal_fd; } |
188 | |
189 | //---------------------------------------------------------------------- |
190 | // Stop id interface |
191 | //---------------------------------------------------------------------- |
192 | |
193 | uint32_t GetStopID() const; |
194 | |
195 | // --------------------------------------------------------------------- |
196 | // Callbacks for low-level process state changes |
197 | // --------------------------------------------------------------------- |
198 | class NativeDelegate { |
199 | public: |
200 | virtual ~NativeDelegate() {} |
201 | |
202 | virtual void InitializeDelegate(NativeProcessProtocol *process) = 0; |
203 | |
204 | virtual void ProcessStateChanged(NativeProcessProtocol *process, |
205 | lldb::StateType state) = 0; |
206 | |
207 | virtual void DidExec(NativeProcessProtocol *process) = 0; |
208 | }; |
209 | |
210 | //------------------------------------------------------------------ |
211 | /// Register a native delegate. |
212 | /// |
213 | /// Clients can register nofication callbacks by passing in a |
214 | /// NativeDelegate impl and passing it into this function. |
215 | /// |
216 | /// Note: it is required that the lifetime of the |
217 | /// native_delegate outlive the NativeProcessProtocol. |
218 | /// |
219 | /// @param[in] native_delegate |
220 | /// A NativeDelegate impl to be called when certain events |
221 | /// happen within the NativeProcessProtocol or related threads. |
222 | /// |
223 | /// @return |
224 | /// true if the delegate was registered successfully; |
225 | /// false if the delegate was already registered. |
226 | /// |
227 | /// @see NativeProcessProtocol::NativeDelegate. |
228 | //------------------------------------------------------------------ |
229 | bool RegisterNativeDelegate(NativeDelegate &native_delegate); |
230 | |
231 | //------------------------------------------------------------------ |
232 | /// Unregister a native delegate previously registered. |
233 | /// |
234 | /// @param[in] native_delegate |
235 | /// A NativeDelegate impl previously registered with this process. |
236 | /// |
237 | /// @return Returns \b true if the NativeDelegate was |
238 | /// successfully removed from the process, \b false otherwise. |
239 | /// |
240 | /// @see NativeProcessProtocol::NativeDelegate |
241 | //------------------------------------------------------------------ |
242 | bool UnregisterNativeDelegate(NativeDelegate &native_delegate); |
243 | |
244 | virtual Status GetLoadedModuleFileSpec(const char *module_path, |
245 | FileSpec &file_spec) = 0; |
246 | |
247 | virtual Status GetFileLoadAddress(const llvm::StringRef &file_name, |
248 | lldb::addr_t &load_addr) = 0; |
249 | |
250 | class Factory { |
251 | public: |
252 | virtual ~Factory(); |
253 | //------------------------------------------------------------------ |
254 | /// Launch a process for debugging. |
255 | /// |
256 | /// @param[in] launch_info |
257 | /// Information required to launch the process. |
258 | /// |
259 | /// @param[in] native_delegate |
260 | /// The delegate that will receive messages regarding the |
261 | /// inferior. Must outlive the NativeProcessProtocol |
262 | /// instance. |
263 | /// |
264 | /// @param[in] mainloop |
265 | /// The mainloop instance with which the process can register |
266 | /// callbacks. Must outlive the NativeProcessProtocol |
267 | /// instance. |
268 | /// |
269 | /// @return |
270 | /// A NativeProcessProtocol shared pointer if the operation succeeded or |
271 | /// an error object if it failed. |
272 | //------------------------------------------------------------------ |
273 | virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>> |
274 | Launch(ProcessLaunchInfo &launch_info, NativeDelegate &native_delegate, |
275 | MainLoop &mainloop) const = 0; |
276 | |
277 | //------------------------------------------------------------------ |
278 | /// Attach to an existing process. |
279 | /// |
280 | /// @param[in] pid |
281 | /// pid of the process locatable |
282 | /// |
283 | /// @param[in] native_delegate |
284 | /// The delegate that will receive messages regarding the |
285 | /// inferior. Must outlive the NativeProcessProtocol |
286 | /// instance. |
287 | /// |
288 | /// @param[in] mainloop |
289 | /// The mainloop instance with which the process can register |
290 | /// callbacks. Must outlive the NativeProcessProtocol |
291 | /// instance. |
292 | /// |
293 | /// @return |
294 | /// A NativeProcessProtocol shared pointer if the operation succeeded or |
295 | /// an error object if it failed. |
296 | //------------------------------------------------------------------ |
297 | virtual llvm::Expected<std::unique_ptr<NativeProcessProtocol>> |
298 | Attach(lldb::pid_t pid, NativeDelegate &native_delegate, |
299 | MainLoop &mainloop) const = 0; |
300 | }; |
301 | |
302 | //------------------------------------------------------------------ |
303 | /// StartTracing API for starting a tracing instance with the |
304 | /// TraceOptions on a specific thread or process. |
305 | /// |
306 | /// @param[in] config |
307 | /// The configuration to use when starting tracing. |
308 | /// |
309 | /// @param[out] error |
310 | /// Status indicates what went wrong. |
311 | /// |
312 | /// @return |
313 | /// The API returns a user_id which can be used to get trace |
314 | /// data, trace configuration or stopping the trace instance. |
315 | /// The user_id is a key to identify and operate with a tracing |
316 | /// instance. It may refer to the complete process or a single |
317 | /// thread. |
318 | //------------------------------------------------------------------ |
319 | virtual lldb::user_id_t StartTrace(const TraceOptions &config, |
320 | Status &error) { |
321 | error.SetErrorString("Not implemented"); |
322 | return LLDB_INVALID_UID(18446744073709551615UL); |
323 | } |
324 | |
325 | //------------------------------------------------------------------ |
326 | /// StopTracing API as the name suggests stops a tracing instance. |
327 | /// |
328 | /// @param[in] traceid |
329 | /// The user id of the trace intended to be stopped. Now a |
330 | /// user_id may map to multiple threads in which case this API |
331 | /// could be used to stop the tracing for a specific thread by |
332 | /// supplying its thread id. |
333 | /// |
334 | /// @param[in] thread |
335 | /// Thread is needed when the complete process is being traced |
336 | /// and the user wishes to stop tracing on a particular thread. |
337 | /// |
338 | /// @return |
339 | /// Status indicating what went wrong. |
340 | //------------------------------------------------------------------ |
341 | virtual Status StopTrace(lldb::user_id_t traceid, |
342 | lldb::tid_t thread = LLDB_INVALID_THREAD_ID0) { |
343 | return Status("Not implemented"); |
344 | } |
345 | |
346 | //------------------------------------------------------------------ |
347 | /// This API provides the trace data collected in the form of raw |
348 | /// data. |
349 | /// |
350 | /// @param[in] traceid thread |
351 | /// The traceid and thread provide the context for the trace |
352 | /// instance. |
353 | /// |
354 | /// @param[in] buffer |
355 | /// The buffer provides the destination buffer where the trace |
356 | /// data would be read to. The buffer should be truncated to the |
357 | /// filled length by this function. |
358 | /// |
359 | /// @param[in] offset |
360 | /// There is possibility to read partially the trace data from |
361 | /// a specified offset where in such cases the buffer provided |
362 | /// may be smaller than the internal trace collection container. |
363 | /// |
364 | /// @return |
365 | /// The size of the data actually read. |
366 | //------------------------------------------------------------------ |
367 | virtual Status GetData(lldb::user_id_t traceid, lldb::tid_t thread, |
368 | llvm::MutableArrayRef<uint8_t> &buffer, |
369 | size_t offset = 0) { |
370 | return Status("Not implemented"); |
371 | } |
372 | |
373 | //------------------------------------------------------------------ |
374 | /// Similar API as above except it aims to provide any extra data |
375 | /// useful for decoding the actual trace data. |
376 | //------------------------------------------------------------------ |
377 | virtual Status GetMetaData(lldb::user_id_t traceid, lldb::tid_t thread, |
378 | llvm::MutableArrayRef<uint8_t> &buffer, |
379 | size_t offset = 0) { |
380 | return Status("Not implemented"); |
381 | } |
382 | |
383 | //------------------------------------------------------------------ |
384 | /// API to query the TraceOptions for a given user id |
385 | /// |
386 | /// @param[in] traceid |
387 | /// The user id of the tracing instance. |
388 | /// |
389 | /// @param[in] config |
390 | /// The thread id of the tracing instance, in case configuration |
391 | /// for a specific thread is needed should be specified in the |
392 | /// config. |
393 | /// |
394 | /// @param[out] error |
395 | /// Status indicates what went wrong. |
396 | /// |
397 | /// @param[out] config |
398 | /// The actual configuration being used for tracing. |
399 | //------------------------------------------------------------------ |
400 | virtual Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) { |
401 | return Status("Not implemented"); |
402 | } |
403 | |
404 | protected: |
405 | lldb::pid_t m_pid; |
406 | |
407 | std::vector<std::unique_ptr<NativeThreadProtocol>> m_threads; |
408 | lldb::tid_t m_current_thread_id = LLDB_INVALID_THREAD_ID0; |
409 | mutable std::recursive_mutex m_threads_mutex; |
410 | |
411 | lldb::StateType m_state = lldb::eStateInvalid; |
412 | mutable std::recursive_mutex m_state_mutex; |
413 | |
414 | llvm::Optional<WaitStatus> m_exit_status; |
415 | |
416 | std::recursive_mutex m_delegates_mutex; |
417 | std::vector<NativeDelegate *> m_delegates; |
418 | NativeBreakpointList m_breakpoint_list; |
419 | NativeWatchpointList m_watchpoint_list; |
420 | HardwareBreakpointMap m_hw_breakpoints_map; |
421 | int m_terminal_fd; |
422 | uint32_t m_stop_id = 0; |
423 | |
424 | // Set of signal numbers that LLDB directly injects back to inferior without |
425 | // stopping it. |
426 | llvm::DenseSet<int> m_signals_to_ignore; |
427 | |
428 | // lldb_private::Host calls should be used to launch a process for debugging, |
429 | // and then the process should be attached to. When attaching to a process |
430 | // lldb_private::Host calls should be used to locate the process to attach |
431 | // to, and then this function should be called. |
432 | NativeProcessProtocol(lldb::pid_t pid, int terminal_fd, |
433 | NativeDelegate &delegate); |
434 | |
435 | // ----------------------------------------------------------- Internal |
436 | // interface for state handling |
437 | // ----------------------------------------------------------- |
438 | void SetState(lldb::StateType state, bool notify_delegates = true); |
439 | |
440 | // Derived classes need not implement this. It can be used as a hook to |
441 | // clear internal caches that should be invalidated when stop ids change. |
442 | // |
443 | // Note this function is called with the state mutex obtained by the caller. |
444 | virtual void DoStopIDBumped(uint32_t newBumpId); |
445 | |
446 | // ----------------------------------------------------------- Internal |
447 | // interface for software breakpoints |
448 | // ----------------------------------------------------------- |
449 | Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint); |
450 | |
451 | virtual llvm::Expected<llvm::ArrayRef<uint8_t>> |
452 | GetSoftwareBreakpointTrapOpcode(size_t size_hint); |
453 | |
454 | /// Return the offset of the PC relative to the software breakpoint that was hit. If an |
455 | /// architecture (e.g. arm) reports breakpoint hits before incrementing the PC, this offset |
456 | /// will be 0. If an architecture (e.g. intel) reports breakpoints hits after incrementing the |
457 | /// PC, this offset will be the size of the breakpoint opcode. |
458 | virtual size_t GetSoftwareBreakpointPCOffset(); |
459 | |
460 | // Adjust the thread's PC after hitting a software breakpoint. On |
461 | // architectures where the PC points after the breakpoint instruction, this |
462 | // resets it to point to the breakpoint itself. |
463 | void FixupBreakpointPCAsNeeded(NativeThreadProtocol &thread); |
464 | |
465 | // ----------------------------------------------------------- |
466 | /// Notify the delegate that an exec occurred. |
467 | /// |
468 | /// Provide a mechanism for a delegate to clear out any exec- |
469 | /// sensitive data. |
470 | // ----------------------------------------------------------- |
471 | void NotifyDidExec(); |
472 | |
473 | NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid); |
474 | |
475 | private: |
476 | void SynchronouslyNotifyProcessStateChanged(lldb::StateType state); |
477 | }; |
478 | } // namespace lldb_private |
479 | |
480 | #endif // #ifndef liblldb_NativeProcessProtocol_h_ |