1e996fd30SGreg Clayton //===-- PlatformLinux.cpp ---------------------------------------*- C++ -*-===// 2e996fd30SGreg Clayton // 3e996fd30SGreg Clayton // The LLVM Compiler Infrastructure 4e996fd30SGreg Clayton // 5e996fd30SGreg Clayton // This file is distributed under the University of Illinois Open Source 6e996fd30SGreg Clayton // License. See LICENSE.TXT for details. 7e996fd30SGreg Clayton // 8e996fd30SGreg Clayton //===----------------------------------------------------------------------===// 9e996fd30SGreg Clayton 1093a64300SDaniel Malea #include "lldb/lldb-python.h" 1193a64300SDaniel Malea 12e996fd30SGreg Clayton #include "PlatformLinux.h" 13b2f1fb29SVirgile Bello #include "lldb/Host/Config.h" 14e996fd30SGreg Clayton 15e996fd30SGreg Clayton // C Includes 16ecc11474SStephen Wilson #include <stdio.h> 17b2f1fb29SVirgile Bello #ifndef LLDB_DISABLE_POSIX 18ecc11474SStephen Wilson #include <sys/utsname.h> 19b2f1fb29SVirgile Bello #endif 20ecc11474SStephen Wilson 21e996fd30SGreg Clayton // C++ Includes 22e996fd30SGreg Clayton // Other libraries and framework includes 23e996fd30SGreg Clayton // Project includes 2428041352SGreg Clayton #include "lldb/Core/Debugger.h" 25*348fb385STodd Fiala #include "lldb/Core/Error.h" 26015d818bSTodd Fiala #include "lldb/Core/Log.h" 27e996fd30SGreg Clayton #include "lldb/Core/Module.h" 28e996fd30SGreg Clayton #include "lldb/Core/ModuleList.h" 291f746071SGreg Clayton #include "lldb/Core/ModuleSpec.h" 30ecc11474SStephen Wilson #include "lldb/Core/PluginManager.h" 31*348fb385STodd Fiala #include "lldb/Core/State.h" 32e996fd30SGreg Clayton #include "lldb/Core/StreamString.h" 33e996fd30SGreg Clayton #include "lldb/Host/FileSpec.h" 3413b18261SZachary Turner #include "lldb/Host/HostInfo.h" 35*348fb385STodd Fiala #include "lldb/Interpreter/OptionValueProperties.h" 36*348fb385STodd Fiala #include "lldb/Interpreter/Property.h" 37ecc11474SStephen Wilson #include "lldb/Target/Target.h" 38e996fd30SGreg Clayton #include "lldb/Target/Process.h" 39e996fd30SGreg Clayton 40af245d11STodd Fiala #if defined(__linux__) 41af245d11STodd Fiala #include "../../Process/Linux/NativeProcessLinux.h" 42af245d11STodd Fiala #endif 43af245d11STodd Fiala 44e996fd30SGreg Clayton using namespace lldb; 45e996fd30SGreg Clayton using namespace lldb_private; 46e996fd30SGreg Clayton 4728041352SGreg Clayton static uint32_t g_initialize_count = 0; 4828041352SGreg Clayton 49281961a8STodd Fiala //------------------------------------------------------------------ 50281961a8STodd Fiala /// Code to handle the PlatformLinux settings 51281961a8STodd Fiala //------------------------------------------------------------------ 52281961a8STodd Fiala 53*348fb385STodd Fiala namespace 54*348fb385STodd Fiala { 55*348fb385STodd Fiala enum 56*348fb385STodd Fiala { 57*348fb385STodd Fiala ePropertyUseLlgsForLocal = 0, 58*348fb385STodd Fiala }; 59*348fb385STodd Fiala 60*348fb385STodd Fiala const PropertyDefinition* 61*348fb385STodd Fiala GetStaticPropertyDefinitions () 62*348fb385STodd Fiala { 63281961a8STodd Fiala static PropertyDefinition 64281961a8STodd Fiala g_properties[] = 65281961a8STodd Fiala { 66281961a8STodd Fiala { "use-llgs-for-local" , OptionValue::eTypeBoolean, true, false, NULL, NULL, "Control whether the platform uses llgs for local debug sessions." }, 67281961a8STodd Fiala { NULL , OptionValue::eTypeInvalid, false, 0 , NULL, NULL, NULL } 68281961a8STodd Fiala }; 69281961a8STodd Fiala 70*348fb385STodd Fiala // Allow environment variable to force using llgs-local. 71*348fb385STodd Fiala if (getenv("PLATFORM_LINUX_FORCE_LLGS_LOCAL")) 72*348fb385STodd Fiala g_properties[ePropertyUseLlgsForLocal].default_uint_value = true; 73281961a8STodd Fiala 74*348fb385STodd Fiala return g_properties; 75*348fb385STodd Fiala } 76*348fb385STodd Fiala } 77281961a8STodd Fiala 78281961a8STodd Fiala class PlatformLinuxProperties : public Properties 79281961a8STodd Fiala { 80281961a8STodd Fiala public: 81281961a8STodd Fiala 82281961a8STodd Fiala static ConstString & 83281961a8STodd Fiala GetSettingName () 84281961a8STodd Fiala { 85281961a8STodd Fiala static ConstString g_setting_name("linux"); 86281961a8STodd Fiala return g_setting_name; 87281961a8STodd Fiala } 88281961a8STodd Fiala 89281961a8STodd Fiala PlatformLinuxProperties() : 90281961a8STodd Fiala Properties () 91281961a8STodd Fiala { 92281961a8STodd Fiala m_collection_sp.reset (new OptionValueProperties(GetSettingName ())); 93*348fb385STodd Fiala m_collection_sp->Initialize (GetStaticPropertyDefinitions ()); 94281961a8STodd Fiala } 95281961a8STodd Fiala 96281961a8STodd Fiala virtual 97281961a8STodd Fiala ~PlatformLinuxProperties() 98281961a8STodd Fiala { 99281961a8STodd Fiala } 100281961a8STodd Fiala 101281961a8STodd Fiala bool 102281961a8STodd Fiala GetUseLlgsForLocal() const 103281961a8STodd Fiala { 104281961a8STodd Fiala const uint32_t idx = ePropertyUseLlgsForLocal; 105*348fb385STodd Fiala return m_collection_sp->GetPropertyAtIndexAsBoolean (NULL, idx, GetStaticPropertyDefinitions()[idx].default_uint_value != 0); 106281961a8STodd Fiala } 107281961a8STodd Fiala }; 108281961a8STodd Fiala 109281961a8STodd Fiala typedef std::shared_ptr<PlatformLinuxProperties> PlatformLinuxPropertiesSP; 110281961a8STodd Fiala 111281961a8STodd Fiala static const PlatformLinuxPropertiesSP & 112281961a8STodd Fiala GetGlobalProperties() 113281961a8STodd Fiala { 114281961a8STodd Fiala static PlatformLinuxPropertiesSP g_settings_sp; 115281961a8STodd Fiala if (!g_settings_sp) 116281961a8STodd Fiala g_settings_sp.reset (new PlatformLinuxProperties ()); 117281961a8STodd Fiala return g_settings_sp; 118281961a8STodd Fiala } 119281961a8STodd Fiala 120281961a8STodd Fiala void 121281961a8STodd Fiala PlatformLinux::DebuggerInitialize (lldb_private::Debugger &debugger) 122281961a8STodd Fiala { 123281961a8STodd Fiala if (!PluginManager::GetSettingForPlatformPlugin (debugger, PlatformLinuxProperties::GetSettingName())) 124281961a8STodd Fiala { 125281961a8STodd Fiala const bool is_global_setting = true; 126281961a8STodd Fiala PluginManager::CreateSettingForPlatformPlugin (debugger, 127281961a8STodd Fiala GetGlobalProperties()->GetValueProperties(), 128281961a8STodd Fiala ConstString ("Properties for the PlatformLinux plug-in."), 129281961a8STodd Fiala is_global_setting); 130281961a8STodd Fiala } 131281961a8STodd Fiala } 132281961a8STodd Fiala 133281961a8STodd Fiala 134281961a8STodd Fiala //------------------------------------------------------------------ 135281961a8STodd Fiala 136615eb7e6SGreg Clayton PlatformSP 137b3a40ba8SGreg Clayton PlatformLinux::CreateInstance (bool force, const ArchSpec *arch) 138ecc11474SStephen Wilson { 139015d818bSTodd Fiala Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 140015d818bSTodd Fiala if (log) 141015d818bSTodd Fiala { 142015d818bSTodd Fiala const char *arch_name; 143015d818bSTodd Fiala if (arch && arch->GetArchitectureName ()) 144015d818bSTodd Fiala arch_name = arch->GetArchitectureName (); 145015d818bSTodd Fiala else 146015d818bSTodd Fiala arch_name = "<null>"; 147015d818bSTodd Fiala 148015d818bSTodd Fiala const char *triple_cstr = arch ? arch->GetTriple ().getTriple ().c_str() : "<null>"; 149015d818bSTodd Fiala 150015d818bSTodd Fiala log->Printf ("PlatformLinux::%s(force=%s, arch={%s,%s})", __FUNCTION__, force ? "true" : "false", arch_name, triple_cstr); 151015d818bSTodd Fiala } 152015d818bSTodd Fiala 153b3a40ba8SGreg Clayton bool create = force; 154b3a40ba8SGreg Clayton if (create == false && arch && arch->IsValid()) 155b3a40ba8SGreg Clayton { 156b3a40ba8SGreg Clayton const llvm::Triple &triple = arch->GetTriple(); 15770512317SGreg Clayton switch (triple.getVendor()) 15870512317SGreg Clayton { 15970512317SGreg Clayton case llvm::Triple::PC: 160b3a40ba8SGreg Clayton create = true; 16170512317SGreg Clayton break; 16270512317SGreg Clayton 163dbc6c0bbSGreg Clayton #if defined(__linux__) 164dbc6c0bbSGreg Clayton // Only accept "unknown" for the vendor if the host is linux and 1656a7f3338SBruce Mitchener // it "unknown" wasn't specified (it was just returned because it 166dbc6c0bbSGreg Clayton // was NOT specified_ 167015d818bSTodd Fiala case llvm::Triple::VendorType::UnknownVendor: 16870512317SGreg Clayton create = !arch->TripleVendorWasSpecified(); 16970512317SGreg Clayton break; 170dbc6c0bbSGreg Clayton #endif 17170512317SGreg Clayton default: 17270512317SGreg Clayton break; 17370512317SGreg Clayton } 17470512317SGreg Clayton 17570512317SGreg Clayton if (create) 17670512317SGreg Clayton { 17770512317SGreg Clayton switch (triple.getOS()) 17870512317SGreg Clayton { 17970512317SGreg Clayton case llvm::Triple::Linux: 18070512317SGreg Clayton break; 18170512317SGreg Clayton 182dbc6c0bbSGreg Clayton #if defined(__linux__) 183dbc6c0bbSGreg Clayton // Only accept "unknown" for the OS if the host is linux and 1846a7f3338SBruce Mitchener // it "unknown" wasn't specified (it was just returned because it 185dbc6c0bbSGreg Clayton // was NOT specified) 186015d818bSTodd Fiala case llvm::Triple::OSType::UnknownOS: 18770512317SGreg Clayton create = !arch->TripleOSWasSpecified(); 18870512317SGreg Clayton break; 189dbc6c0bbSGreg Clayton #endif 19070512317SGreg Clayton default: 19170512317SGreg Clayton create = false; 19270512317SGreg Clayton break; 19370512317SGreg Clayton } 19470512317SGreg Clayton } 195b3a40ba8SGreg Clayton } 196015d818bSTodd Fiala 197b3a40ba8SGreg Clayton if (create) 198015d818bSTodd Fiala { 199015d818bSTodd Fiala if (log) 200015d818bSTodd Fiala log->Printf ("PlatformLinux::%s() creating remote-linux platform", __FUNCTION__); 201615eb7e6SGreg Clayton return PlatformSP(new PlatformLinux(false)); 202015d818bSTodd Fiala } 203015d818bSTodd Fiala 204015d818bSTodd Fiala if (log) 205015d818bSTodd Fiala log->Printf ("PlatformLinux::%s() aborting creation of remote-linux platform", __FUNCTION__); 206015d818bSTodd Fiala 207615eb7e6SGreg Clayton return PlatformSP(); 208ecc11474SStephen Wilson } 209ecc11474SStephen Wilson 210ecc11474SStephen Wilson 21157abc5d6SGreg Clayton lldb_private::ConstString 21257abc5d6SGreg Clayton PlatformLinux::GetPluginNameStatic (bool is_host) 213ecc11474SStephen Wilson { 21428041352SGreg Clayton if (is_host) 21557abc5d6SGreg Clayton { 21657abc5d6SGreg Clayton static ConstString g_host_name(Platform::GetHostPlatformName ()); 21757abc5d6SGreg Clayton return g_host_name; 21857abc5d6SGreg Clayton } 21928041352SGreg Clayton else 22057abc5d6SGreg Clayton { 22157abc5d6SGreg Clayton static ConstString g_remote_name("remote-linux"); 22257abc5d6SGreg Clayton return g_remote_name; 22357abc5d6SGreg Clayton } 22428041352SGreg Clayton } 22528041352SGreg Clayton 22628041352SGreg Clayton const char * 22728041352SGreg Clayton PlatformLinux::GetPluginDescriptionStatic (bool is_host) 22828041352SGreg Clayton { 22928041352SGreg Clayton if (is_host) 23028041352SGreg Clayton return "Local Linux user platform plug-in."; 23128041352SGreg Clayton else 23228041352SGreg Clayton return "Remote Linux user platform plug-in."; 233ecc11474SStephen Wilson } 234ecc11474SStephen Wilson 23557abc5d6SGreg Clayton lldb_private::ConstString 23657abc5d6SGreg Clayton PlatformLinux::GetPluginName() 23757abc5d6SGreg Clayton { 23857abc5d6SGreg Clayton return GetPluginNameStatic(IsHost()); 23957abc5d6SGreg Clayton } 24057abc5d6SGreg Clayton 241e996fd30SGreg Clayton void 242e996fd30SGreg Clayton PlatformLinux::Initialize () 243e996fd30SGreg Clayton { 24428041352SGreg Clayton if (g_initialize_count++ == 0) 245ecc11474SStephen Wilson { 24628041352SGreg Clayton #if defined(__linux__) 24728041352SGreg Clayton PlatformSP default_platform_sp (new PlatformLinux(true)); 24813b18261SZachary Turner default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 249615eb7e6SGreg Clayton Platform::SetHostPlatform (default_platform_sp); 25028041352SGreg Clayton #endif 25157abc5d6SGreg Clayton PluginManager::RegisterPlugin(PlatformLinux::GetPluginNameStatic(false), 25228041352SGreg Clayton PlatformLinux::GetPluginDescriptionStatic(false), 253281961a8STodd Fiala PlatformLinux::CreateInstance, 254281961a8STodd Fiala PlatformLinux::DebuggerInitialize); 255ecc11474SStephen Wilson } 256e996fd30SGreg Clayton } 257e996fd30SGreg Clayton 258e996fd30SGreg Clayton void 259e996fd30SGreg Clayton PlatformLinux::Terminate () 260e996fd30SGreg Clayton { 26128041352SGreg Clayton if (g_initialize_count > 0) 26228041352SGreg Clayton { 26328041352SGreg Clayton if (--g_initialize_count == 0) 26428041352SGreg Clayton { 26528041352SGreg Clayton PluginManager::UnregisterPlugin (PlatformLinux::CreateInstance); 266e996fd30SGreg Clayton } 26728041352SGreg Clayton } 26828041352SGreg Clayton } 269e996fd30SGreg Clayton 270e996fd30SGreg Clayton Error 271e996fd30SGreg Clayton PlatformLinux::ResolveExecutable (const FileSpec &exe_file, 272e996fd30SGreg Clayton const ArchSpec &exe_arch, 273ea5e0cc3SGreg Clayton lldb::ModuleSP &exe_module_sp, 274ea5e0cc3SGreg Clayton const FileSpecList *module_search_paths_ptr) 275e996fd30SGreg Clayton { 276e996fd30SGreg Clayton Error error; 277e996fd30SGreg Clayton // Nothing special to do here, just use the actual file and architecture 278e996fd30SGreg Clayton 27928041352SGreg Clayton char exe_path[PATH_MAX]; 280e996fd30SGreg Clayton FileSpec resolved_exe_file (exe_file); 281e996fd30SGreg Clayton 28228041352SGreg Clayton if (IsHost()) 28328041352SGreg Clayton { 28428041352SGreg Clayton // If we have "ls" as the exe_file, resolve the executable location based on 285e996fd30SGreg Clayton // the current path variables 286e996fd30SGreg Clayton if (!resolved_exe_file.Exists()) 28728041352SGreg Clayton { 28828041352SGreg Clayton exe_file.GetPath(exe_path, sizeof(exe_path)); 28928041352SGreg Clayton resolved_exe_file.SetFile(exe_path, true); 29028041352SGreg Clayton } 29128041352SGreg Clayton 29228041352SGreg Clayton if (!resolved_exe_file.Exists()) 293e996fd30SGreg Clayton resolved_exe_file.ResolveExecutableLocation (); 294e996fd30SGreg Clayton 29528041352SGreg Clayton if (resolved_exe_file.Exists()) 29628041352SGreg Clayton error.Clear(); 29728041352SGreg Clayton else 29828041352SGreg Clayton { 29928041352SGreg Clayton exe_file.GetPath(exe_path, sizeof(exe_path)); 30028041352SGreg Clayton error.SetErrorStringWithFormat("unable to find executable for '%s'", exe_path); 30128041352SGreg Clayton } 30228041352SGreg Clayton } 30328041352SGreg Clayton else 30428041352SGreg Clayton { 30528041352SGreg Clayton if (m_remote_platform_sp) 30628041352SGreg Clayton { 30728041352SGreg Clayton error = m_remote_platform_sp->ResolveExecutable (exe_file, 30828041352SGreg Clayton exe_arch, 3090c90ef47SGreg Clayton exe_module_sp, 3100c90ef47SGreg Clayton NULL); 31128041352SGreg Clayton } 31228041352SGreg Clayton else 31328041352SGreg Clayton { 31428041352SGreg Clayton // We may connect to a process and use the provided executable (Don't use local $PATH). 315e996fd30SGreg Clayton 316e996fd30SGreg Clayton if (resolved_exe_file.Exists()) 31728041352SGreg Clayton error.Clear(); 31828041352SGreg Clayton else 31928041352SGreg Clayton error.SetErrorStringWithFormat("the platform is not currently connected, and '%s' doesn't exist in the system root.", exe_path); 32028041352SGreg Clayton } 32128041352SGreg Clayton } 32228041352SGreg Clayton 32328041352SGreg Clayton if (error.Success()) 324e996fd30SGreg Clayton { 325ea5e0cc3SGreg Clayton ModuleSpec module_spec (resolved_exe_file, exe_arch); 326e996fd30SGreg Clayton if (exe_arch.IsValid()) 327e996fd30SGreg Clayton { 328ea5e0cc3SGreg Clayton error = ModuleList::GetSharedModule (module_spec, 329e996fd30SGreg Clayton exe_module_sp, 330e996fd30SGreg Clayton NULL, 3310c90ef47SGreg Clayton NULL, 332e996fd30SGreg Clayton NULL); 3339f0013d8SMichael Sartain if (error.Fail()) 3349f0013d8SMichael Sartain { 3359f0013d8SMichael Sartain // If we failed, it may be because the vendor and os aren't known. If that is the 3369f0013d8SMichael Sartain // case, try setting them to the host architecture and give it another try. 3379f0013d8SMichael Sartain llvm::Triple &module_triple = module_spec.GetArchitecture().GetTriple(); 3389f0013d8SMichael Sartain bool is_vendor_specified = (module_triple.getVendor() != llvm::Triple::UnknownVendor); 3399f0013d8SMichael Sartain bool is_os_specified = (module_triple.getOS() != llvm::Triple::UnknownOS); 3409f0013d8SMichael Sartain if (!is_vendor_specified || !is_os_specified) 3419f0013d8SMichael Sartain { 34213b18261SZachary Turner const llvm::Triple &host_triple = HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple(); 3439f0013d8SMichael Sartain 3449f0013d8SMichael Sartain if (!is_vendor_specified) 3459f0013d8SMichael Sartain module_triple.setVendorName (host_triple.getVendorName()); 3469f0013d8SMichael Sartain if (!is_os_specified) 3479f0013d8SMichael Sartain module_triple.setOSName (host_triple.getOSName()); 3489f0013d8SMichael Sartain 3499f0013d8SMichael Sartain error = ModuleList::GetSharedModule (module_spec, 3509f0013d8SMichael Sartain exe_module_sp, 3519f0013d8SMichael Sartain NULL, 3529f0013d8SMichael Sartain NULL, 3539f0013d8SMichael Sartain NULL); 3549f0013d8SMichael Sartain } 3559f0013d8SMichael Sartain } 356e996fd30SGreg Clayton 357e635db49SSean Callanan // TODO find out why exe_module_sp might be NULL 358e635db49SSean Callanan if (!exe_module_sp || exe_module_sp->GetObjectFile() == NULL) 359e996fd30SGreg Clayton { 360e996fd30SGreg Clayton exe_module_sp.reset(); 361b5ad4ec7SGreg Clayton error.SetErrorStringWithFormat ("'%s' doesn't contain the architecture %s", 362b5ad4ec7SGreg Clayton exe_file.GetPath().c_str(), 363e996fd30SGreg Clayton exe_arch.GetArchitectureName()); 364e996fd30SGreg Clayton } 365e996fd30SGreg Clayton } 366e996fd30SGreg Clayton else 367e996fd30SGreg Clayton { 368e996fd30SGreg Clayton // No valid architecture was specified, ask the platform for 369e996fd30SGreg Clayton // the architectures that we should be using (in the correct order) 370e996fd30SGreg Clayton // and see if we can find a match that way 371e996fd30SGreg Clayton StreamString arch_names; 372ea5e0cc3SGreg Clayton for (uint32_t idx = 0; GetSupportedArchitectureAtIndex (idx, module_spec.GetArchitecture()); ++idx) 373e996fd30SGreg Clayton { 374ea5e0cc3SGreg Clayton error = ModuleList::GetSharedModule (module_spec, 375e996fd30SGreg Clayton exe_module_sp, 376e996fd30SGreg Clayton NULL, 3770c90ef47SGreg Clayton NULL, 378e996fd30SGreg Clayton NULL); 379e996fd30SGreg Clayton // Did we find an executable using one of the 380e996fd30SGreg Clayton if (error.Success()) 381e996fd30SGreg Clayton { 382e996fd30SGreg Clayton if (exe_module_sp && exe_module_sp->GetObjectFile()) 383e996fd30SGreg Clayton break; 384e996fd30SGreg Clayton else 385e996fd30SGreg Clayton error.SetErrorToGenericError(); 386e996fd30SGreg Clayton } 387e996fd30SGreg Clayton 388e996fd30SGreg Clayton if (idx > 0) 389e996fd30SGreg Clayton arch_names.PutCString (", "); 390ea5e0cc3SGreg Clayton arch_names.PutCString (module_spec.GetArchitecture().GetArchitectureName()); 391e996fd30SGreg Clayton } 392e996fd30SGreg Clayton 393e996fd30SGreg Clayton if (error.Fail() || !exe_module_sp) 394e996fd30SGreg Clayton { 39539945dccSGreg Clayton if (exe_file.Readable()) 39639945dccSGreg Clayton { 397b5ad4ec7SGreg Clayton error.SetErrorStringWithFormat ("'%s' doesn't contain any '%s' platform architectures: %s", 398b5ad4ec7SGreg Clayton exe_file.GetPath().c_str(), 39957abc5d6SGreg Clayton GetPluginName().GetCString(), 400e996fd30SGreg Clayton arch_names.GetString().c_str()); 401e996fd30SGreg Clayton } 40239945dccSGreg Clayton else 40339945dccSGreg Clayton { 40439945dccSGreg Clayton error.SetErrorStringWithFormat("'%s' is not readable", exe_file.GetPath().c_str()); 40539945dccSGreg Clayton } 40639945dccSGreg Clayton } 407e996fd30SGreg Clayton } 408e996fd30SGreg Clayton } 409e996fd30SGreg Clayton 410e996fd30SGreg Clayton return error; 411e996fd30SGreg Clayton } 412e996fd30SGreg Clayton 413e996fd30SGreg Clayton Error 414fc995725SSteve Pucci PlatformLinux::GetFileWithUUID (const FileSpec &platform_file, 41528041352SGreg Clayton const UUID *uuid_ptr, FileSpec &local_file) 416e996fd30SGreg Clayton { 41728041352SGreg Clayton if (IsRemote()) 41828041352SGreg Clayton { 41928041352SGreg Clayton if (m_remote_platform_sp) 420fc995725SSteve Pucci return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file); 42128041352SGreg Clayton } 42228041352SGreg Clayton 423e996fd30SGreg Clayton // Default to the local case 424e996fd30SGreg Clayton local_file = platform_file; 425e996fd30SGreg Clayton return Error(); 426e996fd30SGreg Clayton } 427e996fd30SGreg Clayton 428e996fd30SGreg Clayton 429e996fd30SGreg Clayton //------------------------------------------------------------------ 430e996fd30SGreg Clayton /// Default Constructor 431e996fd30SGreg Clayton //------------------------------------------------------------------ 43228041352SGreg Clayton PlatformLinux::PlatformLinux (bool is_host) : 433015d818bSTodd Fiala PlatformPOSIX(is_host) // This is the local host platform 434e996fd30SGreg Clayton { 435e996fd30SGreg Clayton } 436e996fd30SGreg Clayton 437e996fd30SGreg Clayton //------------------------------------------------------------------ 438e996fd30SGreg Clayton /// Destructor. 439e996fd30SGreg Clayton /// 440e996fd30SGreg Clayton /// The destructor is virtual since this class is designed to be 441e996fd30SGreg Clayton /// inherited from by the plug-in instance. 442e996fd30SGreg Clayton //------------------------------------------------------------------ 443e996fd30SGreg Clayton PlatformLinux::~PlatformLinux() 444e996fd30SGreg Clayton { 445e996fd30SGreg Clayton } 446e996fd30SGreg Clayton 447e996fd30SGreg Clayton bool 44813e8e1c3SJohnny Chen PlatformLinux::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info) 449e996fd30SGreg Clayton { 45028041352SGreg Clayton bool success = false; 45128041352SGreg Clayton if (IsHost()) 45228041352SGreg Clayton { 45328041352SGreg Clayton success = Platform::GetProcessInfo (pid, process_info); 45428041352SGreg Clayton } 45528041352SGreg Clayton else 45628041352SGreg Clayton { 45728041352SGreg Clayton if (m_remote_platform_sp) 45828041352SGreg Clayton success = m_remote_platform_sp->GetProcessInfo (pid, process_info); 45928041352SGreg Clayton } 46028041352SGreg Clayton return success; 461e996fd30SGreg Clayton } 462e996fd30SGreg Clayton 463e996fd30SGreg Clayton bool 464e996fd30SGreg Clayton PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) 465e996fd30SGreg Clayton { 466e996fd30SGreg Clayton if (idx == 0) 467e996fd30SGreg Clayton { 46813b18261SZachary Turner arch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 469e996fd30SGreg Clayton return arch.IsValid(); 470e996fd30SGreg Clayton } 471542e4075SGreg Clayton else if (idx == 1) 472542e4075SGreg Clayton { 473542e4075SGreg Clayton // If the default host architecture is 64-bit, look for a 32-bit variant 47413b18261SZachary Turner ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 475542e4075SGreg Clayton if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) 476542e4075SGreg Clayton { 47713b18261SZachary Turner arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); 478542e4075SGreg Clayton return arch.IsValid(); 479542e4075SGreg Clayton } 480542e4075SGreg Clayton } 481e996fd30SGreg Clayton return false; 482e996fd30SGreg Clayton } 483ecc11474SStephen Wilson 484ecc11474SStephen Wilson void 485ecc11474SStephen Wilson PlatformLinux::GetStatus (Stream &strm) 486ecc11474SStephen Wilson { 4873be69dacSDaniel Malea Platform::GetStatus(strm); 488ecc11474SStephen Wilson 489b2f1fb29SVirgile Bello #ifndef LLDB_DISABLE_POSIX 490b2f1fb29SVirgile Bello struct utsname un; 491b2f1fb29SVirgile Bello 4923be69dacSDaniel Malea if (uname(&un)) 4933be69dacSDaniel Malea return; 4943be69dacSDaniel Malea 4953be69dacSDaniel Malea strm.Printf (" Kernel: %s\n", un.sysname); 4963be69dacSDaniel Malea strm.Printf (" Release: %s\n", un.release); 4973be69dacSDaniel Malea strm.Printf (" Version: %s\n", un.version); 498b2f1fb29SVirgile Bello #endif 499ecc11474SStephen Wilson } 500ecc11474SStephen Wilson 501ecc11474SStephen Wilson size_t 502ecc11474SStephen Wilson PlatformLinux::GetSoftwareBreakpointTrapOpcode (Target &target, 503ecc11474SStephen Wilson BreakpointSite *bp_site) 504ecc11474SStephen Wilson { 505ecc11474SStephen Wilson ArchSpec arch = target.GetArchitecture(); 50628041352SGreg Clayton const uint8_t *trap_opcode = NULL; 50728041352SGreg Clayton size_t trap_opcode_size = 0; 508ecc11474SStephen Wilson 509906e9acfSGreg Clayton switch (arch.GetMachine()) 510ecc11474SStephen Wilson { 511ecc11474SStephen Wilson default: 512ecc11474SStephen Wilson assert(false && "CPU type not supported!"); 513ecc11474SStephen Wilson break; 514ecc11474SStephen Wilson 5152afc5966STodd Fiala case llvm::Triple::aarch64: 5162afc5966STodd Fiala { 5172afc5966STodd Fiala static const uint8_t g_aarch64_opcode[] = { 0x00, 0x00, 0x20, 0xd4 }; 5182afc5966STodd Fiala trap_opcode = g_aarch64_opcode; 5192afc5966STodd Fiala trap_opcode_size = sizeof(g_aarch64_opcode); 5202afc5966STodd Fiala } 5212afc5966STodd Fiala break; 522906e9acfSGreg Clayton case llvm::Triple::x86: 523906e9acfSGreg Clayton case llvm::Triple::x86_64: 52428041352SGreg Clayton { 52528041352SGreg Clayton static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; 52628041352SGreg Clayton trap_opcode = g_i386_breakpoint_opcode; 52728041352SGreg Clayton trap_opcode_size = sizeof(g_i386_breakpoint_opcode); 52828041352SGreg Clayton } 529ecc11474SStephen Wilson break; 530906e9acfSGreg Clayton case llvm::Triple::hexagon: 5318006d319SDeepak Panickal { 5328006d319SDeepak Panickal static const uint8_t g_hex_opcode[] = { 0x0c, 0xdb, 0x00, 0x54 }; 5338006d319SDeepak Panickal trap_opcode = g_hex_opcode; 5348006d319SDeepak Panickal trap_opcode_size = sizeof(g_hex_opcode); 5358006d319SDeepak Panickal } 5368006d319SDeepak Panickal break; 537ecc11474SStephen Wilson } 538ecc11474SStephen Wilson 53928041352SGreg Clayton if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size)) 54028041352SGreg Clayton return trap_opcode_size; 54128041352SGreg Clayton return 0; 54228041352SGreg Clayton } 54328041352SGreg Clayton 544*348fb385STodd Fiala int32_t 545*348fb385STodd Fiala PlatformLinux::GetResumeCountForLaunchInfo (ProcessLaunchInfo &launch_info) 54628041352SGreg Clayton { 547*348fb385STodd Fiala int32_t resume_count = 0; 54828041352SGreg Clayton 549*348fb385STodd Fiala // Always resume past the initial stop when we use eLaunchFlagDebug 550*348fb385STodd Fiala if (launch_info.GetFlags ().Test (eLaunchFlagDebug)) 55128041352SGreg Clayton { 552*348fb385STodd Fiala // Resume past the stop for the final exec into the true inferior. 553*348fb385STodd Fiala ++resume_count; 554*348fb385STodd Fiala } 555015d818bSTodd Fiala 556*348fb385STodd Fiala // If we're not launching a shell, we're done. 557*348fb385STodd Fiala const char *shell = launch_info.GetShell(); 558*348fb385STodd Fiala if (shell == NULL) 559*348fb385STodd Fiala return resume_count; 560*348fb385STodd Fiala 561*348fb385STodd Fiala // We're in a shell, so for sure we have to resume past the shell exec. 562*348fb385STodd Fiala ++resume_count; 563*348fb385STodd Fiala 564*348fb385STodd Fiala // Figure out what shell we're planning on using. 565*348fb385STodd Fiala const char *shell_name = strrchr (shell, '/'); 566*348fb385STodd Fiala if (shell_name == NULL) 567*348fb385STodd Fiala shell_name = shell; 56828041352SGreg Clayton else 569*348fb385STodd Fiala shell_name++; 570*348fb385STodd Fiala 571*348fb385STodd Fiala if (strcmp (shell_name, "csh") == 0 572*348fb385STodd Fiala || strcmp (shell_name, "tcsh") == 0 573*348fb385STodd Fiala || strcmp (shell_name, "zsh") == 0 574*348fb385STodd Fiala || strcmp (shell_name, "sh") == 0) 57528041352SGreg Clayton { 576*348fb385STodd Fiala // These shells seem to re-exec themselves. Add another resume. 577*348fb385STodd Fiala ++resume_count; 578ecc11474SStephen Wilson } 57913e8e1c3SJohnny Chen 580*348fb385STodd Fiala return resume_count; 581*348fb385STodd Fiala } 582*348fb385STodd Fiala 583*348fb385STodd Fiala bool 584*348fb385STodd Fiala PlatformLinux::UseLlgsForLocalDebugging () 585*348fb385STodd Fiala { 586*348fb385STodd Fiala PlatformLinuxPropertiesSP properties_sp = GetGlobalProperties (); 587*348fb385STodd Fiala assert (properties_sp && "global properties shared pointer is null"); 588*348fb385STodd Fiala return properties_sp ? properties_sp->GetUseLlgsForLocal () : false; 589*348fb385STodd Fiala } 590*348fb385STodd Fiala 591015d818bSTodd Fiala bool 592015d818bSTodd Fiala PlatformLinux::CanDebugProcess () 593015d818bSTodd Fiala { 594015d818bSTodd Fiala if (IsHost ()) 595*348fb385STodd Fiala { 596*348fb385STodd Fiala // The platform only does local debugging (i.e. uses llgs) when the setting indicates we do that. 597*348fb385STodd Fiala // Otherwise, we'll use ProcessLinux/ProcessPOSIX to handle with ProcessMonitor. 598*348fb385STodd Fiala return UseLlgsForLocalDebugging (); 599*348fb385STodd Fiala } 600*348fb385STodd Fiala else 601*348fb385STodd Fiala { 602015d818bSTodd Fiala // If we're connected, we can debug. 603015d818bSTodd Fiala return IsConnected (); 604015d818bSTodd Fiala } 605*348fb385STodd Fiala } 606015d818bSTodd Fiala 607*348fb385STodd Fiala // For local debugging, Linux will override the debug logic to use llgs-launch rather than 608*348fb385STodd Fiala // lldb-launch, llgs-attach. This differs from current lldb-launch, debugserver-attach 609*348fb385STodd Fiala // approach on MacOSX. 61013e8e1c3SJohnny Chen lldb::ProcessSP 611*348fb385STodd Fiala PlatformLinux::DebugProcess (ProcessLaunchInfo &launch_info, 61213e8e1c3SJohnny Chen Debugger &debugger, 613*348fb385STodd Fiala Target *target, // Can be NULL, if NULL create a new target, else use existing one 61413e8e1c3SJohnny Chen Listener &listener, 61513e8e1c3SJohnny Chen Error &error) 61613e8e1c3SJohnny Chen { 617*348fb385STodd Fiala Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PLATFORM)); 618*348fb385STodd Fiala if (log) 619*348fb385STodd Fiala log->Printf ("PlatformLinux::%s entered (target %p)", __FUNCTION__, static_cast<void*>(target)); 62028041352SGreg Clayton 621*348fb385STodd Fiala // If we're a remote host, use standard behavior from parent class. 622*348fb385STodd Fiala if (!IsHost ()) 623*348fb385STodd Fiala return PlatformPOSIX::DebugProcess (launch_info, debugger, target, listener, error); 624*348fb385STodd Fiala 625*348fb385STodd Fiala // 626*348fb385STodd Fiala // For local debugging, we'll insist on having ProcessGDBRemote create the process. 627*348fb385STodd Fiala // 628*348fb385STodd Fiala 629*348fb385STodd Fiala ProcessSP process_sp; 630*348fb385STodd Fiala 631*348fb385STodd Fiala // Ensure we're using llgs for local debugging. 632*348fb385STodd Fiala if (!UseLlgsForLocalDebugging ()) 633*348fb385STodd Fiala { 634*348fb385STodd Fiala assert (false && "we're trying to debug a local process but platform.plugin.linux.use-llgs-for-local is false, should never get here"); 635*348fb385STodd Fiala error.SetErrorString ("attempted to start gdb-remote-based debugging for local process but platform.plugin.linux.use-llgs-for-local is false"); 636*348fb385STodd Fiala return process_sp; 637*348fb385STodd Fiala } 638*348fb385STodd Fiala 639*348fb385STodd Fiala // Make sure we stop at the entry point 640*348fb385STodd Fiala launch_info.GetFlags ().Set (eLaunchFlagDebug); 641*348fb385STodd Fiala 642*348fb385STodd Fiala // We always launch the process we are going to debug in a separate process 643*348fb385STodd Fiala // group, since then we can handle ^C interrupts ourselves w/o having to worry 644*348fb385STodd Fiala // about the target getting them as well. 645*348fb385STodd Fiala launch_info.SetLaunchInSeparateProcessGroup(true); 646*348fb385STodd Fiala 647*348fb385STodd Fiala // Ensure we have a target. 648*348fb385STodd Fiala if (target == nullptr) 649*348fb385STodd Fiala { 650*348fb385STodd Fiala if (log) 651*348fb385STodd Fiala log->Printf ("PlatformLinux::%s creating new target", __FUNCTION__); 652*348fb385STodd Fiala 653*348fb385STodd Fiala TargetSP new_target_sp; 65428041352SGreg Clayton error = debugger.GetTargetList().CreateTarget (debugger, 655*348fb385STodd Fiala nullptr, 656*348fb385STodd Fiala nullptr, 65728041352SGreg Clayton false, 658*348fb385STodd Fiala nullptr, 65928041352SGreg Clayton new_target_sp); 660*348fb385STodd Fiala if (error.Fail ()) 661*348fb385STodd Fiala { 662*348fb385STodd Fiala if (log) 663*348fb385STodd Fiala log->Printf ("PlatformLinux::%s failed to create new target: %s", __FUNCTION__, error.AsCString ()); 664*348fb385STodd Fiala return process_sp; 665*348fb385STodd Fiala } 666*348fb385STodd Fiala 66728041352SGreg Clayton target = new_target_sp.get(); 668*348fb385STodd Fiala if (!target) 669*348fb385STodd Fiala { 670*348fb385STodd Fiala error.SetErrorString ("CreateTarget() returned nullptr"); 671*348fb385STodd Fiala if (log) 672*348fb385STodd Fiala log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); 673*348fb385STodd Fiala return process_sp; 674*348fb385STodd Fiala } 67528041352SGreg Clayton } 67628041352SGreg Clayton else 67728041352SGreg Clayton { 678*348fb385STodd Fiala if (log) 679*348fb385STodd Fiala log->Printf ("PlatformLinux::%s using provided target", __FUNCTION__); 680*348fb385STodd Fiala } 681*348fb385STodd Fiala 682*348fb385STodd Fiala // Mark target as currently selected target. 68328041352SGreg Clayton debugger.GetTargetList().SetSelectedTarget(target); 68428041352SGreg Clayton 685*348fb385STodd Fiala // Now create the gdb-remote process. 686*348fb385STodd Fiala if (log) 687*348fb385STodd Fiala log->Printf ("PlatformLinux::%s having target create process with gdb-remote plugin", __FUNCTION__); 688*348fb385STodd Fiala process_sp = target->CreateProcess (listener, "gdb-remote", nullptr); 68928041352SGreg Clayton 690*348fb385STodd Fiala if (!process_sp) 691*348fb385STodd Fiala { 692*348fb385STodd Fiala error.SetErrorString ("CreateProcess() failed for gdb-remote process"); 693*348fb385STodd Fiala if (log) 694*348fb385STodd Fiala log->Printf ("PlatformLinux::%s failed: %s", __FUNCTION__, error.AsCString ()); 695*348fb385STodd Fiala return process_sp; 696*348fb385STodd Fiala } 697*348fb385STodd Fiala else 698*348fb385STodd Fiala { 699*348fb385STodd Fiala if (log) 700*348fb385STodd Fiala log->Printf ("PlatformLinux::%s successfully created process", __FUNCTION__); 701*348fb385STodd Fiala } 702*348fb385STodd Fiala 703*348fb385STodd Fiala // Set the unix signals properly. 704*348fb385STodd Fiala process_sp->SetUnixSignals (Host::GetUnixSignals ()); 705*348fb385STodd Fiala 706*348fb385STodd Fiala // Adjust launch for a hijacker. 707*348fb385STodd Fiala ListenerSP listener_sp; 708*348fb385STodd Fiala if (!launch_info.GetHijackListener ()) 709*348fb385STodd Fiala { 710*348fb385STodd Fiala if (log) 711*348fb385STodd Fiala log->Printf ("PlatformLinux::%s setting up hijacker", __FUNCTION__); 712*348fb385STodd Fiala 713*348fb385STodd Fiala listener_sp.reset (new Listener("lldb.PlatformLinux.DebugProcess.hijack")); 714*348fb385STodd Fiala launch_info.SetHijackListener (listener_sp); 715*348fb385STodd Fiala process_sp->HijackProcessEvents (listener_sp.get ()); 716*348fb385STodd Fiala } 717*348fb385STodd Fiala 718*348fb385STodd Fiala // Log file actions. 719*348fb385STodd Fiala if (log) 720*348fb385STodd Fiala { 721*348fb385STodd Fiala log->Printf ("PlatformLinux::%s launching process with the following file actions:", __FUNCTION__); 722*348fb385STodd Fiala 723*348fb385STodd Fiala StreamString stream; 724*348fb385STodd Fiala size_t i = 0; 725*348fb385STodd Fiala const FileAction *file_action; 726*348fb385STodd Fiala while ((file_action = launch_info.GetFileActionAtIndex (i++)) != nullptr) 727*348fb385STodd Fiala { 728*348fb385STodd Fiala file_action->Dump (stream); 729*348fb385STodd Fiala log->PutCString (stream.GetString().c_str ()); 730*348fb385STodd Fiala stream.Clear(); 731*348fb385STodd Fiala } 732*348fb385STodd Fiala } 733*348fb385STodd Fiala 734*348fb385STodd Fiala // Do the launch. 735*348fb385STodd Fiala error = process_sp->Launch(launch_info); 736*348fb385STodd Fiala if (error.Success ()) 737*348fb385STodd Fiala { 738*348fb385STodd Fiala // Handle the hijacking of process events. 739*348fb385STodd Fiala if (listener_sp) 740*348fb385STodd Fiala { 741*348fb385STodd Fiala const StateType state = process_sp->WaitForProcessToStop (NULL, NULL, false, listener_sp.get()); 742*348fb385STodd Fiala process_sp->RestoreProcessEvents(); 743*348fb385STodd Fiala 744*348fb385STodd Fiala if (state == eStateStopped) 745*348fb385STodd Fiala { 746*348fb385STodd Fiala if (log) 747*348fb385STodd Fiala log->Printf ("PlatformLinux::%s pid %" PRIu64 " state %s\n", 748*348fb385STodd Fiala __FUNCTION__, process_sp->GetID (), StateAsCString (state)); 749*348fb385STodd Fiala } 750*348fb385STodd Fiala else 751*348fb385STodd Fiala { 752*348fb385STodd Fiala if (log) 753*348fb385STodd Fiala log->Printf ("PlatformLinux::%s pid %" PRIu64 " state is not stopped - %s\n", 754*348fb385STodd Fiala __FUNCTION__, process_sp->GetID (), StateAsCString (state)); 755*348fb385STodd Fiala } 756*348fb385STodd Fiala } 757*348fb385STodd Fiala 758*348fb385STodd Fiala // Hook up process PTY if we have one (which we should for local debugging with llgs). 759*348fb385STodd Fiala int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 760*348fb385STodd Fiala if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) 761*348fb385STodd Fiala { 762*348fb385STodd Fiala process_sp->SetSTDIOFileDescriptor(pty_fd); 763*348fb385STodd Fiala if (log) 764*348fb385STodd Fiala log->Printf ("PlatformLinux::%s pid %" PRIu64 " hooked up STDIO pty to process", __FUNCTION__, process_sp->GetID ()); 765*348fb385STodd Fiala } 766*348fb385STodd Fiala else 767*348fb385STodd Fiala { 768*348fb385STodd Fiala if (log) 769*348fb385STodd Fiala log->Printf ("PlatformLinux::%s pid %" PRIu64 " not using process STDIO pty", __FUNCTION__, process_sp->GetID ()); 77028041352SGreg Clayton } 77128041352SGreg Clayton } 77228041352SGreg Clayton else 77328041352SGreg Clayton { 774*348fb385STodd Fiala if (log) 775*348fb385STodd Fiala log->Printf ("PlatformLinux::%s process launch failed: %s", __FUNCTION__, error.AsCString ()); 776*348fb385STodd Fiala // FIXME figure out appropriate cleanup here. Do we delete the target? Do we delete the process? Does our caller do that? 77728041352SGreg Clayton } 778*348fb385STodd Fiala 77928041352SGreg Clayton return process_sp; 78013e8e1c3SJohnny Chen } 7812094dbf4SJason Molenda 7822094dbf4SJason Molenda void 7832094dbf4SJason Molenda PlatformLinux::CalculateTrapHandlerSymbolNames () 7842094dbf4SJason Molenda { 7852094dbf4SJason Molenda m_trap_handlers.push_back (ConstString ("_sigtramp")); 7862094dbf4SJason Molenda } 787af245d11STodd Fiala 788af245d11STodd Fiala Error 789af245d11STodd Fiala PlatformLinux::LaunchNativeProcess ( 790af245d11STodd Fiala ProcessLaunchInfo &launch_info, 791af245d11STodd Fiala lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, 792af245d11STodd Fiala NativeProcessProtocolSP &process_sp) 793af245d11STodd Fiala { 794af245d11STodd Fiala #if !defined(__linux__) 795af245d11STodd Fiala return Error("only implemented on Linux hosts"); 796af245d11STodd Fiala #else 797af245d11STodd Fiala if (!IsHost ()) 798af245d11STodd Fiala return Error("PlatformLinux::%s (): cannot launch a debug process when not the host", __FUNCTION__); 799af245d11STodd Fiala 800af245d11STodd Fiala // Retrieve the exe module. 801af245d11STodd Fiala lldb::ModuleSP exe_module_sp; 802af245d11STodd Fiala 803af245d11STodd Fiala Error error = ResolveExecutable ( 804af245d11STodd Fiala launch_info.GetExecutableFile (), 805af245d11STodd Fiala launch_info.GetArchitecture (), 806af245d11STodd Fiala exe_module_sp, 807af245d11STodd Fiala NULL); 808af245d11STodd Fiala 809af245d11STodd Fiala if (!error.Success ()) 810af245d11STodd Fiala return error; 811af245d11STodd Fiala 812af245d11STodd Fiala if (!exe_module_sp) 813af245d11STodd Fiala return Error("exe_module_sp could not be resolved for %s", launch_info.GetExecutableFile ().GetPath ().c_str ()); 814af245d11STodd Fiala 815af245d11STodd Fiala // Launch it for debugging 816af245d11STodd Fiala error = NativeProcessLinux::LaunchProcess ( 817af245d11STodd Fiala exe_module_sp.get (), 818af245d11STodd Fiala launch_info, 819af245d11STodd Fiala native_delegate, 820af245d11STodd Fiala process_sp); 821af245d11STodd Fiala 822af245d11STodd Fiala return error; 823af245d11STodd Fiala #endif 824af245d11STodd Fiala } 825af245d11STodd Fiala 826af245d11STodd Fiala Error 827af245d11STodd Fiala PlatformLinux::AttachNativeProcess (lldb::pid_t pid, 828af245d11STodd Fiala lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate, 829af245d11STodd Fiala NativeProcessProtocolSP &process_sp) 830af245d11STodd Fiala { 831af245d11STodd Fiala #if !defined(__linux__) 832af245d11STodd Fiala return Error("only implemented on Linux hosts"); 833af245d11STodd Fiala #else 834af245d11STodd Fiala if (!IsHost ()) 835af245d11STodd Fiala return Error("PlatformLinux::%s (): cannot attach to a debug process when not the host", __FUNCTION__); 836af245d11STodd Fiala 837af245d11STodd Fiala // Launch it for debugging 838af245d11STodd Fiala return NativeProcessLinux::AttachToProcess (pid, native_delegate, process_sp); 839af245d11STodd Fiala #endif 840af245d11STodd Fiala } 841