Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- PlatformDarwin.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 "PlatformDarwin.h"
10
11
#include <cstring>
12
13
#include <algorithm>
14
#include <memory>
15
#include <mutex>
16
#include <optional>
17
18
#include "lldb/Breakpoint/BreakpointLocation.h"
19
#include "lldb/Breakpoint/BreakpointSite.h"
20
#include "lldb/Core/Debugger.h"
21
#include "lldb/Core/Module.h"
22
#include "lldb/Core/ModuleSpec.h"
23
#include "lldb/Core/PluginManager.h"
24
#include "lldb/Core/Section.h"
25
#include "lldb/Host/Host.h"
26
#include "lldb/Host/HostInfo.h"
27
#include "lldb/Host/XML.h"
28
#include "lldb/Interpreter/CommandInterpreter.h"
29
#include "lldb/Interpreter/OptionValueProperties.h"
30
#include "lldb/Interpreter/OptionValueString.h"
31
#include "lldb/Interpreter/Options.h"
32
#include "lldb/Symbol/LocateSymbolFile.h"
33
#include "lldb/Symbol/ObjectFile.h"
34
#include "lldb/Symbol/SymbolFile.h"
35
#include "lldb/Symbol/SymbolVendor.h"
36
#include "lldb/Target/Platform.h"
37
#include "lldb/Target/Process.h"
38
#include "lldb/Target/Target.h"
39
#include "lldb/Utility/LLDBLog.h"
40
#include "lldb/Utility/Log.h"
41
#include "lldb/Utility/ProcessInfo.h"
42
#include "lldb/Utility/Status.h"
43
#include "lldb/Utility/Timer.h"
44
#include "llvm/ADT/STLExtras.h"
45
#include "llvm/Support/Error.h"
46
#include "llvm/Support/FileSystem.h"
47
#include "llvm/Support/Threading.h"
48
#include "llvm/Support/VersionTuple.h"
49
50
#if defined(__APPLE__)
51
#include <TargetConditionals.h>
52
#endif
53
54
using namespace lldb;
55
using namespace lldb_private;
56
57
0
static Status ExceptionMaskValidator(const char *string, void *unused) {
58
0
  Status error;
59
0
  llvm::StringRef str_ref(string);
60
0
  llvm::SmallVector<llvm::StringRef> candidates;
61
0
  str_ref.split(candidates, '|');
62
0
  for (auto candidate : candidates) {
63
0
    if (!(candidate == "EXC_BAD_ACCESS"
64
0
          || candidate == "EXC_BAD_INSTRUCTION"
65
0
          || candidate == "EXC_ARITHMETIC"
66
0
          || candidate == "EXC_RESOURCE"
67
0
          || candidate == "EXC_GUARD"
68
0
          || candidate == "EXC_SYSCALL")) {
69
0
      error.SetErrorStringWithFormat("invalid exception type: '%s'",
70
0
          candidate.str().c_str());
71
0
      return error;
72
0
    }
73
0
  }
74
0
  return {};
75
0
}
76
77
/// Destructor.
78
///
79
/// The destructor is virtual since this class is designed to be
80
/// inherited from by the plug-in instance.
81
3.99k
PlatformDarwin::~PlatformDarwin() = default;
82
83
// Static Variables
84
static uint32_t g_initialize_count = 0;
85
86
35.5k
void PlatformDarwin::Initialize() {
87
35.5k
  Platform::Initialize();
88
89
35.5k
  if (g_initialize_count++ == 0) {
90
3.94k
    PluginManager::RegisterPlugin(PlatformDarwin::GetPluginNameStatic(),
91
3.94k
                                  PlatformDarwin::GetDescriptionStatic(),
92
3.94k
                                  PlatformDarwin::CreateInstance,
93
3.94k
                                  PlatformDarwin::DebuggerInitialize);
94
3.94k
  }
95
35.5k
}
96
97
27.5k
void PlatformDarwin::Terminate() {
98
27.5k
  if (g_initialize_count > 0) {
99
27.5k
    if (--g_initialize_count == 0) {
100
3
      PluginManager::UnregisterPlugin(PlatformDarwin::CreateInstance);
101
3
    }
102
27.5k
  }
103
104
27.5k
  Platform::Terminate();
105
27.5k
}
106
107
3.94k
llvm::StringRef PlatformDarwin::GetDescriptionStatic() {
108
3.94k
  return "Darwin platform plug-in.";
109
3.94k
}
110
111
243
PlatformSP PlatformDarwin::CreateInstance(bool force, const ArchSpec *arch) {
112
   // We only create subclasses of the PlatformDarwin plugin.
113
243
   return PlatformSP();
114
243
}
115
116
#define LLDB_PROPERTIES_platformdarwin
117
#include "PlatformMacOSXProperties.inc"
118
119
#define LLDB_PROPERTIES_platformdarwin
120
enum {
121
#include "PlatformMacOSXPropertiesEnum.inc"
122
};
123
124
class PlatformDarwinProperties : public Properties {
125
public:
126
9.93k
  static llvm::StringRef GetSettingName() {
127
9.93k
    static constexpr llvm::StringLiteral g_setting_name("darwin");
128
9.93k
    return g_setting_name;
129
9.93k
  }
130
131
3.88k
  PlatformDarwinProperties() : Properties() {
132
3.88k
    m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
133
3.88k
    m_collection_sp->Initialize(g_platformdarwin_properties);
134
3.88k
  }
135
136
3.88k
  ~PlatformDarwinProperties() override = default;
137
138
2.22k
  const char *GetIgnoredExceptions() const {
139
2.22k
    const uint32_t idx = ePropertyIgnoredExceptions;
140
2.22k
    const OptionValueString *option_value =
141
2.22k
        m_collection_sp->GetPropertyAtIndexAsOptionValueString(idx);
142
2.22k
    assert(option_value);
143
2.22k
    return option_value->GetCurrentValue();
144
2.22k
  }
145
146
3.88k
  OptionValueString *GetIgnoredExceptionValue() {
147
3.88k
    const uint32_t idx = ePropertyIgnoredExceptions;
148
3.88k
    OptionValueString *option_value =
149
3.88k
        m_collection_sp->GetPropertyAtIndexAsOptionValueString(idx);
150
3.88k
    assert(option_value);
151
3.88k
    return option_value;
152
3.88k
  }
153
};
154
155
9.98k
static PlatformDarwinProperties &GetGlobalProperties() {
156
9.98k
  static PlatformDarwinProperties g_settings;
157
9.98k
  return g_settings;
158
9.98k
}
159
160
void PlatformDarwin::DebuggerInitialize(
161
6.05k
    lldb_private::Debugger &debugger) {
162
6.05k
  if (!PluginManager::GetSettingForPlatformPlugin(
163
6.05k
          debugger, PlatformDarwinProperties::GetSettingName())) {
164
3.88k
    const bool is_global_setting = false;
165
3.88k
    PluginManager::CreateSettingForPlatformPlugin(
166
3.88k
        debugger, GetGlobalProperties().GetValueProperties(),
167
3.88k
        "Properties for the Darwin platform plug-in.", is_global_setting);
168
3.88k
    OptionValueString *value = GetGlobalProperties().GetIgnoredExceptionValue();
169
3.88k
    value->SetValidator(ExceptionMaskValidator);
170
3.88k
  }
171
6.05k
}
172
173
Args
174
2.22k
PlatformDarwin::GetExtraStartupCommands() {
175
2.22k
  std::string ignored_exceptions
176
2.22k
      = GetGlobalProperties().GetIgnoredExceptions();
177
2.22k
  if (ignored_exceptions.empty())
178
2.22k
    return {};
179
0
  Args ret_args;
180
0
  std::string packet = "QSetIgnoredExceptions:";
181
0
  packet.append(ignored_exceptions);
182
0
  ret_args.AppendArgument(packet);
183
0
  return ret_args;
184
2.22k
}
185
186
lldb_private::Status
187
PlatformDarwin::PutFile(const lldb_private::FileSpec &source,
188
                        const lldb_private::FileSpec &destination, uint32_t uid,
189
1
                        uint32_t gid) {
190
  // Unconditionally unlink the destination. If it is an executable,
191
  // simply opening it and truncating its contents would invalidate
192
  // its cached code signature.
193
1
  Unlink(destination);
194
1
  return PlatformPOSIX::PutFile(source, destination, uid, gid);
195
1
}
196
197
FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
198
231k
    Target *target, Module &module, Stream &feedback_stream) {
199
231k
  FileSpecList file_list;
200
231k
  if (target &&
201
231k
      
target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython231k
) {
202
    // NB some extensions might be meaningful and should not be stripped -
203
    // "this.binary.file"
204
    // should not lose ".file" but GetFileNameStrippingExtension() will do
205
    // precisely that. Ideally, we should have a per-platform list of
206
    // extensions (".exe", ".app", ".dSYM", ".framework") which should be
207
    // stripped while leaving "this.binary.file" as-is.
208
209
231k
    FileSpec module_spec = module.GetFileSpec();
210
211
231k
    if (module_spec) {
212
231k
      if (SymbolFile *symfile = module.GetSymbolFile()) {
213
230k
        ObjectFile *objfile = symfile->GetObjectFile();
214
230k
        if (objfile) {
215
230k
          FileSpec symfile_spec(objfile->GetFileSpec());
216
230k
          if (symfile_spec &&
217
230k
              llvm::StringRef(symfile_spec.GetPath())
218
225k
                  .contains_insensitive(".dSYM/Contents/Resources/DWARF") &&
219
230k
              
FileSystem::Instance().Exists(symfile_spec)2.89k
) {
220
5.66k
            while (module_spec.GetFilename()) {
221
5.66k
              std::string module_basename(
222
5.66k
                  module_spec.GetFilename().GetCString());
223
5.66k
              std::string original_module_basename(module_basename);
224
225
5.66k
              bool was_keyword = false;
226
227
              // FIXME: for Python, we cannot allow certain characters in
228
              // module
229
              // filenames we import. Theoretically, different scripting
230
              // languages may have different sets of forbidden tokens in
231
              // filenames, and that should be dealt with by each
232
              // ScriptInterpreter. For now, we just replace dots with
233
              // underscores, but if we ever support anything other than
234
              // Python we will need to rework this
235
5.66k
              std::replace(module_basename.begin(), module_basename.end(), '.',
236
5.66k
                           '_');
237
5.66k
              std::replace(module_basename.begin(), module_basename.end(), ' ',
238
5.66k
                           '_');
239
5.66k
              std::replace(module_basename.begin(), module_basename.end(), '-',
240
5.66k
                           '_');
241
5.66k
              ScriptInterpreter *script_interpreter =
242
5.66k
                  target->GetDebugger().GetScriptInterpreter();
243
5.66k
              if (script_interpreter &&
244
5.66k
                  script_interpreter->IsReservedWord(module_basename.c_str())) {
245
2
                module_basename.insert(module_basename.begin(), '_');
246
2
                was_keyword = true;
247
2
              }
248
249
5.66k
              StreamString path_string;
250
5.66k
              StreamString original_path_string;
251
              // for OSX we are going to be in
252
              // .dSYM/Contents/Resources/DWARF/<basename> let us go to
253
              // .dSYM/Contents/Resources/Python/<basename>.py and see if the
254
              // file exists
255
5.66k
              path_string.Printf("%s/../Python/%s.py",
256
5.66k
                                 symfile_spec.GetDirectory().GetCString(),
257
5.66k
                                 module_basename.c_str());
258
5.66k
              original_path_string.Printf(
259
5.66k
                  "%s/../Python/%s.py",
260
5.66k
                  symfile_spec.GetDirectory().GetCString(),
261
5.66k
                  original_module_basename.c_str());
262
5.66k
              FileSpec script_fspec(path_string.GetString());
263
5.66k
              FileSystem::Instance().Resolve(script_fspec);
264
5.66k
              FileSpec orig_script_fspec(original_path_string.GetString());
265
5.66k
              FileSystem::Instance().Resolve(orig_script_fspec);
266
267
              // if we did some replacements of reserved characters, and a
268
              // file with the untampered name exists, then warn the user
269
              // that the file as-is shall not be loaded
270
5.66k
              if (module_basename != original_module_basename &&
271
5.66k
                  
FileSystem::Instance().Exists(orig_script_fspec)2.80k
) {
272
0
                const char *reason_for_complaint =
273
0
                    was_keyword ? "conflicts with a keyword"
274
0
                                : "contains reserved characters";
275
0
                if (FileSystem::Instance().Exists(script_fspec))
276
0
                  feedback_stream.Printf(
277
0
                      "warning: the symbol file '%s' contains a debug "
278
0
                      "script. However, its name"
279
0
                      " '%s' %s and as such cannot be loaded. LLDB will"
280
0
                      " load '%s' instead. Consider removing the file with "
281
0
                      "the malformed name to"
282
0
                      " eliminate this warning.\n",
283
0
                      symfile_spec.GetPath().c_str(),
284
0
                      original_path_string.GetData(), reason_for_complaint,
285
0
                      path_string.GetData());
286
0
                else
287
0
                  feedback_stream.Printf(
288
0
                      "warning: the symbol file '%s' contains a debug "
289
0
                      "script. However, its name"
290
0
                      " %s and as such cannot be loaded. If you intend"
291
0
                      " to have this script loaded, please rename '%s' to "
292
0
                      "'%s' and retry.\n",
293
0
                      symfile_spec.GetPath().c_str(), reason_for_complaint,
294
0
                      original_path_string.GetData(), path_string.GetData());
295
0
              }
296
297
5.66k
              if (FileSystem::Instance().Exists(script_fspec)) {
298
3
                file_list.Append(script_fspec);
299
3
                break;
300
3
              }
301
302
              // If we didn't find the python file, then keep stripping the
303
              // extensions and try again
304
5.66k
              ConstString filename_no_extension(
305
5.66k
                  module_spec.GetFileNameStrippingExtension());
306
5.66k
              if (module_spec.GetFilename() == filename_no_extension)
307
2.89k
                break;
308
309
2.77k
              module_spec.SetFilename(filename_no_extension);
310
2.77k
            }
311
2.89k
          }
312
230k
        }
313
230k
      }
314
231k
    }
315
231k
  }
316
231k
  return file_list;
317
231k
}
318
319
Status PlatformDarwin::ResolveSymbolFile(Target &target,
320
                                         const ModuleSpec &sym_spec,
321
20
                                         FileSpec &sym_file) {
322
20
  sym_file = sym_spec.GetSymbolFileSpec();
323
20
  if (FileSystem::Instance().IsDirectory(sym_file)) {
324
4
    sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(),
325
4
                                               sym_spec.GetArchitecturePtr());
326
4
  }
