]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Host/macosx/objcxx/HostInfoMacOSX.mm
Vendor import of lldb trunk r338150:
[FreeBSD/FreeBSD.git] / source / Host / macosx / objcxx / HostInfoMacOSX.mm
1 //===-- 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
10 #include "lldb/Host/HostInfo.h"
11 #include "lldb/Host/macosx/HostInfoMacOSX.h"
12 #include "lldb/Utility/Args.h"
13 #include "lldb/Utility/Log.h"
14 #include "lldb/Utility/SafeMachO.h"
15
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Support/FileSystem.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/raw_ostream.h"
20
21 // C++ Includes
22 #include <string>
23
24 // C inclues
25 #include <stdlib.h>
26 #include <sys/sysctl.h>
27 #include <sys/syslimits.h>
28 #include <sys/types.h>
29
30 // Objective-C/C++ includes
31 #include <CoreFoundation/CoreFoundation.h>
32 #include <Foundation/Foundation.h>
33 #include <mach-o/dyld.h>
34 #include <objc/objc-auto.h>
35
36 // These are needed when compiling on systems
37 // that do not yet have these definitions
38 #include <AvailabilityMacros.h>
39 #ifndef CPU_SUBTYPE_X86_64_H
40 #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8)
41 #endif
42 #ifndef CPU_TYPE_ARM64
43 #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
44 #endif
45
46 #include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
47
48 using namespace lldb_private;
49
50 bool HostInfoMacOSX::GetOSBuildString(std::string &s) {
51   int mib[2] = {CTL_KERN, KERN_OSVERSION};
52   char cstr[PATH_MAX];
53   size_t cstr_len = sizeof(cstr);
54   if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) {
55     s.assign(cstr, cstr_len);
56     return true;
57   }
58
59   s.clear();
60   return false;
61 }
62
63 bool HostInfoMacOSX::GetOSKernelDescription(std::string &s) {
64   int mib[2] = {CTL_KERN, KERN_VERSION};
65   char cstr[PATH_MAX];
66   size_t cstr_len = sizeof(cstr);
67   if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) {
68     s.assign(cstr, cstr_len);
69     return true;
70   }
71   s.clear();
72   return false;
73 }
74
75 llvm::VersionTuple HostInfoMacOSX::GetOSVersion() {
76   static llvm::VersionTuple g_version;
77
78   if (g_version.empty()) {
79     @autoreleasepool {
80       NSDictionary *version_info = [NSDictionary
81           dictionaryWithContentsOfFile:
82               @"/System/Library/CoreServices/SystemVersion.plist"];
83       NSString *version_value = [version_info objectForKey:@"ProductVersion"];
84       const char *version_str = [version_value UTF8String];
85       g_version.tryParse(version_str);
86     }
87   }
88
89   return g_version;
90 }
91
92 FileSpec HostInfoMacOSX::GetProgramFileSpec() {
93   static FileSpec g_program_filespec;
94   if (!g_program_filespec) {
95     char program_fullpath[PATH_MAX];
96     // If DST is NULL, then return the number of bytes needed.
97     uint32_t len = sizeof(program_fullpath);
98     int err = _NSGetExecutablePath(program_fullpath, &len);
99     if (err == 0)
100       g_program_filespec.SetFile(program_fullpath, false,
101                                  FileSpec::Style::native);
102     else if (err == -1) {
103       char *large_program_fullpath = (char *)::malloc(len + 1);
104
105       err = _NSGetExecutablePath(large_program_fullpath, &len);
106       if (err == 0)
107         g_program_filespec.SetFile(large_program_fullpath, false,
108                                    FileSpec::Style::native);
109
110       ::free(large_program_fullpath);
111     }
112   }
113   return g_program_filespec;
114 }
115
116 bool HostInfoMacOSX::ComputeSupportExeDirectory(FileSpec &file_spec) {
117   FileSpec lldb_file_spec = GetShlibDir();
118   if (!lldb_file_spec)
119     return false;
120
121   std::string raw_path = lldb_file_spec.GetPath();
122
123   size_t framework_pos = raw_path.find("LLDB.framework");
124   if (framework_pos != std::string::npos) {
125     framework_pos += strlen("LLDB.framework");
126 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
127     // Shallow bundle
128     raw_path.resize(framework_pos);
129 #else
130     // Normal bundle
131     raw_path.resize(framework_pos);
132     raw_path.append("/Resources");
133 #endif
134   } else {
135     // Find the bin path relative to the lib path where the cmake-based
136     // OS X .dylib lives.  This is not going to work if the bin and lib
137     // dir are not both in the same dir.
138     //
139     // It is not going to work to do it by the executable path either,
140     // as in the case of a python script, the executable is python, not
141     // the lldb driver.
142     raw_path.append("/../bin");
143     FileSpec support_dir_spec(raw_path, true);
144     if (!llvm::sys::fs::is_directory(support_dir_spec.GetPath())) {
145       Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST);
146       if (log)
147         log->Printf("HostInfoMacOSX::%s(): failed to find support directory",
148                     __FUNCTION__);
149       return false;
150     }
151
152     // Get normalization from support_dir_spec.  Note the FileSpec resolve
153     // does not remove '..' in the path.
154     char *const dir_realpath =
155         realpath(support_dir_spec.GetPath().c_str(), NULL);
156     if (dir_realpath) {
157       raw_path = dir_realpath;
158       free(dir_realpath);
159     } else {
160       raw_path = support_dir_spec.GetPath();
161     }
162   }
163
164   file_spec.GetDirectory().SetString(
165       llvm::StringRef(raw_path.c_str(), raw_path.size()));
166   return (bool)file_spec.GetDirectory();
167 }
168
169 bool HostInfoMacOSX::ComputeHeaderDirectory(FileSpec &file_spec) {
170   FileSpec lldb_file_spec = GetShlibDir();
171   if (!lldb_file_spec)
172     return false;
173
174   std::string raw_path = lldb_file_spec.GetPath();
175
176   size_t framework_pos = raw_path.find("LLDB.framework");
177   if (framework_pos != std::string::npos) {
178     framework_pos += strlen("LLDB.framework");
179     raw_path.resize(framework_pos);
180     raw_path.append("/Headers");
181   }
182   file_spec.GetDirectory().SetString(
183       llvm::StringRef(raw_path.c_str(), raw_path.size()));
184   return true;
185 }
186
187 bool HostInfoMacOSX::ComputeSystemPluginsDirectory(FileSpec &file_spec) {
188   FileSpec lldb_file_spec = GetShlibDir();
189   if (!lldb_file_spec)
190     return false;
191
192   std::string raw_path = lldb_file_spec.GetPath();
193
194   size_t framework_pos = raw_path.find("LLDB.framework");
195   if (framework_pos == std::string::npos)
196     return false;
197
198   framework_pos += strlen("LLDB.framework");
199   raw_path.resize(framework_pos);
200   raw_path.append("/Resources/PlugIns");
201   file_spec.GetDirectory().SetString(
202       llvm::StringRef(raw_path.c_str(), raw_path.size()));
203   return true;
204 }
205
206 bool HostInfoMacOSX::ComputeUserPluginsDirectory(FileSpec &file_spec) {
207   FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns", true);
208   file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
209   return true;
210 }
211
212 void HostInfoMacOSX::ComputeHostArchitectureSupport(ArchSpec &arch_32,
213                                                     ArchSpec &arch_64) {
214   // All apple systems support 32 bit execution.
215   uint32_t cputype, cpusubtype;
216   uint32_t is_64_bit_capable = false;
217   size_t len = sizeof(cputype);
218   ArchSpec host_arch;
219   // These will tell us about the kernel architecture, which even on a 64
220   // bit machine can be 32 bit...
221   if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) {
222     len = sizeof(cpusubtype);
223     if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0)
224       cpusubtype = CPU_TYPE_ANY;
225
226     len = sizeof(is_64_bit_capable);
227     ::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0);
228
229     if (is_64_bit_capable) {
230       if (cputype & CPU_ARCH_ABI64) {
231         // We have a 64 bit kernel on a 64 bit system
232         arch_64.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
233       } else {
234         // We have a 64 bit kernel that is returning a 32 bit cputype, the
235         // cpusubtype will be correct as if it were for a 64 bit architecture
236         arch_64.SetArchitecture(eArchTypeMachO, cputype | CPU_ARCH_ABI64,
237                                 cpusubtype);
238       }
239
240       // Now we need modify the cpusubtype for the 32 bit slices.
241       uint32_t cpusubtype32 = cpusubtype;
242 #if defined(__i386__) || defined(__x86_64__)
243       if (cpusubtype == CPU_SUBTYPE_486 || cpusubtype == CPU_SUBTYPE_X86_64_H)
244         cpusubtype32 = CPU_SUBTYPE_I386_ALL;
245 #elif defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
246       if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64)
247         cpusubtype32 = CPU_SUBTYPE_ARM_V7S;
248 #endif
249       arch_32.SetArchitecture(eArchTypeMachO, cputype & ~(CPU_ARCH_MASK),
250                               cpusubtype32);
251
252       if (cputype == CPU_TYPE_ARM || cputype == CPU_TYPE_ARM64) {
253 // When running on a watch or tv, report the host os correctly
254 #if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
255         arch_32.GetTriple().setOS(llvm::Triple::TvOS);
256         arch_64.GetTriple().setOS(llvm::Triple::TvOS);
257 #else
258         arch_32.GetTriple().setOS(llvm::Triple::IOS);
259         arch_64.GetTriple().setOS(llvm::Triple::IOS);
260 #endif
261       } else {
262         arch_32.GetTriple().setOS(llvm::Triple::MacOSX);
263         arch_64.GetTriple().setOS(llvm::Triple::MacOSX);
264       }
265     } else {
266       // We have a 32 bit kernel on a 32 bit system
267       arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
268 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
269       arch_32.GetTriple().setOS(llvm::Triple::WatchOS);
270 #else
271       arch_32.GetTriple().setOS(llvm::Triple::IOS);
272 #endif
273       arch_64.Clear();
274     }
275   }
276 }