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