327
20
  return {};
328
20
}
329
330
Status PlatformDarwin::GetSharedModule(
331
    const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
332
    const FileSpecList *module_search_paths_ptr,
333
0
    llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
334
0
  Status error;
335
0
  module_sp.reset();
336
337
0
  if (IsRemote()) {
338
    // If we have a remote platform always, let it try and locate the shared
339
    // module first.
340
0
    if (m_remote_platform_sp) {
341
0
      error = m_remote_platform_sp->GetSharedModule(
342
0
          module_spec, process, module_sp, module_search_paths_ptr, old_modules,
343
0
          did_create_ptr);
344
0
    }
345
0
  }
346
347
0
  if (!module_sp) {
348
    // Fall back to the local platform and find the file locally
349
0
    error = Platform::GetSharedModule(module_spec, process, module_sp,
350
0
                                      module_search_paths_ptr, old_modules,
351
0
                                      did_create_ptr);
352
353
0
    const FileSpec &platform_file = module_spec.GetFileSpec();
354
0
    if (!module_sp && module_search_paths_ptr && platform_file) {
355
      // We can try to pull off part of the file path up to the bundle
356
      // directory level and try any module search paths...
357
0
      FileSpec bundle_directory;
358
0
      if (Host::GetBundleDirectory(platform_file, bundle_directory)) {
359
0
        if (platform_file == bundle_directory) {
360
0
          ModuleSpec new_module_spec(module_spec);
361
0
          new_module_spec.GetFileSpec() = bundle_directory;
362
0
          if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) {
363
0
            Status new_error(Platform::GetSharedModule(
364
0
                new_module_spec, process, module_sp, nullptr, old_modules,
365
0
                did_create_ptr));
366
367
0
            if (module_sp)
368
0
              return new_error;
369
0
          }
370
0
        } else {
371
0
          char platform_path[PATH_MAX];
372
0
          char bundle_dir[PATH_MAX];
373
0
          platform_file.GetPath(platform_path, sizeof(platform_path));
374
0
          const size_t bundle_directory_len =
375
0
              bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir));
376
0
          char new_path[PATH_MAX];
377
0
          size_t num_module_search_paths = module_search_paths_ptr->GetSize();
378
0
          for (size_t i = 0; i < num_module_search_paths; ++i) {
379
0
            const size_t search_path_len =
380
0
                module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(
381
0
                    new_path, sizeof(new_path));
382
0
            if (search_path_len < sizeof(new_path)) {
383
0
              snprintf(new_path + search_path_len,
384
0
                       sizeof(new_path) - search_path_len, "/%s",
385
0
                       platform_path + bundle_directory_len);
386
0
              FileSpec new_file_spec(new_path);
387
0
              if (FileSystem::Instance().Exists(new_file_spec)) {
388
0
                ModuleSpec new_module_spec(module_spec);
389
0
                new_module_spec.GetFileSpec() = new_file_spec;
390
0
                Status new_error(Platform::GetSharedModule(
391
0
                    new_module_spec, process, module_sp, nullptr, old_modules,
392
0
                    did_create_ptr));
393
394
0
                if (module_sp) {
395
0
                  module_sp->SetPlatformFileSpec(new_file_spec);
396
0
                  return new_error;
397
0
                }
398
0
              }
399
0
            }
400
0
          }
401
0
        }
402
0
      }
