]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
Vendor import of lldb trunk r290819:
[FreeBSD/FreeBSD.git] / source / Plugins / Platform / MacOSX / PlatformDarwinKernel.cpp
1 //===-- PlatformDarwinKernel.cpp -----------------------------------*- C++
2 //-*-===//
3 //
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "PlatformDarwinKernel.h"
12
13 #if defined(__APPLE__) // This Plugin uses the Mac-specific
14                        // source/Host/macosx/cfcpp utilities
15
16 // C Includes
17 // C++ Includes
18 // Other libraries and framework includes
19 // Project includes
20 #include "lldb/Breakpoint/BreakpointLocation.h"
21 #include "lldb/Core/ArchSpec.h"
22 #include "lldb/Core/Error.h"
23 #include "lldb/Core/Log.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/ModuleList.h"
26 #include "lldb/Core/ModuleSpec.h"
27 #include "lldb/Core/PluginManager.h"
28 #include "lldb/Core/StreamString.h"
29 #include "lldb/Host/FileSpec.h"
30 #include "lldb/Host/Host.h"
31 #include "lldb/Interpreter/OptionValueFileSpecList.h"
32 #include "lldb/Interpreter/OptionValueProperties.h"
33 #include "lldb/Interpreter/Property.h"
34 #include "lldb/Symbol/ObjectFile.h"
35 #include "lldb/Target/Platform.h"
36 #include "lldb/Target/Process.h"
37 #include "lldb/Target/Target.h"
38
39 #include <CoreFoundation/CoreFoundation.h>
40
41 #include "Host/macosx/cfcpp/CFCBundle.h"
42
43 using namespace lldb;
44 using namespace lldb_private;
45
46 //------------------------------------------------------------------
47 // Static Variables
48 //------------------------------------------------------------------
49 static uint32_t g_initialize_count = 0;
50
51 //------------------------------------------------------------------
52 // Static Functions
53 //------------------------------------------------------------------
54 void PlatformDarwinKernel::Initialize() {
55   PlatformDarwin::Initialize();
56
57   if (g_initialize_count++ == 0) {
58     PluginManager::RegisterPlugin(PlatformDarwinKernel::GetPluginNameStatic(),
59                                   PlatformDarwinKernel::GetDescriptionStatic(),
60                                   PlatformDarwinKernel::CreateInstance,
61                                   PlatformDarwinKernel::DebuggerInitialize);
62   }
63 }
64
65 void PlatformDarwinKernel::Terminate() {
66   if (g_initialize_count > 0) {
67     if (--g_initialize_count == 0) {
68       PluginManager::UnregisterPlugin(PlatformDarwinKernel::CreateInstance);
69     }
70   }
71
72   PlatformDarwin::Terminate();
73 }
74
75 PlatformSP PlatformDarwinKernel::CreateInstance(bool force,
76                                                 const ArchSpec *arch) {
77   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
78   if (log) {
79     const char *arch_name;
80     if (arch && arch->GetArchitectureName())
81       arch_name = arch->GetArchitectureName();
82     else
83       arch_name = "<null>";
84
85     const char *triple_cstr =
86         arch ? arch->GetTriple().getTriple().c_str() : "<null>";
87
88     log->Printf("PlatformDarwinKernel::%s(force=%s, arch={%s,%s})",
89                 __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr);
90   }
91
92   // This is a special plugin that we don't want to activate just based on an
93   // ArchSpec for normal
94   // userland debugging.  It is only useful in kernel debug sessions and the
95   // DynamicLoaderDarwinPlugin
96   // (or a user doing 'platform select') will force the creation of this
97   // Platform plugin.
98   if (force == false) {
99     if (log)
100       log->Printf("PlatformDarwinKernel::%s() aborting creation of platform "
101                   "because force == false",
102                   __FUNCTION__);
103     return PlatformSP();
104   }
105
106   bool create = force;
107   LazyBool is_ios_debug_session = eLazyBoolCalculate;
108
109   if (create == false && arch && arch->IsValid()) {
110     const llvm::Triple &triple = arch->GetTriple();
111     switch (triple.getVendor()) {
112     case llvm::Triple::Apple:
113       create = true;
114       break;
115
116     // Only accept "unknown" for vendor if the host is Apple and
117     // it "unknown" wasn't specified (it was just returned because it
118     // was NOT specified)
119     case llvm::Triple::UnknownArch:
120       create = !arch->TripleVendorWasSpecified();
121       break;
122     default:
123       break;
124     }
125
126     if (create) {
127       switch (triple.getOS()) {
128       case llvm::Triple::Darwin:
129       case llvm::Triple::MacOSX:
130       case llvm::Triple::IOS:
131       case llvm::Triple::WatchOS:
132       case llvm::Triple::TvOS:
133         break;
134       // Only accept "vendor" for vendor if the host is Apple and
135       // it "unknown" wasn't specified (it was just returned because it
136       // was NOT specified)
137       case llvm::Triple::UnknownOS:
138         create = !arch->TripleOSWasSpecified();
139         break;
140       default:
141         create = false;
142         break;
143       }
144     }
145   }
146   if (arch && arch->IsValid()) {
147     switch (arch->GetMachine()) {
148     case llvm::Triple::x86:
149     case llvm::Triple::x86_64:
150     case llvm::Triple::ppc:
151     case llvm::Triple::ppc64:
152       is_ios_debug_session = eLazyBoolNo;
153       break;
154     case llvm::Triple::arm:
155     case llvm::Triple::aarch64:
156     case llvm::Triple::thumb:
157       is_ios_debug_session = eLazyBoolYes;
158       break;
159     default:
160       is_ios_debug_session = eLazyBoolCalculate;
161       break;
162     }
163   }
164   if (create) {
165     if (log)
166       log->Printf("PlatformDarwinKernel::%s() creating platform", __FUNCTION__);
167
168     return PlatformSP(new PlatformDarwinKernel(is_ios_debug_session));
169   }
170
171   if (log)
172     log->Printf("PlatformDarwinKernel::%s() aborting creation of platform",
173                 __FUNCTION__);
174
175   return PlatformSP();
176 }
177
178 lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() {
179   static ConstString g_name("darwin-kernel");
180   return g_name;
181 }
182
183 const char *PlatformDarwinKernel::GetDescriptionStatic() {
184   return "Darwin Kernel platform plug-in.";
185 }
186
187 //------------------------------------------------------------------
188 /// Code to handle the PlatformDarwinKernel settings
189 //------------------------------------------------------------------
190
191 static PropertyDefinition g_properties[] = {
192     {"search-locally-for-kexts", OptionValue::eTypeBoolean, true, true, NULL,
193      NULL, "Automatically search for kexts on the local system when doing "
194            "kernel debugging."},
195     {"kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL,
196      "Directories/KDKs to search for kexts in when starting a kernel debug "
197      "session."},
198     {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
199
200 enum { ePropertySearchForKexts = 0, ePropertyKextDirectories };
201
202 class PlatformDarwinKernelProperties : public Properties {
203 public:
204   static ConstString &GetSettingName() {
205     static ConstString g_setting_name("darwin-kernel");
206     return g_setting_name;
207   }
208
209   PlatformDarwinKernelProperties() : Properties() {
210     m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
211     m_collection_sp->Initialize(g_properties);
212   }
213
214   virtual ~PlatformDarwinKernelProperties() {}
215
216   bool GetSearchForKexts() const {
217     const uint32_t idx = ePropertySearchForKexts;
218     return m_collection_sp->GetPropertyAtIndexAsBoolean(
219         NULL, idx, g_properties[idx].default_uint_value != 0);
220   }
221
222   FileSpecList &GetKextDirectories() const {
223     const uint32_t idx = ePropertyKextDirectories;
224     OptionValueFileSpecList *option_value =
225         m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList(
226             NULL, false, idx);
227     assert(option_value);
228     return option_value->GetCurrentValue();
229   }
230 };
231
232 typedef std::shared_ptr<PlatformDarwinKernelProperties>
233     PlatformDarwinKernelPropertiesSP;
234
235 static const PlatformDarwinKernelPropertiesSP &GetGlobalProperties() {
236   static PlatformDarwinKernelPropertiesSP g_settings_sp;
237   if (!g_settings_sp)
238     g_settings_sp.reset(new PlatformDarwinKernelProperties());
239   return g_settings_sp;
240 }
241
242 void PlatformDarwinKernel::DebuggerInitialize(
243     lldb_private::Debugger &debugger) {
244   if (!PluginManager::GetSettingForPlatformPlugin(
245           debugger, PlatformDarwinKernelProperties::GetSettingName())) {
246     const bool is_global_setting = true;
247     PluginManager::CreateSettingForPlatformPlugin(
248         debugger, GetGlobalProperties()->GetValueProperties(),
249         ConstString("Properties for the PlatformDarwinKernel plug-in."),
250         is_global_setting);
251   }
252 }
253
254 //------------------------------------------------------------------
255 /// Default Constructor
256 //------------------------------------------------------------------
257 PlatformDarwinKernel::PlatformDarwinKernel(
258     lldb_private::LazyBool is_ios_debug_session)
259     : PlatformDarwin(false), // This is a remote platform
260       m_name_to_kext_path_map_with_dsyms(),
261       m_name_to_kext_path_map_without_dsyms(), m_search_directories(),
262       m_search_directories_no_recursing(), m_kernel_binaries_with_dsyms(),
263       m_kernel_binaries_without_dsyms(),
264       m_ios_debug_session(is_ios_debug_session)
265
266 {
267   if (GetGlobalProperties()->GetSearchForKexts()) {
268     CollectKextAndKernelDirectories();
269     SearchForKextsAndKernelsRecursively();
270   }
271 }
272
273 //------------------------------------------------------------------
274 /// Destructor.
275 ///
276 /// The destructor is virtual since this class is designed to be
277 /// inherited from by the plug-in instance.
278 //------------------------------------------------------------------
279 PlatformDarwinKernel::~PlatformDarwinKernel() {}
280
281 void PlatformDarwinKernel::GetStatus(Stream &strm) {
282   Platform::GetStatus(strm);
283   strm.Printf(" Debug session type: ");
284   if (m_ios_debug_session == eLazyBoolYes)
285     strm.Printf("iOS kernel debugging\n");
286   else if (m_ios_debug_session == eLazyBoolNo)
287     strm.Printf("Mac OS X kernel debugging\n");
288   else
289     strm.Printf("unknown kernel debugging\n");
290
291   strm.Printf("Directories searched recursively:\n");
292   const uint32_t num_kext_dirs = m_search_directories.size();
293   for (uint32_t i = 0; i < num_kext_dirs; ++i) {
294     strm.Printf("[%d] %s\n", i, m_search_directories[i].GetPath().c_str());
295   }
296
297   strm.Printf("Directories not searched recursively:\n");
298   const uint32_t num_kext_dirs_no_recursion =
299       m_search_directories_no_recursing.size();
300   for (uint32_t i = 0; i < num_kext_dirs_no_recursion; i++) {
301     strm.Printf("[%d] %s\n", i,
302                 m_search_directories_no_recursing[i].GetPath().c_str());
303   }
304
305   strm.Printf(" Number of kexts with dSYMs indexed: %d\n",
306               (int)m_name_to_kext_path_map_with_dsyms.size());
307   strm.Printf(" Number of kexts without dSYMs indexed: %d\n",
308               (int)m_name_to_kext_path_map_without_dsyms.size());
309   strm.Printf(" Number of Kernel binaries with dSYMs indexed: %d\n",
310               (int)m_kernel_binaries_with_dsyms.size());
311   strm.Printf(" Number of Kernel binaries without dSYMs indexed: %d\n",
312               (int)m_kernel_binaries_without_dsyms.size());
313
314   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
315   if (log) {
316     log->Printf("\nkexts with dSYMs");
317     for (auto pos : m_name_to_kext_path_map_with_dsyms) {
318       log->Printf("%s", pos.second.GetPath().c_str());
319     }
320     log->Printf("\nkexts without dSYMs");
321
322     for (auto pos : m_name_to_kext_path_map_without_dsyms) {
323       log->Printf("%s", pos.second.GetPath().c_str());
324     }
325     log->Printf("\nkernels with dSYMS");
326     for (auto fs : m_kernel_binaries_with_dsyms) {
327       log->Printf("%s", fs.GetPath().c_str());
328     }
329     log->Printf("\nkernels without dSYMS");
330     for (auto fs : m_kernel_binaries_without_dsyms) {
331       log->Printf("%s", fs.GetPath().c_str());
332     }
333     log->Printf("\n");
334   }
335 }
336
337 // Populate the m_search_directories vector with directories we should search
338 // for kernel & kext binaries.
339
340 void PlatformDarwinKernel::CollectKextAndKernelDirectories() {
341   // Differentiate between "ios debug session" and "mac debug session" so we
342   // don't index
343   // kext bundles that won't be used in this debug session.  If this is an ios
344   // kext debug
345   // session, looking in /System/Library/Extensions is a waste of stat()s, for
346   // example.
347
348   // DeveloperDirectory is something like
349   // "/Applications/Xcode.app/Contents/Developer"
350   std::string developer_dir = GetDeveloperDirectory();
351   if (developer_dir.empty())
352     developer_dir = "/Applications/Xcode.app/Contents/Developer";
353
354   if (m_ios_debug_session != eLazyBoolNo) {
355     AddSDKSubdirsToSearchPaths(developer_dir +
356                                "/Platforms/iPhoneOS.platform/Developer/SDKs");
357     AddSDKSubdirsToSearchPaths(developer_dir +
358                                "/Platforms/AppleTVOS.platform/Developer/SDKs");
359     AddSDKSubdirsToSearchPaths(developer_dir +
360                                "/Platforms/WatchOS.platform/Developer/SDKs");
361   }
362   if (m_ios_debug_session != eLazyBoolYes) {
363     AddSDKSubdirsToSearchPaths(developer_dir +
364                                "/Platforms/MacOSX.platform/Developer/SDKs");
365   }
366
367   AddSDKSubdirsToSearchPaths("/Volumes/KernelDebugKit");
368   AddSDKSubdirsToSearchPaths("/AppleInternal/Developer/KDKs");
369   // The KDKs distributed from Apple installed on external
370   // developer systems may be in directories like
371   // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
372   AddSDKSubdirsToSearchPaths("/Library/Developer/KDKs");
373
374   if (m_ios_debug_session != eLazyBoolNo) {
375   }
376   if (m_ios_debug_session != eLazyBoolYes) {
377     AddRootSubdirsToSearchPaths(this, "/");
378   }
379
380   GetUserSpecifiedDirectoriesToSearch();
381
382   // Add simple directory /Applications/Xcode.app/Contents/Developer/../Symbols
383   FileSpec possible_dir(developer_dir + "/../Symbols", true);
384   if (possible_dir.Exists() && possible_dir.IsDirectory())
385     m_search_directories.push_back(possible_dir);
386
387   // Add simple directory of the current working directory
388   m_search_directories_no_recursing.push_back(FileSpec(".", true));
389 }
390
391 void PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch() {
392   FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories());
393   std::vector<FileSpec> possible_sdk_dirs;
394
395   const uint32_t user_dirs_count = user_dirs.GetSize();
396   for (uint32_t i = 0; i < user_dirs_count; i++) {
397     FileSpec dir = user_dirs.GetFileSpecAtIndex(i);
398     dir.ResolvePath();
399     if (dir.Exists() && dir.IsDirectory()) {
400       m_search_directories.push_back(dir);
401     }
402   }
403 }
404
405 void PlatformDarwinKernel::AddRootSubdirsToSearchPaths(
406     PlatformDarwinKernel *thisp, const std::string &dir) {
407   const char *subdirs[] = {
408       "/System/Library/Extensions", "/Library/Extensions",
409       "/System/Library/Kernels",
410       "/System/Library/Extensions/KDK", // this one probably only exist in
411                                         // /AppleInternal/Developer/KDKs/*.kdk/...
412       nullptr};
413   for (int i = 0; subdirs[i] != nullptr; i++) {
414     FileSpec testdir(dir + subdirs[i], true);
415     if (testdir.Exists() && testdir.IsDirectory())
416       thisp->m_search_directories.push_back(testdir);
417   }
418
419   // Look for kernel binaries in the top level directory, without any recursion
420   thisp->m_search_directories_no_recursing.push_back(
421       FileSpec(dir + "/", false));
422 }
423
424 // Given a directory path dir, look for any subdirs named *.kdk and *.sdk
425 void PlatformDarwinKernel::AddSDKSubdirsToSearchPaths(const std::string &dir) {
426   // Look for *.kdk and *.sdk in dir
427   const bool find_directories = true;
428   const bool find_files = false;
429   const bool find_other = false;
430   FileSpec::EnumerateDirectory(dir.c_str(), find_directories, find_files,
431                                find_other, FindKDKandSDKDirectoriesInDirectory,
432                                this);
433 }
434
435 // Helper function to find *.sdk and *.kdk directories in a given directory.
436 FileSpec::EnumerateDirectoryResult
437 PlatformDarwinKernel::FindKDKandSDKDirectoriesInDirectory(
438     void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) {
439   static ConstString g_sdk_suffix = ConstString("sdk");
440   static ConstString g_kdk_suffix = ConstString("kdk");
441
442   PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
443   if (file_type == FileSpec::eFileTypeDirectory &&
444       (file_spec.GetFileNameExtension() == g_sdk_suffix ||
445        file_spec.GetFileNameExtension() == g_kdk_suffix)) {
446     AddRootSubdirsToSearchPaths(thisp, file_spec.GetPath());
447   }
448   return FileSpec::eEnumerateDirectoryResultNext;
449 }
450
451 // Recursively search trough m_search_directories looking for
452 // kext and kernel binaries, adding files found to the appropriate
453 // lists.
454 void PlatformDarwinKernel::SearchForKextsAndKernelsRecursively() {
455   const uint32_t num_dirs = m_search_directories.size();
456   for (uint32_t i = 0; i < num_dirs; i++) {
457     const FileSpec &dir = m_search_directories[i];
458     const bool find_directories = true;
459     const bool find_files = true;
460     const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
461     FileSpec::EnumerateDirectory(
462         dir.GetPath().c_str(), find_directories, find_files, find_other,
463         GetKernelsAndKextsInDirectoryWithRecursion, this);
464   }
465   const uint32_t num_dirs_no_recurse = m_search_directories_no_recursing.size();
466   for (uint32_t i = 0; i < num_dirs_no_recurse; i++) {
467     const FileSpec &dir = m_search_directories_no_recursing[i];
468     const bool find_directories = true;
469     const bool find_files = true;
470     const bool find_other = true; // I think eFileTypeSymbolicLink are "other"s.
471     FileSpec::EnumerateDirectory(
472         dir.GetPath().c_str(), find_directories, find_files, find_other,
473         GetKernelsAndKextsInDirectoryNoRecursion, this);
474   }
475 }
476
477 // We're only doing a filename match here.  We won't try opening the file to see
478 // if it's really
479 // a kernel or not until we need to find a kernel of a given UUID.  There's no
480 // cheap way to find
481 // the UUID of a file (or if it's a Mach-O binary at all) without creating a
482 // whole Module for
483 // the file and throwing it away if it's not wanted.
484 //
485 // Recurse into any subdirectories found.
486
487 FileSpec::EnumerateDirectoryResult
488 PlatformDarwinKernel::GetKernelsAndKextsInDirectoryWithRecursion(
489     void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) {
490   return GetKernelsAndKextsInDirectoryHelper(baton, file_type, file_spec, true);
491 }
492
493 FileSpec::EnumerateDirectoryResult
494 PlatformDarwinKernel::GetKernelsAndKextsInDirectoryNoRecursion(
495     void *baton, FileSpec::FileType file_type, const FileSpec &file_spec) {
496   return GetKernelsAndKextsInDirectoryHelper(baton, file_type, file_spec,
497                                              false);
498 }
499
500 FileSpec::EnumerateDirectoryResult
501 PlatformDarwinKernel::GetKernelsAndKextsInDirectoryHelper(
502     void *baton, FileSpec::FileType file_type, const FileSpec &file_spec,
503     bool recurse) {
504   static ConstString g_kext_suffix = ConstString("kext");
505   static ConstString g_dsym_suffix = ConstString("dSYM");
506   static ConstString g_bundle_suffix = ConstString("Bundle");
507   ConstString file_spec_extension = file_spec.GetFileNameExtension();
508
509   Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
510   if (log)
511     log->Printf("PlatformDarwinKernel examining %s",
512                 file_spec.GetPath().c_str());
513
514   PlatformDarwinKernel *thisp = (PlatformDarwinKernel *)baton;
515   if (file_type == FileSpec::eFileTypeRegular ||
516       file_type == FileSpec::eFileTypeSymbolicLink) {
517     ConstString filename = file_spec.GetFilename();
518     if ((strncmp(filename.GetCString(), "kernel", 6) == 0 ||
519          strncmp(filename.GetCString(), "mach", 4) == 0) &&
520         file_spec_extension != g_dsym_suffix) {
521       if (KernelHasdSYMSibling(file_spec))
522         thisp->m_kernel_binaries_with_dsyms.push_back(file_spec);
523       else
524         thisp->m_kernel_binaries_without_dsyms.push_back(file_spec);
525       return FileSpec::eEnumerateDirectoryResultNext;
526     }
527   } else if (file_type == FileSpec::eFileTypeDirectory &&
528              file_spec_extension == g_kext_suffix) {
529     AddKextToMap(thisp, file_spec);
530     // Look to see if there is a PlugIns subdir with more kexts
531     FileSpec contents_plugins(file_spec.GetPath() + "/Contents/PlugIns", false);
532     std::string search_here_too;
533     if (contents_plugins.Exists() && contents_plugins.IsDirectory()) {
534       search_here_too = contents_plugins.GetPath();
535     } else {
536       FileSpec plugins(file_spec.GetPath() + "/PlugIns", false);
537       if (plugins.Exists() && plugins.IsDirectory()) {
538         search_here_too = plugins.GetPath();
539       }
540     }
541
542     if (!search_here_too.empty()) {
543       const bool find_directories = true;
544       const bool find_files = false;
545       const bool find_other = false;
546       FileSpec::EnumerateDirectory(
547           search_here_too.c_str(), find_directories, find_files, find_other,
548           recurse ? GetKernelsAndKextsInDirectoryWithRecursion
549                   : GetKernelsAndKextsInDirectoryNoRecursion,
550           baton);
551     }
552     return FileSpec::eEnumerateDirectoryResultNext;
553   }
554   // Don't recurse into dSYM/kext/bundle directories
555   if (recurse && file_spec_extension != g_dsym_suffix &&
556       file_spec_extension != g_kext_suffix &&
557       file_spec_extension != g_bundle_suffix) {
558     return FileSpec::eEnumerateDirectoryResultEnter;
559   } else {
560     return FileSpec::eEnumerateDirectoryResultNext;
561   }
562 }
563
564 void PlatformDarwinKernel::AddKextToMap(PlatformDarwinKernel *thisp,
565                                         const FileSpec &file_spec) {
566   CFCBundle bundle(file_spec.GetPath().c_str());
567   CFStringRef bundle_id(bundle.GetIdentifier());
568   if (bundle_id && CFGetTypeID(bundle_id) == CFStringGetTypeID()) {
569     char bundle_id_buf[PATH_MAX];
570     if (CFStringGetCString(bundle_id, bundle_id_buf, sizeof(bundle_id_buf),
571                            kCFStringEncodingUTF8)) {
572       ConstString bundle_conststr(bundle_id_buf);
573       if (KextHasdSYMSibling(file_spec))
574         thisp->m_name_to_kext_path_map_with_dsyms.insert(
575             std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
576       else
577         thisp->m_name_to_kext_path_map_without_dsyms.insert(
578             std::pair<ConstString, FileSpec>(bundle_conststr, file_spec));
579     }
580   }
581 }
582
583 // Given a FileSpec of /dir/dir/foo.kext
584 // Return true if any of these exist:
585 //    /dir/dir/foo.kext.dSYM
586 //    /dir/dir/foo.kext/Contents/MacOS/foo.dSYM
587 //    /dir/dir/foo.kext/foo.dSYM
588 bool PlatformDarwinKernel::KextHasdSYMSibling(
589     const FileSpec &kext_bundle_filepath) {
590   FileSpec dsym_fspec = kext_bundle_filepath;
591   std::string filename = dsym_fspec.GetFilename().AsCString();
592   filename += ".dSYM";
593   dsym_fspec.GetFilename() = ConstString(filename);
594   if (dsym_fspec.Exists() && dsym_fspec.IsDirectory()) {
595     return true;
596   }
597   // Should probably get the CFBundleExecutable here or call
598   // CFBundleCopyExecutableURL
599
600   // Look for a deep bundle foramt
601   ConstString executable_name =
602       kext_bundle_filepath.GetFileNameStrippingExtension();
603   std::string deep_bundle_str =
604       kext_bundle_filepath.GetPath() + "/Contents/MacOS/";
605   deep_bundle_str += executable_name.AsCString();
606   deep_bundle_str += ".dSYM";
607   dsym_fspec.SetFile(deep_bundle_str, true);
608   if (dsym_fspec.Exists() && dsym_fspec.IsDirectory()) {
609     return true;
610   }
611
612   // look for a shallow bundle format
613   //
614   std::string shallow_bundle_str = kext_bundle_filepath.GetPath() + "/";
615   shallow_bundle_str += executable_name.AsCString();
616   shallow_bundle_str += ".dSYM";
617   dsym_fspec.SetFile(shallow_bundle_str, true);
618   if (dsym_fspec.Exists() && dsym_fspec.IsDirectory()) {
619     return true;
620   }
621   return false;
622 }
623
624 // Given a FileSpec of /dir/dir/mach.development.t7004
625 // Return true if a dSYM exists next to it:
626 //    /dir/dir/mach.development.t7004.dSYM
627 bool PlatformDarwinKernel::KernelHasdSYMSibling(const FileSpec &kernel_binary) {
628   FileSpec kernel_dsym = kernel_binary;
629   std::string filename = kernel_binary.GetFilename().AsCString();
630   filename += ".dSYM";
631   kernel_dsym.GetFilename() = ConstString(filename);
632   if (kernel_dsym.Exists() && kernel_dsym.IsDirectory()) {
633     return true;
634   }
635   return false;
636 }
637
638 Error PlatformDarwinKernel::GetSharedModule(
639     const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp,
640     const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr,
641     bool *did_create_ptr) {
642   Error error;
643   module_sp.reset();
644   const FileSpec &platform_file = module_spec.GetFileSpec();
645
646   // Treat the file's path as a kext bundle ID (e.g.
647   // "com.apple.driver.AppleIRController") and search our kext index.
648   std::string kext_bundle_id = platform_file.GetPath();
649   if (!kext_bundle_id.empty()) {
650     ConstString kext_bundle_cs(kext_bundle_id.c_str());
651
652     // First look through the kext bundles that had a dsym next to them
653     if (m_name_to_kext_path_map_with_dsyms.count(kext_bundle_cs) > 0) {
654       for (BundleIDToKextIterator it =
655                m_name_to_kext_path_map_with_dsyms.begin();
656            it != m_name_to_kext_path_map_with_dsyms.end(); ++it) {
657         if (it->first == kext_bundle_cs) {
658           error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(),
659                                              module_spec.GetArchitecture(),
660                                              module_sp);
661           if (module_sp.get()) {
662             return error;
663           }
664         }
665       }
666     }
667
668     // Second look through the kext binarys without dSYMs
669     if (m_name_to_kext_path_map_without_dsyms.count(kext_bundle_cs) > 0) {
670       for (BundleIDToKextIterator it =
671                m_name_to_kext_path_map_without_dsyms.begin();
672            it != m_name_to_kext_path_map_without_dsyms.end(); ++it) {
673         if (it->first == kext_bundle_cs) {
674           error = ExamineKextForMatchingUUID(it->second, module_spec.GetUUID(),
675                                              module_spec.GetArchitecture(),
676                                              module_sp);
677           if (module_sp.get()) {
678             return error;
679           }
680         }
681       }
682     }
683   }
684
685   if (kext_bundle_id.compare("mach_kernel") == 0 &&
686       module_spec.GetUUID().IsValid()) {
687     // First try all kernel binaries that have a dSYM next to them
688     for (auto possible_kernel : m_kernel_binaries_with_dsyms) {
689       if (possible_kernel.Exists()) {
690         ModuleSpec kern_spec(possible_kernel);
691         kern_spec.GetUUID() = module_spec.GetUUID();
692         ModuleSP module_sp(new Module(kern_spec));
693         if (module_sp && module_sp->GetObjectFile() &&
694             module_sp->MatchesModuleSpec(kern_spec)) {
695           // module_sp is an actual kernel binary we want to add.
696           if (process) {
697             process->GetTarget().GetImages().AppendIfNeeded(module_sp);
698             error.Clear();
699             return error;
700           } else {
701             error = ModuleList::GetSharedModule(kern_spec, module_sp, NULL,
702                                                 NULL, NULL);
703             if (module_sp && module_sp->GetObjectFile() &&
704                 module_sp->GetObjectFile()->GetType() !=
705                     ObjectFile::Type::eTypeCoreFile) {
706               return error;
707             }
708             module_sp.reset();
709           }
710         }
711       }
712     }
713     // Second try all kernel binaries that don't have a dSYM
714     for (auto possible_kernel : m_kernel_binaries_without_dsyms) {
715       if (possible_kernel.Exists()) {
716         ModuleSpec kern_spec(possible_kernel);
717         kern_spec.GetUUID() = module_spec.GetUUID();
718         ModuleSP module_sp(new Module(kern_spec));
719         if (module_sp && module_sp->GetObjectFile() &&
720             module_sp->MatchesModuleSpec(kern_spec)) {
721           // module_sp is an actual kernel binary we want to add.
722           if (process) {
723             process->GetTarget().GetImages().AppendIfNeeded(module_sp);
724             error.Clear();
725             return error;
726           } else {
727             error = ModuleList::GetSharedModule(kern_spec, module_sp, NULL,
728                                                 NULL, NULL);
729             if (module_sp && module_sp->GetObjectFile() &&
730                 module_sp->GetObjectFile()->GetType() !=
731                     ObjectFile::Type::eTypeCoreFile) {
732               return error;
733             }
734             module_sp.reset();
735           }
736         }
737       }
738     }
739   }
740
741   // Else fall back to treating the file's path as an actual file path - defer
742   // to PlatformDarwin's GetSharedModule.
743   return PlatformDarwin::GetSharedModule(module_spec, process, module_sp,
744                                          module_search_paths_ptr,
745                                          old_module_sp_ptr, did_create_ptr);
746 }
747
748 Error PlatformDarwinKernel::ExamineKextForMatchingUUID(
749     const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid,
750     const ArchSpec &arch, ModuleSP &exe_module_sp) {
751   Error error;
752   FileSpec exe_file = kext_bundle_path;
753   Host::ResolveExecutableInBundle(exe_file);
754   if (exe_file.Exists()) {
755     ModuleSpec exe_spec(exe_file);
756     exe_spec.GetUUID() = uuid;
757     if (!uuid.IsValid()) {
758       exe_spec.GetArchitecture() = arch;
759     }
760
761     // First try to create a ModuleSP with the file / arch and see if the UUID
762     // matches.
763     // If that fails (this exec file doesn't have the correct uuid), don't call
764     // GetSharedModule
765     // (which may call in to the DebugSymbols framework and therefore can be
766     // slow.)
767     ModuleSP module_sp(new Module(exe_spec));
768     if (module_sp && module_sp->GetObjectFile() &&
769         module_sp->MatchesModuleSpec(exe_spec)) {
770       error = ModuleList::GetSharedModule(exe_spec, exe_module_sp, NULL, NULL,
771                                           NULL);
772       if (exe_module_sp && exe_module_sp->GetObjectFile()) {
773         return error;
774       }
775     }
776     exe_module_sp.reset();
777   }
778   return error;
779 }
780
781 bool PlatformDarwinKernel::GetSupportedArchitectureAtIndex(uint32_t idx,
782                                                            ArchSpec &arch) {
783 #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
784   return ARMGetSupportedArchitectureAtIndex(idx, arch);
785 #else
786   return x86GetSupportedArchitectureAtIndex(idx, arch);
787 #endif
788 }
789
790 void PlatformDarwinKernel::CalculateTrapHandlerSymbolNames() {
791   m_trap_handlers.push_back(ConstString("trap_from_kernel"));
792   m_trap_handlers.push_back(ConstString("hndl_machine_check"));
793   m_trap_handlers.push_back(ConstString("hndl_double_fault"));
794   m_trap_handlers.push_back(ConstString("hndl_allintrs"));
795   m_trap_handlers.push_back(ConstString("hndl_alltraps"));
796   m_trap_handlers.push_back(ConstString("interrupt"));
797   m_trap_handlers.push_back(ConstString("fleh_prefabt"));
798   m_trap_handlers.push_back(ConstString("ExceptionVectorsBase"));
799   m_trap_handlers.push_back(ConstString("ExceptionVectorsTable"));
800   m_trap_handlers.push_back(ConstString("fleh_undef"));
801   m_trap_handlers.push_back(ConstString("fleh_dataabt"));
802   m_trap_handlers.push_back(ConstString("fleh_irq"));
803   m_trap_handlers.push_back(ConstString("fleh_decirq"));
804   m_trap_handlers.push_back(ConstString("fleh_fiq_generic"));
805   m_trap_handlers.push_back(ConstString("fleh_dec"));
806 }
807
808 #else // __APPLE__
809
810 // Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on
811 // PlatformDarwinKernel for the plug-in name, we compile just the plug-in name
812 // in
813 // here to avoid issues. We are tracking an internal bug to resolve this issue
814 // by
815 // either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to
816 // make
817 // PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently
818 // not
819 // compiled on other platforms due to the use of the Mac-specific
820 // source/Host/macosx/cfcpp utilities.
821
822 lldb_private::ConstString PlatformDarwinKernel::GetPluginNameStatic() {
823   static lldb_private::ConstString g_name("darwin-kernel");
824   return g_name;
825 }
826
827 #endif // __APPLE__