1 //===-- Platform.h ----------------------------------------------*- 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 #ifndef liblldb_Platform_h_ 11 #define liblldb_Platform_h_ 12 13 // C Includes 14 // C++ Includes 15 #include <map> 16 #include <string> 17 #include <vector> 18 19 // Other libraries and framework includes 20 // Project includes 21 #include "lldb/lldb-public.h" 22 #include "lldb/Core/ArchSpec.h" 23 #include "lldb/Core/ConstString.h" 24 #include "lldb/Core/PluginInterface.h" 25 #include "lldb/Host/Mutex.h" 26 27 namespace lldb_private { 28 29 //---------------------------------------------------------------------- 30 /// @class Platform Platform.h "lldb/Target/Platform.h" 31 /// @brief A plug-in interface definition class for debug platform that 32 /// includes many platform abilities such as: 33 /// @li getting platform information such as supported architectures, 34 /// supported binary file formats and more 35 /// @li launching new processes 36 /// @li attaching to existing processes 37 /// @li download/upload files 38 /// @li execute shell commands 39 /// @li listing and getting info for existing processes 40 /// @li attaching and possibly debugging the platform's kernel 41 //---------------------------------------------------------------------- 42 class Platform : public PluginInterface 43 { 44 public: 45 46 //------------------------------------------------------------------ 47 /// Get the native host platform plug-in. 48 /// 49 /// There should only be one of these for each host that LLDB runs 50 /// upon that should be statically compiled in and registered using 51 /// preprocessor macros or other similar build mechanisms in a 52 /// PlatformSubclass::Initialize() function. 53 /// 54 /// This platform will be used as the default platform when launching 55 /// or attaching to processes unless another platform is specified. 56 //------------------------------------------------------------------ 57 static lldb::PlatformSP 58 GetDefaultPlatform (); 59 60 static lldb::PlatformSP 61 GetPlatformForArchitecture (const ArchSpec &arch, 62 ArchSpec *platform_arch_ptr); 63 64 static const char * 65 GetHostPlatformName (); 66 67 static void 68 SetDefaultPlatform (const lldb::PlatformSP &platform_sp); 69 70 static lldb::PlatformSP 71 Create (const char *platform_name, Error &error); 72 73 static lldb::PlatformSP 74 Create (const ArchSpec &arch, ArchSpec *platform_arch_ptr, Error &error); 75 76 static uint32_t 77 GetNumConnectedRemotePlatforms (); 78 79 static lldb::PlatformSP 80 GetConnectedRemotePlatformAtIndex (uint32_t idx); 81 82 //------------------------------------------------------------------ 83 /// Default Constructor 84 //------------------------------------------------------------------ 85 Platform (bool is_host_platform); 86 87 //------------------------------------------------------------------ 88 /// Destructor. 89 /// 90 /// The destructor is virtual since this class is designed to be 91 /// inherited from by the plug-in instance. 92 //------------------------------------------------------------------ 93 virtual 94 ~Platform(); 95 96 //------------------------------------------------------------------ 97 /// Find a platform plugin for a given process. 98 /// 99 /// Scans the installed Platform plug-ins and tries to find 100 /// an instance that can be used for \a process 101 /// 102 /// @param[in] process 103 /// The process for which to try and locate a platform 104 /// plug-in instance. 105 /// 106 /// @param[in] plugin_name 107 /// An optional name of a specific platform plug-in that 108 /// should be used. If NULL, pick the best plug-in. 109 //------------------------------------------------------------------ 110 static Platform* 111 FindPlugin (Process *process, const ConstString &plugin_name); 112 113 //------------------------------------------------------------------ 114 /// Set the target's executable based off of the existing 115 /// architecture information in \a target given a path to an 116 /// executable \a exe_file. 117 /// 118 /// Each platform knows the architectures that it supports and can 119 /// select the correct architecture slice within \a exe_file by 120 /// inspecting the architecture in \a target. If the target had an 121 /// architecture specified, then in can try and obey that request 122 /// and optionally fail if the architecture doesn't match up. 123 /// If no architecture is specified, the platform should select the 124 /// default architecture from \a exe_file. Any application bundles 125 /// or executable wrappers can also be inspected for the actual 126 /// application binary within the bundle that should be used. 127 /// 128 /// @return 129 /// Returns \b true if this Platform plug-in was able to find 130 /// a suitable executable, \b false otherwise. 131 //------------------------------------------------------------------ 132 virtual Error 133 ResolveExecutable (const FileSpec &exe_file, 134 const ArchSpec &arch, 135 lldb::ModuleSP &module_sp, 136 const FileSpecList *module_search_paths_ptr); 137 138 139 //------------------------------------------------------------------ 140 /// Find a symbol file given a symbol file module specification. 141 /// 142 /// Each platform might have tricks to find symbol files for an 143 /// executable given information in a symbol file ModuleSpec. Some 144 /// platforms might also support symbol files that are bundles and 145 /// know how to extract the right symbol file given a bundle. 146 /// 147 /// @param[in] target 148 /// The target in which we are trying to resolve the symbol file. 149 /// The target has a list of modules that we might be able to 150 /// use in order to help find the right symbol file. If the 151 /// "m_file" or "m_platform_file" entries in the \a sym_spec 152 /// are filled in, then we might be able to locate a module in 153 /// the target, extract its UUID and locate a symbol file. 154 /// If just the "m_uuid" is specified, then we might be able 155 /// to find the module in the target that matches that UUID 156 /// and pair the symbol file along with it. If just "m_symbol_file" 157 /// is specified, we can use a variety of tricks to locate the 158 /// symbols in an SDK, PDK, or other development kit location. 159 /// 160 /// @param[in] sym_spec 161 /// A module spec that describes some information about the 162 /// symbol file we are trying to resolve. The ModuleSpec might 163 /// contain the following: 164 /// m_file - A full or partial path to an executable from the 165 /// target (might be empty). 166 /// m_platform_file - Another executable hint that contains 167 /// the path to the file as known on the 168 /// local/remote platform. 169 /// m_symbol_file - A full or partial path to a symbol file 170 /// or symbol bundle that should be used when 171 /// trying to resolve the symbol file. 172 /// m_arch - The architecture we are looking for when resolving 173 /// the symbol file. 174 /// m_uuid - The UUID of the executable and symbol file. This 175 /// can often be used to match up an exectuable with 176 /// a symbol file, or resolve an symbol file in a 177 /// symbol file bundle. 178 /// 179 /// @param[out] sym_file 180 /// The resolved symbol file spec if the returned error 181 /// indicates succes. 182 /// 183 /// @return 184 /// Returns an error that describes success or failure. 185 //------------------------------------------------------------------ 186 virtual Error 187 ResolveSymbolFile (Target &target, 188 const ModuleSpec &sym_spec, 189 FileSpec &sym_file); 190 191 //------------------------------------------------------------------ 192 /// Resolves the FileSpec to a (possibly) remote path. Remote 193 /// platforms must override this to resolve to a path on the remote 194 /// side. 195 //------------------------------------------------------------------ 196 virtual bool 197 ResolveRemotePath (const FileSpec &platform_path, 198 FileSpec &resolved_platform_path); 199 200 bool 201 GetOSVersion (uint32_t &major, 202 uint32_t &minor, 203 uint32_t &update); 204 205 bool 206 SetOSVersion (uint32_t major, 207 uint32_t minor, 208 uint32_t update); 209 210 bool 211 GetOSBuildString (std::string &s); 212 213 bool 214 GetOSKernelDescription (std::string &s); 215 216 // Returns the the hostname if we are connected, else the short plugin 217 // name. 218 ConstString 219 GetName (); 220 221 virtual const char * 222 GetHostname (); 223 224 virtual const char * 225 GetDescription () = 0; 226 227 //------------------------------------------------------------------ 228 /// Report the current status for this platform. 229 /// 230 /// The returned string usually involves returning the OS version 231 /// (if available), and any SDK directory that might be being used 232 /// for local file caching, and if connected a quick blurb about 233 /// what this platform is connected to. 234 //------------------------------------------------------------------ 235 virtual void 236 GetStatus (Stream &strm); 237 238 //------------------------------------------------------------------ 239 // Subclasses must be able to fetch the current OS version 240 // 241 // Remote classes must be connected for this to succeed. Local 242 // subclasses don't need to override this function as it will just 243 // call the Host::GetOSVersion(). 244 //------------------------------------------------------------------ 245 virtual bool GetRemoteOSVersion()246 GetRemoteOSVersion () 247 { 248 return false; 249 } 250 251 virtual bool GetRemoteOSBuildString(std::string & s)252 GetRemoteOSBuildString (std::string &s) 253 { 254 s.clear(); 255 return false; 256 } 257 258 virtual bool GetRemoteOSKernelDescription(std::string & s)259 GetRemoteOSKernelDescription (std::string &s) 260 { 261 s.clear(); 262 return false; 263 } 264 265 // Remote Platform subclasses need to override this function 266 virtual ArchSpec GetRemoteSystemArchitecture()267 GetRemoteSystemArchitecture () 268 { 269 return ArchSpec(); // Return an invalid architecture 270 } 271 272 virtual const char * 273 GetUserName (uint32_t uid); 274 275 virtual const char * 276 GetGroupName (uint32_t gid); 277 278 //------------------------------------------------------------------ 279 /// Locate a file for a platform. 280 /// 281 /// The default implementation of this function will return the same 282 /// file patch in \a local_file as was in \a platform_file. 283 /// 284 /// @param[in] platform_file 285 /// The platform file path to locate and cache locally. 286 /// 287 /// @param[in] uuid_ptr 288 /// If we know the exact UUID of the file we are looking for, it 289 /// can be specified. If it is not specified, we might now know 290 /// the exact file. The UUID is usually some sort of MD5 checksum 291 /// for the file and is sometimes known by dynamic linkers/loaders. 292 /// If the UUID is known, it is best to supply it to platform 293 /// file queries to ensure we are finding the correct file, not 294 /// just a file at the correct path. 295 /// 296 /// @param[out] local_file 297 /// A locally cached version of the platform file. For platforms 298 /// that describe the current host computer, this will just be 299 /// the same file. For remote platforms, this file might come from 300 /// and SDK directory, or might need to be sync'ed over to the 301 /// current machine for efficient debugging access. 302 /// 303 /// @return 304 /// An error object. 305 //------------------------------------------------------------------ 306 virtual Error 307 GetFile (const FileSpec &platform_file, 308 const UUID *uuid_ptr, 309 FileSpec &local_file); 310 311 //---------------------------------------------------------------------- 312 // Locate the scripting resource given a module specification. 313 // 314 // Locating the file should happen only on the local computer or using 315 // the current computers global settings. 316 //---------------------------------------------------------------------- 317 virtual FileSpecList 318 LocateExecutableScriptingResources (Target *target, 319 Module &module); 320 321 virtual Error 322 GetSharedModule (const ModuleSpec &module_spec, 323 lldb::ModuleSP &module_sp, 324 const FileSpecList *module_search_paths_ptr, 325 lldb::ModuleSP *old_module_sp_ptr, 326 bool *did_create_ptr); 327 328 virtual Error 329 ConnectRemote (Args& args); 330 331 virtual Error 332 DisconnectRemote (); 333 334 //------------------------------------------------------------------ 335 /// Get the platform's supported architectures in the order in which 336 /// they should be searched. 337 /// 338 /// @param[in] idx 339 /// A zero based architecture index 340 /// 341 /// @param[out] arch 342 /// A copy of the archgitecture at index if the return value is 343 /// \b true. 344 /// 345 /// @return 346 /// \b true if \a arch was filled in and is valid, \b false 347 /// otherwise. 348 //------------------------------------------------------------------ 349 virtual bool 350 GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) = 0; 351 352 virtual size_t 353 GetSoftwareBreakpointTrapOpcode (Target &target, 354 BreakpointSite *bp_site) = 0; 355 356 //------------------------------------------------------------------ 357 /// Launch a new process on a platform, not necessarily for 358 /// debugging, it could be just for running the process. 359 //------------------------------------------------------------------ 360 virtual Error 361 LaunchProcess (ProcessLaunchInfo &launch_info); 362 363 //------------------------------------------------------------------ 364 /// Lets a platform answer if it is compatible with a given 365 /// architecture and the target triple contained within. 366 //------------------------------------------------------------------ 367 virtual bool 368 IsCompatibleArchitecture (const ArchSpec &arch, 369 bool exact_arch_match, 370 ArchSpec *compatible_arch_ptr); 371 372 //------------------------------------------------------------------ 373 /// Not all platforms will support debugging a process by spawning 374 /// somehow halted for a debugger (specified using the 375 /// "eLaunchFlagDebug" launch flag) and then attaching. If your 376 /// platform doesn't support this, override this function and return 377 /// false. 378 //------------------------------------------------------------------ 379 virtual bool CanDebugProcess()380 CanDebugProcess () 381 { 382 return true; 383 } 384 385 //------------------------------------------------------------------ 386 /// Subclasses should NOT need to implement this function as it uses 387 /// the Platform::LaunchProcess() followed by Platform::Attach () 388 //------------------------------------------------------------------ 389 lldb::ProcessSP 390 DebugProcess (ProcessLaunchInfo &launch_info, 391 Debugger &debugger, 392 Target *target, // Can be NULL, if NULL create a new target, else use existing one 393 Listener &listener, 394 Error &error); 395 396 //------------------------------------------------------------------ 397 /// Attach to an existing process using a process ID. 398 /// 399 /// Each platform subclass needs to implement this function and 400 /// attempt to attach to the process with the process ID of \a pid. 401 /// The platform subclass should return an appropriate ProcessSP 402 /// subclass that is attached to the process, or an empty shared 403 /// pointer with an appriopriate error. 404 /// 405 /// @param[in] pid 406 /// The process ID that we should attempt to attach to. 407 /// 408 /// @return 409 /// An appropriate ProcessSP containing a valid shared pointer 410 /// to the default Process subclass for the platform that is 411 /// attached to the process, or an empty shared pointer with an 412 /// appriopriate error fill into the \a error object. 413 //------------------------------------------------------------------ 414 virtual lldb::ProcessSP 415 Attach (ProcessAttachInfo &attach_info, 416 Debugger &debugger, 417 Target *target, // Can be NULL, if NULL create a new target, else use existing one 418 Listener &listener, 419 Error &error) = 0; 420 421 //------------------------------------------------------------------ 422 /// Attach to an existing process by process name. 423 /// 424 /// This function is not meant to be overridden by Process 425 /// subclasses. It will first call 426 /// Process::WillAttach (const char *) and if that returns \b 427 /// true, Process::DoAttach (const char *) will be called to 428 /// actually do the attach. If DoAttach returns \b true, then 429 /// Process::DidAttach() will be called. 430 /// 431 /// @param[in] process_name 432 /// A process name to match against the current process list. 433 /// 434 /// @return 435 /// Returns \a pid if attaching was successful, or 436 /// LLDB_INVALID_PROCESS_ID if attaching fails. 437 //------------------------------------------------------------------ 438 // virtual lldb::ProcessSP 439 // Attach (const char *process_name, 440 // bool wait_for_launch, 441 // Error &error) = 0; 442 443 //------------------------------------------------------------------ 444 // The base class Platform will take care of the host platform. 445 // Subclasses will need to fill in the remote case. 446 //------------------------------------------------------------------ 447 virtual uint32_t 448 FindProcesses (const ProcessInstanceInfoMatch &match_info, 449 ProcessInstanceInfoList &proc_infos); 450 451 virtual bool 452 GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info); 453 454 //------------------------------------------------------------------ 455 // Set a breakpoint on all functions that can end up creating a thread 456 // for this platform. This is needed when running expressions and 457 // also for process control. 458 //------------------------------------------------------------------ 459 virtual lldb::BreakpointSP 460 SetThreadCreationBreakpoint (Target &target); 461 462 463 const std::string & GetRemoteURL()464 GetRemoteURL () const 465 { 466 return m_remote_url; 467 } 468 469 bool IsHost()470 IsHost () const 471 { 472 return m_is_host; // Is this the default host platform? 473 } 474 475 bool IsRemote()476 IsRemote () const 477 { 478 return !m_is_host; 479 } 480 481 virtual bool IsConnected()482 IsConnected () const 483 { 484 // Remote subclasses should override this function 485 return IsHost(); 486 } 487 488 const ArchSpec & 489 GetSystemArchitecture(); 490 491 void SetSystemArchitecture(const ArchSpec & arch)492 SetSystemArchitecture (const ArchSpec &arch) 493 { 494 m_system_arch = arch; 495 if (IsHost()) 496 m_os_version_set_while_connected = m_system_arch.IsValid(); 497 } 498 499 // Used for column widths 500 size_t GetMaxUserIDNameLength()501 GetMaxUserIDNameLength() const 502 { 503 return m_max_uid_name_len; 504 } 505 // Used for column widths 506 size_t GetMaxGroupIDNameLength()507 GetMaxGroupIDNameLength() const 508 { 509 return m_max_gid_name_len; 510 } 511 512 const ConstString & GetSDKRootDirectory()513 GetSDKRootDirectory () const 514 { 515 return m_sdk_sysroot; 516 } 517 518 void SetSDKRootDirectory(const ConstString & dir)519 SetSDKRootDirectory (const ConstString &dir) 520 { 521 m_sdk_sysroot = dir; 522 } 523 524 const ConstString & GetSDKBuild()525 GetSDKBuild () const 526 { 527 return m_sdk_build; 528 } 529 530 void SetSDKBuild(const ConstString & sdk_build)531 SetSDKBuild (const ConstString &sdk_build) 532 { 533 m_sdk_build = sdk_build; 534 } 535 536 // There may be modules that we don't want to find by default for operations like "setting breakpoint by name". 537 // The platform will return "true" from this call if the passed in module happens to be one of these. 538 539 virtual bool ModuleIsExcludedForNonModuleSpecificSearches(Target & target,const lldb::ModuleSP & module_sp)540 ModuleIsExcludedForNonModuleSpecificSearches (Target &target, const lldb::ModuleSP &module_sp) 541 { 542 return false; 543 } 544 545 virtual size_t 546 GetEnvironment (StringList &environment); 547 548 protected: 549 bool m_is_host; 550 // Set to true when we are able to actually set the OS version while 551 // being connected. For remote platforms, we might set the version ahead 552 // of time before we actually connect and this version might change when 553 // we actually connect to a remote platform. For the host platform this 554 // will be set to the once we call Host::GetOSVersion(). 555 bool m_os_version_set_while_connected; 556 bool m_system_arch_set_while_connected; 557 ConstString m_sdk_sysroot; // the root location of where the SDK files are all located 558 ConstString m_sdk_build; 559 std::string m_remote_url; 560 std::string m_name; 561 uint32_t m_major_os_version; 562 uint32_t m_minor_os_version; 563 uint32_t m_update_os_version; 564 ArchSpec m_system_arch; // The architecture of the kernel or the remote platform 565 typedef std::map<uint32_t, ConstString> IDToNameMap; 566 Mutex m_uid_map_mutex; 567 Mutex m_gid_map_mutex; 568 IDToNameMap m_uid_map; 569 IDToNameMap m_gid_map; 570 size_t m_max_uid_name_len; 571 size_t m_max_gid_name_len; 572 573 const char * GetCachedUserName(uint32_t uid)574 GetCachedUserName (uint32_t uid) 575 { 576 Mutex::Locker locker (m_uid_map_mutex); 577 IDToNameMap::iterator pos = m_uid_map.find (uid); 578 if (pos != m_uid_map.end()) 579 { 580 // return the empty string if our string is NULL 581 // so we can tell when things were in the negative 582 // cached (didn't find a valid user name, don't keep 583 // trying) 584 return pos->second.AsCString(""); 585 } 586 return NULL; 587 } 588 589 const char * SetCachedUserName(uint32_t uid,const char * name,size_t name_len)590 SetCachedUserName (uint32_t uid, const char *name, size_t name_len) 591 { 592 Mutex::Locker locker (m_uid_map_mutex); 593 ConstString const_name (name); 594 m_uid_map[uid] = const_name; 595 if (m_max_uid_name_len < name_len) 596 m_max_uid_name_len = name_len; 597 // Const strings lives forever in our const string pool, so we can return the const char * 598 return const_name.GetCString(); 599 } 600 601 void SetUserNameNotFound(uint32_t uid)602 SetUserNameNotFound (uint32_t uid) 603 { 604 Mutex::Locker locker (m_uid_map_mutex); 605 m_uid_map[uid] = ConstString(); 606 } 607 608 609 void ClearCachedUserNames()610 ClearCachedUserNames () 611 { 612 Mutex::Locker locker (m_uid_map_mutex); 613 m_uid_map.clear(); 614 } 615 616 const char * GetCachedGroupName(uint32_t gid)617 GetCachedGroupName (uint32_t gid) 618 { 619 Mutex::Locker locker (m_gid_map_mutex); 620 IDToNameMap::iterator pos = m_gid_map.find (gid); 621 if (pos != m_gid_map.end()) 622 { 623 // return the empty string if our string is NULL 624 // so we can tell when things were in the negative 625 // cached (didn't find a valid group name, don't keep 626 // trying) 627 return pos->second.AsCString(""); 628 } 629 return NULL; 630 } 631 632 const char * SetCachedGroupName(uint32_t gid,const char * name,size_t name_len)633 SetCachedGroupName (uint32_t gid, const char *name, size_t name_len) 634 { 635 Mutex::Locker locker (m_gid_map_mutex); 636 ConstString const_name (name); 637 m_gid_map[gid] = const_name; 638 if (m_max_gid_name_len < name_len) 639 m_max_gid_name_len = name_len; 640 // Const strings lives forever in our const string pool, so we can return the const char * 641 return const_name.GetCString(); 642 } 643 644 void SetGroupNameNotFound(uint32_t gid)645 SetGroupNameNotFound (uint32_t gid) 646 { 647 Mutex::Locker locker (m_gid_map_mutex); 648 m_gid_map[gid] = ConstString(); 649 } 650 651 void ClearCachedGroupNames()652 ClearCachedGroupNames () 653 { 654 Mutex::Locker locker (m_gid_map_mutex); 655 m_gid_map.clear(); 656 } 657 658 private: 659 DISALLOW_COPY_AND_ASSIGN (Platform); 660 }; 661 662 663 class PlatformList 664 { 665 public: PlatformList()666 PlatformList() : 667 m_mutex (Mutex::eMutexTypeRecursive), 668 m_platforms (), 669 m_selected_platform_sp() 670 { 671 } 672 ~PlatformList()673 ~PlatformList() 674 { 675 } 676 677 void Append(const lldb::PlatformSP & platform_sp,bool set_selected)678 Append (const lldb::PlatformSP &platform_sp, bool set_selected) 679 { 680 Mutex::Locker locker (m_mutex); 681 m_platforms.push_back (platform_sp); 682 if (set_selected) 683 m_selected_platform_sp = m_platforms.back(); 684 } 685 686 size_t GetSize()687 GetSize() 688 { 689 Mutex::Locker locker (m_mutex); 690 return m_platforms.size(); 691 } 692 693 lldb::PlatformSP GetAtIndex(uint32_t idx)694 GetAtIndex (uint32_t idx) 695 { 696 lldb::PlatformSP platform_sp; 697 { 698 Mutex::Locker locker (m_mutex); 699 if (idx < m_platforms.size()) 700 platform_sp = m_platforms[idx]; 701 } 702 return platform_sp; 703 } 704 705 //------------------------------------------------------------------ 706 /// Select the active platform. 707 /// 708 /// In order to debug remotely, other platform's can be remotely 709 /// connected to and set as the selected platform for any subsequent 710 /// debugging. This allows connection to remote targets and allows 711 /// the ability to discover process info, launch and attach to remote 712 /// processes. 713 //------------------------------------------------------------------ 714 lldb::PlatformSP GetSelectedPlatform()715 GetSelectedPlatform () 716 { 717 Mutex::Locker locker (m_mutex); 718 if (!m_selected_platform_sp && !m_platforms.empty()) 719 m_selected_platform_sp = m_platforms.front(); 720 721 return m_selected_platform_sp; 722 } 723 724 void SetSelectedPlatform(const lldb::PlatformSP & platform_sp)725 SetSelectedPlatform (const lldb::PlatformSP &platform_sp) 726 { 727 if (platform_sp) 728 { 729 Mutex::Locker locker (m_mutex); 730 const size_t num_platforms = m_platforms.size(); 731 for (size_t idx=0; idx<num_platforms; ++idx) 732 { 733 if (m_platforms[idx].get() == platform_sp.get()) 734 { 735 m_selected_platform_sp = m_platforms[idx]; 736 return; 737 } 738 } 739 m_platforms.push_back (platform_sp); 740 m_selected_platform_sp = m_platforms.back(); 741 } 742 } 743 744 protected: 745 typedef std::vector<lldb::PlatformSP> collection; 746 mutable Mutex m_mutex; 747 collection m_platforms; 748 lldb::PlatformSP m_selected_platform_sp; 749 750 private: 751 DISALLOW_COPY_AND_ASSIGN (PlatformList); 752 }; 753 } // namespace lldb_private 754 755 #endif // liblldb_Platform_h_ 756