403
0
    }
404
0
  }
405
0
  if (module_sp)
406
0
    module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
407
0
  return error;
408
0
}
409
410
size_t
411
PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target,
412
70.6k
                                                BreakpointSite *bp_site) {
413
70.6k
  const uint8_t *trap_opcode = nullptr;
414
70.6k
  uint32_t trap_opcode_size = 0;
415
70.6k
  bool bp_is_thumb = false;
416
417
70.6k
  llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
418
70.6k
  switch (machine) {
419
0
  case llvm::Triple::aarch64_32:
420
0
  case llvm::Triple::aarch64: {
421
    // 'brk #0' or 0xd4200000 in BE byte order
422
0
    static const uint8_t g_arm64_breakpoint_opcode[] = {0x00, 0x00, 0x20, 0xD4};
423
0
    trap_opcode = g_arm64_breakpoint_opcode;
424
0
    trap_opcode_size = sizeof(g_arm64_breakpoint_opcode);
425
0
  } break;
426
427
0
  case llvm::Triple::thumb:
428
0
    bp_is_thumb = true;
429
0
    [[fallthrough]];
430
0
  case llvm::Triple::arm: {
431
0
    static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
432
0
    static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE};
433
434
    // Auto detect arm/thumb if it wasn't explicitly specified
435
0
    if (!bp_is_thumb) {
436
0
      lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
437
0
      if (bp_loc_sp)
438
0
        bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() ==
439
0
                      AddressClass::eCodeAlternateISA;
440
0
    }
441
0
    if (bp_is_thumb) {
442
0
      trap_opcode = g_thumb_breakpooint_opcode;
443
0
      trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
444
0
      break;
445
0
    }
446
0
    trap_opcode = g_arm_breakpoint_opcode;
447
0
    trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
448
0
  } break;
449
450
0
  case llvm::Triple::ppc:
451
0
  case llvm::Triple::ppc64: {
452
0
    static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08};
453
0
    trap_opcode = g_ppc_breakpoint_opcode;
454
0
    trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
455
0
  } break;
456
457
70.6k
  default:
458
70.6k
    return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
459
70.6k
  }
460
461
0
  if (trap_opcode && trap_opcode_size) {
462
0
    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
463
0
      return trap_opcode_size;
464
0
  }
465
0
  return 0;
466
0
}
467
468
bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches(
469
273k
    lldb_private::Target &target, const lldb::ModuleSP &module_sp) {
470
273k
  if (!module_sp)
471
0
    return false;
472
473
273k
  ObjectFile *obj_file = module_sp->GetObjectFile();
474
273k
  if (!obj_file)
475
0
    return false;
476
477
273k
  ObjectFile::Type obj_type = obj_file->GetType();
478
273k
  return obj_type == ObjectFile::eTypeDynamicLinker;
479
273k
}
480
481
void PlatformDarwin::x86GetSupportedArchitectures(
482
7.70k
    std::vector<ArchSpec> &archs) {
483
7.70k
  ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
484
7.70k
  archs.push_back(host_arch);
485
486
7.70k
  if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) {
487
0
    archs.push_back(ArchSpec("x86_64-apple-macosx"));
488
0
    archs.push_back(HostInfo::GetArchitecture(HostInfo::eArchKind32));
489
7.70k
  } else {
490
7.70k
    ArchSpec host_arch64 = HostInfo::GetArchitecture(HostInfo::eArchKind64);
491
7.70k
    if (host_arch.IsExactMatch(host_arch64))
492
7.70k
      archs.push_back(HostInfo::GetArchitecture(HostInfo::eArchKind32));
493
7.70k
  }
