1 //===-- Platform.cpp ------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
15 #include "lldb/Breakpoint/BreakpointIDList.h"
16 #include "lldb/Breakpoint/BreakpointLocation.h"
17 #include "lldb/Core/Debugger.h"
18 #include "lldb/Core/Module.h"
19 #include "lldb/Core/ModuleSpec.h"
20 #include "lldb/Core/PluginManager.h"
21 #include "lldb/Core/StreamFile.h"
22 #include "lldb/Host/FileSystem.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Host/HostInfo.h"
25 #include "lldb/Host/OptionParser.h"
26 #include "lldb/Interpreter/OptionValueFileSpec.h"
27 #include "lldb/Interpreter/OptionValueProperties.h"
28 #include "lldb/Interpreter/Property.h"
29 #include "lldb/Symbol/ObjectFile.h"
30 #include "lldb/Target/ModuleCache.h"
31 #include "lldb/Target/Platform.h"
32 #include "lldb/Target/Process.h"
33 #include "lldb/Target/Target.h"
34 #include "lldb/Target/UnixSignals.h"
35 #include "lldb/Utility/DataBufferHeap.h"
36 #include "lldb/Utility/FileSpec.h"
37 #include "lldb/Utility/Log.h"
38 #include "lldb/Utility/Status.h"
39 #include "lldb/Utility/StructuredData.h"
40 #include "llvm/Support/FileSystem.h"
41 #include "llvm/Support/Path.h"
43 // Define these constants from POSIX mman.h rather than include the file so
44 // that they will be correct even when compiled on Linux.
46 #define MAP_ANON 0x1000
49 using namespace lldb_private
;
51 static uint32_t g_initialize_count
= 0;
53 // Use a singleton function for g_local_platform_sp to avoid init constructors
54 // since LLDB is often part of a shared library
55 static PlatformSP
&GetHostPlatformSP() {
56 static PlatformSP g_platform_sp
;
60 const char *Platform::GetHostPlatformName() { return "host"; }
64 #define LLDB_PROPERTIES_platform
65 #include "TargetProperties.inc"
68 #define LLDB_PROPERTIES_platform
69 #include "TargetPropertiesEnum.inc"
74 ConstString
PlatformProperties::GetSettingName() {
75 static ConstString
g_setting_name("platform");
76 return g_setting_name
;
79 PlatformProperties::PlatformProperties() {
80 m_collection_sp
= std::make_shared
<OptionValueProperties
>(GetSettingName());
81 m_collection_sp
->Initialize(g_platform_properties
);
83 auto module_cache_dir
= GetModuleCacheDirectory();
87 llvm::SmallString
<64> user_home_dir
;
88 if (!FileSystem::Instance().GetHomeDirectory(user_home_dir
))
91 module_cache_dir
= FileSpec(user_home_dir
.c_str());
92 module_cache_dir
.AppendPathComponent(".lldb");
93 module_cache_dir
.AppendPathComponent("module_cache");
94 SetDefaultModuleCacheDirectory(module_cache_dir
);
95 SetModuleCacheDirectory(module_cache_dir
);
98 bool PlatformProperties::GetUseModuleCache() const {
99 const auto idx
= ePropertyUseModuleCache
;
100 return m_collection_sp
->GetPropertyAtIndexAsBoolean(
101 nullptr, idx
, g_platform_properties
[idx
].default_uint_value
!= 0);
104 bool PlatformProperties::SetUseModuleCache(bool use_module_cache
) {
105 return m_collection_sp
->SetPropertyAtIndexAsBoolean(
106 nullptr, ePropertyUseModuleCache
, use_module_cache
);
109 FileSpec
PlatformProperties::GetModuleCacheDirectory() const {
110 return m_collection_sp
->GetPropertyAtIndexAsFileSpec(
111 nullptr, ePropertyModuleCacheDirectory
);
114 bool PlatformProperties::SetModuleCacheDirectory(const FileSpec
&dir_spec
) {
115 return m_collection_sp
->SetPropertyAtIndexAsFileSpec(
116 nullptr, ePropertyModuleCacheDirectory
, dir_spec
);
119 void PlatformProperties::SetDefaultModuleCacheDirectory(
120 const FileSpec
&dir_spec
) {
121 auto f_spec_opt
= m_collection_sp
->GetPropertyAtIndexAsOptionValueFileSpec(
122 nullptr, false, ePropertyModuleCacheDirectory
);
124 f_spec_opt
->SetDefaultValue(dir_spec
);
127 /// Get the native host platform plug-in.
129 /// There should only be one of these for each host that LLDB runs
130 /// upon that should be statically compiled in and registered using
131 /// preprocessor macros or other similar build mechanisms.
133 /// This platform will be used as the default platform when launching
134 /// or attaching to processes unless another platform is specified.
135 PlatformSP
Platform::GetHostPlatform() { return GetHostPlatformSP(); }
137 static std::vector
<PlatformSP
> &GetPlatformList() {
138 static std::vector
<PlatformSP
> g_platform_list
;
139 return g_platform_list
;
142 static std::recursive_mutex
&GetPlatformListMutex() {
143 static std::recursive_mutex g_mutex
;
147 void Platform::Initialize() { g_initialize_count
++; }
149 void Platform::Terminate() {
150 if (g_initialize_count
> 0) {
151 if (--g_initialize_count
== 0) {
152 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
153 GetPlatformList().clear();
158 PlatformProperties
&Platform::GetGlobalPlatformProperties() {
159 static PlatformProperties g_settings
;
163 void Platform::SetHostPlatform(const lldb::PlatformSP
&platform_sp
) {
164 // The native platform should use its static void Platform::Initialize()
165 // function to register itself as the native platform.
166 GetHostPlatformSP() = platform_sp
;
169 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
170 GetPlatformList().push_back(platform_sp
);
174 Status
Platform::GetFileWithUUID(const FileSpec
&platform_file
,
175 const UUID
*uuid_ptr
, FileSpec
&local_file
) {
176 // Default to the local case
177 local_file
= platform_file
;
182 Platform::LocateExecutableScriptingResources(Target
*target
, Module
&module
,
183 Stream
*feedback_stream
) {
184 return FileSpecList();
188 // Platform::FindPlugin (Process *process, ConstString plugin_name)
190 // PlatformCreateInstance create_callback = nullptr;
194 // PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
195 // if (create_callback)
200 // arch = process->GetTarget().GetArchitecture();
202 // PlatformSP platform_sp(create_callback(process, &arch));
204 // return platform_sp;
209 // for (uint32_t idx = 0; (create_callback =
210 // PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != nullptr;
213 // PlatformSP platform_sp(create_callback(process, nullptr));
215 // return platform_sp;
218 // return PlatformSP();
221 Status
Platform::GetSharedModule(
222 const ModuleSpec
&module_spec
, Process
*process
, ModuleSP
&module_sp
,
223 const FileSpecList
*module_search_paths_ptr
,
224 llvm::SmallVectorImpl
<lldb::ModuleSP
> *old_modules
, bool *did_create_ptr
) {
226 return ModuleList::GetSharedModule(module_spec
, module_sp
,
227 module_search_paths_ptr
, old_modules
,
228 did_create_ptr
, false);
230 // Module resolver lambda.
231 auto resolver
= [&](const ModuleSpec
&spec
) {
232 Status
error(eErrorTypeGeneric
);
233 ModuleSpec resolved_spec
;
234 // Check if we have sysroot set.
236 // Prepend sysroot to module spec.
237 resolved_spec
= spec
;
238 resolved_spec
.GetFileSpec().PrependPathComponent(
239 m_sdk_sysroot
.GetStringRef());
240 // Try to get shared module with resolved spec.
241 error
= ModuleList::GetSharedModule(resolved_spec
, module_sp
,
242 module_search_paths_ptr
, old_modules
,
243 did_create_ptr
, false);
245 // If we don't have sysroot or it didn't work then
246 // try original module spec.
247 if (!error
.Success()) {
248 resolved_spec
= spec
;
249 error
= ModuleList::GetSharedModule(resolved_spec
, module_sp
,
250 module_search_paths_ptr
, old_modules
,
251 did_create_ptr
, false);
253 if (error
.Success() && module_sp
)
254 module_sp
->SetPlatformFileSpec(resolved_spec
.GetFileSpec());
258 return GetRemoteSharedModule(module_spec
, process
, module_sp
, resolver
,
262 bool Platform::GetModuleSpec(const FileSpec
&module_file_spec
,
263 const ArchSpec
&arch
, ModuleSpec
&module_spec
) {
264 ModuleSpecList module_specs
;
265 if (ObjectFile::GetModuleSpecifications(module_file_spec
, 0, 0,
269 ModuleSpec matched_module_spec
;
270 return module_specs
.FindMatchingModuleSpec(ModuleSpec(module_file_spec
, arch
),
274 PlatformSP
Platform::Find(ConstString name
) {
276 static ConstString
g_host_platform_name("host");
277 if (name
== g_host_platform_name
)
278 return GetHostPlatform();
280 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
281 for (const auto &platform_sp
: GetPlatformList()) {
282 if (platform_sp
->GetName() == name
)
289 PlatformSP
Platform::Create(ConstString name
, Status
&error
) {
290 PlatformCreateInstance create_callback
= nullptr;
291 lldb::PlatformSP platform_sp
;
293 static ConstString
g_host_platform_name("host");
294 if (name
== g_host_platform_name
)
295 return GetHostPlatform();
297 create_callback
= PluginManager::GetPlatformCreateCallbackForPluginName(
298 name
.GetStringRef());
300 platform_sp
= create_callback(true, nullptr);
302 error
.SetErrorStringWithFormat(
303 "unable to find a plug-in for the platform named \"%s\"",
306 error
.SetErrorString("invalid platform name");
309 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
310 GetPlatformList().push_back(platform_sp
);
316 PlatformSP
Platform::Create(const ArchSpec
&arch
, ArchSpec
*platform_arch_ptr
,
318 lldb::PlatformSP platform_sp
;
319 if (arch
.IsValid()) {
322 // First try exact arch matches across all platforms already created
323 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
324 for (const auto &platform_sp
: GetPlatformList()) {
325 if (platform_sp
->IsCompatibleArchitecture(arch
, true,
330 // Next try compatible arch matches across all platforms already created
331 for (const auto &platform_sp
: GetPlatformList()) {
332 if (platform_sp
->IsCompatibleArchitecture(arch
, false,
338 PlatformCreateInstance create_callback
;
339 // First try exact arch matches across all platform plug-ins
341 for (idx
= 0; (create_callback
=
342 PluginManager::GetPlatformCreateCallbackAtIndex(idx
));
344 if (create_callback
) {
345 platform_sp
= create_callback(false, &arch
);
347 platform_sp
->IsCompatibleArchitecture(arch
, true,
348 platform_arch_ptr
)) {
349 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
350 GetPlatformList().push_back(platform_sp
);
355 // Next try compatible arch matches across all platform plug-ins
356 for (idx
= 0; (create_callback
=
357 PluginManager::GetPlatformCreateCallbackAtIndex(idx
));
359 if (create_callback
) {
360 platform_sp
= create_callback(false, &arch
);
362 platform_sp
->IsCompatibleArchitecture(arch
, false,
363 platform_arch_ptr
)) {
364 std::lock_guard
<std::recursive_mutex
> guard(GetPlatformListMutex());
365 GetPlatformList().push_back(platform_sp
);
371 error
.SetErrorString("invalid platform name");
372 if (platform_arch_ptr
)
373 platform_arch_ptr
->Clear();
378 ArchSpec
Platform::GetAugmentedArchSpec(Platform
*platform
, llvm::StringRef triple
) {
380 return platform
->GetAugmentedArchSpec(triple
);
381 return HostInfo::GetAugmentedArchSpec(triple
);
384 /// Default Constructor
385 Platform::Platform(bool is_host
)
386 : m_is_host(is_host
), m_os_version_set_while_connected(false),
387 m_system_arch_set_while_connected(false), m_sdk_sysroot(), m_sdk_build(),
388 m_working_dir(), m_remote_url(), m_name(), m_system_arch(), m_mutex(),
389 m_max_uid_name_len(0), m_max_gid_name_len(0), m_supports_rsync(false),
390 m_rsync_opts(), m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
391 m_ignores_remote_hostname(false), m_trap_handlers(),
392 m_calculated_trap_handlers(false),
393 m_module_cache(std::make_unique
<ModuleCache
>()) {
394 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT
));
395 LLDB_LOGF(log
, "%p Platform::Platform()", static_cast<void *>(this));
398 Platform::~Platform() = default;
400 void Platform::GetStatus(Stream
&strm
) {
401 strm
.Format(" Platform: {0}\n", GetPluginName());
403 ArchSpec
arch(GetSystemArchitecture());
404 if (arch
.IsValid()) {
405 if (!arch
.GetTriple().str().empty()) {
406 strm
.Printf(" Triple: ");
407 arch
.DumpTriple(strm
.AsRawOstream());
412 llvm::VersionTuple os_version
= GetOSVersion();
413 if (!os_version
.empty()) {
414 strm
.Format("OS Version: {0}", os_version
.getAsString());
416 if (llvm::Optional
<std::string
> s
= GetOSBuildString())
417 strm
.Format(" ({0})", *s
);
423 strm
.Printf(" Hostname: %s\n", GetHostname());
425 const bool is_connected
= IsConnected();
427 strm
.Printf(" Hostname: %s\n", GetHostname());
428 strm
.Printf(" Connected: %s\n", is_connected
? "yes" : "no");
431 if (GetWorkingDirectory()) {
432 strm
.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetCString());
437 std::string
specific_info(GetPlatformSpecificConnectionInformation());
439 if (!specific_info
.empty())
440 strm
.Printf("Platform-specific connection: %s\n", specific_info
.c_str());
442 if (llvm::Optional
<std::string
> s
= GetOSKernelDescription())
443 strm
.Format(" Kernel: {0}\n", *s
);
446 llvm::VersionTuple
Platform::GetOSVersion(Process
*process
) {
447 std::lock_guard
<std::mutex
> guard(m_mutex
);
450 if (m_os_version
.empty()) {
451 // We have a local host platform
452 m_os_version
= HostInfo::GetOSVersion();
453 m_os_version_set_while_connected
= !m_os_version
.empty();
456 // We have a remote platform. We can only fetch the remote
457 // OS version if we are connected, and we don't want to do it
460 const bool is_connected
= IsConnected();
463 if (!m_os_version
.empty()) {
464 // We have valid OS version info, check to make sure it wasn't manually
465 // set prior to connecting. If it was manually set prior to connecting,
466 // then lets fetch the actual OS version info if we are now connected.
467 if (is_connected
&& !m_os_version_set_while_connected
)
470 // We don't have valid OS version info, fetch it if we are connected
471 fetch
= is_connected
;
475 m_os_version_set_while_connected
= GetRemoteOSVersion();
478 if (!m_os_version
.empty())
481 // Check with the process in case it can answer the question if a process
483 return process
->GetHostOSVersion();
485 return llvm::VersionTuple();
488 llvm::Optional
<std::string
> Platform::GetOSBuildString() {
490 return HostInfo::GetOSBuildString();
491 return GetRemoteOSBuildString();
494 llvm::Optional
<std::string
> Platform::GetOSKernelDescription() {
496 return HostInfo::GetOSKernelDescription();
497 return GetRemoteOSKernelDescription();
500 void Platform::AddClangModuleCompilationOptions(
501 Target
*target
, std::vector
<std::string
> &options
) {
502 std::vector
<std::string
> default_compilation_options
= {
503 "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc"};
505 options
.insert(options
.end(), default_compilation_options
.begin(),
506 default_compilation_options
.end());
509 FileSpec
Platform::GetWorkingDirectory() {
511 llvm::SmallString
<64> cwd
;
512 if (llvm::sys::fs::current_path(cwd
))
515 FileSpec
file_spec(cwd
);
516 FileSystem::Instance().Resolve(file_spec
);
521 m_working_dir
= GetRemoteWorkingDirectory();
522 return m_working_dir
;
526 struct RecurseCopyBaton
{
528 Platform
*platform_ptr
;
532 static FileSystem::EnumerateDirectoryResult
533 RecurseCopy_Callback(void *baton
, llvm::sys::fs::file_type ft
,
534 llvm::StringRef path
) {
535 RecurseCopyBaton
*rc_baton
= (RecurseCopyBaton
*)baton
;
537 namespace fs
= llvm::sys::fs
;
539 case fs::file_type::fifo_file
:
540 case fs::file_type::socket_file
:
541 // we have no way to copy pipes and sockets - ignore them and continue
542 return FileSystem::eEnumerateDirectoryResultNext
;
545 case fs::file_type::directory_file
: {
546 // make the new directory and get in there
547 FileSpec dst_dir
= rc_baton
->dst
;
548 if (!dst_dir
.GetFilename())
549 dst_dir
.GetFilename() = src
.GetLastPathComponent();
550 Status error
= rc_baton
->platform_ptr
->MakeDirectory(
551 dst_dir
, lldb::eFilePermissionsDirectoryDefault
);
553 rc_baton
->error
.SetErrorStringWithFormat(
554 "unable to setup directory %s on remote end", dst_dir
.GetCString());
555 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
559 std::string
src_dir_path(src
.GetPath());
561 // Make a filespec that only fills in the directory of a FileSpec so when
562 // we enumerate we can quickly fill in the filename for dst copies
563 FileSpec recurse_dst
;
564 recurse_dst
.GetDirectory().SetCString(dst_dir
.GetPath().c_str());
565 RecurseCopyBaton rc_baton2
= {recurse_dst
, rc_baton
->platform_ptr
,
567 FileSystem::Instance().EnumerateDirectory(src_dir_path
, true, true, true,
568 RecurseCopy_Callback
, &rc_baton2
);
569 if (rc_baton2
.error
.Fail()) {
570 rc_baton
->error
.SetErrorString(rc_baton2
.error
.AsCString());
571 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
573 return FileSystem::eEnumerateDirectoryResultNext
;
576 case fs::file_type::symlink_file
: {
577 // copy the file and keep going
578 FileSpec dst_file
= rc_baton
->dst
;
579 if (!dst_file
.GetFilename())
580 dst_file
.GetFilename() = src
.GetFilename();
582 FileSpec src_resolved
;
584 rc_baton
->error
= FileSystem::Instance().Readlink(src
, src_resolved
);
586 if (rc_baton
->error
.Fail())
587 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
590 rc_baton
->platform_ptr
->CreateSymlink(dst_file
, src_resolved
);
592 if (rc_baton
->error
.Fail())
593 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
595 return FileSystem::eEnumerateDirectoryResultNext
;
598 case fs::file_type::regular_file
: {
599 // copy the file and keep going
600 FileSpec dst_file
= rc_baton
->dst
;
601 if (!dst_file
.GetFilename())
602 dst_file
.GetFilename() = src
.GetFilename();
603 Status err
= rc_baton
->platform_ptr
->PutFile(src
, dst_file
);
605 rc_baton
->error
.SetErrorString(err
.AsCString());
606 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
608 return FileSystem::eEnumerateDirectoryResultNext
;
612 rc_baton
->error
.SetErrorStringWithFormat(
613 "invalid file detected during copy: %s", src
.GetPath().c_str());
614 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
617 llvm_unreachable("Unhandled file_type!");
620 Status
Platform::Install(const FileSpec
&src
, const FileSpec
&dst
) {
623 Log
*log
= GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM
);
624 LLDB_LOGF(log
, "Platform::Install (src='%s', dst='%s')",
625 src
.GetPath().c_str(), dst
.GetPath().c_str());
626 FileSpec
fixed_dst(dst
);
628 if (!fixed_dst
.GetFilename())
629 fixed_dst
.GetFilename() = src
.GetFilename();
631 FileSpec working_dir
= GetWorkingDirectory();
634 if (dst
.GetDirectory()) {
635 const char first_dst_dir_char
= dst
.GetDirectory().GetCString()[0];
636 if (first_dst_dir_char
== '/' || first_dst_dir_char
== '\\') {
637 fixed_dst
.GetDirectory() = dst
.GetDirectory();
639 // If the fixed destination file doesn't have a directory yet, then we
640 // must have a relative path. We will resolve this relative path against
641 // the platform's working directory
642 if (!fixed_dst
.GetDirectory()) {
643 FileSpec relative_spec
;
646 relative_spec
= working_dir
;
647 relative_spec
.AppendPathComponent(dst
.GetPath());
648 fixed_dst
.GetDirectory() = relative_spec
.GetDirectory();
650 error
.SetErrorStringWithFormat(
651 "platform working directory must be valid for relative path '%s'",
652 dst
.GetPath().c_str());
658 fixed_dst
.GetDirectory().SetCString(working_dir
.GetCString());
660 error
.SetErrorStringWithFormat(
661 "platform working directory must be valid for relative path '%s'",
662 dst
.GetPath().c_str());
668 fixed_dst
.GetDirectory().SetCString(working_dir
.GetCString());
670 error
.SetErrorStringWithFormat("platform working directory must be valid "
671 "when destination directory is empty");
676 LLDB_LOGF(log
, "Platform::Install (src='%s', dst='%s') fixed_dst='%s'",
677 src
.GetPath().c_str(), dst
.GetPath().c_str(),
678 fixed_dst
.GetPath().c_str());
680 if (GetSupportsRSync()) {
681 error
= PutFile(src
, dst
);
683 namespace fs
= llvm::sys::fs
;
684 switch (fs::get_file_type(src
.GetPath(), false)) {
685 case fs::file_type::directory_file
: {
686 llvm::sys::fs::remove(fixed_dst
.GetPath());
687 uint32_t permissions
= FileSystem::Instance().GetPermissions(src
);
688 if (permissions
== 0)
689 permissions
= eFilePermissionsDirectoryDefault
;
690 error
= MakeDirectory(fixed_dst
, permissions
);
691 if (error
.Success()) {
692 // Make a filespec that only fills in the directory of a FileSpec so
693 // when we enumerate we can quickly fill in the filename for dst copies
694 FileSpec recurse_dst
;
695 recurse_dst
.GetDirectory().SetCString(fixed_dst
.GetCString());
696 std::string
src_dir_path(src
.GetPath());
697 RecurseCopyBaton baton
= {recurse_dst
, this, Status()};
698 FileSystem::Instance().EnumerateDirectory(
699 src_dir_path
, true, true, true, RecurseCopy_Callback
, &baton
);
704 case fs::file_type::regular_file
:
705 llvm::sys::fs::remove(fixed_dst
.GetPath());
706 error
= PutFile(src
, fixed_dst
);
709 case fs::file_type::symlink_file
: {
710 llvm::sys::fs::remove(fixed_dst
.GetPath());
711 FileSpec src_resolved
;
712 error
= FileSystem::Instance().Readlink(src
, src_resolved
);
714 error
= CreateSymlink(dst
, src_resolved
);
716 case fs::file_type::fifo_file
:
717 error
.SetErrorString("platform install doesn't handle pipes");
719 case fs::file_type::socket_file
:
720 error
.SetErrorString("platform install doesn't handle sockets");
723 error
.SetErrorString(
724 "platform install doesn't handle non file or directory items");
731 bool Platform::SetWorkingDirectory(const FileSpec
&file_spec
) {
733 Log
*log
= GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM
);
734 LLDB_LOG(log
, "{0}", file_spec
);
735 if (std::error_code ec
= llvm::sys::fs::set_current_path(file_spec
.GetPath())) {
736 LLDB_LOG(log
, "error: {0}", ec
.message());
741 m_working_dir
.Clear();
742 return SetRemoteWorkingDirectory(file_spec
);
746 Status
Platform::MakeDirectory(const FileSpec
&file_spec
,
747 uint32_t permissions
) {
749 return llvm::sys::fs::create_directory(file_spec
.GetPath(), permissions
);
752 error
.SetErrorStringWithFormatv("remote platform {0} doesn't support {1}",
753 GetPluginName(), LLVM_PRETTY_FUNCTION
);
758 Status
Platform::GetFilePermissions(const FileSpec
&file_spec
,
759 uint32_t &file_permissions
) {
761 auto Value
= llvm::sys::fs::getPermissions(file_spec
.GetPath());
763 file_permissions
= Value
.get();
764 return Status(Value
.getError());
767 error
.SetErrorStringWithFormatv("remote platform {0} doesn't support {1}",
768 GetPluginName(), LLVM_PRETTY_FUNCTION
);
773 Status
Platform::SetFilePermissions(const FileSpec
&file_spec
,
774 uint32_t file_permissions
) {
776 auto Perms
= static_cast<llvm::sys::fs::perms
>(file_permissions
);
777 return llvm::sys::fs::setPermissions(file_spec
.GetPath(), Perms
);
780 error
.SetErrorStringWithFormatv("remote platform {0} doesn't support {1}",
781 GetPluginName(), LLVM_PRETTY_FUNCTION
);
786 ConstString
Platform::GetName() { return ConstString(GetPluginName()); }
788 const char *Platform::GetHostname() {
794 return m_name
.c_str();
797 ConstString
Platform::GetFullNameForDylib(ConstString basename
) {
801 bool Platform::SetRemoteWorkingDirectory(const FileSpec
&working_dir
) {
802 Log
*log
= GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM
);
803 LLDB_LOGF(log
, "Platform::SetRemoteWorkingDirectory('%s')",
804 working_dir
.GetCString());
805 m_working_dir
= working_dir
;
809 bool Platform::SetOSVersion(llvm::VersionTuple version
) {
811 // We don't need anyone setting the OS version for the host platform, we
812 // should be able to figure it out by calling HostInfo::GetOSVersion(...).
815 // We have a remote platform, allow setting the target OS version if we
816 // aren't connected, since if we are connected, we should be able to
817 // request the remote OS version from the connected platform.
821 // We aren't connected and we might want to set the OS version ahead of
822 // time before we connect so we can peruse files and use a local SDK or
823 // PDK cache of support files to disassemble or do other things.
824 m_os_version
= version
;
832 Platform::ResolveExecutable(const ModuleSpec
&module_spec
,
833 lldb::ModuleSP
&exe_module_sp
,
834 const FileSpecList
*module_search_paths_ptr
) {
837 if (FileSystem::Instance().Exists(module_spec
.GetFileSpec())) {
838 if (module_spec
.GetArchitecture().IsValid()) {
839 error
= ModuleList::GetSharedModule(module_spec
, exe_module_sp
,
840 module_search_paths_ptr
, nullptr,
843 // No valid architecture was specified, ask the platform for the
844 // architectures that we should be using (in the correct order) and see
845 // if we can find a match that way
846 ModuleSpec
arch_module_spec(module_spec
);
847 for (const ArchSpec
&arch
: GetSupportedArchitectures()) {
848 arch_module_spec
.GetArchitecture() = arch
;
849 error
= ModuleList::GetSharedModule(arch_module_spec
, exe_module_sp
,
850 module_search_paths_ptr
, nullptr,
852 // Did we find an executable using one of the
853 if (error
.Success() && exe_module_sp
)
858 error
.SetErrorStringWithFormat(
859 "'%s' does not exist", module_spec
.GetFileSpec().GetPath().c_str());
865 Platform::ResolveRemoteExecutable(const ModuleSpec
&module_spec
,
866 lldb::ModuleSP
&exe_module_sp
,
867 const FileSpecList
*module_search_paths_ptr
) {
870 // We may connect to a process and use the provided executable (Don't use
872 ModuleSpec
resolved_module_spec(module_spec
);
874 // Resolve any executable within a bundle on MacOSX
875 Host::ResolveExecutableInBundle(resolved_module_spec
.GetFileSpec());
877 if (FileSystem::Instance().Exists(resolved_module_spec
.GetFileSpec()) ||
878 module_spec
.GetUUID().IsValid()) {
879 if (resolved_module_spec
.GetArchitecture().IsValid() ||
880 resolved_module_spec
.GetUUID().IsValid()) {
881 error
= ModuleList::GetSharedModule(resolved_module_spec
, exe_module_sp
,
882 module_search_paths_ptr
, nullptr,
885 if (exe_module_sp
&& exe_module_sp
->GetObjectFile())
887 exe_module_sp
.reset();
889 // No valid architecture was specified or the exact arch wasn't found so
890 // ask the platform for the architectures that we should be using (in the
891 // correct order) and see if we can find a match that way
892 StreamString arch_names
;
893 llvm::ListSeparator LS
;
894 for (const ArchSpec
&arch
: GetSupportedArchitectures()) {
895 resolved_module_spec
.GetArchitecture() = arch
;
896 error
= ModuleList::GetSharedModule(resolved_module_spec
, exe_module_sp
,
897 module_search_paths_ptr
, nullptr,
899 // Did we find an executable using one of the
900 if (error
.Success()) {
901 if (exe_module_sp
&& exe_module_sp
->GetObjectFile())
904 error
.SetErrorToGenericError();
907 arch_names
<< LS
<< arch
.GetArchitectureName();
910 if (error
.Fail() || !exe_module_sp
) {
911 if (FileSystem::Instance().Readable(resolved_module_spec
.GetFileSpec())) {
912 error
.SetErrorStringWithFormatv(
913 "'{0}' doesn't contain any '{1}' platform architectures: {2}",
914 resolved_module_spec
.GetFileSpec(), GetPluginName(),
915 arch_names
.GetData());
917 error
.SetErrorStringWithFormatv("'{0}' is not readable",
918 resolved_module_spec
.GetFileSpec());
922 error
.SetErrorStringWithFormatv("'{0}' does not exist",
923 resolved_module_spec
.GetFileSpec());
929 Status
Platform::ResolveSymbolFile(Target
&target
, const ModuleSpec
&sym_spec
,
930 FileSpec
&sym_file
) {
932 if (FileSystem::Instance().Exists(sym_spec
.GetSymbolFileSpec()))
933 sym_file
= sym_spec
.GetSymbolFileSpec();
935 error
.SetErrorString("unable to resolve symbol file");
939 bool Platform::ResolveRemotePath(const FileSpec
&platform_path
,
940 FileSpec
&resolved_platform_path
) {
941 resolved_platform_path
= platform_path
;
942 FileSystem::Instance().Resolve(resolved_platform_path
);
946 const ArchSpec
&Platform::GetSystemArchitecture() {
948 if (!m_system_arch
.IsValid()) {
949 // We have a local host platform
950 m_system_arch
= HostInfo::GetArchitecture();
951 m_system_arch_set_while_connected
= m_system_arch
.IsValid();
954 // We have a remote platform. We can only fetch the remote system
955 // architecture if we are connected, and we don't want to do it more than
958 const bool is_connected
= IsConnected();
961 if (m_system_arch
.IsValid()) {
962 // We have valid OS version info, check to make sure it wasn't manually
963 // set prior to connecting. If it was manually set prior to connecting,
964 // then lets fetch the actual OS version info if we are now connected.
965 if (is_connected
&& !m_system_arch_set_while_connected
)
968 // We don't have valid OS version info, fetch it if we are connected
969 fetch
= is_connected
;
973 m_system_arch
= GetRemoteSystemArchitecture();
974 m_system_arch_set_while_connected
= m_system_arch
.IsValid();
977 return m_system_arch
;
980 ArchSpec
Platform::GetAugmentedArchSpec(llvm::StringRef triple
) {
983 llvm::Triple
normalized_triple(llvm::Triple::normalize(triple
));
984 if (!ArchSpec::ContainsOnlyArch(normalized_triple
))
985 return ArchSpec(triple
);
987 if (auto kind
= HostInfo::ParseArchitectureKind(triple
))
988 return HostInfo::GetArchitecture(*kind
);
990 ArchSpec compatible_arch
;
991 ArchSpec
raw_arch(triple
);
992 if (!IsCompatibleArchitecture(raw_arch
, false, &compatible_arch
))
995 if (!compatible_arch
.IsValid())
996 return ArchSpec(normalized_triple
);
998 const llvm::Triple
&compatible_triple
= compatible_arch
.GetTriple();
999 if (normalized_triple
.getVendorName().empty())
1000 normalized_triple
.setVendor(compatible_triple
.getVendor());
1001 if (normalized_triple
.getOSName().empty())
1002 normalized_triple
.setOS(compatible_triple
.getOS());
1003 if (normalized_triple
.getEnvironmentName().empty())
1004 normalized_triple
.setEnvironment(compatible_triple
.getEnvironment());
1005 return ArchSpec(normalized_triple
);
1008 Status
Platform::ConnectRemote(Args
&args
) {
1011 error
.SetErrorStringWithFormatv(
1012 "The currently selected platform ({0}) is "
1013 "the host platform and is always connected.",
1016 error
.SetErrorStringWithFormatv(
1017 "Platform::ConnectRemote() is not supported by {0}", GetPluginName());
1021 Status
Platform::DisconnectRemote() {
1024 error
.SetErrorStringWithFormatv(
1025 "The currently selected platform ({0}) is "
1026 "the host platform and is always connected.",
1029 error
.SetErrorStringWithFormatv(
1030 "Platform::DisconnectRemote() is not supported by {0}",
1035 bool Platform::GetProcessInfo(lldb::pid_t pid
,
1036 ProcessInstanceInfo
&process_info
) {
1037 // Take care of the host case so that each subclass can just call this
1038 // function to get the host functionality.
1040 return Host::GetProcessInfo(pid
, process_info
);
1044 uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch
&match_info
,
1045 ProcessInstanceInfoList
&process_infos
) {
1046 // Take care of the host case so that each subclass can just call this
1047 // function to get the host functionality.
1048 uint32_t match_count
= 0;
1050 match_count
= Host::FindProcesses(match_info
, process_infos
);
1054 Status
Platform::LaunchProcess(ProcessLaunchInfo
&launch_info
) {
1056 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM
));
1057 LLDB_LOGF(log
, "Platform::%s()", __FUNCTION__
);
1059 // Take care of the host case so that each subclass can just call this
1060 // function to get the host functionality.
1062 if (::getenv("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
1063 launch_info
.GetFlags().Set(eLaunchFlagLaunchInTTY
);
1065 if (launch_info
.GetFlags().Test(eLaunchFlagLaunchInShell
)) {
1066 const bool will_debug
= launch_info
.GetFlags().Test(eLaunchFlagDebug
);
1067 const bool first_arg_is_full_shell_command
= false;
1068 uint32_t num_resumes
= GetResumeCountForLaunchInfo(launch_info
);
1070 const FileSpec
&shell
= launch_info
.GetShell();
1071 std::string shell_str
= (shell
) ? shell
.GetPath() : "<null>";
1073 "Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32
1075 __FUNCTION__
, num_resumes
, shell_str
.c_str());
1078 if (!launch_info
.ConvertArgumentsForLaunchingInShell(
1079 error
, will_debug
, first_arg_is_full_shell_command
, num_resumes
))
1081 } else if (launch_info
.GetFlags().Test(eLaunchFlagShellExpandArguments
)) {
1082 error
= ShellExpandArguments(launch_info
);
1084 error
.SetErrorStringWithFormat("shell expansion failed (reason: %s). "
1085 "consider launching with 'process "
1087 error
.AsCString("unknown"));
1092 LLDB_LOGF(log
, "Platform::%s final launch_info resume count: %" PRIu32
,
1093 __FUNCTION__
, launch_info
.GetResumeCount());
1095 error
= Host::LaunchProcess(launch_info
);
1097 error
.SetErrorString(
1098 "base lldb_private::Platform class can't launch remote processes");
1102 Status
Platform::ShellExpandArguments(ProcessLaunchInfo
&launch_info
) {
1104 return Host::ShellExpandArguments(launch_info
);
1105 return Status("base lldb_private::Platform class can't expand arguments");
1108 Status
Platform::KillProcess(const lldb::pid_t pid
) {
1109 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM
));
1110 LLDB_LOGF(log
, "Platform::%s, pid %" PRIu64
, __FUNCTION__
, pid
);
1114 "base lldb_private::Platform class can't kill remote processes");
1116 Host::Kill(pid
, SIGKILL
);
1120 lldb::ProcessSP
Platform::DebugProcess(ProcessLaunchInfo
&launch_info
,
1121 Debugger
&debugger
, Target
&target
,
1123 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM
));
1124 LLDB_LOG(log
, "target = {0})", &target
);
1126 ProcessSP process_sp
;
1127 // Make sure we stop at the entry point
1128 launch_info
.GetFlags().Set(eLaunchFlagDebug
);
1129 // We always launch the process we are going to debug in a separate process
1130 // group, since then we can handle ^C interrupts ourselves w/o having to
1131 // worry about the target getting them as well.
1132 launch_info
.SetLaunchInSeparateProcessGroup(true);
1134 // Allow any StructuredData process-bound plugins to adjust the launch info
1137 bool iteration_complete
= false;
1138 // Note iteration can't simply go until a nullptr callback is returned, as it
1139 // is valid for a plugin to not supply a filter.
1140 auto get_filter_func
= PluginManager::GetStructuredDataFilterCallbackAtIndex
;
1141 for (auto filter_callback
= get_filter_func(i
, iteration_complete
);
1142 !iteration_complete
;
1143 filter_callback
= get_filter_func(++i
, iteration_complete
)) {
1144 if (filter_callback
) {
1145 // Give this ProcessLaunchInfo filter a chance to adjust the launch info.
1146 error
= (*filter_callback
)(launch_info
, &target
);
1147 if (!error
.Success()) {
1149 "Platform::%s() StructuredDataPlugin launch "
1157 error
= LaunchProcess(launch_info
);
1158 if (error
.Success()) {
1160 "Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64
")",
1161 __FUNCTION__
, launch_info
.GetProcessID());
1162 if (launch_info
.GetProcessID() != LLDB_INVALID_PROCESS_ID
) {
1163 ProcessAttachInfo
attach_info(launch_info
);
1164 process_sp
= Attach(attach_info
, debugger
, &target
, error
);
1166 LLDB_LOG(log
, "Attach() succeeded, Process plugin: {0}",
1167 process_sp
->GetPluginName());
1168 launch_info
.SetHijackListener(attach_info
.GetHijackListener());
1170 // Since we attached to the process, it will think it needs to detach
1171 // if the process object just goes away without an explicit call to
1172 // Process::Kill() or Process::Detach(), so let it know to kill the
1173 // process if this happens.
1174 process_sp
->SetShouldDetach(false);
1176 // If we didn't have any file actions, the pseudo terminal might have
1177 // been used where the secondary side was given as the file to open for
1178 // stdin/out/err after we have already opened the primary so we can
1179 // read/write stdin/out/err.
1180 int pty_fd
= launch_info
.GetPTY().ReleasePrimaryFileDescriptor();
1181 if (pty_fd
!= PseudoTerminal::invalid_fd
) {
1182 process_sp
->SetSTDIOFileDescriptor(pty_fd
);
1185 LLDB_LOGF(log
, "Platform::%s Attach() failed: %s", __FUNCTION__
,
1190 "Platform::%s LaunchProcess() returned launch_info with "
1191 "invalid process id",
1195 LLDB_LOGF(log
, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__
,
1203 Platform::GetPlatformForArchitecture(const ArchSpec
&arch
,
1204 ArchSpec
*platform_arch_ptr
) {
1205 lldb::PlatformSP platform_sp
;
1208 platform_sp
= Platform::Create(arch
, platform_arch_ptr
, error
);
1212 std::vector
<ArchSpec
>
1213 Platform::CreateArchList(llvm::ArrayRef
<llvm::Triple::ArchType
> archs
,
1214 llvm::Triple::OSType os
) {
1215 std::vector
<ArchSpec
> list
;
1216 for(auto arch
: archs
) {
1217 llvm::Triple triple
;
1218 triple
.setArch(arch
);
1220 list
.push_back(ArchSpec(triple
));
1225 /// Lets a platform answer if it is compatible with a given
1226 /// architecture and the target triple contained within.
1227 bool Platform::IsCompatibleArchitecture(const ArchSpec
&arch
,
1228 bool exact_arch_match
,
1229 ArchSpec
*compatible_arch_ptr
) {
1230 // If the architecture is invalid, we must answer true...
1231 if (arch
.IsValid()) {
1232 ArchSpec platform_arch
;
1233 auto match
= exact_arch_match
? &ArchSpec::IsExactMatch
1234 : &ArchSpec::IsCompatibleMatch
;
1235 for (const ArchSpec
&platform_arch
: GetSupportedArchitectures()) {
1236 if ((arch
.*match
)(platform_arch
)) {
1237 if (compatible_arch_ptr
)
1238 *compatible_arch_ptr
= platform_arch
;
1243 if (compatible_arch_ptr
)
1244 compatible_arch_ptr
->Clear();
1248 Status
Platform::PutFile(const FileSpec
&source
, const FileSpec
&destination
,
1249 uint32_t uid
, uint32_t gid
) {
1250 Log
*log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM
));
1251 LLDB_LOGF(log
, "[PutFile] Using block by block transfer....\n");
1253 auto source_open_options
=
1254 File::eOpenOptionReadOnly
| File::eOpenOptionCloseOnExec
;
1255 namespace fs
= llvm::sys::fs
;
1256 if (fs::is_symlink_file(source
.GetPath()))
1257 source_open_options
|= File::eOpenOptionDontFollowSymlinks
;
1259 auto source_file
= FileSystem::Instance().Open(source
, source_open_options
,
1260 lldb::eFilePermissionsUserRW
);
1262 return Status(source_file
.takeError());
1264 uint32_t permissions
= source_file
.get()->GetPermissions(error
);
1265 if (permissions
== 0)
1266 permissions
= lldb::eFilePermissionsFileDefault
;
1268 lldb::user_id_t dest_file
= OpenFile(
1269 destination
, File::eOpenOptionCanCreate
| File::eOpenOptionWriteOnly
|
1270 File::eOpenOptionTruncate
| File::eOpenOptionCloseOnExec
,
1271 permissions
, error
);
1272 LLDB_LOGF(log
, "dest_file = %" PRIu64
"\n", dest_file
);
1276 if (dest_file
== UINT64_MAX
)
1277 return Status("unable to open target file");
1278 lldb::DataBufferSP
buffer_sp(new DataBufferHeap(1024 * 16, 0));
1279 uint64_t offset
= 0;
1281 size_t bytes_read
= buffer_sp
->GetByteSize();
1282 error
= source_file
.get()->Read(buffer_sp
->GetBytes(), bytes_read
);
1283 if (error
.Fail() || bytes_read
== 0)
1286 const uint64_t bytes_written
=
1287 WriteFile(dest_file
, offset
, buffer_sp
->GetBytes(), bytes_read
, error
);
1291 offset
+= bytes_written
;
1292 if (bytes_written
!= bytes_read
) {
1293 // We didn't write the correct number of bytes, so adjust the file
1294 // position in the source file we are reading from...
1295 source_file
.get()->SeekFromStart(offset
);
1298 CloseFile(dest_file
, error
);
1300 if (uid
== UINT32_MAX
&& gid
== UINT32_MAX
)
1308 Status
Platform::GetFile(const FileSpec
&source
, const FileSpec
&destination
) {
1309 Status
error("unimplemented");
1314 Platform::CreateSymlink(const FileSpec
&src
, // The name of the link is in src
1315 const FileSpec
&dst
) // The symlink points to dst
1317 Status
error("unimplemented");
1321 bool Platform::GetFileExists(const lldb_private::FileSpec
&file_spec
) {
1325 Status
Platform::Unlink(const FileSpec
&path
) {
1326 Status
error("unimplemented");
1330 MmapArgList
Platform::GetMmapArgumentList(const ArchSpec
&arch
, addr_t addr
,
1331 addr_t length
, unsigned prot
,
1332 unsigned flags
, addr_t fd
,
1334 uint64_t flags_platform
= 0;
1335 if (flags
& eMmapFlagsPrivate
)
1336 flags_platform
|= MAP_PRIVATE
;
1337 if (flags
& eMmapFlagsAnon
)
1338 flags_platform
|= MAP_ANON
;
1340 MmapArgList
args({addr
, length
, prot
, flags_platform
, fd
, offset
});
1344 lldb_private::Status
Platform::RunShellCommand(
1345 llvm::StringRef command
,
1347 working_dir
, // Pass empty FileSpec to use the current working directory
1348 int *status_ptr
, // Pass nullptr if you don't want the process exit status
1349 int *signo_ptr
, // Pass nullptr if you don't want the signal that caused the
1352 *command_output
, // Pass nullptr if you don't want the command output
1353 const Timeout
<std::micro
> &timeout
) {
1354 return RunShellCommand(llvm::StringRef(), command
, working_dir
, status_ptr
,
1355 signo_ptr
, command_output
, timeout
);
1358 lldb_private::Status
Platform::RunShellCommand(
1359 llvm::StringRef shell
, // Pass empty if you want to use the default
1360 // shell interpreter
1361 llvm::StringRef command
, // Shouldn't be empty
1363 working_dir
, // Pass empty FileSpec to use the current working directory
1364 int *status_ptr
, // Pass nullptr if you don't want the process exit status
1365 int *signo_ptr
, // Pass nullptr if you don't want the signal that caused the
1368 *command_output
, // Pass nullptr if you don't want the command output
1369 const Timeout
<std::micro
> &timeout
) {
1371 return Host::RunShellCommand(shell
, command
, working_dir
, status_ptr
,
1372 signo_ptr
, command_output
, timeout
);
1374 return Status("unimplemented");
1377 bool Platform::CalculateMD5(const FileSpec
&file_spec
, uint64_t &low
,
1381 auto Result
= llvm::sys::fs::md5_contents(file_spec
.GetPath());
1384 std::tie(high
, low
) = Result
->words();
1388 void Platform::SetLocalCacheDirectory(const char *local
) {
1389 m_local_cache_directory
.assign(local
);
1392 const char *Platform::GetLocalCacheDirectory() {
1393 return m_local_cache_directory
.c_str();
1396 static constexpr OptionDefinition g_rsync_option_table
[] = {
1397 {LLDB_OPT_SET_ALL
, false, "rsync", 'r', OptionParser::eNoArgument
, nullptr,
1398 {}, 0, eArgTypeNone
, "Enable rsync."},
1399 {LLDB_OPT_SET_ALL
, false, "rsync-opts", 'R',
1400 OptionParser::eRequiredArgument
, nullptr, {}, 0, eArgTypeCommandName
,
1401 "Platform-specific options required for rsync to work."},
1402 {LLDB_OPT_SET_ALL
, false, "rsync-prefix", 'P',
1403 OptionParser::eRequiredArgument
, nullptr, {}, 0, eArgTypeCommandName
,
1404 "Platform-specific rsync prefix put before the remote path."},
1405 {LLDB_OPT_SET_ALL
, false, "ignore-remote-hostname", 'i',
1406 OptionParser::eNoArgument
, nullptr, {}, 0, eArgTypeNone
,
1407 "Do not automatically fill in the remote hostname when composing the "
1411 static constexpr OptionDefinition g_ssh_option_table
[] = {
1412 {LLDB_OPT_SET_ALL
, false, "ssh", 's', OptionParser::eNoArgument
, nullptr,
1413 {}, 0, eArgTypeNone
, "Enable SSH."},
1414 {LLDB_OPT_SET_ALL
, false, "ssh-opts", 'S', OptionParser::eRequiredArgument
,
1415 nullptr, {}, 0, eArgTypeCommandName
,
1416 "Platform-specific options required for SSH to work."},
1419 static constexpr OptionDefinition g_caching_option_table
[] = {
1420 {LLDB_OPT_SET_ALL
, false, "local-cache-dir", 'c',
1421 OptionParser::eRequiredArgument
, nullptr, {}, 0, eArgTypePath
,
1422 "Path in which to store local copies of files."},
1425 llvm::ArrayRef
<OptionDefinition
> OptionGroupPlatformRSync::GetDefinitions() {
1426 return llvm::makeArrayRef(g_rsync_option_table
);
1429 void OptionGroupPlatformRSync::OptionParsingStarting(
1430 ExecutionContext
*execution_context
) {
1432 m_rsync_opts
.clear();
1433 m_rsync_prefix
.clear();
1434 m_ignores_remote_hostname
= false;
1437 lldb_private::Status
1438 OptionGroupPlatformRSync::SetOptionValue(uint32_t option_idx
,
1439 llvm::StringRef option_arg
,
1440 ExecutionContext
*execution_context
) {
1442 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1443 switch (short_option
) {
1449 m_rsync_opts
.assign(std::string(option_arg
));
1453 m_rsync_prefix
.assign(std::string(option_arg
));
1457 m_ignores_remote_hostname
= true;
1461 error
.SetErrorStringWithFormat("unrecognized option '%c'", short_option
);
1469 Platform::SetThreadCreationBreakpoint(lldb_private::Target
&target
) {
1470 return lldb::BreakpointSP();
1473 llvm::ArrayRef
<OptionDefinition
> OptionGroupPlatformSSH::GetDefinitions() {
1474 return llvm::makeArrayRef(g_ssh_option_table
);
1477 void OptionGroupPlatformSSH::OptionParsingStarting(
1478 ExecutionContext
*execution_context
) {
1483 lldb_private::Status
1484 OptionGroupPlatformSSH::SetOptionValue(uint32_t option_idx
,
1485 llvm::StringRef option_arg
,
1486 ExecutionContext
*execution_context
) {
1488 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1489 switch (short_option
) {
1495 m_ssh_opts
.assign(std::string(option_arg
));
1499 error
.SetErrorStringWithFormat("unrecognized option '%c'", short_option
);
1506 llvm::ArrayRef
<OptionDefinition
> OptionGroupPlatformCaching::GetDefinitions() {
1507 return llvm::makeArrayRef(g_caching_option_table
);
1510 void OptionGroupPlatformCaching::OptionParsingStarting(
1511 ExecutionContext
*execution_context
) {
1512 m_cache_dir
.clear();
1515 lldb_private::Status
OptionGroupPlatformCaching::SetOptionValue(
1516 uint32_t option_idx
, llvm::StringRef option_arg
,
1517 ExecutionContext
*execution_context
) {
1519 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1520 switch (short_option
) {
1522 m_cache_dir
.assign(std::string(option_arg
));
1526 error
.SetErrorStringWithFormat("unrecognized option '%c'", short_option
);
1533 Environment
Platform::GetEnvironment() { return Environment(); }
1535 const std::vector
<ConstString
> &Platform::GetTrapHandlerSymbolNames() {
1536 if (!m_calculated_trap_handlers
) {
1537 std::lock_guard
<std::mutex
> guard(m_mutex
);
1538 if (!m_calculated_trap_handlers
) {
1539 CalculateTrapHandlerSymbolNames();
1540 m_calculated_trap_handlers
= true;
1543 return m_trap_handlers
;
1547 Platform::GetCachedExecutable(ModuleSpec
&module_spec
,
1548 lldb::ModuleSP
&module_sp
,
1549 const FileSpecList
*module_search_paths_ptr
) {
1550 FileSpec platform_spec
= module_spec
.GetFileSpec();
1551 Status error
= GetRemoteSharedModule(
1552 module_spec
, nullptr, module_sp
,
1553 [&](const ModuleSpec
&spec
) {
1554 return ResolveRemoteExecutable(spec
, module_sp
,
1555 module_search_paths_ptr
);
1558 if (error
.Success()) {
1559 module_spec
.GetFileSpec() = module_sp
->GetFileSpec();
1560 module_spec
.GetPlatformFileSpec() = platform_spec
;
1566 Status
Platform::GetRemoteSharedModule(const ModuleSpec
&module_spec
,
1568 lldb::ModuleSP
&module_sp
,
1569 const ModuleResolver
&module_resolver
,
1570 bool *did_create_ptr
) {
1571 // Get module information from a target.
1572 ModuleSpec resolved_module_spec
;
1573 bool got_module_spec
= false;
1575 // Try to get module information from the process
1576 if (process
->GetModuleSpec(module_spec
.GetFileSpec(),
1577 module_spec
.GetArchitecture(),
1578 resolved_module_spec
)) {
1579 if (!module_spec
.GetUUID().IsValid() ||
1580 module_spec
.GetUUID() == resolved_module_spec
.GetUUID()) {
1581 got_module_spec
= true;
1586 if (!module_spec
.GetArchitecture().IsValid()) {
1588 // No valid architecture was specified, ask the platform for the
1589 // architectures that we should be using (in the correct order) and see if
1590 // we can find a match that way
1591 ModuleSpec
arch_module_spec(module_spec
);
1592 for (const ArchSpec
&arch
: GetSupportedArchitectures()) {
1593 arch_module_spec
.GetArchitecture() = arch
;
1594 error
= ModuleList::GetSharedModule(arch_module_spec
, module_sp
, nullptr,
1596 // Did we find an executable using one of the
1597 if (error
.Success() && module_sp
)
1601 resolved_module_spec
= arch_module_spec
;
1602 got_module_spec
= true;
1606 if (!got_module_spec
) {
1607 // Get module information from a target.
1608 if (GetModuleSpec(module_spec
.GetFileSpec(), module_spec
.GetArchitecture(),
1609 resolved_module_spec
)) {
1610 if (!module_spec
.GetUUID().IsValid() ||
1611 module_spec
.GetUUID() == resolved_module_spec
.GetUUID()) {
1612 got_module_spec
= true;
1617 if (!got_module_spec
) {
1618 // Fall back to the given module resolver, which may have its own
1620 return module_resolver(module_spec
);
1623 // If we are looking for a specific UUID, make sure resolved_module_spec has
1624 // the same one before we search.
1625 if (module_spec
.GetUUID().IsValid()) {
1626 resolved_module_spec
.GetUUID() = module_spec
.GetUUID();
1629 // Trying to find a module by UUID on local file system.
1630 const auto error
= module_resolver(resolved_module_spec
);
1632 if (GetCachedSharedModule(resolved_module_spec
, module_sp
, did_create_ptr
))
1639 bool Platform::GetCachedSharedModule(const ModuleSpec
&module_spec
,
1640 lldb::ModuleSP
&module_sp
,
1641 bool *did_create_ptr
) {
1642 if (IsHost() || !GetGlobalPlatformProperties().GetUseModuleCache() ||
1643 !GetGlobalPlatformProperties().GetModuleCacheDirectory())
1646 Log
*log
= GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM
);
1648 // Check local cache for a module.
1649 auto error
= m_module_cache
->GetAndPut(
1650 GetModuleCacheRoot(), GetCacheHostname(), module_spec
,
1651 [this](const ModuleSpec
&module_spec
,
1652 const FileSpec
&tmp_download_file_spec
) {
1653 return DownloadModuleSlice(
1654 module_spec
.GetFileSpec(), module_spec
.GetObjectOffset(),
1655 module_spec
.GetObjectSize(), tmp_download_file_spec
);
1658 [this](const ModuleSP
&module_sp
,
1659 const FileSpec
&tmp_download_file_spec
) {
1660 return DownloadSymbolFile(module_sp
, tmp_download_file_spec
);
1662 module_sp
, did_create_ptr
);
1663 if (error
.Success())
1666 LLDB_LOGF(log
, "Platform::%s - module %s not found in local cache: %s",
1667 __FUNCTION__
, module_spec
.GetUUID().GetAsString().c_str(),
1672 Status
Platform::DownloadModuleSlice(const FileSpec
&src_file_spec
,
1673 const uint64_t src_offset
,
1674 const uint64_t src_size
,
1675 const FileSpec
&dst_file_spec
) {
1679 llvm::raw_fd_ostream
dst(dst_file_spec
.GetPath(), EC
, llvm::sys::fs::OF_None
);
1681 error
.SetErrorStringWithFormat("unable to open destination file: %s",
1682 dst_file_spec
.GetPath().c_str());
1686 auto src_fd
= OpenFile(src_file_spec
, File::eOpenOptionReadOnly
,
1687 lldb::eFilePermissionsFileDefault
, error
);
1690 error
.SetErrorStringWithFormat("unable to open source file: %s",
1695 std::vector
<char> buffer(1024);
1696 auto offset
= src_offset
;
1697 uint64_t total_bytes_read
= 0;
1698 while (total_bytes_read
< src_size
) {
1699 const auto to_read
= std::min(static_cast<uint64_t>(buffer
.size()),
1700 src_size
- total_bytes_read
);
1701 const uint64_t n_read
=
1702 ReadFile(src_fd
, offset
, &buffer
[0], to_read
, error
);
1706 error
.SetErrorString("read 0 bytes");
1710 total_bytes_read
+= n_read
;
1711 dst
.write(&buffer
[0], n_read
);
1715 CloseFile(src_fd
, close_error
); // Ignoring close error.
1720 Status
Platform::DownloadSymbolFile(const lldb::ModuleSP
&module_sp
,
1721 const FileSpec
&dst_file_spec
) {
1723 "Symbol file downloading not supported by the default platform.");
1726 FileSpec
Platform::GetModuleCacheRoot() {
1727 auto dir_spec
= GetGlobalPlatformProperties().GetModuleCacheDirectory();
1728 dir_spec
.AppendPathComponent(GetName().AsCString());
1732 const char *Platform::GetCacheHostname() { return GetHostname(); }
1734 const UnixSignalsSP
&Platform::GetRemoteUnixSignals() {
1735 static const auto s_default_unix_signals_sp
= std::make_shared
<UnixSignals
>();
1736 return s_default_unix_signals_sp
;
1739 UnixSignalsSP
Platform::GetUnixSignals() {
1741 return UnixSignals::CreateForHost();
1742 return GetRemoteUnixSignals();
1745 uint32_t Platform::LoadImage(lldb_private::Process
*process
,
1746 const lldb_private::FileSpec
&local_file
,
1747 const lldb_private::FileSpec
&remote_file
,
1748 lldb_private::Status
&error
) {
1749 if (local_file
&& remote_file
) {
1750 // Both local and remote file was specified. Install the local file to the
1752 if (IsRemote() || local_file
!= remote_file
) {
1753 error
= Install(local_file
, remote_file
);
1755 return LLDB_INVALID_IMAGE_TOKEN
;
1757 return DoLoadImage(process
, remote_file
, nullptr, error
);
1761 // Only local file was specified. Install it to the current working
1763 FileSpec target_file
= GetWorkingDirectory();
1764 target_file
.AppendPathComponent(local_file
.GetFilename().AsCString());
1765 if (IsRemote() || local_file
!= target_file
) {
1766 error
= Install(local_file
, target_file
);
1768 return LLDB_INVALID_IMAGE_TOKEN
;
1770 return DoLoadImage(process
, target_file
, nullptr, error
);
1774 // Only remote file was specified so we don't have to do any copying
1775 return DoLoadImage(process
, remote_file
, nullptr, error
);
1778 error
.SetErrorString("Neither local nor remote file was specified");
1779 return LLDB_INVALID_IMAGE_TOKEN
;
1782 uint32_t Platform::DoLoadImage(lldb_private::Process
*process
,
1783 const lldb_private::FileSpec
&remote_file
,
1784 const std::vector
<std::string
> *paths
,
1785 lldb_private::Status
&error
,
1786 lldb_private::FileSpec
*loaded_image
) {
1787 error
.SetErrorString("LoadImage is not supported on the current platform");
1788 return LLDB_INVALID_IMAGE_TOKEN
;
1791 uint32_t Platform::LoadImageUsingPaths(lldb_private::Process
*process
,
1792 const lldb_private::FileSpec
&remote_filename
,
1793 const std::vector
<std::string
> &paths
,
1794 lldb_private::Status
&error
,
1795 lldb_private::FileSpec
*loaded_path
)
1797 FileSpec file_to_use
;
1798 if (remote_filename
.IsAbsolute())
1799 file_to_use
= FileSpec(remote_filename
.GetFilename().GetStringRef(),
1801 remote_filename
.GetPathStyle());
1803 file_to_use
= remote_filename
;
1805 return DoLoadImage(process
, file_to_use
, &paths
, error
, loaded_path
);
1808 Status
Platform::UnloadImage(lldb_private::Process
*process
,
1809 uint32_t image_token
) {
1810 return Status("UnloadImage is not supported on the current platform");
1813 lldb::ProcessSP
Platform::ConnectProcess(llvm::StringRef connect_url
,
1814 llvm::StringRef plugin_name
,
1815 Debugger
&debugger
, Target
*target
,
1817 return DoConnectProcess(connect_url
, plugin_name
, debugger
, nullptr, target
,
1821 lldb::ProcessSP
Platform::ConnectProcessSynchronous(
1822 llvm::StringRef connect_url
, llvm::StringRef plugin_name
,
1823 Debugger
&debugger
, Stream
&stream
, Target
*target
, Status
&error
) {
1824 return DoConnectProcess(connect_url
, plugin_name
, debugger
, &stream
, target
,
1828 lldb::ProcessSP
Platform::DoConnectProcess(llvm::StringRef connect_url
,
1829 llvm::StringRef plugin_name
,
1830 Debugger
&debugger
, Stream
*stream
,
1831 Target
*target
, Status
&error
) {
1836 if (target
&& target
->GetArchitecture().IsValid())
1837 arch
= target
->GetArchitecture();
1839 arch
= Target::GetDefaultArchitecture();
1841 const char *triple
= "";
1843 triple
= arch
.GetTriple().getTriple().c_str();
1845 TargetSP new_target_sp
;
1846 error
= debugger
.GetTargetList().CreateTarget(
1847 debugger
, "", triple
, eLoadDependentsNo
, nullptr, new_target_sp
);
1848 target
= new_target_sp
.get();
1851 if (!target
|| error
.Fail())
1854 lldb::ProcessSP process_sp
=
1855 target
->CreateProcess(debugger
.GetListener(), plugin_name
, nullptr, true);
1860 // If this private method is called with a stream we are synchronous.
1861 const bool synchronous
= stream
!= nullptr;
1863 ListenerSP
listener_sp(
1864 Listener::MakeListener("lldb.Process.ConnectProcess.hijack"));
1866 process_sp
->HijackProcessEvents(listener_sp
);
1868 error
= process_sp
->ConnectRemote(connect_url
);
1871 process_sp
->RestoreProcessEvents();
1877 process_sp
->WaitForProcessToStop(llvm::None
, &event_sp
, true, listener_sp
,
1879 process_sp
->RestoreProcessEvents();
1880 bool pop_process_io_handler
= false;
1881 Process::HandleProcessStateChangedEvent(event_sp
, stream
,
1882 pop_process_io_handler
);
1888 size_t Platform::ConnectToWaitingProcesses(lldb_private::Debugger
&debugger
,
1889 lldb_private::Status
&error
) {
1894 size_t Platform::GetSoftwareBreakpointTrapOpcode(Target
&target
,
1895 BreakpointSite
*bp_site
) {
1896 ArchSpec arch
= target
.GetArchitecture();
1897 assert(arch
.IsValid());
1898 const uint8_t *trap_opcode
= nullptr;
1899 size_t trap_opcode_size
= 0;
1901 switch (arch
.GetMachine()) {
1902 case llvm::Triple::aarch64_32
:
1903 case llvm::Triple::aarch64
: {
1904 static const uint8_t g_aarch64_opcode
[] = {0x00, 0x00, 0x20, 0xd4};
1905 trap_opcode
= g_aarch64_opcode
;
1906 trap_opcode_size
= sizeof(g_aarch64_opcode
);
1909 case llvm::Triple::arc
: {
1910 static const uint8_t g_hex_opcode
[] = { 0xff, 0x7f };
1911 trap_opcode
= g_hex_opcode
;
1912 trap_opcode_size
= sizeof(g_hex_opcode
);
1915 // TODO: support big-endian arm and thumb trap codes.
1916 case llvm::Triple::arm
: {
1917 // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
1918 // linux kernel does otherwise.
1919 static const uint8_t g_arm_breakpoint_opcode
[] = {0xf0, 0x01, 0xf0, 0xe7};
1920 static const uint8_t g_thumb_breakpoint_opcode
[] = {0x01, 0xde};
1922 lldb::BreakpointLocationSP
bp_loc_sp(bp_site
->GetOwnerAtIndex(0));
1923 AddressClass addr_class
= AddressClass::eUnknown
;
1926 addr_class
= bp_loc_sp
->GetAddress().GetAddressClass();
1927 if (addr_class
== AddressClass::eUnknown
&&
1928 (bp_loc_sp
->GetAddress().GetFileAddress() & 1))
1929 addr_class
= AddressClass::eCodeAlternateISA
;
1932 if (addr_class
== AddressClass::eCodeAlternateISA
) {
1933 trap_opcode
= g_thumb_breakpoint_opcode
;
1934 trap_opcode_size
= sizeof(g_thumb_breakpoint_opcode
);
1936 trap_opcode
= g_arm_breakpoint_opcode
;
1937 trap_opcode_size
= sizeof(g_arm_breakpoint_opcode
);
1941 case llvm::Triple::avr
: {
1942 static const uint8_t g_hex_opcode
[] = {0x98, 0x95};
1943 trap_opcode
= g_hex_opcode
;
1944 trap_opcode_size
= sizeof(g_hex_opcode
);
1947 case llvm::Triple::mips
:
1948 case llvm::Triple::mips64
: {
1949 static const uint8_t g_hex_opcode
[] = {0x00, 0x00, 0x00, 0x0d};
1950 trap_opcode
= g_hex_opcode
;
1951 trap_opcode_size
= sizeof(g_hex_opcode
);
1954 case llvm::Triple::mipsel
:
1955 case llvm::Triple::mips64el
: {
1956 static const uint8_t g_hex_opcode
[] = {0x0d, 0x00, 0x00, 0x00};
1957 trap_opcode
= g_hex_opcode
;
1958 trap_opcode_size
= sizeof(g_hex_opcode
);
1961 case llvm::Triple::systemz
: {
1962 static const uint8_t g_hex_opcode
[] = {0x00, 0x01};
1963 trap_opcode
= g_hex_opcode
;
1964 trap_opcode_size
= sizeof(g_hex_opcode
);
1967 case llvm::Triple::hexagon
: {
1968 static const uint8_t g_hex_opcode
[] = {0x0c, 0xdb, 0x00, 0x54};
1969 trap_opcode
= g_hex_opcode
;
1970 trap_opcode_size
= sizeof(g_hex_opcode
);
1973 case llvm::Triple::ppc
:
1974 case llvm::Triple::ppc64
: {
1975 static const uint8_t g_ppc_opcode
[] = {0x7f, 0xe0, 0x00, 0x08};
1976 trap_opcode
= g_ppc_opcode
;
1977 trap_opcode_size
= sizeof(g_ppc_opcode
);
1980 case llvm::Triple::ppc64le
: {
1981 static const uint8_t g_ppc64le_opcode
[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
1982 trap_opcode
= g_ppc64le_opcode
;
1983 trap_opcode_size
= sizeof(g_ppc64le_opcode
);
1986 case llvm::Triple::x86
:
1987 case llvm::Triple::x86_64
: {
1988 static const uint8_t g_i386_opcode
[] = {0xCC};
1989 trap_opcode
= g_i386_opcode
;
1990 trap_opcode_size
= sizeof(g_i386_opcode
);
1998 if (bp_site
->SetTrapOpcode(trap_opcode
, trap_opcode_size
))
1999 return trap_opcode_size
;