Coverage Report

Created: 2023-09-30 09:22

/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
}