494
7.70k
}
495
496
83
static llvm::ArrayRef<const char *> GetCompatibleArchs(ArchSpec::Core core) {
497
83
  switch (core) {
498
83
  default:
499
83
    [[fallthrough]];
500
83
  case ArchSpec::eCore_arm_arm64e: {
501
83
    static const char *g_arm64e_compatible_archs[] = {
502
83
        "arm64e",    "arm64",    "armv7",    "armv7f",   "armv7k",   "armv7s",
503
83
        "armv7m",    "armv7em",  "armv6m",   "armv6",    "armv5",    "armv4",
504
83
        "arm",       "thumbv7",  "thumbv7f", "thumbv7k", "thumbv7s", "thumbv7m",
505
83
        "thumbv7em", "thumbv6m", "thumbv6",  "thumbv5",  "thumbv4t", "thumb",
506
83
    };
507
83
    return {g_arm64e_compatible_archs};
508
83
  }
509
0
  case ArchSpec::eCore_arm_arm64: {
510
0
    static const char *g_arm64_compatible_archs[] = {
511
0
        "arm64",    "armv7",    "armv7f",   "armv7k",   "armv7s",   "armv7m",
512
0
        "armv7em",  "armv6m",   "armv6",    "armv5",    "armv4",    "arm",
513
0
        "thumbv7",  "thumbv7f", "thumbv7k", "thumbv7s", "thumbv7m", "thumbv7em",
514
0
        "thumbv6m", "thumbv6",  "thumbv5",  "thumbv4t", "thumb",
515
0
    };
516
0
    return {g_arm64_compatible_archs};
517
83
  }
518
0
  case ArchSpec::eCore_arm_armv7: {
519
0
    static const char *g_armv7_compatible_archs[] = {
520
0
        "armv7",   "armv6m",   "armv6",   "armv5",   "armv4",    "arm",
521
0
        "thumbv7", "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb",
522
0
    };
523
0
    return {g_armv7_compatible_archs};
524
83
  }
525
0
  case ArchSpec::eCore_arm_armv7f: {
526
0
    static const char *g_armv7f_compatible_archs[] = {
527
0
        "armv7f",  "armv7",   "armv6m",   "armv6",   "armv5",
528
0
        "armv4",   "arm",     "thumbv7f", "thumbv7", "thumbv6m",
529
0
        "thumbv6", "thumbv5", "thumbv4t", "thumb",
530
0
    };
531
0
    return {g_armv7f_compatible_archs};
532
83
  }
533
0
  case ArchSpec::eCore_arm_armv7k: {
534
0
    static const char *g_armv7k_compatible_archs[] = {
535
0
        "armv7k",  "armv7",   "armv6m",   "armv6",   "armv5",
536
0
        "armv4",   "arm",     "thumbv7k", "thumbv7", "thumbv6m",
537
0
        "thumbv6", "thumbv5", "thumbv4t", "thumb",
538
0
    };
539
0
    return {g_armv7k_compatible_archs};
540
83
  }
541
0
  case ArchSpec::eCore_arm_armv7s: {
542
0
    static const char *g_armv7s_compatible_archs[] = {
543
0
        "armv7s",  "armv7",   "armv6m",   "armv6",   "armv5",
544
0
        "armv4",   "arm",     "thumbv7s", "thumbv7", "thumbv6m",
545
0
        "thumbv6", "thumbv5", "thumbv4t", "thumb",
546
0
    };
547
0
    return {g_armv7s_compatible_archs};
548
83
  }
549
0
  case ArchSpec::eCore_arm_armv7m: {
550
0
    static const char *g_armv7m_compatible_archs[] = {
551
0
        "armv7m",  "armv7",   "armv6m",   "armv6",   "armv5",
552
0
        "armv4",   "arm",     "thumbv7m", "thumbv7", "thumbv6m",
553
0
        "thumbv6", "thumbv5", "thumbv4t", "thumb",
554
0
    };
555
0
    return {g_armv7m_compatible_archs};
556
83
  }
557
0
  case ArchSpec::eCore_arm_armv7em: {
558
0
    static const char *g_armv7em_compatible_archs[] = {
559
0
        "armv7em", "armv7",   "armv6m",    "armv6",   "armv5",
560
0
        "armv4",   "arm",     "thumbv7em", "thumbv7", "thumbv6m",
561
0
        "thumbv6", "thumbv5", "thumbv4t",  "thumb",
562
0
    };
563
0
    return {g_armv7em_compatible_archs};
564
83
  }
565
0
  case ArchSpec::eCore_arm_armv6m: {
566
0
    static const char *g_armv6m_compatible_archs[] = {
567
0
        "armv6m",   "armv6",   "armv5",   "armv4",    "arm",
568
0
        "thumbv6m", "thumbv6", "thumbv5", "thumbv4t", "thumb",
569
0
    };
570
0
    return {g_armv6m_compatible_archs};
571
83
  }
572
0
  case ArchSpec::eCore_arm_armv6: {
573
0
    static const char *g_armv6_compatible_archs[] = {
574
0
        "armv6",   "armv5",   "armv4",    "arm",
575
0
        "thumbv6", "thumbv5", "thumbv4t", "thumb",
576
0
    };
577
0
    return {g_armv6_compatible_archs};
578
83
  }
579
0
  case ArchSpec::eCore_arm_armv5: {
580
0
    static const char *g_armv5_compatible_archs[] = {
581
0
        "armv5", "armv4", "arm", "thumbv5", "thumbv4t", "thumb",
582
0
    };
583
0
    return {g_armv5_compatible_archs};
584
83
  }
585
0
  case ArchSpec::eCore_arm_armv4: {
586
0
    static const char *g_armv4_compatible_archs[] = {
587
0
        "armv4",
588
0
        "arm",
589
0
        "thumbv4t",
590
0
        "thumb",
591
0
    };
592
0
    return {g_armv4_compatible_archs};
593
83
  }
594
83
  }
595
0
  return {};
596
83
}
597
598
/// The architecture selection rules for arm processors These cpu subtypes have
599
/// distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f
600
/// processor.
601
void PlatformDarwin::ARMGetSupportedArchitectures(
602
83
    std::vector<ArchSpec> &archs, std::optional<llvm::Triple::OSType> os) {
603
83
  const ArchSpec system_arch = GetSystemArchitecture();
604
83
  const ArchSpec::Core system_core = system_arch.GetCore();
605
1.99k
  for (const char *arch : GetCompatibleArchs(system_core)) {
606
1.99k
    llvm::Triple triple;
607
1.99k
    triple.setArchName(arch);
608
1.99k
    triple.setVendor(llvm::Triple::VendorType::Apple);
609
1.99k
    if (os)
610
1.99k
      triple.setOS(*os);
611
1.99k
    archs.push_back(ArchSpec(triple));
612
1.99k
  }
613
83
}
614
615
0
static FileSpec GetXcodeSelectPath() {
616
0
  static FileSpec g_xcode_select_filespec;
617
618
0
  if (!g_xcode_select_filespec) {
619
0
    FileSpec xcode_select_cmd("/usr/bin/xcode-select");
620
0
    if (FileSystem::Instance().Exists(xcode_select_cmd)) {
621
0
      int exit_status = -1;
622
0
      int signo = -1;
623
0
      std::string command_output;
624
0
      Status status =
625
0
          Host::RunShellCommand("/usr/bin/xcode-select --print-path",
626
0
                                FileSpec(), // current working directory
627
0
                                &exit_status, &signo, &command_output,
628
0
                                std::chrono::seconds(2), // short timeout
629
0
                                false);                  // don't run in a shell
630
0
      if (status.Success() && exit_status == 0 && !command_output.empty()) {
631
0
        size_t first_non_newline = command_output.find_last_not_of("\r\n");
632
0
        if (first_non_newline != std::string::npos) {
633
0
          command_output.erase(first_non_newline + 1);
634
0
        }
635
0
        g_xcode_select_filespec = FileSpec(command_output);
636
0
      }
637
0
    }
638
0
  }
639
640
0
  return g_xcode_select_filespec;
641
0
}
642
643
1.08k
BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
644
1.08k
  BreakpointSP bp_sp;
645
1.08k
  static const char *g_bp_names[] = {
646
1.08k
      "start_wqthread", "_pthread_wqthread", "_pthread_start",
647
1.08k
  };
648
649
1.08k
  static const char *g_bp_modules[] = {"libsystem_c.dylib",
650
1.08k
                                       "libSystem.B.dylib"};
651
652
1.08k
  FileSpecList bp_modules;
653
3.24k
  for (size_t i = 0; i < std::size(g_bp_modules); 
i++2.16k
) {
654
2.16k
    const char *bp_module = g_bp_modules[i];
655
2.16k
    bp_modules.EmplaceBack(bp_module);
656
2.16k
  }
657
658
1.08k
  bool internal = true;
659
1.08k
  bool hardware = false;
660
1.08k
  LazyBool skip_prologue = eLazyBoolNo;
661
1.08k
  bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names,
662
1.08k
                                  std::size(g_bp_names), eFunctionNameTypeFull,
663
1.08k
                                  eLanguageTypeUnknown, 0, skip_prologue,
664
1.08k
                                  internal, hardware);
665
1.08k
  bp_sp->SetBreakpointKind("thread-creation");
666
667
1.08k
  return bp_sp;
668
1.08k
}
669
670
uint32_t
671
0
PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
672
0
  const FileSpec &shell = launch_info.GetShell();
673
0
  if (!shell)
674
0
    return 1;
675
676
0
  std::string shell_string = shell.GetPath();
677
0
  const char *shell_name = strrchr(shell_string.c_str(), '/');
678
0
  if (shell_name == nullptr)
679
0
    shell_name = shell_string.c_str();
680
0
  else
681
0
    shell_name++;
682
683
0
  if (strcmp(shell_name, "sh") == 0) {
684
    // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it
685
    // only does this if the COMMAND_MODE environment variable is set to
686
    // "legacy".
687
0
    if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy")
688
0
      return 2;
689
0
    return 1;
690
0
  } else if (strcmp(shell_name, "csh") == 0 ||
691
0
             strcmp(shell_name, "tcsh") == 0 ||
692
0
             strcmp(shell_name, "zsh") == 0) {
693
    // csh and tcsh always seem to re-exec themselves.
694
0
    return 2;
695
0
  } else
696
0
    return 1;
