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