/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/API/SBProcess.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- SBProcess.cpp -----------------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "lldb/API/SBProcess.h" |
10 | | #include "lldb/Utility/Instrumentation.h" |
11 | | |
12 | | #include <cinttypes> |
13 | | |
14 | | #include "lldb/lldb-defines.h" |
15 | | #include "lldb/lldb-types.h" |
16 | | |
17 | | #include "lldb/Core/Debugger.h" |
18 | | #include "lldb/Core/Module.h" |
19 | | #include "lldb/Core/PluginManager.h" |
20 | | #include "lldb/Core/StructuredDataImpl.h" |
21 | | #include "lldb/Host/StreamFile.h" |
22 | | #include "lldb/Target/MemoryRegionInfo.h" |
23 | | #include "lldb/Target/Process.h" |
24 | | #include "lldb/Target/RegisterContext.h" |
25 | | #include "lldb/Target/SystemRuntime.h" |
26 | | #include "lldb/Target/Target.h" |
27 | | #include "lldb/Target/Thread.h" |
28 | | #include "lldb/Utility/Args.h" |
29 | | #include "lldb/Utility/ProcessInfo.h" |
30 | | #include "lldb/Utility/State.h" |
31 | | #include "lldb/Utility/Stream.h" |
32 | | |
33 | | #include "lldb/API/SBBroadcaster.h" |
34 | | #include "lldb/API/SBCommandReturnObject.h" |
35 | | #include "lldb/API/SBDebugger.h" |
36 | | #include "lldb/API/SBEvent.h" |
37 | | #include "lldb/API/SBFile.h" |
38 | | #include "lldb/API/SBFileSpec.h" |
39 | | #include "lldb/API/SBMemoryRegionInfo.h" |
40 | | #include "lldb/API/SBMemoryRegionInfoList.h" |
41 | | #include "lldb/API/SBScriptObject.h" |
42 | | #include "lldb/API/SBStream.h" |
43 | | #include "lldb/API/SBStringList.h" |
44 | | #include "lldb/API/SBStructuredData.h" |
45 | | #include "lldb/API/SBThread.h" |
46 | | #include "lldb/API/SBThreadCollection.h" |
47 | | #include "lldb/API/SBTrace.h" |
48 | | #include "lldb/API/SBUnixSignals.h" |
49 | | |
50 | | using namespace lldb; |
51 | | using namespace lldb_private; |
52 | | |
53 | 23.5k | SBProcess::SBProcess() { LLDB_INSTRUMENT_VA(this); } |
54 | | |
55 | | // SBProcess constructor |
56 | | |
57 | 11.6k | SBProcess::SBProcess(const SBProcess &rhs) : m_opaque_wp(rhs.m_opaque_wp) { |
58 | 11.6k | LLDB_INSTRUMENT_VA(this, rhs); |
59 | 11.6k | } |
60 | | |
61 | | SBProcess::SBProcess(const lldb::ProcessSP &process_sp) |
62 | 16 | : m_opaque_wp(process_sp) { |
63 | 16 | LLDB_INSTRUMENT_VA(this, process_sp); |
64 | 16 | } |
65 | | |
66 | 11.6k | const SBProcess &SBProcess::operator=(const SBProcess &rhs) { |
67 | 11.6k | LLDB_INSTRUMENT_VA(this, rhs); |
68 | | |
69 | 11.6k | if (this != &rhs) |
70 | 11.6k | m_opaque_wp = rhs.m_opaque_wp; |
71 | 11.6k | return *this; |
72 | 11.6k | } |
73 | | |
74 | | // Destructor |
75 | 35.2k | SBProcess::~SBProcess() = default; |
76 | | |
77 | 2 | const char *SBProcess::GetBroadcasterClassName() { |
78 | 2 | LLDB_INSTRUMENT(); |
79 | | |
80 | 2 | return Process::GetStaticBroadcasterClass().AsCString(); |
81 | 2 | } |
82 | | |
83 | 0 | const char *SBProcess::GetPluginName() { |
84 | 0 | LLDB_INSTRUMENT_VA(this); |
85 | |
|
86 | 0 | ProcessSP process_sp(GetSP()); |
87 | 0 | if (process_sp) { |
88 | 0 | return ConstString(process_sp->GetPluginName()).GetCString(); |
89 | 0 | } |
90 | 0 | return "<Unknown>"; |
91 | 0 | } |
92 | | |
93 | 0 | const char *SBProcess::GetShortPluginName() { |
94 | 0 | LLDB_INSTRUMENT_VA(this); |
95 | |
|
96 | 0 | ProcessSP process_sp(GetSP()); |
97 | 0 | if (process_sp) { |
98 | 0 | return ConstString(process_sp->GetPluginName()).GetCString(); |
99 | 0 | } |
100 | 0 | return "<Unknown>"; |
101 | 0 | } |
102 | | |
103 | 37.3k | lldb::ProcessSP SBProcess::GetSP() const { return m_opaque_wp.lock(); } |
104 | | |
105 | 11.6k | void SBProcess::SetSP(const ProcessSP &process_sp) { m_opaque_wp = process_sp; } |
106 | | |
107 | 1 | void SBProcess::Clear() { |
108 | 1 | LLDB_INSTRUMENT_VA(this); |
109 | | |
110 | 1 | m_opaque_wp.reset(); |
111 | 1 | } |
112 | | |
113 | 77 | bool SBProcess::IsValid() const { |
114 | 77 | LLDB_INSTRUMENT_VA(this); |
115 | 77 | return this->operator bool(); |
116 | 77 | } |
117 | 4.02k | SBProcess::operator bool() const { |
118 | 4.02k | LLDB_INSTRUMENT_VA(this); |
119 | | |
120 | 4.02k | ProcessSP process_sp(m_opaque_wp.lock()); |
121 | 4.02k | return ((bool)process_sp && process_sp->IsValid()3.64k ); |
122 | 4.02k | } |
123 | | |
124 | | bool SBProcess::RemoteLaunch(char const **argv, char const **envp, |
125 | | const char *stdin_path, const char *stdout_path, |
126 | | const char *stderr_path, |
127 | | const char *working_directory, |
128 | | uint32_t launch_flags, bool stop_at_entry, |
129 | 3 | lldb::SBError &error) { |
130 | 3 | LLDB_INSTRUMENT_VA(this, argv, envp, stdin_path, stdout_path, stderr_path, |
131 | 3 | working_directory, launch_flags, stop_at_entry, error); |
132 | | |
133 | 3 | ProcessSP process_sp(GetSP()); |
134 | 3 | if (process_sp) { |
135 | 2 | std::lock_guard<std::recursive_mutex> guard( |
136 | 2 | process_sp->GetTarget().GetAPIMutex()); |
137 | 2 | if (process_sp->GetState() == eStateConnected) { |
138 | 0 | if (stop_at_entry) |
139 | 0 | launch_flags |= eLaunchFlagStopAtEntry; |
140 | 0 | ProcessLaunchInfo launch_info(FileSpec(stdin_path), FileSpec(stdout_path), |
141 | 0 | FileSpec(stderr_path), |
142 | 0 | FileSpec(working_directory), launch_flags); |
143 | 0 | Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer(); |
144 | 0 | if (exe_module) |
145 | 0 | launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); |
146 | 0 | if (argv) |
147 | 0 | launch_info.GetArguments().AppendArguments(argv); |
148 | 0 | if (envp) |
149 | 0 | launch_info.GetEnvironment() = Environment(envp); |
150 | 0 | error.SetError(process_sp->Launch(launch_info)); |
151 | 2 | } else { |
152 | 2 | error.SetErrorString("must be in eStateConnected to call RemoteLaunch"); |
153 | 2 | } |
154 | 2 | } else { |
155 | 1 | error.SetErrorString("unable to attach pid"); |
156 | 1 | } |
157 | | |
158 | 3 | return error.Success(); |
159 | 3 | } |
160 | | |
161 | | bool SBProcess::RemoteAttachToProcessWithID(lldb::pid_t pid, |
162 | 1 | lldb::SBError &error) { |
163 | 1 | LLDB_INSTRUMENT_VA(this, pid, error); |
164 | | |
165 | 1 | ProcessSP process_sp(GetSP()); |
166 | 1 | if (process_sp) { |
167 | 0 | std::lock_guard<std::recursive_mutex> guard( |
168 | 0 | process_sp->GetTarget().GetAPIMutex()); |
169 | 0 | if (process_sp->GetState() == eStateConnected) { |
170 | 0 | ProcessAttachInfo attach_info; |
171 | 0 | attach_info.SetProcessID(pid); |
172 | 0 | error.SetError(process_sp->Attach(attach_info)); |
173 | 0 | } else { |
174 | 0 | error.SetErrorString( |
175 | 0 | "must be in eStateConnected to call RemoteAttachToProcessWithID"); |
176 | 0 | } |
177 | 1 | } else { |
178 | 1 | error.SetErrorString("unable to attach pid"); |
179 | 1 | } |
180 | | |
181 | 1 | return error.Success(); |
182 | 1 | } |
183 | | |
184 | 7.15k | uint32_t SBProcess::GetNumThreads() { |
185 | 7.15k | LLDB_INSTRUMENT_VA(this); |
186 | | |
187 | 7.15k | uint32_t num_threads = 0; |
188 | 7.15k | ProcessSP process_sp(GetSP()); |
189 | 7.15k | if (process_sp) { |
190 | 7.14k | Process::StopLocker stop_locker; |
191 | | |
192 | 7.14k | const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); |
193 | 7.14k | std::lock_guard<std::recursive_mutex> guard( |
194 | 7.14k | process_sp->GetTarget().GetAPIMutex()); |
195 | 7.14k | num_threads = process_sp->GetThreadList().GetSize(can_update); |
196 | 7.14k | } |
197 | | |
198 | 7.15k | return num_threads; |
199 | 7.15k | } |
200 | | |
201 | 7.12k | SBThread SBProcess::GetSelectedThread() const { |
202 | 7.12k | LLDB_INSTRUMENT_VA(this); |
203 | | |
204 | 7.12k | SBThread sb_thread; |
205 | 7.12k | ThreadSP thread_sp; |
206 | 7.12k | ProcessSP process_sp(GetSP()); |
207 | 7.12k | if (process_sp) { |
208 | 6.63k | std::lock_guard<std::recursive_mutex> guard( |
209 | 6.63k | process_sp->GetTarget().GetAPIMutex()); |
210 | 6.63k | thread_sp = process_sp->GetThreadList().GetSelectedThread(); |
211 | 6.63k | sb_thread.SetThread(thread_sp); |
212 | 6.63k | } |
213 | | |
214 | 7.12k | return sb_thread; |
215 | 7.12k | } |
216 | | |
217 | | SBThread SBProcess::CreateOSPluginThread(lldb::tid_t tid, |
218 | 0 | lldb::addr_t context) { |
219 | 0 | LLDB_INSTRUMENT_VA(this, tid, context); |
220 | |
|
221 | 0 | SBThread sb_thread; |
222 | 0 | ThreadSP thread_sp; |
223 | 0 | ProcessSP process_sp(GetSP()); |
224 | 0 | if (process_sp) { |
225 | 0 | std::lock_guard<std::recursive_mutex> guard( |
226 | 0 | process_sp->GetTarget().GetAPIMutex()); |
227 | 0 | thread_sp = process_sp->CreateOSPluginThread(tid, context); |
228 | 0 | sb_thread.SetThread(thread_sp); |
229 | 0 | } |
230 | |
|
231 | 0 | return sb_thread; |
232 | 0 | } |
233 | | |
234 | 4.32k | SBTarget SBProcess::GetTarget() const { |
235 | 4.32k | LLDB_INSTRUMENT_VA(this); |
236 | | |
237 | 4.32k | SBTarget sb_target; |
238 | 4.32k | TargetSP target_sp; |
239 | 4.32k | ProcessSP process_sp(GetSP()); |
240 | 4.32k | if (process_sp) { |
241 | 4.31k | target_sp = process_sp->GetTarget().shared_from_this(); |
242 | 4.31k | sb_target.SetSP(target_sp); |
243 | 4.31k | } |
244 | | |
245 | 4.32k | return sb_target; |
246 | 4.32k | } |
247 | | |
248 | 14 | size_t SBProcess::PutSTDIN(const char *src, size_t src_len) { |
249 | 14 | LLDB_INSTRUMENT_VA(this, src, src_len); |
250 | | |
251 | 14 | size_t ret_val = 0; |
252 | 14 | ProcessSP process_sp(GetSP()); |
253 | 14 | if (process_sp) { |
254 | 13 | Status error; |
255 | 13 | ret_val = process_sp->PutSTDIN(src, src_len, error); |
256 | 13 | } |
257 | | |
258 | 14 | return ret_val; |
259 | 14 | } |
260 | | |
261 | 29 | size_t SBProcess::GetSTDOUT(char *dst, size_t dst_len) const { |
262 | 29 | LLDB_INSTRUMENT_VA(this, dst, dst_len); |
263 | | |
264 | 29 | size_t bytes_read = 0; |
265 | 29 | ProcessSP process_sp(GetSP()); |
266 | 29 | if (process_sp) { |
267 | 28 | Status error; |
268 | 28 | bytes_read = process_sp->GetSTDOUT(dst, dst_len, error); |
269 | 28 | } |
270 | | |
271 | 29 | return bytes_read; |
272 | 29 | } |
273 | | |
274 | 5 | size_t SBProcess::GetSTDERR(char *dst, size_t dst_len) const { |
275 | 5 | LLDB_INSTRUMENT_VA(this, dst, dst_len); |
276 | | |
277 | 5 | size_t bytes_read = 0; |
278 | 5 | ProcessSP process_sp(GetSP()); |
279 | 5 | if (process_sp) { |
280 | 4 | Status error; |
281 | 4 | bytes_read = process_sp->GetSTDERR(dst, dst_len, error); |
282 | 4 | } |
283 | | |
284 | 5 | return bytes_read; |
285 | 5 | } |
286 | | |
287 | 0 | size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const { |
288 | 0 | LLDB_INSTRUMENT_VA(this, dst, dst_len); |
289 | |
|
290 | 0 | size_t bytes_read = 0; |
291 | 0 | ProcessSP process_sp(GetSP()); |
292 | 0 | if (process_sp) { |
293 | 0 | Status error; |
294 | 0 | bytes_read = process_sp->GetAsyncProfileData(dst, dst_len, error); |
295 | 0 | } |
296 | |
|
297 | 0 | return bytes_read; |
298 | 0 | } |
299 | | |
300 | 0 | void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const { |
301 | 0 | LLDB_INSTRUMENT_VA(this, event, out); |
302 | |
|
303 | 0 | return ReportEventState(event, out.m_opaque_sp); |
304 | 0 | } |
305 | | |
306 | 0 | void SBProcess::ReportEventState(const SBEvent &event, FILE *out) const { |
307 | 0 | LLDB_INSTRUMENT_VA(this, event, out); |
308 | 0 | FileSP outfile = std::make_shared<NativeFile>(out, false); |
309 | 0 | return ReportEventState(event, outfile); |
310 | 0 | } |
311 | | |
312 | 0 | void SBProcess::ReportEventState(const SBEvent &event, FileSP out) const { |
313 | |
|
314 | 0 | LLDB_INSTRUMENT_VA(this, event, out); |
315 | |
|
316 | 0 | if (!out || !out->IsValid()) |
317 | 0 | return; |
318 | | |
319 | 0 | ProcessSP process_sp(GetSP()); |
320 | 0 | if (process_sp) { |
321 | 0 | StreamFile stream(out); |
322 | 0 | const StateType event_state = SBProcess::GetStateFromEvent(event); |
323 | 0 | stream.Printf("Process %" PRIu64 " %s\n", |
324 | 0 | process_sp->GetID(), SBDebugger::StateAsCString(event_state)); |
325 | 0 | } |
326 | 0 | } |
327 | | |
328 | | void SBProcess::AppendEventStateReport(const SBEvent &event, |
329 | 1 | SBCommandReturnObject &result) { |
330 | 1 | LLDB_INSTRUMENT_VA(this, event, result); |
331 | | |
332 | 1 | ProcessSP process_sp(GetSP()); |
333 | 1 | if (process_sp) { |
334 | 0 | const StateType event_state = SBProcess::GetStateFromEvent(event); |
335 | 0 | char message[1024]; |
336 | 0 | ::snprintf(message, sizeof(message), "Process %" PRIu64 " %s\n", |
337 | 0 | process_sp->GetID(), SBDebugger::StateAsCString(event_state)); |
338 | |
|
339 | 0 | result.AppendMessage(message); |
340 | 0 | } |
341 | 1 | } |
342 | | |
343 | 3 | bool SBProcess::SetSelectedThread(const SBThread &thread) { |
344 | 3 | LLDB_INSTRUMENT_VA(this, thread); |
345 | | |
346 | 3 | ProcessSP process_sp(GetSP()); |
347 | 3 | if (process_sp) { |
348 | 2 | std::lock_guard<std::recursive_mutex> guard( |
349 | 2 | process_sp->GetTarget().GetAPIMutex()); |
350 | 2 | return process_sp->GetThreadList().SetSelectedThreadByID( |
351 | 2 | thread.GetThreadID()); |
352 | 2 | } |
353 | 1 | return false; |
354 | 3 | } |
355 | | |
356 | 1 | bool SBProcess::SetSelectedThreadByID(lldb::tid_t tid) { |
357 | 1 | LLDB_INSTRUMENT_VA(this, tid); |
358 | | |
359 | 1 | bool ret_val = false; |
360 | 1 | ProcessSP process_sp(GetSP()); |
361 | 1 | if (process_sp) { |
362 | 0 | std::lock_guard<std::recursive_mutex> guard( |
363 | 0 | process_sp->GetTarget().GetAPIMutex()); |
364 | 0 | ret_val = process_sp->GetThreadList().SetSelectedThreadByID(tid); |
365 | 0 | } |
366 | | |
367 | 1 | return ret_val; |
368 | 1 | } |
369 | | |
370 | 1 | bool SBProcess::SetSelectedThreadByIndexID(uint32_t index_id) { |
371 | 1 | LLDB_INSTRUMENT_VA(this, index_id); |
372 | | |
373 | 1 | bool ret_val = false; |
374 | 1 | ProcessSP process_sp(GetSP()); |
375 | 1 | if (process_sp) { |
376 | 1 | std::lock_guard<std::recursive_mutex> guard( |
377 | 1 | process_sp->GetTarget().GetAPIMutex()); |
378 | 1 | ret_val = process_sp->GetThreadList().SetSelectedThreadByIndexID(index_id); |
379 | 1 | } |
380 | | |
381 | | |
382 | 1 | return ret_val; |
383 | 1 | } |
384 | | |
385 | 3.40k | SBThread SBProcess::GetThreadAtIndex(size_t index) { |
386 | 3.40k | LLDB_INSTRUMENT_VA(this, index); |
387 | | |
388 | 3.40k | SBThread sb_thread; |
389 | 3.40k | ThreadSP thread_sp; |
390 | 3.40k | ProcessSP process_sp(GetSP()); |
391 | 3.40k | if (process_sp) { |
392 | 3.40k | Process::StopLocker stop_locker; |
393 | 3.40k | const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); |
394 | 3.40k | std::lock_guard<std::recursive_mutex> guard( |
395 | 3.40k | process_sp->GetTarget().GetAPIMutex()); |
396 | 3.40k | thread_sp = process_sp->GetThreadList().GetThreadAtIndex(index, can_update); |
397 | 3.40k | sb_thread.SetThread(thread_sp); |
398 | 3.40k | } |
399 | | |
400 | 3.40k | return sb_thread; |
401 | 3.40k | } |
402 | | |
403 | 4 | uint32_t SBProcess::GetNumQueues() { |
404 | 4 | LLDB_INSTRUMENT_VA(this); |
405 | | |
406 | 4 | uint32_t num_queues = 0; |
407 | 4 | ProcessSP process_sp(GetSP()); |
408 | 4 | if (process_sp) { |
409 | 4 | Process::StopLocker stop_locker; |
410 | 4 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
411 | 4 | std::lock_guard<std::recursive_mutex> guard( |
412 | 4 | process_sp->GetTarget().GetAPIMutex()); |
413 | 4 | num_queues = process_sp->GetQueueList().GetSize(); |
414 | 4 | } |
415 | 4 | } |
416 | | |
417 | 4 | return num_queues; |
418 | 4 | } |
419 | | |
420 | 40 | SBQueue SBProcess::GetQueueAtIndex(size_t index) { |
421 | 40 | LLDB_INSTRUMENT_VA(this, index); |
422 | | |
423 | 40 | SBQueue sb_queue; |
424 | 40 | QueueSP queue_sp; |
425 | 40 | ProcessSP process_sp(GetSP()); |
426 | 40 | if (process_sp) { |
427 | 40 | Process::StopLocker stop_locker; |
428 | 40 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
429 | 40 | std::lock_guard<std::recursive_mutex> guard( |
430 | 40 | process_sp->GetTarget().GetAPIMutex()); |
431 | 40 | queue_sp = process_sp->GetQueueList().GetQueueAtIndex(index); |
432 | 40 | sb_queue.SetQueue(queue_sp); |
433 | 40 | } |
434 | 40 | } |
435 | | |
436 | 40 | return sb_queue; |
437 | 40 | } |
438 | | |
439 | 14 | uint32_t SBProcess::GetStopID(bool include_expression_stops) { |
440 | 14 | LLDB_INSTRUMENT_VA(this, include_expression_stops); |
441 | | |
442 | 14 | ProcessSP process_sp(GetSP()); |
443 | 14 | if (process_sp) { |
444 | 14 | std::lock_guard<std::recursive_mutex> guard( |
445 | 14 | process_sp->GetTarget().GetAPIMutex()); |
446 | 14 | if (include_expression_stops) |
447 | 4 | return process_sp->GetStopID(); |
448 | 10 | else |
449 | 10 | return process_sp->GetLastNaturalStopID(); |
450 | 14 | } |
451 | 0 | return 0; |
452 | 14 | } |
453 | | |
454 | 0 | SBEvent SBProcess::GetStopEventForStopID(uint32_t stop_id) { |
455 | 0 | LLDB_INSTRUMENT_VA(this, stop_id); |
456 | |
|
457 | 0 | SBEvent sb_event; |
458 | 0 | EventSP event_sp; |
459 | 0 | ProcessSP process_sp(GetSP()); |
460 | 0 | if (process_sp) { |
461 | 0 | std::lock_guard<std::recursive_mutex> guard( |
462 | 0 | process_sp->GetTarget().GetAPIMutex()); |
463 | 0 | event_sp = process_sp->GetStopEventForStopID(stop_id); |
464 | 0 | sb_event.reset(event_sp); |
465 | 0 | } |
466 | |
|
467 | 0 | return sb_event; |
468 | 0 | } |
469 | | |
470 | 4 | void SBProcess::ForceScriptedState(StateType new_state) { |
471 | 4 | LLDB_INSTRUMENT_VA(this, new_state); |
472 | | |
473 | 4 | if (ProcessSP process_sp = GetSP()) { |
474 | 4 | std::lock_guard<std::recursive_mutex> guard( |
475 | 4 | process_sp->GetTarget().GetAPIMutex()); |
476 | 4 | process_sp->ForceScriptedState(new_state); |
477 | 4 | } |
478 | 4 | } |
479 | | |
480 | 6.23k | StateType SBProcess::GetState() { |
481 | 6.23k | LLDB_INSTRUMENT_VA(this); |
482 | | |
483 | 6.23k | StateType ret_val = eStateInvalid; |
484 | 6.23k | ProcessSP process_sp(GetSP()); |
485 | 6.23k | if (process_sp) { |
486 | 6.23k | std::lock_guard<std::recursive_mutex> guard( |
487 | 6.23k | process_sp->GetTarget().GetAPIMutex()); |
488 | 6.23k | ret_val = process_sp->GetState(); |
489 | 6.23k | } |
490 | | |
491 | 6.23k | return ret_val; |
492 | 6.23k | } |
493 | | |
494 | 29 | int SBProcess::GetExitStatus() { |
495 | 29 | LLDB_INSTRUMENT_VA(this); |
496 | | |
497 | 29 | int exit_status = 0; |
498 | 29 | ProcessSP process_sp(GetSP()); |
499 | 29 | if (process_sp) { |
500 | 28 | std::lock_guard<std::recursive_mutex> guard( |
501 | 28 | process_sp->GetTarget().GetAPIMutex()); |
502 | 28 | exit_status = process_sp->GetExitStatus(); |
503 | 28 | } |
504 | | |
505 | 29 | return exit_status; |
506 | 29 | } |
507 | | |
508 | 2 | const char *SBProcess::GetExitDescription() { |
509 | 2 | LLDB_INSTRUMENT_VA(this); |
510 | | |
511 | 2 | ProcessSP process_sp(GetSP()); |
512 | 2 | if (!process_sp) |
513 | 1 | return nullptr; |
514 | | |
515 | 1 | std::lock_guard<std::recursive_mutex> guard( |
516 | 1 | process_sp->GetTarget().GetAPIMutex()); |
517 | 1 | return ConstString(process_sp->GetExitDescription()).GetCString(); |
518 | 2 | } |
519 | | |
520 | 51 | lldb::pid_t SBProcess::GetProcessID() { |
521 | 51 | LLDB_INSTRUMENT_VA(this); |
522 | | |
523 | 51 | lldb::pid_t ret_val = LLDB_INVALID_PROCESS_ID; |
524 | 51 | ProcessSP process_sp(GetSP()); |
525 | 51 | if (process_sp) |
526 | 50 | ret_val = process_sp->GetID(); |
527 | | |
528 | 51 | return ret_val; |
529 | 51 | } |
530 | | |
531 | 0 | uint32_t SBProcess::GetUniqueID() { |
532 | 0 | LLDB_INSTRUMENT_VA(this); |
533 | |
|
534 | 0 | uint32_t ret_val = 0; |
535 | 0 | ProcessSP process_sp(GetSP()); |
536 | 0 | if (process_sp) |
537 | 0 | ret_val = process_sp->GetUniqueID(); |
538 | 0 | return ret_val; |
539 | 0 | } |
540 | | |
541 | 56 | ByteOrder SBProcess::GetByteOrder() const { |
542 | 56 | LLDB_INSTRUMENT_VA(this); |
543 | | |
544 | 56 | ByteOrder byteOrder = eByteOrderInvalid; |
545 | 56 | ProcessSP process_sp(GetSP()); |
546 | 56 | if (process_sp) |
547 | 55 | byteOrder = process_sp->GetTarget().GetArchitecture().GetByteOrder(); |
548 | | |
549 | | |
550 | 56 | return byteOrder; |
551 | 56 | } |
552 | | |
553 | 90 | uint32_t SBProcess::GetAddressByteSize() const { |
554 | 90 | LLDB_INSTRUMENT_VA(this); |
555 | | |
556 | 90 | uint32_t size = 0; |
557 | 90 | ProcessSP process_sp(GetSP()); |
558 | 90 | if (process_sp) |
559 | 89 | size = process_sp->GetTarget().GetArchitecture().GetAddressByteSize(); |
560 | | |
561 | | |
562 | 90 | return size; |
563 | 90 | } |
564 | | |
565 | 937 | SBError SBProcess::Continue() { |
566 | 937 | LLDB_INSTRUMENT_VA(this); |
567 | | |
568 | 937 | SBError sb_error; |
569 | 937 | ProcessSP process_sp(GetSP()); |
570 | | |
571 | 937 | if (process_sp) { |
572 | 936 | std::lock_guard<std::recursive_mutex> guard( |
573 | 936 | process_sp->GetTarget().GetAPIMutex()); |
574 | | |
575 | 936 | if (process_sp->GetTarget().GetDebugger().GetAsyncExecution()) |
576 | 12 | sb_error.ref() = process_sp->Resume(); |
577 | 924 | else |
578 | 924 | sb_error.ref() = process_sp->ResumeSynchronous(nullptr); |
579 | 936 | } else |
580 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
581 | | |
582 | 937 | return sb_error; |
583 | 937 | } |
584 | | |
585 | 30 | SBError SBProcess::Destroy() { |
586 | 30 | LLDB_INSTRUMENT_VA(this); |
587 | | |
588 | 30 | SBError sb_error; |
589 | 30 | ProcessSP process_sp(GetSP()); |
590 | 30 | if (process_sp) { |
591 | 25 | std::lock_guard<std::recursive_mutex> guard( |
592 | 25 | process_sp->GetTarget().GetAPIMutex()); |
593 | 25 | sb_error.SetError(process_sp->Destroy(false)); |
594 | 25 | } else |
595 | 5 | sb_error.SetErrorString("SBProcess is invalid"); |
596 | | |
597 | 30 | return sb_error; |
598 | 30 | } |
599 | | |
600 | 1 | SBError SBProcess::Stop() { |
601 | 1 | LLDB_INSTRUMENT_VA(this); |
602 | | |
603 | 1 | SBError sb_error; |
604 | 1 | ProcessSP process_sp(GetSP()); |
605 | 1 | if (process_sp) { |
606 | 0 | std::lock_guard<std::recursive_mutex> guard( |
607 | 0 | process_sp->GetTarget().GetAPIMutex()); |
608 | 0 | sb_error.SetError(process_sp->Halt()); |
609 | 0 | } else |
610 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
611 | | |
612 | 1 | return sb_error; |
613 | 1 | } |
614 | | |
615 | 2.25k | SBError SBProcess::Kill() { |
616 | 2.25k | LLDB_INSTRUMENT_VA(this); |
617 | | |
618 | 2.25k | SBError sb_error; |
619 | 2.25k | ProcessSP process_sp(GetSP()); |
620 | 2.25k | if (process_sp) { |
621 | 2.24k | std::lock_guard<std::recursive_mutex> guard( |
622 | 2.24k | process_sp->GetTarget().GetAPIMutex()); |
623 | 2.24k | sb_error.SetError(process_sp->Destroy(true)); |
624 | 2.24k | } else |
625 | 17 | sb_error.SetErrorString("SBProcess is invalid"); |
626 | | |
627 | 2.25k | return sb_error; |
628 | 2.25k | } |
629 | | |
630 | 3 | SBError SBProcess::Detach() { |
631 | 3 | LLDB_INSTRUMENT_VA(this); |
632 | | |
633 | | // FIXME: This should come from a process default. |
634 | 3 | bool keep_stopped = false; |
635 | 3 | return Detach(keep_stopped); |
636 | 3 | } |
637 | | |
638 | 3 | SBError SBProcess::Detach(bool keep_stopped) { |
639 | 3 | LLDB_INSTRUMENT_VA(this, keep_stopped); |
640 | | |
641 | 3 | SBError sb_error; |
642 | 3 | ProcessSP process_sp(GetSP()); |
643 | 3 | if (process_sp) { |
644 | 2 | std::lock_guard<std::recursive_mutex> guard( |
645 | 2 | process_sp->GetTarget().GetAPIMutex()); |
646 | 2 | sb_error.SetError(process_sp->Detach(keep_stopped)); |
647 | 2 | } else |
648 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
649 | | |
650 | 3 | return sb_error; |
651 | 3 | } |
652 | | |
653 | 3 | SBError SBProcess::Signal(int signo) { |
654 | 3 | LLDB_INSTRUMENT_VA(this, signo); |
655 | | |
656 | 3 | SBError sb_error; |
657 | 3 | ProcessSP process_sp(GetSP()); |
658 | 3 | if (process_sp) { |
659 | 2 | std::lock_guard<std::recursive_mutex> guard( |
660 | 2 | process_sp->GetTarget().GetAPIMutex()); |
661 | 2 | sb_error.SetError(process_sp->Signal(signo)); |
662 | 2 | } else |
663 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
664 | | |
665 | 3 | return sb_error; |
666 | 3 | } |
667 | | |
668 | 23 | SBUnixSignals SBProcess::GetUnixSignals() { |
669 | 23 | LLDB_INSTRUMENT_VA(this); |
670 | | |
671 | 23 | if (auto process_sp = GetSP()) |
672 | 23 | return SBUnixSignals{process_sp}; |
673 | | |
674 | 0 | return SBUnixSignals{}; |
675 | 23 | } |
676 | | |
677 | 4 | void SBProcess::SendAsyncInterrupt() { |
678 | 4 | LLDB_INSTRUMENT_VA(this); |
679 | | |
680 | 4 | ProcessSP process_sp(GetSP()); |
681 | 4 | if (process_sp) { |
682 | 4 | process_sp->SendAsyncInterrupt(); |
683 | 4 | } |
684 | 4 | } |
685 | | |
686 | 37 | SBThread SBProcess::GetThreadByID(tid_t tid) { |
687 | 37 | LLDB_INSTRUMENT_VA(this, tid); |
688 | | |
689 | 37 | SBThread sb_thread; |
690 | 37 | ThreadSP thread_sp; |
691 | 37 | ProcessSP process_sp(GetSP()); |
692 | 37 | if (process_sp) { |
693 | 36 | Process::StopLocker stop_locker; |
694 | 36 | const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); |
695 | 36 | std::lock_guard<std::recursive_mutex> guard( |
696 | 36 | process_sp->GetTarget().GetAPIMutex()); |
697 | 36 | thread_sp = process_sp->GetThreadList().FindThreadByID(tid, can_update); |
698 | 36 | sb_thread.SetThread(thread_sp); |
699 | 36 | } |
700 | | |
701 | 37 | return sb_thread; |
702 | 37 | } |
703 | | |
704 | 0 | SBThread SBProcess::GetThreadByIndexID(uint32_t index_id) { |
705 | 0 | LLDB_INSTRUMENT_VA(this, index_id); |
706 | |
|
707 | 0 | SBThread sb_thread; |
708 | 0 | ThreadSP thread_sp; |
709 | 0 | ProcessSP process_sp(GetSP()); |
710 | 0 | if (process_sp) { |
711 | 0 | Process::StopLocker stop_locker; |
712 | 0 | const bool can_update = stop_locker.TryLock(&process_sp->GetRunLock()); |
713 | 0 | std::lock_guard<std::recursive_mutex> guard( |
714 | 0 | process_sp->GetTarget().GetAPIMutex()); |
715 | 0 | thread_sp = |
716 | 0 | process_sp->GetThreadList().FindThreadByIndexID(index_id, can_update); |
717 | 0 | sb_thread.SetThread(thread_sp); |
718 | 0 | } |
719 | |
|
720 | 0 | return sb_thread; |
721 | 0 | } |
722 | | |
723 | 217 | StateType SBProcess::GetStateFromEvent(const SBEvent &event) { |
724 | 217 | LLDB_INSTRUMENT_VA(event); |
725 | | |
726 | 217 | StateType ret_val = Process::ProcessEventData::GetStateFromEvent(event.get()); |
727 | | |
728 | 217 | return ret_val; |
729 | 217 | } |
730 | | |
731 | 74 | bool SBProcess::GetRestartedFromEvent(const SBEvent &event) { |
732 | 74 | LLDB_INSTRUMENT_VA(event); |
733 | | |
734 | 74 | bool ret_val = Process::ProcessEventData::GetRestartedFromEvent(event.get()); |
735 | | |
736 | 74 | return ret_val; |
737 | 74 | } |
738 | | |
739 | 0 | size_t SBProcess::GetNumRestartedReasonsFromEvent(const lldb::SBEvent &event) { |
740 | 0 | LLDB_INSTRUMENT_VA(event); |
741 | |
|
742 | 0 | return Process::ProcessEventData::GetNumRestartedReasons(event.get()); |
743 | 0 | } |
744 | | |
745 | | const char * |
746 | | SBProcess::GetRestartedReasonAtIndexFromEvent(const lldb::SBEvent &event, |
747 | 0 | size_t idx) { |
748 | 0 | LLDB_INSTRUMENT_VA(event, idx); |
749 | |
|
750 | 0 | return ConstString(Process::ProcessEventData::GetRestartedReasonAtIndex( |
751 | 0 | event.get(), idx)) |
752 | 0 | .GetCString(); |
753 | 0 | } |
754 | | |
755 | 5 | SBProcess SBProcess::GetProcessFromEvent(const SBEvent &event) { |
756 | 5 | LLDB_INSTRUMENT_VA(event); |
757 | | |
758 | 5 | ProcessSP process_sp = |
759 | 5 | Process::ProcessEventData::GetProcessFromEvent(event.get()); |
760 | 5 | if (!process_sp) { |
761 | | // StructuredData events also know the process they come from. Try that. |
762 | 0 | process_sp = EventDataStructuredData::GetProcessFromEvent(event.get()); |
763 | 0 | } |
764 | | |
765 | 5 | return SBProcess(process_sp); |
766 | 5 | } |
767 | | |
768 | 0 | bool SBProcess::GetInterruptedFromEvent(const SBEvent &event) { |
769 | 0 | LLDB_INSTRUMENT_VA(event); |
770 | |
|
771 | 0 | return Process::ProcessEventData::GetInterruptedFromEvent(event.get()); |
772 | 0 | } |
773 | | |
774 | | lldb::SBStructuredData |
775 | 0 | SBProcess::GetStructuredDataFromEvent(const lldb::SBEvent &event) { |
776 | 0 | LLDB_INSTRUMENT_VA(event); |
777 | |
|
778 | 0 | return SBStructuredData(event.GetSP()); |
779 | 0 | } |
780 | | |
781 | 0 | bool SBProcess::EventIsProcessEvent(const SBEvent &event) { |
782 | 0 | LLDB_INSTRUMENT_VA(event); |
783 | |
|
784 | 0 | return Process::ProcessEventData::GetEventDataFromEvent(event.get()) != |
785 | 0 | nullptr; |
786 | 0 | } |
787 | | |
788 | 0 | bool SBProcess::EventIsStructuredDataEvent(const lldb::SBEvent &event) { |
789 | 0 | LLDB_INSTRUMENT_VA(event); |
790 | |
|
791 | 0 | EventSP event_sp = event.GetSP(); |
792 | 0 | EventData *event_data = event_sp ? event_sp->GetData() : nullptr; |
793 | 0 | return event_data && (event_data->GetFlavor() == |
794 | 0 | EventDataStructuredData::GetFlavorString()); |
795 | 0 | } |
796 | | |
797 | 99 | SBBroadcaster SBProcess::GetBroadcaster() const { |
798 | 99 | LLDB_INSTRUMENT_VA(this); |
799 | | |
800 | 99 | ProcessSP process_sp(GetSP()); |
801 | | |
802 | 99 | SBBroadcaster broadcaster(process_sp.get(), false); |
803 | | |
804 | 99 | return broadcaster; |
805 | 99 | } |
806 | | |
807 | 0 | const char *SBProcess::GetBroadcasterClass() { |
808 | 0 | LLDB_INSTRUMENT(); |
809 | |
|
810 | 0 | return Process::GetStaticBroadcasterClass().AsCString(); |
811 | 0 | } |
812 | | |
813 | | size_t SBProcess::ReadMemory(addr_t addr, void *dst, size_t dst_len, |
814 | 19 | SBError &sb_error) { |
815 | 19 | LLDB_INSTRUMENT_VA(this, addr, dst, dst_len, sb_error); |
816 | | |
817 | 19 | if (!dst) { |
818 | 0 | sb_error.SetErrorStringWithFormat( |
819 | 0 | "no buffer provided to read %zu bytes into", dst_len); |
820 | 0 | return 0; |
821 | 0 | } |
822 | | |
823 | 19 | size_t bytes_read = 0; |
824 | 19 | ProcessSP process_sp(GetSP()); |
825 | | |
826 | | |
827 | 19 | if (process_sp) { |
828 | 18 | Process::StopLocker stop_locker; |
829 | 18 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
830 | 18 | std::lock_guard<std::recursive_mutex> guard( |
831 | 18 | process_sp->GetTarget().GetAPIMutex()); |
832 | 18 | bytes_read = process_sp->ReadMemory(addr, dst, dst_len, sb_error.ref()); |
833 | 18 | } else { |
834 | 0 | sb_error.SetErrorString("process is running"); |
835 | 0 | } |
836 | 18 | } else { |
837 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
838 | 1 | } |
839 | | |
840 | 19 | return bytes_read; |
841 | 19 | } |
842 | | |
843 | | size_t SBProcess::ReadCStringFromMemory(addr_t addr, void *buf, size_t size, |
844 | 17 | lldb::SBError &sb_error) { |
845 | 17 | LLDB_INSTRUMENT_VA(this, addr, buf, size, sb_error); |
846 | | |
847 | 17 | size_t bytes_read = 0; |
848 | 17 | ProcessSP process_sp(GetSP()); |
849 | 17 | if (process_sp) { |
850 | 16 | Process::StopLocker stop_locker; |
851 | 16 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
852 | 16 | std::lock_guard<std::recursive_mutex> guard( |
853 | 16 | process_sp->GetTarget().GetAPIMutex()); |
854 | 16 | bytes_read = process_sp->ReadCStringFromMemory(addr, (char *)buf, size, |
855 | 16 | sb_error.ref()); |
856 | 16 | } else { |
857 | 0 | sb_error.SetErrorString("process is running"); |
858 | 0 | } |
859 | 16 | } else { |
860 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
861 | 1 | } |
862 | 17 | return bytes_read; |
863 | 17 | } |
864 | | |
865 | | uint64_t SBProcess::ReadUnsignedFromMemory(addr_t addr, uint32_t byte_size, |
866 | 5 | lldb::SBError &sb_error) { |
867 | 5 | LLDB_INSTRUMENT_VA(this, addr, byte_size, sb_error); |
868 | | |
869 | 5 | uint64_t value = 0; |
870 | 5 | ProcessSP process_sp(GetSP()); |
871 | 5 | if (process_sp) { |
872 | 4 | Process::StopLocker stop_locker; |
873 | 4 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
874 | 4 | std::lock_guard<std::recursive_mutex> guard( |
875 | 4 | process_sp->GetTarget().GetAPIMutex()); |
876 | 4 | value = process_sp->ReadUnsignedIntegerFromMemory(addr, byte_size, 0, |
877 | 4 | sb_error.ref()); |
878 | 4 | } else { |
879 | 0 | sb_error.SetErrorString("process is running"); |
880 | 0 | } |
881 | 4 | } else { |
882 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
883 | 1 | } |
884 | 5 | return value; |
885 | 5 | } |
886 | | |
887 | | lldb::addr_t SBProcess::ReadPointerFromMemory(addr_t addr, |
888 | 19 | lldb::SBError &sb_error) { |
889 | 19 | LLDB_INSTRUMENT_VA(this, addr, sb_error); |
890 | | |
891 | 19 | lldb::addr_t ptr = LLDB_INVALID_ADDRESS; |
892 | 19 | ProcessSP process_sp(GetSP()); |
893 | 19 | if (process_sp) { |
894 | 18 | Process::StopLocker stop_locker; |
895 | 18 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
896 | 18 | std::lock_guard<std::recursive_mutex> guard( |
897 | 18 | process_sp->GetTarget().GetAPIMutex()); |
898 | 18 | ptr = process_sp->ReadPointerFromMemory(addr, sb_error.ref()); |
899 | 18 | } else { |
900 | 0 | sb_error.SetErrorString("process is running"); |
901 | 0 | } |
902 | 18 | } else { |
903 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
904 | 1 | } |
905 | 19 | return ptr; |
906 | 19 | } |
907 | | |
908 | | size_t SBProcess::WriteMemory(addr_t addr, const void *src, size_t src_len, |
909 | 12 | SBError &sb_error) { |
910 | 12 | LLDB_INSTRUMENT_VA(this, addr, src, src_len, sb_error); |
911 | | |
912 | 12 | size_t bytes_written = 0; |
913 | | |
914 | 12 | ProcessSP process_sp(GetSP()); |
915 | | |
916 | 12 | if (process_sp) { |
917 | 11 | Process::StopLocker stop_locker; |
918 | 11 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
919 | 11 | std::lock_guard<std::recursive_mutex> guard( |
920 | 11 | process_sp->GetTarget().GetAPIMutex()); |
921 | 11 | bytes_written = |
922 | 11 | process_sp->WriteMemory(addr, src, src_len, sb_error.ref()); |
923 | 11 | } else { |
924 | 0 | sb_error.SetErrorString("process is running"); |
925 | 0 | } |
926 | 11 | } |
927 | | |
928 | 12 | return bytes_written; |
929 | 12 | } |
930 | | |
931 | 4.22k | bool SBProcess::GetDescription(SBStream &description) { |
932 | 4.22k | LLDB_INSTRUMENT_VA(this, description); |
933 | | |
934 | 4.22k | Stream &strm = description.ref(); |
935 | | |
936 | 4.22k | ProcessSP process_sp(GetSP()); |
937 | 4.22k | if (process_sp) { |
938 | 4.21k | char path[PATH_MAX]; |
939 | 4.21k | GetTarget().GetExecutable().GetPath(path, sizeof(path)); |
940 | 4.21k | Module *exe_module = process_sp->GetTarget().GetExecutableModulePointer(); |
941 | 4.21k | const char *exe_name = nullptr; |
942 | 4.21k | if (exe_module) |
943 | 4.01k | exe_name = exe_module->GetFileSpec().GetFilename().AsCString(); |
944 | | |
945 | 4.21k | strm.Printf("SBProcess: pid = %" PRIu64 ", state = %s, threads = %d%s%s", |
946 | 4.21k | process_sp->GetID(), lldb_private::StateAsCString(GetState()), |
947 | 4.21k | GetNumThreads(), exe_name ? ", executable = "4.01k : ""204 , |
948 | 4.21k | exe_name ? exe_name4.01k : ""204 ); |
949 | 4.21k | } else |
950 | 2 | strm.PutCString("No value"); |
951 | | |
952 | 4.22k | return true; |
953 | 4.22k | } |
954 | | |
955 | 4 | SBStructuredData SBProcess::GetExtendedCrashInformation() { |
956 | 4 | LLDB_INSTRUMENT_VA(this); |
957 | 4 | SBStructuredData data; |
958 | 4 | ProcessSP process_sp(GetSP()); |
959 | 4 | if (!process_sp) |
960 | 0 | return data; |
961 | | |
962 | 4 | PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); |
963 | | |
964 | 4 | if (!platform_sp) |
965 | 0 | return data; |
966 | | |
967 | 4 | auto expected_data = |
968 | 4 | platform_sp->FetchExtendedCrashInformation(*process_sp.get()); |
969 | | |
970 | 4 | if (!expected_data) |
971 | 0 | return data; |
972 | | |
973 | 4 | StructuredData::ObjectSP fetched_data = *expected_data; |
974 | 4 | data.m_impl_up->SetObjectSP(fetched_data); |
975 | 4 | return data; |
976 | 4 | } |
977 | | |
978 | | uint32_t |
979 | 3 | SBProcess::GetNumSupportedHardwareWatchpoints(lldb::SBError &sb_error) const { |
980 | 3 | LLDB_INSTRUMENT_VA(this, sb_error); |
981 | | |
982 | 3 | uint32_t num = 0; |
983 | 3 | ProcessSP process_sp(GetSP()); |
984 | 3 | if (process_sp) { |
985 | 2 | std::lock_guard<std::recursive_mutex> guard( |
986 | 2 | process_sp->GetTarget().GetAPIMutex()); |
987 | 2 | std::optional<uint32_t> actual_num = process_sp->GetWatchpointSlotCount(); |
988 | 2 | if (actual_num) { |
989 | 2 | num = *actual_num; |
990 | 2 | } else { |
991 | 0 | sb_error.SetErrorString("Unable to determine number of watchpoints"); |
992 | 0 | } |
993 | 2 | } else { |
994 | 1 | sb_error.SetErrorString("SBProcess is invalid"); |
995 | 1 | } |
996 | 3 | return num; |
997 | 3 | } |
998 | | |
999 | | uint32_t SBProcess::LoadImage(lldb::SBFileSpec &sb_remote_image_spec, |
1000 | 1 | lldb::SBError &sb_error) { |
1001 | 1 | LLDB_INSTRUMENT_VA(this, sb_remote_image_spec, sb_error); |
1002 | | |
1003 | 1 | return LoadImage(SBFileSpec(), sb_remote_image_spec, sb_error); |
1004 | 1 | } |
1005 | | |
1006 | | uint32_t SBProcess::LoadImage(const lldb::SBFileSpec &sb_local_image_spec, |
1007 | | const lldb::SBFileSpec &sb_remote_image_spec, |
1008 | 1 | lldb::SBError &sb_error) { |
1009 | 1 | LLDB_INSTRUMENT_VA(this, sb_local_image_spec, sb_remote_image_spec, sb_error); |
1010 | | |
1011 | 1 | ProcessSP process_sp(GetSP()); |
1012 | 1 | if (process_sp) { |
1013 | 0 | Process::StopLocker stop_locker; |
1014 | 0 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1015 | 0 | std::lock_guard<std::recursive_mutex> guard( |
1016 | 0 | process_sp->GetTarget().GetAPIMutex()); |
1017 | 0 | PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); |
1018 | 0 | return platform_sp->LoadImage(process_sp.get(), *sb_local_image_spec, |
1019 | 0 | *sb_remote_image_spec, sb_error.ref()); |
1020 | 0 | } else { |
1021 | 0 | sb_error.SetErrorString("process is running"); |
1022 | 0 | } |
1023 | 1 | } else { |
1024 | 1 | sb_error.SetErrorString("process is invalid"); |
1025 | 1 | } |
1026 | 1 | return LLDB_INVALID_IMAGE_TOKEN; |
1027 | 1 | } |
1028 | | |
1029 | | uint32_t SBProcess::LoadImageUsingPaths(const lldb::SBFileSpec &image_spec, |
1030 | | SBStringList &paths, |
1031 | | lldb::SBFileSpec &loaded_path, |
1032 | 7 | lldb::SBError &error) { |
1033 | 7 | LLDB_INSTRUMENT_VA(this, image_spec, paths, loaded_path, error); |
1034 | | |
1035 | 7 | ProcessSP process_sp(GetSP()); |
1036 | 7 | if (process_sp) { |
1037 | 7 | Process::StopLocker stop_locker; |
1038 | 7 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1039 | 7 | std::lock_guard<std::recursive_mutex> guard( |
1040 | 7 | process_sp->GetTarget().GetAPIMutex()); |
1041 | 7 | PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); |
1042 | 7 | size_t num_paths = paths.GetSize(); |
1043 | 7 | std::vector<std::string> paths_vec; |
1044 | 7 | paths_vec.reserve(num_paths); |
1045 | 25 | for (size_t i = 0; i < num_paths; i++18 ) |
1046 | 18 | paths_vec.push_back(paths.GetStringAtIndex(i)); |
1047 | 7 | FileSpec loaded_spec; |
1048 | | |
1049 | 7 | uint32_t token = platform_sp->LoadImageUsingPaths( |
1050 | 7 | process_sp.get(), *image_spec, paths_vec, error.ref(), &loaded_spec); |
1051 | 7 | if (token != LLDB_INVALID_IMAGE_TOKEN) |
1052 | 5 | loaded_path = loaded_spec; |
1053 | 7 | return token; |
1054 | 7 | } else { |
1055 | 0 | error.SetErrorString("process is running"); |
1056 | 0 | } |
1057 | 7 | } else { |
1058 | 0 | error.SetErrorString("process is invalid"); |
1059 | 0 | } |
1060 | | |
1061 | 0 | return LLDB_INVALID_IMAGE_TOKEN; |
1062 | 7 | } |
1063 | | |
1064 | 4 | lldb::SBError SBProcess::UnloadImage(uint32_t image_token) { |
1065 | 4 | LLDB_INSTRUMENT_VA(this, image_token); |
1066 | | |
1067 | 4 | lldb::SBError sb_error; |
1068 | 4 | ProcessSP process_sp(GetSP()); |
1069 | 4 | if (process_sp) { |
1070 | 3 | Process::StopLocker stop_locker; |
1071 | 3 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1072 | 3 | std::lock_guard<std::recursive_mutex> guard( |
1073 | 3 | process_sp->GetTarget().GetAPIMutex()); |
1074 | 3 | PlatformSP platform_sp = process_sp->GetTarget().GetPlatform(); |
1075 | 3 | sb_error.SetError( |
1076 | 3 | platform_sp->UnloadImage(process_sp.get(), image_token)); |
1077 | 3 | } else { |
1078 | 0 | sb_error.SetErrorString("process is running"); |
1079 | 0 | } |
1080 | 3 | } else |
1081 | 1 | sb_error.SetErrorString("invalid process"); |
1082 | 4 | return sb_error; |
1083 | 4 | } |
1084 | | |
1085 | 0 | lldb::SBError SBProcess::SendEventData(const char *event_data) { |
1086 | 0 | LLDB_INSTRUMENT_VA(this, event_data); |
1087 | |
|
1088 | 0 | lldb::SBError sb_error; |
1089 | 0 | ProcessSP process_sp(GetSP()); |
1090 | 0 | if (process_sp) { |
1091 | 0 | Process::StopLocker stop_locker; |
1092 | 0 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1093 | 0 | std::lock_guard<std::recursive_mutex> guard( |
1094 | 0 | process_sp->GetTarget().GetAPIMutex()); |
1095 | 0 | sb_error.SetError(process_sp->SendEventData(event_data)); |
1096 | 0 | } else { |
1097 | 0 | sb_error.SetErrorString("process is running"); |
1098 | 0 | } |
1099 | 0 | } else |
1100 | 0 | sb_error.SetErrorString("invalid process"); |
1101 | 0 | return sb_error; |
1102 | 0 | } |
1103 | | |
1104 | 0 | uint32_t SBProcess::GetNumExtendedBacktraceTypes() { |
1105 | 0 | LLDB_INSTRUMENT_VA(this); |
1106 | |
|
1107 | 0 | ProcessSP process_sp(GetSP()); |
1108 | 0 | if (process_sp && process_sp->GetSystemRuntime()) { |
1109 | 0 | SystemRuntime *runtime = process_sp->GetSystemRuntime(); |
1110 | 0 | return runtime->GetExtendedBacktraceTypes().size(); |
1111 | 0 | } |
1112 | 0 | return 0; |
1113 | 0 | } |
1114 | | |
1115 | 0 | const char *SBProcess::GetExtendedBacktraceTypeAtIndex(uint32_t idx) { |
1116 | 0 | LLDB_INSTRUMENT_VA(this, idx); |
1117 | |
|
1118 | 0 | ProcessSP process_sp(GetSP()); |
1119 | 0 | if (process_sp && process_sp->GetSystemRuntime()) { |
1120 | 0 | SystemRuntime *runtime = process_sp->GetSystemRuntime(); |
1121 | 0 | const std::vector<ConstString> &names = |
1122 | 0 | runtime->GetExtendedBacktraceTypes(); |
1123 | 0 | if (idx < names.size()) { |
1124 | 0 | return names[idx].AsCString(); |
1125 | 0 | } |
1126 | 0 | } |
1127 | 0 | return nullptr; |
1128 | 0 | } |
1129 | | |
1130 | 0 | SBThreadCollection SBProcess::GetHistoryThreads(addr_t addr) { |
1131 | 0 | LLDB_INSTRUMENT_VA(this, addr); |
1132 | |
|
1133 | 0 | ProcessSP process_sp(GetSP()); |
1134 | 0 | SBThreadCollection threads; |
1135 | 0 | if (process_sp) { |
1136 | 0 | threads = SBThreadCollection(process_sp->GetHistoryThreads(addr)); |
1137 | 0 | } |
1138 | 0 | return threads; |
1139 | 0 | } |
1140 | | |
1141 | | bool SBProcess::IsInstrumentationRuntimePresent( |
1142 | 0 | InstrumentationRuntimeType type) { |
1143 | 0 | LLDB_INSTRUMENT_VA(this, type); |
1144 | |
|
1145 | 0 | ProcessSP process_sp(GetSP()); |
1146 | 0 | if (!process_sp) |
1147 | 0 | return false; |
1148 | | |
1149 | 0 | std::lock_guard<std::recursive_mutex> guard( |
1150 | 0 | process_sp->GetTarget().GetAPIMutex()); |
1151 | |
|
1152 | 0 | InstrumentationRuntimeSP runtime_sp = |
1153 | 0 | process_sp->GetInstrumentationRuntime(type); |
1154 | |
|
1155 | 0 | if (!runtime_sp.get()) |
1156 | 0 | return false; |
1157 | | |
1158 | 0 | return runtime_sp->IsActive(); |
1159 | 0 | } |
1160 | | |
1161 | 0 | lldb::SBError SBProcess::SaveCore(const char *file_name) { |
1162 | 0 | LLDB_INSTRUMENT_VA(this, file_name); |
1163 | 0 | return SaveCore(file_name, "", SaveCoreStyle::eSaveCoreFull); |
1164 | 0 | } |
1165 | | |
1166 | | lldb::SBError SBProcess::SaveCore(const char *file_name, |
1167 | | const char *flavor, |
1168 | 0 | SaveCoreStyle core_style) { |
1169 | 0 | LLDB_INSTRUMENT_VA(this, file_name, flavor, core_style); |
1170 | |
|
1171 | 0 | lldb::SBError error; |
1172 | 0 | ProcessSP process_sp(GetSP()); |
1173 | 0 | if (!process_sp) { |
1174 | 0 | error.SetErrorString("SBProcess is invalid"); |
1175 | 0 | return error; |
1176 | 0 | } |
1177 | | |
1178 | 0 | std::lock_guard<std::recursive_mutex> guard( |
1179 | 0 | process_sp->GetTarget().GetAPIMutex()); |
1180 | |
|
1181 | 0 | if (process_sp->GetState() != eStateStopped) { |
1182 | 0 | error.SetErrorString("the process is not stopped"); |
1183 | 0 | return error; |
1184 | 0 | } |
1185 | | |
1186 | 0 | FileSpec core_file(file_name); |
1187 | 0 | FileSystem::Instance().Resolve(core_file); |
1188 | 0 | error.ref() = PluginManager::SaveCore(process_sp, core_file, core_style, |
1189 | 0 | flavor); |
1190 | |
|
1191 | 0 | return error; |
1192 | 0 | } |
1193 | | |
1194 | | lldb::SBError |
1195 | | SBProcess::GetMemoryRegionInfo(lldb::addr_t load_addr, |
1196 | 831 | SBMemoryRegionInfo &sb_region_info) { |
1197 | 831 | LLDB_INSTRUMENT_VA(this, load_addr, sb_region_info); |
1198 | | |
1199 | 831 | lldb::SBError sb_error; |
1200 | 831 | ProcessSP process_sp(GetSP()); |
1201 | 831 | if (process_sp) { |
1202 | 831 | Process::StopLocker stop_locker; |
1203 | 831 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1204 | 831 | std::lock_guard<std::recursive_mutex> guard( |
1205 | 831 | process_sp->GetTarget().GetAPIMutex()); |
1206 | | |
1207 | 831 | sb_error.ref() = |
1208 | 831 | process_sp->GetMemoryRegionInfo(load_addr, sb_region_info.ref()); |
1209 | 831 | } else { |
1210 | 0 | sb_error.SetErrorString("process is running"); |
1211 | 0 | } |
1212 | 831 | } else { |
1213 | 0 | sb_error.SetErrorString("SBProcess is invalid"); |
1214 | 0 | } |
1215 | 831 | return sb_error; |
1216 | 831 | } |
1217 | | |
1218 | 18 | lldb::SBMemoryRegionInfoList SBProcess::GetMemoryRegions() { |
1219 | 18 | LLDB_INSTRUMENT_VA(this); |
1220 | | |
1221 | 18 | lldb::SBMemoryRegionInfoList sb_region_list; |
1222 | | |
1223 | 18 | ProcessSP process_sp(GetSP()); |
1224 | 18 | Process::StopLocker stop_locker; |
1225 | 18 | if (process_sp && stop_locker.TryLock(&process_sp->GetRunLock())) { |
1226 | 18 | std::lock_guard<std::recursive_mutex> guard( |
1227 | 18 | process_sp->GetTarget().GetAPIMutex()); |
1228 | | |
1229 | 18 | process_sp->GetMemoryRegions(sb_region_list.ref()); |
1230 | 18 | } |
1231 | | |
1232 | 18 | return sb_region_list; |
1233 | 18 | } |
1234 | | |
1235 | 1 | lldb::SBProcessInfo SBProcess::GetProcessInfo() { |
1236 | 1 | LLDB_INSTRUMENT_VA(this); |
1237 | | |
1238 | 1 | lldb::SBProcessInfo sb_proc_info; |
1239 | 1 | ProcessSP process_sp(GetSP()); |
1240 | 1 | ProcessInstanceInfo proc_info; |
1241 | 1 | if (process_sp && process_sp->GetProcessInfo(proc_info)) { |
1242 | 1 | sb_proc_info.SetProcessInfo(proc_info); |
1243 | 1 | } |
1244 | 1 | return sb_proc_info; |
1245 | 1 | } |
1246 | | |
1247 | | lldb::addr_t SBProcess::AllocateMemory(size_t size, uint32_t permissions, |
1248 | 2 | lldb::SBError &sb_error) { |
1249 | 2 | LLDB_INSTRUMENT_VA(this, size, permissions, sb_error); |
1250 | | |
1251 | 2 | lldb::addr_t addr = LLDB_INVALID_ADDRESS; |
1252 | 2 | ProcessSP process_sp(GetSP()); |
1253 | 2 | if (process_sp) { |
1254 | 2 | Process::StopLocker stop_locker; |
1255 | 2 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1256 | 2 | std::lock_guard<std::recursive_mutex> guard( |
1257 | 2 | process_sp->GetTarget().GetAPIMutex()); |
1258 | 2 | addr = process_sp->AllocateMemory(size, permissions, sb_error.ref()); |
1259 | 2 | } else { |
1260 | 0 | sb_error.SetErrorString("process is running"); |
1261 | 0 | } |
1262 | 2 | } else { |
1263 | 0 | sb_error.SetErrorString("SBProcess is invalid"); |
1264 | 0 | } |
1265 | 2 | return addr; |
1266 | 2 | } |
1267 | | |
1268 | 2 | lldb::SBError SBProcess::DeallocateMemory(lldb::addr_t ptr) { |
1269 | 2 | LLDB_INSTRUMENT_VA(this, ptr); |
1270 | | |
1271 | 2 | lldb::SBError sb_error; |
1272 | 2 | ProcessSP process_sp(GetSP()); |
1273 | 2 | if (process_sp) { |
1274 | 2 | Process::StopLocker stop_locker; |
1275 | 2 | if (stop_locker.TryLock(&process_sp->GetRunLock())) { |
1276 | 2 | std::lock_guard<std::recursive_mutex> guard( |
1277 | 2 | process_sp->GetTarget().GetAPIMutex()); |
1278 | 2 | Status error = process_sp->DeallocateMemory(ptr); |
1279 | 2 | sb_error.SetError(error); |
1280 | 2 | } else { |
1281 | 0 | sb_error.SetErrorString("process is running"); |
1282 | 0 | } |
1283 | 2 | } else { |
1284 | 0 | sb_error.SetErrorString("SBProcess is invalid"); |
1285 | 0 | } |
1286 | 2 | return sb_error; |
1287 | 2 | } |
1288 | | |
1289 | 7 | lldb::SBScriptObject SBProcess::GetScriptedImplementation() { |
1290 | 7 | LLDB_INSTRUMENT_VA(this); |
1291 | 7 | ProcessSP process_sp(GetSP()); |
1292 | 7 | return lldb::SBScriptObject((process_sp) ? process_sp->GetImplementation() |
1293 | 7 | : nullptr0 , |
1294 | 7 | eScriptLanguageDefault); |
1295 | 7 | } |