697
0
}
698
699
lldb::ProcessSP PlatformDarwin::DebugProcess(ProcessLaunchInfo &launch_info,
700
                                             Debugger &debugger, Target &target,
701
2.10k
                                             Status &error) {
702
2.10k
  ProcessSP process_sp;
703
704
2.10k
  if (IsHost()) {
705
    // We are going to hand this process off to debugserver which will be in
706
    // charge of setting the exit status.  However, we still need to reap it
707
    // from lldb. So, make sure we use a exit callback which does not set exit
708
    // status.
709
2.10k
    launch_info.SetMonitorProcessCallback(
710
2.10k
        &ProcessLaunchInfo::NoOpMonitorCallback);
711
2.10k
    process_sp = Platform::DebugProcess(launch_info, debugger, target, error);
712
2.10k
  } else {
713
1
    if (m_remote_platform_sp)
714
1
      process_sp = m_remote_platform_sp->DebugProcess(launch_info, debugger,
715
1
                                                      target, error);
716
0
    else
717
0
      error.SetErrorString("the platform is not currently connected");
718
1
  }
719
2.10k
  return process_sp;
720
2.10k
}
721
722
851
void PlatformDarwin::CalculateTrapHandlerSymbolNames() {
723
851
  m_trap_handlers.push_back(ConstString("_sigtramp"));
724
851
}
725
726
0
static FileSpec GetCommandLineToolsLibraryPath() {
727
0
  static FileSpec g_command_line_tools_filespec;
728
729
0
  if (!g_command_line_tools_filespec) {
730
0
    FileSpec command_line_tools_path(GetXcodeSelectPath());
731
0
    command_line_tools_path.AppendPathComponent("Library");
732
0
    if (FileSystem::Instance().Exists(command_line_tools_path)) {
733
0
      g_command_line_tools_filespec = command_line_tools_path;
734
0
    }
735
0
  }
736
737
0
  return g_command_line_tools_filespec;
738
0
}
739
740
FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
741
453
    void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
742
453
  SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
743
744
453
  FileSpec spec(path);
745
453
  if (XcodeSDK::SDKSupportsModules(enumerator_info->sdk_type, spec)) {
746
151
    enumerator_info->found_path = spec;
747
151
    return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
748
151
  }
749
750
302
  return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
751
453
}
752
753
FileSpec PlatformDarwin::FindSDKInXcodeForModules(XcodeSDK::Type sdk_type,
754
151
                                                  const FileSpec &sdks_spec) {
755
  // Look inside Xcode for the required installed iOS SDK version
756
757
151
  if (!FileSystem::Instance().IsDirectory(sdks_spec)) {
758
0
    return FileSpec();
759
0
  }
760
761
151
  const bool find_directories = true;
762
151
  const bool find_files = false;
763
151
  const bool find_other = true; // include symlinks
764
765
151
  SDKEnumeratorInfo enumerator_info;
766
767
151
  enumerator_info.sdk_type = sdk_type;
768
769
151
  FileSystem::Instance().EnumerateDirectory(
770
151
      sdks_spec.GetPath(), find_directories, find_files, find_other,
771
151
      DirectoryEnumerator, &enumerator_info);
772
773
151
  if (FileSystem::Instance().IsDirectory(enumerator_info.found_path))
774
151
    return enumerator_info.found_path;
775
0
  else
776
0
    return FileSpec();
777
151
}
778
779
151
FileSpec PlatformDarwin::GetSDKDirectoryForModules(XcodeSDK::Type sdk_type) {
780
151
  FileSpec sdks_spec = HostInfo::GetXcodeContentsDirectory();
781
151
  sdks_spec.AppendPathComponent("Developer");
782
151
  sdks_spec.AppendPathComponent("Platforms");
783
784
151
  switch (sdk_type) {
785
151
  case XcodeSDK::Type::MacOSX:
786
151
    sdks_spec.AppendPathComponent("MacOSX.platform");
787
151
    break;
788
0
  case XcodeSDK::Type::iPhoneSimulator:
789
0
    sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
790
0
    break;
791
0
  case XcodeSDK::Type::iPhoneOS:
792
0
    sdks_spec.AppendPathComponent("iPhoneOS.platform");
793
0
    break;
794
0
  case XcodeSDK::Type::WatchSimulator:
795
0
    sdks_spec.AppendPathComponent("WatchSimulator.platform");
796
0
    break;
797
0
  case XcodeSDK::Type::AppleTVSimulator:
798
0
    sdks_spec.AppendPathComponent("AppleTVSimulator.platform");
799
0
    break;
800
0
  default:
801
0
    llvm_unreachable("unsupported sdk");
802
151
  }
803
804
151
  sdks_spec.AppendPathComponent("Developer");
805
151
  sdks_spec.AppendPathComponent("SDKs");
806
807
151
  if (sdk_type == XcodeSDK::Type::MacOSX) {
808
151
    llvm::VersionTuple version = HostInfo::GetOSVersion();
809
810
151
    if (!version.empty()) {
811
151
      if (XcodeSDK::SDKSupportsModules(XcodeSDK::Type::MacOSX, version)) {
812
        // If the Xcode SDKs are not available then try to use the
813
        // Command Line Tools one which is only for MacOSX.
814
151
        if (!FileSystem::Instance().Exists(sdks_spec)) {
815
0
          sdks_spec = GetCommandLineToolsLibraryPath();
816
0
          sdks_spec.AppendPathComponent("SDKs");
817
0
        }
818
819
        // We slightly prefer the exact SDK for this machine.  See if it is
820
        // there.
821
822
151
        FileSpec native_sdk_spec = sdks_spec;
823
151
        StreamString native_sdk_name;
824
151
        native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(),
825
151
                               version.getMinor().value_or(0));
826
151
        native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
827
828
151
        if (FileSystem::Instance().Exists(native_sdk_spec)) {
829
0
          return native_sdk_spec;
830
0
        }
831
151
      }
832
151
    }
833
151
  }
834
835
151
  return FindSDKInXcodeForModules(sdk_type, sdks_spec);
836
151
}
837
838
std::tuple<llvm::VersionTuple, llvm::StringRef>
839
87
PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
840
87
  llvm::StringRef build;
841
87
  llvm::StringRef version_str;
842
87
  llvm::StringRef build_str;
843
87
  std::tie(version_str, build_str) = dir.split(' ');
844
87
  llvm::VersionTuple version;
845
87
  if (!version.tryParse(version_str) ||
846
87
      
build_str.empty()0
) {
847
87
    if (build_str.consume_front("(")) {
848
4
      size_t pos = build_str.find(')');
849
4
      build = build_str.slice(0, pos);
850
4
    }
851
87
  }
852
853
87
  return std::make_tuple(version, build);
