]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Target/TargetList.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Target / TargetList.cpp
1 //===-- TargetList.cpp ------------------------------------------*- C++ -*-===//
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 "lldb/Target/TargetList.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/ModuleSpec.h"
13 #include "lldb/Host/Host.h"
14 #include "lldb/Host/HostInfo.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/OptionGroupPlatform.h"
17 #include "lldb/Symbol/ObjectFile.h"
18 #include "lldb/Target/Platform.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Utility/Broadcaster.h"
21 #include "lldb/Utility/Event.h"
22 #include "lldb/Utility/State.h"
23 #include "lldb/Utility/TildeExpressionResolver.h"
24 #include "lldb/Utility/Timer.h"
25
26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/Support/FileSystem.h"
28
29 using namespace lldb;
30 using namespace lldb_private;
31
32 ConstString &TargetList::GetStaticBroadcasterClass() {
33   static ConstString class_name("lldb.targetList");
34   return class_name;
35 }
36
37 // TargetList constructor
38 TargetList::TargetList(Debugger &debugger)
39     : Broadcaster(debugger.GetBroadcasterManager(),
40                   TargetList::GetStaticBroadcasterClass().AsCString()),
41       m_target_list(), m_target_list_mutex(), m_selected_target_idx(0) {
42   CheckInWithManager();
43 }
44
45 // Destructor
46 TargetList::~TargetList() {
47   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
48   m_target_list.clear();
49 }
50
51 Status TargetList::CreateTarget(Debugger &debugger,
52                                 llvm::StringRef user_exe_path,
53                                 llvm::StringRef triple_str,
54                                 LoadDependentFiles load_dependent_files,
55                                 const OptionGroupPlatform *platform_options,
56                                 TargetSP &target_sp) {
57   return CreateTargetInternal(debugger, user_exe_path, triple_str,
58                               load_dependent_files, platform_options, target_sp,
59                               false);
60 }
61
62 Status TargetList::CreateTarget(Debugger &debugger,
63                                 llvm::StringRef user_exe_path,
64                                 const ArchSpec &specified_arch,
65                                 LoadDependentFiles load_dependent_files,
66                                 PlatformSP &platform_sp, TargetSP &target_sp) {
67   return CreateTargetInternal(debugger, user_exe_path, specified_arch,
68                               load_dependent_files, platform_sp, target_sp,
69                               false);
70 }
71
72 Status TargetList::CreateTargetInternal(
73     Debugger &debugger, llvm::StringRef user_exe_path,
74     llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
75     const OptionGroupPlatform *platform_options, TargetSP &target_sp,
76     bool is_dummy_target) {
77   Status error;
78   PlatformSP platform_sp;
79
80   // This is purposely left empty unless it is specified by triple_cstr. If not
81   // initialized via triple_cstr, then the currently selected platform will set
82   // the architecture correctly.
83   const ArchSpec arch(triple_str);
84   if (!triple_str.empty()) {
85     if (!arch.IsValid()) {
86       error.SetErrorStringWithFormat("invalid triple '%s'",
87                                      triple_str.str().c_str());
88       return error;
89     }
90   }
91
92   ArchSpec platform_arch(arch);
93
94   bool prefer_platform_arch = false;
95
96   CommandInterpreter &interpreter = debugger.GetCommandInterpreter();
97
98   // let's see if there is already an existing platform before we go creating
99   // another...
100   platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
101
102   if (platform_options && platform_options->PlatformWasSpecified()) {
103     // Create a new platform if it doesn't match the selected platform
104     if (!platform_options->PlatformMatches(platform_sp)) {
105       const bool select_platform = true;
106       platform_sp = platform_options->CreatePlatformWithOptions(
107           interpreter, arch, select_platform, error, platform_arch);
108       if (!platform_sp)
109         return error;
110     }
111   }
112
113   if (!user_exe_path.empty()) {
114     ModuleSpecList module_specs;
115     ModuleSpec module_spec;
116     module_spec.GetFileSpec().SetFile(user_exe_path, FileSpec::Style::native);
117     FileSystem::Instance().Resolve(module_spec.GetFileSpec());
118
119     // Resolve the executable in case we are given a path to a application
120     // bundle like a .app bundle on MacOSX
121     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
122
123     lldb::offset_t file_offset = 0;
124     lldb::offset_t file_size = 0;
125     const size_t num_specs = ObjectFile::GetModuleSpecifications(
126         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
127     if (num_specs > 0) {
128       ModuleSpec matching_module_spec;
129
130       if (num_specs == 1) {
131         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
132           if (platform_arch.IsValid()) {
133             if (platform_arch.IsCompatibleMatch(
134                     matching_module_spec.GetArchitecture())) {
135               // If the OS or vendor weren't specified, then adopt the module's
136               // architecture so that the platform matching can be more
137               // accurate
138               if (!platform_arch.TripleOSWasSpecified() ||
139                   !platform_arch.TripleVendorWasSpecified()) {
140                 prefer_platform_arch = true;
141                 platform_arch = matching_module_spec.GetArchitecture();
142               }
143             } else {
144               StreamString platform_arch_strm;
145               StreamString module_arch_strm;
146
147               platform_arch.DumpTriple(platform_arch_strm.AsRawOstream());
148               matching_module_spec.GetArchitecture().DumpTriple(
149                   module_arch_strm.AsRawOstream());
150               error.SetErrorStringWithFormat(
151                   "the specified architecture '%s' is not compatible with '%s' "
152                   "in '%s'",
153                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
154                   module_spec.GetFileSpec().GetPath().c_str());
155               return error;
156             }
157           } else {
158             // Only one arch and none was specified
159             prefer_platform_arch = true;
160             platform_arch = matching_module_spec.GetArchitecture();
161           }
162         }
163       } else {
164         if (arch.IsValid()) {
165           module_spec.GetArchitecture() = arch;
166           if (module_specs.FindMatchingModuleSpec(module_spec,
167                                                   matching_module_spec)) {
168             prefer_platform_arch = true;
169             platform_arch = matching_module_spec.GetArchitecture();
170           }
171         } else {
172           // No architecture specified, check if there is only one platform for
173           // all of the architectures.
174
175           typedef std::vector<PlatformSP> PlatformList;
176           PlatformList platforms;
177           PlatformSP host_platform_sp = Platform::GetHostPlatform();
178           for (size_t i = 0; i < num_specs; ++i) {
179             ModuleSpec module_spec;
180             if (module_specs.GetModuleSpecAtIndex(i, module_spec)) {
181               // See if there was a selected platform and check that first
182               // since the user may have specified it.
183               if (platform_sp) {
184                 if (platform_sp->IsCompatibleArchitecture(
185                         module_spec.GetArchitecture(), false, nullptr)) {
186                   platforms.push_back(platform_sp);
187                   continue;
188                 }
189               }
190
191               // Next check the host platform it if wasn't already checked
192               // above
193               if (host_platform_sp &&
194                   (!platform_sp ||
195                    host_platform_sp->GetName() != platform_sp->GetName())) {
196                 if (host_platform_sp->IsCompatibleArchitecture(
197                         module_spec.GetArchitecture(), false, nullptr)) {
198                   platforms.push_back(host_platform_sp);
199                   continue;
200                 }
201               }
202
203               // Just find a platform that matches the architecture in the
204               // executable file
205               PlatformSP fallback_platform_sp(
206                   Platform::GetPlatformForArchitecture(
207                       module_spec.GetArchitecture(), nullptr));
208               if (fallback_platform_sp) {
209                 platforms.push_back(fallback_platform_sp);
210               }
211             }
212           }
213
214           Platform *platform_ptr = nullptr;
215           bool more_than_one_platforms = false;
216           for (const auto &the_platform_sp : platforms) {
217             if (platform_ptr) {
218               if (platform_ptr->GetName() != the_platform_sp->GetName()) {
219                 more_than_one_platforms = true;
220                 platform_ptr = nullptr;
221                 break;
222               }
223             } else {
224               platform_ptr = the_platform_sp.get();
225             }
226           }
227
228           if (platform_ptr) {
229             // All platforms for all modules in the executable match, so we can
230             // select this platform
231             platform_sp = platforms.front();
232           } else if (!more_than_one_platforms) {
233             // No platforms claim to support this file
234             error.SetErrorString("No matching platforms found for this file, "
235                                  "specify one with the --platform option");
236             return error;
237           } else {
238             // More than one platform claims to support this file, so the
239             // --platform option must be specified
240             StreamString error_strm;
241             std::set<Platform *> platform_set;
242             error_strm.Printf(
243                 "more than one platform supports this executable (");
244             for (const auto &the_platform_sp : platforms) {
245               if (platform_set.find(the_platform_sp.get()) ==
246                   platform_set.end()) {
247                 if (!platform_set.empty())
248                   error_strm.PutCString(", ");
249                 error_strm.PutCString(the_platform_sp->GetName().GetCString());
250                 platform_set.insert(the_platform_sp.get());
251               }
252             }
253             error_strm.Printf(
254                 "), use the --platform option to specify a platform");
255             error.SetErrorString(error_strm.GetString());
256             return error;
257           }
258         }
259       }
260     }
261   }
262
263   // If we have a valid architecture, make sure the current platform is
264   // compatible with that architecture
265   if (!prefer_platform_arch && arch.IsValid()) {
266     if (!platform_sp->IsCompatibleArchitecture(arch, false, &platform_arch)) {
267       platform_sp = Platform::GetPlatformForArchitecture(arch, &platform_arch);
268       if (!is_dummy_target && platform_sp)
269         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
270     }
271   } else if (platform_arch.IsValid()) {
272     // if "arch" isn't valid, yet "platform_arch" is, it means we have an
273     // executable file with a single architecture which should be used
274     ArchSpec fixed_platform_arch;
275     if (!platform_sp->IsCompatibleArchitecture(platform_arch, false,
276                                                &fixed_platform_arch)) {
277       platform_sp = Platform::GetPlatformForArchitecture(platform_arch,
278                                                          &fixed_platform_arch);
279       if (!is_dummy_target && platform_sp)
280         debugger.GetPlatformList().SetSelectedPlatform(platform_sp);
281     }
282   }
283
284   if (!platform_arch.IsValid())
285     platform_arch = arch;
286
287   error = TargetList::CreateTargetInternal(
288       debugger, user_exe_path, platform_arch, load_dependent_files, platform_sp,
289       target_sp, is_dummy_target);
290   return error;
291 }
292
293 lldb::TargetSP TargetList::GetDummyTarget(lldb_private::Debugger &debugger) {
294   // FIXME: Maybe the dummy target should be per-Debugger
295   if (!m_dummy_target_sp || !m_dummy_target_sp->IsValid()) {
296     ArchSpec arch(Target::GetDefaultArchitecture());
297     if (!arch.IsValid())
298       arch = HostInfo::GetArchitecture();
299     Status err = CreateDummyTarget(
300         debugger, arch.GetTriple().getTriple().c_str(), m_dummy_target_sp);
301   }
302
303   return m_dummy_target_sp;
304 }
305
306 Status TargetList::CreateDummyTarget(Debugger &debugger,
307                                      llvm::StringRef specified_arch_name,
308                                      lldb::TargetSP &target_sp) {
309   PlatformSP host_platform_sp(Platform::GetHostPlatform());
310   return CreateTargetInternal(
311       debugger, (const char *)nullptr, specified_arch_name, eLoadDependentsNo,
312       (const OptionGroupPlatform *)nullptr, target_sp, true);
313 }
314
315 Status TargetList::CreateTargetInternal(Debugger &debugger,
316                                         llvm::StringRef user_exe_path,
317                                         const ArchSpec &specified_arch,
318                                         LoadDependentFiles load_dependent_files,
319                                         lldb::PlatformSP &platform_sp,
320                                         lldb::TargetSP &target_sp,
321                                         bool is_dummy_target) {
322   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
323   Timer scoped_timer(
324       func_cat, "TargetList::CreateTarget (file = '%s', arch = '%s')",
325       user_exe_path.str().c_str(), specified_arch.GetArchitectureName());
326   Status error;
327
328   ArchSpec arch(specified_arch);
329
330   if (arch.IsValid()) {
331     if (!platform_sp ||
332         !platform_sp->IsCompatibleArchitecture(arch, false, nullptr))
333       platform_sp = Platform::GetPlatformForArchitecture(specified_arch, &arch);
334   }
335
336   if (!platform_sp)
337     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
338
339   if (!arch.IsValid())
340     arch = specified_arch;
341
342   FileSpec file(user_exe_path);
343   if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) {
344     // we want to expand the tilde but we don't want to resolve any symbolic
345     // links so we can't use the FileSpec constructor's resolve flag
346     llvm::SmallString<64> unglobbed_path;
347     StandardTildeExpressionResolver Resolver;
348     Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
349
350     if (unglobbed_path.empty())
351       file = FileSpec(user_exe_path);
352     else
353       file = FileSpec(unglobbed_path.c_str());
354   }
355
356   bool user_exe_path_is_bundle = false;
357   char resolved_bundle_exe_path[PATH_MAX];
358   resolved_bundle_exe_path[0] = '\0';
359   if (file) {
360     if (FileSystem::Instance().IsDirectory(file))
361       user_exe_path_is_bundle = true;
362
363     if (file.IsRelative() && !user_exe_path.empty()) {
364       llvm::SmallString<64> cwd;
365       if (! llvm::sys::fs::current_path(cwd)) {
366         FileSpec cwd_file(cwd.c_str());
367         cwd_file.AppendPathComponent(file);
368         if (FileSystem::Instance().Exists(cwd_file))
369           file = cwd_file;
370       }
371     }
372
373     ModuleSP exe_module_sp;
374     if (platform_sp) {
375       FileSpecList executable_search_paths(
376           Target::GetDefaultExecutableSearchPaths());
377       ModuleSpec module_spec(file, arch);
378       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
379                                              executable_search_paths.GetSize()
380                                                  ? &executable_search_paths
381                                                  : nullptr);
382     }
383
384     if (error.Success() && exe_module_sp) {
385       if (exe_module_sp->GetObjectFile() == nullptr) {
386         if (arch.IsValid()) {
387           error.SetErrorStringWithFormat(
388               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
389               arch.GetArchitectureName());
390         } else {
391           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
392                                          file.GetPath().c_str());
393         }
394         return error;
395       }
396       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
397       target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
398       if (user_exe_path_is_bundle)
399         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
400                                              sizeof(resolved_bundle_exe_path));
401     }
402   } else {
403     // No file was specified, just create an empty target with any arch if a
404     // valid arch was specified
405     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
406   }
407
408   if (target_sp) {
409     // Set argv0 with what the user typed, unless the user specified a
410     // directory. If the user specified a directory, then it is probably a
411     // bundle that was resolved and we need to use the resolved bundle path
412     if (!user_exe_path.empty()) {
413       // Use exactly what the user typed as the first argument when we exec or
414       // posix_spawn
415       if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
416         target_sp->SetArg0(resolved_bundle_exe_path);
417       } else {
418         // Use resolved path
419         target_sp->SetArg0(file.GetPath().c_str());
420       }
421     }
422     if (file.GetDirectory()) {
423       FileSpec file_dir;
424       file_dir.GetDirectory() = file.GetDirectory();
425       target_sp->AppendExecutableSearchPaths(file_dir);
426     }
427
428     // Don't put the dummy target in the target list, it's held separately.
429     if (!is_dummy_target) {
430       std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
431       m_selected_target_idx = m_target_list.size();
432       m_target_list.push_back(target_sp);
433       // Now prime this from the dummy target:
434       target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
435     } else {
436       m_dummy_target_sp = target_sp;
437     }
438   }
439
440   return error;
441 }
442
443 bool TargetList::DeleteTarget(TargetSP &target_sp) {
444   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
445   collection::iterator pos, end = m_target_list.end();
446
447   for (pos = m_target_list.begin(); pos != end; ++pos) {
448     if (pos->get() == target_sp.get()) {
449       m_target_list.erase(pos);
450       return true;
451     }
452   }
453   return false;
454 }
455
456 TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
457     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
458   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
459   TargetSP target_sp;
460   collection::const_iterator pos, end = m_target_list.end();
461   for (pos = m_target_list.begin(); pos != end; ++pos) {
462     Module *exe_module = (*pos)->GetExecutableModulePointer();
463
464     if (exe_module) {
465       if (FileSpec::Match(exe_file_spec, exe_module->GetFileSpec())) {
466         if (exe_arch_ptr) {
467           if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
468             continue;
469         }
470         target_sp = *pos;
471         break;
472       }
473     }
474   }
475   return target_sp;
476 }
477
478 TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
479   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
480   TargetSP target_sp;
481   collection::const_iterator pos, end = m_target_list.end();
482   for (pos = m_target_list.begin(); pos != end; ++pos) {
483     Process *process = (*pos)->GetProcessSP().get();
484     if (process && process->GetID() == pid) {
485       target_sp = *pos;
486       break;
487     }
488   }
489   return target_sp;
490 }
491
492 TargetSP TargetList::FindTargetWithProcess(Process *process) const {
493   TargetSP target_sp;
494   if (process) {
495     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
496     collection::const_iterator pos, end = m_target_list.end();
497     for (pos = m_target_list.begin(); pos != end; ++pos) {
498       if (process == (*pos)->GetProcessSP().get()) {
499         target_sp = *pos;
500         break;
501       }
502     }
503   }
504   return target_sp;
505 }
506
507 TargetSP TargetList::GetTargetSP(Target *target) const {
508   TargetSP target_sp;
509   if (target) {
510     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
511     collection::const_iterator pos, end = m_target_list.end();
512     for (pos = m_target_list.begin(); pos != end; ++pos) {
513       if (target == (*pos).get()) {
514         target_sp = *pos;
515         break;
516       }
517     }
518   }
519   return target_sp;
520 }
521
522 uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
523   uint32_t num_async_interrupts_sent = 0;
524
525   if (pid != LLDB_INVALID_PROCESS_ID) {
526     TargetSP target_sp(FindTargetWithProcessID(pid));
527     if (target_sp) {
528       Process *process = target_sp->GetProcessSP().get();
529       if (process) {
530         process->SendAsyncInterrupt();
531         ++num_async_interrupts_sent;
532       }
533     }
534   } else {
535     // We don't have a valid pid to broadcast to, so broadcast to the target
536     // list's async broadcaster...
537     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
538   }
539
540   return num_async_interrupts_sent;
541 }
542
543 uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
544   uint32_t num_signals_sent = 0;
545   Process *process = nullptr;
546   if (pid == LLDB_INVALID_PROCESS_ID) {
547     // Signal all processes with signal
548     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
549     collection::iterator pos, end = m_target_list.end();
550     for (pos = m_target_list.begin(); pos != end; ++pos) {
551       process = (*pos)->GetProcessSP().get();
552       if (process) {
553         if (process->IsAlive()) {
554           ++num_signals_sent;
555           process->Signal(signo);
556         }
557       }
558     }
559   } else {
560     // Signal a specific process with signal
561     TargetSP target_sp(FindTargetWithProcessID(pid));
562     if (target_sp) {
563       process = target_sp->GetProcessSP().get();
564       if (process) {
565         if (process->IsAlive()) {
566           ++num_signals_sent;
567           process->Signal(signo);
568         }
569       }
570     }
571   }
572   return num_signals_sent;
573 }
574
575 int TargetList::GetNumTargets() const {
576   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
577   return m_target_list.size();
578 }
579
580 lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
581   TargetSP target_sp;
582   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
583   if (idx < m_target_list.size())
584     target_sp = m_target_list[idx];
585   return target_sp;
586 }
587
588 uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
589   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
590   size_t num_targets = m_target_list.size();
591   for (size_t idx = 0; idx < num_targets; idx++) {
592     if (target_sp == m_target_list[idx])
593       return idx;
594   }
595   return UINT32_MAX;
596 }
597
598 uint32_t TargetList::SetSelectedTarget(Target *target) {
599   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
600   collection::const_iterator pos, begin = m_target_list.begin(),
601                                   end = m_target_list.end();
602   for (pos = begin; pos != end; ++pos) {
603     if (pos->get() == target) {
604       m_selected_target_idx = std::distance(begin, pos);
605       return m_selected_target_idx;
606     }
607   }
608   m_selected_target_idx = 0;
609   return m_selected_target_idx;
610 }
611
612 lldb::TargetSP TargetList::GetSelectedTarget() {
613   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
614   if (m_selected_target_idx >= m_target_list.size())
615     m_selected_target_idx = 0;
616   return GetTargetAtIndex(m_selected_target_idx);
617 }