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