854
87
}
855
856
llvm::Expected<StructuredData::DictionarySP>
857
6
PlatformDarwin::FetchExtendedCrashInformation(Process &process) {
858
6
  StructuredData::DictionarySP extended_crash_info =
859
6
      std::make_shared<StructuredData::Dictionary>();
860
861
6
  StructuredData::ArraySP annotations = ExtractCrashInfoAnnotations(process);
862
6
  if (annotations && annotations->GetSize())
863
4
    extended_crash_info->AddItem("Crash-Info Annotations", annotations);
864
865
6
  StructuredData::DictionarySP app_specific_info =
866
6
      ExtractAppSpecificInfo(process);
867
6
  if (app_specific_info && 
app_specific_info->GetSize()0
)
868
0
    extended_crash_info->AddItem("Application Specific Information",
869
0
                                 app_specific_info);
870
871
6
  return extended_crash_info->GetSize() ? 
extended_crash_info4
:
nullptr2
;
872
6
}
873
874
StructuredData::ArraySP
875
6
PlatformDarwin::ExtractCrashInfoAnnotations(Process &process) {
876
6
  Log *log = GetLog(LLDBLog::Process);
877
878
6
  ConstString section_name("__crash_info");
879
6
  Target &target = process.GetTarget();
880
6
  StructuredData::ArraySP array_sp = std::make_shared<StructuredData::Array>();
881
882
252
  for (ModuleSP module : target.GetImages().Modules()) {
883
252
    SectionList *sections = module->GetSectionList();
884
885
252
    std::string module_name = module->GetSpecificationDescription();
886
887
    // The DYDL module is skipped since it's always loaded when running the
888
    // binary.
889
252
    if (module_name == "/usr/lib/dyld")
890
6
      continue;
891
892
246
    if (!sections) {
893
0
      LLDB_LOG(log, "Module {0} doesn't have any section!", module_name);
894
0
      continue;
895
0
    }
896
897
246
    SectionSP crash_info = sections->FindSectionByName(section_name);
898
246
    if (!crash_info) {
899
156
      LLDB_LOG(log, "Module {0} doesn't have section {1}!", module_name,
900
156
               section_name);
901
156
      continue;
902
156
    }
903
904
90
    addr_t load_addr = crash_info->GetLoadBaseAddress(&target);
905
906
90
    if (load_addr == LLDB_INVALID_ADDRESS) {
907
0
      LLDB_LOG(log, "Module {0} has an invalid '{1}' section load address: {2}",
908
0
               module_name, section_name, load_addr);
909
0
      continue;
910
0
    }
911
912
90
    Status error;
913
90
    CrashInfoAnnotations annotations;
914
90
    size_t expected_size = sizeof(CrashInfoAnnotations);
915
90
    size_t bytes_read = process.ReadMemoryFromInferior(load_addr, &annotations,
916
90
                                                       expected_size, error);
917
918
90
    if (expected_size != bytes_read || error.Fail()) {
919
0
      LLDB_LOG(log, "Failed to read {0} section from memory in module {1}: {2}",
920
0
               section_name, module_name, error);
921
0
      continue;
922
0
    }
923
924
    // initial support added for version 5
925
90
    if (annotations.version < 5) {
926
0
      LLDB_LOG(log,
927
0
               "Annotation version lower than 5 unsupported! Module {0} has "
928
0
               "version {1} instead.",
929
0
               module_name, annotations.version);
930
0
      continue;
931
0
    }
932
933
90
    if (!annotations.message) {
934
82
      LLDB_LOG(log, "No message available for module {0}.", module_name);
935
82
      continue;
936
82
    }
937
938
8
    std::string message;
939
8
    bytes_read =
940
8
        process.ReadCStringFromMemory(annotations.message, message, error);
941
942
8
    if (message.empty() || bytes_read != message.size() || error.Fail()) {
943
0
      LLDB_LOG(log, "Failed to read the message from memory in module {0}: {1}",
944
0
               module_name, error);
945
0
      continue;
946
0
    }
947
948
    // Remove trailing newline from message
949
8
    if (message.back() == '\n')
950
4
      message.pop_back();
951
952
8
    if (!annotations.message2)
953
8
      LLDB_LOG(log, "No message2 available for module {0}.", module_name);
954
955
8
    std::string message2;
956
8
    bytes_read =
957
8
        process.ReadCStringFromMemory(annotations.message2, message2, error);
958
959
8
    if (!message2.empty() && 
bytes_read == message2.size()0
&&
error.Success()0
)
960
0
      if (message2.back() == '\n')
961
0
        message2.pop_back();
962
963
8
    StructuredData::DictionarySP entry_sp =
964
8
        std::make_shared<StructuredData::Dictionary>();
965
966
8
    entry_sp->AddStringItem("image", module->GetFileSpec().GetPath(false));
967
8
    entry_sp->AddStringItem("uuid", module->GetUUID().GetAsString());
968
8
    entry_sp->AddStringItem("message", message);
969
8
    entry_sp->AddStringItem("message2", message2);
970
8
    entry_sp->AddIntegerItem("abort-cause", annotations.abort_cause);
971
972
8
    array_sp->AddItem(entry_sp);
973
8
  }
974
975
6
  return array_sp;
976
6
}
977
978
StructuredData::DictionarySP
979
6
PlatformDarwin::ExtractAppSpecificInfo(Process &process) {
980
6
  StructuredData::DictionarySP metadata_sp = process.GetMetadata();
981
982
6
  if (!metadata_sp || 
!metadata_sp->GetSize()0
||
!metadata_sp->HasKey("asi")0
)
983
6
    return {};
984
985
0
  StructuredData::Dictionary *asi;
986
0
  if (!metadata_sp->GetValueForKeyAsDictionary("asi", asi))
987
0
    return {};
988
989
0
  StructuredData::DictionarySP dict_sp =
990
0
      std::make_shared<StructuredData::Dictionary>();
991
992
0
  auto flatten_asi_dict = [&dict_sp](llvm::StringRef key,
993
0
                                     StructuredData::Object *val) -> bool {
994
0
    if (!val)
995
0
      return false;
996
997
0
    StructuredData::Array *arr = val->GetAsArray();
998
0
    if (!arr || !arr->GetSize())
999
0
      return false;
1000
1001
0
    dict_sp->AddItem(key, arr->GetItemAtIndex(0));
1002
0
    return true;
1003
0
  };
1004
1005
0
  asi->ForEach(flatten_asi_dict);
1006
1007
0
  return dict_sp;
1008
0
}
1009
1010
void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
1011
1.23k
    Target *target, std::vector<std::string> &options, XcodeSDK::Type sdk_type) {
1012
1.23k
  const std::vector<std::string> apple_arguments = {
1013
1.23k
      "-x",       "objective-c++", "-fobjc-arc",
1014
1.23k
      "-fblocks", "-D_ISO646_H",   "-D__ISO646_H",
1015
1.23k
      "-fgnuc-version=4.2.1"};
1016
1017
1.23k
  options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
1018
1019
1.23k
  StreamString minimum_version_option;
1020
1.23k
  bool use_current_os_version = false;
1021
  // If the SDK type is for the host OS, use its version number.
1022
1.23k
  auto get_host_os = []() { return HostInfo::GetTargetTriple().getOS(); };
1023
1.23k
  switch (sdk_type) {
1024
1.23k
  case XcodeSDK::Type::MacOSX:
1025
1.23k
    use_current_os_version = get_host_os() == llvm::Triple::MacOSX;
1026
1.23k
    break;
1027
0
  case XcodeSDK::Type::iPhoneOS:
1028
0
    use_current_os_version = get_host_os() == llvm::Triple::IOS;
1029
0
    break;
1030
0
  case XcodeSDK::Type::AppleTVOS:
1031
0
    use_current_os_version = get_host_os() == llvm::Triple::TvOS;
1032
0
    break;
1033
0
  case XcodeSDK::Type::watchOS:
1034
0
    use_current_os_version = get_host_os() == llvm::Triple::WatchOS;
1035
0
    break;
1036
0
  default:
1037
0
    break;
1038
1.23k
  }
1039
1040
1.23k
  llvm::VersionTuple version;
1041
1.23k
  if (use_current_os_version)
1042
1.23k
    version = GetOSVersion();
1043
0
  else if (target) {
1044
    // Our OS doesn't match our executable so we need to get the min OS version
1045
    // from the object file
1046
0
    ModuleSP exe_module_sp = target->GetExecutableModule();
1047
0
    if (exe_module_sp) {
1048
0
      ObjectFile *object_file = exe_module_sp->GetObjectFile();
1049
0
      if (object_file)
1050
0
        version = object_file->GetMinimumOSVersion();
1051
0
    }
1052
0
  }
1053
  // Only add the version-min options if we got a version from somewhere
1054
1.23k
  if (!version.empty() && sdk_type != XcodeSDK::Type::Linux) {
1055
1.23k
#define OPTION(PREFIX, NAME, VAR, ...)                                         \
1056
3.95M
  llvm::StringRef opt_##VAR = NAME;                                            \
1057
3.95M
  (void)opt_##VAR;
1058
1.23k
#include "clang/Driver/Options.inc"
1059
1.23k
#undef OPTION
1060
1.23k
    minimum_version_option << '-';
1061
1.23k
    switch (sdk_type) {
1062
1.23k
    case XcodeSDK::Type::MacOSX:
1063
1.23k
      minimum_version_option << opt_mmacos_version_min_EQ;
1064
1.23k
      break;
1065
0
    case XcodeSDK::Type::iPhoneSimulator:
1066
0
      minimum_version_option << opt_mios_simulator_version_min_EQ;
1067
0
      break;
1068
0
    case XcodeSDK::Type::iPhoneOS:
1069
0
      minimum_version_option << opt_mios_version_min_EQ;
1070
0
      break;
1071
0
    case XcodeSDK::Type::AppleTVSimulator:
1072
0
      minimum_version_option << opt_mtvos_simulator_version_min_EQ;
1073
0
      break;
1074
0
    case XcodeSDK::Type::AppleTVOS:
1075
0
      minimum_version_option << opt_mtvos_version_min_EQ;
1076
0
      break;
1077
0
    case XcodeSDK::Type::WatchSimulator:
1078
0
      minimum_version_option << opt_mwatchos_simulator_version_min_EQ;
1079
0
      break;
1080
0
    case XcodeSDK::Type::watchOS:
1081
0
      minimum_version_option << opt_mwatchos_version_min_EQ;
1082
0
      break;
1083
0
    case XcodeSDK::Type::bridgeOS:
1084
0
    case XcodeSDK::Type::Linux:
1085
0
    case XcodeSDK::Type::unknown:
1086
0
      if (Log *log = GetLog(LLDBLog::Host)) {
1087
0
        XcodeSDK::Info info;
1088
0
        info.type = sdk_type;
1089
0
        LLDB_LOGF(log, "Clang modules on %s are not supported",
1090
0
                  XcodeSDK::GetCanonicalName(info).c_str());
1091
0
      }
1092
0
      return;
1093
1.23k
    }
1094
1.23k
    minimum_version_option << version.getAsString();
1095
1.23k
    options.emplace_back(std::string(minimum_version_option.GetString()));
1096
1.23k
  }
1097
1098
1.23k
  FileSpec sysroot_spec;
1099
1100
1.23k
  if (target) {
1101
1.23k
    if (ModuleSP exe_module_sp = target->GetExecutableModule()) {
1102
1.13k
      auto path_or_err = ResolveSDKPathFromDebugInfo(*exe_module_sp);
1103
1.13k
      if (path_or_err) {
1104
1.08k
        sysroot_spec = FileSpec(*path_or_err);
1105
1.08k
      } else {
1106
53
        LLDB_LOG_ERROR(GetLog(LLDBLog::Types | LLDBLog::Host),
1107
53
                       path_or_err.takeError(),
1108
53
                       "Failed to resolve SDK path: {0}");
1109
53
      }
1110
1.13k
    }
1111
1.23k
  }
1112
1113
1.23k
  if (!FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
1114
151
    std::lock_guard<std::mutex> guard(m_mutex);
1115
151
    sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1116
151
  }
1117
1118
1.23k
  if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
1119
1.23k
    options.push_back("-isysroot");
1120
1.23k
    options.push_back(sysroot_spec.GetPath());
1121
1.23k
  }
