1//===-- SBPlatform.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/SBPlatform.h"
10#include "lldb/API/SBDebugger.h"
11#include "lldb/API/SBEnvironment.h"
12#include "lldb/API/SBError.h"
13#include "lldb/API/SBFileSpec.h"
14#include "lldb/API/SBLaunchInfo.h"
15#include "lldb/API/SBModuleSpec.h"
16#include "lldb/API/SBPlatform.h"
17#include "lldb/API/SBProcessInfoList.h"
18#include "lldb/API/SBTarget.h"
19#include "lldb/API/SBUnixSignals.h"
20#include "lldb/Host/File.h"
21#include "lldb/Target/Platform.h"
22#include "lldb/Target/Target.h"
23#include "lldb/Utility/ArchSpec.h"
24#include "lldb/Utility/Args.h"
25#include "lldb/Utility/Instrumentation.h"
26#include "lldb/Utility/Status.h"
27
28#include "llvm/Support/FileSystem.h"
29
30#include <functional>
31
32using namespace lldb;
33using namespace lldb_private;
34
35// PlatformConnectOptions
36struct PlatformConnectOptions {
37 PlatformConnectOptions(const char *url = nullptr) {
38 if (url && url[0])
39 m_url = url;
40 }
41
42 ~PlatformConnectOptions() = default;
43
44 std::string m_url;
45 std::string m_rsync_options;
46 std::string m_rsync_remote_path_prefix;
47 bool m_rsync_enabled = false;
48 bool m_rsync_omit_hostname_from_remote_path = false;
49 ConstString m_local_cache_directory;
50};
51
52// PlatformShellCommand
53struct PlatformShellCommand {
54 PlatformShellCommand(llvm::StringRef shell_interpreter,
55 llvm::StringRef shell_command) {
56 if (!shell_interpreter.empty())
57 m_shell = shell_interpreter.str();
58
59 if (!m_shell.empty() && !shell_command.empty())
60 m_command = shell_command.str();
61 }
62
63 PlatformShellCommand(llvm::StringRef shell_command = llvm::StringRef()) {
64 if (!shell_command.empty())
65 m_command = shell_command.str();
66 }
67
68 ~PlatformShellCommand() = default;
69
70 std::string m_shell;
71 std::string m_command;
72 std::string m_working_dir;
73 std::string m_output;
74 int m_status = 0;
75 int m_signo = 0;
76 Timeout<std::ratio<1>> m_timeout = std::nullopt;
77};
78// SBPlatformConnectOptions
79SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url)
80 : m_opaque_ptr(new PlatformConnectOptions(url)) {
81 LLDB_INSTRUMENT_VA(this, url);
82}
83
84SBPlatformConnectOptions::SBPlatformConnectOptions(
85 const SBPlatformConnectOptions &rhs)
86 : m_opaque_ptr(new PlatformConnectOptions()) {
87 LLDB_INSTRUMENT_VA(this, rhs);
88
89 *m_opaque_ptr = *rhs.m_opaque_ptr;
90}
91
92SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; }
93
94SBPlatformConnectOptions &
95SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) {
96 LLDB_INSTRUMENT_VA(this, rhs);
97
98 *m_opaque_ptr = *rhs.m_opaque_ptr;
99 return *this;
100}
101
102const char *SBPlatformConnectOptions::GetURL() {
103 LLDB_INSTRUMENT_VA(this);
104
105 if (m_opaque_ptr->m_url.empty())
106 return nullptr;
107 return ConstString(m_opaque_ptr->m_url.c_str()).GetCString();
108}
109
110void SBPlatformConnectOptions::SetURL(const char *url) {
111 LLDB_INSTRUMENT_VA(this, url);
112
113 if (url && url[0])
114 m_opaque_ptr->m_url = url;
115 else
116 m_opaque_ptr->m_url.clear();
117}
118
119bool SBPlatformConnectOptions::GetRsyncEnabled() {
120 LLDB_INSTRUMENT_VA(this);
121
122 return m_opaque_ptr->m_rsync_enabled;
123}
124
125void SBPlatformConnectOptions::EnableRsync(
126 const char *options, const char *remote_path_prefix,
127 bool omit_hostname_from_remote_path) {
128 LLDB_INSTRUMENT_VA(this, options, remote_path_prefix,
129 omit_hostname_from_remote_path);
130
131 m_opaque_ptr->m_rsync_enabled = true;
132 m_opaque_ptr->m_rsync_omit_hostname_from_remote_path =
133 omit_hostname_from_remote_path;
134 if (remote_path_prefix && remote_path_prefix[0])
135 m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
136 else
137 m_opaque_ptr->m_rsync_remote_path_prefix.clear();
138
139 if (options && options[0])
140 m_opaque_ptr->m_rsync_options = options;
141 else
142 m_opaque_ptr->m_rsync_options.clear();
143}
144
145void SBPlatformConnectOptions::DisableRsync() {
146 LLDB_INSTRUMENT_VA(this);
147
148 m_opaque_ptr->m_rsync_enabled = false;
149}
150
151const char *SBPlatformConnectOptions::GetLocalCacheDirectory() {
152 LLDB_INSTRUMENT_VA(this);
153
154 return m_opaque_ptr->m_local_cache_directory.GetCString();
155}
156
157void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) {
158 LLDB_INSTRUMENT_VA(this, path);
159
160 if (path && path[0])
161 m_opaque_ptr->m_local_cache_directory.SetCString(path);
162 else
163 m_opaque_ptr->m_local_cache_directory = ConstString();
164}
165
166// SBPlatformShellCommand
167SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_interpreter,
168 const char *shell_command)
169 : m_opaque_ptr(new PlatformShellCommand(shell_interpreter, shell_command)) {
170 LLDB_INSTRUMENT_VA(this, shell_interpreter, shell_command);
171}
172
173SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command)
174 : m_opaque_ptr(new PlatformShellCommand(shell_command)) {
175 LLDB_INSTRUMENT_VA(this, shell_command);
176}
177
178SBPlatformShellCommand::SBPlatformShellCommand(
179 const SBPlatformShellCommand &rhs)
180 : m_opaque_ptr(new PlatformShellCommand()) {
181 LLDB_INSTRUMENT_VA(this, rhs);
182
183 *m_opaque_ptr = *rhs.m_opaque_ptr;
184}
185
186SBPlatformShellCommand &
187SBPlatformShellCommand::operator=(const SBPlatformShellCommand &rhs) {
188
189 LLDB_INSTRUMENT_VA(this, rhs);
190
191 *m_opaque_ptr = *rhs.m_opaque_ptr;
192 return *this;
193}
194
195SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; }
196
197void SBPlatformShellCommand::Clear() {
198 LLDB_INSTRUMENT_VA(this);
199
200 m_opaque_ptr->m_output = std::string();
201 m_opaque_ptr->m_status = 0;
202 m_opaque_ptr->m_signo = 0;
203}
204
205const char *SBPlatformShellCommand::GetShell() {
206 LLDB_INSTRUMENT_VA(this);
207
208 if (m_opaque_ptr->m_shell.empty())
209 return nullptr;
210 return ConstString(m_opaque_ptr->m_shell.c_str()).GetCString();
211}
212
213void SBPlatformShellCommand::SetShell(const char *shell_interpreter) {
214 LLDB_INSTRUMENT_VA(this, shell_interpreter);
215
216 if (shell_interpreter && shell_interpreter[0])
217 m_opaque_ptr->m_shell = shell_interpreter;
218 else
219 m_opaque_ptr->m_shell.clear();
220}
221
222const char *SBPlatformShellCommand::GetCommand() {
223 LLDB_INSTRUMENT_VA(this);
224
225 if (m_opaque_ptr->m_command.empty())
226 return nullptr;
227 return ConstString(m_opaque_ptr->m_command.c_str()).GetCString();
228}
229
230void SBPlatformShellCommand::SetCommand(const char *shell_command) {
231 LLDB_INSTRUMENT_VA(this, shell_command);
232
233 if (shell_command && shell_command[0])
234 m_opaque_ptr->m_command = shell_command;
235 else
236 m_opaque_ptr->m_command.clear();
237}
238
239const char *SBPlatformShellCommand::GetWorkingDirectory() {
240 LLDB_INSTRUMENT_VA(this);
241
242 if (m_opaque_ptr->m_working_dir.empty())
243 return nullptr;
244 return ConstString(m_opaque_ptr->m_working_dir.c_str()).GetCString();
245}
246
247void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {
248 LLDB_INSTRUMENT_VA(this, path);
249
250 if (path && path[0])
251 m_opaque_ptr->m_working_dir = path;
252 else
253 m_opaque_ptr->m_working_dir.clear();
254}
255
256uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {
257 LLDB_INSTRUMENT_VA(this);
258
259 if (m_opaque_ptr->m_timeout)
260 return m_opaque_ptr->m_timeout->count();
261 return UINT32_MAX;
262}
263
264void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {
265 LLDB_INSTRUMENT_VA(this, sec);
266
267 if (sec == UINT32_MAX)
268 m_opaque_ptr->m_timeout = std::nullopt;
269 else
270 m_opaque_ptr->m_timeout = std::chrono::seconds(sec);
271}
272
273int SBPlatformShellCommand::GetSignal() {
274 LLDB_INSTRUMENT_VA(this);
275
276 return m_opaque_ptr->m_signo;
277}
278
279int SBPlatformShellCommand::GetStatus() {
280 LLDB_INSTRUMENT_VA(this);
281
282 return m_opaque_ptr->m_status;
283}
284
285const char *SBPlatformShellCommand::GetOutput() {
286 LLDB_INSTRUMENT_VA(this);
287
288 if (m_opaque_ptr->m_output.empty())
289 return nullptr;
290 return ConstString(m_opaque_ptr->m_output.c_str()).GetCString();
291}
292
293// SBPlatform
294SBPlatform::SBPlatform() { LLDB_INSTRUMENT_VA(this); }
295
296SBPlatform::SBPlatform(const char *platform_name) {
297 LLDB_INSTRUMENT_VA(this, platform_name);
298
299 m_opaque_sp = Platform::Create(name: platform_name);
300}
301
302SBPlatform::SBPlatform(const SBPlatform &rhs) {
303 LLDB_INSTRUMENT_VA(this, rhs);
304
305 m_opaque_sp = rhs.m_opaque_sp;
306}
307
308SBPlatform &SBPlatform::operator=(const SBPlatform &rhs) {
309 LLDB_INSTRUMENT_VA(this, rhs);
310
311 m_opaque_sp = rhs.m_opaque_sp;
312 return *this;
313}
314
315SBPlatform::~SBPlatform() = default;
316
317SBPlatform SBPlatform::GetHostPlatform() {
318 LLDB_INSTRUMENT();
319
320 SBPlatform host_platform;
321 host_platform.m_opaque_sp = Platform::GetHostPlatform();
322 return host_platform;
323}
324
325bool SBPlatform::IsValid() const {
326 LLDB_INSTRUMENT_VA(this);
327 return this->operator bool();
328}
329SBPlatform::operator bool() const {
330 LLDB_INSTRUMENT_VA(this);
331
332 return m_opaque_sp.get() != nullptr;
333}
334
335void SBPlatform::Clear() {
336 LLDB_INSTRUMENT_VA(this);
337
338 m_opaque_sp.reset();
339}
340
341const char *SBPlatform::GetName() {
342 LLDB_INSTRUMENT_VA(this);
343
344 PlatformSP platform_sp(GetSP());
345 if (platform_sp)
346 return ConstString(platform_sp->GetName()).AsCString();
347 return nullptr;
348}
349
350lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; }
351
352void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) {
353 m_opaque_sp = platform_sp;
354}
355
356const char *SBPlatform::GetWorkingDirectory() {
357 LLDB_INSTRUMENT_VA(this);
358
359 PlatformSP platform_sp(GetSP());
360 if (platform_sp)
361 return platform_sp->GetWorkingDirectory().GetPathAsConstString().AsCString();
362 return nullptr;
363}
364
365bool SBPlatform::SetWorkingDirectory(const char *path) {
366 LLDB_INSTRUMENT_VA(this, path);
367
368 PlatformSP platform_sp(GetSP());
369 if (platform_sp) {
370 if (path)
371 platform_sp->SetWorkingDirectory(FileSpec(path));
372 else
373 platform_sp->SetWorkingDirectory(FileSpec());
374 return true;
375 }
376 return false;
377}
378
379SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {
380 LLDB_INSTRUMENT_VA(this, connect_options);
381
382 SBError sb_error;
383 PlatformSP platform_sp(GetSP());
384 if (platform_sp && connect_options.GetURL()) {
385 Args args;
386 args.AppendArgument(arg_str: connect_options.GetURL());
387 sb_error.ref() = platform_sp->ConnectRemote(args);
388 } else {
389 sb_error.SetErrorString("invalid platform");
390 }
391 return sb_error;
392}
393
394void SBPlatform::DisconnectRemote() {
395 LLDB_INSTRUMENT_VA(this);
396
397 PlatformSP platform_sp(GetSP());
398 if (platform_sp)
399 platform_sp->DisconnectRemote();
400}
401
402bool SBPlatform::IsConnected() {
403 LLDB_INSTRUMENT_VA(this);
404
405 PlatformSP platform_sp(GetSP());
406 if (platform_sp)
407 return platform_sp->IsConnected();
408 return false;
409}
410
411const char *SBPlatform::GetTriple() {
412 LLDB_INSTRUMENT_VA(this);
413
414 PlatformSP platform_sp(GetSP());
415 if (platform_sp) {
416 ArchSpec arch(platform_sp->GetSystemArchitecture());
417 if (arch.IsValid()) {
418 // Const-ify the string so we don't need to worry about the lifetime of
419 // the string
420 return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
421 }
422 }
423 return nullptr;
424}
425
426const char *SBPlatform::GetOSBuild() {
427 LLDB_INSTRUMENT_VA(this);
428
429 PlatformSP platform_sp(GetSP());
430 if (platform_sp) {
431 std::string s = platform_sp->GetOSBuildString().value_or(u: "");
432 if (!s.empty()) {
433 // Const-ify the string so we don't need to worry about the lifetime of
434 // the string
435 return ConstString(s).GetCString();
436 }
437 }
438 return nullptr;
439}
440
441const char *SBPlatform::GetOSDescription() {
442 LLDB_INSTRUMENT_VA(this);
443
444 PlatformSP platform_sp(GetSP());
445 if (platform_sp) {
446 std::string s = platform_sp->GetOSKernelDescription().value_or(u: "");
447 if (!s.empty()) {
448 // Const-ify the string so we don't need to worry about the lifetime of
449 // the string
450 return ConstString(s.c_str()).GetCString();
451 }
452 }
453 return nullptr;
454}
455
456const char *SBPlatform::GetHostname() {
457 LLDB_INSTRUMENT_VA(this);
458
459 PlatformSP platform_sp(GetSP());
460 if (platform_sp)
461 return ConstString(platform_sp->GetHostname()).GetCString();
462 return nullptr;
463}
464
465uint32_t SBPlatform::GetOSMajorVersion() {
466 LLDB_INSTRUMENT_VA(this);
467
468 llvm::VersionTuple version;
469 if (PlatformSP platform_sp = GetSP())
470 version = platform_sp->GetOSVersion();
471 return version.empty() ? UINT32_MAX : version.getMajor();
472}
473
474uint32_t SBPlatform::GetOSMinorVersion() {
475 LLDB_INSTRUMENT_VA(this);
476
477 llvm::VersionTuple version;
478 if (PlatformSP platform_sp = GetSP())
479 version = platform_sp->GetOSVersion();
480 return version.getMinor().value_or(UINT32_MAX);
481}
482
483uint32_t SBPlatform::GetOSUpdateVersion() {
484 LLDB_INSTRUMENT_VA(this);
485
486 llvm::VersionTuple version;
487 if (PlatformSP platform_sp = GetSP())
488 version = platform_sp->GetOSVersion();
489 return version.getSubminor().value_or(UINT32_MAX);
490}
491
492void SBPlatform::SetSDKRoot(const char *sysroot) {
493 LLDB_INSTRUMENT_VA(this, sysroot);
494 if (PlatformSP platform_sp = GetSP())
495 platform_sp->SetSDKRootDirectory(llvm::StringRef(sysroot).str());
496}
497
498SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
499 LLDB_INSTRUMENT_VA(this, src, dst);
500
501 SBError sb_error;
502 PlatformSP platform_sp(GetSP());
503 if (platform_sp) {
504 sb_error.ref() = platform_sp->GetFile(source: src.ref(), destination: dst.ref());
505 } else {
506 sb_error.SetErrorString("invalid platform");
507 }
508 return sb_error;
509}
510
511SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {
512 LLDB_INSTRUMENT_VA(this, src, dst);
513 return ExecuteConnected(func: [&](const lldb::PlatformSP &platform_sp) {
514 if (src.Exists()) {
515 uint32_t permissions = FileSystem::Instance().GetPermissions(file_spec: src.ref());
516 if (permissions == 0) {
517 if (FileSystem::Instance().IsDirectory(file_spec: src.ref()))
518 permissions = eFilePermissionsDirectoryDefault;
519 else
520 permissions = eFilePermissionsFileDefault;
521 }
522
523 return platform_sp->PutFile(source: src.ref(), destination: dst.ref(), uid: permissions);
524 }
525
526 Status error;
527 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",
528 src.ref().GetPath().c_str());
529 return error;
530 });
531}
532
533SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) {
534 LLDB_INSTRUMENT_VA(this, src, dst);
535 return ExecuteConnected(func: [&](const lldb::PlatformSP &platform_sp) {
536 if (src.Exists())
537 return platform_sp->Install(src: src.ref(), dst: dst.ref());
538
539 Status error;
540 error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",
541 src.ref().GetPath().c_str());
542 return error;
543 });
544}
545
546SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
547 LLDB_INSTRUMENT_VA(this, shell_command);
548 return ExecuteConnected(
549 func: [&](const lldb::PlatformSP &platform_sp) {
550 const char *command = shell_command.GetCommand();
551 if (!command)
552 return Status("invalid shell command (empty)");
553
554 if (shell_command.GetWorkingDirectory() == nullptr) {
555 std::string platform_working_dir =
556 platform_sp->GetWorkingDirectory().GetPath();
557 if (!platform_working_dir.empty())
558 shell_command.SetWorkingDirectory(platform_working_dir.c_str());
559 }
560 return platform_sp->RunShellCommand(
561 shell: shell_command.m_opaque_ptr->m_shell, command,
562 working_dir: FileSpec(shell_command.GetWorkingDirectory()),
563 status_ptr: &shell_command.m_opaque_ptr->m_status,
564 signo_ptr: &shell_command.m_opaque_ptr->m_signo,
565 command_output: &shell_command.m_opaque_ptr->m_output,
566 timeout: shell_command.m_opaque_ptr->m_timeout);
567 });
568}
569
570SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {
571 LLDB_INSTRUMENT_VA(this, launch_info);
572 return ExecuteConnected(func: [&](const lldb::PlatformSP &platform_sp) {
573 ProcessLaunchInfo info = launch_info.ref();
574 Status error = platform_sp->LaunchProcess(launch_info&: info);
575 launch_info.set_ref(info);
576 return error;
577 });
578}
579
580SBProcess SBPlatform::Attach(SBAttachInfo &attach_info,
581 const SBDebugger &debugger, SBTarget &target,
582 SBError &error) {
583 LLDB_INSTRUMENT_VA(this, attach_info, debugger, target, error);
584
585 if (PlatformSP platform_sp = GetSP()) {
586 if (platform_sp->IsConnected()) {
587 ProcessAttachInfo &info = attach_info.ref();
588 Status status;
589 ProcessSP process_sp = platform_sp->Attach(attach_info&: info, debugger&: debugger.ref(),
590 target: target.GetSP().get(), error&: status);
591 error.SetError(status);
592 return SBProcess(process_sp);
593 }
594
595 error.SetErrorString("not connected");
596 return {};
597 }
598
599 error.SetErrorString("invalid platform");
600 return {};
601}
602
603SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) {
604 if (PlatformSP platform_sp = GetSP()) {
605 if (platform_sp->IsConnected()) {
606 ProcessInstanceInfoList list = platform_sp->GetAllProcesses();
607 return SBProcessInfoList(list);
608 }
609 error.SetErrorString("not connected");
610 return {};
611 }
612
613 error.SetErrorString("invalid platform");
614 return {};
615}
616
617SBError SBPlatform::Kill(const lldb::pid_t pid) {
618 LLDB_INSTRUMENT_VA(this, pid);
619 return ExecuteConnected(func: [&](const lldb::PlatformSP &platform_sp) {
620 return platform_sp->KillProcess(pid);
621 });
622}
623
624SBError SBPlatform::ExecuteConnected(
625 const std::function<Status(const lldb::PlatformSP &)> &func) {
626 SBError sb_error;
627 const auto platform_sp(GetSP());
628 if (platform_sp) {
629 if (platform_sp->IsConnected())
630 sb_error.ref() = func(platform_sp);
631 else
632 sb_error.SetErrorString("not connected");
633 } else
634 sb_error.SetErrorString("invalid platform");
635
636 return sb_error;
637}
638
639SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {
640 LLDB_INSTRUMENT_VA(this, path, file_permissions);
641
642 SBError sb_error;
643 PlatformSP platform_sp(GetSP());
644 if (platform_sp) {
645 sb_error.ref() =
646 platform_sp->MakeDirectory(file_spec: FileSpec(path), permissions: file_permissions);
647 } else {
648 sb_error.SetErrorString("invalid platform");
649 }
650 return sb_error;
651}
652
653uint32_t SBPlatform::GetFilePermissions(const char *path) {
654 LLDB_INSTRUMENT_VA(this, path);
655
656 PlatformSP platform_sp(GetSP());
657 if (platform_sp) {
658 uint32_t file_permissions = 0;
659 platform_sp->GetFilePermissions(file_spec: FileSpec(path), file_permissions);
660 return file_permissions;
661 }
662 return 0;
663}
664
665SBError SBPlatform::SetFilePermissions(const char *path,
666 uint32_t file_permissions) {
667 LLDB_INSTRUMENT_VA(this, path, file_permissions);
668
669 SBError sb_error;
670 PlatformSP platform_sp(GetSP());
671 if (platform_sp) {
672 sb_error.ref() =
673 platform_sp->SetFilePermissions(file_spec: FileSpec(path), file_permissions);
674 } else {
675 sb_error.SetErrorString("invalid platform");
676 }
677 return sb_error;
678}
679
680SBUnixSignals SBPlatform::GetUnixSignals() const {
681 LLDB_INSTRUMENT_VA(this);
682
683 if (auto platform_sp = GetSP())
684 return SBUnixSignals{platform_sp};
685
686 return SBUnixSignals();
687}
688
689SBEnvironment SBPlatform::GetEnvironment() {
690 LLDB_INSTRUMENT_VA(this);
691 PlatformSP platform_sp(GetSP());
692
693 if (platform_sp) {
694 return SBEnvironment(platform_sp->GetEnvironment());
695 }
696
697 return SBEnvironment();
698}
699
700SBError SBPlatform::SetLocateModuleCallback(
701 lldb::SBPlatformLocateModuleCallback callback, void *callback_baton) {
702 LLDB_INSTRUMENT_VA(this, callback, callback_baton);
703 PlatformSP platform_sp(GetSP());
704 if (!platform_sp)
705 return SBError("invalid platform");
706
707 if (!callback) {
708 // Clear the callback.
709 platform_sp->SetLocateModuleCallback(nullptr);
710 return SBError();
711 }
712
713 // Platform.h does not accept lldb::SBPlatformLocateModuleCallback directly
714 // because of the SBModuleSpec and SBFileSpec dependencies. Use a lambda to
715 // convert ModuleSpec/FileSpec <--> SBModuleSpec/SBFileSpec for the callback
716 // arguments.
717 platform_sp->SetLocateModuleCallback(
718 [callback, callback_baton](const ModuleSpec &module_spec,
719 FileSpec &module_file_spec,
720 FileSpec &symbol_file_spec) {
721 SBModuleSpec module_spec_sb(module_spec);
722 SBFileSpec module_file_spec_sb;
723 SBFileSpec symbol_file_spec_sb;
724
725 SBError error = callback(callback_baton, module_spec_sb,
726 module_file_spec_sb, symbol_file_spec_sb);
727
728 if (error.Success()) {
729 module_file_spec = module_file_spec_sb.ref();
730 symbol_file_spec = symbol_file_spec_sb.ref();
731 }
732
733 return error.ref();
734 });
735 return SBError();
736}
737

source code of lldb/source/API/SBPlatform.cpp