blob: 161182616cd02f8c1074344fc0472a7d9a59d534 [file] [log] [blame]
Zachary Turner97a14e62014-08-19 17:18:29 +00001//===-- HostInfoMacOSX.mm ---------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Zachary Turner2c1f46d2015-07-30 20:28:07 +000010#if !defined(LLDB_DISABLE_PYTHON)
11#include "Plugins/ScriptInterpreter/Python/lldb-python.h"
12#endif
Zachary Turner365dc292015-05-29 18:18:26 +000013
Zachary Turner42ff0ad2014-08-21 17:29:12 +000014#include "lldb/Host/HostInfo.h"
Zachary Turner97a14e62014-08-19 17:18:29 +000015#include "lldb/Host/macosx/HostInfoMacOSX.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000016#include "lldb/Utility/Args.h"
Zachary Turner6f9e6902017-03-03 20:56:28 +000017#include "lldb/Utility/Log.h"
Zachary Turner13b18262014-08-20 16:42:51 +000018#include "lldb/Utility/SafeMachO.h"
19
Zachary Turner42ff0ad2014-08-21 17:29:12 +000020#include "llvm/ADT/SmallString.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000021#include "llvm/Support/FileSystem.h"
Adrian Prantl7d46f0e2018-05-11 17:54:09 +000022#include "llvm/Support/Path.h"
Zachary Turner42ff0ad2014-08-21 17:29:12 +000023#include "llvm/Support/raw_ostream.h"
24
Zachary Turner97a14e62014-08-19 17:18:29 +000025// C++ Includes
26#include <string>
27
28// C inclues
Todd Fiala5e365482015-09-24 21:59:48 +000029#include <stdlib.h>
Zachary Turner97a14e62014-08-19 17:18:29 +000030#include <sys/sysctl.h>
Todd Fiala5e365482015-09-24 21:59:48 +000031#include <sys/syslimits.h>
Zachary Turner97a14e62014-08-19 17:18:29 +000032#include <sys/types.h>
33
34// Objective C/C++ includes
35#include <CoreFoundation/CoreFoundation.h>
36#include <Foundation/Foundation.h>
Zachary Turnera21fee02014-08-21 21:49:24 +000037#include <mach-o/dyld.h>
Zachary Turner97a14e62014-08-19 17:18:29 +000038#include <objc/objc-auto.h>
39
Keno Fischer5777edf2014-08-23 21:40:29 +000040// These are needed when compiling on systems
41// that do not yet have these definitions
42#include <AvailabilityMacros.h>
43#ifndef CPU_SUBTYPE_X86_64_H
44#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8)
45#endif
46#ifndef CPU_TYPE_ARM64
Kate Stoneb9c1b512016-09-06 20:57:50 +000047#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
Keno Fischer5777edf2014-08-23 21:40:29 +000048#endif
49
Jason Molendae92a74c2015-11-21 04:00:43 +000050#include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
51
Zachary Turner97a14e62014-08-19 17:18:29 +000052using namespace lldb_private;
53
Kate Stoneb9c1b512016-09-06 20:57:50 +000054bool HostInfoMacOSX::GetOSBuildString(std::string &s) {
55 int mib[2] = {CTL_KERN, KERN_OSVERSION};
56 char cstr[PATH_MAX];
57 size_t cstr_len = sizeof(cstr);
58 if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) {
59 s.assign(cstr, cstr_len);
60 return true;
61 }
Zachary Turner97a14e62014-08-19 17:18:29 +000062
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 s.clear();
64 return false;
65}
66
67bool HostInfoMacOSX::GetOSKernelDescription(std::string &s) {
68 int mib[2] = {CTL_KERN, KERN_VERSION};
69 char cstr[PATH_MAX];
70 size_t cstr_len = sizeof(cstr);
71 if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) {
72 s.assign(cstr, cstr_len);
73 return true;
74 }
75 s.clear();
76 return false;
77}
78
79bool HostInfoMacOSX::GetOSVersion(uint32_t &major, uint32_t &minor,
80 uint32_t &update) {
81 static uint32_t g_major = 0;
82 static uint32_t g_minor = 0;
83 static uint32_t g_update = 0;
84
85 if (g_major == 0) {
86 @autoreleasepool {
87 NSDictionary *version_info = [NSDictionary
88 dictionaryWithContentsOfFile:
89 @"/System/Library/CoreServices/SystemVersion.plist"];
90 NSString *version_value = [version_info objectForKey:@"ProductVersion"];
91 const char *version_str = [version_value UTF8String];
92 if (version_str)
Sean Callanan1355f472016-09-19 22:06:12 +000093 Args::StringToVersion(llvm::StringRef(version_str), g_major, g_minor,
94 g_update);
Kate Stoneb9c1b512016-09-06 20:57:50 +000095 }
96 }
97
98 if (g_major != 0) {
99 major = g_major;
100 minor = g_minor;
101 update = g_update;
102 return true;
103 }
104 return false;
105}
106
107FileSpec HostInfoMacOSX::GetProgramFileSpec() {
108 static FileSpec g_program_filespec;
109 if (!g_program_filespec) {
110 char program_fullpath[PATH_MAX];
111 // If DST is NULL, then return the number of bytes needed.
112 uint32_t len = sizeof(program_fullpath);
113 int err = _NSGetExecutablePath(program_fullpath, &len);
114 if (err == 0)
115 g_program_filespec.SetFile(program_fullpath, false);
116 else if (err == -1) {
117 char *large_program_fullpath = (char *)::malloc(len + 1);
118
119 err = _NSGetExecutablePath(large_program_fullpath, &len);
120 if (err == 0)
121 g_program_filespec.SetFile(large_program_fullpath, false);
122
123 ::free(large_program_fullpath);
124 }
125 }
126 return g_program_filespec;
127}
128
129bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) {
130 FileSpec lldb_file_spec;
131 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
Zachary Turner97a14e62014-08-19 17:18:29 +0000132 return false;
Zachary Turner97a14e62014-08-19 17:18:29 +0000133
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134 std::string raw_path = lldb_file_spec.GetPath();
Zachary Turner97a14e62014-08-19 17:18:29 +0000135
Kate Stoneb9c1b512016-09-06 20:57:50 +0000136 size_t framework_pos = raw_path.find("LLDB.framework");
137 if (framework_pos != std::string::npos) {
138 framework_pos += strlen("LLDB.framework");
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000139#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000140 // Shallow bundle
141 raw_path.resize(framework_pos);
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000142#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 // Normal bundle
144 raw_path.resize(framework_pos);
145 raw_path.append("/Resources");
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000146#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 } else {
148 // Find the bin path relative to the lib path where the cmake-based
149 // OS X .dylib lives. This is not going to work if the bin and lib
150 // dir are not both in the same dir.
151 //
152 // It is not going to work to do it by the executable path either,
153 // as in the case of a python script, the executable is python, not
154 // the lldb driver.
155 raw_path.append("/../bin");
156 FileSpec support_dir_spec(raw_path, true);
Zachary Turner7d86ee52017-03-08 17:56:08 +0000157 if (!llvm::sys::fs::is_directory(support_dir_spec.GetPath())) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
159 if (log)
160 log->Printf("HostInfoMacOSX::%s(): failed to find support directory",
161 __FUNCTION__);
162 return false;
Todd Fiala5e365482015-09-24 21:59:48 +0000163 }
164
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165 // Get normalization from support_dir_spec. Note the FileSpec resolve
166 // does not remove '..' in the path.
167 char *const dir_realpath =
168 realpath(support_dir_spec.GetPath().c_str(), NULL);
169 if (dir_realpath) {
170 raw_path = dir_realpath;
171 free(dir_realpath);
172 } else {
173 raw_path = support_dir_spec.GetPath();
174 }
175 }
176
177 file_spec.GetDirectory().SetString(
178 llvm::StringRef(raw_path.c_str(), raw_path.size()));
179 return (bool)file_spec.GetDirectory();
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000180}
181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182bool HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec) {
183 FileSpec lldb_file_spec;
184 if (!HostInfo::GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
Keno Fischer15d5e2b2014-09-09 04:52:37 +0000185 return false;
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000186
Kate Stoneb9c1b512016-09-06 20:57:50 +0000187 std::string raw_path = lldb_file_spec.GetPath();
Sean Callananb1e1c622014-12-05 01:15:04 +0000188
Kate Stoneb9c1b512016-09-06 20:57:50 +0000189 size_t framework_pos = raw_path.find("LLDB.framework");
190 if (framework_pos != std::string::npos) {
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000191 framework_pos += strlen("LLDB.framework");
Ilia K686b1fe2015-02-27 19:43:08 +0000192 raw_path.resize(framework_pos);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000193 raw_path.append("/Headers");
194 }
195 file_spec.GetDirectory().SetString(
196 llvm::StringRef(raw_path.c_str(), raw_path.size()));
197 return true;
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000198}
199
Kate Stoneb9c1b512016-09-06 20:57:50 +0000200bool HostInfoMacOSX::ComputePythonDirectory(FileSpec &file_spec) {
201#ifndef LLDB_DISABLE_PYTHON
202 FileSpec lldb_file_spec;
203 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
204 return false;
205
206 std::string raw_path = lldb_file_spec.GetPath();
207
208 size_t framework_pos = raw_path.find("LLDB.framework");
209 if (framework_pos != std::string::npos) {
210 framework_pos += strlen("LLDB.framework");
211 raw_path.resize(framework_pos);
212 raw_path.append("/Resources/Python");
213 } else {
214 llvm::SmallString<256> python_version_dir;
215 llvm::raw_svector_ostream os(python_version_dir);
216 os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION
217 << "/site-packages";
218
219 // We may get our string truncated. Should we protect this with an assert?
220 raw_path.append(python_version_dir.c_str());
221 }
222 file_spec.GetDirectory().SetString(
223 llvm::StringRef(raw_path.c_str(), raw_path.size()));
224 return true;
225#else
226 return false;
227#endif
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000228}
229
Adrian Prantl7d46f0e2018-05-11 17:54:09 +0000230static bool VerifyClangPath(const llvm::Twine &clang_path) {
231 if (llvm::sys::fs::is_directory(clang_path))
232 return true;
233 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
234 if (log)
235 log->Printf("HostInfoMacOSX::ComputeClangDirectory(): "
236 "failed to stat clang resource directory at \"%s\"",
237 clang_path.str().c_str());
238 return false;
239}
240
Kate Stoneb9c1b512016-09-06 20:57:50 +0000241bool HostInfoMacOSX::ComputeClangDirectory(FileSpec &file_spec) {
242 FileSpec lldb_file_spec;
243 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
244 return false;
Adrian Prantl7d46f0e2018-05-11 17:54:09 +0000245 return ComputeClangDirectory(lldb_file_spec, file_spec, true);
246}
Zachary Turner13b18262014-08-20 16:42:51 +0000247
Adrian Prantl7d46f0e2018-05-11 17:54:09 +0000248bool HostInfoMacOSX::ComputeClangDirectory(FileSpec &lldb_shlib_spec,
249 FileSpec &file_spec, bool verify) {
250 std::string raw_path = lldb_shlib_spec.GetPath();
Zachary Turner13b18262014-08-20 16:42:51 +0000251
Adrian Prantl7d46f0e2018-05-11 17:54:09 +0000252 auto rev_it = llvm::sys::path::rbegin(raw_path);
253 auto r_end = llvm::sys::path::rend(raw_path);
254
255 // Check for a Posix-style build of LLDB.
256 if (rev_it == r_end || *rev_it != "LLDB.framework")
Chris Bieneman5f15a302016-11-02 17:19:23 +0000257 return HostInfoPosix::ComputeClangDirectory(file_spec);
Adrian Prantl7d46f0e2018-05-11 17:54:09 +0000258
259 // Inside Xcode and in Xcode toolchains LLDB is always in lockstep
260 // with the Swift compiler, so it can reuse its Clang resource
261 // directory. This allows LLDB and the Swift compiler to share the
262 // same Clang module cache.
263 llvm::SmallString<256> clang_path;
264 const char *swift_clang_resource_dir = "usr/lib/swift/clang";
265 ++rev_it;
266 if (rev_it != r_end && *rev_it == "SharedFrameworks") {
267 // This is the top-level LLDB in the Xcode.app bundle.
268 raw_path.resize(rev_it - r_end);
269 llvm::sys::path::append(clang_path, raw_path,
270 "Developer/Toolchains/XcodeDefault.xctoolchain",
271 swift_clang_resource_dir);
272 if (!verify || VerifyClangPath(clang_path)) {
273 file_spec.SetFile(clang_path.c_str(), true);
274 return true;
275 }
276 } else if (rev_it != r_end && *rev_it == "PrivateFrameworks" &&
277 ++rev_it != r_end && ++rev_it != r_end) {
278 // This is LLDB inside an Xcode toolchain.
279 raw_path.resize(rev_it - r_end);
280 llvm::sys::path::append(clang_path, raw_path, swift_clang_resource_dir);
281 if (!verify || VerifyClangPath(clang_path)) {
282 file_spec.SetFile(clang_path.c_str(), true);
283 return true;
284 }
285 } else {
286 raw_path.resize(rev_it - r_end);
287 }
288
289 // Fall back to the Clang resource directory inside the framework.
Chris Bieneman5f15a302016-11-02 17:19:23 +0000290 raw_path.append("/Resources/Clang");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000291 file_spec.SetFile(raw_path.c_str(), true);
292 return true;
293}
Zachary Turner13b18262014-08-20 16:42:51 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
296 FileSpec lldb_file_spec;
297 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
298 return false;
299
300 std::string raw_path = lldb_file_spec.GetPath();
301
302 size_t framework_pos = raw_path.find("LLDB.framework");
303 if (framework_pos == std::string::npos)
304 return false;
305
306 framework_pos += strlen("LLDB.framework");
307 raw_path.resize(framework_pos);
308 raw_path.append("/Resources/PlugIns");
309 file_spec.GetDirectory().SetString(
310 llvm::StringRef(raw_path.c_str(), raw_path.size()));
311 return true;
312}
313
314bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
315 FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true);
316 file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
317 return true;
318}
319
320void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32,
321 ArchSpec &arch_64) {
322 // All apple systems support 32 bit execution.
323 uint32_t cputype, cpusubtype;
324 uint32_t is_64_bit_capable = false;
325 size_t len = sizeof(cputype);
326 ArchSpec host_arch;
327 // These will tell us about the kernel architecture, which even on a 64
328 // bit machine can be 32 bit...
329 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) {
330 len = sizeof(cpusubtype);
331 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
332 cpusubtype = CPU_TYPE_ANY;
333
334 len = sizeof(is_64_bit_capable);
335 ::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0);
336
337 if (is_64_bit_capable) {
338 if (cputype & CPU_ARCH_ABI64) {
339 // We have a 64 bit kernel on a 64 bit system
340 arch_64.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
341 } else {
342 // We have a 64 bit kernel that is returning a 32 bit cputype, the
343 // cpusubtype will be correct as if it were for a 64 bit architecture
344 arch_64.SetArchitecture(eArchTypeMachO, cputype | CPU_ARCH_ABI64,
345 cpusubtype);
346 }
347
348 // Now we need modify the cpusubtype for the 32 bit slices.
349 uint32_t cpusubtype32 = cpusubtype;
Zachary Turner13b18262014-08-20 16:42:51 +0000350#if defined(__i386__) || defined(__x86_64__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000351 if (cpusubtype == CPU_SUBTYPE_486 || cpusubtype == CPU_SUBTYPE_X86_64_H)
352 cpusubtype32 = CPU_SUBTYPE_I386_ALL;
Zachary Turner13b18262014-08-20 16:42:51 +0000353#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000354 if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
355 cpusubtype32 = CPU_SUBTYPE_ARM_V7S;
Zachary Turner13b18262014-08-20 16:42:51 +0000356#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357 arch_32.SetArchitecture(eArchTypeMachO, cputype & ~(CPU_ARCH_MASK),
358 cpusubtype32);
Zachary Turner13b18262014-08-20 16:42:51 +0000359
Kate Stoneb9c1b512016-09-06 20:57:50 +0000360 if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
361// When running on a watch or tv, report the host os correctly
362#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
363 arch_32.GetTriple().setOS(llvm::Triple::TvOS);
364 arch_64.GetTriple().setOS(llvm::Triple::TvOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000365#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000366 arch_32.GetTriple().setOS(llvm::Triple::IOS);
367 arch_64.GetTriple().setOS(llvm::Triple::IOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000368#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369 } else {
370 arch_32.GetTriple().setOS(llvm::Triple::MacOSX);
371 arch_64.GetTriple().setOS(llvm::Triple::MacOSX);
372 }
373 } else {
374 // We have a 32 bit kernel on a 32 bit system
375 arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
376#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
377 arch_32.GetTriple().setOS(llvm::Triple::WatchOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000378#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379 arch_32.GetTriple().setOS(llvm::Triple::IOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000380#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000381 arch_64.Clear();
Zachary Turner13b18262014-08-20 16:42:51 +0000382 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383 }
Zachary Turner13b18262014-08-20 16:42:51 +0000384}