1122
1.23k
}
1123
1124
0
ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
1125
0
  if (basename.IsEmpty())
1126
0
    return basename;
1127
1128
0
  StreamString stream;
1129
0
  stream.Printf("lib%s.dylib", basename.GetCString());
1130
0
  return ConstString(stream.GetString());
1131
0
}
1132
1133
1.25k
llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) {
1134
1.25k
  if (process && 
GetPluginName().contains("-simulator")0
) {
1135
0
    lldb_private::ProcessInstanceInfo proc_info;
1136
0
    if (Host::GetProcessInfo(process->GetID(), proc_info)) {
1137
0
      const Environment &env = proc_info.GetEnvironment();
1138
1139
0
      llvm::VersionTuple result;
1140
0
      if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION")))
1141
0
        return result;
1142
1143
0
      std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH");
1144
0
      if (!dyld_root_path.empty()) {
1145
0
        dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1146
0
        ApplePropertyList system_version_plist(dyld_root_path.c_str());
1147
0
        std::string product_version;
1148
0
        if (system_version_plist.GetValueAsString("ProductVersion",
1149
0
                                                  product_version)) {
1150
0
          if (!result.tryParse(product_version))
1151
0
            return result;
1152
0
        }
1153
0
      }
1154
0
    }
1155
    // For simulator platforms, do NOT call back through
1156
    // Platform::GetOSVersion() as it might call Process::GetHostOSVersion()
1157
    // which we don't want as it will be incorrect
1158
0
    return llvm::VersionTuple();
1159
0
  }
1160
1161
1.25k
  return Platform::GetOSVersion(process);
1162
1.25k
}
1163
1164
0
lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
1165
  // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
1166
  // in with any executable directories that should be searched.
1167
0
  static std::vector<FileSpec> g_executable_dirs;
1168
1169
  // Find the global list of directories that we will search for executables
1170
  // once so we don't keep doing the work over and over.
1171
0
  static llvm::once_flag g_once_flag;
1172
0
  llvm::call_once(g_once_flag, []() {
1173
1174
    // When locating executables, trust the DEVELOPER_DIR first if it is set
1175
0
    FileSpec xcode_contents_dir = HostInfo::GetXcodeContentsDirectory();
1176
0
    if (xcode_contents_dir) {
1177
0
      FileSpec xcode_lldb_resources = xcode_contents_dir;
1178
0
      xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1179
0
      xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1180
0
      xcode_lldb_resources.AppendPathComponent("Resources");
1181
0
      if (FileSystem::Instance().Exists(xcode_lldb_resources)) {
1182
0
        FileSpec dir;
1183
0
        dir.SetDirectory(xcode_lldb_resources.GetPathAsConstString());
1184
0
        g_executable_dirs.push_back(dir);
1185
0
      }
1186
0
    }
1187
    // Xcode might not be installed so we also check for the Command Line Tools.
1188
0
    FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath();
1189
0
    if (command_line_tools_dir) {
1190
0
      FileSpec cmd_line_lldb_resources = command_line_tools_dir;
1191
0
      cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks");
1192
0
      cmd_line_lldb_resources.AppendPathComponent("LLDB.framework");
1193
0
      cmd_line_lldb_resources.AppendPathComponent("Resources");
1194
0
      if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) {
1195
0
        FileSpec dir;
1196
0
        dir.SetDirectory(cmd_line_lldb_resources.GetPathAsConstString());
1197
0
        g_executable_dirs.push_back(dir);
1198
0
      }
1199
0
    }
1200
0
  });
1201
1202
  // Now search the global list of executable directories for the executable we
1203
  // are looking for
1204
0
  for (const auto &executable_dir : g_executable_dirs) {
1205
0
    FileSpec executable_file;
1206
0
    executable_file.SetDirectory(executable_dir.GetDirectory());
1207
0
    executable_file.SetFilename(basename);
1208
0
    if (FileSystem::Instance().Exists(executable_file))
1209
0
      return executable_file;
1210
0
  }
1211
1212
0
  return FileSpec();
1213
0
}
1214
1215
lldb_private::Status
1216
2.10k
PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
1217
  // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if
1218
  // the OS_ACTIVITY_DT_MODE environment variable is set.  (It doesn't require
1219
  // any specific value; rather, it just needs to exist). We will set it here
1220
  // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set.  Xcode
1221
  // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
1222
  // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
1223
  // specifically want it unset.
1224
2.10k
  const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
1225
2.10k
  auto &env_vars = launch_info.GetEnvironment();
1226
2.10k
  if (!env_vars.count(disable_env_var)) {
1227
    // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get
1228
    // os_log and NSLog messages mirrored to the target process stderr.
1229
2.09k
    env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable");
1230
2.09k
  }
1231
1232
  // Let our parent class do the real launching.
1233
2.10k
  return PlatformPOSIX::LaunchProcess(launch_info);
