1 //===-- PlatformDarwin.cpp --------------------------------------*- C++ -*-===//
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 <string.h>
12
13 #include <algorithm>
14 #include <memory>
15 #include <mutex>
16
17 #include "lldb/Breakpoint/BreakpointLocation.h"
18 #include "lldb/Breakpoint/BreakpointSite.h"
19 #include "lldb/Core/Debugger.h"
20 #include "lldb/Core/Module.h"
21 #include "lldb/Core/ModuleSpec.h"
22 #include "lldb/Host/Host.h"
23 #include "lldb/Host/HostInfo.h"
24 #include "lldb/Host/XML.h"
25 #include "lldb/Interpreter/CommandInterpreter.h"
26 #include "lldb/Symbol/LocateSymbolFile.h"
27 #include "lldb/Symbol/ObjectFile.h"
28 #include "lldb/Symbol/SymbolFile.h"
29 #include "lldb/Symbol/SymbolVendor.h"
30 #include "lldb/Target/Platform.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Target/Target.h"
33 #include "lldb/Utility/Log.h"
34 #include "lldb/Utility/ProcessInfo.h"
35 #include "lldb/Utility/Status.h"
36 #include "lldb/Utility/Timer.h"
37 #include "llvm/ADT/STLExtras.h"
38 #include "llvm/Support/FileSystem.h"
39 #include "llvm/Support/Threading.h"
40 #include "llvm/Support/VersionTuple.h"
41
42 #if defined(__APPLE__)
43 #include <TargetConditionals.h>
44 #endif
45
46 using namespace lldb;
47 using namespace lldb_private;
48
49 /// Default Constructor
PlatformDarwin(bool is_host)50 PlatformDarwin::PlatformDarwin(bool is_host)
51 : PlatformPOSIX(is_host), // This is the local host platform
52 m_developer_directory() {}
53
54 /// Destructor.
55 ///
56 /// The destructor is virtual since this class is designed to be
57 /// inherited from by the plug-in instance.
~PlatformDarwin()58 PlatformDarwin::~PlatformDarwin() {}
59
LocateExecutableScriptingResources(Target * target,Module & module,Stream * feedback_stream)60 FileSpecList PlatformDarwin::LocateExecutableScriptingResources(
61 Target *target, Module &module, Stream *feedback_stream) {
62 FileSpecList file_list;
63 if (target &&
64 target->GetDebugger().GetScriptLanguage() == eScriptLanguagePython) {
65 // NB some extensions might be meaningful and should not be stripped -
66 // "this.binary.file"
67 // should not lose ".file" but GetFileNameStrippingExtension() will do
68 // precisely that. Ideally, we should have a per-platform list of
69 // extensions (".exe", ".app", ".dSYM", ".framework") which should be
70 // stripped while leaving "this.binary.file" as-is.
71
72 FileSpec module_spec = module.GetFileSpec();
73
74 if (module_spec) {
75 if (SymbolFile *symfile = module.GetSymbolFile()) {
76 ObjectFile *objfile = symfile->GetObjectFile();
77 if (objfile) {
78 FileSpec symfile_spec(objfile->GetFileSpec());
79 if (symfile_spec &&
80 strcasestr(symfile_spec.GetPath().c_str(),
81 ".dSYM/Contents/Resources/DWARF") != nullptr &&
82 FileSystem::Instance().Exists(symfile_spec)) {
83 while (module_spec.GetFilename()) {
84 std::string module_basename(
85 module_spec.GetFilename().GetCString());
86 std::string original_module_basename(module_basename);
87
88 bool was_keyword = false;
89
90 // FIXME: for Python, we cannot allow certain characters in
91 // module
92 // filenames we import. Theoretically, different scripting
93 // languages may have different sets of forbidden tokens in
94 // filenames, and that should be dealt with by each
95 // ScriptInterpreter. For now, we just replace dots with
96 // underscores, but if we ever support anything other than
97 // Python we will need to rework this
98 std::replace(module_basename.begin(), module_basename.end(), '.',
99 '_');
100 std::replace(module_basename.begin(), module_basename.end(), ' ',
101 '_');
102 std::replace(module_basename.begin(), module_basename.end(), '-',
103 '_');
104 ScriptInterpreter *script_interpreter =
105 target->GetDebugger().GetScriptInterpreter();
106 if (script_interpreter &&
107 script_interpreter->IsReservedWord(module_basename.c_str())) {
108 module_basename.insert(module_basename.begin(), '_');
109 was_keyword = true;
110 }
111
112 StreamString path_string;
113 StreamString original_path_string;
114 // for OSX we are going to be in
115 // .dSYM/Contents/Resources/DWARF/<basename> let us go to
116 // .dSYM/Contents/Resources/Python/<basename>.py and see if the
117 // file exists
118 path_string.Printf("%s/../Python/%s.py",
119 symfile_spec.GetDirectory().GetCString(),
120 module_basename.c_str());
121 original_path_string.Printf(
122 "%s/../Python/%s.py",
123 symfile_spec.GetDirectory().GetCString(),
124 original_module_basename.c_str());
125 FileSpec script_fspec(path_string.GetString());
126 FileSystem::Instance().Resolve(script_fspec);
127 FileSpec orig_script_fspec(original_path_string.GetString());
128 FileSystem::Instance().Resolve(orig_script_fspec);
129
130 // if we did some replacements of reserved characters, and a
131 // file with the untampered name exists, then warn the user
132 // that the file as-is shall not be loaded
133 if (feedback_stream) {
134 if (module_basename != original_module_basename &&
135 FileSystem::Instance().Exists(orig_script_fspec)) {
136 const char *reason_for_complaint =
137 was_keyword ? "conflicts with a keyword"
138 : "contains reserved characters";
139 if (FileSystem::Instance().Exists(script_fspec))
140 feedback_stream->Printf(
141 "warning: the symbol file '%s' contains a debug "
142 "script. However, its name"
143 " '%s' %s and as such cannot be loaded. LLDB will"
144 " load '%s' instead. Consider removing the file with "
145 "the malformed name to"
146 " eliminate this warning.\n",
147 symfile_spec.GetPath().c_str(),
148 original_path_string.GetData(), reason_for_complaint,
149 path_string.GetData());
150 else
151 feedback_stream->Printf(
152 "warning: the symbol file '%s' contains a debug "
153 "script. However, its name"
154 " %s and as such cannot be loaded. If you intend"
155 " to have this script loaded, please rename '%s' to "
156 "'%s' and retry.\n",
157 symfile_spec.GetPath().c_str(), reason_for_complaint,
158 original_path_string.GetData(), path_string.GetData());
159 }
160 }
161
162 if (FileSystem::Instance().Exists(script_fspec)) {
163 file_list.Append(script_fspec);
164 break;
165 }
166
167 // If we didn't find the python file, then keep stripping the
168 // extensions and try again
169 ConstString filename_no_extension(
170 module_spec.GetFileNameStrippingExtension());
171 if (module_spec.GetFilename() == filename_no_extension)
172 break;
173
174 module_spec.GetFilename() = filename_no_extension;
175 }
176 }
177 }
178 }
179 }
180 }
181 return file_list;
182 }
183
ResolveSymbolFile(Target & target,const ModuleSpec & sym_spec,FileSpec & sym_file)184 Status PlatformDarwin::ResolveSymbolFile(Target &target,
185 const ModuleSpec &sym_spec,
186 FileSpec &sym_file) {
187 sym_file = sym_spec.GetSymbolFileSpec();
188 if (FileSystem::Instance().IsDirectory(sym_file)) {
189 sym_file = Symbols::FindSymbolFileInBundle(sym_file, sym_spec.GetUUIDPtr(),
190 sym_spec.GetArchitecturePtr());
191 }
192 return {};
193 }
194
195 static lldb_private::Status
MakeCacheFolderForFile(const FileSpec & module_cache_spec)196 MakeCacheFolderForFile(const FileSpec &module_cache_spec) {
197 FileSpec module_cache_folder =
198 module_cache_spec.CopyByRemovingLastPathComponent();
199 return llvm::sys::fs::create_directory(module_cache_folder.GetPath());
200 }
201
202 static lldb_private::Status
BringInRemoteFile(Platform * platform,const lldb_private::ModuleSpec & module_spec,const FileSpec & module_cache_spec)203 BringInRemoteFile(Platform *platform,
204 const lldb_private::ModuleSpec &module_spec,
205 const FileSpec &module_cache_spec) {
206 MakeCacheFolderForFile(module_cache_spec);
207 Status err = platform->GetFile(module_spec.GetFileSpec(), module_cache_spec);
208 return err;
209 }
210
GetSharedModuleWithLocalCache(const lldb_private::ModuleSpec & module_spec,lldb::ModuleSP & module_sp,const lldb_private::FileSpecList * module_search_paths_ptr,lldb::ModuleSP * old_module_sp_ptr,bool * did_create_ptr)211 lldb_private::Status PlatformDarwin::GetSharedModuleWithLocalCache(
212 const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp,
213 const lldb_private::FileSpecList *module_search_paths_ptr,
214 lldb::ModuleSP *old_module_sp_ptr, bool *did_create_ptr) {
215
216 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
217 LLDB_LOGF(log,
218 "[%s] Trying to find module %s/%s - platform path %s/%s symbol "
219 "path %s/%s",
220 (IsHost() ? "host" : "remote"),
221 module_spec.GetFileSpec().GetDirectory().AsCString(),
222 module_spec.GetFileSpec().GetFilename().AsCString(),
223 module_spec.GetPlatformFileSpec().GetDirectory().AsCString(),
224 module_spec.GetPlatformFileSpec().GetFilename().AsCString(),
225 module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),
226 module_spec.GetSymbolFileSpec().GetFilename().AsCString());
227
228 Status err;
229
230 err = ModuleList::GetSharedModule(module_spec, module_sp,
231 module_search_paths_ptr, old_module_sp_ptr,
232 did_create_ptr);
233 if (module_sp)
234 return err;
235
236 if (!IsHost()) {
237 std::string cache_path(GetLocalCacheDirectory());
238 // Only search for a locally cached file if we have a valid cache path
239 if (!cache_path.empty()) {
240 std::string module_path(module_spec.GetFileSpec().GetPath());
241 cache_path.append(module_path);
242 FileSpec module_cache_spec(cache_path);
243
244 // if rsync is supported, always bring in the file - rsync will be very
245 // efficient when files are the same on the local and remote end of the
246 // connection
247 if (this->GetSupportsRSync()) {
248 err = BringInRemoteFile(this, module_spec, module_cache_spec);
249 if (err.Fail())
250 return err;
251 if (FileSystem::Instance().Exists(module_cache_spec)) {
252 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
253 LLDB_LOGF(log, "[%s] module %s/%s was rsynced and is now there",
254 (IsHost() ? "host" : "remote"),
255 module_spec.GetFileSpec().GetDirectory().AsCString(),
256 module_spec.GetFileSpec().GetFilename().AsCString());
257 ModuleSpec local_spec(module_cache_spec,
258 module_spec.GetArchitecture());
259 module_sp = std::make_shared<Module>(local_spec);
260 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
261 return Status();
262 }
263 }
264
265 // try to find the module in the cache
266 if (FileSystem::Instance().Exists(module_cache_spec)) {
267 // get the local and remote MD5 and compare
268 if (m_remote_platform_sp) {
269 // when going over the *slow* GDB remote transfer mechanism we first
270 // check the hashes of the files - and only do the actual transfer if
271 // they differ
272 uint64_t high_local, high_remote, low_local, low_remote;
273 auto MD5 = llvm::sys::fs::md5_contents(module_cache_spec.GetPath());
274 if (!MD5)
275 return Status(MD5.getError());
276 std::tie(high_local, low_local) = MD5->words();
277
278 m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(),
279 low_remote, high_remote);
280 if (low_local != low_remote || high_local != high_remote) {
281 // bring in the remote file
282 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
283 LLDB_LOGF(log,
284 "[%s] module %s/%s needs to be replaced from remote copy",
285 (IsHost() ? "host" : "remote"),
286 module_spec.GetFileSpec().GetDirectory().AsCString(),
287 module_spec.GetFileSpec().GetFilename().AsCString());
288 Status err =
289 BringInRemoteFile(this, module_spec, module_cache_spec);
290 if (err.Fail())
291 return err;
292 }
293 }
294
295 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
296 module_sp = std::make_shared<Module>(local_spec);
297 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
298 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
299 LLDB_LOGF(log, "[%s] module %s/%s was found in the cache",
300 (IsHost() ? "host" : "remote"),
301 module_spec.GetFileSpec().GetDirectory().AsCString(),
302 module_spec.GetFileSpec().GetFilename().AsCString());
303 return Status();
304 }
305
306 // bring in the remote module file
307 LLDB_LOGF(log, "[%s] module %s/%s needs to come in remotely",
308 (IsHost() ? "host" : "remote"),
309 module_spec.GetFileSpec().GetDirectory().AsCString(),
310 module_spec.GetFileSpec().GetFilename().AsCString());
311 Status err = BringInRemoteFile(this, module_spec, module_cache_spec);
312 if (err.Fail())
313 return err;
314 if (FileSystem::Instance().Exists(module_cache_spec)) {
315 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
316 LLDB_LOGF(log, "[%s] module %s/%s is now cached and fine",
317 (IsHost() ? "host" : "remote"),
318 module_spec.GetFileSpec().GetDirectory().AsCString(),
319 module_spec.GetFileSpec().GetFilename().AsCString());
320 ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
321 module_sp = std::make_shared<Module>(local_spec);
322 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
323 return Status();
324 } else
325 return Status("unable to obtain valid module file");
326 } else
327 return Status("no cache path");
328 } else
329 return Status("unable to resolve module");
330 }
331
GetSharedModule(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,ModuleSP * old_module_sp_ptr,bool * did_create_ptr)332 Status PlatformDarwin::GetSharedModule(
333 const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
334 const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
335 bool *did_create_ptr) {
336 Status error;
337 module_sp.reset();
338
339 if (IsRemote()) {
340 // If we have a remote platform always, let it try and locate the shared
341 // module first.
342 if (m_remote_platform_sp) {
343 error = m_remote_platform_sp->GetSharedModule(
344 module_spec, process, module_sp, module_search_paths_ptr,
345 old_module_sp_ptr, did_create_ptr);
346 }
347 }
348
349 if (!module_sp) {
350 // Fall back to the local platform and find the file locally
351 error = Platform::GetSharedModule(module_spec, process, module_sp,
352 module_search_paths_ptr,
353 old_module_sp_ptr, did_create_ptr);
354
355 const FileSpec &platform_file = module_spec.GetFileSpec();
356 if (!module_sp && module_search_paths_ptr && platform_file) {
357 // We can try to pull off part of the file path up to the bundle
358 // directory level and try any module search paths...
359 FileSpec bundle_directory;
360 if (Host::GetBundleDirectory(platform_file, bundle_directory)) {
361 if (platform_file == bundle_directory) {
362 ModuleSpec new_module_spec(module_spec);
363 new_module_spec.GetFileSpec() = bundle_directory;
364 if (Host::ResolveExecutableInBundle(new_module_spec.GetFileSpec())) {
365 Status new_error(Platform::GetSharedModule(
366 new_module_spec, process, module_sp, nullptr, old_module_sp_ptr,
367 did_create_ptr));
368
369 if (module_sp)
370 return new_error;
371 }
372 } else {
373 char platform_path[PATH_MAX];
374 char bundle_dir[PATH_MAX];
375 platform_file.GetPath(platform_path, sizeof(platform_path));
376 const size_t bundle_directory_len =
377 bundle_directory.GetPath(bundle_dir, sizeof(bundle_dir));
378 char new_path[PATH_MAX];
379 size_t num_module_search_paths = module_search_paths_ptr->GetSize();
380 for (size_t i = 0; i < num_module_search_paths; ++i) {
381 const size_t search_path_len =
382 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath(
383 new_path, sizeof(new_path));
384 if (search_path_len < sizeof(new_path)) {
385 snprintf(new_path + search_path_len,
386 sizeof(new_path) - search_path_len, "/%s",
387 platform_path + bundle_directory_len);
388 FileSpec new_file_spec(new_path);
389 if (FileSystem::Instance().Exists(new_file_spec)) {
390 ModuleSpec new_module_spec(module_spec);
391 new_module_spec.GetFileSpec() = new_file_spec;
392 Status new_error(Platform::GetSharedModule(
393 new_module_spec, process, module_sp, nullptr,
394 old_module_sp_ptr, did_create_ptr));
395
396 if (module_sp) {
397 module_sp->SetPlatformFileSpec(new_file_spec);
398 return new_error;
399 }
400 }
401 }
402 }
403 }
404 }
405 }
406 }
407 if (module_sp)
408 module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
409 return error;
410 }
411
412 size_t
GetSoftwareBreakpointTrapOpcode(Target & target,BreakpointSite * bp_site)413 PlatformDarwin::GetSoftwareBreakpointTrapOpcode(Target &target,
414 BreakpointSite *bp_site) {
415 const uint8_t *trap_opcode = nullptr;
416 uint32_t trap_opcode_size = 0;
417 bool bp_is_thumb = false;
418
419 llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
420 switch (machine) {
421 case llvm::Triple::aarch64_32:
422 case llvm::Triple::aarch64: {
423 // 'brk #0' or 0xd4200000 in BE byte order
424 static const uint8_t g_arm64_breakpoint_opcode[] = {0x00, 0x00, 0x20, 0xD4};
425 trap_opcode = g_arm64_breakpoint_opcode;
426 trap_opcode_size = sizeof(g_arm64_breakpoint_opcode);
427 } break;
428
429 case llvm::Triple::thumb:
430 bp_is_thumb = true;
431 LLVM_FALLTHROUGH;
432 case llvm::Triple::arm: {
433 static const uint8_t g_arm_breakpoint_opcode[] = {0xFE, 0xDE, 0xFF, 0xE7};
434 static const uint8_t g_thumb_breakpooint_opcode[] = {0xFE, 0xDE};
435
436 // Auto detect arm/thumb if it wasn't explicitly specified
437 if (!bp_is_thumb) {
438 lldb::BreakpointLocationSP bp_loc_sp(bp_site->GetOwnerAtIndex(0));
439 if (bp_loc_sp)
440 bp_is_thumb = bp_loc_sp->GetAddress().GetAddressClass() ==
441 AddressClass::eCodeAlternateISA;
442 }
443 if (bp_is_thumb) {
444 trap_opcode = g_thumb_breakpooint_opcode;
445 trap_opcode_size = sizeof(g_thumb_breakpooint_opcode);
446 break;
447 }
448 trap_opcode = g_arm_breakpoint_opcode;
449 trap_opcode_size = sizeof(g_arm_breakpoint_opcode);
450 } break;
451
452 case llvm::Triple::ppc:
453 case llvm::Triple::ppc64: {
454 static const uint8_t g_ppc_breakpoint_opcode[] = {0x7F, 0xC0, 0x00, 0x08};
455 trap_opcode = g_ppc_breakpoint_opcode;
456 trap_opcode_size = sizeof(g_ppc_breakpoint_opcode);
457 } break;
458
459 default:
460 return Platform::GetSoftwareBreakpointTrapOpcode(target, bp_site);
461 }
462
463 if (trap_opcode && trap_opcode_size) {
464 if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
465 return trap_opcode_size;
466 }
467 return 0;
468 }
469
ModuleIsExcludedForUnconstrainedSearches(lldb_private::Target & target,const lldb::ModuleSP & module_sp)470 bool PlatformDarwin::ModuleIsExcludedForUnconstrainedSearches(
471 lldb_private::Target &target, const lldb::ModuleSP &module_sp) {
472 if (!module_sp)
473 return false;
474
475 ObjectFile *obj_file = module_sp->GetObjectFile();
476 if (!obj_file)
477 return false;
478
479 ObjectFile::Type obj_type = obj_file->GetType();
480 return obj_type == ObjectFile::eTypeDynamicLinker;
481 }
482
x86GetSupportedArchitectureAtIndex(uint32_t idx,ArchSpec & arch)483 bool PlatformDarwin::x86GetSupportedArchitectureAtIndex(uint32_t idx,
484 ArchSpec &arch) {
485 ArchSpec host_arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
486 if (host_arch.GetCore() == ArchSpec::eCore_x86_64_x86_64h) {
487 switch (idx) {
488 case 0:
489 arch = host_arch;
490 return true;
491
492 case 1:
493 arch.SetTriple("x86_64-apple-macosx");
494 return true;
495
496 case 2:
497 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
498 return true;
499
500 default:
501 return false;
502 }
503 } else {
504 if (idx == 0) {
505 arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
506 return arch.IsValid();
507 } else if (idx == 1) {
508 ArchSpec platform_arch(
509 HostInfo::GetArchitecture(HostInfo::eArchKindDefault));
510 ArchSpec platform_arch64(
511 HostInfo::GetArchitecture(HostInfo::eArchKind64));
512 if (platform_arch.IsExactMatch(platform_arch64)) {
513 // This macosx platform supports both 32 and 64 bit. Since we already
514 // returned the 64 bit arch for idx == 0, return the 32 bit arch for
515 // idx == 1
516 arch = HostInfo::GetArchitecture(HostInfo::eArchKind32);
517 return arch.IsValid();
518 }
519 }
520 }
521 return false;
522 }
523
524 // The architecture selection rules for arm processors These cpu subtypes have
525 // distinct names (e.g. armv7f) but armv7 binaries run fine on an armv7f
526 // processor.
527
ARMGetSupportedArchitectureAtIndex(uint32_t idx,ArchSpec & arch)528 bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex(uint32_t idx,
529 ArchSpec &arch) {
530 ArchSpec system_arch(GetSystemArchitecture());
531
532 // When lldb is running on a watch or tv, set the arch OS name appropriately.
533 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
534 #define OSNAME "tvos"
535 #elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
536 #define OSNAME "watchos"
537 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
538 #define OSNAME "bridgeos"
539 #else
540 #define OSNAME "ios"
541 #endif
542
543 const ArchSpec::Core system_core = system_arch.GetCore();
544 switch (system_core) {
545 default:
546 switch (idx) {
547 case 0:
548 arch.SetTriple("arm64-apple-" OSNAME);
549 return true;
550 case 1:
551 arch.SetTriple("armv7-apple-" OSNAME);
552 return true;
553 case 2:
554 arch.SetTriple("armv7f-apple-" OSNAME);
555 return true;
556 case 3:
557 arch.SetTriple("armv7k-apple-" OSNAME);
558 return true;
559 case 4:
560 arch.SetTriple("armv7s-apple-" OSNAME);
561 return true;
562 case 5:
563 arch.SetTriple("armv7m-apple-" OSNAME);
564 return true;
565 case 6:
566 arch.SetTriple("armv7em-apple-" OSNAME);
567 return true;
568 case 7:
569 arch.SetTriple("armv6m-apple-" OSNAME);
570 return true;
571 case 8:
572 arch.SetTriple("armv6-apple-" OSNAME);
573 return true;
574 case 9:
575 arch.SetTriple("armv5-apple-" OSNAME);
576 return true;
577 case 10:
578 arch.SetTriple("armv4-apple-" OSNAME);
579 return true;
580 case 11:
581 arch.SetTriple("arm-apple-" OSNAME);
582 return true;
583 case 12:
584 arch.SetTriple("thumbv7-apple-" OSNAME);
585 return true;
586 case 13:
587 arch.SetTriple("thumbv7f-apple-" OSNAME);
588 return true;
589 case 14:
590 arch.SetTriple("thumbv7k-apple-" OSNAME);
591 return true;
592 case 15:
593 arch.SetTriple("thumbv7s-apple-" OSNAME);
594 return true;
595 case 16:
596 arch.SetTriple("thumbv7m-apple-" OSNAME);
597 return true;
598 case 17:
599 arch.SetTriple("thumbv7em-apple-" OSNAME);
600 return true;
601 case 18:
602 arch.SetTriple("thumbv6m-apple-" OSNAME);
603 return true;
604 case 19:
605 arch.SetTriple("thumbv6-apple-" OSNAME);
606 return true;
607 case 20:
608 arch.SetTriple("thumbv5-apple-" OSNAME);
609 return true;
610 case 21:
611 arch.SetTriple("thumbv4t-apple-" OSNAME);
612 return true;
613 case 22:
614 arch.SetTriple("thumb-apple-" OSNAME);
615 return true;
616 default:
617 break;
618 }
619 break;
620
621 case ArchSpec::eCore_arm_arm64:
622 switch (idx) {
623 case 0:
624 arch.SetTriple("arm64-apple-" OSNAME);
625 return true;
626 case 1:
627 arch.SetTriple("armv7s-apple-" OSNAME);
628 return true;
629 case 2:
630 arch.SetTriple("armv7f-apple-" OSNAME);
631 return true;
632 case 3:
633 arch.SetTriple("armv7m-apple-" OSNAME);
634 return true;
635 case 4:
636 arch.SetTriple("armv7em-apple-" OSNAME);
637 return true;
638 case 5:
639 arch.SetTriple("armv7-apple-" OSNAME);
640 return true;
641 case 6:
642 arch.SetTriple("armv6m-apple-" OSNAME);
643 return true;
644 case 7:
645 arch.SetTriple("armv6-apple-" OSNAME);
646 return true;
647 case 8:
648 arch.SetTriple("armv5-apple-" OSNAME);
649 return true;
650 case 9:
651 arch.SetTriple("armv4-apple-" OSNAME);
652 return true;
653 case 10:
654 arch.SetTriple("arm-apple-" OSNAME);
655 return true;
656 case 11:
657 arch.SetTriple("thumbv7-apple-" OSNAME);
658 return true;
659 case 12:
660 arch.SetTriple("thumbv7f-apple-" OSNAME);
661 return true;
662 case 13:
663 arch.SetTriple("thumbv7k-apple-" OSNAME);
664 return true;
665 case 14:
666 arch.SetTriple("thumbv7s-apple-" OSNAME);
667 return true;
668 case 15:
669 arch.SetTriple("thumbv7m-apple-" OSNAME);
670 return true;
671 case 16:
672 arch.SetTriple("thumbv7em-apple-" OSNAME);
673 return true;
674 case 17:
675 arch.SetTriple("thumbv6m-apple-" OSNAME);
676 return true;
677 case 18:
678 arch.SetTriple("thumbv6-apple-" OSNAME);
679 return true;
680 case 19:
681 arch.SetTriple("thumbv5-apple-" OSNAME);
682 return true;
683 case 20:
684 arch.SetTriple("thumbv4t-apple-" OSNAME);
685 return true;
686 case 21:
687 arch.SetTriple("thumb-apple-" OSNAME);
688 return true;
689 default:
690 break;
691 }
692 break;
693
694 case ArchSpec::eCore_arm_armv7f:
695 switch (idx) {
696 case 0:
697 arch.SetTriple("armv7f-apple-" OSNAME);
698 return true;
699 case 1:
700 arch.SetTriple("armv7-apple-" OSNAME);
701 return true;
702 case 2:
703 arch.SetTriple("armv6m-apple-" OSNAME);
704 return true;
705 case 3:
706 arch.SetTriple("armv6-apple-" OSNAME);
707 return true;
708 case 4:
709 arch.SetTriple("armv5-apple-" OSNAME);
710 return true;
711 case 5:
712 arch.SetTriple("armv4-apple-" OSNAME);
713 return true;
714 case 6:
715 arch.SetTriple("arm-apple-" OSNAME);
716 return true;
717 case 7:
718 arch.SetTriple("thumbv7f-apple-" OSNAME);
719 return true;
720 case 8:
721 arch.SetTriple("thumbv7-apple-" OSNAME);
722 return true;
723 case 9:
724 arch.SetTriple("thumbv6m-apple-" OSNAME);
725 return true;
726 case 10:
727 arch.SetTriple("thumbv6-apple-" OSNAME);
728 return true;
729 case 11:
730 arch.SetTriple("thumbv5-apple-" OSNAME);
731 return true;
732 case 12:
733 arch.SetTriple("thumbv4t-apple-" OSNAME);
734 return true;
735 case 13:
736 arch.SetTriple("thumb-apple-" OSNAME);
737 return true;
738 default:
739 break;
740 }
741 break;
742
743 case ArchSpec::eCore_arm_armv7k:
744 switch (idx) {
745 case 0:
746 arch.SetTriple("armv7k-apple-" OSNAME);
747 return true;
748 case 1:
749 arch.SetTriple("armv7-apple-" OSNAME);
750 return true;
751 case 2:
752 arch.SetTriple("armv6m-apple-" OSNAME);
753 return true;
754 case 3:
755 arch.SetTriple("armv6-apple-" OSNAME);
756 return true;
757 case 4:
758 arch.SetTriple("armv5-apple-" OSNAME);
759 return true;
760 case 5:
761 arch.SetTriple("armv4-apple-" OSNAME);
762 return true;
763 case 6:
764 arch.SetTriple("arm-apple-" OSNAME);
765 return true;
766 case 7:
767 arch.SetTriple("thumbv7k-apple-" OSNAME);
768 return true;
769 case 8:
770 arch.SetTriple("thumbv7-apple-" OSNAME);
771 return true;
772 case 9:
773 arch.SetTriple("thumbv6m-apple-" OSNAME);
774 return true;
775 case 10:
776 arch.SetTriple("thumbv6-apple-" OSNAME);
777 return true;
778 case 11:
779 arch.SetTriple("thumbv5-apple-" OSNAME);
780 return true;
781 case 12:
782 arch.SetTriple("thumbv4t-apple-" OSNAME);
783 return true;
784 case 13:
785 arch.SetTriple("thumb-apple-" OSNAME);
786 return true;
787 default:
788 break;
789 }
790 break;
791
792 case ArchSpec::eCore_arm_armv7s:
793 switch (idx) {
794 case 0:
795 arch.SetTriple("armv7s-apple-" OSNAME);
796 return true;
797 case 1:
798 arch.SetTriple("armv7-apple-" OSNAME);
799 return true;
800 case 2:
801 arch.SetTriple("armv6m-apple-" OSNAME);
802 return true;
803 case 3:
804 arch.SetTriple("armv6-apple-" OSNAME);
805 return true;
806 case 4:
807 arch.SetTriple("armv5-apple-" OSNAME);
808 return true;
809 case 5:
810 arch.SetTriple("armv4-apple-" OSNAME);
811 return true;
812 case 6:
813 arch.SetTriple("arm-apple-" OSNAME);
814 return true;
815 case 7:
816 arch.SetTriple("thumbv7s-apple-" OSNAME);
817 return true;
818 case 8:
819 arch.SetTriple("thumbv7-apple-" OSNAME);
820 return true;
821 case 9:
822 arch.SetTriple("thumbv6m-apple-" OSNAME);
823 return true;
824 case 10:
825 arch.SetTriple("thumbv6-apple-" OSNAME);
826 return true;
827 case 11:
828 arch.SetTriple("thumbv5-apple-" OSNAME);
829 return true;
830 case 12:
831 arch.SetTriple("thumbv4t-apple-" OSNAME);
832 return true;
833 case 13:
834 arch.SetTriple("thumb-apple-" OSNAME);
835 return true;
836 default:
837 break;
838 }
839 break;
840
841 case ArchSpec::eCore_arm_armv7m:
842 switch (idx) {
843 case 0:
844 arch.SetTriple("armv7m-apple-" OSNAME);
845 return true;
846 case 1:
847 arch.SetTriple("armv7-apple-" OSNAME);
848 return true;
849 case 2:
850 arch.SetTriple("armv6m-apple-" OSNAME);
851 return true;
852 case 3:
853 arch.SetTriple("armv6-apple-" OSNAME);
854 return true;
855 case 4:
856 arch.SetTriple("armv5-apple-" OSNAME);
857 return true;
858 case 5:
859 arch.SetTriple("armv4-apple-" OSNAME);
860 return true;
861 case 6:
862 arch.SetTriple("arm-apple-" OSNAME);
863 return true;
864 case 7:
865 arch.SetTriple("thumbv7m-apple-" OSNAME);
866 return true;
867 case 8:
868 arch.SetTriple("thumbv7-apple-" OSNAME);
869 return true;
870 case 9:
871 arch.SetTriple("thumbv6m-apple-" OSNAME);
872 return true;
873 case 10:
874 arch.SetTriple("thumbv6-apple-" OSNAME);
875 return true;
876 case 11:
877 arch.SetTriple("thumbv5-apple-" OSNAME);
878 return true;
879 case 12:
880 arch.SetTriple("thumbv4t-apple-" OSNAME);
881 return true;
882 case 13:
883 arch.SetTriple("thumb-apple-" OSNAME);
884 return true;
885 default:
886 break;
887 }
888 break;
889
890 case ArchSpec::eCore_arm_armv7em:
891 switch (idx) {
892 case 0:
893 arch.SetTriple("armv7em-apple-" OSNAME);
894 return true;
895 case 1:
896 arch.SetTriple("armv7-apple-" OSNAME);
897 return true;
898 case 2:
899 arch.SetTriple("armv6m-apple-" OSNAME);
900 return true;
901 case 3:
902 arch.SetTriple("armv6-apple-" OSNAME);
903 return true;
904 case 4:
905 arch.SetTriple("armv5-apple-" OSNAME);
906 return true;
907 case 5:
908 arch.SetTriple("armv4-apple-" OSNAME);
909 return true;
910 case 6:
911 arch.SetTriple("arm-apple-" OSNAME);
912 return true;
913 case 7:
914 arch.SetTriple("thumbv7em-apple-" OSNAME);
915 return true;
916 case 8:
917 arch.SetTriple("thumbv7-apple-" OSNAME);
918 return true;
919 case 9:
920 arch.SetTriple("thumbv6m-apple-" OSNAME);
921 return true;
922 case 10:
923 arch.SetTriple("thumbv6-apple-" OSNAME);
924 return true;
925 case 11:
926 arch.SetTriple("thumbv5-apple-" OSNAME);
927 return true;
928 case 12:
929 arch.SetTriple("thumbv4t-apple-" OSNAME);
930 return true;
931 case 13:
932 arch.SetTriple("thumb-apple-" OSNAME);
933 return true;
934 default:
935 break;
936 }
937 break;
938
939 case ArchSpec::eCore_arm_armv7:
940 switch (idx) {
941 case 0:
942 arch.SetTriple("armv7-apple-" OSNAME);
943 return true;
944 case 1:
945 arch.SetTriple("armv6m-apple-" OSNAME);
946 return true;
947 case 2:
948 arch.SetTriple("armv6-apple-" OSNAME);
949 return true;
950 case 3:
951 arch.SetTriple("armv5-apple-" OSNAME);
952 return true;
953 case 4:
954 arch.SetTriple("armv4-apple-" OSNAME);
955 return true;
956 case 5:
957 arch.SetTriple("arm-apple-" OSNAME);
958 return true;
959 case 6:
960 arch.SetTriple("thumbv7-apple-" OSNAME);
961 return true;
962 case 7:
963 arch.SetTriple("thumbv6m-apple-" OSNAME);
964 return true;
965 case 8:
966 arch.SetTriple("thumbv6-apple-" OSNAME);
967 return true;
968 case 9:
969 arch.SetTriple("thumbv5-apple-" OSNAME);
970 return true;
971 case 10:
972 arch.SetTriple("thumbv4t-apple-" OSNAME);
973 return true;
974 case 11:
975 arch.SetTriple("thumb-apple-" OSNAME);
976 return true;
977 default:
978 break;
979 }
980 break;
981
982 case ArchSpec::eCore_arm_armv6m:
983 switch (idx) {
984 case 0:
985 arch.SetTriple("armv6m-apple-" OSNAME);
986 return true;
987 case 1:
988 arch.SetTriple("armv6-apple-" OSNAME);
989 return true;
990 case 2:
991 arch.SetTriple("armv5-apple-" OSNAME);
992 return true;
993 case 3:
994 arch.SetTriple("armv4-apple-" OSNAME);
995 return true;
996 case 4:
997 arch.SetTriple("arm-apple-" OSNAME);
998 return true;
999 case 5:
1000 arch.SetTriple("thumbv6m-apple-" OSNAME);
1001 return true;
1002 case 6:
1003 arch.SetTriple("thumbv6-apple-" OSNAME);
1004 return true;
1005 case 7:
1006 arch.SetTriple("thumbv5-apple-" OSNAME);
1007 return true;
1008 case 8:
1009 arch.SetTriple("thumbv4t-apple-" OSNAME);
1010 return true;
1011 case 9:
1012 arch.SetTriple("thumb-apple-" OSNAME);
1013 return true;
1014 default:
1015 break;
1016 }
1017 break;
1018
1019 case ArchSpec::eCore_arm_armv6:
1020 switch (idx) {
1021 case 0:
1022 arch.SetTriple("armv6-apple-" OSNAME);
1023 return true;
1024 case 1:
1025 arch.SetTriple("armv5-apple-" OSNAME);
1026 return true;
1027 case 2:
1028 arch.SetTriple("armv4-apple-" OSNAME);
1029 return true;
1030 case 3:
1031 arch.SetTriple("arm-apple-" OSNAME);
1032 return true;
1033 case 4:
1034 arch.SetTriple("thumbv6-apple-" OSNAME);
1035 return true;
1036 case 5:
1037 arch.SetTriple("thumbv5-apple-" OSNAME);
1038 return true;
1039 case 6:
1040 arch.SetTriple("thumbv4t-apple-" OSNAME);
1041 return true;
1042 case 7:
1043 arch.SetTriple("thumb-apple-" OSNAME);
1044 return true;
1045 default:
1046 break;
1047 }
1048 break;
1049
1050 case ArchSpec::eCore_arm_armv5:
1051 switch (idx) {
1052 case 0:
1053 arch.SetTriple("armv5-apple-" OSNAME);
1054 return true;
1055 case 1:
1056 arch.SetTriple("armv4-apple-" OSNAME);
1057 return true;
1058 case 2:
1059 arch.SetTriple("arm-apple-" OSNAME);
1060 return true;
1061 case 3:
1062 arch.SetTriple("thumbv5-apple-" OSNAME);
1063 return true;
1064 case 4:
1065 arch.SetTriple("thumbv4t-apple-" OSNAME);
1066 return true;
1067 case 5:
1068 arch.SetTriple("thumb-apple-" OSNAME);
1069 return true;
1070 default:
1071 break;
1072 }
1073 break;
1074
1075 case ArchSpec::eCore_arm_armv4:
1076 switch (idx) {
1077 case 0:
1078 arch.SetTriple("armv4-apple-" OSNAME);
1079 return true;
1080 case 1:
1081 arch.SetTriple("arm-apple-" OSNAME);
1082 return true;
1083 case 2:
1084 arch.SetTriple("thumbv4t-apple-" OSNAME);
1085 return true;
1086 case 3:
1087 arch.SetTriple("thumb-apple-" OSNAME);
1088 return true;
1089 default:
1090 break;
1091 }
1092 break;
1093 }
1094 arch.Clear();
1095 return false;
1096 }
1097
GetXcodeSelectPath()1098 static FileSpec GetXcodeSelectPath() {
1099 static FileSpec g_xcode_select_filespec;
1100
1101 if (!g_xcode_select_filespec) {
1102 FileSpec xcode_select_cmd("/usr/bin/xcode-select");
1103 if (FileSystem::Instance().Exists(xcode_select_cmd)) {
1104 int exit_status = -1;
1105 int signo = -1;
1106 std::string command_output;
1107 Status status =
1108 Host::RunShellCommand("/usr/bin/xcode-select --print-path",
1109 FileSpec(), // current working directory
1110 &exit_status, &signo, &command_output,
1111 std::chrono::seconds(2), // short timeout
1112 false); // don't run in a shell
1113 if (status.Success() && exit_status == 0 && !command_output.empty()) {
1114 size_t first_non_newline = command_output.find_last_not_of("\r\n");
1115 if (first_non_newline != std::string::npos) {
1116 command_output.erase(first_non_newline + 1);
1117 }
1118 g_xcode_select_filespec = FileSpec(command_output);
1119 }
1120 }
1121 }
1122
1123 return g_xcode_select_filespec;
1124 }
1125
1126 // Return a directory path like /Applications/Xcode.app/Contents/Developer
GetDeveloperDirectory()1127 const char *PlatformDarwin::GetDeveloperDirectory() {
1128 std::lock_guard<std::mutex> guard(m_mutex);
1129 if (m_developer_directory.empty()) {
1130 bool developer_dir_path_valid = false;
1131 char developer_dir_path[PATH_MAX];
1132
1133 // Get the lldb framework's file path, and if it exists, truncate some
1134 // components to only the developer directory path.
1135 FileSpec temp_file_spec = HostInfo::GetShlibDir();
1136 if (temp_file_spec) {
1137 if (temp_file_spec.GetPath(developer_dir_path,
1138 sizeof(developer_dir_path))) {
1139 // e.g.
1140 // /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework
1141 char *shared_frameworks =
1142 strstr(developer_dir_path, "/SharedFrameworks/LLDB.framework");
1143 if (shared_frameworks) {
1144 shared_frameworks[0] = '\0'; // truncate developer_dir_path at this point
1145 strncat (developer_dir_path, "/Developer", sizeof (developer_dir_path) - 1); // add /Developer on
1146 developer_dir_path_valid = true;
1147 } else {
1148 // e.g.
1149 // /Applications/Xcode.app/Contents/Developer/Toolchains/iOS11.2.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework
1150 char *developer_toolchains =
1151 strstr(developer_dir_path, "/Contents/Developer/Toolchains/");
1152 if (developer_toolchains) {
1153 developer_toolchains += sizeof ("/Contents/Developer") - 1;
1154 developer_toolchains[0] = '\0'; // truncate developer_dir_path at this point
1155 developer_dir_path_valid = true;
1156 }
1157 }
1158 }
1159 }
1160
1161 if (!developer_dir_path_valid) {
1162 std::string xcode_dir_path;
1163 const char *xcode_select_prefix_dir = getenv("XCODE_SELECT_PREFIX_DIR");
1164 if (xcode_select_prefix_dir)
1165 xcode_dir_path.append(xcode_select_prefix_dir);
1166 xcode_dir_path.append("/usr/share/xcode-select/xcode_dir_path");
1167 temp_file_spec.SetFile(xcode_dir_path, FileSpec::Style::native);
1168 auto dir_buffer =
1169 FileSystem::Instance().CreateDataBuffer(temp_file_spec.GetPath());
1170 if (dir_buffer && dir_buffer->GetByteSize() > 0) {
1171 llvm::StringRef path_ref(dir_buffer->GetChars());
1172 // Trim tailing newlines and make sure there is enough room for a null
1173 // terminator.
1174 path_ref =
1175 path_ref.rtrim("\r\n").take_front(sizeof(developer_dir_path) - 1);
1176 ::memcpy(developer_dir_path, path_ref.data(), path_ref.size());
1177 developer_dir_path[path_ref.size()] = '\0';
1178 developer_dir_path_valid = true;
1179 }
1180 }
1181
1182 if (!developer_dir_path_valid) {
1183 FileSpec devel_dir = GetXcodeSelectPath();
1184 if (FileSystem::Instance().IsDirectory(devel_dir)) {
1185 devel_dir.GetPath(&developer_dir_path[0], sizeof(developer_dir_path));
1186 developer_dir_path_valid = true;
1187 }
1188 }
1189
1190 if (developer_dir_path_valid) {
1191 temp_file_spec.SetFile(developer_dir_path, FileSpec::Style::native);
1192 if (FileSystem::Instance().Exists(temp_file_spec)) {
1193 m_developer_directory.assign(developer_dir_path);
1194 return m_developer_directory.c_str();
1195 }
1196 }
1197 // Assign a single NULL character so we know we tried to find the device
1198 // support directory and we don't keep trying to find it over and over.
1199 m_developer_directory.assign(1, '\0');
1200 }
1201
1202 // We should have put a single NULL character into m_developer_directory or
1203 // it should have a valid path if the code gets here
1204 assert(m_developer_directory.empty() == false);
1205 if (m_developer_directory[0])
1206 return m_developer_directory.c_str();
1207 return nullptr;
1208 }
1209
SetThreadCreationBreakpoint(Target & target)1210 BreakpointSP PlatformDarwin::SetThreadCreationBreakpoint(Target &target) {
1211 BreakpointSP bp_sp;
1212 static const char *g_bp_names[] = {
1213 "start_wqthread", "_pthread_wqthread", "_pthread_start",
1214 };
1215
1216 static const char *g_bp_modules[] = {"libsystem_c.dylib",
1217 "libSystem.B.dylib"};
1218
1219 FileSpecList bp_modules;
1220 for (size_t i = 0; i < llvm::array_lengthof(g_bp_modules); i++) {
1221 const char *bp_module = g_bp_modules[i];
1222 bp_modules.EmplaceBack(bp_module);
1223 }
1224
1225 bool internal = true;
1226 bool hardware = false;
1227 LazyBool skip_prologue = eLazyBoolNo;
1228 bp_sp = target.CreateBreakpoint(&bp_modules, nullptr, g_bp_names,
1229 llvm::array_lengthof(g_bp_names),
1230 eFunctionNameTypeFull, eLanguageTypeUnknown,
1231 0, skip_prologue, internal, hardware);
1232 bp_sp->SetBreakpointKind("thread-creation");
1233
1234 return bp_sp;
1235 }
1236
1237 int32_t
GetResumeCountForLaunchInfo(ProcessLaunchInfo & launch_info)1238 PlatformDarwin::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) {
1239 const FileSpec &shell = launch_info.GetShell();
1240 if (!shell)
1241 return 1;
1242
1243 std::string shell_string = shell.GetPath();
1244 const char *shell_name = strrchr(shell_string.c_str(), '/');
1245 if (shell_name == nullptr)
1246 shell_name = shell_string.c_str();
1247 else
1248 shell_name++;
1249
1250 if (strcmp(shell_name, "sh") == 0) {
1251 // /bin/sh re-exec's itself as /bin/bash requiring another resume. But it
1252 // only does this if the COMMAND_MODE environment variable is set to
1253 // "legacy".
1254 if (launch_info.GetEnvironment().lookup("COMMAND_MODE") == "legacy")
1255 return 2;
1256 return 1;
1257 } else if (strcmp(shell_name, "csh") == 0 ||
1258 strcmp(shell_name, "tcsh") == 0 ||
1259 strcmp(shell_name, "zsh") == 0) {
1260 // csh and tcsh always seem to re-exec themselves.
1261 return 2;
1262 } else
1263 return 1;
1264 }
1265
CalculateTrapHandlerSymbolNames()1266 void PlatformDarwin::CalculateTrapHandlerSymbolNames() {
1267 m_trap_handlers.push_back(ConstString("_sigtramp"));
1268 }
1269
1270 static const char *const sdk_strings[] = {
1271 "MacOSX", "iPhoneSimulator", "iPhoneOS",
1272 };
1273
CheckPathForXcode(const FileSpec & fspec)1274 static FileSpec CheckPathForXcode(const FileSpec &fspec) {
1275 if (FileSystem::Instance().Exists(fspec)) {
1276 const char substr[] = ".app/Contents";
1277
1278 std::string path_to_shlib = fspec.GetPath();
1279 size_t pos = path_to_shlib.rfind(substr);
1280 if (pos != std::string::npos) {
1281 path_to_shlib.erase(pos + strlen(substr));
1282 FileSpec ret(path_to_shlib);
1283
1284 FileSpec xcode_binary_path = ret;
1285 xcode_binary_path.AppendPathComponent("MacOS");
1286 xcode_binary_path.AppendPathComponent("Xcode");
1287
1288 if (FileSystem::Instance().Exists(xcode_binary_path)) {
1289 return ret;
1290 }
1291 }
1292 }
1293 return FileSpec();
1294 }
1295
GetXcodeContentsPath()1296 static FileSpec GetXcodeContentsPath() {
1297 static FileSpec g_xcode_filespec;
1298 static llvm::once_flag g_once_flag;
1299 llvm::call_once(g_once_flag, []() {
1300
1301 FileSpec fspec;
1302
1303 // First get the program file spec. If lldb.so or LLDB.framework is running
1304 // in a program and that program is Xcode, the path returned with be the
1305 // path to Xcode.app/Contents/MacOS/Xcode, so this will be the correct
1306 // Xcode to use.
1307 fspec = HostInfo::GetProgramFileSpec();
1308
1309 if (fspec) {
1310 // Ignore the current binary if it is python.
1311 std::string basename_lower = fspec.GetFilename().GetCString();
1312 std::transform(basename_lower.begin(), basename_lower.end(),
1313 basename_lower.begin(), tolower);
1314 if (basename_lower != "python") {
1315 g_xcode_filespec = CheckPathForXcode(fspec);
1316 }
1317 }
1318
1319 // Next check DEVELOPER_DIR environment variable
1320 if (!g_xcode_filespec) {
1321 const char *developer_dir_env_var = getenv("DEVELOPER_DIR");
1322 if (developer_dir_env_var && developer_dir_env_var[0]) {
1323 FileSpec developer_dir_spec = FileSpec(developer_dir_env_var);
1324 FileSystem::Instance().Resolve(developer_dir_spec);
1325 g_xcode_filespec = CheckPathForXcode(developer_dir_spec);
1326 }
1327
1328 // Fall back to using "xcode-select" to find the selected Xcode
1329 if (!g_xcode_filespec) {
1330 FileSpec xcode_select_path(GetXcodeSelectPath());
1331 xcode_select_path.RemoveLastPathComponent();
1332 g_xcode_filespec = CheckPathForXcode(xcode_select_path);
1333 }
1334 }
1335 });
1336
1337 return g_xcode_filespec;
1338 }
1339
GetCommandLineToolsLibraryPath()1340 static FileSpec GetCommandLineToolsLibraryPath() {
1341 static FileSpec g_command_line_tools_filespec;
1342
1343 if (!g_command_line_tools_filespec) {
1344 FileSpec command_line_tools_path(GetXcodeSelectPath());
1345 command_line_tools_path.AppendPathComponent("Library");
1346 if (FileSystem::Instance().Exists(command_line_tools_path)) {
1347 g_command_line_tools_filespec = command_line_tools_path;
1348 }
1349 }
1350
1351 return g_command_line_tools_filespec;
1352 }
1353
SDKSupportsModules(SDKType sdk_type,llvm::VersionTuple version)1354 bool PlatformDarwin::SDKSupportsModules(SDKType sdk_type,
1355 llvm::VersionTuple version) {
1356 switch (sdk_type) {
1357 case SDKType::MacOSX:
1358 return version >= llvm::VersionTuple(10, 10);
1359 case SDKType::iPhoneOS:
1360 case SDKType::iPhoneSimulator:
1361 return version >= llvm::VersionTuple(8);
1362 }
1363
1364 return false;
1365 }
1366
SDKSupportsModules(SDKType desired_type,const FileSpec & sdk_path)1367 bool PlatformDarwin::SDKSupportsModules(SDKType desired_type,
1368 const FileSpec &sdk_path) {
1369 ConstString last_path_component = sdk_path.GetLastPathComponent();
1370
1371 if (last_path_component) {
1372 const llvm::StringRef sdk_name = last_path_component.GetStringRef();
1373
1374 if (!sdk_name.startswith(sdk_strings[desired_type]))
1375 return false;
1376 auto version_part =
1377 sdk_name.drop_front(strlen(sdk_strings[desired_type]));
1378 version_part.consume_back(".sdk");
1379
1380 llvm::VersionTuple version;
1381 if (version.tryParse(version_part))
1382 return false;
1383 return SDKSupportsModules(desired_type, version);
1384 }
1385
1386 return false;
1387 }
1388
DirectoryEnumerator(void * baton,llvm::sys::fs::file_type file_type,llvm::StringRef path)1389 FileSystem::EnumerateDirectoryResult PlatformDarwin::DirectoryEnumerator(
1390 void *baton, llvm::sys::fs::file_type file_type, llvm::StringRef path) {
1391 SDKEnumeratorInfo *enumerator_info = static_cast<SDKEnumeratorInfo *>(baton);
1392
1393 FileSpec spec(path);
1394 if (SDKSupportsModules(enumerator_info->sdk_type, spec)) {
1395 enumerator_info->found_path = spec;
1396 return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1397 }
1398
1399 return FileSystem::EnumerateDirectoryResult::eEnumerateDirectoryResultNext;
1400 }
1401
FindSDKInXcodeForModules(SDKType sdk_type,const FileSpec & sdks_spec)1402 FileSpec PlatformDarwin::FindSDKInXcodeForModules(SDKType sdk_type,
1403 const FileSpec &sdks_spec) {
1404 // Look inside Xcode for the required installed iOS SDK version
1405
1406 if (!FileSystem::Instance().IsDirectory(sdks_spec)) {
1407 return FileSpec();
1408 }
1409
1410 const bool find_directories = true;
1411 const bool find_files = false;
1412 const bool find_other = true; // include symlinks
1413
1414 SDKEnumeratorInfo enumerator_info;
1415
1416 enumerator_info.sdk_type = sdk_type;
1417
1418 FileSystem::Instance().EnumerateDirectory(
1419 sdks_spec.GetPath(), find_directories, find_files, find_other,
1420 DirectoryEnumerator, &enumerator_info);
1421
1422 if (FileSystem::Instance().IsDirectory(enumerator_info.found_path))
1423 return enumerator_info.found_path;
1424 else
1425 return FileSpec();
1426 }
1427
GetSDKDirectoryForModules(SDKType sdk_type)1428 FileSpec PlatformDarwin::GetSDKDirectoryForModules(SDKType sdk_type) {
1429 switch (sdk_type) {
1430 case SDKType::MacOSX:
1431 case SDKType::iPhoneSimulator:
1432 case SDKType::iPhoneOS:
1433 break;
1434 }
1435
1436 FileSpec sdks_spec = GetXcodeContentsPath();
1437 sdks_spec.AppendPathComponent("Developer");
1438 sdks_spec.AppendPathComponent("Platforms");
1439
1440 switch (sdk_type) {
1441 case SDKType::MacOSX:
1442 sdks_spec.AppendPathComponent("MacOSX.platform");
1443 break;
1444 case SDKType::iPhoneSimulator:
1445 sdks_spec.AppendPathComponent("iPhoneSimulator.platform");
1446 break;
1447 case SDKType::iPhoneOS:
1448 sdks_spec.AppendPathComponent("iPhoneOS.platform");
1449 break;
1450 }
1451
1452 sdks_spec.AppendPathComponent("Developer");
1453 sdks_spec.AppendPathComponent("SDKs");
1454
1455 if (sdk_type == SDKType::MacOSX) {
1456 llvm::VersionTuple version = HostInfo::GetOSVersion();
1457
1458 if (!version.empty()) {
1459 if (SDKSupportsModules(SDKType::MacOSX, version)) {
1460 // If the Xcode SDKs are not available then try to use the
1461 // Command Line Tools one which is only for MacOSX.
1462 if (!FileSystem::Instance().Exists(sdks_spec)) {
1463 sdks_spec = GetCommandLineToolsLibraryPath();
1464 sdks_spec.AppendPathComponent("SDKs");
1465 }
1466
1467 // We slightly prefer the exact SDK for this machine. See if it is
1468 // there.
1469
1470 FileSpec native_sdk_spec = sdks_spec;
1471 StreamString native_sdk_name;
1472 native_sdk_name.Printf("MacOSX%u.%u.sdk", version.getMajor(),
1473 version.getMinor().getValueOr(0));
1474 native_sdk_spec.AppendPathComponent(native_sdk_name.GetString());
1475
1476 if (FileSystem::Instance().Exists(native_sdk_spec)) {
1477 return native_sdk_spec;
1478 }
1479 }
1480 }
1481 }
1482
1483 return FindSDKInXcodeForModules(sdk_type, sdks_spec);
1484 }
1485
1486 std::tuple<llvm::VersionTuple, llvm::StringRef>
ParseVersionBuildDir(llvm::StringRef dir)1487 PlatformDarwin::ParseVersionBuildDir(llvm::StringRef dir) {
1488 llvm::StringRef build;
1489 llvm::StringRef version_str;
1490 llvm::StringRef build_str;
1491 std::tie(version_str, build_str) = dir.split(' ');
1492 llvm::VersionTuple version;
1493 if (!version.tryParse(version_str) ||
1494 build_str.empty()) {
1495 if (build_str.consume_front("(")) {
1496 size_t pos = build_str.find(')');
1497 build = build_str.slice(0, pos);
1498 }
1499 }
1500
1501 return std::make_tuple(version, build);
1502 }
1503
AddClangModuleCompilationOptionsForSDKType(Target * target,std::vector<std::string> & options,SDKType sdk_type)1504 void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
1505 Target *target, std::vector<std::string> &options, SDKType sdk_type) {
1506 const std::vector<std::string> apple_arguments = {
1507 "-x", "objective-c++", "-fobjc-arc",
1508 "-fblocks", "-D_ISO646_H", "-D__ISO646_H",
1509 "-fgnuc-version=4.2.1"};
1510
1511 options.insert(options.end(), apple_arguments.begin(), apple_arguments.end());
1512
1513 StreamString minimum_version_option;
1514 bool use_current_os_version = false;
1515 switch (sdk_type) {
1516 case SDKType::iPhoneOS:
1517 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
1518 use_current_os_version = true;
1519 #else
1520 use_current_os_version = false;
1521 #endif
1522 break;
1523
1524 case SDKType::iPhoneSimulator:
1525 use_current_os_version = false;
1526 break;
1527
1528 case SDKType::MacOSX:
1529 #if defined(__i386__) || defined(__x86_64__)
1530 use_current_os_version = true;
1531 #else
1532 use_current_os_version = false;
1533 #endif
1534 break;
1535 }
1536
1537 llvm::VersionTuple version;
1538 if (use_current_os_version)
1539 version = GetOSVersion();
1540 else if (target) {
1541 // Our OS doesn't match our executable so we need to get the min OS version
1542 // from the object file
1543 ModuleSP exe_module_sp = target->GetExecutableModule();
1544 if (exe_module_sp) {
1545 ObjectFile *object_file = exe_module_sp->GetObjectFile();
1546 if (object_file)
1547 version = object_file->GetMinimumOSVersion();
1548 }
1549 }
1550 // Only add the version-min options if we got a version from somewhere
1551 if (!version.empty()) {
1552 switch (sdk_type) {
1553 case SDKType::iPhoneOS:
1554 minimum_version_option.PutCString("-mios-version-min=");
1555 minimum_version_option.PutCString(version.getAsString());
1556 break;
1557 case SDKType::iPhoneSimulator:
1558 minimum_version_option.PutCString("-mios-simulator-version-min=");
1559 minimum_version_option.PutCString(version.getAsString());
1560 break;
1561 case SDKType::MacOSX:
1562 minimum_version_option.PutCString("-mmacosx-version-min=");
1563 minimum_version_option.PutCString(version.getAsString());
1564 }
1565 options.push_back(minimum_version_option.GetString());
1566 }
1567
1568 FileSpec sysroot_spec;
1569 // Scope for mutex locker below
1570 {
1571 std::lock_guard<std::mutex> guard(m_mutex);
1572 sysroot_spec = GetSDKDirectoryForModules(sdk_type);
1573 }
1574
1575 if (FileSystem::Instance().IsDirectory(sysroot_spec.GetPath())) {
1576 options.push_back("-isysroot");
1577 options.push_back(sysroot_spec.GetPath());
1578 }
1579 }
1580
GetFullNameForDylib(ConstString basename)1581 ConstString PlatformDarwin::GetFullNameForDylib(ConstString basename) {
1582 if (basename.IsEmpty())
1583 return basename;
1584
1585 StreamString stream;
1586 stream.Printf("lib%s.dylib", basename.GetCString());
1587 return ConstString(stream.GetString());
1588 }
1589
GetOSVersion(Process * process)1590 llvm::VersionTuple PlatformDarwin::GetOSVersion(Process *process) {
1591 if (process && strstr(GetPluginName().GetCString(), "-simulator")) {
1592 lldb_private::ProcessInstanceInfo proc_info;
1593 if (Host::GetProcessInfo(process->GetID(), proc_info)) {
1594 const Environment &env = proc_info.GetEnvironment();
1595
1596 llvm::VersionTuple result;
1597 if (!result.tryParse(env.lookup("SIMULATOR_RUNTIME_VERSION")))
1598 return result;
1599
1600 std::string dyld_root_path = env.lookup("DYLD_ROOT_PATH");
1601 if (!dyld_root_path.empty()) {
1602 dyld_root_path += "/System/Library/CoreServices/SystemVersion.plist";
1603 ApplePropertyList system_version_plist(dyld_root_path.c_str());
1604 std::string product_version;
1605 if (system_version_plist.GetValueAsString("ProductVersion",
1606 product_version)) {
1607 if (!result.tryParse(product_version))
1608 return result;
1609 }
1610 }
1611 }
1612 // For simulator platforms, do NOT call back through
1613 // Platform::GetOSVersion() as it might call Process::GetHostOSVersion()
1614 // which we don't want as it will be incorrect
1615 return llvm::VersionTuple();
1616 }
1617
1618 return Platform::GetOSVersion(process);
1619 }
1620
LocateExecutable(const char * basename)1621 lldb_private::FileSpec PlatformDarwin::LocateExecutable(const char *basename) {
1622 // A collection of SBFileSpec whose SBFileSpec.m_directory members are filled
1623 // in with
1624 // any executable directories that should be searched.
1625 static std::vector<FileSpec> g_executable_dirs;
1626
1627 // Find the global list of directories that we will search for executables
1628 // once so we don't keep doing the work over and over.
1629 static llvm::once_flag g_once_flag;
1630 llvm::call_once(g_once_flag, []() {
1631
1632 // When locating executables, trust the DEVELOPER_DIR first if it is set
1633 FileSpec xcode_contents_dir = GetXcodeContentsPath();
1634 if (xcode_contents_dir) {
1635 FileSpec xcode_lldb_resources = xcode_contents_dir;
1636 xcode_lldb_resources.AppendPathComponent("SharedFrameworks");
1637 xcode_lldb_resources.AppendPathComponent("LLDB.framework");
1638 xcode_lldb_resources.AppendPathComponent("Resources");
1639 if (FileSystem::Instance().Exists(xcode_lldb_resources)) {
1640 FileSpec dir;
1641 dir.GetDirectory().SetCString(xcode_lldb_resources.GetPath().c_str());
1642 g_executable_dirs.push_back(dir);
1643 }
1644 }
1645 // Xcode might not be installed so we also check for the Command Line Tools.
1646 FileSpec command_line_tools_dir = GetCommandLineToolsLibraryPath();
1647 if (command_line_tools_dir) {
1648 FileSpec cmd_line_lldb_resources = command_line_tools_dir;
1649 cmd_line_lldb_resources.AppendPathComponent("PrivateFrameworks");
1650 cmd_line_lldb_resources.AppendPathComponent("LLDB.framework");
1651 cmd_line_lldb_resources.AppendPathComponent("Resources");
1652 if (FileSystem::Instance().Exists(cmd_line_lldb_resources)) {
1653 FileSpec dir;
1654 dir.GetDirectory().SetCString(
1655 cmd_line_lldb_resources.GetPath().c_str());
1656 g_executable_dirs.push_back(dir);
1657 }
1658 }
1659 });
1660
1661 // Now search the global list of executable directories for the executable we
1662 // are looking for
1663 for (const auto &executable_dir : g_executable_dirs) {
1664 FileSpec executable_file;
1665 executable_file.GetDirectory() = executable_dir.GetDirectory();
1666 executable_file.GetFilename().SetCString(basename);
1667 if (FileSystem::Instance().Exists(executable_file))
1668 return executable_file;
1669 }
1670
1671 return FileSpec();
1672 }
1673
1674 lldb_private::Status
LaunchProcess(lldb_private::ProcessLaunchInfo & launch_info)1675 PlatformDarwin::LaunchProcess(lldb_private::ProcessLaunchInfo &launch_info) {
1676 // Starting in Fall 2016 OSes, NSLog messages only get mirrored to stderr if
1677 // the OS_ACTIVITY_DT_MODE environment variable is set. (It doesn't require
1678 // any specific value; rather, it just needs to exist). We will set it here
1679 // as long as the IDE_DISABLED_OS_ACTIVITY_DT_MODE flag is not set. Xcode
1680 // makes use of IDE_DISABLED_OS_ACTIVITY_DT_MODE to tell
1681 // LLDB *not* to muck with the OS_ACTIVITY_DT_MODE flag when they
1682 // specifically want it unset.
1683 const char *disable_env_var = "IDE_DISABLED_OS_ACTIVITY_DT_MODE";
1684 auto &env_vars = launch_info.GetEnvironment();
1685 if (!env_vars.count(disable_env_var)) {
1686 // We want to make sure that OS_ACTIVITY_DT_MODE is set so that we get
1687 // os_log and NSLog messages mirrored to the target process stderr.
1688 env_vars.try_emplace("OS_ACTIVITY_DT_MODE", "enable");
1689 }
1690
1691 // Let our parent class do the real launching.
1692 return PlatformPOSIX::LaunchProcess(launch_info);
1693 }
1694
1695 lldb_private::Status
FindBundleBinaryInExecSearchPaths(const ModuleSpec & module_spec,Process * process,ModuleSP & module_sp,const FileSpecList * module_search_paths_ptr,ModuleSP * old_module_sp_ptr,bool * did_create_ptr)1696 PlatformDarwin::FindBundleBinaryInExecSearchPaths (const ModuleSpec &module_spec, Process *process,
1697 ModuleSP &module_sp,
1698 const FileSpecList *module_search_paths_ptr,
1699 ModuleSP *old_module_sp_ptr, bool *did_create_ptr)
1700 {
1701 const FileSpec &platform_file = module_spec.GetFileSpec();
1702 // See if the file is present in any of the module_search_paths_ptr
1703 // directories.
1704 if (!module_sp && module_search_paths_ptr && platform_file) {
1705 // create a vector of all the file / directory names in platform_file e.g.
1706 // this might be
1707 // /System/Library/PrivateFrameworks/UIFoundation.framework/UIFoundation
1708 //
1709 // We'll need to look in the module_search_paths_ptr directories for both
1710 // "UIFoundation" and "UIFoundation.framework" -- most likely the latter
1711 // will be the one we find there.
1712
1713 FileSpec platform_pull_upart(platform_file);
1714 std::vector<std::string> path_parts;
1715 path_parts.push_back(
1716 platform_pull_upart.GetLastPathComponent().AsCString());
1717 while (platform_pull_upart.RemoveLastPathComponent()) {
1718 ConstString part = platform_pull_upart.GetLastPathComponent();
1719 path_parts.push_back(part.AsCString());
1720 }
1721 const size_t path_parts_size = path_parts.size();
1722
1723 size_t num_module_search_paths = module_search_paths_ptr->GetSize();
1724 for (size_t i = 0; i < num_module_search_paths; ++i) {
1725 Log *log_verbose = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
1726 LLDB_LOGF(
1727 log_verbose,
1728 "PlatformRemoteDarwinDevice::GetSharedModule searching for binary in "
1729 "search-path %s",
1730 module_search_paths_ptr->GetFileSpecAtIndex(i).GetPath().c_str());
1731 // Create a new FileSpec with this module_search_paths_ptr plus just the
1732 // filename ("UIFoundation"), then the parent dir plus filename
1733 // ("UIFoundation.framework/UIFoundation") etc - up to four names (to
1734 // handle "Foo.framework/Contents/MacOS/Foo")
1735
1736 for (size_t j = 0; j < 4 && j < path_parts_size - 1; ++j) {
1737 FileSpec path_to_try(module_search_paths_ptr->GetFileSpecAtIndex(i));
1738
1739 // Add the components backwards. For
1740 // .../PrivateFrameworks/UIFoundation.framework/UIFoundation path_parts
1741 // is
1742 // [0] UIFoundation
1743 // [1] UIFoundation.framework
1744 // [2] PrivateFrameworks
1745 //
1746 // and if 'j' is 2, we want to append path_parts[1] and then
1747 // path_parts[0], aka 'UIFoundation.framework/UIFoundation', to the
1748 // module_search_paths_ptr path.
1749
1750 for (int k = j; k >= 0; --k) {
1751 path_to_try.AppendPathComponent(path_parts[k]);
1752 }
1753
1754 if (FileSystem::Instance().Exists(path_to_try)) {
1755 ModuleSpec new_module_spec(module_spec);
1756 new_module_spec.GetFileSpec() = path_to_try;
1757 Status new_error(Platform::GetSharedModule(
1758 new_module_spec, process, module_sp, nullptr, old_module_sp_ptr,
1759 did_create_ptr));
1760
1761 if (module_sp) {
1762 module_sp->SetPlatformFileSpec(path_to_try);
1763 return new_error;
1764 }
1765 }
1766 }
1767 }
1768 }
1769 return Status();
1770 }
1771