1 //===-- PlatformDarwinKernel.cpp -----------------------------------*- 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 "PlatformDarwinKernel.h"
11 
12 #if defined (__APPLE__)  // This Plugin uses the Mac-specific source/Host/macosx/cfcpp utilities
13 
14 
15 // C Includes
16 // C++ Includes
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Core/ArchSpec.h"
21 #include "lldb/Core/Error.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Core/ModuleList.h"
24 #include "lldb/Core/ModuleSpec.h"
25 #include "lldb/Core/PluginManager.h"
26 #include "lldb/Core/StreamString.h"
27 #include "lldb/Host/FileSpec.h"
28 #include "lldb/Host/Host.h"
29 #include "lldb/Interpreter/OptionValueFileSpecList.h"
30 #include "lldb/Interpreter/OptionValueProperties.h"
31 #include "lldb/Interpreter/Property.h"
32 #include "lldb/Target/Platform.h"
33 #include "lldb/Target/Process.h"
34 #include "lldb/Target/Target.h"
35 
36 #include <CoreFoundation/CoreFoundation.h>
37 
38 #include "Host/macosx/cfcpp/CFCBundle.h"
39 
40 using namespace lldb;
41 using namespace lldb_private;
42 
43 //------------------------------------------------------------------
44 // Static Variables
45 //------------------------------------------------------------------
46 static uint32_t g_initialize_count = 0;
47 
48 //------------------------------------------------------------------
49 // Static Functions
50 //------------------------------------------------------------------
51 void
52 PlatformDarwinKernel::Initialize ()
53 {
54     PlatformDarwin::Initialize ();
55 
56     if (g_initialize_count++ == 0)
57     {
58         PluginManager::RegisterPlugin (PlatformDarwinKernel::GetPluginNameStatic(),
59                                        PlatformDarwinKernel::GetDescriptionStatic(),
60                                        PlatformDarwinKernel::CreateInstance,
61                                        PlatformDarwinKernel::DebuggerInitialize);
62     }
63 }
64 
65 void
66 PlatformDarwinKernel::Terminate ()
67 {
68     if (g_initialize_count > 0)
69     {
70         if (--g_initialize_count == 0)
71         {
72             PluginManager::UnregisterPlugin (PlatformDarwinKernel::CreateInstance);
73         }
74     }
75 
76     PlatformDarwin::Terminate ();
77 }
78 
79 PlatformSP
80 PlatformDarwinKernel::CreateInstance (bool force, const ArchSpec *arch)
81 {
82     // This is a special plugin that we don't want to activate just based on an ArchSpec for normal
83     // userland debugging.  It is only useful in kernel debug sessions and the DynamicLoaderDarwinPlugin
84     // (or a user doing 'platform select') will force the creation of this Platform plugin.
85     if (force == false)
86         return PlatformSP();
87 
88     bool create = force;
89     LazyBool is_ios_debug_session = eLazyBoolCalculate;
90 
91     if (create == false && arch && arch->IsValid())
92     {
93         const llvm::Triple &triple = arch->GetTriple();
94         switch (triple.getVendor())
95         {
96             case llvm::Triple::Apple:
97                 create = true;
98                 break;
99 
100             // Only accept "unknown" for vendor if the host is Apple and
101             // it "unknown" wasn't specified (it was just returned because it
102             // was NOT specified)
103             case llvm::Triple::UnknownArch:
104                 create = !arch->TripleVendorWasSpecified();
105                 break;
106             default:
107                 break;
108         }
109 
110         if (create)
111         {
112             switch (triple.getOS())
113             {
114                 case llvm::Triple::Darwin:
115                 case llvm::Triple::MacOSX:
116                 case llvm::Triple::IOS:
117                 case llvm::Triple::WatchOS:
118                 case llvm::Triple::TvOS:
119                     break;
120                 // Only accept "vendor" for vendor if the host is Apple and
121                 // it "unknown" wasn't specified (it was just returned because it
122                 // was NOT specified)
123                 case llvm::Triple::UnknownOS:
124                     create = !arch->TripleOSWasSpecified();
125                     break;
126                 default:
127                     create = false;
128                     break;
129             }
130         }
131     }
132     if (arch && arch->IsValid())
133     {
134         switch (arch->GetMachine())
135         {
136         case llvm::Triple::x86:
137         case llvm::Triple::x86_64:
138         case llvm::Triple::ppc:
139         case llvm::Triple::ppc64:
140             is_ios_debug_session = eLazyBoolNo;
141             break;
142         case llvm::Triple::arm:
143         case llvm::Triple::aarch64:
144         case llvm::Triple::thumb:
145             is_ios_debug_session = eLazyBoolYes;
146             break;
147         default:
148             is_ios_debug_session = eLazyBoolCalculate;
149             break;
150         }
151     }
152     if (create)
153         return PlatformSP(new PlatformDarwinKernel (is_ios_debug_session));
154     return PlatformSP();
155 }
156 
157 
158 lldb_private::ConstString
159 PlatformDarwinKernel::GetPluginNameStatic ()
160 {
161     static ConstString g_name("darwin-kernel");
162     return g_name;
163 }
164 
165 const char *
166 PlatformDarwinKernel::GetDescriptionStatic()
167 {
168     return "Darwin Kernel platform plug-in.";
169 }
170 
171 //------------------------------------------------------------------
172 /// Code to handle the PlatformDarwinKernel settings
173 //------------------------------------------------------------------
174 
175 static PropertyDefinition
176 g_properties[] =
177 {
178     { "search-locally-for-kexts" , OptionValue::eTypeBoolean,      true, true, NULL, NULL, "Automatically search for kexts on the local system when doing kernel debugging." },
179     { "kext-directories",          OptionValue::eTypeFileSpecList, false, 0,   NULL, NULL, "Directories/KDKs to search for kexts in when starting a kernel debug session." },
180     {  NULL        , OptionValue::eTypeInvalid, false, 0  , NULL, NULL, NULL  }
181 };
182 
183 enum {
184     ePropertySearchForKexts = 0,
185     ePropertyKextDirectories
186 };
187 
188 
189 
190 class PlatformDarwinKernelProperties : public Properties
191 {
192 public:
193 
194     static ConstString &
195     GetSettingName ()
196     {
197         static ConstString g_setting_name("darwin-kernel");
198         return g_setting_name;
199     }
200 
201     PlatformDarwinKernelProperties() :
202         Properties ()
203     {
204         m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
205         m_collection_sp->Initialize(g_properties);
206     }
207 
208     virtual
209     ~PlatformDarwinKernelProperties()
210     {
211     }
212 
213     bool
214     GetSearchForKexts() const
215     {
216         const uint32_t idx = ePropertySearchForKexts;
217         return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0);
218     }
219 
220     FileSpecList &
221     GetKextDirectories() const
222     {
223         const uint32_t idx = ePropertyKextDirectories;
224         OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx);
225         assert(option_value);
226         return option_value->GetCurrentValue();
227     }
228 };
229 
230 typedef std::shared_ptr<PlatformDarwinKernelProperties> PlatformDarwinKernelPropertiesSP;
231 
232 static const PlatformDarwinKernelPropertiesSP &
233 GetGlobalProperties()
234 {
235     static PlatformDarwinKernelPropertiesSP g_settings_sp;
236     if (!g_settings_sp)
237         g_settings_sp.reset (new PlatformDarwinKernelProperties ());
238     return g_settings_sp;
239 }
240 
241 void
242 PlatformDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger)
243 {
244     if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformDarwinKernelProperties::GetSettingName()))
245     {
246         const bool is_global_setting = true;
247         PluginManager::CreateSettingForPlatformPlugin (debugger,
248                                                             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 (lldb_private::LazyBool is_ios_debug_session) :
258     PlatformDarwin (false),    // This is a remote platform
259     m_name_to_kext_path_map(),
260     m_search_directories(),
261     m_kernel_binaries(),
262     m_ios_debug_session(is_ios_debug_session)
263 
264 {
265     if (GetGlobalProperties()->GetSearchForKexts())
266     {
267         CollectKextAndKernelDirectories ();
268         IndexKextsInDirectories ();
269         IndexKernelsInDirectories ();
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 }
282 
283 
284 void
285 PlatformDarwinKernel::GetStatus (Stream &strm)
286 {
287     Platform::GetStatus (strm);
288     strm.Printf (" Debug session type: ");
289     if (m_ios_debug_session == eLazyBoolYes)
290         strm.Printf ("iOS kernel debugging\n");
291     else if (m_ios_debug_session == eLazyBoolNo)
292         strm.Printf ("Mac OS X kernel debugging\n");
293     else
294             strm.Printf ("unknown kernel debugging\n");
295     const uint32_t num_kext_dirs = m_search_directories.size();
296     for (uint32_t i=0; i<num_kext_dirs; ++i)
297     {
298         const FileSpec &kext_dir = m_search_directories[i];
299         strm.Printf (" Kext directories: [%2u] \"%s\"\n", i, kext_dir.GetPath().c_str());
300     }
301     strm.Printf (" Total number of kexts indexed: %d\n", (int) m_name_to_kext_path_map.size());
302 }
303 
304 // Populate the m_search_directories vector with directories we should search
305 // for kernel & kext binaries.
306 
307 void
308 PlatformDarwinKernel::CollectKextAndKernelDirectories ()
309 {
310     // Differentiate between "ios debug session" and "mac debug session" so we don't index
311     // kext bundles that won't be used in this debug session.  If this is an ios kext debug
312     // session, looking in /System/Library/Extensions is a waste of stat()s, for example.
313 
314     // Build up a list of all SDKs we'll be searching for directories of kexts/kernels
315     // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk
316     std::vector<FileSpec> sdk_dirs;
317     if (m_ios_debug_session != eLazyBoolNo)
318     {
319         GetiOSSDKDirectoriesToSearch (sdk_dirs);
320         GetAppleTVOSSDKDirectoriesToSearch (sdk_dirs);
321         GetWatchOSSDKDirectoriesToSearch (sdk_dirs);
322     }
323     if (m_ios_debug_session != eLazyBoolYes)
324         GetMacSDKDirectoriesToSearch (sdk_dirs);
325 
326     GetGenericSDKDirectoriesToSearch (sdk_dirs);
327 
328     // Build up a list of directories that hold may kext bundles & kernels
329     //
330     // e.g. given /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/
331     // find
332     // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/
333     // and
334     // /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/System/Library/Extensions
335 
336     std::vector<FileSpec> kext_dirs;
337     SearchSDKsForKextDirectories (sdk_dirs, kext_dirs);
338 
339     if (m_ios_debug_session != eLazyBoolNo)
340         GetiOSDirectoriesToSearch (kext_dirs);
341     if (m_ios_debug_session != eLazyBoolYes)
342         GetMacDirectoriesToSearch (kext_dirs);
343 
344     GetGenericDirectoriesToSearch (kext_dirs);
345 
346     GetUserSpecifiedDirectoriesToSearch (kext_dirs);
347 
348     GetKernelDirectoriesToSearch (kext_dirs);
349 
350     GetCurrentDirectoryToSearch (kext_dirs);
351 
352     // We now have a complete list of directories that we will search for kext bundles
353     m_search_directories = kext_dirs;
354 }
355 
356 void
357 PlatformDarwinKernel::GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
358 {
359     // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
360     const char *developer_dir = GetDeveloperDirectory();
361     if (developer_dir == NULL)
362         developer_dir = "/Applications/Xcode.app/Contents/Developer";
363 
364     char pathbuf[PATH_MAX];
365     ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/iPhoneOS.platform/Developer/SDKs", developer_dir);
366     FileSpec ios_sdk(pathbuf, true);
367     if (ios_sdk.Exists() && ios_sdk.IsDirectory())
368     {
369         directories.push_back (ios_sdk);
370     }
371 }
372 
373 void
374 PlatformDarwinKernel::GetAppleTVOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
375 {
376     // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
377     const char *developer_dir = GetDeveloperDirectory();
378     if (developer_dir == NULL)
379         developer_dir = "/Applications/Xcode.app/Contents/Developer";
380 
381     char pathbuf[PATH_MAX];
382     ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/AppleTVOS.platform/Developer/SDKs", developer_dir);
383     FileSpec ios_sdk(pathbuf, true);
384     if (ios_sdk.Exists() && ios_sdk.IsDirectory())
385     {
386         directories.push_back (ios_sdk);
387     }
388 }
389 
390 void
391 PlatformDarwinKernel::GetWatchOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
392 {
393     // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
394     const char *developer_dir = GetDeveloperDirectory();
395     if (developer_dir == NULL)
396         developer_dir = "/Applications/Xcode.app/Contents/Developer";
397 
398     char pathbuf[PATH_MAX];
399     ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/watchOS.platform/Developer/SDKs", developer_dir);
400     FileSpec ios_sdk(pathbuf, true);
401     if (ios_sdk.Exists() && ios_sdk.IsDirectory())
402     {
403         directories.push_back (ios_sdk);
404     }
405     else
406     {
407         ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/WatchOS.platform/Developer/SDKs", developer_dir);
408         FileSpec alt_watch_sdk(pathbuf, true);
409         if (ios_sdk.Exists() && ios_sdk.IsDirectory())
410         {
411             directories.push_back (ios_sdk);
412         }
413     }
414 }
415 
416 
417 void
418 PlatformDarwinKernel::GetMacSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
419 {
420     // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
421     const char *developer_dir = GetDeveloperDirectory();
422     if (developer_dir == NULL)
423         developer_dir = "/Applications/Xcode.app/Contents/Developer";
424 
425     char pathbuf[PATH_MAX];
426     ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/MacOSX.platform/Developer/SDKs", developer_dir);
427     FileSpec mac_sdk(pathbuf, true);
428     if (mac_sdk.Exists() && mac_sdk.IsDirectory())
429     {
430         directories.push_back (mac_sdk);
431     }
432 }
433 
434 void
435 PlatformDarwinKernel::GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
436 {
437     FileSpec generic_sdk("/AppleInternal/Developer/KDKs", true);
438     if (generic_sdk.Exists() && generic_sdk.IsDirectory())
439     {
440         directories.push_back (generic_sdk);
441     }
442 
443     // The KDKs distributed from Apple installed on external
444     // developer systems may be in directories like
445     // /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
446     FileSpec installed_kdks("/Library/Developer/KDKs", true);
447     if (installed_kdks.Exists() && installed_kdks.IsDirectory())
448     {
449         directories.push_back (installed_kdks);
450     }
451 }
452 
453 void
454 PlatformDarwinKernel::GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
455 {
456 }
457 
458 void
459 PlatformDarwinKernel::GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
460 {
461     FileSpec sle("/System/Library/Extensions", true);
462     if (sle.Exists() && sle.IsDirectory())
463     {
464         directories.push_back(sle);
465     }
466 
467     FileSpec le("/Library/Extensions", true);
468     if (le.Exists() && le.IsDirectory())
469     {
470         directories.push_back(le);
471     }
472 
473     FileSpec kdk("/Volumes/KernelDebugKit", true);
474     if (kdk.Exists() && kdk.IsDirectory())
475     {
476         directories.push_back(kdk);
477     }
478 }
479 
480 void
481 PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
482 {
483     // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer"
484     const char *developer_dir = GetDeveloperDirectory();
485     if (developer_dir == NULL)
486         developer_dir = "/Applications/Xcode.app/Contents/Developer";
487 
488     char pathbuf[PATH_MAX];
489     ::snprintf (pathbuf, sizeof (pathbuf), "%s/../Symbols", developer_dir);
490     FileSpec symbols_dir (pathbuf, true);
491     if (symbols_dir.Exists() && symbols_dir.IsDirectory())
492     {
493         directories.push_back (symbols_dir);
494     }
495 }
496 
497 void
498 PlatformDarwinKernel::GetKernelDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
499 {
500     FileSpec system_library_kernels ("/System/Library/Kernels", true);
501     if (system_library_kernels.Exists() && system_library_kernels.IsDirectory())
502     {
503         directories.push_back (system_library_kernels);
504     }
505     FileSpec slek("/System/Library/Extensions/KDK", true);
506     if (slek.Exists() && slek.IsDirectory())
507     {
508         directories.push_back(slek);
509     }
510 }
511 
512 void
513 PlatformDarwinKernel::GetCurrentDirectoryToSearch (std::vector<lldb_private::FileSpec> &directories)
514 {
515     directories.push_back (FileSpec (".", true));
516 
517     FileSpec sle_directory ("System/Library/Extensions", true);
518     if (sle_directory.Exists() && sle_directory.IsDirectory())
519     {
520         directories.push_back (sle_directory);
521     }
522 
523     FileSpec le_directory ("Library/Extensions", true);
524     if (le_directory.Exists() && le_directory.IsDirectory())
525     {
526         directories.push_back (le_directory);
527     }
528 
529     FileSpec slk_directory ("System/Library/Kernels", true);
530     if (slk_directory.Exists() && slk_directory.IsDirectory())
531     {
532         directories.push_back (slk_directory);
533     }
534     FileSpec slek("System/Library/Extensions/KDK", true);
535     if (slek.Exists() && slek.IsDirectory())
536     {
537         directories.push_back(slek);
538     }
539 }
540 
541 void
542 PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories)
543 {
544     FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories());
545     std::vector<FileSpec> possible_sdk_dirs;
546 
547     const uint32_t user_dirs_count = user_dirs.GetSize();
548     for (uint32_t i = 0; i < user_dirs_count; i++)
549     {
550         FileSpec dir = user_dirs.GetFileSpecAtIndex (i);
551         dir.ResolvePath();
552         if (dir.Exists() && dir.IsDirectory())
553         {
554             directories.push_back (dir);
555             possible_sdk_dirs.push_back (dir);  // does this directory have a *.sdk or *.kdk that we should look in?
556 
557             // Is there a "System/Library/Extensions" subdir of this directory?
558             std::string dir_sle_path = dir.GetPath();
559             dir_sle_path.append ("/System/Library/Extensions");
560             FileSpec dir_sle(dir_sle_path.c_str(), true);
561             if (dir_sle.Exists() && dir_sle.IsDirectory())
562             {
563                 directories.push_back (dir_sle);
564             }
565 
566             // Is there a "System/Library/Kernels" subdir of this directory?
567             std::string dir_slk_path = dir.GetPath();
568             dir_slk_path.append ("/System/Library/Kernels");
569             FileSpec dir_slk(dir_slk_path.c_str(), true);
570             if (dir_slk.Exists() && dir_slk.IsDirectory())
571             {
572                 directories.push_back (dir_slk);
573             }
574 
575             // Is there a "System/Library/Extensions/KDK" subdir of this directory?
576             std::string dir_slek_path = dir.GetPath();
577             dir_slek_path.append ("/System/Library/Kernels");
578             FileSpec dir_slek(dir_slek_path.c_str(), true);
579             if (dir_slek.Exists() && dir_slek.IsDirectory())
580             {
581                 directories.push_back (dir_slek);
582             }
583         }
584     }
585 
586     SearchSDKsForKextDirectories (possible_sdk_dirs, directories);
587 }
588 
589 // Scan through the SDK directories, looking for directories where kexts are likely.
590 // Add those directories to kext_dirs.
591 void
592 PlatformDarwinKernel::SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs)
593 {
594     const uint32_t num_sdks = sdk_dirs.size();
595     for (uint32_t i = 0; i < num_sdks; i++)
596     {
597         const FileSpec &sdk_dir = sdk_dirs[i];
598         std::string sdk_dir_path = sdk_dir.GetPath();
599         if (!sdk_dir_path.empty())
600         {
601             const bool find_directories = true;
602             const bool find_files = false;
603             const bool find_other = false;
604             FileSpec::EnumerateDirectory (sdk_dir_path.c_str(),
605                                           find_directories,
606                                           find_files,
607                                           find_other,
608                                           GetKextDirectoriesInSDK,
609                                           &kext_dirs);
610         }
611     }
612 }
613 
614 // Callback for FileSpec::EnumerateDirectory().
615 // Step through the entries in a directory like
616 //    /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs
617 // looking for any subdirectories of the form MacOSX10.8.Internal.sdk/System/Library/Extensions
618 // Adds these to the vector of FileSpec's.
619 
620 FileSpec::EnumerateDirectoryResult
621 PlatformDarwinKernel::GetKextDirectoriesInSDK (void *baton,
622                                                FileSpec::FileType file_type,
623                                                const FileSpec &file_spec)
624 {
625     if (file_type == FileSpec::eFileTypeDirectory
626         && (file_spec.GetFileNameExtension() == ConstString("sdk")
627             || file_spec.GetFileNameExtension() == ConstString("kdk")))
628     {
629         std::string kext_directory_path = file_spec.GetPath();
630 
631         // Append the raw directory path, e.g. /Library/Developer/KDKs/KDK_10.10_14A298i.kdk
632         // to the directory search list -- there may be kexts sitting directly
633         // in that directory instead of being in a System/Library/Extensions subdir.
634         ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
635 
636         // Check to see if there is a System/Library/Extensions subdir & add it if it exists
637 
638         std::string sle_kext_directory_path (kext_directory_path);
639         sle_kext_directory_path.append ("/System/Library/Extensions");
640         FileSpec sle_kext_directory (sle_kext_directory_path.c_str(), true);
641         if (sle_kext_directory.Exists() && sle_kext_directory.IsDirectory())
642         {
643             ((std::vector<lldb_private::FileSpec> *)baton)->push_back(sle_kext_directory);
644         }
645 
646         // Check to see if there is a Library/Extensions subdir & add it if it exists
647 
648         std::string le_kext_directory_path (kext_directory_path);
649         le_kext_directory_path.append ("/Library/Extensions");
650         FileSpec le_kext_directory (le_kext_directory_path.c_str(), true);
651         if (le_kext_directory.Exists() && le_kext_directory.IsDirectory())
652         {
653             ((std::vector<lldb_private::FileSpec> *)baton)->push_back(le_kext_directory);
654         }
655 
656         // Check to see if there is a System/Library/Kernels subdir & add it if it exists
657         std::string slk_kernel_path (kext_directory_path);
658         slk_kernel_path.append ("/System/Library/Kernels");
659         FileSpec slk_kernel_directory (slk_kernel_path.c_str(), true);
660         if (slk_kernel_directory.Exists() && slk_kernel_directory.IsDirectory())
661         {
662             ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slk_kernel_directory);
663         }
664 
665         // Check to see if there is a System/Library/Extensions/KDK subdir & add it if it exists
666         std::string slek_kernel_path (kext_directory_path);
667         slek_kernel_path.append ("/System/Library/Extensions/KDK");
668         FileSpec slek_kernel_directory (slek_kernel_path.c_str(), true);
669         if (slek_kernel_directory.Exists() && slek_kernel_directory.IsDirectory())
670         {
671             ((std::vector<lldb_private::FileSpec> *)baton)->push_back(slek_kernel_directory);
672         }
673     }
674     return FileSpec::eEnumerateDirectoryResultNext;
675 }
676 
677 void
678 PlatformDarwinKernel::IndexKextsInDirectories ()
679 {
680     std::vector<FileSpec> kext_bundles;
681 
682     const uint32_t num_dirs = m_search_directories.size();
683     for (uint32_t i = 0; i < num_dirs; i++)
684     {
685         const FileSpec &dir = m_search_directories[i];
686         const bool find_directories = true;
687         const bool find_files = false;
688         const bool find_other = false;
689         FileSpec::EnumerateDirectory (dir.GetPath().c_str(),
690                                       find_directories,
691                                       find_files,
692                                       find_other,
693                                       GetKextsInDirectory,
694                                       &kext_bundles);
695     }
696 
697     const uint32_t num_kexts = kext_bundles.size();
698     for (uint32_t i = 0; i < num_kexts; i++)
699     {
700         const FileSpec &kext = kext_bundles[i];
701         CFCBundle bundle (kext.GetPath().c_str());
702         CFStringRef bundle_id (bundle.GetIdentifier());
703         if (bundle_id && CFGetTypeID (bundle_id) == CFStringGetTypeID ())
704         {
705             char bundle_id_buf[PATH_MAX];
706             if (CFStringGetCString (bundle_id, bundle_id_buf, sizeof (bundle_id_buf), kCFStringEncodingUTF8))
707             {
708                 ConstString bundle_conststr(bundle_id_buf);
709                 m_name_to_kext_path_map.insert(std::pair<ConstString, FileSpec>(bundle_conststr, kext));
710             }
711         }
712     }
713 }
714 
715 // Callback for FileSpec::EnumerateDirectory().
716 // Step through the entries in a directory like /System/Library/Extensions, find .kext bundles, add them
717 // to the vector of FileSpecs.
718 // If a .kext bundle has a Contents/PlugIns or PlugIns subdir, search for kexts in there too.
719 
720 FileSpec::EnumerateDirectoryResult
721 PlatformDarwinKernel::GetKextsInDirectory (void *baton,
722                                            FileSpec::FileType file_type,
723                                            const FileSpec &file_spec)
724 {
725     if (file_type == FileSpec::eFileTypeDirectory && file_spec.GetFileNameExtension() == ConstString("kext"))
726     {
727         ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
728         std::string kext_bundle_path = file_spec.GetPath();
729         std::string search_here_too;
730         std::string contents_plugins_path = kext_bundle_path + "/Contents/PlugIns";
731         FileSpec contents_plugins (contents_plugins_path.c_str(), false);
732         if (contents_plugins.Exists() && contents_plugins.IsDirectory())
733         {
734             search_here_too = contents_plugins_path;
735         }
736         else
737         {
738             std::string plugins_path = kext_bundle_path + "/PlugIns";
739             FileSpec plugins (plugins_path.c_str(), false);
740             if (plugins.Exists() && plugins.IsDirectory())
741             {
742                 search_here_too = plugins_path;
743             }
744         }
745 
746         if (!search_here_too.empty())
747         {
748             const bool find_directories = true;
749             const bool find_files = false;
750             const bool find_other = false;
751             FileSpec::EnumerateDirectory (search_here_too.c_str(),
752                                           find_directories,
753                                           find_files,
754                                           find_other,
755                                           GetKextsInDirectory,
756                                           baton);
757         }
758     }
759     return FileSpec::eEnumerateDirectoryResultNext;
760 }
761 
762 void
763 PlatformDarwinKernel::IndexKernelsInDirectories ()
764 {
765     std::vector<FileSpec> kernels;
766 
767 
768     const uint32_t num_dirs = m_search_directories.size();
769     for (uint32_t i = 0; i < num_dirs; i++)
770     {
771         const FileSpec &dir = m_search_directories[i];
772         const bool find_directories = false;
773         const bool find_files = true;
774         const bool find_other = true;  // I think eFileTypeSymbolicLink are "other"s.
775         FileSpec::EnumerateDirectory (dir.GetPath().c_str(),
776                                       find_directories,
777                                       find_files,
778                                       find_other,
779                                       GetKernelsInDirectory,
780                                       &m_kernel_binaries);
781     }
782 }
783 
784 // Callback for FileSpec::EnumerateDirectory().
785 // Step through the entries in a directory like /System/Library/Kernels/, find kernel binaries,
786 // add them to m_kernel_binaries.
787 
788 // We're only doing a filename match here.  We won't try opening the file to see if it's really
789 // a kernel or not until we need to find a kernel of a given UUID.  There's no cheap way to find
790 // the UUID of a file (or if it's a Mach-O binary at all) without creating a whole Module for
791 // the file and throwing it away if it's not wanted.
792 
793 FileSpec::EnumerateDirectoryResult
794 PlatformDarwinKernel::GetKernelsInDirectory (void *baton,
795                                            FileSpec::FileType file_type,
796                                            const FileSpec &file_spec)
797 {
798     if (file_type == FileSpec::eFileTypeRegular || file_type == FileSpec::eFileTypeSymbolicLink)
799     {
800         ConstString filename = file_spec.GetFilename();
801         if (strncmp (filename.GetCString(), "kernel", 6) == 0
802             || strncmp (filename.GetCString(), "mach", 4) == 0)
803         {
804             // This is m_kernel_binaries but we're in a class method here
805             ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec);
806         }
807     }
808     return FileSpec::eEnumerateDirectoryResultNext;
809 }
810 
811 
812 Error
813 PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec,
814                                        Process *process,
815                                        ModuleSP &module_sp,
816                                        const FileSpecList *module_search_paths_ptr,
817                                        ModuleSP *old_module_sp_ptr,
818                                        bool *did_create_ptr)
819 {
820     Error error;
821     module_sp.reset();
822     const FileSpec &platform_file = module_spec.GetFileSpec();
823 
824     // Treat the file's path as a kext bundle ID (e.g. "com.apple.driver.AppleIRController") and search our kext index.
825     std::string kext_bundle_id = platform_file.GetPath();
826     if (!kext_bundle_id.empty())
827     {
828         ConstString kext_bundle_cs(kext_bundle_id.c_str());
829         if (m_name_to_kext_path_map.count(kext_bundle_cs) > 0)
830         {
831             for (BundleIDToKextIterator it = m_name_to_kext_path_map.begin (); it != m_name_to_kext_path_map.end (); ++it)
832             {
833                 if (it->first == kext_bundle_cs)
834                 {
835                     error = ExamineKextForMatchingUUID (it->second, module_spec.GetUUID(), module_spec.GetArchitecture(), module_sp);
836                     if (module_sp.get())
837                     {
838                         return error;
839                     }
840                 }
841             }
842         }
843     }
844 
845     if (kext_bundle_id.compare("mach_kernel") == 0 && module_spec.GetUUID().IsValid())
846     {
847         for (auto possible_kernel : m_kernel_binaries)
848         {
849             if (possible_kernel.Exists())
850             {
851                 ModuleSpec kern_spec (possible_kernel);
852                 kern_spec.GetUUID() = module_spec.GetUUID();
853                 ModuleSP module_sp (new Module (kern_spec));
854                 if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (kern_spec))
855                 {
856                     Error error;
857                     error = ModuleList::GetSharedModule (kern_spec, module_sp, NULL, NULL, NULL);
858                     if (module_sp && module_sp->GetObjectFile())
859                     {
860                         return error;
861                     }
862                 }
863             }
864         }
865     }
866 
867     // Else fall back to treating the file's path as an actual file path - defer to PlatformDarwin's GetSharedModule.
868     return PlatformDarwin::GetSharedModule (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
869 }
870 
871 Error
872 PlatformDarwinKernel::ExamineKextForMatchingUUID (const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, const ArchSpec &arch, ModuleSP &exe_module_sp)
873 {
874     Error error;
875     FileSpec exe_file = kext_bundle_path;
876     Host::ResolveExecutableInBundle (exe_file);
877     if (exe_file.Exists())
878     {
879         ModuleSpec exe_spec (exe_file);
880         exe_spec.GetUUID() = uuid;
881         if (!uuid.IsValid())
882         {
883             exe_spec.GetArchitecture() = arch;
884         }
885 
886         // First try to create a ModuleSP with the file / arch and see if the UUID matches.
887         // If that fails (this exec file doesn't have the correct uuid), don't call GetSharedModule
888         // (which may call in to the DebugSymbols framework and therefore can be slow.)
889         ModuleSP module_sp (new Module (exe_spec));
890         if (module_sp && module_sp->GetObjectFile() && module_sp->MatchesModuleSpec (exe_spec))
891         {
892             error = ModuleList::GetSharedModule (exe_spec, exe_module_sp, NULL, NULL, NULL);
893             if (exe_module_sp && exe_module_sp->GetObjectFile())
894             {
895                 return error;
896             }
897         }
898         exe_module_sp.reset();
899     }
900     return error;
901 }
902 
903 bool
904 PlatformDarwinKernel::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
905 {
906 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
907     return ARMGetSupportedArchitectureAtIndex (idx, arch);
908 #else
909     return x86GetSupportedArchitectureAtIndex (idx, arch);
910 #endif
911 }
912 
913 void
914 PlatformDarwinKernel::CalculateTrapHandlerSymbolNames ()
915 {
916     m_trap_handlers.push_back(ConstString ("trap_from_kernel"));
917     m_trap_handlers.push_back(ConstString ("hndl_machine_check"));
918     m_trap_handlers.push_back(ConstString ("hndl_double_fault"));
919     m_trap_handlers.push_back(ConstString ("hndl_allintrs"));
920     m_trap_handlers.push_back(ConstString ("hndl_alltraps"));
921     m_trap_handlers.push_back(ConstString ("interrupt"));
922     m_trap_handlers.push_back(ConstString ("fleh_prefabt"));
923     m_trap_handlers.push_back(ConstString ("ExceptionVectorsBase"));
924     m_trap_handlers.push_back(ConstString ("ExceptionVectorsTable"));
925     m_trap_handlers.push_back(ConstString ("fleh_undef"));
926     m_trap_handlers.push_back(ConstString ("fleh_dataabt"));
927     m_trap_handlers.push_back(ConstString ("fleh_irq"));
928     m_trap_handlers.push_back(ConstString ("fleh_decirq"));
929     m_trap_handlers.push_back(ConstString ("fleh_fiq_generic"));
930     m_trap_handlers.push_back(ConstString ("fleh_dec"));
931 
932 }
933 
934 #else  // __APPLE__
935 
936 // Since DynamicLoaderDarwinKernel is compiled in for all systems, and relies on
937 // PlatformDarwinKernel for the plug-in name, we compile just the plug-in name in
938 // here to avoid issues. We are tracking an internal bug to resolve this issue by
939 // either not compiling in DynamicLoaderDarwinKernel for non-apple builds, or to make
940 // PlatformDarwinKernel build on all systems. PlatformDarwinKernel is currently not
941 // compiled on other platforms due to the use of the Mac-specific
942 // source/Host/macosx/cfcpp utilities.
943 
944 lldb_private::ConstString
945 PlatformDarwinKernel::GetPluginNameStatic ()
946 {
947     static lldb_private::ConstString g_name("darwin-kernel");
948     return g_name;
949 }
950 
951 #endif // __APPLE__
952