1234
2.10k
}
1235
1236
lldb_private::Status PlatformDarwin::FindBundleBinaryInExecSearchPaths(
1237
    const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
1238
    const FileSpecList *module_search_paths_ptr,
1239
365
    llvm::SmallVectorImpl<ModuleSP> *old_modules, bool *did_create_ptr) {
1240
365
  const FileSpec &platform_file = module_spec.GetFileSpec();
1241
  // See if the file is present in any of the module_search_paths_ptr
1242
  // directories.
1243
365
  if (!module_sp && module_search_paths_ptr && platform_file) {
1244
    // create a vector of all the file / directory names in platform_file e.g.
1245
    // this might be
1246
    // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
1247
    //
1248
    // We'll need to look in the module_search_paths_ptr directories for both
1249
    // "UIFoundation" and "UIFoundation.framework" -- most likely the latter
1250
    // will be the one we find there.
1251
1252
360
    std::vector<llvm::StringRef> path_parts = platform_file.GetComponents();
1253
    // We want the components in reverse order.
1254
360
    std::reverse(path_parts.begin(), path_parts.end());
1255
360
    const size_t path_parts_size = path_parts.size();
1256
1257
360
    size_t num_module_search_paths = module_search_paths_ptr->GetSize();
1258
419
    for (size_t i = 0; i < num_module_search_paths; 
++i59
) {
1259
61
      Log *log_verbose = GetLog(LLDBLog::Host);
1260
61
      LLDB_LOGF(
1261
61
          log_verbose,
1262
61
          "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in "
1263
61
          "search-path %s",
1264
61
          module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
1265
      // Create a new FileSpec with this module_search_paths_ptr plus just the
1266
      // filename ("UIFoundation"), then the parent dir plus filename
1267
      // ("UIFoundation.framework/UIFoundation") etc - up to four names (to
1268
      // handle "Foo.framework/Contents/MacOS/Foo")
1269
1270
195
      for (size_t j = 0; j < 4 && 
j < path_parts_size - 1177
;
++j134
) {
1271
136
        FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
1272
1273
        // Add the components backwards.  For
1274
        // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts
1275
        // is
1276
        //   [0] UIFoundation
1277
        //   [1] UIFoundation.framework
1278
        //   [2] PrivateFrameworks
1279
        //
1280
        // and if 'j' is 2, we want to append path_parts[1] and then
1281
        // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the
1282
        // module_search_paths_ptr path.
1283
1284
437
        for (int k = j; k >= 0; 
--k301
) {
1285
301
          path_to_try.AppendPathComponent(path_parts[k]);
1286
301
        }
1287
1288
136
        if (FileSystem::Instance().Exists(path_to_try)) {
1289
2
          ModuleSpec new_module_spec(module_spec);
1290
2
          new_module_spec.GetFileSpec() = path_to_try;
1291
2
          Status new_error(
1292
2
              Platform::GetSharedModule(new_module_spec, process, module_sp,
1293
2
                                        nullptr, old_modules, did_create_ptr));
1294
1295
2
          if (module_sp) {
1296
2
            module_sp->SetPlatformFileSpec(path_to_try);
1297
2
            return new_error;
1298
2
          }
1299
2
        }
1300
136
      }
1301
61
    }
1302
360
  }
1303
363
  return Status();
1304
365
}
1305
1306
std::string PlatformDarwin::FindComponentInPath(llvm::StringRef path,
1307
5
                                                llvm::StringRef component) {
1308
5
  auto begin = llvm::sys::path::begin(path);
1309
5
  auto end = llvm::sys::path::end(path);
1310
21
  for (auto it = begin; it != end; 
++it16
) {
1311
20
    if (it->contains(component)) {
1312
4
      llvm::SmallString<128> buffer;
1313
4
      llvm::sys::path::append(buffer, begin, ++it,
1314
4
                              llvm::sys::path::Style::posix);
1315
4
      return buffer.str().str();
1316
4
    }
1317
20
  }
1318
1
  return {};
1319
5
}
1320
1321
0
FileSpec PlatformDarwin::GetCurrentToolchainDirectory() {
1322
0
  if (FileSpec fspec = HostInfo::GetShlibDir())
1323
0
    return FileSpec(FindComponentInPath(fspec.GetPath(), ".xctoolchain"));
1324
0
  return {};
1325
0
}
1326
1327
0
FileSpec PlatformDarwin::GetCurrentCommandLineToolsDirectory() {
1328
0
  if (FileSpec fspec = HostInfo::GetShlibDir())
1329
0
    return FileSpec(FindComponentInPath(fspec.GetPath(), "CommandLineTools"));
1330
0
  return {};
1331
0
}
1332
1333
0
llvm::Triple::OSType PlatformDarwin::GetHostOSType() {
1334
#if !defined(__APPLE__)
1335
  return llvm::Triple::MacOSX;
1336
#else
1337
0
#if TARGET_OS_OSX
1338
0
  return llvm::Triple::MacOSX;
1339
#elif TARGET_OS_IOS
1340
  return llvm::Triple::IOS;
1341
#elif TARGET_OS_WATCH
1342
  return llvm::Triple::WatchOS;
1343
#elif TARGET_OS_TV
1344
  return llvm::Triple::TvOS;
1345
#elif TARGET_OS_BRIDGE
1346
  return llvm::Triple::BridgeOS;
1347
#else
1348
#error "LLDB being compiled for an unrecognized Darwin OS"
1349
#endif
1350
0
#endif // __APPLE__
1351
0
}
1352
1353
llvm::Expected<std::pair<XcodeSDK, bool>>
1354
1.14k
PlatformDarwin::GetSDKPathFromDebugInfo(Module &module) {
1355
1.14k
  SymbolFile *sym_file = module.GetSymbolFile();
1356
1.14k
  if (!sym_file)
1357
0
    return llvm::createStringError(
1358
0
        llvm::inconvertibleErrorCode(),
1359
0
        llvm::formatv("No symbol file available for module '{0}'",
1360
0
                      module.GetFileSpec().GetFilename().AsCString("")));
1361
1362
1.14k
  bool found_public_sdk = false;
1363
1.14k
  bool found_internal_sdk = false;
1364
1.14k
  XcodeSDK merged_sdk;
1365
2.41k
  for (unsigned i = 0; i < sym_file->GetNumCompileUnits(); 
++i1.27k
) {
1366
1.27k
    if (auto cu_sp = sym_file->GetCompileUnitAtIndex(i)) {
1367
1.27k
      auto cu_sdk = sym_file->ParseXcodeSDK(*cu_sp);
1368
1.27k
      bool is_internal_sdk = cu_sdk.IsAppleInternalSDK();
1369
1.27k
      found_public_sdk |= !is_internal_sdk;
1370
1.27k
      found_internal_sdk |= is_internal_sdk;
1371
1372
1.27k
      merged_sdk.Merge(cu_sdk);
1373
1.27k
    }
1374
1.27k
  }
1375
1376
1.14k
  const bool found_mismatch = found_internal_sdk && 
found_public_sdk3
;
1377
1378
1.14k
  return std::pair{std::move(merged_sdk), found_mismatch};
1379
1.14k
}
1380
1381
llvm::Expected<std::string>
1382
1.13k
PlatformDarwin::ResolveSDKPathFromDebugInfo(Module &module) {
1383
1.13k
  auto sdk_or_err = GetSDKPathFromDebugInfo(module);
1384
1.13k
  if (!sdk_or_err)
1385
0
    return llvm::createStringError(
1386
0
        llvm::inconvertibleErrorCode(),
1387
0
        llvm::formatv("Failed to parse SDK path from debug-info: {0}",
1388
0
                      llvm::toString(sdk_or_err.takeError())));
1389
1390
1.13k
  auto [sdk, _] = std::move(*sdk_or_err);
1391
1392
1.13k
  auto path_or_err = HostInfo::GetSDKRoot(HostInfo::SDKOptions{sdk});
1393
1.13k
  if (!path_or_err)
1394
55
    return llvm::createStringError(
1395
55
        llvm::inconvertibleErrorCode(),
1396
55
        llvm::formatv("Error while searching for SDK (XcodeSDK '{0}'): {1}",
1397
55
                      sdk.GetString(),
1398
55
                      llvm::toString(path_or_err.takeError())));
1399
1400
1.08k
  return path_or_err->str();
1401
1.13k
}