LLDB  mainline
HostInfoMacOSX.mm
Go to the documentation of this file.
1 //===-- HostInfoMacOSX.mm ---------------------------------------*- 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 
10 #include "lldb/Host/FileSystem.h"
11 #include "lldb/Host/HostInfo.h"
12 #include "lldb/Utility/Args.h"
13 #include "lldb/Utility/Log.h"
14 
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 // C++ Includes
21 #include <string>
22 
23 // C inclues
24 #include <stdlib.h>
25 #include <sys/sysctl.h>
26 #include <sys/syslimits.h>
27 #include <sys/types.h>
28 
29 // Objective-C/C++ includes
30 #include <CoreFoundation/CoreFoundation.h>
31 #include <Foundation/Foundation.h>
32 #include <mach-o/dyld.h>
33 #include <objc/objc-auto.h>
34 
35 // These are needed when compiling on systems
36 // that do not yet have these definitions
37 #include <AvailabilityMacros.h>
38 #ifndef CPU_SUBTYPE_X86_64_H
39 #define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8)
40 #endif
41 #ifndef CPU_TYPE_ARM64
42 #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
43 #endif
44 
45 #include <TargetConditionals.h> // for TARGET_OS_TV, TARGET_OS_WATCH
46 
47 using namespace lldb_private;
48 
49 bool HostInfoMacOSX::GetOSBuildString(std::string &s) {
50  int mib[2] = {CTL_KERN, KERN_OSVERSION};
51  char cstr[PATH_MAX];
52  size_t cstr_len = sizeof(cstr);
53  if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) {
54  s.assign(cstr, cstr_len);
55  return true;
56  }
57 
58  s.clear();
59  return false;
60 }
61 
63  int mib[2] = {CTL_KERN, KERN_VERSION};
64  char cstr[PATH_MAX];
65  size_t cstr_len = sizeof(cstr);
66  if (::sysctl(mib, 2, cstr, &cstr_len, NULL, 0) == 0) {
67  s.assign(cstr, cstr_len);
68  return true;
69  }
70  s.clear();
71  return false;
72 }
73 
74 llvm::VersionTuple HostInfoMacOSX::GetOSVersion() {
75  static llvm::VersionTuple g_version;
76 
77  if (g_version.empty()) {
78  @autoreleasepool {
79  NSDictionary *version_info = [NSDictionary
80  dictionaryWithContentsOfFile:
81  @"/System/Library/CoreServices/SystemVersion.plist"];
82  NSString *version_value = [version_info objectForKey:@"ProductVersion"];
83  const char *version_str = [version_value UTF8String];
84  g_version.tryParse(version_str);
85  }
86  }
87 
88  return g_version;
89 }
90 
92  static FileSpec g_program_filespec;
93  if (!g_program_filespec) {
94  char program_fullpath[PATH_MAX];
95  // If DST is NULL, then return the number of bytes needed.
96  uint32_t len = sizeof(program_fullpath);
97  int err = _NSGetExecutablePath(program_fullpath, &len);
98  if (err == 0)
99  g_program_filespec.SetFile(program_fullpath, FileSpec::Style::native);
100  else if (err == -1) {
101  char *large_program_fullpath = (char *)::malloc(len + 1);
102 
103  err = _NSGetExecutablePath(large_program_fullpath, &len);
104  if (err == 0)
105  g_program_filespec.SetFile(large_program_fullpath,
106  FileSpec::Style::native);
107 
108  ::free(large_program_fullpath);
109  }
110  }
111  return g_program_filespec;
112 }
113 
115  FileSpec lldb_file_spec = GetShlibDir();
116  if (!lldb_file_spec)
117  return false;
118 
119  std::string raw_path = lldb_file_spec.GetPath();
120 
121  size_t framework_pos = raw_path.find("LLDB.framework");
122  if (framework_pos != std::string::npos) {
123  framework_pos += strlen("LLDB.framework");
124 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
125  // Shallow bundle
126  raw_path.resize(framework_pos);
127 #else
128  // Normal bundle
129  raw_path.resize(framework_pos);
130  raw_path.append("/Resources");
131 #endif
132  } else {
133  // Find the bin path relative to the lib path where the cmake-based
134  // OS X .dylib lives. This is not going to work if the bin and lib
135  // dir are not both in the same dir.
136  //
137  // It is not going to work to do it by the executable path either,
138  // as in the case of a python script, the executable is python, not
139  // the lldb driver.
140  raw_path.append("/../bin");
141  FileSpec support_dir_spec(raw_path);
142  FileSystem::Instance().Resolve(support_dir_spec);
143  if (!FileSystem::Instance().IsDirectory(support_dir_spec)) {
145  if (log)
146  log->Printf("HostInfoMacOSX::%s(): failed to find support directory",
147  __FUNCTION__);
148  return false;
149  }
150 
151  // Get normalization from support_dir_spec. Note the FileSpec resolve
152  // does not remove '..' in the path.
153  char *const dir_realpath =
154  realpath(support_dir_spec.GetPath().c_str(), NULL);
155  if (dir_realpath) {
156  raw_path = dir_realpath;
157  free(dir_realpath);
158  } else {
159  raw_path = support_dir_spec.GetPath();
160  }
161  }
162 
163  file_spec.GetDirectory().SetString(
164  llvm::StringRef(raw_path.c_str(), raw_path.size()));
165  return (bool)file_spec.GetDirectory();
166 }
167 
169  FileSpec lldb_file_spec = GetShlibDir();
170  if (!lldb_file_spec)
171  return false;
172 
173  std::string raw_path = lldb_file_spec.GetPath();
174 
175  size_t framework_pos = raw_path.find("LLDB.framework");
176  if (framework_pos != std::string::npos) {
177  framework_pos += strlen("LLDB.framework");
178  raw_path.resize(framework_pos);
179  raw_path.append("/Headers");
180  }
181  file_spec.GetDirectory().SetString(
182  llvm::StringRef(raw_path.c_str(), raw_path.size()));
183  return true;
184 }
185 
187  FileSpec lldb_file_spec = GetShlibDir();
188  if (!lldb_file_spec)
189  return false;
190 
191  std::string raw_path = lldb_file_spec.GetPath();
192 
193  size_t framework_pos = raw_path.find("LLDB.framework");
194  if (framework_pos == std::string::npos)
195  return false;
196 
197  framework_pos += strlen("LLDB.framework");
198  raw_path.resize(framework_pos);
199  raw_path.append("/Resources/PlugIns");
200  file_spec.GetDirectory().SetString(
201  llvm::StringRef(raw_path.c_str(), raw_path.size()));
202  return true;
203 }
204 
206  FileSpec temp_file("~/Library/Application Support/LLDB/PlugIns");
207  FileSystem::Instance().Resolve(temp_file);
208  file_spec.GetDirectory().SetCString(temp_file.GetPath().c_str());
209  return true;
210 }
211 
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 #elif defined(TARGET_OS_BRIDGE) && TARGET_OS_BRIDGE == 1
258  arch_32.GetTriple().setOS(llvm::Triple::BridgeOS);
259  arch_64.GetTriple().setOS(llvm::Triple::BridgeOS);
260 #else
261  arch_32.GetTriple().setOS(llvm::Triple::IOS);
262  arch_64.GetTriple().setOS(llvm::Triple::IOS);
263 #endif
264  } else {
265  arch_32.GetTriple().setOS(llvm::Triple::MacOSX);
266  arch_64.GetTriple().setOS(llvm::Triple::MacOSX);
267  }
268  } else {
269  // We have a 32 bit kernel on a 32 bit system
270  arch_32.SetArchitecture(eArchTypeMachO, cputype, cpusubtype);
271 #if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
272  arch_32.GetTriple().setOS(llvm::Triple::WatchOS);
273 #else
274  arch_32.GetTriple().setOS(llvm::Triple::IOS);
275 #endif
276  arch_64.Clear();
277  }
278  }
279 }
void SetString(const llvm::StringRef &s)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
static FileSpec GetProgramFileSpec()
#define CPU_SUBTYPE_X86_64_H
A file utility class.
Definition: FileSpec.h:55
An architecture specification class.
Definition: ArchSpec.h:32
static bool GetOSBuildString(std::string &s)
static FileSystem & Instance()
static llvm::VersionTuple GetOSVersion()
char * realpath(const char *name, char *resolved)
Definition: Windows.cpp:90
static bool GetOSKernelDescription(std::string &s)
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:431
static FileSpec GetShlibDir()
Returns the directory containing the lldb shared library.
void Clear()
Clears the object state.
Definition: ArchSpec.cpp:580
static bool ComputeUserPluginsDirectory(FileSpec &file_spec)
static void ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64)
static bool ComputeHeaderDirectory(FileSpec &file_spec)
#define LIBLLDB_LOG_HOST
Definition: Logging.h:28
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:57
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec)
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
ConstString & GetDirectory()
Directory string get accessor.
Definition: FileSpec.cpp:363
#define CPU_TYPE_ARM64
#define PATH_MAX
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:198
static bool ComputeSupportExeDirectory(FileSpec &file_spec)
bool SetArchitecture(ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os=0)
Change the architecture object type, CPU type and OS type.
Definition: ArchSpec.cpp:892
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
void Printf(const char *format,...) __attribute__((format(printf
Definition: Log.cpp:113
void SetCString(const char *cstr)
Set the C string value.