1 //===-- TargetList.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 "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 Status TargetList::CreateTarget(Debugger &debugger,
46                                 llvm::StringRef user_exe_path,
47                                 llvm::StringRef triple_str,
48                                 LoadDependentFiles load_dependent_files,
49                                 const OptionGroupPlatform *platform_options,
50                                 TargetSP &target_sp) {
51   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
52   auto result = TargetList::CreateTargetInternal(
53       debugger, user_exe_path, triple_str, load_dependent_files,
54       platform_options, target_sp);
55 
56   if (target_sp && result.Success())
57     AddTargetInternal(target_sp, /*do_select*/ true);
58   return result;
59 }
60 
61 Status TargetList::CreateTarget(Debugger &debugger,
62                                 llvm::StringRef user_exe_path,
63                                 const ArchSpec &specified_arch,
64                                 LoadDependentFiles load_dependent_files,
65                                 PlatformSP &platform_sp, TargetSP &target_sp) {
66   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
67   auto result = TargetList::CreateTargetInternal(
68       debugger, user_exe_path, specified_arch, load_dependent_files,
69       platform_sp, target_sp);
70 
71   if (target_sp && result.Success())
72     AddTargetInternal(target_sp, /*do_select*/ true);
73   return result;
74 }
75 
76 Status TargetList::CreateTargetInternal(
77     Debugger &debugger, llvm::StringRef user_exe_path,
78     llvm::StringRef triple_str, LoadDependentFiles load_dependent_files,
79     const OptionGroupPlatform *platform_options, TargetSP &target_sp) {
80   Status error;
81 
82   PlatformList &platform_list = debugger.GetPlatformList();
83   // Let's start by looking at the selected platform.
84   PlatformSP platform_sp = platform_list.GetSelectedPlatform();
85 
86   // This variable corresponds to the architecture specified by the triple
87   // string. If that string was empty the currently selected platform will
88   // determine the architecture.
89   const ArchSpec arch(triple_str);
90   if (!triple_str.empty() && !arch.IsValid()) {
91     error.SetErrorStringWithFormat("invalid triple '%s'",
92                                    triple_str.str().c_str());
93     return error;
94   }
95 
96   ArchSpec platform_arch(arch);
97 
98   // Create a new platform if a platform was specified in the platform options
99   // and doesn't match the selected platform.
100   if (platform_options && platform_options->PlatformWasSpecified() &&
101       !platform_options->PlatformMatches(platform_sp)) {
102     const bool select_platform = true;
103     platform_sp = platform_options->CreatePlatformWithOptions(
104         debugger.GetCommandInterpreter(), arch, select_platform, error,
105         platform_arch);
106     if (!platform_sp)
107       return error;
108   }
109 
110   bool prefer_platform_arch = false;
111   auto update_platform_arch = [&](const ArchSpec &module_arch) {
112     // If the OS or vendor weren't specified, then adopt the module's
113     // architecture so that the platform matching can be more accurate.
114     if (!platform_arch.TripleOSWasSpecified() ||
115         !platform_arch.TripleVendorWasSpecified()) {
116       prefer_platform_arch = true;
117       platform_arch = module_arch;
118     }
119   };
120 
121   if (!user_exe_path.empty()) {
122     ModuleSpec module_spec(FileSpec(user_exe_path, FileSpec::Style::native));
123     FileSystem::Instance().Resolve(module_spec.GetFileSpec());
124     // Resolve the executable in case we are given a path to a application
125     // bundle like a .app bundle on MacOSX.
126     Host::ResolveExecutableInBundle(module_spec.GetFileSpec());
127 
128     lldb::offset_t file_offset = 0;
129     lldb::offset_t file_size = 0;
130     ModuleSpecList module_specs;
131     const size_t num_specs = ObjectFile::GetModuleSpecifications(
132         module_spec.GetFileSpec(), file_offset, file_size, module_specs);
133 
134     if (num_specs > 0) {
135       ModuleSpec matching_module_spec;
136 
137       if (num_specs == 1) {
138         if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) {
139           if (platform_arch.IsValid()) {
140             if (platform_arch.IsCompatibleMatch(
141                     matching_module_spec.GetArchitecture())) {
142               // If the OS or vendor weren't specified, then adopt the module's
143               // architecture so that the platform matching can be more
144               // accurate.
145               update_platform_arch(matching_module_spec.GetArchitecture());
146             } else {
147               StreamString platform_arch_strm;
148               StreamString module_arch_strm;
149 
150               platform_arch.DumpTriple(platform_arch_strm.AsRawOstream());
151               matching_module_spec.GetArchitecture().DumpTriple(
152                   module_arch_strm.AsRawOstream());
153               error.SetErrorStringWithFormat(
154                   "the specified architecture '%s' is not compatible with '%s' "
155                   "in '%s'",
156                   platform_arch_strm.GetData(), module_arch_strm.GetData(),
157                   module_spec.GetFileSpec().GetPath().c_str());
158               return error;
159             }
160           } else {
161             // Only one arch and none was specified.
162             prefer_platform_arch = true;
163             platform_arch = matching_module_spec.GetArchitecture();
164           }
165         }
166       } else if (arch.IsValid()) {
167         // Fat binary. A (valid) architecture was specified.
168         module_spec.GetArchitecture() = arch;
169         if (module_specs.FindMatchingModuleSpec(module_spec,
170                                                 matching_module_spec))
171             update_platform_arch(matching_module_spec.GetArchitecture());
172       } else {
173         // Fat binary. No architecture specified, check if there is
174         // only one platform for all of the architectures.
175         std::vector<PlatformSP> candidates;
176         std::vector<ArchSpec> archs;
177         for (const ModuleSpec &spec : module_specs.ModuleSpecs())
178           archs.push_back(spec.GetArchitecture());
179         if (PlatformSP platform_for_archs_sp =
180                 platform_list.GetOrCreate(archs, {}, candidates)) {
181           platform_sp = platform_for_archs_sp;
182         } else if (candidates.empty()) {
183           error.SetErrorString("no matching platforms found for this file");
184           return error;
185         } else {
186           // More than one platform claims to support this file.
187           StreamString error_strm;
188           std::set<llvm::StringRef> platform_set;
189           error_strm.Printf(
190               "more than one platform supports this executable (");
191           for (const auto &candidate : candidates) {
192             llvm::StringRef platform_name = candidate->GetName();
193             if (platform_set.count(platform_name))
194               continue;
195             if (!platform_set.empty())
196               error_strm.PutCString(", ");
197             error_strm.PutCString(platform_name);
198             platform_set.insert(platform_name);
199           }
200           error_strm.Printf("), specify an architecture to disambiguate");
201           error.SetErrorString(error_strm.GetString());
202           return error;
203         }
204       }
205     }
206   }
207 
208   // If we have a valid architecture, make sure the current platform is
209   // compatible with that architecture.
210   if (!prefer_platform_arch && arch.IsValid()) {
211     if (!platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr)) {
212       platform_sp = platform_list.GetOrCreate(arch, {}, &platform_arch);
213       if (platform_sp)
214         platform_list.SetSelectedPlatform(platform_sp);
215     }
216   } else if (platform_arch.IsValid()) {
217     // If "arch" isn't valid, yet "platform_arch" is, it means we have an
218     // executable file with a single architecture which should be used.
219     ArchSpec fixed_platform_arch;
220     if (!platform_sp->IsCompatibleArchitecture(platform_arch, {}, false, nullptr)) {
221       platform_sp =
222           platform_list.GetOrCreate(platform_arch, {}, &fixed_platform_arch);
223       if (platform_sp)
224         platform_list.SetSelectedPlatform(platform_sp);
225     }
226   }
227 
228   if (!platform_arch.IsValid())
229     platform_arch = arch;
230 
231   return TargetList::CreateTargetInternal(debugger, user_exe_path,
232                                           platform_arch, load_dependent_files,
233                                           platform_sp, target_sp);
234 }
235 
236 Status TargetList::CreateTargetInternal(Debugger &debugger,
237                                         llvm::StringRef user_exe_path,
238                                         const ArchSpec &specified_arch,
239                                         LoadDependentFiles load_dependent_files,
240                                         lldb::PlatformSP &platform_sp,
241                                         lldb::TargetSP &target_sp) {
242   LLDB_SCOPED_TIMERF("TargetList::CreateTarget (file = '%s', arch = '%s')",
243                      user_exe_path.str().c_str(),
244                      specified_arch.GetArchitectureName());
245   Status error;
246   const bool is_dummy_target = false;
247 
248   ArchSpec arch(specified_arch);
249 
250   if (arch.IsValid()) {
251     if (!platform_sp ||
252         !platform_sp->IsCompatibleArchitecture(arch, {}, false, nullptr))
253       platform_sp =
254           debugger.GetPlatformList().GetOrCreate(specified_arch, {}, &arch);
255   }
256 
257   if (!platform_sp)
258     platform_sp = debugger.GetPlatformList().GetSelectedPlatform();
259 
260   if (!arch.IsValid())
261     arch = specified_arch;
262 
263   FileSpec file(user_exe_path);
264   if (!FileSystem::Instance().Exists(file) && user_exe_path.startswith("~")) {
265     // we want to expand the tilde but we don't want to resolve any symbolic
266     // links so we can't use the FileSpec constructor's resolve flag
267     llvm::SmallString<64> unglobbed_path;
268     StandardTildeExpressionResolver Resolver;
269     Resolver.ResolveFullPath(user_exe_path, unglobbed_path);
270 
271     if (unglobbed_path.empty())
272       file = FileSpec(user_exe_path);
273     else
274       file = FileSpec(unglobbed_path.c_str());
275   }
276 
277   bool user_exe_path_is_bundle = false;
278   char resolved_bundle_exe_path[PATH_MAX];
279   resolved_bundle_exe_path[0] = '\0';
280   if (file) {
281     if (FileSystem::Instance().IsDirectory(file))
282       user_exe_path_is_bundle = true;
283 
284     if (file.IsRelative() && !user_exe_path.empty()) {
285       llvm::SmallString<64> cwd;
286       if (! llvm::sys::fs::current_path(cwd)) {
287         FileSpec cwd_file(cwd.c_str());
288         cwd_file.AppendPathComponent(file);
289         if (FileSystem::Instance().Exists(cwd_file))
290           file = cwd_file;
291       }
292     }
293 
294     ModuleSP exe_module_sp;
295     if (platform_sp) {
296       FileSpecList executable_search_paths(
297           Target::GetDefaultExecutableSearchPaths());
298       ModuleSpec module_spec(file, arch);
299       error = platform_sp->ResolveExecutable(module_spec, exe_module_sp,
300                                              executable_search_paths.GetSize()
301                                                  ? &executable_search_paths
302                                                  : nullptr);
303     }
304 
305     if (error.Success() && exe_module_sp) {
306       if (exe_module_sp->GetObjectFile() == nullptr) {
307         if (arch.IsValid()) {
308           error.SetErrorStringWithFormat(
309               "\"%s\" doesn't contain architecture %s", file.GetPath().c_str(),
310               arch.GetArchitectureName());
311         } else {
312           error.SetErrorStringWithFormat("unsupported file type \"%s\"",
313                                          file.GetPath().c_str());
314         }
315         return error;
316       }
317       target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
318       target_sp->SetExecutableModule(exe_module_sp, load_dependent_files);
319       if (user_exe_path_is_bundle)
320         exe_module_sp->GetFileSpec().GetPath(resolved_bundle_exe_path,
321                                              sizeof(resolved_bundle_exe_path));
322       if (target_sp->GetPreloadSymbols())
323         exe_module_sp->PreloadSymbols();
324     }
325   } else {
326     // No file was specified, just create an empty target with any arch if a
327     // valid arch was specified
328     target_sp.reset(new Target(debugger, arch, platform_sp, is_dummy_target));
329   }
330 
331   if (!target_sp)
332     return error;
333 
334   // Set argv0 with what the user typed, unless the user specified a
335   // directory. If the user specified a directory, then it is probably a
336   // bundle that was resolved and we need to use the resolved bundle path
337   if (!user_exe_path.empty()) {
338     // Use exactly what the user typed as the first argument when we exec or
339     // posix_spawn
340     if (user_exe_path_is_bundle && resolved_bundle_exe_path[0]) {
341       target_sp->SetArg0(resolved_bundle_exe_path);
342     } else {
343       // Use resolved path
344       target_sp->SetArg0(file.GetPath().c_str());
345     }
346   }
347   if (file.GetDirectory()) {
348     FileSpec file_dir;
349     file_dir.GetDirectory() = file.GetDirectory();
350     target_sp->AppendExecutableSearchPaths(file_dir);
351   }
352 
353   // Now prime this from the dummy target:
354   target_sp->PrimeFromDummyTarget(debugger.GetDummyTarget());
355 
356   return error;
357 }
358 
359 bool TargetList::DeleteTarget(TargetSP &target_sp) {
360   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
361   auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
362   if (it == m_target_list.end())
363     return false;
364 
365   m_target_list.erase(it);
366   return true;
367 }
368 
369 TargetSP TargetList::FindTargetWithExecutableAndArchitecture(
370     const FileSpec &exe_file_spec, const ArchSpec *exe_arch_ptr) const {
371   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
372   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
373       [&exe_file_spec, exe_arch_ptr](const TargetSP &item) {
374         Module *exe_module = item->GetExecutableModulePointer();
375         if (!exe_module ||
376             !FileSpec::Match(exe_file_spec, exe_module->GetFileSpec()))
377           return false;
378 
379         return !exe_arch_ptr ||
380                exe_arch_ptr->IsCompatibleMatch(exe_module->GetArchitecture());
381       });
382 
383   if (it != m_target_list.end())
384     return *it;
385 
386   return TargetSP();
387 }
388 
389 TargetSP TargetList::FindTargetWithProcessID(lldb::pid_t pid) const {
390   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
391   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
392       [pid](const TargetSP &item) {
393         auto *process_ptr = item->GetProcessSP().get();
394         return process_ptr && (process_ptr->GetID() == pid);
395       });
396 
397   if (it != m_target_list.end())
398     return *it;
399 
400   return TargetSP();
401 }
402 
403 TargetSP TargetList::FindTargetWithProcess(Process *process) const {
404   TargetSP target_sp;
405   if (!process)
406     return target_sp;
407 
408   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
409   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
410       [process](const TargetSP &item) {
411         return item->GetProcessSP().get() == process;
412       });
413 
414   if (it != m_target_list.end())
415     target_sp = *it;
416 
417   return target_sp;
418 }
419 
420 TargetSP TargetList::GetTargetSP(Target *target) const {
421   TargetSP target_sp;
422   if (!target)
423     return target_sp;
424 
425   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
426   auto it = std::find_if(m_target_list.begin(), m_target_list.end(),
427       [target](const TargetSP &item) { return item.get() == target; });
428   if (it != m_target_list.end())
429     target_sp = *it;
430 
431   return target_sp;
432 }
433 
434 uint32_t TargetList::SendAsyncInterrupt(lldb::pid_t pid) {
435   uint32_t num_async_interrupts_sent = 0;
436 
437   if (pid != LLDB_INVALID_PROCESS_ID) {
438     TargetSP target_sp(FindTargetWithProcessID(pid));
439     if (target_sp) {
440       Process *process = target_sp->GetProcessSP().get();
441       if (process) {
442         process->SendAsyncInterrupt();
443         ++num_async_interrupts_sent;
444       }
445     }
446   } else {
447     // We don't have a valid pid to broadcast to, so broadcast to the target
448     // list's async broadcaster...
449     BroadcastEvent(Process::eBroadcastBitInterrupt, nullptr);
450   }
451 
452   return num_async_interrupts_sent;
453 }
454 
455 uint32_t TargetList::SignalIfRunning(lldb::pid_t pid, int signo) {
456   uint32_t num_signals_sent = 0;
457   Process *process = nullptr;
458   if (pid == LLDB_INVALID_PROCESS_ID) {
459     // Signal all processes with signal
460     std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
461     for (const auto &target_sp : m_target_list) {
462       process = target_sp->GetProcessSP().get();
463       if (process && process->IsAlive()) {
464         ++num_signals_sent;
465         process->Signal(signo);
466       }
467     }
468   } else {
469     // Signal a specific process with signal
470     TargetSP target_sp(FindTargetWithProcessID(pid));
471     if (target_sp) {
472       process = target_sp->GetProcessSP().get();
473       if (process && process->IsAlive()) {
474         ++num_signals_sent;
475         process->Signal(signo);
476       }
477     }
478   }
479   return num_signals_sent;
480 }
481 
482 int TargetList::GetNumTargets() const {
483   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
484   return m_target_list.size();
485 }
486 
487 lldb::TargetSP TargetList::GetTargetAtIndex(uint32_t idx) const {
488   TargetSP target_sp;
489   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
490   if (idx < m_target_list.size())
491     target_sp = m_target_list[idx];
492   return target_sp;
493 }
494 
495 uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const {
496   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
497   auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
498   if (it != m_target_list.end())
499     return std::distance(m_target_list.begin(), it);
500   return UINT32_MAX;
501 }
502 
503 void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) {
504   lldbassert(std::find(m_target_list.begin(), m_target_list.end(), target_sp) ==
505                  m_target_list.end() &&
506              "target already exists it the list");
507   m_target_list.push_back(std::move(target_sp));
508   if (do_select)
509     SetSelectedTargetInternal(m_target_list.size() - 1);
510 }
511 
512 void TargetList::SetSelectedTargetInternal(uint32_t index) {
513   lldbassert(!m_target_list.empty());
514   m_selected_target_idx = index < m_target_list.size() ? index : 0;
515 }
516 
517 void TargetList::SetSelectedTarget(uint32_t index) {
518   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
519   SetSelectedTargetInternal(index);
520 }
521 
522 void TargetList::SetSelectedTarget(const TargetSP &target_sp) {
523   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
524   auto it = std::find(m_target_list.begin(), m_target_list.end(), target_sp);
525   SetSelectedTargetInternal(std::distance(m_target_list.begin(), it));
526 }
527 
528 lldb::TargetSP TargetList::GetSelectedTarget() {
529   std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
530   if (m_selected_target_idx >= m_target_list.size())
531     m_selected_target_idx = 0;
532   return GetTargetAtIndex(m_selected_target_idx);
533 }
534