2253 lines · cpp
1//===-- Platform.cpp ------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <algorithm>10#include <csignal>11#include <fstream>12#include <memory>13#include <optional>14#include <vector>15 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"45 46// Define these constants from POSIX mman.h rather than include the file so47// that they will be correct even when compiled on Linux.48#define MAP_PRIVATE 249#define MAP_ANON 0x100050 51using namespace lldb;52using namespace lldb_private;53 54// Use a singleton function for g_local_platform_sp to avoid init constructors55// since LLDB is often part of a shared library56static PlatformSP &GetHostPlatformSP() {57 static PlatformSP g_platform_sp;58 return g_platform_sp;59}60 61const char *Platform::GetHostPlatformName() { return "host"; }62 63namespace {64 65#define LLDB_PROPERTIES_platform66#include "TargetProperties.inc"67 68enum {69#define LLDB_PROPERTIES_platform70#include "TargetPropertiesEnum.inc"71};72 73} // namespace74 75llvm::StringRef PlatformProperties::GetSettingName() {76 static constexpr llvm::StringLiteral g_setting_name("platform");77 return g_setting_name;78}79 80PlatformProperties::PlatformProperties() {81 m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());82 m_collection_sp->Initialize(g_platform_properties);83 84 auto module_cache_dir = GetModuleCacheDirectory();85 if (module_cache_dir)86 return;87 88 llvm::SmallString<64> user_home_dir;89 if (!FileSystem::Instance().GetHomeDirectory(user_home_dir))90 return;91 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);97}98 99bool PlatformProperties::GetUseModuleCache() const {100 const auto idx = ePropertyUseModuleCache;101 return GetPropertyAtIndexAs<bool>(102 idx, g_platform_properties[idx].default_uint_value != 0);103}104 105bool PlatformProperties::SetUseModuleCache(bool use_module_cache) {106 return SetPropertyAtIndex(ePropertyUseModuleCache, use_module_cache);107}108 109FileSpec PlatformProperties::GetModuleCacheDirectory() const {110 return GetPropertyAtIndexAs<FileSpec>(ePropertyModuleCacheDirectory, {});111}112 113bool PlatformProperties::SetModuleCacheDirectory(const FileSpec &dir_spec) {114 return m_collection_sp->SetPropertyAtIndex(ePropertyModuleCacheDirectory,115 dir_spec);116}117 118void PlatformProperties::SetDefaultModuleCacheDirectory(119 const FileSpec &dir_spec) {120 auto f_spec_opt = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpec(121 ePropertyModuleCacheDirectory);122 assert(f_spec_opt);123 f_spec_opt->SetDefaultValue(dir_spec);124}125 126/// Get the native host platform plug-in.127///128/// There should only be one of these for each host that LLDB runs129/// upon that should be statically compiled in and registered using130/// preprocessor macros or other similar build mechanisms.131///132/// This platform will be used as the default platform when launching133/// or attaching to processes unless another platform is specified.134PlatformSP Platform::GetHostPlatform() { return GetHostPlatformSP(); }135 136void Platform::Initialize() {}137 138void Platform::Terminate() {}139 140PlatformProperties &Platform::GetGlobalPlatformProperties() {141 static PlatformProperties g_settings;142 return g_settings;143}144 145void 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;149}150 151Status Platform::GetFileWithUUID(const FileSpec &platform_file,152 const UUID *uuid_ptr, FileSpec &local_file) {153 // Default to the local case154 local_file = platform_file;155 return Status();156}157 158FileSpecList159Platform::LocateExecutableScriptingResources(Target *target, Module &module,160 Stream &feedback_stream) {161 return FileSpecList();162}163 164Status Platform::GetSharedModule(165 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,166 llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) {167 if (IsHost())168 // Note: module_search_paths_ptr functionality is now handled internally169 // by getting target from module_spec and calling170 // target->GetExecutableSearchPaths()171 return ModuleList::GetSharedModule(module_spec, module_sp, old_modules,172 did_create_ptr, false);173 174 // Module resolver lambda.175 auto resolver = [&](const ModuleSpec &spec) {176 Status error(eErrorTypeGeneric);177 ModuleSpec resolved_spec;178 // Check if we have sysroot set.179 if (!m_sdk_sysroot.empty()) {180 // Prepend sysroot to module spec.181 resolved_spec = spec;182 resolved_spec.GetFileSpec().PrependPathComponent(m_sdk_sysroot);183 // Try to get shared module with resolved spec.184 error = ModuleList::GetSharedModule(resolved_spec, module_sp, old_modules,185 did_create_ptr, false);186 }187 // If we don't have sysroot or it didn't work then188 // try original module spec.189 if (!error.Success()) {190 resolved_spec = spec;191 error = ModuleList::GetSharedModule(resolved_spec, module_sp, old_modules,192 did_create_ptr, false);193 }194 if (error.Success() && module_sp)195 module_sp->SetPlatformFileSpec(resolved_spec.GetFileSpec());196 return error;197 };198 199 return GetRemoteSharedModule(module_spec, process, module_sp, resolver,200 did_create_ptr);201}202 203bool Platform::GetModuleSpec(const FileSpec &module_file_spec,204 const ArchSpec &arch, ModuleSpec &module_spec) {205 ModuleSpecList module_specs;206 if (ObjectFile::GetModuleSpecifications(module_file_spec, 0, 0,207 module_specs) == 0)208 return false;209 210 ModuleSpec matched_module_spec;211 return module_specs.FindMatchingModuleSpec(ModuleSpec(module_file_spec, arch),212 module_spec);213}214 215PlatformSP Platform::Create(llvm::StringRef name) {216 lldb::PlatformSP platform_sp;217 if (name == GetHostPlatformName())218 return GetHostPlatform();219 220 if (PlatformCreateInstance create_callback =221 PluginManager::GetPlatformCreateCallbackForPluginName(name))222 return create_callback(true, nullptr);223 return nullptr;224}225 226ArchSpec Platform::GetAugmentedArchSpec(Platform *platform, llvm::StringRef triple) {227 if (platform)228 return platform->GetAugmentedArchSpec(triple);229 return HostInfo::GetAugmentedArchSpec(triple);230}231 232/// Default Constructor233Platform::Platform(bool is_host)234 : m_is_host(is_host), m_os_version_set_while_connected(false),235 m_system_arch_set_while_connected(false), m_max_uid_name_len(0),236 m_max_gid_name_len(0), m_supports_rsync(false), m_rsync_opts(),237 m_rsync_prefix(), m_supports_ssh(false), m_ssh_opts(),238 m_ignores_remote_hostname(false), m_trap_handlers(),239 m_calculated_trap_handlers(false),240 m_module_cache(std::make_unique<ModuleCache>()) {241 Log *log = GetLog(LLDBLog::Object);242 LLDB_LOGF(log, "%p Platform::Platform()", static_cast<void *>(this));243}244 245Platform::~Platform() = default;246 247void Platform::GetStatus(Stream &strm) {248 strm.Format(" Platform: {0}\n", GetPluginName());249 250 ArchSpec arch(GetSystemArchitecture());251 if (arch.IsValid()) {252 if (!arch.GetTriple().str().empty()) {253 strm.Printf(" Triple: ");254 arch.DumpTriple(strm.AsRawOstream());255 strm.EOL();256 }257 }258 259 llvm::VersionTuple os_version = GetOSVersion();260 if (!os_version.empty()) {261 strm.Format("OS Version: {0}", os_version.getAsString());262 263 if (std::optional<std::string> s = GetOSBuildString())264 strm.Format(" ({0})", *s);265 266 strm.EOL();267 }268 269 if (IsHost()) {270 strm.Printf(" Hostname: %s\n", GetHostname());271 } else {272 const bool is_connected = IsConnected();273 if (is_connected)274 strm.Printf(" Hostname: %s\n", GetHostname());275 strm.Printf(" Connected: %s\n", is_connected ? "yes" : "no");276 }277 278 if (const std::string &sdk_root = GetSDKRootDirectory(); !sdk_root.empty())279 strm.Format(" Sysroot: {0}\n", sdk_root);280 281 if (GetWorkingDirectory()) {282 strm.Printf("WorkingDir: %s\n", GetWorkingDirectory().GetPath().c_str());283 }284 if (!IsConnected())285 return;286 287 std::string specific_info(GetPlatformSpecificConnectionInformation());288 289 if (!specific_info.empty())290 strm.Printf("Platform-specific connection: %s\n", specific_info.c_str());291 292 if (std::optional<std::string> s = GetOSKernelDescription())293 strm.Format(" Kernel: {0}\n", *s);294}295 296llvm::VersionTuple Platform::GetOSVersion(Process *process) {297 std::lock_guard<std::mutex> guard(m_mutex);298 299 if (IsHost()) {300 if (m_os_version.empty()) {301 // We have a local host platform302 m_os_version = HostInfo::GetOSVersion();303 m_os_version_set_while_connected = !m_os_version.empty();304 }305 } else {306 // We have a remote platform. We can only fetch the remote307 // OS version if we are connected, and we don't want to do it308 // more than once.309 310 const bool is_connected = IsConnected();311 312 bool fetch = false;313 if (!m_os_version.empty()) {314 // We have valid OS version info, check to make sure it wasn't manually315 // set prior to connecting. If it was manually set prior to connecting,316 // then lets fetch the actual OS version info if we are now connected.317 if (is_connected && !m_os_version_set_while_connected)318 fetch = true;319 } else {320 // We don't have valid OS version info, fetch it if we are connected321 fetch = is_connected;322 }323 324 if (fetch)325 m_os_version_set_while_connected = GetRemoteOSVersion();326 }327 328 if (!m_os_version.empty())329 return m_os_version;330 if (process) {331 // Check with the process in case it can answer the question if a process332 // was provided333 return process->GetHostOSVersion();334 }335 return llvm::VersionTuple();336}337 338std::optional<std::string> Platform::GetOSBuildString() {339 if (IsHost())340 return HostInfo::GetOSBuildString();341 return GetRemoteOSBuildString();342}343 344std::optional<std::string> Platform::GetOSKernelDescription() {345 if (IsHost())346 return HostInfo::GetOSKernelDescription();347 return GetRemoteOSKernelDescription();348}349 350void Platform::AddClangModuleCompilationOptions(351 Target *target, std::vector<std::string> &options) {352 std::vector<std::string> default_compilation_options = {353 "-x", "c++", "-Xclang", "-nostdsysteminc", "-Xclang", "-nostdsysteminc"};354 355 options.insert(options.end(), default_compilation_options.begin(),356 default_compilation_options.end());357}358 359FileSpec Platform::GetWorkingDirectory() {360 if (IsHost()) {361 llvm::SmallString<64> cwd;362 if (llvm::sys::fs::current_path(cwd))363 return {};364 else {365 FileSpec file_spec(cwd);366 FileSystem::Instance().Resolve(file_spec);367 return file_spec;368 }369 } else {370 if (!m_working_dir)371 m_working_dir = GetRemoteWorkingDirectory();372 return m_working_dir;373 }374}375 376struct RecurseCopyBaton {377 const FileSpec &dst;378 Platform *platform_ptr;379 Status error;380};381 382static FileSystem::EnumerateDirectoryResult383RecurseCopy_Callback(void *baton, llvm::sys::fs::file_type ft,384 llvm::StringRef path) {385 RecurseCopyBaton *rc_baton = (RecurseCopyBaton *)baton;386 FileSpec src(path);387 namespace fs = llvm::sys::fs;388 switch (ft) {389 case fs::file_type::fifo_file:390 case fs::file_type::socket_file:391 // we have no way to copy pipes and sockets - ignore them and continue392 return FileSystem::eEnumerateDirectoryResultNext;393 break;394 395 case fs::file_type::directory_file: {396 // make the new directory and get in there397 FileSpec dst_dir = rc_baton->dst;398 if (!dst_dir.GetFilename())399 dst_dir.SetFilename(src.GetFilename());400 Status error = rc_baton->platform_ptr->MakeDirectory(401 dst_dir, lldb::eFilePermissionsDirectoryDefault);402 if (error.Fail()) {403 rc_baton->error = Status::FromErrorStringWithFormatv(404 "unable to setup directory {0} on remote end", dst_dir.GetPath());405 return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out406 }407 408 // now recurse409 std::string src_dir_path(src.GetPath());410 411 // Make a filespec that only fills in the directory of a FileSpec so when412 // we enumerate we can quickly fill in the filename for dst copies413 FileSpec recurse_dst;414 recurse_dst.SetDirectory(dst_dir.GetPathAsConstString());415 RecurseCopyBaton rc_baton2 = {recurse_dst, rc_baton->platform_ptr,416 Status()};417 FileSystem::Instance().EnumerateDirectory(src_dir_path, true, true, true,418 RecurseCopy_Callback, &rc_baton2);419 if (rc_baton2.error.Fail()) {420 rc_baton->error = Status::FromErrorString(rc_baton2.error.AsCString());421 return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out422 }423 return FileSystem::eEnumerateDirectoryResultNext;424 } break;425 426 case fs::file_type::symlink_file: {427 // copy the file and keep going428 FileSpec dst_file = rc_baton->dst;429 if (!dst_file.GetFilename())430 dst_file.SetFilename(src.GetFilename());431 432 FileSpec src_resolved;433 434 rc_baton->error = FileSystem::Instance().Readlink(src, src_resolved);435 436 if (rc_baton->error.Fail())437 return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out438 439 rc_baton->error =440 rc_baton->platform_ptr->CreateSymlink(dst_file, src_resolved);441 442 if (rc_baton->error.Fail())443 return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out444 445 return FileSystem::eEnumerateDirectoryResultNext;446 } break;447 448 case fs::file_type::regular_file: {449 // copy the file and keep going450 FileSpec dst_file = rc_baton->dst;451 if (!dst_file.GetFilename())452 dst_file.SetFilename(src.GetFilename());453 Status err = rc_baton->platform_ptr->PutFile(src, dst_file);454 if (err.Fail()) {455 rc_baton->error = Status::FromErrorString(err.AsCString());456 return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out457 }458 return FileSystem::eEnumerateDirectoryResultNext;459 } break;460 461 default:462 rc_baton->error = Status::FromErrorStringWithFormat(463 "invalid file detected during copy: %s", src.GetPath().c_str());464 return FileSystem::eEnumerateDirectoryResultQuit; // got an error, bail out465 break;466 }467 llvm_unreachable("Unhandled file_type!");468}469 470Status Platform::Install(const FileSpec &src, const FileSpec &dst) {471 Status error;472 473 Log *log = GetLog(LLDBLog::Platform);474 LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s')",475 src.GetPath().c_str(), dst.GetPath().c_str());476 FileSpec fixed_dst(dst);477 478 if (!fixed_dst.GetFilename())479 fixed_dst.SetFilename(src.GetFilename());480 481 FileSpec working_dir = GetWorkingDirectory();482 483 if (dst) {484 if (dst.GetDirectory()) {485 const char first_dst_dir_char = dst.GetDirectory().GetCString()[0];486 if (first_dst_dir_char == '/' || first_dst_dir_char == '\\') {487 fixed_dst.SetDirectory(dst.GetDirectory());488 }489 // If the fixed destination file doesn't have a directory yet, then we490 // must have a relative path. We will resolve this relative path against491 // the platform's working directory492 if (!fixed_dst.GetDirectory()) {493 FileSpec relative_spec;494 if (working_dir) {495 relative_spec = working_dir;496 relative_spec.AppendPathComponent(dst.GetPath());497 fixed_dst.SetDirectory(relative_spec.GetDirectory());498 } else {499 error = Status::FromErrorStringWithFormat(500 "platform working directory must be valid for relative path '%s'",501 dst.GetPath().c_str());502 return error;503 }504 }505 } else {506 if (working_dir) {507 fixed_dst.SetDirectory(working_dir.GetPathAsConstString());508 } else {509 error = Status::FromErrorStringWithFormat(510 "platform working directory must be valid for relative path '%s'",511 dst.GetPath().c_str());512 return error;513 }514 }515 } else {516 if (working_dir) {517 fixed_dst.SetDirectory(working_dir.GetPathAsConstString());518 } else {519 error =520 Status::FromErrorString("platform working directory must be valid "521 "when destination directory is empty");522 return error;523 }524 }525 526 LLDB_LOGF(log, "Platform::Install (src='%s', dst='%s') fixed_dst='%s'",527 src.GetPath().c_str(), dst.GetPath().c_str(),528 fixed_dst.GetPath().c_str());529 530 if (GetSupportsRSync()) {531 error = PutFile(src, dst);532 } else {533 namespace fs = llvm::sys::fs;534 switch (fs::get_file_type(src.GetPath(), false)) {535 case fs::file_type::directory_file: {536 llvm::sys::fs::remove(fixed_dst.GetPath());537 uint32_t permissions = FileSystem::Instance().GetPermissions(src);538 if (permissions == 0)539 permissions = eFilePermissionsDirectoryDefault;540 error = MakeDirectory(fixed_dst, permissions);541 if (error.Success()) {542 // Make a filespec that only fills in the directory of a FileSpec so543 // when we enumerate we can quickly fill in the filename for dst copies544 FileSpec recurse_dst;545 recurse_dst.SetDirectory(fixed_dst.GetPathAsConstString());546 std::string src_dir_path(src.GetPath());547 RecurseCopyBaton baton = {recurse_dst, this, Status()};548 FileSystem::Instance().EnumerateDirectory(549 src_dir_path, true, true, true, RecurseCopy_Callback, &baton);550 return std::move(baton.error);551 }552 } break;553 554 case fs::file_type::regular_file:555 llvm::sys::fs::remove(fixed_dst.GetPath());556 error = PutFile(src, fixed_dst);557 break;558 559 case fs::file_type::symlink_file: {560 llvm::sys::fs::remove(fixed_dst.GetPath());561 FileSpec src_resolved;562 error = FileSystem::Instance().Readlink(src, src_resolved);563 if (error.Success())564 error = CreateSymlink(dst, src_resolved);565 } break;566 case fs::file_type::fifo_file:567 error = Status::FromErrorString("platform install doesn't handle pipes");568 break;569 case fs::file_type::socket_file:570 error =571 Status::FromErrorString("platform install doesn't handle sockets");572 break;573 default:574 error = Status::FromErrorString(575 "platform install doesn't handle non file or directory items");576 break;577 }578 }579 return error;580}581 582bool Platform::SetWorkingDirectory(const FileSpec &file_spec) {583 if (IsHost()) {584 Log *log = GetLog(LLDBLog::Platform);585 LLDB_LOG(log, "{0}", file_spec);586 if (std::error_code ec = llvm::sys::fs::set_current_path(file_spec.GetPath())) {587 LLDB_LOG(log, "error: {0}", ec.message());588 return false;589 }590 return true;591 } else {592 m_working_dir.Clear();593 return SetRemoteWorkingDirectory(file_spec);594 }595}596 597Status Platform::MakeDirectory(const FileSpec &file_spec,598 uint32_t permissions) {599 if (IsHost())600 return llvm::sys::fs::create_directory(file_spec.GetPath(), permissions);601 else {602 Status error;603 return Status::FromErrorStringWithFormatv(604 "remote platform {0} doesn't support {1}", GetPluginName(),605 LLVM_PRETTY_FUNCTION);606 return error;607 }608}609 610Status Platform::GetFilePermissions(const FileSpec &file_spec,611 uint32_t &file_permissions) {612 if (IsHost()) {613 auto Value = llvm::sys::fs::getPermissions(file_spec.GetPath());614 if (Value)615 file_permissions = Value.get();616 return Status(Value.getError());617 } else {618 Status error;619 return Status::FromErrorStringWithFormatv(620 "remote platform {0} doesn't support {1}", GetPluginName(),621 LLVM_PRETTY_FUNCTION);622 return error;623 }624}625 626Status Platform::SetFilePermissions(const FileSpec &file_spec,627 uint32_t file_permissions) {628 if (IsHost()) {629 auto Perms = static_cast<llvm::sys::fs::perms>(file_permissions);630 return llvm::sys::fs::setPermissions(file_spec.GetPath(), Perms);631 } else {632 Status error;633 return Status::FromErrorStringWithFormatv(634 "remote platform {0} doesn't support {1}", GetPluginName(),635 LLVM_PRETTY_FUNCTION);636 return error;637 }638}639 640user_id_t Platform::OpenFile(const FileSpec &file_spec,641 File::OpenOptions flags, uint32_t mode,642 Status &error) {643 if (IsHost())644 return FileCache::GetInstance().OpenFile(file_spec, flags, mode, error);645 return UINT64_MAX;646}647 648bool Platform::CloseFile(user_id_t fd, Status &error) {649 if (IsHost())650 return FileCache::GetInstance().CloseFile(fd, error);651 return false;652}653 654user_id_t Platform::GetFileSize(const FileSpec &file_spec) {655 if (!IsHost())656 return UINT64_MAX;657 658 uint64_t Size;659 if (llvm::sys::fs::file_size(file_spec.GetPath(), Size))660 return 0;661 return Size;662}663 664uint64_t Platform::ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,665 uint64_t dst_len, Status &error) {666 if (IsHost())667 return FileCache::GetInstance().ReadFile(fd, offset, dst, dst_len, error);668 error = Status::FromErrorStringWithFormatv(669 "Platform::ReadFile() is not supported in the {0} platform",670 GetPluginName());671 return -1;672}673 674uint64_t Platform::WriteFile(lldb::user_id_t fd, uint64_t offset,675 const void *src, uint64_t src_len, Status &error) {676 if (IsHost())677 return FileCache::GetInstance().WriteFile(fd, offset, src, src_len, error);678 error = Status::FromErrorStringWithFormatv(679 "Platform::WriteFile() is not supported in the {0} platform",680 GetPluginName());681 return -1;682}683 684UserIDResolver &Platform::GetUserIDResolver() {685 if (IsHost())686 return HostInfo::GetUserIDResolver();687 return UserIDResolver::GetNoopResolver();688}689 690const char *Platform::GetHostname() {691 if (IsHost())692 return "127.0.0.1";693 694 if (m_hostname.empty())695 return nullptr;696 return m_hostname.c_str();697}698 699ConstString Platform::GetFullNameForDylib(ConstString basename) {700 return basename;701}702 703bool Platform::SetRemoteWorkingDirectory(const FileSpec &working_dir) {704 Log *log = GetLog(LLDBLog::Platform);705 LLDB_LOGF(log, "Platform::SetRemoteWorkingDirectory('%s')",706 working_dir.GetPath().c_str());707 m_working_dir = working_dir;708 return true;709}710 711bool Platform::SetOSVersion(llvm::VersionTuple version) {712 if (IsHost()) {713 // We don't need anyone setting the OS version for the host platform, we714 // should be able to figure it out by calling HostInfo::GetOSVersion(...).715 return false;716 } else {717 // We have a remote platform, allow setting the target OS version if we718 // aren't connected, since if we are connected, we should be able to719 // request the remote OS version from the connected platform.720 if (IsConnected())721 return false;722 else {723 // We aren't connected and we might want to set the OS version ahead of724 // time before we connect so we can peruse files and use a local SDK or725 // PDK cache of support files to disassemble or do other things.726 m_os_version = version;727 return true;728 }729 }730 return false;731}732 733Status Platform::ResolveExecutable(const ModuleSpec &module_spec,734 lldb::ModuleSP &exe_module_sp) {735 736 // We may connect to a process and use the provided executable (Don't use737 // local $PATH).738 ModuleSpec resolved_module_spec(module_spec);739 740 // Resolve any executable within a bundle on MacOSX741 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());742 743 if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()) &&744 !module_spec.GetUUID().IsValid())745 return Status::FromErrorStringWithFormatv(746 "'{0}' does not exist", resolved_module_spec.GetFileSpec());747 748 if (resolved_module_spec.GetArchitecture().IsValid() ||749 resolved_module_spec.GetUUID().IsValid()) {750 Status error = ModuleList::GetSharedModule(resolved_module_spec,751 exe_module_sp, nullptr, nullptr);752 753 if (exe_module_sp && exe_module_sp->GetObjectFile())754 return error;755 exe_module_sp.reset();756 }757 // No valid architecture was specified or the exact arch wasn't found.758 // Ask the platform for the architectures that we should be using (in the759 // correct order) and see if we can find a match that way.760 StreamString arch_names;761 llvm::ListSeparator LS;762 ArchSpec process_host_arch;763 Status error;764 for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {765 resolved_module_spec.GetArchitecture() = arch;766 767 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,768 nullptr, nullptr);769 if (error.Success()) {770 if (exe_module_sp && exe_module_sp->GetObjectFile())771 break;772 error = Status::FromErrorString("no exe object file");773 }774 775 arch_names << LS << arch.GetArchitectureName();776 }777 778 if (exe_module_sp && error.Success())779 return {};780 781 if (!FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec()))782 return Status::FromErrorStringWithFormatv(783 "'{0}' is not readable", resolved_module_spec.GetFileSpec());784 785 if (!ObjectFile::IsObjectFile(resolved_module_spec.GetFileSpec()))786 return Status::FromErrorStringWithFormatv(787 "'{0}' is not a valid executable", resolved_module_spec.GetFileSpec());788 789 return Status::FromErrorStringWithFormatv(790 "'{0}' doesn't contain any '{1}' platform architectures: {2}",791 resolved_module_spec.GetFileSpec(), GetPluginName(),792 arch_names.GetData());793}794 795Status Platform::ResolveSymbolFile(Target &target, const ModuleSpec &sym_spec,796 FileSpec &sym_file) {797 Status error;798 if (FileSystem::Instance().Exists(sym_spec.GetSymbolFileSpec()))799 sym_file = sym_spec.GetSymbolFileSpec();800 else801 error = Status::FromErrorString("unable to resolve symbol file");802 return error;803}804 805bool Platform::ResolveRemotePath(const FileSpec &platform_path,806 FileSpec &resolved_platform_path) {807 resolved_platform_path = platform_path;808 FileSystem::Instance().Resolve(resolved_platform_path);809 return true;810}811 812const ArchSpec &Platform::GetSystemArchitecture() {813 if (IsHost()) {814 if (!m_system_arch.IsValid()) {815 // We have a local host platform816 m_system_arch = HostInfo::GetArchitecture();817 m_system_arch_set_while_connected = m_system_arch.IsValid();818 }819 } else {820 // We have a remote platform. We can only fetch the remote system821 // architecture if we are connected, and we don't want to do it more than822 // once.823 824 const bool is_connected = IsConnected();825 826 bool fetch = false;827 if (m_system_arch.IsValid()) {828 // We have valid OS version info, check to make sure it wasn't manually829 // set prior to connecting. If it was manually set prior to connecting,830 // then lets fetch the actual OS version info if we are now connected.831 if (is_connected && !m_system_arch_set_while_connected)832 fetch = true;833 } else {834 // We don't have valid OS version info, fetch it if we are connected835 fetch = is_connected;836 }837 838 if (fetch) {839 m_system_arch = GetRemoteSystemArchitecture();840 m_system_arch_set_while_connected = m_system_arch.IsValid();841 }842 }843 return m_system_arch;844}845 846ArchSpec Platform::GetAugmentedArchSpec(llvm::StringRef triple) {847 if (triple.empty())848 return ArchSpec();849 llvm::Triple normalized_triple(llvm::Triple::normalize(triple));850 if (!ArchSpec::ContainsOnlyArch(normalized_triple))851 return ArchSpec(triple);852 853 if (auto kind = HostInfo::ParseArchitectureKind(triple))854 return HostInfo::GetArchitecture(*kind);855 856 ArchSpec compatible_arch;857 ArchSpec raw_arch(triple);858 if (!IsCompatibleArchitecture(raw_arch, {}, ArchSpec::CompatibleMatch,859 &compatible_arch))860 return raw_arch;861 862 if (!compatible_arch.IsValid())863 return ArchSpec(normalized_triple);864 865 const llvm::Triple &compatible_triple = compatible_arch.GetTriple();866 if (normalized_triple.getVendorName().empty())867 normalized_triple.setVendor(compatible_triple.getVendor());868 if (normalized_triple.getOSName().empty())869 normalized_triple.setOS(compatible_triple.getOS());870 if (normalized_triple.getEnvironmentName().empty())871 normalized_triple.setEnvironment(compatible_triple.getEnvironment());872 return ArchSpec(normalized_triple);873}874 875Status Platform::ConnectRemote(Args &args) {876 Status error;877 if (IsHost())878 return Status::FromErrorStringWithFormatv(879 "The currently selected platform ({0}) is "880 "the host platform and is always connected.",881 GetPluginName());882 else883 return Status::FromErrorStringWithFormatv(884 "Platform::ConnectRemote() is not supported by {0}", GetPluginName());885 return error;886}887 888Status Platform::DisconnectRemote() {889 Status error;890 if (IsHost())891 return Status::FromErrorStringWithFormatv(892 "The currently selected platform ({0}) is "893 "the host platform and is always connected.",894 GetPluginName());895 else896 return Status::FromErrorStringWithFormatv(897 "Platform::DisconnectRemote() is not supported by {0}",898 GetPluginName());899 return error;900}901 902bool Platform::GetProcessInfo(lldb::pid_t pid,903 ProcessInstanceInfo &process_info) {904 // Take care of the host case so that each subclass can just call this905 // function to get the host functionality.906 if (IsHost())907 return Host::GetProcessInfo(pid, process_info);908 return false;909}910 911uint32_t Platform::FindProcesses(const ProcessInstanceInfoMatch &match_info,912 ProcessInstanceInfoList &process_infos) {913 // Take care of the host case so that each subclass can just call this914 // function to get the host functionality.915 uint32_t match_count = 0;916 if (IsHost())917 match_count = Host::FindProcesses(match_info, process_infos);918 return match_count;919}920 921ProcessInstanceInfoList Platform::GetAllProcesses() {922 ProcessInstanceInfoList processes;923 ProcessInstanceInfoMatch match;924 assert(match.MatchAllProcesses());925 FindProcesses(match, processes);926 return processes;927}928 929Status Platform::LaunchProcess(ProcessLaunchInfo &launch_info) {930 Status error;931 Log *log = GetLog(LLDBLog::Platform);932 LLDB_LOGF(log, "Platform::%s()", __FUNCTION__);933 934 // Take care of the host case so that each subclass can just call this935 // function to get the host functionality.936 if (IsHost()) {937 if (::getenv("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"))938 launch_info.GetFlags().Set(eLaunchFlagLaunchInTTY);939 940 if (launch_info.GetFlags().Test(eLaunchFlagLaunchInShell)) {941 const bool will_debug = launch_info.GetFlags().Test(eLaunchFlagDebug);942 const bool first_arg_is_full_shell_command = false;943 uint32_t num_resumes = GetResumeCountForLaunchInfo(launch_info);944 if (log) {945 const FileSpec &shell = launch_info.GetShell();946 std::string shell_str = (shell) ? shell.GetPath() : "<null>";947 LLDB_LOGF(log,948 "Platform::%s GetResumeCountForLaunchInfo() returned %" PRIu32949 ", shell is '%s'",950 __FUNCTION__, num_resumes, shell_str.c_str());951 }952 953 if (!launch_info.ConvertArgumentsForLaunchingInShell(954 error, will_debug, first_arg_is_full_shell_command, num_resumes))955 return error;956 } else if (launch_info.GetFlags().Test(eLaunchFlagShellExpandArguments)) {957 error = ShellExpandArguments(launch_info);958 if (error.Fail()) {959 error = Status::FromErrorStringWithFormat(960 "shell expansion failed (reason: %s). "961 "consider launching with 'process "962 "launch'.",963 error.AsCString("unknown"));964 return error;965 }966 }967 968 LLDB_LOGF(log, "Platform::%s final launch_info resume count: %" PRIu32,969 __FUNCTION__, launch_info.GetResumeCount());970 971 error = Host::LaunchProcess(launch_info);972 } else973 error = Status::FromErrorString(974 "base lldb_private::Platform class can't launch remote processes");975 return error;976}977 978Status Platform::ShellExpandArguments(ProcessLaunchInfo &launch_info) {979 if (IsHost())980 return Host::ShellExpandArguments(launch_info);981 return Status::FromErrorString(982 "base lldb_private::Platform class can't expand arguments");983}984 985Status Platform::KillProcess(const lldb::pid_t pid) {986 Log *log = GetLog(LLDBLog::Platform);987 LLDB_LOGF(log, "Platform::%s, pid %" PRIu64, __FUNCTION__, pid);988 989 if (!IsHost()) {990 return Status::FromErrorString(991 "base lldb_private::Platform class can't kill remote processes");992 }993 Host::Kill(pid, SIGKILL);994 return Status();995}996 997lldb::ProcessSP Platform::DebugProcess(ProcessLaunchInfo &launch_info,998 Debugger &debugger, Target &target,999 Status &error) {1000 Log *log = GetLog(LLDBLog::Platform);1001 LLDB_LOG(log, "target = {0}", &target);1002 1003 ProcessSP process_sp;1004 // Make sure we stop at the entry point1005 launch_info.GetFlags().Set(eLaunchFlagDebug);1006 // We always launch the process we are going to debug in a separate process1007 // group, since then we can handle ^C interrupts ourselves w/o having to1008 // worry about the target getting them as well.1009 launch_info.SetLaunchInSeparateProcessGroup(true);1010 1011 // Allow any StructuredData process-bound plugins to adjust the launch info1012 // if needed1013 size_t i = 0;1014 bool iteration_complete = false;1015 // Note iteration can't simply go until a nullptr callback is returned, as it1016 // is valid for a plugin to not supply a filter.1017 auto get_filter_func = PluginManager::GetStructuredDataFilterCallbackAtIndex;1018 for (auto filter_callback = get_filter_func(i, iteration_complete);1019 !iteration_complete;1020 filter_callback = get_filter_func(++i, iteration_complete)) {1021 if (filter_callback) {1022 // Give this ProcessLaunchInfo filter a chance to adjust the launch info.1023 error = (*filter_callback)(launch_info, &target);1024 if (!error.Success()) {1025 LLDB_LOGF(log,1026 "Platform::%s() StructuredDataPlugin launch "1027 "filter failed.",1028 __FUNCTION__);1029 return process_sp;1030 }1031 }1032 }1033 1034 error = LaunchProcess(launch_info);1035 if (error.Success()) {1036 LLDB_LOGF(log,1037 "Platform::%s LaunchProcess() call succeeded (pid=%" PRIu64 ")",1038 __FUNCTION__, launch_info.GetProcessID());1039 if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {1040 ProcessAttachInfo attach_info(launch_info);1041 process_sp = Attach(attach_info, debugger, &target, error);1042 if (process_sp) {1043 LLDB_LOG(log, "Attach() succeeded, Process plugin: {0}",1044 process_sp->GetPluginName());1045 launch_info.SetHijackListener(attach_info.GetHijackListener());1046 1047 // Since we attached to the process, it will think it needs to detach1048 // if the process object just goes away without an explicit call to1049 // Process::Kill() or Process::Detach(), so let it know to kill the1050 // process if this happens.1051 process_sp->SetShouldDetach(false);1052 1053 // If we didn't have any file actions, the pseudo terminal might have1054 // been used where the secondary side was given as the file to open for1055 // stdin/out/err after we have already opened the primary so we can1056 // read/write stdin/out/err.1057 int pty_fd = launch_info.GetPTY().ReleasePrimaryFileDescriptor();1058 if (pty_fd != PseudoTerminal::invalid_fd) {1059 process_sp->SetSTDIOFileDescriptor(pty_fd);1060 }1061 } else {1062 LLDB_LOGF(log, "Platform::%s Attach() failed: %s", __FUNCTION__,1063 error.AsCString());1064 }1065 } else {1066 LLDB_LOGF(log,1067 "Platform::%s LaunchProcess() returned launch_info with "1068 "invalid process id",1069 __FUNCTION__);1070 }1071 } else {1072 LLDB_LOGF(log, "Platform::%s LaunchProcess() failed: %s", __FUNCTION__,1073 error.AsCString());1074 }1075 1076 return process_sp;1077}1078 1079std::vector<ArchSpec>1080Platform::CreateArchList(llvm::ArrayRef<llvm::Triple::ArchType> archs,1081 llvm::Triple::OSType os) {1082 std::vector<ArchSpec> list;1083 for(auto arch : archs) {1084 llvm::Triple triple;1085 triple.setArch(arch);1086 triple.setOS(os);1087 list.push_back(ArchSpec(triple));1088 }1089 return list;1090}1091 1092/// Lets a platform answer if it is compatible with a given1093/// architecture and the target triple contained within.1094bool Platform::IsCompatibleArchitecture(const ArchSpec &arch,1095 const ArchSpec &process_host_arch,1096 ArchSpec::MatchType match,1097 ArchSpec *compatible_arch_ptr) {1098 // If the architecture is invalid, we must answer true...1099 if (arch.IsValid()) {1100 ArchSpec platform_arch;1101 for (const ArchSpec &platform_arch :1102 GetSupportedArchitectures(process_host_arch)) {1103 if (arch.IsMatch(platform_arch, match)) {1104 if (compatible_arch_ptr)1105 *compatible_arch_ptr = platform_arch;1106 return true;1107 }1108 }1109 }1110 if (compatible_arch_ptr)1111 compatible_arch_ptr->Clear();1112 return false;1113}1114 1115Status Platform::PutFile(const FileSpec &source, const FileSpec &destination,1116 uint32_t uid, uint32_t gid) {1117 Log *log = GetLog(LLDBLog::Platform);1118 LLDB_LOGF(log, "[PutFile] Using block by block transfer....\n");1119 1120 auto source_open_options =1121 File::eOpenOptionReadOnly | File::eOpenOptionCloseOnExec;1122 namespace fs = llvm::sys::fs;1123 if (fs::is_symlink_file(source.GetPath()))1124 source_open_options |= File::eOpenOptionDontFollowSymlinks;1125 1126 auto source_file = FileSystem::Instance().Open(source, source_open_options,1127 lldb::eFilePermissionsUserRW);1128 if (!source_file)1129 return Status::FromError(source_file.takeError());1130 Status error;1131 1132 bool requires_upload = true;1133 llvm::ErrorOr<llvm::MD5::MD5Result> remote_md5 = CalculateMD5(destination);1134 if (std::error_code ec = remote_md5.getError()) {1135 LLDB_LOG(log, "[PutFile] couldn't get md5 sum of destination: {0}",1136 ec.message());1137 } else {1138 llvm::ErrorOr<llvm::MD5::MD5Result> local_md5 =1139 llvm::sys::fs::md5_contents(source.GetPath());1140 if (std::error_code ec = local_md5.getError()) {1141 LLDB_LOG(log, "[PutFile] couldn't get md5 sum of source: {0}",1142 ec.message());1143 } else {1144 LLDB_LOGF(log, "[PutFile] destination md5: %016" PRIx64 "%016" PRIx64,1145 remote_md5->high(), remote_md5->low());1146 LLDB_LOGF(log, "[PutFile] local md5: %016" PRIx64 "%016" PRIx64,1147 local_md5->high(), local_md5->low());1148 requires_upload = *remote_md5 != *local_md5;1149 }1150 }1151 1152 if (!requires_upload) {1153 LLDB_LOGF(log, "[PutFile] skipping PutFile because md5sums match");1154 return error;1155 }1156 1157 uint32_t permissions = source_file.get()->GetPermissions(error);1158 if (permissions == 0)1159 permissions = lldb::eFilePermissionsUserRWX;1160 1161 lldb::user_id_t dest_file = OpenFile(1162 destination, File::eOpenOptionCanCreate | File::eOpenOptionWriteOnly |1163 File::eOpenOptionTruncate | File::eOpenOptionCloseOnExec,1164 permissions, error);1165 LLDB_LOGF(log, "dest_file = %" PRIu64 "\n", dest_file);1166 1167 if (error.Fail())1168 return error;1169 if (dest_file == UINT64_MAX)1170 return Status::FromErrorString("unable to open target file");1171 lldb::WritableDataBufferSP buffer_sp(new DataBufferHeap(1024 * 16, 0));1172 uint64_t offset = 0;1173 for (;;) {1174 size_t bytes_read = buffer_sp->GetByteSize();1175 error = source_file.get()->Read(buffer_sp->GetBytes(), bytes_read);1176 if (error.Fail() || bytes_read == 0)1177 break;1178 1179 const uint64_t bytes_written =1180 WriteFile(dest_file, offset, buffer_sp->GetBytes(), bytes_read, error);1181 if (error.Fail())1182 break;1183 1184 offset += bytes_written;1185 if (bytes_written != bytes_read) {1186 // We didn't write the correct number of bytes, so adjust the file1187 // position in the source file we are reading from...1188 source_file.get()->SeekFromStart(offset);1189 }1190 }1191 CloseFile(dest_file, error);1192 1193 if (uid == UINT32_MAX && gid == UINT32_MAX)1194 return error;1195 1196 // TODO: ChownFile?1197 1198 return error;1199}1200 1201Status Platform::GetFile(const FileSpec &source, const FileSpec &destination) {1202 return Status::FromErrorString("unimplemented");1203}1204 1205Status1206Platform::CreateSymlink(const FileSpec &src, // The name of the link is in src1207 const FileSpec &dst) // The symlink points to dst1208{1209 if (IsHost())1210 return FileSystem::Instance().Symlink(src, dst);1211 return Status::FromErrorString("unimplemented");1212}1213 1214bool Platform::GetFileExists(const lldb_private::FileSpec &file_spec) {1215 if (IsHost())1216 return FileSystem::Instance().Exists(file_spec);1217 return false;1218}1219 1220Status Platform::Unlink(const FileSpec &path) {1221 if (IsHost())1222 return llvm::sys::fs::remove(path.GetPath());1223 return Status::FromErrorString("unimplemented");1224}1225 1226MmapArgList Platform::GetMmapArgumentList(const ArchSpec &arch, addr_t addr,1227 addr_t length, unsigned prot,1228 unsigned flags, addr_t fd,1229 addr_t offset) {1230 uint64_t flags_platform = 0;1231 if (flags & eMmapFlagsPrivate)1232 flags_platform |= MAP_PRIVATE;1233 if (flags & eMmapFlagsAnon)1234 flags_platform |= MAP_ANON;1235 1236 MmapArgList args({addr, length, prot, flags_platform, fd, offset});1237 return args;1238}1239 1240lldb_private::Status Platform::RunShellCommand(1241 llvm::StringRef command,1242 const FileSpec &1243 working_dir, // Pass empty FileSpec to use the current working directory1244 int *status_ptr, // Pass nullptr if you don't want the process exit status1245 int *signo_ptr, // Pass nullptr if you don't want the signal that caused the1246 // process to exit1247 std::string1248 *command_output, // Pass nullptr if you don't want the command output1249 const Timeout<std::micro> &timeout) {1250 return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,1251 signo_ptr, command_output, timeout);1252}1253 1254lldb_private::Status Platform::RunShellCommand(1255 llvm::StringRef shell, // Pass empty if you want to use the default1256 // shell interpreter1257 llvm::StringRef command, // Shouldn't be empty1258 const FileSpec &1259 working_dir, // Pass empty FileSpec to use the current working directory1260 int *status_ptr, // Pass nullptr if you don't want the process exit status1261 int *signo_ptr, // Pass nullptr if you don't want the signal that caused the1262 // process to exit1263 std::string1264 *command_output, // Pass nullptr if you don't want the command output1265 const Timeout<std::micro> &timeout) {1266 if (IsHost())1267 return Host::RunShellCommand(shell, command, working_dir, status_ptr,1268 signo_ptr, command_output, timeout);1269 return Status::FromErrorString(1270 "unable to run a remote command without a platform");1271}1272 1273llvm::ErrorOr<llvm::MD5::MD5Result>1274Platform::CalculateMD5(const FileSpec &file_spec) {1275 if (!IsHost())1276 return std::make_error_code(std::errc::not_supported);1277 return llvm::sys::fs::md5_contents(file_spec.GetPath());1278}1279 1280void Platform::SetLocalCacheDirectory(const char *local) {1281 m_local_cache_directory.assign(local);1282}1283 1284const char *Platform::GetLocalCacheDirectory() {1285 return m_local_cache_directory.c_str();1286}1287 1288static constexpr OptionDefinition g_rsync_option_table[] = {1289 {LLDB_OPT_SET_ALL, false, "rsync", 'r', OptionParser::eNoArgument, nullptr,1290 {}, 0, eArgTypeNone, "Enable rsync."},1291 {LLDB_OPT_SET_ALL, false, "rsync-opts", 'R',1292 OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,1293 "Platform-specific options required for rsync to work."},1294 {LLDB_OPT_SET_ALL, false, "rsync-prefix", 'P',1295 OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommandName,1296 "Platform-specific rsync prefix put before the remote path."},1297 {LLDB_OPT_SET_ALL, false, "ignore-remote-hostname", 'i',1298 OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone,1299 "Do not automatically fill in the remote hostname when composing the "1300 "rsync command."},1301};1302 1303static constexpr OptionDefinition g_ssh_option_table[] = {1304 {LLDB_OPT_SET_ALL, false, "ssh", 's', OptionParser::eNoArgument, nullptr,1305 {}, 0, eArgTypeNone, "Enable SSH."},1306 {LLDB_OPT_SET_ALL, false, "ssh-opts", 'S', OptionParser::eRequiredArgument,1307 nullptr, {}, 0, eArgTypeCommandName,1308 "Platform-specific options required for SSH to work."},1309};1310 1311static constexpr OptionDefinition g_caching_option_table[] = {1312 {LLDB_OPT_SET_ALL, false, "local-cache-dir", 'c',1313 OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePath,1314 "Path in which to store local copies of files."},1315};1316 1317llvm::ArrayRef<OptionDefinition> OptionGroupPlatformRSync::GetDefinitions() {1318 return llvm::ArrayRef(g_rsync_option_table);1319}1320 1321void OptionGroupPlatformRSync::OptionParsingStarting(1322 ExecutionContext *execution_context) {1323 m_rsync = false;1324 m_rsync_opts.clear();1325 m_rsync_prefix.clear();1326 m_ignores_remote_hostname = false;1327}1328 1329lldb_private::Status1330OptionGroupPlatformRSync::SetOptionValue(uint32_t option_idx,1331 llvm::StringRef option_arg,1332 ExecutionContext *execution_context) {1333 Status error;1334 char short_option = (char)GetDefinitions()[option_idx].short_option;1335 switch (short_option) {1336 case 'r':1337 m_rsync = true;1338 break;1339 1340 case 'R':1341 m_rsync_opts.assign(std::string(option_arg));1342 break;1343 1344 case 'P':1345 m_rsync_prefix.assign(std::string(option_arg));1346 break;1347 1348 case 'i':1349 m_ignores_remote_hostname = true;1350 break;1351 1352 default:1353 error = Status::FromErrorStringWithFormat("unrecognized option '%c'",1354 short_option);1355 break;1356 }1357 1358 return error;1359}1360 1361lldb::BreakpointSP1362Platform::SetThreadCreationBreakpoint(lldb_private::Target &target) {1363 return lldb::BreakpointSP();1364}1365 1366llvm::ArrayRef<OptionDefinition> OptionGroupPlatformSSH::GetDefinitions() {1367 return llvm::ArrayRef(g_ssh_option_table);1368}1369 1370void OptionGroupPlatformSSH::OptionParsingStarting(1371 ExecutionContext *execution_context) {1372 m_ssh = false;1373 m_ssh_opts.clear();1374}1375 1376lldb_private::Status1377OptionGroupPlatformSSH::SetOptionValue(uint32_t option_idx,1378 llvm::StringRef option_arg,1379 ExecutionContext *execution_context) {1380 Status error;1381 char short_option = (char)GetDefinitions()[option_idx].short_option;1382 switch (short_option) {1383 case 's':1384 m_ssh = true;1385 break;1386 1387 case 'S':1388 m_ssh_opts.assign(std::string(option_arg));1389 break;1390 1391 default:1392 error = Status::FromErrorStringWithFormat("unrecognized option '%c'",1393 short_option);1394 break;1395 }1396 1397 return error;1398}1399 1400llvm::ArrayRef<OptionDefinition> OptionGroupPlatformCaching::GetDefinitions() {1401 return llvm::ArrayRef(g_caching_option_table);1402}1403 1404void OptionGroupPlatformCaching::OptionParsingStarting(1405 ExecutionContext *execution_context) {1406 m_cache_dir.clear();1407}1408 1409lldb_private::Status OptionGroupPlatformCaching::SetOptionValue(1410 uint32_t option_idx, llvm::StringRef option_arg,1411 ExecutionContext *execution_context) {1412 Status error;1413 char short_option = (char)GetDefinitions()[option_idx].short_option;1414 switch (short_option) {1415 case 'c':1416 m_cache_dir.assign(std::string(option_arg));1417 break;1418 1419 default:1420 error = Status::FromErrorStringWithFormat("unrecognized option '%c'",1421 short_option);1422 break;1423 }1424 1425 return error;1426}1427 1428Environment Platform::GetEnvironment() {1429 if (IsHost())1430 return Host::GetEnvironment();1431 return Environment();1432}1433 1434const std::vector<ConstString> &Platform::GetTrapHandlerSymbolNames() {1435 if (!m_calculated_trap_handlers) {1436 std::lock_guard<std::mutex> guard(m_mutex);1437 if (!m_calculated_trap_handlers) {1438 CalculateTrapHandlerSymbolNames();1439 m_calculated_trap_handlers = true;1440 }1441 }1442 return m_trap_handlers;1443}1444 1445Status Platform::GetCachedExecutable(ModuleSpec &module_spec,1446 lldb::ModuleSP &module_sp) {1447 FileSpec platform_spec = module_spec.GetFileSpec();1448 Status error = GetRemoteSharedModule(1449 module_spec, nullptr, module_sp,1450 [&](const ModuleSpec &spec) {1451 return Platform::ResolveExecutable(spec, module_sp);1452 },1453 nullptr);1454 if (error.Success()) {1455 module_spec.GetFileSpec() = module_sp->GetFileSpec();1456 module_spec.GetPlatformFileSpec() = platform_spec;1457 }1458 1459 return error;1460}1461 1462Status Platform::GetRemoteSharedModule(const ModuleSpec &module_spec,1463 Process *process,1464 lldb::ModuleSP &module_sp,1465 const ModuleResolver &module_resolver,1466 bool *did_create_ptr) {1467 // Get module information from a target.1468 ModuleSpec resolved_module_spec;1469 ArchSpec process_host_arch;1470 bool got_module_spec = false;1471 if (process) {1472 process_host_arch = process->GetSystemArchitecture();1473 // Try to get module information from the process1474 if (process->GetModuleSpec(module_spec.GetFileSpec(),1475 module_spec.GetArchitecture(),1476 resolved_module_spec)) {1477 if (!module_spec.GetUUID().IsValid() ||1478 module_spec.GetUUID() == resolved_module_spec.GetUUID()) {1479 got_module_spec = true;1480 }1481 }1482 }1483 1484 if (!module_spec.GetArchitecture().IsValid()) {1485 Status error;1486 // No valid architecture was specified, ask the platform for the1487 // architectures that we should be using (in the correct order) and see if1488 // we can find a match that way1489 ModuleSpec arch_module_spec(module_spec);1490 for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {1491 arch_module_spec.GetArchitecture() = arch;1492 error = ModuleList::GetSharedModule(arch_module_spec, module_sp, nullptr,1493 nullptr);1494 // Did we find an executable using one of the1495 if (error.Success() && module_sp)1496 break;1497 }1498 if (module_sp) {1499 resolved_module_spec = arch_module_spec;1500 got_module_spec = true;1501 }1502 }1503 1504 if (!got_module_spec) {1505 // Get module information from a target.1506 if (GetModuleSpec(module_spec.GetFileSpec(), module_spec.GetArchitecture(),1507 resolved_module_spec)) {1508 if (!module_spec.GetUUID().IsValid() ||1509 module_spec.GetUUID() == resolved_module_spec.GetUUID()) {1510 got_module_spec = true;1511 }1512 }1513 }1514 1515 if (!got_module_spec) {1516 // Fall back to the given module resolver, which may have its own1517 // search logic.1518 return module_resolver(module_spec);1519 }1520 1521 // If we are looking for a specific UUID, make sure resolved_module_spec has1522 // the same one before we search.1523 if (module_spec.GetUUID().IsValid()) {1524 resolved_module_spec.GetUUID() = module_spec.GetUUID();1525 }1526 1527 // Call locate module callback if set. This allows users to implement their1528 // own module cache system. For example, to leverage build system artifacts,1529 // to bypass pulling files from remote platform, or to search symbol files1530 // from symbol servers.1531 FileSpec symbol_file_spec;1532 CallLocateModuleCallbackIfSet(resolved_module_spec, module_sp,1533 symbol_file_spec, did_create_ptr);1534 if (module_sp) {1535 // The module is loaded.1536 if (symbol_file_spec) {1537 // 1. module_sp:loaded, symbol_file_spec:set1538 // The callback found a module file and a symbol file for this1539 // resolved_module_spec. Set the symbol file to the module.1540 module_sp->SetSymbolFileFileSpec(symbol_file_spec);1541 } else {1542 // 2. module_sp:loaded, symbol_file_spec:empty1543 // The callback only found a module file for this1544 // resolved_module_spec.1545 }1546 return Status();1547 }1548 1549 // The module is not loaded by CallLocateModuleCallbackIfSet.1550 // 3. module_sp:empty, symbol_file_spec:set1551 // The callback only found a symbol file for the module. We continue to1552 // find a module file for this resolved_module_spec. and we will call1553 // module_sp->SetSymbolFileFileSpec with the symbol_file_spec later.1554 // 4. module_sp:empty, symbol_file_spec:empty1555 // The callback is not set. Or the callback did not find any module1556 // files nor any symbol files. Or the callback failed, or something1557 // went wrong. We continue to find a module file for this1558 // resolved_module_spec.1559 1560 // Trying to find a module by UUID on local file system.1561 Status error = module_resolver(resolved_module_spec);1562 if (error.Success()) {1563 if (module_sp && symbol_file_spec) {1564 // Set the symbol file to the module if the locate modudle callback was1565 // called and returned only a symbol file.1566 module_sp->SetSymbolFileFileSpec(symbol_file_spec);1567 }1568 return error;1569 }1570 1571 // Fallback to call GetCachedSharedModule on failure.1572 if (GetCachedSharedModule(resolved_module_spec, module_sp, did_create_ptr)) {1573 if (module_sp && symbol_file_spec) {1574 // Set the symbol file to the module if the locate modudle callback was1575 // called and returned only a symbol file.1576 module_sp->SetSymbolFileFileSpec(symbol_file_spec);1577 }1578 return Status();1579 }1580 1581 return Status::FromErrorStringWithFormat(1582 "Failed to call GetCachedSharedModule");1583}1584 1585void Platform::CallLocateModuleCallbackIfSet(const ModuleSpec &module_spec,1586 lldb::ModuleSP &module_sp,1587 FileSpec &symbol_file_spec,1588 bool *did_create_ptr) {1589 if (!m_locate_module_callback) {1590 // Locate module callback is not set.1591 return;1592 }1593 1594 FileSpec module_file_spec;1595 Status error =1596 m_locate_module_callback(module_spec, module_file_spec, symbol_file_spec);1597 1598 // Locate module callback is set and called. Check the error.1599 Log *log = GetLog(LLDBLog::Platform);1600 if (error.Fail()) {1601 LLDB_LOGF(log, "%s: locate module callback failed: %s",1602 LLVM_PRETTY_FUNCTION, error.AsCString());1603 return;1604 }1605 1606 // The locate module callback was succeeded.1607 // Check the module_file_spec and symbol_file_spec values.1608 // 1. module:empty symbol:empty -> Failure1609 // - The callback did not return any files.1610 // 2. module:exists symbol:exists -> Success1611 // - The callback returned a module file and a symbol file.1612 // 3. module:exists symbol:empty -> Success1613 // - The callback returned only a module file.1614 // 4. module:empty symbol:exists -> Success1615 // - The callback returned only a symbol file.1616 // For example, a breakpad symbol text file.1617 if (!module_file_spec && !symbol_file_spec) {1618 // This is '1. module:empty symbol:empty -> Failure'1619 // The callback did not return any files.1620 LLDB_LOGF(log,1621 "%s: locate module callback did not set both "1622 "module_file_spec and symbol_file_spec",1623 LLVM_PRETTY_FUNCTION);1624 return;1625 }1626 1627 // If the callback returned a module file, it should exist.1628 if (module_file_spec && !FileSystem::Instance().Exists(module_file_spec)) {1629 LLDB_LOGF(log,1630 "%s: locate module callback set a non-existent file to "1631 "module_file_spec: %s",1632 LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str());1633 // Clear symbol_file_spec for the error.1634 symbol_file_spec.Clear();1635 return;1636 }1637 1638 // If the callback returned a symbol file, it should exist.1639 if (symbol_file_spec && !FileSystem::Instance().Exists(symbol_file_spec)) {1640 LLDB_LOGF(log,1641 "%s: locate module callback set a non-existent file to "1642 "symbol_file_spec: %s",1643 LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());1644 // Clear symbol_file_spec for the error.1645 symbol_file_spec.Clear();1646 return;1647 }1648 1649 if (!module_file_spec && symbol_file_spec) {1650 // This is '4. module:empty symbol:exists -> Success'1651 // The locate module callback returned only a symbol file. For example,1652 // a breakpad symbol text file. GetRemoteSharedModule will use this returned1653 // symbol_file_spec.1654 LLDB_LOGF(log, "%s: locate module callback succeeded: symbol=%s",1655 LLVM_PRETTY_FUNCTION, symbol_file_spec.GetPath().c_str());1656 return;1657 }1658 1659 // This is one of the following.1660 // - 2. module:exists symbol:exists -> Success1661 // - The callback returned a module file and a symbol file.1662 // - 3. module:exists symbol:empty -> Success1663 // - The callback returned Only a module file.1664 // Load the module file.1665 auto cached_module_spec(module_spec);1666 cached_module_spec.GetUUID().Clear(); // Clear UUID since it may contain md51667 // content hash instead of real UUID.1668 cached_module_spec.GetFileSpec() = module_file_spec;1669 cached_module_spec.GetSymbolFileSpec() = symbol_file_spec;1670 cached_module_spec.GetPlatformFileSpec() = module_spec.GetFileSpec();1671 cached_module_spec.SetObjectOffset(0);1672 1673 error = ModuleList::GetSharedModule(cached_module_spec, module_sp, nullptr,1674 did_create_ptr, false, false);1675 if (error.Success() && module_sp) {1676 // Succeeded to load the module file.1677 LLDB_LOGF(log, "%s: locate module callback succeeded: module=%s symbol=%s",1678 LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),1679 symbol_file_spec.GetPath().c_str());1680 } else {1681 LLDB_LOGF(log,1682 "%s: locate module callback succeeded but failed to load: "1683 "module=%s symbol=%s",1684 LLVM_PRETTY_FUNCTION, module_file_spec.GetPath().c_str(),1685 symbol_file_spec.GetPath().c_str());1686 // Clear module_sp and symbol_file_spec for the error.1687 module_sp.reset();1688 symbol_file_spec.Clear();1689 }1690}1691 1692bool Platform::GetCachedSharedModule(const ModuleSpec &module_spec,1693 lldb::ModuleSP &module_sp,1694 bool *did_create_ptr) {1695 if (IsHost() || !GetGlobalPlatformProperties().GetUseModuleCache() ||1696 !GetGlobalPlatformProperties().GetModuleCacheDirectory())1697 return false;1698 1699 Log *log = GetLog(LLDBLog::Platform);1700 1701 // Check local cache for a module.1702 auto error = m_module_cache->GetAndPut(1703 GetModuleCacheRoot(), GetCacheHostname(), module_spec,1704 [this](const ModuleSpec &module_spec,1705 const FileSpec &tmp_download_file_spec) {1706 return DownloadModuleSlice(1707 module_spec.GetFileSpec(), module_spec.GetObjectOffset(),1708 module_spec.GetObjectSize(), tmp_download_file_spec);1709 1710 },1711 [this](const ModuleSP &module_sp,1712 const FileSpec &tmp_download_file_spec) {1713 return DownloadSymbolFile(module_sp, tmp_download_file_spec);1714 },1715 module_sp, did_create_ptr);1716 if (error.Success())1717 return true;1718 1719 LLDB_LOGF(log, "Platform::%s - module %s not found in local cache: %s",1720 __FUNCTION__, module_spec.GetUUID().GetAsString().c_str(),1721 error.AsCString());1722 return false;1723}1724 1725Status Platform::DownloadModuleSlice(const FileSpec &src_file_spec,1726 const uint64_t src_offset,1727 const uint64_t src_size,1728 const FileSpec &dst_file_spec) {1729 Status error;1730 1731 std::error_code EC;1732 llvm::raw_fd_ostream dst(dst_file_spec.GetPath(), EC, llvm::sys::fs::OF_None);1733 if (EC) {1734 error = Status::FromErrorStringWithFormat(1735 "unable to open destination file: %s", dst_file_spec.GetPath().c_str());1736 return error;1737 }1738 1739 auto src_fd = OpenFile(src_file_spec, File::eOpenOptionReadOnly,1740 lldb::eFilePermissionsFileDefault, error);1741 1742 if (error.Fail()) {1743 error = Status::FromErrorStringWithFormat("unable to open source file: %s",1744 error.AsCString());1745 return error;1746 }1747 1748 std::vector<char> buffer(512 * 1024);1749 auto offset = src_offset;1750 uint64_t total_bytes_read = 0;1751 while (total_bytes_read < src_size) {1752 const auto to_read = std::min(static_cast<uint64_t>(buffer.size()),1753 src_size - total_bytes_read);1754 const uint64_t n_read =1755 ReadFile(src_fd, offset, &buffer[0], to_read, error);1756 if (error.Fail())1757 break;1758 if (n_read == 0) {1759 error = Status::FromErrorString("read 0 bytes");1760 break;1761 }1762 offset += n_read;1763 total_bytes_read += n_read;1764 dst.write(&buffer[0], n_read);1765 }1766 1767 Status close_error;1768 CloseFile(src_fd, close_error); // Ignoring close error.1769 1770 return error;1771}1772 1773Status Platform::DownloadSymbolFile(const lldb::ModuleSP &module_sp,1774 const FileSpec &dst_file_spec) {1775 return Status::FromErrorString(1776 "Symbol file downloading not supported by the default platform.");1777}1778 1779FileSpec Platform::GetModuleCacheRoot() {1780 auto dir_spec = GetGlobalPlatformProperties().GetModuleCacheDirectory();1781 dir_spec.AppendPathComponent(GetPluginName());1782 return dir_spec;1783}1784 1785const char *Platform::GetCacheHostname() { return GetHostname(); }1786 1787const UnixSignalsSP &Platform::GetRemoteUnixSignals() {1788 static const auto s_default_unix_signals_sp = std::make_shared<UnixSignals>();1789 return s_default_unix_signals_sp;1790}1791 1792UnixSignalsSP Platform::GetUnixSignals() {1793 if (IsHost())1794 return UnixSignals::CreateForHost();1795 return GetRemoteUnixSignals();1796}1797 1798uint32_t Platform::LoadImage(lldb_private::Process *process,1799 const lldb_private::FileSpec &local_file,1800 const lldb_private::FileSpec &remote_file,1801 lldb_private::Status &error) {1802 if (local_file && remote_file) {1803 // Both local and remote file was specified. Install the local file to the1804 // given location.1805 if (IsRemote() || local_file != remote_file) {1806 error = Install(local_file, remote_file);1807 if (error.Fail())1808 return LLDB_INVALID_IMAGE_TOKEN;1809 }1810 return DoLoadImage(process, remote_file, nullptr, error);1811 }1812 1813 if (local_file) {1814 // Only local file was specified. Install it to the current working1815 // directory.1816 FileSpec target_file = GetWorkingDirectory();1817 target_file.AppendPathComponent(local_file.GetFilename().AsCString());1818 if (IsRemote() || local_file != target_file) {1819 error = Install(local_file, target_file);1820 if (error.Fail())1821 return LLDB_INVALID_IMAGE_TOKEN;1822 }1823 return DoLoadImage(process, target_file, nullptr, error);1824 }1825 1826 if (remote_file) {1827 // Only remote file was specified so we don't have to do any copying1828 return DoLoadImage(process, remote_file, nullptr, error);1829 }1830 1831 error =1832 Status::FromErrorString("Neither local nor remote file was specified");1833 return LLDB_INVALID_IMAGE_TOKEN;1834}1835 1836uint32_t Platform::DoLoadImage(lldb_private::Process *process,1837 const lldb_private::FileSpec &remote_file,1838 const std::vector<std::string> *paths,1839 lldb_private::Status &error,1840 lldb_private::FileSpec *loaded_image) {1841 error = Status::FromErrorString(1842 "LoadImage is not supported on the current platform");1843 return LLDB_INVALID_IMAGE_TOKEN;1844}1845 1846uint32_t Platform::LoadImageUsingPaths(lldb_private::Process *process,1847 const lldb_private::FileSpec &remote_filename,1848 const std::vector<std::string> &paths,1849 lldb_private::Status &error,1850 lldb_private::FileSpec *loaded_path)1851{1852 FileSpec file_to_use;1853 if (remote_filename.IsAbsolute())1854 file_to_use = FileSpec(remote_filename.GetFilename().GetStringRef(),1855 1856 remote_filename.GetPathStyle());1857 else1858 file_to_use = remote_filename;1859 1860 return DoLoadImage(process, file_to_use, &paths, error, loaded_path);1861}1862 1863Status Platform::UnloadImage(lldb_private::Process *process,1864 uint32_t image_token) {1865 return Status::FromErrorString(1866 "UnloadImage is not supported on the current platform");1867}1868 1869lldb::ProcessSP Platform::ConnectProcess(llvm::StringRef connect_url,1870 llvm::StringRef plugin_name,1871 Debugger &debugger, Target *target,1872 Status &error) {1873 return DoConnectProcess(connect_url, plugin_name, debugger, nullptr, target,1874 error);1875}1876 1877lldb::ProcessSP Platform::ConnectProcessSynchronous(1878 llvm::StringRef connect_url, llvm::StringRef plugin_name,1879 Debugger &debugger, Stream &stream, Target *target, Status &error) {1880 return DoConnectProcess(connect_url, plugin_name, debugger, &stream, target,1881 error);1882}1883 1884lldb::ProcessSP Platform::DoConnectProcess(llvm::StringRef connect_url,1885 llvm::StringRef plugin_name,1886 Debugger &debugger, Stream *stream,1887 Target *target, Status &error) {1888 error.Clear();1889 1890 if (!target) {1891 ArchSpec arch = Target::GetDefaultArchitecture();1892 1893 const char *triple =1894 arch.IsValid() ? arch.GetTriple().getTriple().c_str() : "";1895 1896 TargetSP new_target_sp;1897 error = debugger.GetTargetList().CreateTarget(1898 debugger, "", triple, eLoadDependentsNo, nullptr, new_target_sp);1899 1900 target = new_target_sp.get();1901 if (!target || error.Fail()) {1902 return nullptr;1903 }1904 }1905 1906 lldb::ProcessSP process_sp =1907 target->CreateProcess(debugger.GetListener(), plugin_name, nullptr, true);1908 1909 if (!process_sp)1910 return nullptr;1911 1912 // If this private method is called with a stream we are synchronous.1913 const bool synchronous = stream != nullptr;1914 1915 ListenerSP listener_sp(1916 Listener::MakeListener("lldb.Process.ConnectProcess.hijack"));1917 if (synchronous)1918 process_sp->HijackProcessEvents(listener_sp);1919 1920 error = process_sp->ConnectRemote(connect_url);1921 if (error.Fail()) {1922 if (synchronous)1923 process_sp->RestoreProcessEvents();1924 return nullptr;1925 }1926 1927 if (synchronous) {1928 EventSP event_sp;1929 process_sp->WaitForProcessToStop(std::nullopt, &event_sp, true, listener_sp,1930 nullptr);1931 process_sp->RestoreProcessEvents();1932 bool pop_process_io_handler = false;1933 // This is a user-level stop, so we allow recognizers to select frames.1934 Process::HandleProcessStateChangedEvent(1935 event_sp, stream, SelectMostRelevantFrame, pop_process_io_handler);1936 }1937 1938 return process_sp;1939}1940 1941size_t Platform::ConnectToWaitingProcesses(lldb_private::Debugger &debugger,1942 lldb_private::Status &error) {1943 error.Clear();1944 return 0;1945}1946 1947size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,1948 BreakpointSite *bp_site) {1949 ArchSpec arch = target.GetArchitecture();1950 assert(arch.IsValid());1951 const uint8_t *trap_opcode = nullptr;1952 size_t trap_opcode_size = 0;1953 1954 switch (arch.GetMachine()) {1955 case llvm::Triple::aarch64_32:1956 case llvm::Triple::aarch64: {1957 static const uint8_t g_aarch64_opcode[] = {0x00, 0x00, 0x20, 0xd4};1958 trap_opcode = g_aarch64_opcode;1959 trap_opcode_size = sizeof(g_aarch64_opcode);1960 } break;1961 1962 case llvm::Triple::arc: {1963 static const uint8_t g_hex_opcode[] = { 0xff, 0x7f };1964 trap_opcode = g_hex_opcode;1965 trap_opcode_size = sizeof(g_hex_opcode);1966 } break;1967 1968 // TODO: support big-endian arm and thumb trap codes.1969 case llvm::Triple::arm: {1970 // The ARM reference recommends the use of 0xe7fddefe and 0xdefe but the1971 // linux kernel does otherwise.1972 static const uint8_t g_arm_breakpoint_opcode[] = {0xf0, 0x01, 0xf0, 0xe7};1973 static const uint8_t g_thumb_breakpoint_opcode[] = {0x01, 0xde};1974 1975 lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetConstituentAtIndex(0));1976 AddressClass addr_class = AddressClass::eUnknown;1977 1978 if (bp_loc_sp) {1979 addr_class = bp_loc_sp->GetAddress().GetAddressClass();1980 if (addr_class == AddressClass::eUnknown &&1981 (bp_loc_sp->GetAddress().GetFileAddress() & 1))1982 addr_class = AddressClass::eCodeAlternateISA;1983 }1984 1985 if (addr_class == AddressClass::eCodeAlternateISA) {1986 trap_opcode = g_thumb_breakpoint_opcode;1987 trap_opcode_size = sizeof(g_thumb_breakpoint_opcode);1988 } else {1989 trap_opcode = g_arm_breakpoint_opcode;1990 trap_opcode_size = sizeof(g_arm_breakpoint_opcode);1991 }1992 } break;1993 1994 case llvm::Triple::avr: {1995 static const uint8_t g_hex_opcode[] = {0x98, 0x95};1996 trap_opcode = g_hex_opcode;1997 trap_opcode_size = sizeof(g_hex_opcode);1998 } break;1999 2000 case llvm::Triple::mips:2001 case llvm::Triple::mips64: {2002 static const uint8_t g_hex_opcode[] = {0x00, 0x00, 0x00, 0x0d};2003 trap_opcode = g_hex_opcode;2004 trap_opcode_size = sizeof(g_hex_opcode);2005 } break;2006 2007 case llvm::Triple::mipsel:2008 case llvm::Triple::mips64el: {2009 static const uint8_t g_hex_opcode[] = {0x0d, 0x00, 0x00, 0x00};2010 trap_opcode = g_hex_opcode;2011 trap_opcode_size = sizeof(g_hex_opcode);2012 } break;2013 2014 case llvm::Triple::msp430: {2015 static const uint8_t g_msp430_opcode[] = {0x43, 0x43};2016 trap_opcode = g_msp430_opcode;2017 trap_opcode_size = sizeof(g_msp430_opcode);2018 } break;2019 2020 case llvm::Triple::systemz: {2021 static const uint8_t g_hex_opcode[] = {0x00, 0x01};2022 trap_opcode = g_hex_opcode;2023 trap_opcode_size = sizeof(g_hex_opcode);2024 } break;2025 2026 case llvm::Triple::hexagon: {2027 static const uint8_t g_hex_opcode[] = {0x0c, 0xdb, 0x00, 0x54};2028 trap_opcode = g_hex_opcode;2029 trap_opcode_size = sizeof(g_hex_opcode);2030 } break;2031 2032 case llvm::Triple::ppc:2033 case llvm::Triple::ppc64: {2034 static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08};2035 trap_opcode = g_ppc_opcode;2036 trap_opcode_size = sizeof(g_ppc_opcode);2037 } break;2038 2039 case llvm::Triple::ppc64le: {2040 static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap2041 trap_opcode = g_ppc64le_opcode;2042 trap_opcode_size = sizeof(g_ppc64le_opcode);2043 } break;2044 2045 case llvm::Triple::x86:2046 case llvm::Triple::x86_64: {2047 static const uint8_t g_i386_opcode[] = {0xCC};2048 trap_opcode = g_i386_opcode;2049 trap_opcode_size = sizeof(g_i386_opcode);2050 } break;2051 2052 case llvm::Triple::riscv32:2053 case llvm::Triple::riscv64: {2054 static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak2055 static const uint8_t g_riscv_opcode_c[] = {0x02, 0x90}; // c.ebreak2056 if (arch.GetFlags() & ArchSpec::eRISCV_rvc) {2057 trap_opcode = g_riscv_opcode_c;2058 trap_opcode_size = sizeof(g_riscv_opcode_c);2059 } else {2060 trap_opcode = g_riscv_opcode;2061 trap_opcode_size = sizeof(g_riscv_opcode);2062 }2063 } break;2064 2065 case llvm::Triple::loongarch32:2066 case llvm::Triple::loongarch64: {2067 static const uint8_t g_loongarch_opcode[] = {0x05, 0x00, 0x2a,2068 0x00}; // break 0x52069 trap_opcode = g_loongarch_opcode;2070 trap_opcode_size = sizeof(g_loongarch_opcode);2071 } break;2072 2073 case llvm::Triple::wasm32: {2074 // Unreachable (0x00) triggers an unconditional trap.2075 static const uint8_t g_wasm_opcode[] = {0x00};2076 trap_opcode = g_wasm_opcode;2077 trap_opcode_size = sizeof(g_wasm_opcode);2078 } break;2079 2080 default:2081 return 0;2082 }2083 2084 assert(bp_site);2085 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))2086 return trap_opcode_size;2087 2088 return 0;2089}2090 2091CompilerType Platform::GetSiginfoType(const llvm::Triple& triple) {2092 return CompilerType();2093}2094 2095Args Platform::GetExtraStartupCommands() {2096 return {};2097}2098 2099void Platform::SetLocateModuleCallback(LocateModuleCallback callback) {2100 m_locate_module_callback = callback;2101}2102 2103Platform::LocateModuleCallback Platform::GetLocateModuleCallback() const {2104 return m_locate_module_callback;2105}2106 2107PlatformSP PlatformList::GetOrCreate(llvm::StringRef name) {2108 std::lock_guard<std::recursive_mutex> guard(m_mutex);2109 for (const PlatformSP &platform_sp : m_platforms) {2110 if (platform_sp->GetName() == name)2111 return platform_sp;2112 }2113 return Create(name);2114}2115 2116PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,2117 const ArchSpec &process_host_arch,2118 ArchSpec *platform_arch_ptr,2119 Status &error) {2120 std::lock_guard<std::recursive_mutex> guard(m_mutex);2121 // First try exact arch matches across all platforms already created2122 for (const auto &platform_sp : m_platforms) {2123 if (platform_sp->IsCompatibleArchitecture(2124 arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr))2125 return platform_sp;2126 }2127 2128 // Next try compatible arch matches across all platforms already created2129 for (const auto &platform_sp : m_platforms) {2130 if (platform_sp->IsCompatibleArchitecture(arch, process_host_arch,2131 ArchSpec::CompatibleMatch,2132 platform_arch_ptr))2133 return platform_sp;2134 }2135 2136 PlatformCreateInstance create_callback;2137 // First try exact arch matches across all platform plug-ins2138 uint32_t idx;2139 for (idx = 0;2140 (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));2141 ++idx) {2142 PlatformSP platform_sp = create_callback(false, &arch);2143 if (platform_sp &&2144 platform_sp->IsCompatibleArchitecture(2145 arch, process_host_arch, ArchSpec::ExactMatch, platform_arch_ptr)) {2146 m_platforms.push_back(platform_sp);2147 return platform_sp;2148 }2149 }2150 // Next try compatible arch matches across all platform plug-ins2151 for (idx = 0;2152 (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));2153 ++idx) {2154 PlatformSP platform_sp = create_callback(false, &arch);2155 if (platform_sp && platform_sp->IsCompatibleArchitecture(2156 arch, process_host_arch, ArchSpec::CompatibleMatch,2157 platform_arch_ptr)) {2158 m_platforms.push_back(platform_sp);2159 return platform_sp;2160 }2161 }2162 if (platform_arch_ptr)2163 platform_arch_ptr->Clear();2164 return nullptr;2165}2166 2167PlatformSP PlatformList::GetOrCreate(const ArchSpec &arch,2168 const ArchSpec &process_host_arch,2169 ArchSpec *platform_arch_ptr) {2170 Status error;2171 if (arch.IsValid())2172 return GetOrCreate(arch, process_host_arch, platform_arch_ptr, error);2173 return nullptr;2174}2175 2176PlatformSP PlatformList::GetOrCreate(llvm::ArrayRef<ArchSpec> archs,2177 const ArchSpec &process_host_arch,2178 std::vector<PlatformSP> &candidates) {2179 candidates.clear();2180 candidates.reserve(archs.size());2181 2182 if (archs.empty())2183 return nullptr;2184 2185 PlatformSP host_platform_sp = Platform::GetHostPlatform();2186 2187 // Prefer the selected platform if it matches at least one architecture.2188 if (m_selected_platform_sp) {2189 for (const ArchSpec &arch : archs) {2190 if (m_selected_platform_sp->IsCompatibleArchitecture(2191 arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr))2192 return m_selected_platform_sp;2193 }2194 }2195 2196 // Prefer the host platform if it matches at least one architecture.2197 if (host_platform_sp) {2198 for (const ArchSpec &arch : archs) {2199 if (host_platform_sp->IsCompatibleArchitecture(2200 arch, process_host_arch, ArchSpec::CompatibleMatch, nullptr))2201 return host_platform_sp;2202 }2203 }2204 2205 // Collect a list of candidate platforms for the architectures.2206 for (const ArchSpec &arch : archs) {2207 if (PlatformSP platform = GetOrCreate(arch, process_host_arch, nullptr))2208 candidates.push_back(platform);2209 }2210 2211 // The selected or host platform didn't match any of the architectures. If2212 // the same platform supports all architectures then that's the obvious next2213 // best thing.2214 if (candidates.size() == archs.size()) {2215 if (llvm::all_of(candidates, [&](const PlatformSP &p) -> bool {2216 return p->GetName() == candidates.front()->GetName();2217 })) {2218 return candidates.front();2219 }2220 }2221 2222 // At this point we either have no platforms that match the given2223 // architectures or multiple platforms with no good way to disambiguate2224 // between them.2225 return nullptr;2226}2227 2228PlatformSP PlatformList::Create(llvm::StringRef name) {2229 std::lock_guard<std::recursive_mutex> guard(m_mutex);2230 PlatformSP platform_sp = Platform::Create(name);2231 if (platform_sp)2232 m_platforms.push_back(platform_sp);2233 return platform_sp;2234}2235 2236bool PlatformList::LoadPlatformBinaryAndSetup(Process *process,2237 lldb::addr_t addr, bool notify) {2238 std::lock_guard<std::recursive_mutex> guard(m_mutex);2239 2240 PlatformCreateInstance create_callback;2241 for (int idx = 0;2242 (create_callback = PluginManager::GetPlatformCreateCallbackAtIndex(idx));2243 ++idx) {2244 ArchSpec arch;2245 PlatformSP platform_sp = create_callback(true, &arch);2246 if (platform_sp) {2247 if (platform_sp->LoadPlatformBinaryAndSetup(process, addr, notify))2248 return true;2249 }2250 }2251 return false;2252}2253