PlatformDarwinKernel.cpp revision 36b15e2e98c2fc30ac3ac73ddc116fcd8cd1decd
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 40using namespace lldb; 41using namespace lldb_private; 42 43//------------------------------------------------------------------ 44// Static Variables 45//------------------------------------------------------------------ 46static uint32_t g_initialize_count = 0; 47 48//------------------------------------------------------------------ 49// Static Functions 50//------------------------------------------------------------------ 51void 52PlatformDarwinKernel::Initialize () 53{ 54 if (g_initialize_count++ == 0) 55 { 56 PluginManager::RegisterPlugin (PlatformDarwinKernel::GetShortPluginNameStatic(), 57 PlatformDarwinKernel::GetDescriptionStatic(), 58 PlatformDarwinKernel::CreateInstance, 59 PlatformDarwinKernel::DebuggerInitialize); 60 } 61} 62 63void 64PlatformDarwinKernel::Terminate () 65{ 66 if (g_initialize_count > 0) 67 { 68 if (--g_initialize_count == 0) 69 { 70 PluginManager::UnregisterPlugin (PlatformDarwinKernel::CreateInstance); 71 } 72 } 73} 74 75Platform* 76PlatformDarwinKernel::CreateInstance (bool force, const ArchSpec *arch) 77{ 78 // This is a special plugin that we don't want to activate just based on an ArchSpec for normal 79 // userlnad debugging. It is only useful in kernel debug sessions and the DynamicLoaderDarwinPlugin 80 // (or a user doing 'platform select') will force the creation of this Platform plugin. 81 if (force == false) 82 return NULL; 83 84 bool create = force; 85 LazyBool is_ios_debug_session = eLazyBoolCalculate; 86 87 if (create == false && arch && arch->IsValid()) 88 { 89 const llvm::Triple &triple = arch->GetTriple(); 90 switch (triple.getVendor()) 91 { 92 case llvm::Triple::Apple: 93 create = true; 94 break; 95 96 // Only accept "unknown" for vendor if the host is Apple and 97 // it "unknown" wasn't specified (it was just returned becasue it 98 // was NOT specified) 99 case llvm::Triple::UnknownArch: 100 create = !arch->TripleVendorWasSpecified(); 101 break; 102 default: 103 break; 104 } 105 106 if (create) 107 { 108 switch (triple.getOS()) 109 { 110 case llvm::Triple::Darwin: // Deprecated, but still support Darwin for historical reasons 111 case llvm::Triple::MacOSX: 112 break; 113 // Only accept "vendor" for vendor if the host is Apple and 114 // it "unknown" wasn't specified (it was just returned becasue it 115 // was NOT specified) 116 case llvm::Triple::UnknownOS: 117 create = !arch->TripleOSWasSpecified(); 118 break; 119 default: 120 create = false; 121 break; 122 } 123 } 124 } 125 if (arch && arch->IsValid()) 126 { 127 switch (arch->GetMachine()) 128 { 129 case llvm::Triple::x86: 130 case llvm::Triple::x86_64: 131 case llvm::Triple::ppc: 132 case llvm::Triple::ppc64: 133 is_ios_debug_session = eLazyBoolNo; 134 break; 135 case llvm::Triple::arm: 136 case llvm::Triple::thumb: 137 is_ios_debug_session = eLazyBoolYes; 138 break; 139 default: 140 is_ios_debug_session = eLazyBoolCalculate; 141 break; 142 } 143 } 144 if (create) 145 return new PlatformDarwinKernel (is_ios_debug_session); 146 return NULL; 147} 148 149 150const char * 151PlatformDarwinKernel::GetPluginNameStatic () 152{ 153 return "PlatformDarwinKernel"; 154} 155 156const char * 157PlatformDarwinKernel::GetShortPluginNameStatic() 158{ 159 return "darwin-kernel"; 160} 161 162const char * 163PlatformDarwinKernel::GetDescriptionStatic() 164{ 165 return "Darwin Kernel platform plug-in."; 166} 167 168//------------------------------------------------------------------ 169/// Code to handle the PlatformDarwinKernel settings 170//------------------------------------------------------------------ 171 172static PropertyDefinition 173g_properties[] = 174{ 175 { "search-locally-for-kexts" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "Automatically search for kexts on the local system when doing kernel debugging." }, 176 { "kext-directories", OptionValue::eTypeFileSpecList, false, 0, NULL, NULL, "Directories/KDKs to search for kexts in when starting a kernel debug session." }, 177 { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL } 178}; 179 180enum { 181 ePropertySearchForKexts = 0, 182 ePropertyKextDirectories 183}; 184 185 186 187class PlatformDarwinKernelProperties : public Properties 188{ 189public: 190 191 static ConstString & 192 GetSettingName () 193 { 194 static ConstString g_setting_name("darwin-kernel"); 195 return g_setting_name; 196 } 197 198 PlatformDarwinKernelProperties() : 199 Properties () 200 { 201 m_collection_sp.reset (new OptionValueProperties(GetSettingName())); 202 m_collection_sp->Initialize(g_properties); 203 } 204 205 virtual 206 ~PlatformDarwinKernelProperties() 207 { 208 } 209 210 bool 211 GetSearchForKexts() const 212 { 213 const uint32_t idx = ePropertySearchForKexts; 214 return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, g_properties[idx].default_uint_value != 0); 215 } 216 217 FileSpecList & 218 GetKextDirectories() const 219 { 220 const uint32_t idx = ePropertyKextDirectories; 221 OptionValueFileSpecList *option_value = m_collection_sp->GetPropertyAtIndexAsOptionValueFileSpecList (NULL, false, idx); 222 assert(option_value); 223 return option_value->GetCurrentValue(); 224 } 225}; 226 227typedef STD_SHARED_PTR(PlatformDarwinKernelProperties) PlatformDarwinKernelPropertiesSP; 228 229static const PlatformDarwinKernelPropertiesSP & 230GetGlobalProperties() 231{ 232 static PlatformDarwinKernelPropertiesSP g_settings_sp; 233 if (!g_settings_sp) 234 g_settings_sp.reset (new PlatformDarwinKernelProperties ()); 235 return g_settings_sp; 236} 237 238void 239PlatformDarwinKernel::DebuggerInitialize (lldb_private::Debugger &debugger) 240{ 241 if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformDarwinKernelProperties::GetSettingName())) 242 { 243 const bool is_global_setting = true; 244 PluginManager::CreateSettingForPlatformPlugin (debugger, 245 GetGlobalProperties()->GetValueProperties(), 246 ConstString ("Properties for the PlatformDarwinKernel plug-in."), 247 is_global_setting); 248 } 249} 250 251//------------------------------------------------------------------ 252/// Default Constructor 253//------------------------------------------------------------------ 254PlatformDarwinKernel::PlatformDarwinKernel (lldb_private::LazyBool is_ios_debug_session) : 255 PlatformDarwin (false), // This is a remote platform 256 m_name_to_kext_path_map(), 257 m_directories_searched(), 258 m_ios_debug_session(is_ios_debug_session) 259 260{ 261 if (GetGlobalProperties()->GetSearchForKexts()) 262 { 263 SearchForKexts (); 264 } 265} 266 267//------------------------------------------------------------------ 268/// Destructor. 269/// 270/// The destructor is virtual since this class is designed to be 271/// inherited from by the plug-in instance. 272//------------------------------------------------------------------ 273PlatformDarwinKernel::~PlatformDarwinKernel() 274{ 275} 276 277 278void 279PlatformDarwinKernel::GetStatus (Stream &strm) 280{ 281 Platform::GetStatus (strm); 282 strm.Printf (" Debug session type: "); 283 if (m_ios_debug_session == eLazyBoolYes) 284 strm.Printf ("iOS kernel debugging\n"); 285 else if (m_ios_debug_session == eLazyBoolNo) 286 strm.Printf ("Mac OS X kernel debugging\n"); 287 else 288 strm.Printf ("unknown kernel debugging\n"); 289 const uint32_t num_kext_dirs = m_directories_searched.size(); 290 for (uint32_t i=0; i<num_kext_dirs; ++i) 291 { 292 const FileSpec &kext_dir = m_directories_searched[i]; 293 char pathbuf[PATH_MAX]; 294 if (kext_dir.GetPath (pathbuf, sizeof (pathbuf))) 295 { 296 strm.Printf (" Kext directories: [%2u] \"%s\"\n", i, pathbuf); 297 } 298 } 299 strm.Printf (" Total number of kexts indexed: %d\n", (int) m_name_to_kext_path_map.size()); 300} 301 302void 303PlatformDarwinKernel::SearchForKexts () 304{ 305 // Differentiate between "ios debug session" and "mac debug session" so we don't index 306 // kext bundles that won't be used in this debug session. If this is an ios kext debug 307 // session, looking in /System/Library/Extensions is a waste of stat()s, for example. 308 309 // Build up a list of all SDKs we'll be searching for directories of kexts 310 // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk 311 std::vector<FileSpec> sdk_dirs; 312 if (m_ios_debug_session != eLazyBoolNo) 313 GetiOSSDKDirectoriesToSearch (sdk_dirs); 314 if (m_ios_debug_session != eLazyBoolYes) 315 GetMacSDKDirectoriesToSearch (sdk_dirs); 316 317 GetGenericSDKDirectoriesToSearch (sdk_dirs); 318 319 // Build up a list of directories that hold kext bundles on the system 320 // e.g. /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.Internal.sdk/System/Library/Extensions 321 std::vector<FileSpec> kext_dirs; 322 SearchSDKsForKextDirectories (sdk_dirs, kext_dirs); 323 324 if (m_ios_debug_session != eLazyBoolNo) 325 GetiOSDirectoriesToSearch (kext_dirs); 326 if (m_ios_debug_session != eLazyBoolYes) 327 GetMacDirectoriesToSearch (kext_dirs); 328 329 GetGenericDirectoriesToSearch (kext_dirs); 330 331 GetUserSpecifiedDirectoriesToSearch (kext_dirs); 332 333 // We now have a complete list of directories that we will search for kext bundles 334 m_directories_searched = kext_dirs; 335 336 IndexKextsInDirectories (kext_dirs); 337} 338 339void 340PlatformDarwinKernel::GetiOSSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 341{ 342 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 343 const char *developer_dir = GetDeveloperDirectory(); 344 if (developer_dir == NULL) 345 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 346 347 char pathbuf[PATH_MAX]; 348 ::snprintf (pathbuf, sizeof (pathbuf), "%s/Platforms/iPhoneOS.platform/Developer/SDKs", developer_dir); 349 FileSpec ios_sdk(pathbuf, true); 350 if (ios_sdk.Exists() && ios_sdk.GetFileType() == FileSpec::eFileTypeDirectory) 351 { 352 directories.push_back (ios_sdk); 353 } 354} 355 356void 357PlatformDarwinKernel::GetMacSDKDirectoriesToSearch (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/MacOSX.platform/Developer/SDKs", developer_dir); 366 FileSpec mac_sdk(pathbuf, true); 367 if (mac_sdk.Exists() && mac_sdk.GetFileType() == FileSpec::eFileTypeDirectory) 368 { 369 directories.push_back (mac_sdk); 370 } 371} 372 373void 374PlatformDarwinKernel::GetGenericSDKDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 375{ 376 FileSpec generic_sdk("/AppleInternal/Developer/KDKs", true); 377 if (generic_sdk.Exists() && generic_sdk.GetFileType() == FileSpec::eFileTypeDirectory) 378 { 379 directories.push_back (generic_sdk); 380 } 381} 382 383void 384PlatformDarwinKernel::GetiOSDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 385{ 386} 387 388void 389PlatformDarwinKernel::GetMacDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 390{ 391 FileSpec sle("/System/Library/Extensions", true); 392 if (sle.Exists() && sle.GetFileType() == FileSpec::eFileTypeDirectory) 393 { 394 directories.push_back(sle); 395 } 396} 397 398void 399PlatformDarwinKernel::GetGenericDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 400{ 401 // DeveloperDirectory is something like "/Applications/Xcode.app/Contents/Developer" 402 const char *developer_dir = GetDeveloperDirectory(); 403 if (developer_dir == NULL) 404 developer_dir = "/Applications/Xcode.app/Contents/Developer"; 405 406 char pathbuf[PATH_MAX]; 407 ::snprintf (pathbuf, sizeof (pathbuf), "%s/../Symbols", developer_dir); 408 FileSpec symbols_dir (pathbuf, true); 409 if (symbols_dir.Exists() && symbols_dir.GetFileType() == FileSpec::eFileTypeDirectory) 410 { 411 directories.push_back (symbols_dir); 412 } 413} 414 415void 416PlatformDarwinKernel::GetUserSpecifiedDirectoriesToSearch (std::vector<lldb_private::FileSpec> &directories) 417{ 418 FileSpecList user_dirs(GetGlobalProperties()->GetKextDirectories()); 419 std::vector<FileSpec> possible_sdk_dirs; 420 421 const uint32_t user_dirs_count = user_dirs.GetSize(); 422 for (uint32_t i = 0; i < user_dirs_count; i++) 423 { 424 FileSpec dir = user_dirs.GetFileSpecAtIndex (i); 425 dir.ResolvePath(); 426 if (dir.Exists() && dir.GetFileType() == FileSpec::eFileTypeDirectory) 427 { 428 directories.push_back (dir); 429 possible_sdk_dirs.push_back (dir); // does this directory have a *.sdk or *.kdk that we should look in? 430 431 char dir_pathbuf[PATH_MAX]; 432 if (dir.GetPath (dir_pathbuf, sizeof (dir_pathbuf))) 433 { 434 // Is there a "System/Library/Extensions" subdir of this directory? 435 char pathbuf[PATH_MAX]; 436 ::snprintf (pathbuf, sizeof (pathbuf), "%s/System/Library/Extensions", dir_pathbuf); 437 FileSpec dir_sle(pathbuf, true); 438 if (dir_sle.Exists() && dir_sle.GetFileType() == FileSpec::eFileTypeDirectory) 439 { 440 directories.push_back (dir_sle); 441 } 442 } 443 } 444 } 445 446 SearchSDKsForKextDirectories (possible_sdk_dirs, directories); 447} 448 449// Scan through the SDK directories, looking for directories where kexts are likely. 450// Add those directories to kext_dirs. 451void 452PlatformDarwinKernel::SearchSDKsForKextDirectories (std::vector<lldb_private::FileSpec> sdk_dirs, std::vector<lldb_private::FileSpec> &kext_dirs) 453{ 454 const uint32_t num_sdks = sdk_dirs.size(); 455 for (uint32_t i = 0; i < num_sdks; i++) 456 { 457 const FileSpec &sdk_dir = sdk_dirs[i]; 458 char pathbuf[PATH_MAX]; 459 if (sdk_dir.GetPath (pathbuf, sizeof (pathbuf))) 460 { 461 const bool find_directories = true; 462 const bool find_files = false; 463 const bool find_other = false; 464 FileSpec::EnumerateDirectory (pathbuf, 465 find_directories, 466 find_files, 467 find_other, 468 GetKextDirectoriesInSDK, 469 &kext_dirs); 470 } 471 } 472} 473 474// Callback for FileSpec::EnumerateDirectory(). 475// Step through the entries in a directory like 476// /Applications/Xcode.app//Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs 477// looking for any subdirectories of the form MacOSX10.8.Internal.sdk/System/Library/Extensions 478// Adds these to the vector of FileSpec's. 479 480FileSpec::EnumerateDirectoryResult 481PlatformDarwinKernel::GetKextDirectoriesInSDK (void *baton, 482 FileSpec::FileType file_type, 483 const FileSpec &file_spec) 484{ 485 if (file_type == FileSpec::eFileTypeDirectory 486 && (file_spec.GetFileNameExtension() == ConstString("sdk") 487 || file_spec.GetFileNameExtension() == ConstString("kdk"))) 488 { 489 char pathbuf[PATH_MAX]; 490 if (file_spec.GetPath (pathbuf, PATH_MAX)) 491 { 492 char kext_directory_str[PATH_MAX]; 493 ::snprintf (kext_directory_str, sizeof (kext_directory_str), "%s/%s", pathbuf, "System/Library/Extensions"); 494 FileSpec kext_directory (kext_directory_str, true); 495 if (kext_directory.Exists() && kext_directory.GetFileType() == FileSpec::eFileTypeDirectory) 496 { 497 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(kext_directory); 498 } 499 } 500 } 501 return FileSpec::eEnumerateDirectoryResultNext; 502} 503 504void 505PlatformDarwinKernel::IndexKextsInDirectories (std::vector<lldb_private::FileSpec> kext_dirs) 506{ 507 std::vector<FileSpec> kext_bundles; 508 509 const uint32_t num_dirs = kext_dirs.size(); 510 for (uint32_t i = 0; i < num_dirs; i++) 511 { 512 const FileSpec &dir = kext_dirs[i]; 513 char pathbuf[PATH_MAX]; 514 if (dir.GetPath (pathbuf, sizeof(pathbuf))) 515 { 516 const bool find_directories = true; 517 const bool find_files = false; 518 const bool find_other = false; 519 FileSpec::EnumerateDirectory (pathbuf, 520 find_directories, 521 find_files, 522 find_other, 523 GetKextsInDirectory, 524 &kext_bundles); 525 } 526 } 527 528 const uint32_t num_kexts = kext_bundles.size(); 529 for (uint32_t i = 0; i < num_kexts; i++) 530 { 531 const FileSpec &kext = kext_bundles[i]; 532 char pathbuf[PATH_MAX]; 533 if (kext.GetPath (pathbuf, sizeof (pathbuf))) 534 { 535 CFCBundle bundle (pathbuf); 536 CFStringRef bundle_id (bundle.GetIdentifier()); 537 if (bundle_id && CFGetTypeID (bundle_id) == CFStringGetTypeID ()) 538 { 539 char bundle_id_buf[PATH_MAX]; 540 if (CFStringGetCString (bundle_id, bundle_id_buf, sizeof (bundle_id_buf), kCFStringEncodingUTF8)) 541 { 542 ConstString bundle_conststr(bundle_id_buf); 543 m_name_to_kext_path_map.insert(std::pair<ConstString, FileSpec>(bundle_conststr, kext)); 544 } 545 } 546 } 547 } 548} 549 550// Callback for FileSpec::EnumerateDirectory(). 551// Step through the entries in a directory like /System/Library/Extensions, find .kext bundles, add them 552// to the vector of FileSpecs. 553// If a .kext bundle has a Contents/PlugIns or PlugIns subdir, search for kexts in there too. 554 555FileSpec::EnumerateDirectoryResult 556PlatformDarwinKernel::GetKextsInDirectory (void *baton, 557 FileSpec::FileType file_type, 558 const FileSpec &file_spec) 559{ 560 if (file_type == FileSpec::eFileTypeDirectory && file_spec.GetFileNameExtension() == ConstString("kext")) 561 { 562 ((std::vector<lldb_private::FileSpec> *)baton)->push_back(file_spec); 563 bool search_inside = false; 564 char pathbuf[PATH_MAX]; 565 ::snprintf (pathbuf, sizeof (pathbuf), "%s/%s/Contents/PlugIns", file_spec.GetDirectory().GetCString(), file_spec.GetFilename().GetCString()); 566 FileSpec contents_plugins (pathbuf, false); 567 if (contents_plugins.Exists() && contents_plugins.GetFileType() == FileSpec::eFileTypeDirectory) 568 { 569 search_inside = true; 570 } 571 else 572 { 573 ::snprintf (pathbuf, sizeof (pathbuf), "%s/%s/PlugIns", file_spec.GetDirectory().GetCString(), file_spec.GetFilename().GetCString()); 574 FileSpec plugins (pathbuf, false); 575 if (plugins.Exists() && plugins.GetFileType() == FileSpec::eFileTypeDirectory) 576 { 577 search_inside = true; 578 } 579 } 580 581 if (search_inside) 582 { 583 const bool find_directories = true; 584 const bool find_files = false; 585 const bool find_other = false; 586 FileSpec::EnumerateDirectory (pathbuf, 587 find_directories, 588 find_files, 589 find_other, 590 GetKextsInDirectory, 591 baton); 592 } 593 } 594 return FileSpec::eEnumerateDirectoryResultNext; 595} 596 597Error 598PlatformDarwinKernel::GetSharedModule (const ModuleSpec &module_spec, 599 ModuleSP &module_sp, 600 const FileSpecList *module_search_paths_ptr, 601 ModuleSP *old_module_sp_ptr, 602 bool *did_create_ptr) 603{ 604 Error error; 605 module_sp.reset(); 606 const FileSpec &platform_file = module_spec.GetFileSpec(); 607 char kext_bundle_id[PATH_MAX]; 608 if (platform_file.GetPath (kext_bundle_id, sizeof (kext_bundle_id))) 609 { 610 ConstString kext_bundle_cs(kext_bundle_id); 611 if (m_name_to_kext_path_map.count(kext_bundle_cs) > 0) 612 { 613 for (BundleIDToKextIterator it = m_name_to_kext_path_map.begin (); it != m_name_to_kext_path_map.end (); ++it) 614 { 615 if (it->first == kext_bundle_cs) 616 { 617 error = ExamineKextForMatchingUUID (it->second, module_spec.GetUUID(), module_sp); 618 if (module_sp.get()) 619 { 620 return error; 621 } 622 } 623 } 624 } 625 } 626 627 return error; 628} 629 630Error 631PlatformDarwinKernel::ExamineKextForMatchingUUID (const FileSpec &kext_bundle_path, const lldb_private::UUID &uuid, ModuleSP &exe_module_sp) 632{ 633 Error error; 634 FileSpec exe_file = kext_bundle_path; 635 Host::ResolveExecutableInBundle (exe_file); 636 if (exe_file.Exists()) 637 { 638 ModuleSpec exe_spec (exe_file); 639 exe_spec.GetUUID() = uuid; 640 error = ModuleList::GetSharedModule (exe_spec, exe_module_sp, NULL, NULL, NULL); 641 if (exe_module_sp && exe_module_sp->GetObjectFile()) 642 { 643 return error; 644 } 645 exe_module_sp.reset(); 646 } 647 return error; 648} 649 650bool 651PlatformDarwinKernel::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 652{ 653#if defined (__arm__) 654 return ARMGetSupportedArchitectureAtIndex (idx, arch); 655#else 656 return x86GetSupportedArchitectureAtIndex (idx, arch); 657#endif 658} 659 660#endif // __APPLE__ 661