blob: d499411c7de9438c189fcc07bcb7bbea6974a473 [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"
Todd Fiala5e365482015-09-24 21:59:48 +000016#include "lldb/Core/Log.h"
Zachary Turner97a14e62014-08-19 17:18:29 +000017#include "lldb/Interpreter/Args.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"
21#include "llvm/Support/raw_ostream.h"
22
Zachary Turner97a14e62014-08-19 17:18:29 +000023// C++ Includes
24#include <string>
25
26// C inclues
Todd Fiala5e365482015-09-24 21:59:48 +000027#include <stdlib.h>
Zachary Turner97a14e62014-08-19 17:18:29 +000028#include <sys/sysctl.h>
Todd Fiala5e365482015-09-24 21:59:48 +000029#include <sys/syslimits.h>
Zachary Turner97a14e62014-08-19 17:18:29 +000030#include <sys/types.h>
31
32// Objective C/C++ includes
33#include <CoreFoundation/CoreFoundation.h>
34#include <Foundation/Foundation.h>
Zachary Turnera21fee02014-08-21 21:49:24 +000035#include <mach-o/dyld.h>
Zachary Turner97a14e62014-08-19 17:18:29 +000036#include <objc/objc-auto.h>
37
Keno Fischer5777edf2014-08-23 21:40:29 +000038// These are needed when compiling on systems
39// that do not yet have these definitions
40#include <AvailabilityMacros.h>
41#ifndef CPU_SUBTYPE_X86_64_H
42#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8)
43#endif
44#ifndef CPU_TYPE_ARM64
45#define CPU_TYPE_ARM64 (CPU_TYPE_ARM|CPU_ARCH_ABI64)
46#endif
47
Zachary Turner97a14e62014-08-19 17:18:29 +000048using namespace lldb_private;
49
50bool
51HostInfoMacOSX::GetOSBuildString(std::string &s)
52{
53 int mib[2] = {CTL_KERN, KERN_OSVERSION};
54 char cstr[PATH_MAX];
55 size_t cstr_len = sizeof(cstr);
56 if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0)
57 {
58 s.assign(cstr, cstr_len);
59 return true;
60 }
61
62 s.clear();
63 return false;
64}
65
66bool
67HostInfoMacOSX::GetOSKernelDescription(std::string &s)
68{
69 int mib[2] = {CTL_KERN, KERN_VERSION};
70 char cstr[PATH_MAX];
71 size_t cstr_len = sizeof(cstr);
72 if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0)
73 {
74 s.assign(cstr, cstr_len);
75 return true;
76 }
77 s.clear();
78 return false;
79}
80
81bool
82HostInfoMacOSX::GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update)
83{
84 static uint32_t g_major = 0;
85 static uint32_t g_minor = 0;
86 static uint32_t g_update = 0;
87
88 if (g_major == 0)
89 {
90 @autoreleasepool
91 {
92 NSDictionary *version_info = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"];
93 NSString *version_value = [version_info objectForKey:@"ProductVersion"];
94 const char *version_str = [version_value UTF8String];
95 if (version_str)
96 Args::StringToVersion(version_str, g_major, g_minor, g_update);
97 }
98 }
99
100 if (g_major != 0)
101 {
102 major = g_major;
103 minor = g_minor;
104 update = g_update;
105 return true;
106 }
107 return false;
108}
Zachary Turner13b18262014-08-20 16:42:51 +0000109
Zachary Turnera21fee02014-08-21 21:49:24 +0000110FileSpec
111HostInfoMacOSX::GetProgramFileSpec()
112{
113 static FileSpec g_program_filespec;
114 if (!g_program_filespec)
115 {
116 char program_fullpath[PATH_MAX];
117 // If DST is NULL, then return the number of bytes needed.
118 uint32_t len = sizeof(program_fullpath);
119 int err = _NSGetExecutablePath(program_fullpath, &len);
120 if (err == 0)
121 g_program_filespec.SetFile(program_fullpath, false);
122 else if (err == -1)
123 {
124 char *large_program_fullpath = (char *)::malloc(len + 1);
125
126 err = _NSGetExecutablePath(large_program_fullpath, &len);
127 if (err == 0)
128 g_program_filespec.SetFile(large_program_fullpath, false);
129
130 ::free(large_program_fullpath);
131 }
132 }
133 return g_program_filespec;
134}
135
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000136bool
137HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec)
138{
139 FileSpec lldb_file_spec;
140 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
141 return false;
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000142
Ilia K686b1fe2015-02-27 19:43:08 +0000143 std::string raw_path = lldb_file_spec.GetPath();
144
145 size_t framework_pos = raw_path.find("LLDB.framework");
146 if (framework_pos != std::string::npos)
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000147 {
148 framework_pos += strlen("LLDB.framework");
149#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
150 // Shallow bundle
Ilia K686b1fe2015-02-27 19:43:08 +0000151 raw_path.resize(framework_pos);
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000152#else
153 // Normal bundle
Ilia K686b1fe2015-02-27 19:43:08 +0000154 raw_path.resize(framework_pos);
155 raw_path.append("/Resources");
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000156#endif
157 }
Todd Fiala5e365482015-09-24 21:59:48 +0000158 else
159 {
160 // Find the bin path relative to the lib path where the cmake-based
161 // OS X .dylib lives. This is not going to work if the bin and lib
162 // dir are not both in the same dir.
163 //
164 // It is not going to work to do it by the executable path either,
165 // as in the case of a python script, the executable is python, not
166 // the lldb driver.
167 raw_path.append("/../bin");
168 FileSpec support_dir_spec(raw_path, true);
169 if (!support_dir_spec.Exists() || !support_dir_spec.IsDirectory())
170 {
171 Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
172 if (log)
173 log->Printf("HostInfoMacOSX::%s(): failed to find support directory",
174 __FUNCTION__);
175 return false;
176 }
177
178 // Get normalization from support_dir_spec. Note the FileSpec resolve
179 // does not remove '..' in the path.
180 char *const dir_realpath = realpath(support_dir_spec.GetPath().c_str(), NULL);
181 if (dir_realpath)
182 {
183 raw_path = dir_realpath;
184 free(dir_realpath);
185 }
186 else
187 {
188 raw_path = support_dir_spec.GetPath();
189 }
190 }
191
Ilia K686b1fe2015-02-27 19:43:08 +0000192 file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size()));
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000193 return (bool)file_spec.GetDirectory();
194}
195
196bool
197HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec)
198{
199 FileSpec lldb_file_spec;
200 if (!HostInfo::GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
201 return false;
202
Ilia K686b1fe2015-02-27 19:43:08 +0000203 std::string raw_path = lldb_file_spec.GetPath();
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000204
Ilia K686b1fe2015-02-27 19:43:08 +0000205 size_t framework_pos = raw_path.find("LLDB.framework");
206 if (framework_pos != std::string::npos)
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000207 {
208 framework_pos += strlen("LLDB.framework");
Ilia K686b1fe2015-02-27 19:43:08 +0000209 raw_path.resize(framework_pos);
210 raw_path.append("/Headers");
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000211 }
Ilia K686b1fe2015-02-27 19:43:08 +0000212 file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size()));
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000213 return true;
214}
215
216bool
217HostInfoMacOSX::ComputePythonDirectory(FileSpec &file_spec)
218{
Keno Fischer15d5e2b2014-09-09 04:52:37 +0000219#ifndef LLDB_DISABLE_PYTHON
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000220 FileSpec lldb_file_spec;
221 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
222 return false;
223
Ilia K686b1fe2015-02-27 19:43:08 +0000224 std::string raw_path = lldb_file_spec.GetPath();
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000225
Ilia K686b1fe2015-02-27 19:43:08 +0000226 size_t framework_pos = raw_path.find("LLDB.framework");
227 if (framework_pos != std::string::npos)
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000228 {
229 framework_pos += strlen("LLDB.framework");
Ilia K686b1fe2015-02-27 19:43:08 +0000230 raw_path.resize(framework_pos);
231 raw_path.append("/Resources/Python");
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000232 }
233 else
234 {
235 llvm::SmallString<256> python_version_dir;
236 llvm::raw_svector_ostream os(python_version_dir);
237 os << "/python" << PY_MAJOR_VERSION << '.' << PY_MINOR_VERSION << "/site-packages";
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000238
239 // We may get our string truncated. Should we protect this with an assert?
Ilia K686b1fe2015-02-27 19:43:08 +0000240 raw_path.append(python_version_dir.c_str());
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000241 }
Ilia K686b1fe2015-02-27 19:43:08 +0000242 file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size()));
Keno Fischera89da492014-09-09 04:56:16 +0000243 return true;
Keno Fischer15d5e2b2014-09-09 04:52:37 +0000244#else
245 return false;
246#endif
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000247}
248
249bool
Sean Callananb1e1c622014-12-05 01:15:04 +0000250HostInfoMacOSX::ComputeClangDirectory(FileSpec &file_spec)
251{
252 FileSpec lldb_file_spec;
253 if (!GetLLDBPath (lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
254 return false;
255
Ilia K686b1fe2015-02-27 19:43:08 +0000256 std::string raw_path = lldb_file_spec.GetPath();
Sean Callananb1e1c622014-12-05 01:15:04 +0000257
Ilia K686b1fe2015-02-27 19:43:08 +0000258 size_t framework_pos = raw_path.find("LLDB.framework");
259 if (framework_pos != std::string::npos)
Sean Callananb1e1c622014-12-05 01:15:04 +0000260 {
261 framework_pos += strlen("LLDB.framework");
Ilia K686b1fe2015-02-27 19:43:08 +0000262 raw_path.resize(framework_pos);
263 raw_path.append("/Resources/Clang");
Sean Callananb1e1c622014-12-05 01:15:04 +0000264 }
Ilia K686b1fe2015-02-27 19:43:08 +0000265 file_spec.SetFile (raw_path.c_str(), true);
Sean Callananb1e1c622014-12-05 01:15:04 +0000266 return true;
267}
268
269bool
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000270HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec)
271{
272 FileSpec lldb_file_spec;
273 if (!GetLLDBPath(lldb::ePathTypeLLDBShlibDir, lldb_file_spec))
274 return false;
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000275
Ilia K686b1fe2015-02-27 19:43:08 +0000276 std::string raw_path = lldb_file_spec.GetPath();
277
278 size_t framework_pos = raw_path.find("LLDB.framework");
279 if (framework_pos == std::string::npos)
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000280 return false;
281
282 framework_pos += strlen("LLDB.framework");
Ilia K686b1fe2015-02-27 19:43:08 +0000283 raw_path.resize(framework_pos);
284 raw_path.append("/Resources/PlugIns");
285 file_spec.GetDirectory().SetString(llvm::StringRef(raw_path.c_str(), raw_path.size()));
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000286 return true;
287}
288
289bool
290HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec)
291{
Greg Clayton0d8400c2014-08-25 18:21:06 +0000292 FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true);
293 file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
Zachary Turner42ff0ad2014-08-21 17:29:12 +0000294 return true;
295}
296
Zachary Turner13b18262014-08-20 16:42:51 +0000297void
298HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
299{
300 // All apple systems support 32 bit execution.
301 uint32_t cputype, cpusubtype;
302 uint32_t is_64_bit_capable = false;
303 size_t len = sizeof(cputype);
304 ArchSpec host_arch;
305 // These will tell us about the kernel architecture, which even on a 64
306 // bit machine can be 32 bit...
307 if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0)
308 {
309 len = sizeof(cpusubtype);
310 if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
311 cpusubtype = CPU_TYPE_ANY;
312
313 len = sizeof(is_64_bit_capable);
314 ::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0);
315
316 if (is_64_bit_capable)
317 {
318 if (cputype & CPU_ARCH_ABI64)
319 {
320 // We have a 64 bit kernel on a 64 bit system
321 arch_64.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
322 }
323 else
324 {
325 // We have a 64 bit kernel that is returning a 32 bit cputype, the
326 // cpusubtype will be correct as if it were for a 64 bit architecture
327 arch_64.SetArchitecture(eArchTypeMachO, cputype | CPU_ARCH_ABI64, cpusubtype);
328 }
329
330 // Now we need modify the cpusubtype for the 32 bit slices.
331 uint32_t cpusubtype32 = cpusubtype;
332#if defined(__i386__) || defined(__x86_64__)
333 if (cpusubtype == CPU_SUBTYPE_486 || cpusubtype == CPU_SUBTYPE_X86_64_H)
334 cpusubtype32 = CPU_SUBTYPE_I386_ALL;
335#elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
336 if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
337 cpusubtype32 = CPU_SUBTYPE_ARM_V7S;
338#endif
339 arch_32.SetArchitecture(eArchTypeMachO, cputype & ~(CPU_ARCH_MASK), cpusubtype32);
340
341 if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
342 {
343 arch_32.GetTriple().setOS(llvm::Triple::IOS);
344 arch_64.GetTriple().setOS(llvm::Triple::IOS);
345 }
346 else
347 {
348 arch_32.GetTriple().setOS(llvm::Triple::MacOSX);
349 arch_64.GetTriple().setOS(llvm::Triple::MacOSX);
350 }
351 }
352 else
353 {
354 // We have a 32 bit kernel on a 32 bit system
355 arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
356 arch_64.Clear();
357 }
358 }
359}