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 //===----------------------------------------------------------------------===//
16 #include "lldb/Breakpoint/BreakpointIDList.h"
17 #include "lldb/Breakpoint/BreakpointLocation.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/Module.h"
20 #include "lldb/Core/ModuleSpec.h"
21 #include "lldb/Core/PluginManager.h"
22 #include "lldb/Host/FileCache.h"
23 #include "lldb/Host/FileSystem.h"
24 #include "lldb/Host/Host.h"
25 #include "lldb/Host/HostInfo.h"
26 #include "lldb/Host/OptionParser.h"
27 #include "lldb/Interpreter/OptionValueFileSpec.h"
28 #include "lldb/Interpreter/OptionValueProperties.h"
29 #include "lldb/Interpreter/Property.h"
30 #include "lldb/Symbol/ObjectFile.h"
31 #include "lldb/Target/ModuleCache.h"
32 #include "lldb/Target/Platform.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/Target.h"
35 #include "lldb/Target/UnixSignals.h"
36 #include "lldb/Utility/DataBufferHeap.h"
37 #include "lldb/Utility/FileSpec.h"
38 #include "lldb/Utility/LLDBLog.h"
39 #include "lldb/Utility/Log.h"
40 #include "lldb/Utility/Status.h"
41 #include "lldb/Utility/StructuredData.h"
42 #include "llvm/ADT/STLExtras.h"
43 #include "llvm/Support/FileSystem.h"
44 #include "llvm/Support/Path.h"
46 // Define these constants from POSIX mman.h rather than include the file so
47 // that they will be correct even when compiled on Linux.
49 #define MAP_ANON 0x1000
52 using namespace lldb_private
;
54 // Use a singleton function for g_local_platform_sp to avoid init constructors
55 // since LLDB is often part of a shared library
56 static PlatformSP
&GetHostPlatformSP() {
57 static PlatformSP g_platform_sp
;
61 const char *Platform::GetHostPlatformName() { return "host"; }
65 #define LLDB_PROPERTIES_platform
66 #include "TargetProperties.inc"
69 #define LLDB_PROPERTIES_platform
70 #include "TargetPropertiesEnum.inc"
75 llvm::StringRef
PlatformProperties::GetSettingName() {
76 static constexpr llvm::StringLiteral
g_setting_name("platform");
77 return g_setting_name
;
80 PlatformProperties::PlatformProperties() {
81 m_collection_sp
= std::make_shared
<OptionValueProperties
>(GetSettingName());
82 m_collection_sp
->Initialize(g_platform_properties
);
84 auto module_cache_dir
= GetModuleCacheDirectory();
88 llvm::SmallString
<64> user_home_dir
;
89 if (!FileSystem::Instance().GetHomeDirectory(user_home_dir
))
92 module_cache_dir
= FileSpec(user_home_dir
.c_str());
93 module_cache_dir
.AppendPathComponent(".lldb");
94 module_cache_dir
.AppendPathComponent("module_cache");
95 SetDefaultModuleCacheDirectory(module_cache_dir
);
96 SetModuleCacheDirectory(module_cache_dir
);
99 bool PlatformProperties::GetUseModuleCache() const {
100 const auto idx
= ePropertyUseModuleCache
;
101 return GetPropertyAtIndexAs
<bool>(
102 idx
, g_platform_properties
[idx
].default_uint_value
!= 0);
105 bool PlatformProperties::SetUseModuleCache(bool use_module_cache
) {
106 return SetPropertyAtIndex(ePropertyUseModuleCache
, use_module_cache
);
109 FileSpec
PlatformProperties::GetModuleCacheDirectory() const {
110 return GetPropertyAtIndexAs
<FileSpec
>(ePropertyModuleCacheDirectory
, {});
113 bool PlatformProperties::SetModuleCacheDirectory(const FileSpec
&dir_spec
) {
114 return m_collection_sp
->SetPropertyAtIndex(ePropertyModuleCacheDirectory
,
118 void PlatformProperties::SetDefaultModuleCacheDirectory(
119 const FileSpec
&dir_spec
) {
120 auto f_spec_opt
= m_collection_sp
->GetPropertyAtIndexAsOptionValueFileSpec(
121 ePropertyModuleCacheDirectory
);
123 f_spec_opt
->SetDefaultValue(dir_spec
);
126 /// Get the native host platform plug-in.
128 /// There should only be one of these for each host that LLDB runs
129 /// upon that should be statically compiled in and registered using
130 /// preprocessor macros or other similar build mechanisms.
132 /// This platform will be used as the default platform when launching
133 /// or attaching to processes unless another platform is specified.
134 PlatformSP
Platform::GetHostPlatform() { return GetHostPlatformSP(); }
136 void Platform::Initialize() {}
138 void Platform::Terminate() {}
140 PlatformProperties
&Platform::GetGlobalPlatformProperties() {
141 static PlatformProperties g_settings
;
145 void Platform::SetHostPlatform(const lldb::PlatformSP
&platform_sp
) {
146 // The native platform should use its static void Platform::Initialize()
147 // function to register itself as the native platform.
148 GetHostPlatformSP() = platform_sp
;
151 Status
Platform::GetFileWithUUID(const FileSpec
&platform_file
,
152 const UUID
*uuid_ptr
, FileSpec
&local_file
) {
153 // Default to the local case
154 local_file
= platform_file
;
159 Platform::LocateExecutableScriptingResources(Target
*target
, Module
&module
,
160 Stream
&feedback_stream
) {
161 return FileSpecList();
165 // Platform::FindPlugin (Process *process, ConstString plugin_name)
167 // PlatformCreateInstance create_callback = nullptr;
171 // PluginManager::GetPlatformCreateCallbackForPluginName (plugin_name);
172 // if (create_callback)
177 // arch = process->GetTarget().GetArchitecture();
179 // PlatformSP platform_sp(create_callback(process, &arch));
181 // return platform_sp;
186 // for (uint32_t idx = 0; (create_callback =
187 // PluginManager::GetPlatformCreateCallbackAtIndex(idx)) != nullptr;
190 // PlatformSP platform_sp(create_callback(process, nullptr));
192 // return platform_sp;
195 // return PlatformSP();
198 Status
Platform::GetSharedModule(
199 const ModuleSpec
&module_spec
, Process
*process
, ModuleSP
&module_sp
,
200 const FileSpecList
*module_search_paths_ptr
,
201 llvm::SmallVectorImpl
<lldb::ModuleSP
> *old_modules
, bool *did_create_ptr
) {
203 return ModuleList::GetSharedModule(module_spec
, module_sp
,
204 module_search_paths_ptr
, old_modules
,
205 did_create_ptr
, false);
207 // Module resolver lambda.
208 auto resolver
= [&](const ModuleSpec
&spec
) {
209 Status
error(eErrorTypeGeneric
);
210 ModuleSpec resolved_spec
;
211 // Check if we have sysroot set.
212 if (!m_sdk_sysroot
.empty()) {
213 // Prepend sysroot to module spec.
214 resolved_spec
= spec
;
215 resolved_spec
.GetFileSpec().PrependPathComponent(m_sdk_sysroot
);
216 // Try to get shared module with resolved spec.
217 error
= ModuleList::GetSharedModule(resolved_spec
, module_sp
,
218 module_search_paths_ptr
, old_modules
,
219 did_create_ptr
, false);
221 // If we don't have sysroot or it didn't work then
222 // try original module spec.
223 if (!error
.Success()) {
224 resolved_spec
= spec
;
225 error
= ModuleList::GetSharedModule(resolved_spec
, module_sp
,
226 module_search_paths_ptr
, old_modules
,
227 did_create_ptr
, false);
229 if (error
.Success() && module_sp
)
230 module_sp
->SetPlatformFileSpec(resolved_spec
.GetFileSpec());
234 return GetRemoteSharedModule(module_spec
, process
, module_sp
, resolver
,
238 bool Platform::GetModuleSpec(const FileSpec
&module_file_spec
,
239 const ArchSpec
&arch
, ModuleSpec
&module_spec
) {
240 ModuleSpecList module_specs
;
241 if (ObjectFile::GetModuleSpecifications(module_file_spec
, 0, 0,
245 ModuleSpec matched_module_spec
;
246 return module_specs
.FindMatchingModuleSpec(ModuleSpec(module_file_spec
, arch
),
250 PlatformSP
Platform::Create(llvm::StringRef name
) {
251 lldb::PlatformSP platform_sp
;
252 if (name
== GetHostPlatformName())
253 return GetHostPlatform();
255 if (PlatformCreateInstance create_callback
=
256 PluginManager::GetPlatformCreateCallbackForPluginName(name
))
257 return create_callback(true, nullptr);
261 ArchSpec
Platform::GetAugmentedArchSpec(Platform
*platform
, llvm::StringRef triple
) {
263 return platform
->GetAugmentedArchSpec(triple
);
264 return HostInfo::GetAugmentedArchSpec(triple
);
267 /// Default Constructor
268 Platform::Platform(bool is_host
)
269 : m_is_host(is_host
), m_os_version_set_while_connected(false),
270 m_system_arch_set_while_connected(false), m_max_uid_name_len(0),
271 m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(),
272 m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),
273 m_ignores_remote_hostname(false), m_trap_handlers(),
274 m_calculated_trap_handlers(false),
275 m_module_cache(std::make_unique
<ModuleCache
>()) {
276 Log
*log
= GetLog(LLDBLog::Object
);
277 LLDB_LOGF(log
, "%p Platform::Platform()", static_cast<void *>(this));
280 Platform::~Platform() = default;
282 void Platform::GetStatus(Stream
&strm
) {
283 strm
.Format(" Platform: {0}\n", GetPluginName());
285 ArchSpec
arch(GetSystemArchitecture());
286 if (arch
.IsValid()) {
287 if (!arch
.GetTriple().str().empty()) {
288 strm
.Printf(" Triple: ");
289 arch
.DumpTriple(strm
.AsRawOstream());
294 llvm::VersionTuple os_version
= GetOSVersion();
295 if (!os_version
.empty()) {
296 strm
.Format("OS Version: {0}", os_version
.getAsString());
298 if (std::optional
<std::string
> s
= GetOSBuildString())
299 strm
.Format(" ({0})", *s
);
305 strm
.Printf(" Hostname: %s\n", GetHostname());
307 const bool is_connected
= IsConnected();
309 strm
.Printf(" Hostname: %s\n", GetHostname());
310 strm
.Printf(" Connected: %s\n", is_connected
? "yes" : "no");
313 if (const std::string
&sdk_root
= GetSDKRootDirectory(); !sdk_root
.empty())
314 strm
.Format(" Sysroot: {0}\n", sdk_root
);
316 if (GetWorkingDirectory()) {
317 strm
.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetPath().c_str());
322 std::string
specific_info(GetPlatformSpecificConnectionInformation());
324 if (!specific_info
.empty())
325 strm
.Printf("Platform-specific connection: %s\n", specific_info
.c_str());
327 if (std::optional
<std::string
> s
= GetOSKernelDescription())
328 strm
.Format(" Kernel: {0}\n", *s
);
331 llvm::VersionTuple
Platform::GetOSVersion(Process
*process
) {
332 std::lock_guard
<std::mutex
> guard(m_mutex
);
335 if (m_os_version
.empty()) {
336 // We have a local host platform
337 m_os_version
= HostInfo::GetOSVersion();
338 m_os_version_set_while_connected
= !m_os_version
.empty();
341 // We have a remote platform. We can only fetch the remote
342 // OS version if we are connected, and we don't want to do it
345 const bool is_connected
= IsConnected();
348 if (!m_os_version
.empty()) {
349 // We have valid OS version info, check to make sure it wasn't manually
350 // set prior to connecting. If it was manually set prior to connecting,
351 // then lets fetch the actual OS version info if we are now connected.
352 if (is_connected
&& !m_os_version_set_while_connected
)
355 // We don't have valid OS version info, fetch it if we are connected
356 fetch
= is_connected
;
360 m_os_version_set_while_connected
= GetRemoteOSVersion();
363 if (!m_os_version
.empty())
366 // Check with the process in case it can answer the question if a process
368 return process
->GetHostOSVersion();
370 return llvm::VersionTuple();
373 std::optional
<std::string
> Platform::GetOSBuildString() {
375 return HostInfo::GetOSBuildString();
376 return GetRemoteOSBuildString();
379 std::optional
<std::string
> Platform::GetOSKernelDescription() {
381 return HostInfo::GetOSKernelDescription();
382 return GetRemoteOSKernelDescription();
385 void Platform::AddClangModuleCompilationOptions(
386 Target
*target
, std::vector
<std::string
> &options
) {
387 std::vector
<std::string
> default_compilation_options
= {
388 "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc"};
390 options
.insert(options
.end(), default_compilation_options
.begin(),
391 default_compilation_options
.end());
394 FileSpec
Platform::GetWorkingDirectory() {
396 llvm::SmallString
<64> cwd
;
397 if (llvm::sys::fs::current_path(cwd
))
400 FileSpec
file_spec(cwd
);
401 FileSystem::Instance().Resolve(file_spec
);
406 m_working_dir
= GetRemoteWorkingDirectory();
407 return m_working_dir
;
411 struct RecurseCopyBaton
{
413 Platform
*platform_ptr
;
417 static FileSystem::EnumerateDirectoryResult
418 RecurseCopy_Callback(void *baton
, llvm::sys::fs::file_type ft
,
419 llvm::StringRef path
) {
420 RecurseCopyBaton
*rc_baton
= (RecurseCopyBaton
*)baton
;
422 namespace fs
= llvm::sys::fs
;
424 case fs::file_type::fifo_file
:
425 case fs::file_type::socket_file
:
426 // we have no way to copy pipes and sockets - ignore them and continue
427 return FileSystem::eEnumerateDirectoryResultNext
;
430 case fs::file_type::directory_file
: {
431 // make the new directory and get in there
432 FileSpec dst_dir
= rc_baton
->dst
;
433 if (!dst_dir
.GetFilename())
434 dst_dir
.SetFilename(src
.GetFilename());
435 Status error
= rc_baton
->platform_ptr
->MakeDirectory(
436 dst_dir
, lldb::eFilePermissionsDirectoryDefault
);
438 rc_baton
->error
.SetErrorStringWithFormat(
439 "unable to setup directory %s on remote end",
440 dst_dir
.GetPath().c_str());
441 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
445 std::string
src_dir_path(src
.GetPath());
447 // Make a filespec that only fills in the directory of a FileSpec so when
448 // we enumerate we can quickly fill in the filename for dst copies
449 FileSpec recurse_dst
;
450 recurse_dst
.SetDirectory(dst_dir
.GetPathAsConstString());
451 RecurseCopyBaton rc_baton2
= {recurse_dst
, rc_baton
->platform_ptr
,
453 FileSystem::Instance().EnumerateDirectory(src_dir_path
, true, true, true,
454 RecurseCopy_Callback
, &rc_baton2
);
455 if (rc_baton2
.error
.Fail()) {
456 rc_baton
->error
.SetErrorString(rc_baton2
.error
.AsCString());
457 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
459 return FileSystem::eEnumerateDirectoryResultNext
;
462 case fs::file_type::symlink_file
: {
463 // copy the file and keep going
464 FileSpec dst_file
= rc_baton
->dst
;
465 if (!dst_file
.GetFilename())
466 dst_file
.SetFilename(src
.GetFilename());
468 FileSpec src_resolved
;
470 rc_baton
->error
= FileSystem::Instance().Readlink(src
, src_resolved
);
472 if (rc_baton
->error
.Fail())
473 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
476 rc_baton
->platform_ptr
->CreateSymlink(dst_file
, src_resolved
);
478 if (rc_baton
->error
.Fail())
479 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
481 return FileSystem::eEnumerateDirectoryResultNext
;
484 case fs::file_type::regular_file
: {
485 // copy the file and keep going
486 FileSpec dst_file
= rc_baton
->dst
;
487 if (!dst_file
.GetFilename())
488 dst_file
.SetFilename(src
.GetFilename());
489 Status err
= rc_baton
->platform_ptr
->PutFile(src
, dst_file
);
491 rc_baton
->error
.SetErrorString(err
.AsCString());
492 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
494 return FileSystem::eEnumerateDirectoryResultNext
;
498 rc_baton
->error
.SetErrorStringWithFormat(
499 "invalid file detected during copy: %s", src
.GetPath().c_str());
500 return FileSystem::eEnumerateDirectoryResultQuit
; // got an error, bail out
503 llvm_unreachable("Unhandled file_type!");
506 Status
Platform::Install(const FileSpec
&src
, const FileSpec
&dst
) {
509 Log
*log
= GetLog(LLDBLog::Platform
);
510 LLDB_LOGF(log
, "Platform::Install (src='%s', dst='%s')",
511 src
.GetPath().c_str(), dst
.GetPath().c_str());
512 FileSpec
fixed_dst(dst
);
514 if (!fixed_dst
.GetFilename())
515 fixed_dst
.SetFilename(src
.GetFilename());
517 FileSpec working_dir
= GetWorkingDirectory();
520 if (dst
.GetDirectory()) {
521 const char first_dst_dir_char
= dst
.GetDirectory().GetCString()[0];
522 if (first_dst_dir_char
== '/' || first_dst_dir_char
== '\\') {
523 fixed_dst
.SetDirectory(dst
.GetDirectory());
525 // If the fixed destination file doesn't have a directory yet, then we
526 // must have a relative path. We will resolve this relative path against
527 // the platform's working directory
528 if (!fixed_dst
.GetDirectory()) {
529 FileSpec relative_spec
;
532 relative_spec
= working_dir
;
533 relative_spec
.AppendPathComponent(dst
.GetPath());
534 fixed_dst
.SetDirectory(relative_spec
.GetDirectory());
536 error
.SetErrorStringWithFormat(
537 "platform working directory must be valid for relative path '%s'",
538 dst
.GetPath().c_str());
544 fixed_dst
.SetDirectory(working_dir
.GetPathAsConstString());
546 error
.SetErrorStringWithFormat(
547 "platform working directory must be valid for relative path '%s'",
548 dst
.GetPath().c_str());
554 fixed_dst
.SetDirectory(working_dir
.GetPathAsConstString());
556 error
.SetErrorStringWithFormat("platform working directory must be valid "
557 "when destination directory is empty");
562 LLDB_LOGF(log
, "Platform::Install (src='%s', dst='%s') fixed_dst='%s'",
563 src
.GetPath().c_str(), dst
.GetPath().c_str(),
564 fixed_dst
.GetPath().c_str());
566 if (GetSupportsRSync()) {
567 error
= PutFile(src
, dst
);
569 namespace fs
= llvm::sys::fs
;
570 switch (fs::get_file_type(src
.GetPath(), false)) {
571 case fs::file_type::directory_file
: {
572 llvm::sys::fs::remove(fixed_dst
.GetPath());
573 uint32_t permissions
= FileSystem::Instance().GetPermissions(src
);
574 if (permissions
== 0)
575 permissions
= eFilePermissionsDirectoryDefault
;
576 error
= MakeDirectory(fixed_dst
, permissions
);
577 if (error
.Success()) {
578 // Make a filespec that only fills in the directory of a FileSpec so
579 // when we enumerate we can quickly fill in the filename for dst copies
580 FileSpec recurse_dst
;
581 recurse_dst
.SetDirectory(fixed_dst
.GetPathAsConstString());
582 std::string
src_dir_path(src
.GetPath());
583 RecurseCopyBaton baton
= {recurse_dst
, this, Status()};
584 FileSystem::Instance().EnumerateDirectory(
585 src_dir_path
, true, true, true, RecurseCopy_Callback
, &baton
);
590 case fs::file_type::regular_file
:
591 llvm::sys::fs::remove(fixed_dst
.GetPath());
592 error
= PutFile(src
, fixed_dst
);
595 case fs::file_type::symlink_file
: {
596 llvm::sys::fs::remove(fixed_dst
.GetPath());
597 FileSpec src_resolved
;
598 error
= FileSystem::Instance().Readlink(src
, src_resolved
);
600 error
= CreateSymlink(dst
, src_resolved
);
602 case fs::file_type::fifo_file
:
603 error
.SetErrorString("platform install doesn't handle pipes");
605 case fs::file_type::socket_file
:
606 error
.SetErrorString("platform install doesn't handle sockets");
609 error
.SetErrorString(
610 "platform install doesn't handle non file or directory items");
617 bool Platform::SetWorkingDirectory(const FileSpec
&file_spec
) {
619 Log
*log
= GetLog(LLDBLog::Platform
);
620 LLDB_LOG(log
, "{0}", file_spec
);
621 if (std::error_code ec
= llvm::sys::fs::set_current_path(file_spec
.GetPath())) {
622 LLDB_LOG(log
, "error: {0}", ec
.message());
627 m_working_dir
.Clear();
628 return SetRemoteWorkingDirectory(file_spec
);
632 Status
Platform::MakeDirectory(const FileSpec
&file_spec
,
633 uint32_t permissions
) {
635 return llvm::sys::fs::create_directory(file_spec
.GetPath(), permissions
);
638 error
.SetErrorStringWithFormatv("remote platform {0} doesn't support {1}",
639 GetPluginName(), LLVM_PRETTY_FUNCTION
);
644 Status
Platform::GetFilePermissions(const FileSpec
&file_spec
,
645 uint32_t &file_permissions
) {
647 auto Value
= llvm::sys::fs::getPermissions(file_spec
.GetPath());
649 file_permissions
= Value
.get();
650 return Status(Value
.getError());
653 error
.SetErrorStringWithFormatv("remote platform {0} doesn't support {1}",
654 GetPluginName(), LLVM_PRETTY_FUNCTION
);
659 Status
Platform::SetFilePermissions(const FileSpec
&file_spec
,
660 uint32_t file_permissions
) {
662 auto Perms
= static_cast<llvm::sys::fs::perms
>(file_permissions
);
663 return llvm::sys::fs::setPermissions(file_spec
.GetPath(), Perms
);
666 error
.SetErrorStringWithFormatv("remote platform {0} doesn't support {1}",
667 GetPluginName(), LLVM_PRETTY_FUNCTION
);
672 user_id_t
Platform::OpenFile(const FileSpec
&file_spec
,
673 File::OpenOptions flags
, uint32_t mode
,
676 return FileCache::GetInstance().OpenFile(file_spec
, flags
, mode
, error
);
680 bool Platform::CloseFile(user_id_t fd
, Status
&error
) {
682 return FileCache::GetInstance().CloseFile(fd
, error
);
686 user_id_t
Platform::GetFileSize(const FileSpec
&file_spec
) {
691 if (llvm::sys::fs::file_size(file_spec
.GetPath(), Size
))
696 uint64_t Platform::ReadFile(lldb::user_id_t fd
, uint64_t offset
, void *dst
,
697 uint64_t dst_len
, Status
&error
) {
699 return FileCache::GetInstance().ReadFile(fd
, offset
, dst
, dst_len
, error
);
700 error
.SetErrorStringWithFormatv(
701 "Platform::ReadFile() is not supported in the {0} platform",
706 uint64_t Platform::WriteFile(lldb::user_id_t fd
, uint64_t offset
,
707 const void *src
, uint64_t src_len
, Status
&error
) {
709 return FileCache::GetInstance().WriteFile(fd
, offset
, src
, src_len
, error
);
710 error
.SetErrorStringWithFormatv(
711 "Platform::WriteFile() is not supported in the {0} platform",
716 UserIDResolver
&Platform::GetUserIDResolver() {
718 return HostInfo::GetUserIDResolver();
719 return UserIDResolver::GetNoopResolver();
722 const char *Platform::GetHostname() {
726 if (m_hostname
.empty())
728 return m_hostname
.c_str();
731 ConstString
Platform::GetFullNameForDylib(ConstString basename
) {
735 bool Platform::SetRemoteWorkingDirectory(const FileSpec
&working_dir
) {
736 Log
*log
= GetLog(LLDBLog::Platform
);
737 LLDB_LOGF(log
, "Platform::SetRemoteWorkingDirectory('%s')",
738 working_dir
.GetPath().c_str());
739 m_working_dir
= working_dir
;
743 bool Platform::SetOSVersion(llvm::VersionTuple version
) {
745 // We don't need anyone setting the OS version for the host platform, we
746 // should be able to figure it out by calling HostInfo::GetOSVersion(...).
749 // We have a remote platform, allow setting the target OS version if we
750 // aren't connected, since if we are connected, we should be able to
751 // request the remote OS version from the connected platform.
755 // We aren't connected and we might want to set the OS version ahead of
756 // time before we connect so we can peruse files and use a local SDK or
757 // PDK cache of support files to disassemble or do other things.
758 m_os_version
= version
;
766 Platform::ResolveExecutable(const ModuleSpec
&module_spec
,
767 lldb::ModuleSP
&exe_module_sp
,
768 const FileSpecList
*module_search_paths_ptr
) {
771 if (FileSystem::Instance().Exists(module_spec
.GetFileSpec())) {
772 if (module_spec
.GetArchitecture().IsValid()) {
773 error
= ModuleList::GetSharedModule(module_spec
, exe_module_sp
,
774 module_search_paths_ptr
, nullptr,
777 // No valid architecture was specified, ask the platform for the
778 // architectures that we should be using (in the correct order) and see
779 // if we can find a match that way
780 ModuleSpec
arch_module_spec(module_spec
);
781 ArchSpec process_host_arch
;
782 for (const ArchSpec
&arch
:
783 GetSupportedArchitectures(process_host_arch
)) {
784 arch_module_spec
.GetArchitecture() = arch
;
785 error
= ModuleList::GetSharedModule(arch_module_spec
, exe_module_sp
,
786 module_search_paths_ptr
, nullptr,
788 // Did we find an executable using one of the
789 if (error
.Success() && exe_module_sp
)
794 error
.SetErrorStringWithFormat(
795 "'%s' does not exist", module_spec
.GetFileSpec().GetPath().c_str());
801 Platform::ResolveRemoteExecutable(const ModuleSpec
&module_spec
,
802 lldb::ModuleSP
&exe_module_sp
,
803 const FileSpecList
*module_search_paths_ptr
) {
806 // We may connect to a process and use the provided executable (Don't use
808 ModuleSpec
resolved_module_spec(module_spec
);
810 // Resolve any executable within a bundle on MacOSX
811 Host::ResolveExecutableInBundle(resolved_module_spec
.GetFileSpec());
813 if (FileSystem::Instance().Exists(resolved_module_spec
.GetFileSpec()) ||
814 module_spec
.GetUUID().IsValid()) {
815 if (resolved_module_spec
.GetArchitecture().IsValid() ||
816 resolved_module_spec
.GetUUID().IsValid()) {
817 error
= ModuleList::GetSharedModule(resolved_module_spec
, exe_module_sp
,
818 module_search_paths_ptr
, nullptr,
821 if (exe_module_sp
&& exe_module_sp
->GetObjectFile())
823 exe_module_sp
.reset();
825 // No valid architecture was specified or the exact arch wasn't found so
826 // ask the platform for the architectures that we should be using (in the
827 // correct order) and see if we can find a match that way
828 StreamString arch_names
;
829 llvm::ListSeparator LS
;
830 ArchSpec process_host_arch
;
831 for (const ArchSpec
&arch
: GetSupportedArchitectures(process_host_arch
)) {
832 resolved_module_spec
.GetArchitecture() = arch
;
833 error
= ModuleList::GetSharedModule(resolved_module_spec
, exe_module_sp
,
834 module_search_paths_ptr
, nullptr,
836 // Did we find an executable using one of the
837 if (error
.Success()) {
838 if (exe_module_sp
&& exe_module_sp
->GetObjectFile())
841 error
.SetErrorToGenericError();
844 arch_names
<< LS
<< arch
.GetArchitectureName();
847 if (error
.Fail() || !exe_module_sp
) {
848 if (FileSystem::Instance().Readable(resolved_module_spec
.GetFileSpec())) {
849 error
.SetErrorStringWithFormatv(
850 "'{0}' doesn't contain any '{1}' platform architectures: {2}",
851 resolved_module_spec
.GetFileSpec(), GetPluginName(),
852 arch_names
.GetData());
854 error
.SetErrorStringWithFormatv("'{0}' is not readable",
855 resolved_module_spec
.GetFileSpec());
859 error
.SetErrorStringWithFormatv("'{0}' does not exist",
860 resolved_module_spec
.GetFileSpec());
866 Status
Platform::ResolveSymbolFile(Target
&target
, const ModuleSpec
&sym_spec
,
867 FileSpec
&sym_file
) {
869 if (FileSystem::Instance().Exists(sym_spec
.GetSymbolFileSpec()))
870 sym_file
= sym_spec
.GetSymbolFileSpec();
872 error
.SetErrorString("unable to resolve symbol file");
876 bool Platform::ResolveRemotePath(const FileSpec
&platform_path
,
877 FileSpec
&resolved_platform_path
) {
878 resolved_platform_path
= platform_path
;
879 FileSystem::Instance().Resolve(resolved_platform_path
);
883 const ArchSpec
&Platform::GetSystemArchitecture() {
885 if (!m_system_arch
.IsValid()) {
886 // We have a local host platform
887 m_system_arch
= HostInfo::GetArchitecture();
888 m_system_arch_set_while_connected
= m_system_arch
.IsValid();
891 // We have a remote platform. We can only fetch the remote system
892 // architecture if we are connected, and we don't want to do it more than
895 const bool is_connected
= IsConnected();
898 if (m_system_arch
.IsValid()) {
899 // We have valid OS version info, check to make sure it wasn't manually
900 // set prior to connecting. If it was manually set prior to connecting,
901 // then lets fetch the actual OS version info if we are now connected.
902 if (is_connected
&& !m_system_arch_set_while_connected
)
905 // We don't have valid OS version info, fetch it if we are connected
906 fetch
= is_connected
;
910 m_system_arch
= GetRemoteSystemArchitecture();
911 m_system_arch_set_while_connected
= m_system_arch
.IsValid();
914 return m_system_arch
;
917 ArchSpec
Platform::GetAugmentedArchSpec(llvm::StringRef triple
) {
920 llvm::Triple
normalized_triple(llvm::Triple::normalize(triple
));
921 if (!ArchSpec::ContainsOnlyArch(normalized_triple
))
922 return ArchSpec(triple
);
924 if (auto kind
= HostInfo::ParseArchitectureKind(triple
))
925 return HostInfo::GetArchitecture(*kind
);
927 ArchSpec compatible_arch
;
928 ArchSpec
raw_arch(triple
);
929 if (!IsCompatibleArchitecture(raw_arch
, {}, ArchSpec::CompatibleMatch
,
933 if (!compatible_arch
.IsValid())
934 return ArchSpec(normalized_triple
);
936 const llvm::Triple
&compatible_triple
= compatible_arch
.GetTriple();
937 if (normalized_triple
.getVendorName().empty())
938 normalized_triple
.setVendor(compatible_triple
.getVendor());
939 if (normalized_triple
.getOSName().empty())
940 normalized_triple
.setOS(compatible_triple
.getOS());
941 if (normalized_triple
.getEnvironmentName().empty())
942 normalized_triple
.setEnvironment(compatible_triple
.getEnvironment());
943 return ArchSpec(normalized_triple
);
946 Status
Platform::ConnectRemote(Args
&args
) {
949 error
.SetErrorStringWithFormatv(
950 "The currently selected platform ({0}) is "
951 "the host platform and is always connected.",
954 error
.SetErrorStringWithFormatv(
955 "Platform::ConnectRemote() is not supported by {0}", GetPluginName());
959 Status
Platform::DisconnectRemote() {
962 error
.SetErrorStringWithFormatv(
963 "The currently selected platform ({0}) is "
964 "the host platform and is always connected.",
967 error
.SetErrorStringWithFormatv(
968 "Platform::DisconnectRemote() is not supported by {0}",
973 bool Platform::GetProcessInfo(lldb::pid_t pid
,
974 ProcessInstanceInfo
&process_info
) {
975 // Take care of the host case so that each subclass can just call this
976 // function to get the host functionality.
978 return Host::GetProcessInfo(pid
, process_info
);
982 uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch
&match_info
,
983 ProcessInstanceInfoList
&process_infos
) {
984 // Take care of the host case so that each subclass can just call this
985 // function to get the host functionality.
986 uint32_t match_count
= 0;
988 match_count
= Host::FindProcesses(match_info
, process_infos
);
992 ProcessInstanceInfoList
Platform::GetAllProcesses() {
993 ProcessInstanceInfoList processes
;
994 ProcessInstanceInfoMatch match
;
995 assert(match
.MatchAllProcesses());
996 FindProcesses(match
, processes
);
1000 Status
Platform::LaunchProcess(ProcessLaunchInfo
&launch_info
) {
1002 Log
*log
= GetLog(LLDBLog::Platform
);
1003 LLDB_LOGF(log
, "Platform::%s()", __FUNCTION__
);
1005 // Take care of the host case so that each subclass can just call this
1006 // function to get the host functionality.
1008 if (::getenv("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))
1009 launch_info
.GetFlags().Set(eLaunchFlagLaunchInTTY
);
1011 if (launch_info
.GetFlags().Test(eLaunchFlagLaunchInShell
)) {
1012 const bool will_debug
= launch_info
.GetFlags().Test(eLaunchFlagDebug
);
1013 const bool first_arg_is_full_shell_command
= false;
1014 uint32_t num_resumes
= GetResumeCountForLaunchInfo(launch_info
);
1016 const FileSpec
&shell
= launch_info
.GetShell();
1017 std::string shell_str
= (shell
) ? shell
.GetPath() : "<null>";
1019 "Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32
1021 __FUNCTION__
, num_resumes
, shell_str
.c_str());
1024 if (!launch_info
.ConvertArgumentsForLaunchingInShell(
1025 error
, will_debug
, first_arg_is_full_shell_command
, num_resumes
))
1027 } else if (launch_info
.GetFlags().Test(eLaunchFlagShellExpandArguments
)) {
1028 error
= ShellExpandArguments(launch_info
);
1030 error
.SetErrorStringWithFormat("shell expansion failed (reason: %s). "
1031 "consider launching with 'process "
1033 error
.AsCString("unknown"));
1038 LLDB_LOGF(log
, "Platform::%s final launch_info resume count: %" PRIu32
,
1039 __FUNCTION__
, launch_info
.GetResumeCount());
1041 error
= Host::LaunchProcess(launch_info
);
1043 error
.SetErrorString(
1044 "base lldb_private::Platform class can't launch remote processes");
1048 Status
Platform::ShellExpandArguments(ProcessLaunchInfo
&launch_info
) {
1050 return Host::ShellExpandArguments(launch_info
);
1051 return Status("base lldb_private::Platform class can't expand arguments");
1054 Status
Platform::KillProcess(const lldb::pid_t pid
) {
1055 Log
*log
= GetLog(LLDBLog::Platform
);
1056 LLDB_LOGF(log
, "Platform::%s, pid %" PRIu64
, __FUNCTION__
, pid
);
1060 "base lldb_private::Platform class can't kill remote processes");
1062 Host::Kill(pid
, SIGKILL
);
1066 lldb::ProcessSP
Platform::DebugProcess(ProcessLaunchInfo
&launch_info
,
1067 Debugger
&debugger
, Target
&target
,
1069 Log
*log
= GetLog(LLDBLog::Platform
);
1070 LLDB_LOG(log
, "target = {0}", &target
);
1072 ProcessSP process_sp
;
1073 // Make sure we stop at the entry point
1074 launch_info
.GetFlags().Set(eLaunchFlagDebug
);
1075 // We always launch the process we are going to debug in a separate process
1076 // group, since then we can handle ^C interrupts ourselves w/o having to
1077 // worry about the target getting them as well.
1078 launch_info
.SetLaunchInSeparateProcessGroup(true);
1080 // Allow any StructuredData process-bound plugins to adjust the launch info
1083 bool iteration_complete
= false;
1084 // Note iteration can't simply go until a nullptr callback is returned, as it
1085 // is valid for a plugin to not supply a filter.
1086 auto get_filter_func
= PluginManager::GetStructuredDataFilterCallbackAtIndex
;
1087 for (auto filter_callback
= get_filter_func(i
, iteration_complete
);
1088 !iteration_complete
;
1089 filter_callback
= get_filter_func(++i
, iteration_complete
)) {
1090 if (filter_callback
) {
1091 // Give this ProcessLaunchInfo filter a chance to adjust the launch info.
1092 error
= (*filter_callback
)(launch_info
, &target
);
1093 if (!error
.Success()) {
1095 "Platform::%s() StructuredDataPlugin launch "
1103 error
= LaunchProcess(launch_info
);
1104 if (error
.Success()) {
1106 "Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64
")",
1107 __FUNCTION__
, launch_info
.GetProcessID());
1108 if (launch_info
.GetProcessID() != LLDB_INVALID_PROCESS_ID
) {
1109 ProcessAttachInfo
attach_info(launch_info
);
1110 process_sp
= Attach(attach_info
, debugger
, &target
, error
);
1112 LLDB_LOG(log
, "Attach() succeeded, Process plugin: {0}",
1113 process_sp
->GetPluginName());
1114 launch_info
.SetHijackListener(attach_info
.GetHijackListener());
1116 // Since we attached to the process, it will think it needs to detach
1117 // if the process object just goes away without an explicit call to
1118 // Process::Kill() or Process::Detach(), so let it know to kill the
1119 // process if this happens.
1120 process_sp
->SetShouldDetach(false);
1122 // If we didn't have any file actions, the pseudo terminal might have
1123 // been used where the secondary side was given as the file to open for
1124 // stdin/out/err after we have already opened the primary so we can
1125 // read/write stdin/out/err.
1126 int pty_fd
= launch_info
.GetPTY().ReleasePrimaryFileDescriptor();
1127 if (pty_fd
!= PseudoTerminal::invalid_fd
) {
1128 process_sp
->SetSTDIOFileDescriptor(pty_fd
);
1131 LLDB_LOGF(log
, "Platform::%s Attach() failed: %s", __FUNCTION__
,
1136 "Platform::%s LaunchProcess() returned launch_info with "
1137 "invalid process id",
1141 LLDB_LOGF(log
, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__
,
1148 std::vector
<ArchSpec
>
1149 Platform::CreateArchList(llvm::ArrayRef
<llvm::Triple::ArchType
> archs
,
1150 llvm::Triple::OSType os
) {
1151 std::vector
<ArchSpec
> list
;
1152 for(auto arch
: archs
) {
1153 llvm::Triple triple
;
1154 triple
.setArch(arch
);
1156 list
.push_back(ArchSpec(triple
));
1161 /// Lets a platform answer if it is compatible with a given
1162 /// architecture and the target triple contained within.
1163 bool Platform::IsCompatibleArchitecture(const ArchSpec
&arch
,
1164 const ArchSpec
&process_host_arch
,
1165 ArchSpec::MatchType match
,
1166 ArchSpec
*compatible_arch_ptr
) {
1167 // If the architecture is invalid, we must answer true...
1168 if (arch
.IsValid()) {
1169 ArchSpec platform_arch
;
1170 for (const ArchSpec
&platform_arch
:
1171 GetSupportedArchitectures(process_host_arch
)) {
1172 if (arch
.IsMatch(platform_arch
, match
)) {
1173 if (compatible_arch_ptr
)
1174 *compatible_arch_ptr
= platform_arch
;
1179 if (compatible_arch_ptr
)
1180 compatible_arch_ptr
->Clear();
1184 Status
Platform::PutFile(const FileSpec
&source
, const FileSpec
&destination
,
1185 uint32_t uid
, uint32_t gid
) {
1186 Log
*log
= GetLog(LLDBLog::Platform
);
1187 LLDB_LOGF(log
, "[PutFile] Using block by block transfer....\n");
1189 auto source_open_options
=
1190 File::eOpenOptionReadOnly
| File::eOpenOptionCloseOnExec
;
1191 namespace fs
= llvm::sys::fs
;
1192 if (fs::is_symlink_file(source
.GetPath()))
1193 source_open_options
|= File::eOpenOptionDontFollowSymlinks
;
1195 auto source_file
= FileSystem::Instance().Open(source
, source_open_options
,
1196 lldb::eFilePermissionsUserRW
);
1198 return Status(source_file
.takeError());
1200 uint32_t permissions
= source_file
.get()->GetPermissions(error
);
1201 if (permissions
== 0)
1202 permissions
= lldb::eFilePermissionsFileDefault
;
1204 lldb::user_id_t dest_file
= OpenFile(
1205 destination
, File::eOpenOptionCanCreate
| File::eOpenOptionWriteOnly
|
1206 File::eOpenOptionTruncate
| File::eOpenOptionCloseOnExec
,
1207 permissions
, error
);
1208 LLDB_LOGF(log
, "dest_file = %" PRIu64
"\n", dest_file
);
1212 if (dest_file
== UINT64_MAX
)
1213 return Status("unable to open target file");
1214 lldb::WritableDataBufferSP
buffer_sp(new DataBufferHeap(1024 * 16, 0));
1215 uint64_t offset
= 0;
1217 size_t bytes_read
= buffer_sp
->GetByteSize();
1218 error
= source_file
.get()->Read(buffer_sp
->GetBytes(), bytes_read
);
1219 if (error
.Fail() || bytes_read
== 0)
1222 const uint64_t bytes_written
=
1223 WriteFile(dest_file
, offset
, buffer_sp
->GetBytes(), bytes_read
, error
);
1227 offset
+= bytes_written
;
1228 if (bytes_written
!= bytes_read
) {
1229 // We didn't write the correct number of bytes, so adjust the file
1230 // position in the source file we are reading from...
1231 source_file
.get()->SeekFromStart(offset
);
1234 CloseFile(dest_file
, error
);
1236 if (uid
== UINT32_MAX
&& gid
== UINT32_MAX
)
1244 Status
Platform::GetFile(const FileSpec
&source
, const FileSpec
&destination
) {
1245 Status
error("unimplemented");
1250 Platform::CreateSymlink(const FileSpec
&src
, // The name of the link is in src
1251 const FileSpec
&dst
) // The symlink points to dst
1254 return FileSystem::Instance().Symlink(src
, dst
);
1255 return Status("unimplemented");
1258 bool Platform::GetFileExists(const lldb_private::FileSpec
&file_spec
) {
1260 return FileSystem::Instance().Exists(file_spec
);
1264 Status
Platform::Unlink(const FileSpec
&path
) {
1266 return llvm::sys::fs::remove(path
.GetPath());
1267 return Status("unimplemented");
1270 MmapArgList
Platform::GetMmapArgumentList(const ArchSpec
&arch
, addr_t addr
,
1271 addr_t length
, unsigned prot
,
1272 unsigned flags
, addr_t fd
,
1274 uint64_t flags_platform
= 0;
1275 if (flags
& eMmapFlagsPrivate
)
1276 flags_platform
|= MAP_PRIVATE
;
1277 if (flags
& eMmapFlagsAnon
)
1278 flags_platform
|= MAP_ANON
;
1280 MmapArgList
args({addr
, length
, prot
, flags_platform
, fd
, offset
});
1284 lldb_private::Status
Platform::RunShellCommand(
1285 llvm::StringRef command
,
1287 working_dir
, // Pass empty FileSpec to use the current working directory
1288 int *status_ptr
, // Pass nullptr if you don't want the process exit status
1289 int *signo_ptr
, // Pass nullptr if you don't want the signal that caused the
1292 *command_output
, // Pass nullptr if you don't want the command output
1293 const Timeout
<std::micro
> &timeout
) {
1294 return RunShellCommand(llvm::StringRef(), command
, working_dir
, status_ptr
,
1295 signo_ptr
, command_output
, timeout
);
1298 lldb_private::Status
Platform::RunShellCommand(
1299 llvm::StringRef shell
, // Pass empty if you want to use the default
1300 // shell interpreter
1301 llvm::StringRef command
, // Shouldn't be empty
1303 working_dir
, // Pass empty FileSpec to use the current working directory
1304 int *status_ptr
, // Pass nullptr if you don't want the process exit status
1305 int *signo_ptr
, // Pass nullptr if you don't want the signal that caused the
1308 *command_output
, // Pass nullptr if you don't want the command output
1309 const Timeout
<std::micro
> &timeout
) {
1311 return Host::RunShellCommand(shell
, command
, working_dir
, status_ptr
,
1312 signo_ptr
, command_output
, timeout
);
1313 return Status("unable to run a remote command without a platform");
1316 bool Platform::CalculateMD5(const FileSpec
&file_spec
, uint64_t &low
,
1320 auto Result
= llvm::sys::fs::md5_contents(file_spec
.GetPath());
1323 std::tie(high
, low
) = Result
->words();
1327 void Platform::SetLocalCacheDirectory(const char *local
) {
1328 m_local_cache_directory
.assign(local
);
1331 const char *Platform::GetLocalCacheDirectory() {
1332 return m_local_cache_directory
.c_str();
1335 static constexpr OptionDefinition g_rsync_option_table
[] = {
1336 {LLDB_OPT_SET_ALL
, false, "rsync", 'r', OptionParser::eNoArgument
, nullptr,
1337 {}, 0, eArgTypeNone
, "Enable rsync."},
1338 {LLDB_OPT_SET_ALL
, false, "rsync-opts", 'R',
1339 OptionParser::eRequiredArgument
, nullptr, {}, 0, eArgTypeCommandName
,
1340 "Platform-specific options required for rsync to work."},
1341 {LLDB_OPT_SET_ALL
, false, "rsync-prefix", 'P',
1342 OptionParser::eRequiredArgument
, nullptr, {}, 0, eArgTypeCommandName
,
1343 "Platform-specific rsync prefix put before the remote path."},
1344 {LLDB_OPT_SET_ALL
, false, "ignore-remote-hostname", 'i',
1345 OptionParser::eNoArgument
, nullptr, {}, 0, eArgTypeNone
,
1346 "Do not automatically fill in the remote hostname when composing the "
1350 static constexpr OptionDefinition g_ssh_option_table
[] = {
1351 {LLDB_OPT_SET_ALL
, false, "ssh", 's', OptionParser::eNoArgument
, nullptr,
1352 {}, 0, eArgTypeNone
, "Enable SSH."},
1353 {LLDB_OPT_SET_ALL
, false, "ssh-opts", 'S', OptionParser::eRequiredArgument
,
1354 nullptr, {}, 0, eArgTypeCommandName
,
1355 "Platform-specific options required for SSH to work."},
1358 static constexpr OptionDefinition g_caching_option_table
[] = {
1359 {LLDB_OPT_SET_ALL
, false, "local-cache-dir", 'c',
1360 OptionParser::eRequiredArgument
, nullptr, {}, 0, eArgTypePath
,
1361 "Path in which to store local copies of files."},
1364 llvm::ArrayRef
<OptionDefinition
> OptionGroupPlatformRSync::GetDefinitions() {
1365 return llvm::ArrayRef(g_rsync_option_table
);
1368 void OptionGroupPlatformRSync::OptionParsingStarting(
1369 ExecutionContext
*execution_context
) {
1371 m_rsync_opts
.clear();
1372 m_rsync_prefix
.clear();
1373 m_ignores_remote_hostname
= false;
1376 lldb_private::Status
1377 OptionGroupPlatformRSync::SetOptionValue(uint32_t option_idx
,
1378 llvm::StringRef option_arg
,
1379 ExecutionContext
*execution_context
) {
1381 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1382 switch (short_option
) {
1388 m_rsync_opts
.assign(std::string(option_arg
));
1392 m_rsync_prefix
.assign(std::string(option_arg
));
1396 m_ignores_remote_hostname
= true;
1400 error
.SetErrorStringWithFormat("unrecognized option '%c'", short_option
);
1408 Platform::SetThreadCreationBreakpoint(lldb_private::Target
&target
) {
1409 return lldb::BreakpointSP();
1412 llvm::ArrayRef
<OptionDefinition
> OptionGroupPlatformSSH::GetDefinitions() {
1413 return llvm::ArrayRef(g_ssh_option_table
);
1416 void OptionGroupPlatformSSH::OptionParsingStarting(
1417 ExecutionContext
*execution_context
) {
1422 lldb_private::Status
1423 OptionGroupPlatformSSH::SetOptionValue(uint32_t option_idx
,
1424 llvm::StringRef option_arg
,
1425 ExecutionContext
*execution_context
) {
1427 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1428 switch (short_option
) {
1434 m_ssh_opts
.assign(std::string(option_arg
));
1438 error
.SetErrorStringWithFormat("unrecognized option '%c'", short_option
);
1445 llvm::ArrayRef
<OptionDefinition
> OptionGroupPlatformCaching::GetDefinitions() {
1446 return llvm::ArrayRef(g_caching_option_table
);
1449 void OptionGroupPlatformCaching::OptionParsingStarting(
1450 ExecutionContext
*execution_context
) {
1451 m_cache_dir
.clear();
1454 lldb_private::Status
OptionGroupPlatformCaching::SetOptionValue(
1455 uint32_t option_idx
, llvm::StringRef option_arg
,
1456 ExecutionContext
*execution_context
) {
1458 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1459 switch (short_option
) {
1461 m_cache_dir
.assign(std::string(option_arg
));
1465 error
.SetErrorStringWithFormat("unrecognized option '%c'", short_option
);
1472 Environment
Platform::GetEnvironment() {
1474 return Host::GetEnvironment();
1475 return Environment();
1478 const std::vector
<ConstString
> &Platform::GetTrapHandlerSymbolNames() {
1479 if (!m_calculated_trap_handlers
) {
1480 std::lock_guard
<std::mutex
> guard(m_mutex
);
1481 if (!m_calculated_trap_handlers
) {
1482 CalculateTrapHandlerSymbolNames();
1483 m_calculated_trap_handlers
= true;
1486 return m_trap_handlers
;
1490 Platform::GetCachedExecutable(ModuleSpec
&module_spec
,
1491 lldb::ModuleSP
&module_sp
,
1492 const FileSpecList
*module_search_paths_ptr
) {
1493 FileSpec platform_spec
= module_spec
.GetFileSpec();
1494 Status error
= GetRemoteSharedModule(
1495 module_spec
, nullptr, module_sp
,
1496 [&](const ModuleSpec
&spec
) {
1497 return ResolveRemoteExecutable(spec
, module_sp
,
1498 module_search_paths_ptr
);
1501 if (error
.Success()) {
1502 module_spec
.GetFileSpec() = module_sp
->GetFileSpec();
1503 module_spec
.GetPlatformFileSpec() = platform_spec
;
1509 Status
Platform::GetRemoteSharedModule(const ModuleSpec
&module_spec
,
1511 lldb::ModuleSP
&module_sp
,
1512 const ModuleResolver
&module_resolver
,
1513 bool *did_create_ptr
) {
1514 // Get module information from a target.
1515 ModuleSpec resolved_module_spec
;
1516 ArchSpec process_host_arch
;
1517 bool got_module_spec
= false;
1519 process_host_arch
= process
->GetSystemArchitecture();
1520 // Try to get module information from the process
1521 if (process
->GetModuleSpec(module_spec
.GetFileSpec(),
1522 module_spec
.GetArchitecture(),
1523 resolved_module_spec
)) {
1524 if (!module_spec
.GetUUID().IsValid() ||
1525 module_spec
.GetUUID() == resolved_module_spec
.GetUUID()) {
1526 got_module_spec
= true;
1531 if (!module_spec
.GetArchitecture().IsValid()) {
1533 // No valid architecture was specified, ask the platform for the
1534 // architectures that we should be using (in the correct order) and see if
1535 // we can find a match that way
1536 ModuleSpec
arch_module_spec(module_spec
);
1537 for (const ArchSpec
&arch
: GetSupportedArchitectures(process_host_arch
)) {
1538 arch_module_spec
.GetArchitecture() = arch
;
1539 error
= ModuleList::GetSharedModule(arch_module_spec
, module_sp
, nullptr,
1541 // Did we find an executable using one of the
1542 if (error
.Success() && module_sp
)
1546 resolved_module_spec
= arch_module_spec
;
1547 got_module_spec
= true;
1551 if (!got_module_spec
) {
1552 // Get module information from a target.
1553 if (GetModuleSpec(module_spec
.GetFileSpec(), module_spec
.GetArchitecture(),
1554 resolved_module_spec
)) {
1555 if (!module_spec
.GetUUID().IsValid() ||
1556 module_spec
.GetUUID() == resolved_module_spec
.GetUUID()) {
1557 got_module_spec
= true;
1562 if (!got_module_spec
) {
1563 // Fall back to the given module resolver, which may have its own
1565 return module_resolver(module_spec
);
1568 // If we are looking for a specific UUID, make sure resolved_module_spec has
1569 // the same one before we search.
1570 if (module_spec
.GetUUID().IsValid()) {
1571 resolved_module_spec
.GetUUID() = module_spec
.GetUUID();
1574 // Call locate module callback if set. This allows users to implement their
1575 // own module cache system. For example, to leverage build system artifacts,
1576 // to bypass pulling files from remote platform, or to search symbol files
1577 // from symbol servers.
1578 FileSpec symbol_file_spec
;
1579 CallLocateModuleCallbackIfSet(resolved_module_spec
, module_sp
,
1580 symbol_file_spec
, did_create_ptr
);
1582 // The module is loaded.
1583 if (symbol_file_spec
) {
1584 // 1. module_sp:loaded, symbol_file_spec:set
1585 // The callback found a module file and a symbol file for this
1586 // resolved_module_spec. Set the symbol file to the module.
1587 module_sp
->SetSymbolFileFileSpec(symbol_file_spec
);
1589 // 2. module_sp:loaded, symbol_file_spec:empty
1590 // The callback only found a module file for this
1591 // resolved_module_spec.
1596 // The module is not loaded by CallLocateModuleCallbackIfSet.
1597 // 3. module_sp:empty, symbol_file_spec:set
1598 // The callback only found a symbol file for the module. We continue to
1599 // find a module file for this resolved_module_spec. and we will call
1600 // module_sp->SetSymbolFileFileSpec with the symbol_file_spec later.
1601 // 4. module_sp:empty, symbol_file_spec:empty
1602 // The callback is not set. Or the callback did not find any module
1603 // files nor any symbol files. Or the callback failed, or something
1604 // went wrong. We continue to find a module file for this
1605 // resolved_module_spec.
1607 // Trying to find a module by UUID on local file system.
1608 const Status error
= module_resolver(resolved_module_spec
);
1609 if (error
.Success()) {
1610 if (module_sp
&& symbol_file_spec
) {
1611 // Set the symbol file to the module if the locate modudle callback was
1612 // called and returned only a symbol file.
1613 module_sp
->SetSymbolFileFileSpec(symbol_file_spec
);
1618 // Fallback to call GetCachedSharedModule on failure.
1619 if (GetCachedSharedModule(resolved_module_spec
, module_sp
, did_create_ptr
)) {
1620 if (module_sp
&& symbol_file_spec
) {
1621 // Set the symbol file to the module if the locate modudle callback was
1622 // called and returned only a symbol file.
1623 module_sp
->SetSymbolFileFileSpec(symbol_file_spec
);
1628 return Status("Failed to call GetCachedSharedModule");
1631 void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec
&module_spec
,
1632 lldb::ModuleSP
&module_sp
,
1633 FileSpec
&symbol_file_spec
,
1634 bool *did_create_ptr
) {
1635 if (!m_locate_module_callback
) {
1636 // Locate module callback is not set.
1640 FileSpec module_file_spec
;
1642 m_locate_module_callback(module_spec
, module_file_spec
, symbol_file_spec
);
1644 // Locate module callback is set and called. Check the error.
1645 Log
*log
= GetLog(LLDBLog::Platform
);
1647 LLDB_LOGF(log
, "%s: locate module callback failed: %s",
1648 LLVM_PRETTY_FUNCTION
, error
.AsCString());
1652 // The locate module callback was succeeded.
1653 // Check the module_file_spec and symbol_file_spec values.
1654 // 1. module:empty symbol:empty -> Failure
1655 // - The callback did not return any files.
1656 // 2. module:exists symbol:exists -> Success
1657 // - The callback returned a module file and a symbol file.
1658 // 3. module:exists symbol:empty -> Success
1659 // - The callback returned only a module file.
1660 // 4. module:empty symbol:exists -> Success
1661 // - The callback returned only a symbol file.
1662 // For example, a breakpad symbol text file.
1663 if (!module_file_spec
&& !symbol_file_spec
) {
1664 // This is '1. module:empty symbol:empty -> Failure'
1665 // The callback did not return any files.
1667 "%s: locate module callback did not set both "
1668 "module_file_spec and symbol_file_spec",
1669 LLVM_PRETTY_FUNCTION
);
1673 // If the callback returned a module file, it should exist.
1674 if (module_file_spec
&& !FileSystem::Instance().Exists(module_file_spec
)) {
1676 "%s: locate module callback set a non-existent file to "
1677 "module_file_spec: %s",
1678 LLVM_PRETTY_FUNCTION
, module_file_spec
.GetPath().c_str());
1679 // Clear symbol_file_spec for the error.
1680 symbol_file_spec
.Clear();
1684 // If the callback returned a symbol file, it should exist.
1685 if (symbol_file_spec
&& !FileSystem::Instance().Exists(symbol_file_spec
)) {
1687 "%s: locate module callback set a non-existent file to "
1688 "symbol_file_spec: %s",
1689 LLVM_PRETTY_FUNCTION
, symbol_file_spec
.GetPath().c_str());
1690 // Clear symbol_file_spec for the error.
1691 symbol_file_spec
.Clear();
1695 if (!module_file_spec
&& symbol_file_spec
) {
1696 // This is '4. module:empty symbol:exists -> Success'
1697 // The locate module callback returned only a symbol file. For example,
1698 // a breakpad symbol text file. GetRemoteSharedModule will use this returned
1699 // symbol_file_spec.
1700 LLDB_LOGF(log
, "%s: locate module callback succeeded: symbol=%s",
1701 LLVM_PRETTY_FUNCTION
, symbol_file_spec
.GetPath().c_str());
1705 // This is one of the following.
1706 // - 2. module:exists symbol:exists -> Success
1707 // - The callback returned a module file and a symbol file.
1708 // - 3. module:exists symbol:empty -> Success
1709 // - The callback returned Only a module file.
1710 // Load the module file.
1711 auto cached_module_spec(module_spec
);
1712 cached_module_spec
.GetUUID().Clear(); // Clear UUID since it may contain md5
1713 // content hash instead of real UUID.
1714 cached_module_spec
.GetFileSpec() = module_file_spec
;
1715 cached_module_spec
.GetPlatformFileSpec() = module_spec
.GetFileSpec();
1716 cached_module_spec
.SetObjectOffset(0);
1718 error
= ModuleList::GetSharedModule(cached_module_spec
, module_sp
, nullptr,
1719 nullptr, did_create_ptr
, false);
1720 if (error
.Success() && module_sp
) {
1721 // Succeeded to load the module file.
1722 LLDB_LOGF(log
, "%s: locate module callback succeeded: module=%s symbol=%s",
1723 LLVM_PRETTY_FUNCTION
, module_file_spec
.GetPath().c_str(),
1724 symbol_file_spec
.GetPath().c_str());
1727 "%s: locate module callback succeeded but failed to load: "
1728 "module=%s symbol=%s",
1729 LLVM_PRETTY_FUNCTION
, module_file_spec
.GetPath().c_str(),
1730 symbol_file_spec
.GetPath().c_str());
1731 // Clear module_sp and symbol_file_spec for the error.
1733 symbol_file_spec
.Clear();
1737 bool Platform::GetCachedSharedModule(const ModuleSpec
&module_spec
,
1738 lldb::ModuleSP
&module_sp
,
1739 bool *did_create_ptr
) {
1740 if (IsHost() || !GetGlobalPlatformProperties().GetUseModuleCache() ||
1741 !GetGlobalPlatformProperties().GetModuleCacheDirectory())
1744 Log
*log
= GetLog(LLDBLog::Platform
);
1746 // Check local cache for a module.
1747 auto error
= m_module_cache
->GetAndPut(
1748 GetModuleCacheRoot(), GetCacheHostname(), module_spec
,
1749 [this](const ModuleSpec
&module_spec
,
1750 const FileSpec
&tmp_download_file_spec
) {
1751 return DownloadModuleSlice(
1752 module_spec
.GetFileSpec(), module_spec
.GetObjectOffset(),
1753 module_spec
.GetObjectSize(), tmp_download_file_spec
);
1756 [this](const ModuleSP
&module_sp
,
1757 const FileSpec
&tmp_download_file_spec
) {
1758 return DownloadSymbolFile(module_sp
, tmp_download_file_spec
);
1760 module_sp
, did_create_ptr
);
1761 if (error
.Success())
1764 LLDB_LOGF(log
, "Platform::%s - module %s not found in local cache: %s",
1765 __FUNCTION__
, module_spec
.GetUUID().GetAsString().c_str(),
1770 Status
Platform::DownloadModuleSlice(const FileSpec
&src_file_spec
,
1771 const uint64_t src_offset
,
1772 const uint64_t src_size
,
1773 const FileSpec
&dst_file_spec
) {
1777 llvm::raw_fd_ostream
dst(dst_file_spec
.GetPath(), EC
, llvm::sys::fs::OF_None
);
1779 error
.SetErrorStringWithFormat("unable to open destination file: %s",
1780 dst_file_spec
.GetPath().c_str());
1784 auto src_fd
= OpenFile(src_file_spec
, File::eOpenOptionReadOnly
,
1785 lldb::eFilePermissionsFileDefault
, error
);
1788 error
.SetErrorStringWithFormat("unable to open source file: %s",
1793 std::vector
<char> buffer(512 * 1024);
1794 auto offset
= src_offset
;
1795 uint64_t total_bytes_read
= 0;
1796 while (total_bytes_read
< src_size
) {
1797 const auto to_read
= std::min(static_cast<uint64_t>(buffer
.size()),
1798 src_size
- total_bytes_read
);
1799 const uint64_t n_read
=
1800 ReadFile(src_fd
, offset
, &buffer
[0], to_read
, error
);
1804 error
.SetErrorString("read 0 bytes");
1808 total_bytes_read
+= n_read
;
1809 dst
.write(&buffer
[0], n_read
);
1813 CloseFile(src_fd
, close_error
); // Ignoring close error.
1818 Status
Platform::DownloadSymbolFile(const lldb::ModuleSP
&module_sp
,
1819 const FileSpec
&dst_file_spec
) {
1821 "Symbol file downloading not supported by the default platform.");
1824 FileSpec
Platform::GetModuleCacheRoot() {
1825 auto dir_spec
= GetGlobalPlatformProperties().GetModuleCacheDirectory();
1826 dir_spec
.AppendPathComponent(GetPluginName());
1830 const char *Platform::GetCacheHostname() { return GetHostname(); }
1832 const UnixSignalsSP
&Platform::GetRemoteUnixSignals() {
1833 static const auto s_default_unix_signals_sp
= std::make_shared
<UnixSignals
>();
1834 return s_default_unix_signals_sp
;
1837 UnixSignalsSP
Platform::GetUnixSignals() {
1839 return UnixSignals::CreateForHost();
1840 return GetRemoteUnixSignals();
1843 uint32_t Platform::LoadImage(lldb_private::Process
*process
,
1844 const lldb_private::FileSpec
&local_file
,
1845 const lldb_private::FileSpec
&remote_file
,
1846 lldb_private::Status
&error
) {
1847 if (local_file
&& remote_file
) {
1848 // Both local and remote file was specified. Install the local file to the
1850 if (IsRemote() || local_file
!= remote_file
) {
1851 error
= Install(local_file
, remote_file
);
1853 return LLDB_INVALID_IMAGE_TOKEN
;
1855 return DoLoadImage(process
, remote_file
, nullptr, error
);
1859 // Only local file was specified. Install it to the current working
1861 FileSpec target_file
= GetWorkingDirectory();
1862 target_file
.AppendPathComponent(local_file
.GetFilename().AsCString());
1863 if (IsRemote() || local_file
!= target_file
) {
1864 error
= Install(local_file
, target_file
);
1866 return LLDB_INVALID_IMAGE_TOKEN
;
1868 return DoLoadImage(process
, target_file
, nullptr, error
);
1872 // Only remote file was specified so we don't have to do any copying
1873 return DoLoadImage(process
, remote_file
, nullptr, error
);
1876 error
.SetErrorString("Neither local nor remote file was specified");
1877 return LLDB_INVALID_IMAGE_TOKEN
;
1880 uint32_t Platform::DoLoadImage(lldb_private::Process
*process
,
1881 const lldb_private::FileSpec
&remote_file
,
1882 const std::vector
<std::string
> *paths
,
1883 lldb_private::Status
&error
,
1884 lldb_private::FileSpec
*loaded_image
) {
1885 error
.SetErrorString("LoadImage is not supported on the current platform");
1886 return LLDB_INVALID_IMAGE_TOKEN
;
1889 uint32_t Platform::LoadImageUsingPaths(lldb_private::Process
*process
,
1890 const lldb_private::FileSpec
&remote_filename
,
1891 const std::vector
<std::string
> &paths
,
1892 lldb_private::Status
&error
,
1893 lldb_private::FileSpec
*loaded_path
)
1895 FileSpec file_to_use
;
1896 if (remote_filename
.IsAbsolute())
1897 file_to_use
= FileSpec(remote_filename
.GetFilename().GetStringRef(),
1899 remote_filename
.GetPathStyle());
1901 file_to_use
= remote_filename
;
1903 return DoLoadImage(process
, file_to_use
, &paths
, error
, loaded_path
);
1906 Status
Platform::UnloadImage(lldb_private::Process
*process
,
1907 uint32_t image_token
) {
1908 return Status("UnloadImage is not supported on the current platform");
1911 lldb::ProcessSP
Platform::ConnectProcess(llvm::StringRef connect_url
,
1912 llvm::StringRef plugin_name
,
1913 Debugger
&debugger
, Target
*target
,
1915 return DoConnectProcess(connect_url
, plugin_name
, debugger
, nullptr, target
,
1919 lldb::ProcessSP
Platform::ConnectProcessSynchronous(
1920 llvm::StringRef connect_url
, llvm::StringRef plugin_name
,
1921 Debugger
&debugger
, Stream
&stream
, Target
*target
, Status
&error
) {
1922 return DoConnectProcess(connect_url
, plugin_name
, debugger
, &stream
, target
,
1926 lldb::ProcessSP
Platform::DoConnectProcess(llvm::StringRef connect_url
,
1927 llvm::StringRef plugin_name
,
1928 Debugger
&debugger
, Stream
*stream
,
1929 Target
*target
, Status
&error
) {
1933 ArchSpec arch
= Target::GetDefaultArchitecture();
1935 const char *triple
=
1936 arch
.IsValid() ? arch
.GetTriple().getTriple().c_str() : "";
1938 TargetSP new_target_sp
;
1939 error
= debugger
.GetTargetList().CreateTarget(
1940 debugger
, "", triple
, eLoadDependentsNo
, nullptr, new_target_sp
);
1942 target
= new_target_sp
.get();
1943 if (!target
|| error
.Fail()) {
1948 lldb::ProcessSP process_sp
=
1949 target
->CreateProcess(debugger
.GetListener(), plugin_name
, nullptr, true);
1954 // If this private method is called with a stream we are synchronous.
1955 const bool synchronous
= stream
!= nullptr;
1957 ListenerSP
listener_sp(
1958 Listener::MakeListener("lldb.Process.ConnectProcess.hijack"));
1960 process_sp
->HijackProcessEvents(listener_sp
);
1962 error
= process_sp
->ConnectRemote(connect_url
);
1965 process_sp
->RestoreProcessEvents();
1971 process_sp
->WaitForProcessToStop(std::nullopt
, &event_sp
, true, listener_sp
,
1973 process_sp
->RestoreProcessEvents();
1974 bool pop_process_io_handler
= false;
1975 // This is a user-level stop, so we allow recognizers to select frames.
1976 Process::HandleProcessStateChangedEvent(
1977 event_sp
, stream
, SelectMostRelevantFrame
, pop_process_io_handler
);
1983 size_t Platform::ConnectToWaitingProcesses(lldb_private::Debugger
&debugger
,
1984 lldb_private::Status
&error
) {
1989 size_t Platform::GetSoftwareBreakpointTrapOpcode(Target
&target
,
1990 BreakpointSite
*bp_site
) {
1991 ArchSpec arch
= target
.GetArchitecture();
1992 assert(arch
.IsValid());
1993 const uint8_t *trap_opcode
= nullptr;
1994 size_t trap_opcode_size
= 0;
1996 switch (arch
.GetMachine()) {
1997 case llvm::Triple::aarch64_32
:
1998 case llvm::Triple::aarch64
: {
1999 static const uint8_t g_aarch64_opcode
[] = {0x00, 0x00, 0x20, 0xd4};
2000 trap_opcode
= g_aarch64_opcode
;
2001 trap_opcode_size
= sizeof(g_aarch64_opcode
);
2004 case llvm::Triple::arc
: {
2005 static const uint8_t g_hex_opcode
[] = { 0xff, 0x7f };
2006 trap_opcode
= g_hex_opcode
;
2007 trap_opcode_size
= sizeof(g_hex_opcode
);
2010 // TODO: support big-endian arm and thumb trap codes.
2011 case llvm::Triple::arm
: {
2012 // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the
2013 // linux kernel does otherwise.
2014 static const uint8_t g_arm_breakpoint_opcode
[] = {0xf0, 0x01, 0xf0, 0xe7};
2015 static const uint8_t g_thumb_breakpoint_opcode
[] = {0x01, 0xde};
2017 lldb::BreakpointLocationSP
bp_loc_sp(bp_site
->GetOwnerAtIndex(0));
2018 AddressClass addr_class
= AddressClass::eUnknown
;
2021 addr_class
= bp_loc_sp
->GetAddress().GetAddressClass();
2022 if (addr_class
== AddressClass::eUnknown
&&
2023 (bp_loc_sp
->GetAddress().GetFileAddress() & 1))
2024 addr_class
= AddressClass::eCodeAlternateISA
;
2027 if (addr_class
== AddressClass::eCodeAlternateISA
) {
2028 trap_opcode
= g_thumb_breakpoint_opcode
;
2029 trap_opcode_size
= sizeof(g_thumb_breakpoint_opcode
);
2031 trap_opcode
= g_arm_breakpoint_opcode
;
2032 trap_opcode_size
= sizeof(g_arm_breakpoint_opcode
);
2036 case llvm::Triple::avr
: {
2037 static const uint8_t g_hex_opcode
[] = {0x98, 0x95};
2038 trap_opcode
= g_hex_opcode
;
2039 trap_opcode_size
= sizeof(g_hex_opcode
);
2042 case llvm::Triple::mips
:
2043 case llvm::Triple::mips64
: {
2044 static const uint8_t g_hex_opcode
[] = {0x00, 0x00, 0x00, 0x0d};
2045 trap_opcode
= g_hex_opcode
;
2046 trap_opcode_size
= sizeof(g_hex_opcode
);
2049 case llvm::Triple::mipsel
:
2050 case llvm::Triple::mips64el
: {
2051 static const uint8_t g_hex_opcode
[] = {0x0d, 0x00, 0x00, 0x00};
2052 trap_opcode
= g_hex_opcode
;
2053 trap_opcode_size
= sizeof(g_hex_opcode
);
2056 case llvm::Triple::msp430
: {
2057 static const uint8_t g_msp430_opcode
[] = {0x43, 0x43};
2058 trap_opcode
= g_msp430_opcode
;
2059 trap_opcode_size
= sizeof(g_msp430_opcode
);
2062 case llvm::Triple::systemz
: {
2063 static const uint8_t g_hex_opcode
[] = {0x00, 0x01};
2064 trap_opcode
= g_hex_opcode
;
2065 trap_opcode_size
= sizeof(g_hex_opcode
);
2068 case llvm::Triple::hexagon
: {
2069 static const uint8_t g_hex_opcode
[] = {0x0c, 0xdb, 0x00, 0x54};
2070 trap_opcode
= g_hex_opcode
;
2071 trap_opcode_size
= sizeof(g_hex_opcode
);
2074 case llvm::Triple::ppc
:
2075 case llvm::Triple::ppc64
: {
2076 static const uint8_t g_ppc_opcode
[] = {0x7f, 0xe0, 0x00, 0x08};
2077 trap_opcode
= g_ppc_opcode
;
2078 trap_opcode_size
= sizeof(g_ppc_opcode
);
2081 case llvm::Triple::ppc64le
: {
2082 static const uint8_t g_ppc64le_opcode
[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
2083 trap_opcode
= g_ppc64le_opcode
;
2084 trap_opcode_size
= sizeof(g_ppc64le_opcode
);
2087 case llvm::Triple::x86
:
2088 case llvm::Triple::x86_64
: {
2089 static const uint8_t g_i386_opcode
[] = {0xCC};
2090 trap_opcode
= g_i386_opcode
;
2091 trap_opcode_size
= sizeof(g_i386_opcode
);
2094 case llvm::Triple::riscv32
:
2095 case llvm::Triple::riscv64
: {
2096 static const uint8_t g_riscv_opcode
[] = {0x73, 0x00, 0x10, 0x00}; // ebreak
2097 static const uint8_t g_riscv_opcode_c
[] = {0x02, 0x90}; // c.ebreak
2098 if (arch
.GetFlags() & ArchSpec::eRISCV_rvc
) {
2099 trap_opcode
= g_riscv_opcode_c
;
2100 trap_opcode_size
= sizeof(g_riscv_opcode_c
);
2102 trap_opcode
= g_riscv_opcode
;
2103 trap_opcode_size
= sizeof(g_riscv_opcode
);
2107 case llvm::Triple::loongarch32
:
2108 case llvm::Triple::loongarch64
: {
2109 static const uint8_t g_loongarch_opcode
[] = {0x05, 0x00, 0x2a,
2111 trap_opcode
= g_loongarch_opcode
;
2112 trap_opcode_size
= sizeof(g_loongarch_opcode
);
2120 if (bp_site
->SetTrapOpcode(trap_opcode
, trap_opcode_size
))
2121 return trap_opcode_size
;
2126 CompilerType
Platform::GetSiginfoType(const llvm::Triple
& triple
) {
2127 return CompilerType();
2130 Args
Platform::GetExtraStartupCommands() {
2134 void Platform::SetLocateModuleCallback(LocateModuleCallback callback
) {
2135 m_locate_module_callback
= callback
;
2138 Platform::LocateModuleCallback
Platform::GetLocateModuleCallback() const {
2139 return m_locate_module_callback
;
2142 PlatformSP
PlatformList::GetOrCreate(llvm::StringRef name
) {
2143 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
2144 for (const PlatformSP
&platform_sp
: m_platforms
) {
2145 if (platform_sp
->GetName() == name
)
2148 return Create(name
);
2151 PlatformSP
PlatformList::GetOrCreate(const ArchSpec
&arch
,
2152 const ArchSpec
&process_host_arch
,
2153 ArchSpec
*platform_arch_ptr
,
2155 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
2156 // First try exact arch matches across all platforms already created
2157 for (const auto &platform_sp
: m_platforms
) {
2158 if (platform_sp
->IsCompatibleArchitecture(
2159 arch
, process_host_arch
, ArchSpec::ExactMatch
, platform_arch_ptr
))
2163 // Next try compatible arch matches across all platforms already created
2164 for (const auto &platform_sp
: m_platforms
) {
2165 if (platform_sp
->IsCompatibleArchitecture(arch
, process_host_arch
,
2166 ArchSpec::CompatibleMatch
,
2171 PlatformCreateInstance create_callback
;
2172 // First try exact arch matches across all platform plug-ins
2175 (create_callback
= PluginManager::GetPlatformCreateCallbackAtIndex(idx
));
2177 PlatformSP platform_sp
= create_callback(false, &arch
);
2179 platform_sp
->IsCompatibleArchitecture(
2180 arch
, process_host_arch
, ArchSpec::ExactMatch
, platform_arch_ptr
)) {
2181 m_platforms
.push_back(platform_sp
);
2185 // Next try compatible arch matches across all platform plug-ins
2187 (create_callback
= PluginManager::GetPlatformCreateCallbackAtIndex(idx
));
2189 PlatformSP platform_sp
= create_callback(false, &arch
);
2190 if (platform_sp
&& platform_sp
->IsCompatibleArchitecture(
2191 arch
, process_host_arch
, ArchSpec::CompatibleMatch
,
2192 platform_arch_ptr
)) {
2193 m_platforms
.push_back(platform_sp
);
2197 if (platform_arch_ptr
)
2198 platform_arch_ptr
->Clear();
2202 PlatformSP
PlatformList::GetOrCreate(const ArchSpec
&arch
,
2203 const ArchSpec
&process_host_arch
,
2204 ArchSpec
*platform_arch_ptr
) {
2207 return GetOrCreate(arch
, process_host_arch
, platform_arch_ptr
, error
);
2211 PlatformSP
PlatformList::GetOrCreate(llvm::ArrayRef
<ArchSpec
> archs
,
2212 const ArchSpec
&process_host_arch
,
2213 std::vector
<PlatformSP
> &candidates
) {
2215 candidates
.reserve(archs
.size());
2220 PlatformSP host_platform_sp
= Platform::GetHostPlatform();
2222 // Prefer the selected platform if it matches at least one architecture.
2223 if (m_selected_platform_sp
) {
2224 for (const ArchSpec
&arch
: archs
) {
2225 if (m_selected_platform_sp
->IsCompatibleArchitecture(
2226 arch
, process_host_arch
, ArchSpec::CompatibleMatch
, nullptr))
2227 return m_selected_platform_sp
;
2231 // Prefer the host platform if it matches at least one architecture.
2232 if (host_platform_sp
) {
2233 for (const ArchSpec
&arch
: archs
) {
2234 if (host_platform_sp
->IsCompatibleArchitecture(
2235 arch
, process_host_arch
, ArchSpec::CompatibleMatch
, nullptr))
2236 return host_platform_sp
;
2240 // Collect a list of candidate platforms for the architectures.
2241 for (const ArchSpec
&arch
: archs
) {
2242 if (PlatformSP platform
= GetOrCreate(arch
, process_host_arch
, nullptr))
2243 candidates
.push_back(platform
);
2246 // The selected or host platform didn't match any of the architectures. If
2247 // the same platform supports all architectures then that's the obvious next
2249 if (candidates
.size() == archs
.size()) {
2250 if (llvm::all_of(candidates
, [&](const PlatformSP
&p
) -> bool {
2251 return p
->GetName() == candidates
.front()->GetName();
2253 return candidates
.front();
2257 // At this point we either have no platforms that match the given
2258 // architectures or multiple platforms with no good way to disambiguate
2263 PlatformSP
PlatformList::Create(llvm::StringRef name
) {
2264 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
2265 PlatformSP platform_sp
= Platform::Create(name
);
2266 m_platforms
.push_back(platform_sp
);
2270 bool PlatformList::LoadPlatformBinaryAndSetup(Process
*process
,
2271 lldb::addr_t addr
, bool notify
) {
2272 std::lock_guard
<std::recursive_mutex
> guard(m_mutex
);
2274 PlatformCreateInstance create_callback
;
2276 (create_callback
= PluginManager::GetPlatformCreateCallbackAtIndex(idx
));
2279 PlatformSP platform_sp
= create_callback(true, &arch
);
2281 if (platform_sp
->LoadPlatformBinaryAndSetup(process
, addr
, notify
))