blob: fb9e4e02765fe7711a63bcd9766e6b7b2523aa59 [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
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
231 FileSpec lldb_file_spec;
232 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
233 return false;
234
235 std::string raw_path = lldb_file_spec.GetPath();
236
237 size_t framework_pos = raw_path.find("LLDB.framework");
238 if (framework_pos == std::string::npos)
239 return false;
240
241 framework_pos += strlen("LLDB.framework");
242 raw_path.resize(framework_pos);
243 raw_path.append("/Resources/PlugIns");
244 file_spec.GetDirectory().SetString(
245 llvm::StringRef(raw_path.c_str(), raw_path.size()));
246 return true;
247}
248
249bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
250 FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true);
251 file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
252 return true;
253}
254
255void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32,
256 ArchSpec &arch_64) {
257 // All apple systems support 32 bit execution.
258 uint32_t cputype, cpusubtype;
259 uint32_t is_64_bit_capable = false;
260 size_t len = sizeof(cputype);
261 ArchSpec host_arch;
262 // These will tell us about the kernel architecture, which even on a 64
263 // bit machine can be 32 bit...
264 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) {
265 len = sizeof(cpusubtype);
266 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
267 cpusubtype = CPU_TYPE_ANY;
268
269 len = sizeof(is_64_bit_capable);
270 ::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0);
271
272 if (is_64_bit_capable) {
273 if (cputype & CPU_ARCH_ABI64) {
274 // We have a 64 bit kernel on a 64 bit system
275 arch_64.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
276 } else {
277 // We have a 64 bit kernel that is returning a 32 bit cputype, the
278 // cpusubtype will be correct as if it were for a 64 bit architecture
279 arch_64.SetArchitecture(eArchTypeMachO, cputype | CPU_ARCH_ABI64,
280 cpusubtype);
281 }
282
283 // Now we need modify the cpusubtype for the 32 bit slices.
284 uint32_t cpusubtype32 = cpusubtype;
Zachary Turner13b18262014-08-20 16:42:51 +0000285#if defined(__i386__) || defined(__x86_64__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 if (cpusubtype == CPU_SUBTYPE_486 || cpusubtype == CPU_SUBTYPE_X86_64_H)
287 cpusubtype32 = CPU_SUBTYPE_I386_ALL;
Zachary Turner13b18262014-08-20 16:42:51 +0000288#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
290 cpusubtype32 = CPU_SUBTYPE_ARM_V7S;
Zachary Turner13b18262014-08-20 16:42:51 +0000291#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 arch_32.SetArchitecture(eArchTypeMachO, cputype & ~(CPU_ARCH_MASK),
293 cpusubtype32);
Zachary Turner13b18262014-08-20 16:42:51 +0000294
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
296// When running on a watch or tv, report the host os correctly
297#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
298 arch_32.GetTriple().setOS(llvm::Triple::TvOS);
299 arch_64.GetTriple().setOS(llvm::Triple::TvOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000300#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 arch_32.GetTriple().setOS(llvm::Triple::IOS);
302 arch_64.GetTriple().setOS(llvm::Triple::IOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000303#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304 } else {
305 arch_32.GetTriple().setOS(llvm::Triple::MacOSX);
306 arch_64.GetTriple().setOS(llvm::Triple::MacOSX);
307 }
308 } else {
309 // We have a 32 bit kernel on a 32 bit system
310 arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
311#if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
312 arch_32.GetTriple().setOS(llvm::Triple::WatchOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000313#else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314 arch_32.GetTriple().setOS(llvm::Triple::IOS);
Jason Molendae92a74c2015-11-21 04:00:43 +0000315#endif
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 arch_64.Clear();
Zachary Turner13b18262014-08-20 16:42:51 +0000317 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000318 }
Zachary Turner13b18262014-08-20 16:42:51 +0000319}