xref: /freebsd-src/contrib/llvm-project/lldb/source/Target/TargetList.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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);
148               matching_module_spec.GetArchitecture().DumpTriple(
149                   module_arch_strm);
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   bool full_match = (bool)exe_file_spec.GetDirectory();
461 
462   collection::const_iterator pos, end = m_target_list.end();
463   for (pos = m_target_list.begin(); pos != end; ++pos) {
464     Module *exe_module = (*pos)->GetExecutableModulePointer();
465 
466     if (exe_module) {
467       if (FileSpec::Equal(exe_file_spec, exe_module->GetFileSpec(),
468                           full_match)) {
469         if (exe_arch_ptr) {
470           if (!exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture()))
471             continue;
472         }
473         target_sp = *pos;
474         break;
475       }
476     }
477   }
478   return target_sp;
479 }
480 
481 TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
482   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
483   TargetSP target_sp;
484   collection::const_iterator pos, end = m_target_list.end();
485   for (pos = m_target_list.begin(); pos != end; ++pos) {
486     Process *process = (*pos)->GetProcessSP().get();
487     if (process && process->GetID() == pid) {
488       target_sp = *pos;
489       break;
490     }
491   }
492   return target_sp;
493 }
494 
495 TargetSP TargetList::FindTargetWithProcess(Process *process) const {
496   TargetSP target_sp;
497   if (process) {
498     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
499     collection::const_iterator pos, end = m_target_list.end();
500     for (pos = m_target_list.begin(); pos != end; ++pos) {
501       if (process == (*pos)->GetProcessSP().get()) {
502         target_sp = *pos;
503         break;
504       }
505     }
506   }
507   return target_sp;
508 }
509 
510 TargetSP TargetList::GetTargetSP(Target *target) const {
511   TargetSP target_sp;
512   if (target) {
513     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
514     collection::const_iterator pos, end = m_target_list.end();
515     for (pos = m_target_list.begin(); pos != end; ++pos) {
516       if (target == (*pos).get()) {
517         target_sp = *pos;
518         break;
519       }
520     }
521   }
522   return target_sp;
523 }
524 
525 uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
526   uint32_t num_async_interrupts_sent = 0;
527 
528   if (pid != LLDB_INVALID_PROCESS_ID) {
529     TargetSP target_sp(FindTargetWithProcessID(pid));
530     if (target_sp) {
531       Process *process = target_sp->GetProcessSP().get();
532       if (process) {
533         process->SendAsyncInterrupt();
534         ++num_async_interrupts_sent;
535       }
536     }
537   } else {
538     // We don't have a valid pid to broadcast to, so broadcast to the target
539     // list's async broadcaster...
540     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
541   }
542 
543   return num_async_interrupts_sent;
544 }
545 
546 uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
547   uint32_t num_signals_sent = 0;
548   Process *process = nullptr;
549   if (pid == LLDB_INVALID_PROCESS_ID) {
550     // Signal all processes with signal
551     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
552     collection::iterator pos, end = m_target_list.end();
553     for (pos = m_target_list.begin(); pos != end; ++pos) {
554       process = (*pos)->GetProcessSP().get();
555       if (process) {
556         if (process->IsAlive()) {
557           ++num_signals_sent;
558           process->Signal(signo);
559         }
560       }
561     }
562   } else {
563     // Signal a specific process with signal
564     TargetSP target_sp(FindTargetWithProcessID(pid));
565     if (target_sp) {
566       process = target_sp->GetProcessSP().get();
567       if (process) {
568         if (process->IsAlive()) {
569           ++num_signals_sent;
570           process->Signal(signo);
571         }
572       }
573     }
574   }
575   return num_signals_sent;
576 }
577 
578 int TargetList::GetNumTargets() const {
579   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
580   return m_target_list.size();
581 }
582 
583 lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
584   TargetSP target_sp;
585   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
586   if (idx < m_target_list.size())
587     target_sp = m_target_list[idx];
588   return target_sp;
589 }
590 
591 uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
592   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
593   size_t num_targets = m_target_list.size();
594   for (size_t idx = 0; idx < num_targets; idx++) {
595     if (target_sp == m_target_list[idx])
596       return idx;
597   }
598   return UINT32_MAX;
599 }
600 
601 uint32_t TargetList::SetSelectedTarget(Target *target) {
602   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
603   collection::const_iterator pos, begin = m_target_list.begin(),
604                                   end = m_target_list.end();
605   for (pos = begin; pos != end; ++pos) {
606     if (pos->get() == target) {
607       m_selected_target_idx = std::distance(begin, pos);
608       return m_selected_target_idx;
609     }
610   }
611   m_selected_target_idx = 0;
612   return m_selected_target_idx;
613 }
614 
615 lldb::TargetSP TargetList::GetSelectedTarget() {
616   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
617   if (m_selected_target_idx >= m_target_list.size())
618     m_selected_target_idx = 0;
619   return GetTargetAtIndex(m_selected_target_idx);
620 }
621