1dda28197Spatrick //===-- PlatformRemoteDarwinDevice.cpp ------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "PlatformRemoteDarwinDevice.h"
10061da546Spatrick
11061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
12061da546Spatrick #include "lldb/Core/Module.h"
13061da546Spatrick #include "lldb/Core/ModuleList.h"
14061da546Spatrick #include "lldb/Core/ModuleSpec.h"
15061da546Spatrick #include "lldb/Core/PluginManager.h"
16061da546Spatrick #include "lldb/Host/FileSystem.h"
17061da546Spatrick #include "lldb/Host/Host.h"
18dda28197Spatrick #include "lldb/Host/HostInfo.h"
19061da546Spatrick #include "lldb/Target/Process.h"
20061da546Spatrick #include "lldb/Target/Target.h"
21061da546Spatrick #include "lldb/Utility/FileSpec.h"
22*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
23061da546Spatrick #include "lldb/Utility/Log.h"
24061da546Spatrick #include "lldb/Utility/Status.h"
25061da546Spatrick #include "lldb/Utility/StreamString.h"
26*f6aab3d8Srobert #include <optional>
27061da546Spatrick
28061da546Spatrick using namespace lldb;
29061da546Spatrick using namespace lldb_private;
30061da546Spatrick
SDKDirectoryInfo(const lldb_private::FileSpec & sdk_dir)31061da546Spatrick PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo(
32061da546Spatrick const lldb_private::FileSpec &sdk_dir)
33061da546Spatrick : directory(sdk_dir), build(), user_cached(false) {
34061da546Spatrick llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef();
35061da546Spatrick llvm::StringRef build_str;
36061da546Spatrick std::tie(version, build_str) = ParseVersionBuildDir(dirname_str);
37061da546Spatrick build.SetString(build_str);
38061da546Spatrick }
39061da546Spatrick
40061da546Spatrick /// Default Constructor
PlatformRemoteDarwinDevice()41061da546Spatrick PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice()
42*f6aab3d8Srobert : PlatformDarwinDevice(false) {} // This is a remote platform
43061da546Spatrick
44061da546Spatrick /// Destructor.
45061da546Spatrick ///
46061da546Spatrick /// The destructor is virtual since this class is designed to be
47061da546Spatrick /// inherited from by the plug-in instance.
48be691f3bSpatrick PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default;
49061da546Spatrick
GetStatus(Stream & strm)50061da546Spatrick void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) {
51061da546Spatrick Platform::GetStatus(strm);
52061da546Spatrick const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion();
53061da546Spatrick if (sdk_directory)
54061da546Spatrick strm.Printf(" SDK Path: \"%s\"\n", sdk_directory);
55061da546Spatrick else
56061da546Spatrick strm.PutCString(" SDK Path: error: unable to locate SDK\n");
57061da546Spatrick
58061da546Spatrick const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
59061da546Spatrick for (uint32_t i = 0; i < num_sdk_infos; ++i) {
60061da546Spatrick const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
61061da546Spatrick strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i,
62061da546Spatrick sdk_dir_info.directory.GetPath().c_str());
63061da546Spatrick }
64061da546Spatrick }
65061da546Spatrick
ResolveExecutable(const ModuleSpec & ms,lldb::ModuleSP & exe_module_sp,const FileSpecList * module_search_paths_ptr)66061da546Spatrick Status PlatformRemoteDarwinDevice::ResolveExecutable(
67061da546Spatrick const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp,
68061da546Spatrick const FileSpecList *module_search_paths_ptr) {
69061da546Spatrick Status error;
70061da546Spatrick // Nothing special to do here, just use the actual file and architecture
71061da546Spatrick
72061da546Spatrick ModuleSpec resolved_module_spec(ms);
73061da546Spatrick
74061da546Spatrick // Resolve any executable within a bundle on MacOSX
75061da546Spatrick // TODO: verify that this handles shallow bundles, if not then implement one
76061da546Spatrick // ourselves
77061da546Spatrick Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
78061da546Spatrick
79061da546Spatrick if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
80061da546Spatrick if (resolved_module_spec.GetArchitecture().IsValid() ||
81061da546Spatrick resolved_module_spec.GetUUID().IsValid()) {
82061da546Spatrick error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
83061da546Spatrick nullptr, nullptr, nullptr);
84061da546Spatrick
85061da546Spatrick if (exe_module_sp && exe_module_sp->GetObjectFile())
86061da546Spatrick return error;
87061da546Spatrick exe_module_sp.reset();
88061da546Spatrick }
89061da546Spatrick // No valid architecture was specified or the exact ARM slice wasn't found
90061da546Spatrick // so ask the platform for the architectures that we should be using (in
91061da546Spatrick // the correct order) and see if we can find a match that way
92061da546Spatrick StreamString arch_names;
93*f6aab3d8Srobert llvm::ListSeparator LS;
94*f6aab3d8Srobert ArchSpec process_host_arch;
95*f6aab3d8Srobert for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) {
96*f6aab3d8Srobert resolved_module_spec.GetArchitecture() = arch;
97061da546Spatrick error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
98061da546Spatrick nullptr, nullptr, nullptr);
99061da546Spatrick // Did we find an executable using one of the
100061da546Spatrick if (error.Success()) {
101061da546Spatrick if (exe_module_sp && exe_module_sp->GetObjectFile())
102061da546Spatrick break;
103061da546Spatrick else
104061da546Spatrick error.SetErrorToGenericError();
105061da546Spatrick }
106061da546Spatrick
107*f6aab3d8Srobert arch_names << LS << arch.GetArchitectureName();
108061da546Spatrick }
109061da546Spatrick
110061da546Spatrick if (error.Fail() || !exe_module_sp) {
111061da546Spatrick if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) {
112*f6aab3d8Srobert error.SetErrorStringWithFormatv(
113*f6aab3d8Srobert "'{0}' doesn't contain any '{1}' platform architectures: {2}",
114*f6aab3d8Srobert resolved_module_spec.GetFileSpec(), GetPluginName(),
115*f6aab3d8Srobert arch_names.GetData());
116061da546Spatrick } else {
117061da546Spatrick error.SetErrorStringWithFormat(
118061da546Spatrick "'%s' is not readable",
119061da546Spatrick resolved_module_spec.GetFileSpec().GetPath().c_str());
120061da546Spatrick }
121061da546Spatrick }
122061da546Spatrick } else {
123061da546Spatrick error.SetErrorStringWithFormat(
124061da546Spatrick "'%s' does not exist",
125061da546Spatrick resolved_module_spec.GetFileSpec().GetPath().c_str());
126061da546Spatrick }
127061da546Spatrick
128061da546Spatrick return error;
129061da546Spatrick }
130061da546Spatrick
GetFileInSDK(const char * platform_file_path,uint32_t sdk_idx,lldb_private::FileSpec & local_file)131061da546Spatrick bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path,
132061da546Spatrick uint32_t sdk_idx,
133061da546Spatrick lldb_private::FileSpec &local_file) {
134*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Host);
135061da546Spatrick if (sdk_idx < m_sdk_directory_infos.size()) {
136061da546Spatrick std::string sdkroot_path =
137061da546Spatrick m_sdk_directory_infos[sdk_idx].directory.GetPath();
138061da546Spatrick local_file.Clear();
139061da546Spatrick
140061da546Spatrick if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) {
141061da546Spatrick // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between
142061da546Spatrick // the
143061da546Spatrick // SDK root directory and the file path.
144061da546Spatrick
145061da546Spatrick const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr};
146061da546Spatrick for (size_t i = 0; paths_to_try[i] != nullptr; i++) {
147061da546Spatrick local_file.SetFile(sdkroot_path, FileSpec::Style::native);
148061da546Spatrick if (paths_to_try[i][0] != '\0')
149061da546Spatrick local_file.AppendPathComponent(paths_to_try[i]);
150061da546Spatrick local_file.AppendPathComponent(platform_file_path);
151061da546Spatrick FileSystem::Instance().Resolve(local_file);
152061da546Spatrick if (FileSystem::Instance().Exists(local_file)) {
153061da546Spatrick LLDB_LOGF(log, "Found a copy of %s in the SDK dir %s/%s",
154061da546Spatrick platform_file_path, sdkroot_path.c_str(), paths_to_try[i]);
155061da546Spatrick return true;
156061da546Spatrick }
157061da546Spatrick local_file.Clear();
158061da546Spatrick }
159061da546Spatrick }
160061da546Spatrick }
161061da546Spatrick return false;
162061da546Spatrick }
163061da546Spatrick
GetSymbolFile(const FileSpec & platform_file,const UUID * uuid_ptr,FileSpec & local_file)164061da546Spatrick Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file,
165061da546Spatrick const UUID *uuid_ptr,
166061da546Spatrick FileSpec &local_file) {
167*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Host);
168061da546Spatrick Status error;
169061da546Spatrick char platform_file_path[PATH_MAX];
170061da546Spatrick if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
171061da546Spatrick const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion();
172061da546Spatrick if (os_version_dir) {
173061da546Spatrick std::string resolved_path =
174061da546Spatrick (llvm::Twine(os_version_dir) + "/" + platform_file_path).str();
175061da546Spatrick
176061da546Spatrick local_file.SetFile(resolved_path, FileSpec::Style::native);
177061da546Spatrick FileSystem::Instance().Resolve(local_file);
178061da546Spatrick if (FileSystem::Instance().Exists(local_file)) {
179061da546Spatrick if (log) {
180061da546Spatrick LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s",
181061da546Spatrick platform_file_path, os_version_dir);
182061da546Spatrick }
183061da546Spatrick return error;
184061da546Spatrick }
185061da546Spatrick
186061da546Spatrick resolved_path = (llvm::Twine(os_version_dir) + "/Symbols.Internal/" +
187061da546Spatrick platform_file_path)
188061da546Spatrick .str();
189061da546Spatrick
190061da546Spatrick local_file.SetFile(resolved_path, FileSpec::Style::native);
191061da546Spatrick FileSystem::Instance().Resolve(local_file);
192061da546Spatrick if (FileSystem::Instance().Exists(local_file)) {
193061da546Spatrick LLDB_LOGF(
194061da546Spatrick log,
195061da546Spatrick "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal",
196061da546Spatrick platform_file_path, os_version_dir);
197061da546Spatrick return error;
198061da546Spatrick }
199061da546Spatrick resolved_path =
200061da546Spatrick (llvm::Twine(os_version_dir) + "/Symbols/" + platform_file_path)
201061da546Spatrick .str();
202061da546Spatrick
203061da546Spatrick local_file.SetFile(resolved_path, FileSpec::Style::native);
204061da546Spatrick FileSystem::Instance().Resolve(local_file);
205061da546Spatrick if (FileSystem::Instance().Exists(local_file)) {
206061da546Spatrick LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s/Symbols",
207061da546Spatrick platform_file_path, os_version_dir);
208061da546Spatrick return error;
209061da546Spatrick }
210061da546Spatrick }
211061da546Spatrick local_file = platform_file;
212061da546Spatrick if (FileSystem::Instance().Exists(local_file))
213061da546Spatrick return error;
214061da546Spatrick
215*f6aab3d8Srobert error.SetErrorStringWithFormatv(
216*f6aab3d8Srobert "unable to locate a platform file for '{0}' in platform '{1}'",
217*f6aab3d8Srobert platform_file_path, GetPluginName());
218061da546Spatrick } else {
219061da546Spatrick error.SetErrorString("invalid platform file argument");
220061da546Spatrick }
221061da546Spatrick return error;
222061da546Spatrick }
223061da546Spatrick
GetSharedModule(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,llvm::SmallVectorImpl<ModuleSP> * old_modules,bool * did_create_ptr)224061da546Spatrick Status PlatformRemoteDarwinDevice::GetSharedModule(
225061da546Spatrick const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
226dda28197Spatrick const FileSpecList *module_search_paths_ptr,
227dda28197Spatrick llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
228061da546Spatrick // For iOS, the SDK files are all cached locally on the host system. So first
229061da546Spatrick // we ask for the file in the cached SDK, then we attempt to get a shared
230061da546Spatrick // module for the right architecture with the right UUID.
231061da546Spatrick const FileSpec &platform_file = module_spec.GetFileSpec();
232*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Host);
233061da546Spatrick
234061da546Spatrick Status error;
235061da546Spatrick char platform_file_path[PATH_MAX];
236061da546Spatrick
237061da546Spatrick if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) {
238061da546Spatrick ModuleSpec platform_module_spec(module_spec);
239061da546Spatrick
240061da546Spatrick UpdateSDKDirectoryInfosIfNeeded();
241061da546Spatrick
242061da546Spatrick const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
243061da546Spatrick
244061da546Spatrick // If we are connected we migth be able to correctly deduce the SDK
245061da546Spatrick // directory using the OS build.
246061da546Spatrick const uint32_t connected_sdk_idx = GetConnectedSDKIndex();
247061da546Spatrick if (connected_sdk_idx < num_sdk_infos) {
248061da546Spatrick LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
249061da546Spatrick m_sdk_directory_infos[connected_sdk_idx].directory);
250061da546Spatrick if (GetFileInSDK(platform_file_path, connected_sdk_idx,
251061da546Spatrick platform_module_spec.GetFileSpec())) {
252061da546Spatrick module_sp.reset();
253061da546Spatrick error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
254061da546Spatrick if (module_sp) {
255061da546Spatrick m_last_module_sdk_idx = connected_sdk_idx;
256061da546Spatrick error.Clear();
257061da546Spatrick return error;
258061da546Spatrick }
259061da546Spatrick }
260061da546Spatrick }
261061da546Spatrick
262061da546Spatrick // Try the last SDK index if it is set as most files from an SDK will tend
263061da546Spatrick // to be valid in that same SDK.
264061da546Spatrick if (m_last_module_sdk_idx < num_sdk_infos) {
265061da546Spatrick LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
266061da546Spatrick m_sdk_directory_infos[m_last_module_sdk_idx].directory);
267061da546Spatrick if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx,
268061da546Spatrick platform_module_spec.GetFileSpec())) {
269061da546Spatrick module_sp.reset();
270061da546Spatrick error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
271061da546Spatrick if (module_sp) {
272061da546Spatrick error.Clear();
273061da546Spatrick return error;
274061da546Spatrick }
275061da546Spatrick }
276061da546Spatrick }
277061da546Spatrick
278061da546Spatrick // First try for an exact match of major, minor and update: If a particalar
279061da546Spatrick // SDK version was specified via --version or --build, look for a match on
280061da546Spatrick // disk.
281061da546Spatrick const SDKDirectoryInfo *current_sdk_info =
282061da546Spatrick GetSDKDirectoryForCurrentOSVersion();
283061da546Spatrick const uint32_t current_sdk_idx =
284061da546Spatrick GetSDKIndexBySDKDirectoryInfo(current_sdk_info);
285061da546Spatrick if (current_sdk_idx < num_sdk_infos &&
286061da546Spatrick current_sdk_idx != m_last_module_sdk_idx) {
287061da546Spatrick LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
288061da546Spatrick m_sdk_directory_infos[current_sdk_idx].directory);
289061da546Spatrick if (GetFileInSDK(platform_file_path, current_sdk_idx,
290061da546Spatrick platform_module_spec.GetFileSpec())) {
291061da546Spatrick module_sp.reset();
292061da546Spatrick error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
293061da546Spatrick if (module_sp) {
294061da546Spatrick m_last_module_sdk_idx = current_sdk_idx;
295061da546Spatrick error.Clear();
296061da546Spatrick return error;
297061da546Spatrick }
298061da546Spatrick }
299061da546Spatrick }
300061da546Spatrick
301061da546Spatrick // Second try all SDKs that were found.
302061da546Spatrick for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) {
303061da546Spatrick if (m_last_module_sdk_idx == sdk_idx) {
304061da546Spatrick // Skip the last module SDK index if we already searched it above
305061da546Spatrick continue;
306061da546Spatrick }
307061da546Spatrick LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file,
308061da546Spatrick m_sdk_directory_infos[sdk_idx].directory);
309061da546Spatrick if (GetFileInSDK(platform_file_path, sdk_idx,
310061da546Spatrick platform_module_spec.GetFileSpec())) {
311061da546Spatrick // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str());
312061da546Spatrick
313061da546Spatrick error = ResolveExecutable(platform_module_spec, module_sp, nullptr);
314061da546Spatrick if (module_sp) {
315061da546Spatrick // Remember the index of the last SDK that we found a file in in case
316061da546Spatrick // the wrong SDK was selected.
317061da546Spatrick m_last_module_sdk_idx = sdk_idx;
318061da546Spatrick error.Clear();
319061da546Spatrick return error;
320061da546Spatrick }
321061da546Spatrick }
322061da546Spatrick }
323061da546Spatrick }
324061da546Spatrick // Not the module we are looking for... Nothing to see here...
325061da546Spatrick module_sp.reset();
326061da546Spatrick
327061da546Spatrick // This may not be an SDK-related module. Try whether we can bring in the
328061da546Spatrick // thing to our local cache.
329061da546Spatrick error = GetSharedModuleWithLocalCache(module_spec, module_sp,
330dda28197Spatrick module_search_paths_ptr, old_modules,
331dda28197Spatrick did_create_ptr);
332061da546Spatrick if (error.Success())
333061da546Spatrick return error;
334061da546Spatrick
335061da546Spatrick // See if the file is present in any of the module_search_paths_ptr
336061da546Spatrick // directories.
337061da546Spatrick if (!module_sp)
338dda28197Spatrick error = PlatformDarwin::FindBundleBinaryInExecSearchPaths(
339dda28197Spatrick module_spec, process, module_sp, module_search_paths_ptr, old_modules,
340dda28197Spatrick did_create_ptr);
341061da546Spatrick
342061da546Spatrick if (error.Success())
343061da546Spatrick return error;
344061da546Spatrick
345061da546Spatrick const bool always_create = false;
346dda28197Spatrick error = ModuleList::GetSharedModule(module_spec, module_sp,
347dda28197Spatrick module_search_paths_ptr, old_modules,
348061da546Spatrick did_create_ptr, always_create);
349061da546Spatrick
350061da546Spatrick if (module_sp)
351061da546Spatrick module_sp->SetPlatformFileSpec(platform_file);
352061da546Spatrick
353061da546Spatrick return error;
354061da546Spatrick }
355061da546Spatrick
GetConnectedSDKIndex()356061da546Spatrick uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() {
357061da546Spatrick if (IsConnected()) {
358061da546Spatrick if (m_connected_module_sdk_idx == UINT32_MAX) {
359*f6aab3d8Srobert if (std::optional<std::string> build = GetRemoteOSBuildString()) {
360061da546Spatrick const uint32_t num_sdk_infos = m_sdk_directory_infos.size();
361061da546Spatrick for (uint32_t i = 0; i < num_sdk_infos; ++i) {
362061da546Spatrick const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i];
363061da546Spatrick if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""),
364*f6aab3d8Srobert build->c_str())) {
365061da546Spatrick m_connected_module_sdk_idx = i;
366061da546Spatrick }
367061da546Spatrick }
368061da546Spatrick }
369061da546Spatrick }
370061da546Spatrick } else {
371061da546Spatrick m_connected_module_sdk_idx = UINT32_MAX;
372061da546Spatrick }
373061da546Spatrick return m_connected_module_sdk_idx;
374061da546Spatrick }
375061da546Spatrick
GetSDKIndexBySDKDirectoryInfo(const SDKDirectoryInfo * sdk_info)376061da546Spatrick uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo(
377061da546Spatrick const SDKDirectoryInfo *sdk_info) {
378061da546Spatrick if (sdk_info == nullptr) {
379061da546Spatrick return UINT32_MAX;
380061da546Spatrick }
381061da546Spatrick
382061da546Spatrick return sdk_info - &m_sdk_directory_infos[0];
383061da546Spatrick }
384