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