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