/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===-- PlatformRemoteDarwinDevice.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 "PlatformRemoteDarwinDevice.h" |
10 | | |
11 | | #include "lldb/Breakpoint/BreakpointLocation.h" |
12 | | #include "lldb/Core/Module.h" |
13 | | #include "lldb/Core/ModuleList.h" |
14 | | #include "lldb/Core/ModuleSpec.h" |
15 | | #include "lldb/Core/PluginManager.h" |
16 | | #include "lldb/Host/FileSystem.h" |
17 | | #include "lldb/Host/Host.h" |
18 | | #include "lldb/Host/HostInfo.h" |
19 | | #include "lldb/Target/Process.h" |
20 | | #include "lldb/Target/Target.h" |
21 | | #include "lldb/Utility/FileSpec.h" |
22 | | #include "lldb/Utility/LLDBLog.h" |
23 | | #include "lldb/Utility/Log.h" |
24 | | #include "lldb/Utility/Status.h" |
25 | | #include "lldb/Utility/StreamString.h" |
26 | | #include <optional> |
27 | | |
28 | | using namespace lldb; |
29 | | using namespace lldb_private; |
30 | | |
31 | | PlatformRemoteDarwinDevice::SDKDirectoryInfo::SDKDirectoryInfo( |
32 | | const lldb_private::FileSpec &sdk_dir) |
33 | 81 | : directory(sdk_dir), build(), user_cached(false) { |
34 | 81 | llvm::StringRef dirname_str = sdk_dir.GetFilename().GetStringRef(); |
35 | 81 | llvm::StringRef build_str; |
36 | 81 | std::tie(version, build_str) = ParseVersionBuildDir(dirname_str); |
37 | 81 | build.SetString(build_str); |
38 | 81 | } |
39 | | |
40 | | /// Default Constructor |
41 | | PlatformRemoteDarwinDevice::PlatformRemoteDarwinDevice() |
42 | 74 | : PlatformDarwinDevice(false) {} // This is a remote platform |
43 | | |
44 | | /// Destructor. |
45 | | /// |
46 | | /// The destructor is virtual since this class is designed to be |
47 | | /// inherited from by the plug-in instance. |
48 | 74 | PlatformRemoteDarwinDevice::~PlatformRemoteDarwinDevice() = default; |
49 | | |
50 | 1 | void PlatformRemoteDarwinDevice::GetStatus(Stream &strm) { |
51 | 1 | Platform::GetStatus(strm); |
52 | 1 | const char *sdk_directory = GetDeviceSupportDirectoryForOSVersion(); |
53 | 1 | if (sdk_directory) |
54 | 1 | strm.Printf(" SDK Path: \"%s\"\n", sdk_directory); |
55 | 0 | else |
56 | 0 | strm.PutCString(" SDK Path: error: unable to locate SDK\n"); |
57 | | |
58 | 1 | const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); |
59 | 2 | for (uint32_t i = 0; i < num_sdk_infos; ++i1 ) { |
60 | 1 | const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; |
61 | 1 | strm.Printf(" SDK Roots: [%2u] \"%s\"\n", i, |
62 | 1 | sdk_dir_info.directory.GetPath().c_str()); |
63 | 1 | } |
64 | 1 | } |
65 | | |
66 | | Status PlatformRemoteDarwinDevice::ResolveExecutable( |
67 | | const ModuleSpec &ms, lldb::ModuleSP &exe_module_sp, |
68 | 24 | const FileSpecList *module_search_paths_ptr) { |
69 | 24 | Status error; |
70 | | // Nothing special to do here, just use the actual file and architecture |
71 | | |
72 | 24 | ModuleSpec resolved_module_spec(ms); |
73 | | |
74 | | // Resolve any executable within a bundle on MacOSX |
75 | | // TODO: verify that this handles shallow bundles, if not then implement one |
76 | | // ourselves |
77 | 24 | Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec()); |
78 | | |
79 | 24 | if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) { |
80 | 24 | if (resolved_module_spec.GetArchitecture().IsValid() || |
81 | 24 | resolved_module_spec.GetUUID().IsValid()1 ) { |
82 | 24 | error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, |
83 | 24 | nullptr, nullptr, nullptr); |
84 | | |
85 | 24 | if (exe_module_sp && exe_module_sp->GetObjectFile()) |
86 | 24 | return error; |
87 | 0 | exe_module_sp.reset(); |
88 | 0 | } |
89 | | // No valid architecture was specified or the exact ARM slice wasn't found |
90 | | // so ask the platform for the architectures that we should be using (in |
91 | | // the correct order) and see if we can find a match that way |
92 | 0 | StreamString arch_names; |
93 | 0 | llvm::ListSeparator LS; |
94 | 0 | ArchSpec process_host_arch; |
95 | 0 | for (const ArchSpec &arch : GetSupportedArchitectures(process_host_arch)) { |
96 | 0 | resolved_module_spec.GetArchitecture() = arch; |
97 | 0 | error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp, |
98 | 0 | nullptr, nullptr, nullptr); |
99 | | // Did we find an executable using one of the |
100 | 0 | if (error.Success()) { |
101 | 0 | if (exe_module_sp && exe_module_sp->GetObjectFile()) |
102 | 0 | break; |
103 | 0 | else |
104 | 0 | error.SetErrorToGenericError(); |
105 | 0 | } |
106 | | |
107 | 0 | arch_names << LS << arch.GetArchitectureName(); |
108 | 0 | } |
109 | |
|
110 | 0 | if (error.Fail() || !exe_module_sp) { |
111 | 0 | if (FileSystem::Instance().Readable(resolved_module_spec.GetFileSpec())) { |
112 | 0 | error.SetErrorStringWithFormatv( |
113 | 0 | "'{0}' doesn't contain any '{1}' platform architectures: {2}", |
114 | 0 | resolved_module_spec.GetFileSpec(), GetPluginName(), |
115 | 0 | arch_names.GetData()); |
116 | 0 | } else { |
117 | 0 | error.SetErrorStringWithFormat( |
118 | 0 | "'%s' is not readable", |
119 | 0 | resolved_module_spec.GetFileSpec().GetPath().c_str()); |
120 | 0 | } |
121 | 0 | } |
122 | 0 | } else { |
123 | 0 | error.SetErrorStringWithFormat( |
124 | 0 | "'%s' does not exist", |
125 | 0 | resolved_module_spec.GetFileSpec().GetPath().c_str()); |
126 | 0 | } |
127 | | |
128 | 0 | return error; |
129 | 24 | } |
130 | | |
131 | | bool PlatformRemoteDarwinDevice::GetFileInSDK(const char *platform_file_path, |
132 | | uint32_t sdk_idx, |
133 | 1 | lldb_private::FileSpec &local_file) { |
134 | 1 | Log *log = GetLog(LLDBLog::Host); |
135 | 1 | if (sdk_idx < m_sdk_directory_infos.size()) { |
136 | 1 | std::string sdkroot_path = |
137 | 1 | m_sdk_directory_infos[sdk_idx].directory.GetPath(); |
138 | 1 | local_file.Clear(); |
139 | | |
140 | 1 | if (!sdkroot_path.empty() && platform_file_path && platform_file_path[0]) { |
141 | | // We may need to interpose "/Symbols/" or "/Symbols.Internal/" between |
142 | | // the |
143 | | // SDK root directory and the file path. |
144 | | |
145 | 1 | const char *paths_to_try[] = {"Symbols", "", "Symbols.Internal", nullptr}; |
146 | 1 | for (size_t i = 0; paths_to_try[i] != nullptr; i++0 ) { |
147 | 1 | local_file.SetFile(sdkroot_path, FileSpec::Style::native); |
148 | 1 | if (paths_to_try[i][0] != '\0') |
149 | 1 | local_file.AppendPathComponent(paths_to_try[i]); |
150 | 1 | local_file.AppendPathComponent(platform_file_path); |
151 | 1 | FileSystem::Instance().Resolve(local_file); |
152 | 1 | if (FileSystem::Instance().Exists(local_file)) { |
153 | 1 | LLDB_LOGF(log, "Found a copy of %s in the SDK dir %s/%s", |
154 | 1 | platform_file_path, sdkroot_path.c_str(), paths_to_try[i]); |
155 | 1 | return true; |
156 | 1 | } |
157 | 0 | local_file.Clear(); |
158 | 0 | } |
159 | 1 | } |
160 | 1 | } |
161 | 0 | return false; |
162 | 1 | } |
163 | | |
164 | | Status PlatformRemoteDarwinDevice::GetSymbolFile(const FileSpec &platform_file, |
165 | | const UUID *uuid_ptr, |
166 | 0 | FileSpec &local_file) { |
167 | 0 | Log *log = GetLog(LLDBLog::Host); |
168 | 0 | Status error; |
169 | 0 | char platform_file_path[PATH_MAX]; |
170 | 0 | if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { |
171 | 0 | const char *os_version_dir = GetDeviceSupportDirectoryForOSVersion(); |
172 | 0 | if (os_version_dir) { |
173 | 0 | std::string resolved_path = |
174 | 0 | (llvm::Twine(os_version_dir) + "/" + platform_file_path).str(); |
175 | |
|
176 | 0 | local_file.SetFile(resolved_path, FileSpec::Style::native); |
177 | 0 | FileSystem::Instance().Resolve(local_file); |
178 | 0 | if (FileSystem::Instance().Exists(local_file)) { |
179 | 0 | if (log) { |
180 | 0 | LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s", |
181 | 0 | platform_file_path, os_version_dir); |
182 | 0 | } |
183 | 0 | return error; |
184 | 0 | } |
185 | | |
186 | 0 | resolved_path = (llvm::Twine(os_version_dir) + "/Symbols.Internal/" + |
187 | 0 | platform_file_path) |
188 | 0 | .str(); |
189 | |
|
190 | 0 | local_file.SetFile(resolved_path, FileSpec::Style::native); |
191 | 0 | FileSystem::Instance().Resolve(local_file); |
192 | 0 | if (FileSystem::Instance().Exists(local_file)) { |
193 | 0 | LLDB_LOGF( |
194 | 0 | log, |
195 | 0 | "Found a copy of %s in the DeviceSupport dir %s/Symbols.Internal", |
196 | 0 | platform_file_path, os_version_dir); |
197 | 0 | return error; |
198 | 0 | } |
199 | 0 | resolved_path = |
200 | 0 | (llvm::Twine(os_version_dir) + "/Symbols/" + platform_file_path) |
201 | 0 | .str(); |
202 | |
|
203 | 0 | local_file.SetFile(resolved_path, FileSpec::Style::native); |
204 | 0 | FileSystem::Instance().Resolve(local_file); |
205 | 0 | if (FileSystem::Instance().Exists(local_file)) { |
206 | 0 | LLDB_LOGF(log, "Found a copy of %s in the DeviceSupport dir %s/Symbols", |
207 | 0 | platform_file_path, os_version_dir); |
208 | 0 | return error; |
209 | 0 | } |
210 | 0 | } |
211 | 0 | local_file = platform_file; |
212 | 0 | if (FileSystem::Instance().Exists(local_file)) |
213 | 0 | return error; |
214 | | |
215 | 0 | error.SetErrorStringWithFormatv( |
216 | 0 | "unable to locate a platform file for '{0}' in platform '{1}'", |
217 | 0 | platform_file_path, GetPluginName()); |
218 | 0 | } else { |
219 | 0 | error.SetErrorString("invalid platform file argument"); |
220 | 0 | } |
221 | 0 | return error; |
222 | 0 | } |
223 | | |
224 | | Status PlatformRemoteDarwinDevice::GetSharedModule( |
225 | | const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, |
226 | | const FileSpecList *module_search_paths_ptr, |
227 | 52 | llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) { |
228 | | // For iOS, the SDK files are all cached locally on the host system. So first |
229 | | // we ask for the file in the cached SDK, then we attempt to get a shared |
230 | | // module for the right architecture with the right UUID. |
231 | 52 | const FileSpec &platform_file = module_spec.GetFileSpec(); |
232 | 52 | Log *log = GetLog(LLDBLog::Host); |
233 | | |
234 | 52 | Status error; |
235 | 52 | char platform_file_path[PATH_MAX]; |
236 | | |
237 | 52 | if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { |
238 | 52 | ModuleSpec platform_module_spec(module_spec); |
239 | | |
240 | 52 | UpdateSDKDirectoryInfosIfNeeded(); |
241 | | |
242 | 52 | const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); |
243 | | |
244 | | // If we are connected we migth be able to correctly deduce the SDK |
245 | | // directory using the OS build. |
246 | 52 | const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); |
247 | 52 | if (connected_sdk_idx < num_sdk_infos) { |
248 | 0 | LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, |
249 | 0 | m_sdk_directory_infos[connected_sdk_idx].directory); |
250 | 0 | if (GetFileInSDK(platform_file_path, connected_sdk_idx, |
251 | 0 | platform_module_spec.GetFileSpec())) { |
252 | 0 | module_sp.reset(); |
253 | 0 | error = ResolveExecutable(platform_module_spec, module_sp, nullptr); |
254 | 0 | if (module_sp) { |
255 | 0 | m_last_module_sdk_idx = connected_sdk_idx; |
256 | 0 | error.Clear(); |
257 | 0 | return error; |
258 | 0 | } |
259 | 0 | } |
260 | 0 | } |
261 | | |
262 | | // Try the last SDK index if it is set as most files from an SDK will tend |
263 | | // to be valid in that same SDK. |
264 | 52 | if (m_last_module_sdk_idx < num_sdk_infos) { |
265 | 0 | LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, |
266 | 0 | m_sdk_directory_infos[m_last_module_sdk_idx].directory); |
267 | 0 | if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, |
268 | 0 | platform_module_spec.GetFileSpec())) { |
269 | 0 | module_sp.reset(); |
270 | 0 | error = ResolveExecutable(platform_module_spec, module_sp, nullptr); |
271 | 0 | if (module_sp) { |
272 | 0 | error.Clear(); |
273 | 0 | return error; |
274 | 0 | } |
275 | 0 | } |
276 | 0 | } |
277 | | |
278 | | // First try for an exact match of major, minor and update: If a particalar |
279 | | // SDK version was specified via --version or --build, look for a match on |
280 | | // disk. |
281 | 52 | const SDKDirectoryInfo *current_sdk_info = |
282 | 52 | GetSDKDirectoryForCurrentOSVersion(); |
283 | 52 | const uint32_t current_sdk_idx = |
284 | 52 | GetSDKIndexBySDKDirectoryInfo(current_sdk_info); |
285 | 52 | if (current_sdk_idx < num_sdk_infos && |
286 | 52 | current_sdk_idx != m_last_module_sdk_idx0 ) { |
287 | 0 | LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, |
288 | 0 | m_sdk_directory_infos[current_sdk_idx].directory); |
289 | 0 | if (GetFileInSDK(platform_file_path, current_sdk_idx, |
290 | 0 | platform_module_spec.GetFileSpec())) { |
291 | 0 | module_sp.reset(); |
292 | 0 | error = ResolveExecutable(platform_module_spec, module_sp, nullptr); |
293 | 0 | if (module_sp) { |
294 | 0 | m_last_module_sdk_idx = current_sdk_idx; |
295 | 0 | error.Clear(); |
296 | 0 | return error; |
297 | 0 | } |
298 | 0 | } |
299 | 0 | } |
300 | | |
301 | | // Second try all SDKs that were found. |
302 | 52 | for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx0 ) { |
303 | 1 | if (m_last_module_sdk_idx == sdk_idx) { |
304 | | // Skip the last module SDK index if we already searched it above |
305 | 0 | continue; |
306 | 0 | } |
307 | 1 | LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, |
308 | 1 | m_sdk_directory_infos[sdk_idx].directory); |
309 | 1 | if (GetFileInSDK(platform_file_path, sdk_idx, |
310 | 1 | platform_module_spec.GetFileSpec())) { |
311 | | // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); |
312 | | |
313 | 1 | error = ResolveExecutable(platform_module_spec, module_sp, nullptr); |
314 | 1 | if (module_sp) { |
315 | | // Remember the index of the last SDK that we found a file in in case |
316 | | // the wrong SDK was selected. |
317 | 1 | m_last_module_sdk_idx = sdk_idx; |
318 | 1 | error.Clear(); |
319 | 1 | return error; |
320 | 1 | } |
321 | 1 | } |
322 | 1 | } |
323 | 52 | } |
324 | | // Not the module we are looking for... Nothing to see here... |
325 | 51 | module_sp.reset(); |
326 | | |
327 | | // This may not be an SDK-related module. Try whether we can bring in the |
328 | | // thing to our local cache. |
329 | 51 | error = GetSharedModuleWithLocalCache(module_spec, module_sp, |
330 | 51 | module_search_paths_ptr, old_modules, |
331 | 51 | did_create_ptr); |
332 | 51 | if (error.Success()) |
333 | 41 | return error; |
334 | | |
335 | | // See if the file is present in any of the module_search_paths_ptr |
336 | | // directories. |
337 | 10 | if (!module_sp) |
338 | 10 | error = PlatformDarwin::FindBundleBinaryInExecSearchPaths( |
339 | 10 | module_spec, process, module_sp, module_search_paths_ptr, old_modules, |
340 | 10 | did_create_ptr); |
341 | | |
342 | 10 | if (error.Success()) |
343 | 10 | return error; |
344 | | |
345 | 0 | const bool always_create = false; |
346 | 0 | error = ModuleList::GetSharedModule(module_spec, module_sp, |
347 | 0 | module_search_paths_ptr, old_modules, |
348 | 0 | did_create_ptr, always_create); |
349 | |
|
350 | 0 | if (module_sp) |
351 | 0 | module_sp->SetPlatformFileSpec(platform_file); |
352 | |
|
353 | 0 | return error; |
354 | 10 | } |
355 | | |
356 | 52 | uint32_t PlatformRemoteDarwinDevice::GetConnectedSDKIndex() { |
357 | 52 | if (IsConnected()) { |
358 | 41 | if (m_connected_module_sdk_idx == UINT32_MAX) { |
359 | 41 | if (std::optional<std::string> build = GetRemoteOSBuildString()) { |
360 | 41 | const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); |
361 | 41 | for (uint32_t i = 0; i < num_sdk_infos; ++i0 ) { |
362 | 0 | const SDKDirectoryInfo &sdk_dir_info = m_sdk_directory_infos[i]; |
363 | 0 | if (strstr(sdk_dir_info.directory.GetFilename().AsCString(""), |
364 | 0 | build->c_str())) { |
365 | 0 | m_connected_module_sdk_idx = i; |
366 | 0 | } |
367 | 0 | } |
368 | 41 | } |
369 | 41 | } |
370 | 41 | } else { |
371 | 11 | m_connected_module_sdk_idx = UINT32_MAX; |
372 | 11 | } |
373 | 52 | return m_connected_module_sdk_idx; |
374 | 52 | } |
375 | | |
376 | | uint32_t PlatformRemoteDarwinDevice::GetSDKIndexBySDKDirectoryInfo( |
377 | 52 | const SDKDirectoryInfo *sdk_info) { |
378 | 52 | if (sdk_info == nullptr) { |
379 | 52 | return UINT32_MAX; |
380 | 52 | } |
381 | | |
382 | 0 | return sdk_info - &m_sdk_directory_infos[0]; |
383 | 52 | } |