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 10e996fd30SGreg Clayton #include "PlatformLinux.h" 11b2f1fb29SVirgile Bello #include "lldb/Host/Config.h" 12e996fd30SGreg Clayton 13e996fd30SGreg Clayton // C Includes 14ecc11474SStephen Wilson #include <stdio.h> 15b2f1fb29SVirgile Bello #ifndef LLDB_DISABLE_POSIX 16ecc11474SStephen Wilson #include <sys/utsname.h> 17b2f1fb29SVirgile Bello #endif 18ecc11474SStephen Wilson 19e996fd30SGreg Clayton // C++ Includes 20e996fd30SGreg Clayton // Other libraries and framework includes 21e996fd30SGreg Clayton // Project includes 222586e94bSJason Molenda #include "lldb/Breakpoint/BreakpointLocation.h" 2328041352SGreg Clayton #include "lldb/Core/Debugger.h" 24015d818bSTodd Fiala #include "lldb/Core/Log.h" 25e996fd30SGreg Clayton #include "lldb/Core/Module.h" 26e996fd30SGreg Clayton #include "lldb/Core/ModuleList.h" 271f746071SGreg Clayton #include "lldb/Core/ModuleSpec.h" 28ecc11474SStephen Wilson #include "lldb/Core/PluginManager.h" 29348fb385STodd Fiala #include "lldb/Core/State.h" 30e996fd30SGreg Clayton #include "lldb/Host/FileSpec.h" 3113b18261SZachary Turner #include "lldb/Host/HostInfo.h" 32348fb385STodd Fiala #include "lldb/Interpreter/OptionValueProperties.h" 33348fb385STodd Fiala #include "lldb/Interpreter/Property.h" 34e996fd30SGreg Clayton #include "lldb/Target/Process.h" 35b9c1b51eSKate Stone #include "lldb/Target/Target.h" 36*bf9a7730SZachary Turner #include "lldb/Utility/Error.h" 37*bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h" 38e996fd30SGreg Clayton 39a868c13cSBruce Mitchener // Define these constants from Linux mman.h for use when targeting 4096ad3de5SRobert Flack // remote linux systems even when host has different values. 4196ad3de5SRobert Flack #define MAP_PRIVATE 2 4296ad3de5SRobert Flack #define MAP_ANON 0x20 4396ad3de5SRobert Flack 44e996fd30SGreg Clayton using namespace lldb; 45e996fd30SGreg Clayton using namespace lldb_private; 46db264a6dSTamas Berghammer using namespace lldb_private::platform_linux; 47e996fd30SGreg Clayton 4828041352SGreg Clayton static uint32_t g_initialize_count = 0; 4928041352SGreg Clayton 50281961a8STodd Fiala //------------------------------------------------------------------ 51281961a8STodd Fiala /// Code to handle the PlatformLinux settings 52281961a8STodd Fiala //------------------------------------------------------------------ 53281961a8STodd Fiala 54b9c1b51eSKate Stone namespace { 55b9c1b51eSKate Stone class PlatformLinuxProperties : public Properties { 56db264a6dSTamas Berghammer public: 57db264a6dSTamas Berghammer PlatformLinuxProperties(); 58db264a6dSTamas Berghammer 59222b937cSEugene Zelenko ~PlatformLinuxProperties() override = default; 60222b937cSEugene Zelenko 61b9c1b51eSKate Stone static ConstString &GetSettingName(); 62db264a6dSTamas Berghammer 63db264a6dSTamas Berghammer private: 64b9c1b51eSKate Stone static const PropertyDefinition *GetStaticPropertyDefinitions(); 65db264a6dSTamas Berghammer }; 66db264a6dSTamas Berghammer 67db264a6dSTamas Berghammer typedef std::shared_ptr<PlatformLinuxProperties> PlatformLinuxPropertiesSP; 68db264a6dSTamas Berghammer 69db264a6dSTamas Berghammer } // anonymous namespace 70db264a6dSTamas Berghammer 71b9c1b51eSKate Stone PlatformLinuxProperties::PlatformLinuxProperties() : Properties() { 72db264a6dSTamas Berghammer m_collection_sp.reset(new OptionValueProperties(GetSettingName())); 73db264a6dSTamas Berghammer m_collection_sp->Initialize(GetStaticPropertyDefinitions()); 74db264a6dSTamas Berghammer } 75db264a6dSTamas Berghammer 76b9c1b51eSKate Stone ConstString &PlatformLinuxProperties::GetSettingName() { 77db264a6dSTamas Berghammer static ConstString g_setting_name("linux"); 78db264a6dSTamas Berghammer return g_setting_name; 79db264a6dSTamas Berghammer } 80db264a6dSTamas Berghammer 81348fb385STodd Fiala const PropertyDefinition * 82b9c1b51eSKate Stone PlatformLinuxProperties::GetStaticPropertyDefinitions() { 83b9c1b51eSKate Stone static PropertyDefinition g_properties[] = { 84b9c1b51eSKate Stone {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}}; 85281961a8STodd Fiala 86348fb385STodd Fiala return g_properties; 87348fb385STodd Fiala } 88281961a8STodd Fiala 89b9c1b51eSKate Stone static const PlatformLinuxPropertiesSP &GetGlobalProperties() { 90281961a8STodd Fiala static PlatformLinuxPropertiesSP g_settings_sp; 91281961a8STodd Fiala if (!g_settings_sp) 92281961a8STodd Fiala g_settings_sp.reset(new PlatformLinuxProperties()); 93281961a8STodd Fiala return g_settings_sp; 94281961a8STodd Fiala } 95281961a8STodd Fiala 96b9c1b51eSKate Stone void PlatformLinux::DebuggerInitialize(Debugger &debugger) { 97b9c1b51eSKate Stone if (!PluginManager::GetSettingForPlatformPlugin( 98b9c1b51eSKate Stone debugger, PlatformLinuxProperties::GetSettingName())) { 99281961a8STodd Fiala const bool is_global_setting = true; 100b9c1b51eSKate Stone PluginManager::CreateSettingForPlatformPlugin( 101b9c1b51eSKate Stone debugger, GetGlobalProperties()->GetValueProperties(), 102281961a8STodd Fiala ConstString("Properties for the PlatformLinux plug-in."), 103281961a8STodd Fiala is_global_setting); 104281961a8STodd Fiala } 105281961a8STodd Fiala } 106281961a8STodd Fiala 107281961a8STodd Fiala //------------------------------------------------------------------ 108281961a8STodd Fiala 109b9c1b51eSKate Stone PlatformSP PlatformLinux::CreateInstance(bool force, const ArchSpec *arch) { 110db264a6dSTamas Berghammer Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 111b9c1b51eSKate Stone if (log) { 112015d818bSTodd Fiala const char *arch_name; 113015d818bSTodd Fiala if (arch && arch->GetArchitectureName()) 114015d818bSTodd Fiala arch_name = arch->GetArchitectureName(); 115015d818bSTodd Fiala else 116015d818bSTodd Fiala arch_name = "<null>"; 117015d818bSTodd Fiala 118b9c1b51eSKate Stone const char *triple_cstr = 119b9c1b51eSKate Stone arch ? arch->GetTriple().getTriple().c_str() : "<null>"; 120015d818bSTodd Fiala 121b9c1b51eSKate Stone log->Printf("PlatformLinux::%s(force=%s, arch={%s,%s})", __FUNCTION__, 122b9c1b51eSKate Stone force ? "true" : "false", arch_name, triple_cstr); 123015d818bSTodd Fiala } 124015d818bSTodd Fiala 125b3a40ba8SGreg Clayton bool create = force; 126b9c1b51eSKate Stone if (create == false && arch && arch->IsValid()) { 127b3a40ba8SGreg Clayton const llvm::Triple &triple = arch->GetTriple(); 128b9c1b51eSKate Stone switch (triple.getOS()) { 12970512317SGreg Clayton case llvm::Triple::Linux: 130b1da257aSTed Woodward create = true; 13170512317SGreg Clayton break; 13270512317SGreg Clayton 133dbc6c0bbSGreg Clayton #if defined(__linux__) 134dbc6c0bbSGreg Clayton // Only accept "unknown" for the OS if the host is linux and 1356a7f3338SBruce Mitchener // it "unknown" wasn't specified (it was just returned because it 136dbc6c0bbSGreg Clayton // was NOT specified) 137015d818bSTodd Fiala case llvm::Triple::OSType::UnknownOS: 13870512317SGreg Clayton create = !arch->TripleOSWasSpecified(); 13970512317SGreg Clayton break; 140dbc6c0bbSGreg Clayton #endif 14170512317SGreg Clayton default: 14270512317SGreg Clayton break; 14370512317SGreg Clayton } 14470512317SGreg Clayton } 145015d818bSTodd Fiala 146b9c1b51eSKate Stone if (create) { 147015d818bSTodd Fiala if (log) 148b9c1b51eSKate Stone log->Printf("PlatformLinux::%s() creating remote-linux platform", 149b9c1b51eSKate Stone __FUNCTION__); 150615eb7e6SGreg Clayton return PlatformSP(new PlatformLinux(false)); 151015d818bSTodd Fiala } 152015d818bSTodd Fiala 153015d818bSTodd Fiala if (log) 154b9c1b51eSKate Stone log->Printf( 155b9c1b51eSKate Stone "PlatformLinux::%s() aborting creation of remote-linux platform", 156b9c1b51eSKate Stone __FUNCTION__); 157015d818bSTodd Fiala 158615eb7e6SGreg Clayton return PlatformSP(); 159ecc11474SStephen Wilson } 160ecc11474SStephen Wilson 161b9c1b51eSKate Stone ConstString PlatformLinux::GetPluginNameStatic(bool is_host) { 162b9c1b51eSKate Stone if (is_host) { 16357abc5d6SGreg Clayton static ConstString g_host_name(Platform::GetHostPlatformName()); 16457abc5d6SGreg Clayton return g_host_name; 165b9c1b51eSKate Stone } else { 16657abc5d6SGreg Clayton static ConstString g_remote_name("remote-linux"); 16757abc5d6SGreg Clayton return g_remote_name; 16857abc5d6SGreg Clayton } 16928041352SGreg Clayton } 17028041352SGreg Clayton 171b9c1b51eSKate Stone const char *PlatformLinux::GetPluginDescriptionStatic(bool is_host) { 17228041352SGreg Clayton if (is_host) 17328041352SGreg Clayton return "Local Linux user platform plug-in."; 17428041352SGreg Clayton else 17528041352SGreg Clayton return "Remote Linux user platform plug-in."; 176ecc11474SStephen Wilson } 177ecc11474SStephen Wilson 178b9c1b51eSKate Stone ConstString PlatformLinux::GetPluginName() { 17957abc5d6SGreg Clayton return GetPluginNameStatic(IsHost()); 18057abc5d6SGreg Clayton } 18157abc5d6SGreg Clayton 182b9c1b51eSKate Stone void PlatformLinux::Initialize() { 1833c4f89d7STamas Berghammer PlatformPOSIX::Initialize(); 1843c4f89d7STamas Berghammer 185b9c1b51eSKate Stone if (g_initialize_count++ == 0) { 1861c6a1ea9STamas Berghammer #if defined(__linux__) && !defined(__ANDROID__) 18728041352SGreg Clayton PlatformSP default_platform_sp(new PlatformLinux(true)); 18813b18261SZachary Turner default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture()); 189615eb7e6SGreg Clayton Platform::SetHostPlatform(default_platform_sp); 19028041352SGreg Clayton #endif 191b9c1b51eSKate Stone PluginManager::RegisterPlugin( 192b9c1b51eSKate Stone PlatformLinux::GetPluginNameStatic(false), 19328041352SGreg Clayton PlatformLinux::GetPluginDescriptionStatic(false), 194b9c1b51eSKate Stone PlatformLinux::CreateInstance, PlatformLinux::DebuggerInitialize); 195ecc11474SStephen Wilson } 196e996fd30SGreg Clayton } 197e996fd30SGreg Clayton 198b9c1b51eSKate Stone void PlatformLinux::Terminate() { 199b9c1b51eSKate Stone if (g_initialize_count > 0) { 200b9c1b51eSKate Stone if (--g_initialize_count == 0) { 20128041352SGreg Clayton PluginManager::UnregisterPlugin(PlatformLinux::CreateInstance); 202e996fd30SGreg Clayton } 20328041352SGreg Clayton } 2043c4f89d7STamas Berghammer 2053c4f89d7STamas Berghammer PlatformPOSIX::Terminate(); 20628041352SGreg Clayton } 207e996fd30SGreg Clayton 208b9c1b51eSKate Stone Error PlatformLinux::GetFileWithUUID(const FileSpec &platform_file, 209b9c1b51eSKate Stone const UUID *uuid_ptr, 210b9c1b51eSKate Stone FileSpec &local_file) { 211b9c1b51eSKate Stone if (IsRemote()) { 21228041352SGreg Clayton if (m_remote_platform_sp) 213b9c1b51eSKate Stone return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr, 214b9c1b51eSKate Stone local_file); 21528041352SGreg Clayton } 21628041352SGreg Clayton 217e996fd30SGreg Clayton // Default to the local case 218e996fd30SGreg Clayton local_file = platform_file; 219c1edf566SMehdi Amini return Error(); 220e996fd30SGreg Clayton } 221e996fd30SGreg Clayton 222e996fd30SGreg Clayton //------------------------------------------------------------------ 223e996fd30SGreg Clayton /// Default Constructor 224e996fd30SGreg Clayton //------------------------------------------------------------------ 225b9c1b51eSKate Stone PlatformLinux::PlatformLinux(bool is_host) 226b9c1b51eSKate Stone : PlatformPOSIX(is_host) // This is the local host platform 227b9c1b51eSKate Stone {} 228e996fd30SGreg Clayton 229e996fd30SGreg Clayton //------------------------------------------------------------------ 230e996fd30SGreg Clayton /// Destructor. 231e996fd30SGreg Clayton /// 232e996fd30SGreg Clayton /// The destructor is virtual since this class is designed to be 233e996fd30SGreg Clayton /// inherited from by the plug-in instance. 234e996fd30SGreg Clayton //------------------------------------------------------------------ 235222b937cSEugene Zelenko PlatformLinux::~PlatformLinux() = default; 236e996fd30SGreg Clayton 237b9c1b51eSKate Stone bool PlatformLinux::GetProcessInfo(lldb::pid_t pid, 238b9c1b51eSKate Stone ProcessInstanceInfo &process_info) { 23928041352SGreg Clayton bool success = false; 240b9c1b51eSKate Stone if (IsHost()) { 24128041352SGreg Clayton success = Platform::GetProcessInfo(pid, process_info); 242b9c1b51eSKate Stone } else { 24328041352SGreg Clayton if (m_remote_platform_sp) 24428041352SGreg Clayton success = m_remote_platform_sp->GetProcessInfo(pid, process_info); 24528041352SGreg Clayton } 24628041352SGreg Clayton return success; 247e996fd30SGreg Clayton } 248e996fd30SGreg Clayton 2498e6ec453SStephane Sezer uint32_t 2508e6ec453SStephane Sezer PlatformLinux::FindProcesses(const ProcessInstanceInfoMatch &match_info, 251b9c1b51eSKate Stone ProcessInstanceInfoList &process_infos) { 2528e6ec453SStephane Sezer uint32_t match_count = 0; 253b9c1b51eSKate Stone if (IsHost()) { 2548e6ec453SStephane Sezer // Let the base class figure out the host details 2558e6ec453SStephane Sezer match_count = Platform::FindProcesses(match_info, process_infos); 256b9c1b51eSKate Stone } else { 2578e6ec453SStephane Sezer // If we are remote, we can only return results if we are connected 2588e6ec453SStephane Sezer if (m_remote_platform_sp) 259b9c1b51eSKate Stone match_count = 260b9c1b51eSKate Stone m_remote_platform_sp->FindProcesses(match_info, process_infos); 2618e6ec453SStephane Sezer } 2628e6ec453SStephane Sezer return match_count; 2638e6ec453SStephane Sezer } 2648e6ec453SStephane Sezer 265b9c1b51eSKate Stone bool PlatformLinux::GetSupportedArchitectureAtIndex(uint32_t idx, 266b9c1b51eSKate Stone ArchSpec &arch) { 267b9c1b51eSKate Stone if (IsHost()) { 268e49b8e06SRobert Flack ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); 269b9c1b51eSKate Stone if (hostArch.GetTriple().isOSLinux()) { 270b9c1b51eSKate Stone if (idx == 0) { 271e49b8e06SRobert Flack arch = hostArch; 272e49b8e06SRobert Flack return arch.IsValid(); 273b9c1b51eSKate Stone } else if (idx == 1) { 274e49b8e06SRobert Flack // If the default host architecture is 64-bit, look for a 32-bit variant 275b9c1b51eSKate Stone if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { 276e49b8e06SRobert Flack arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); 277e49b8e06SRobert Flack return arch.IsValid(); 278e49b8e06SRobert Flack } 279e49b8e06SRobert Flack } 280e49b8e06SRobert Flack } 281b9c1b51eSKate Stone } else { 282e49b8e06SRobert Flack if (m_remote_platform_sp) 283e49b8e06SRobert Flack return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); 284bb1e283cSTed Woodward 285bb1e283cSTed Woodward llvm::Triple triple; 286bb1e283cSTed Woodward // Set the OS to linux 287bb1e283cSTed Woodward triple.setOS(llvm::Triple::Linux); 288bb1e283cSTed Woodward // Set the architecture 289b9c1b51eSKate Stone switch (idx) { 290b9c1b51eSKate Stone case 0: 291b9c1b51eSKate Stone triple.setArchName("x86_64"); 292b9c1b51eSKate Stone break; 293b9c1b51eSKate Stone case 1: 294b9c1b51eSKate Stone triple.setArchName("i386"); 295b9c1b51eSKate Stone break; 296b9c1b51eSKate Stone case 2: 297b9c1b51eSKate Stone triple.setArchName("arm"); 298b9c1b51eSKate Stone break; 299b9c1b51eSKate Stone case 3: 300b9c1b51eSKate Stone triple.setArchName("aarch64"); 301b9c1b51eSKate Stone break; 302b9c1b51eSKate Stone case 4: 303b9c1b51eSKate Stone triple.setArchName("mips64"); 304b9c1b51eSKate Stone break; 305b9c1b51eSKate Stone case 5: 306b9c1b51eSKate Stone triple.setArchName("hexagon"); 307b9c1b51eSKate Stone break; 308b9c1b51eSKate Stone case 6: 309b9c1b51eSKate Stone triple.setArchName("mips"); 310b9c1b51eSKate Stone break; 311b9c1b51eSKate Stone case 7: 312b9c1b51eSKate Stone triple.setArchName("mips64el"); 313b9c1b51eSKate Stone break; 314b9c1b51eSKate Stone case 8: 315b9c1b51eSKate Stone triple.setArchName("mipsel"); 316b9c1b51eSKate Stone break; 317b9c1b51eSKate Stone case 9: 318b9c1b51eSKate Stone triple.setArchName("s390x"); 319b9c1b51eSKate Stone break; 320b9c1b51eSKate Stone default: 321b9c1b51eSKate Stone return false; 322bb1e283cSTed Woodward } 323b9c1b51eSKate Stone // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the 324b9c1b51eSKate Stone // vendor by 325b9c1b51eSKate Stone // calling triple.SetVendorName("unknown") so that it is a "unspecified 326b9c1b51eSKate Stone // unknown". 327b9c1b51eSKate Stone // This means when someone calls triple.GetVendorName() it will return an 328b9c1b51eSKate Stone // empty string 329b9c1b51eSKate Stone // which indicates that the vendor can be set when two architectures are 330b9c1b51eSKate Stone // merged 331bb1e283cSTed Woodward 332bb1e283cSTed Woodward // Now set the triple into "arch" and return true 333bb1e283cSTed Woodward arch.SetTriple(triple); 334bb1e283cSTed Woodward return true; 335e49b8e06SRobert Flack } 336e996fd30SGreg Clayton return false; 337e996fd30SGreg Clayton } 338ecc11474SStephen Wilson 339b9c1b51eSKate Stone void PlatformLinux::GetStatus(Stream &strm) { 3403be69dacSDaniel Malea Platform::GetStatus(strm); 341ecc11474SStephen Wilson 342b2f1fb29SVirgile Bello #ifndef LLDB_DISABLE_POSIX 343b743a803SStephane Sezer // Display local kernel information only when we are running in host mode. 344b743a803SStephane Sezer // Otherwise, we would end up printing non-Linux information (when running 34517b45390SJason Molenda // on Mac OS for example). 346b9c1b51eSKate Stone if (IsHost()) { 347b2f1fb29SVirgile Bello struct utsname un; 348b2f1fb29SVirgile Bello 3493be69dacSDaniel Malea if (uname(&un)) 3503be69dacSDaniel Malea return; 3513be69dacSDaniel Malea 3523be69dacSDaniel Malea strm.Printf(" Kernel: %s\n", un.sysname); 3533be69dacSDaniel Malea strm.Printf(" Release: %s\n", un.release); 3543be69dacSDaniel Malea strm.Printf(" Version: %s\n", un.version); 355b743a803SStephane Sezer } 356b2f1fb29SVirgile Bello #endif 357ecc11474SStephen Wilson } 358ecc11474SStephen Wilson 359348fb385STodd Fiala int32_t 360b9c1b51eSKate Stone PlatformLinux::GetResumeCountForLaunchInfo(ProcessLaunchInfo &launch_info) { 361348fb385STodd Fiala int32_t resume_count = 0; 36228041352SGreg Clayton 363348fb385STodd Fiala // Always resume past the initial stop when we use eLaunchFlagDebug 364b9c1b51eSKate Stone if (launch_info.GetFlags().Test(eLaunchFlagDebug)) { 365348fb385STodd Fiala // Resume past the stop for the final exec into the true inferior. 366348fb385STodd Fiala ++resume_count; 367348fb385STodd Fiala } 368015d818bSTodd Fiala 369348fb385STodd Fiala // If we're not launching a shell, we're done. 37010687b0eSZachary Turner const FileSpec &shell = launch_info.GetShell(); 37110687b0eSZachary Turner if (!shell) 372348fb385STodd Fiala return resume_count; 373348fb385STodd Fiala 37410687b0eSZachary Turner std::string shell_string = shell.GetPath(); 375348fb385STodd Fiala // We're in a shell, so for sure we have to resume past the shell exec. 376348fb385STodd Fiala ++resume_count; 377348fb385STodd Fiala 378348fb385STodd Fiala // Figure out what shell we're planning on using. 37910687b0eSZachary Turner const char *shell_name = strrchr(shell_string.c_str(), '/'); 380348fb385STodd Fiala if (shell_name == NULL) 38110687b0eSZachary Turner shell_name = shell_string.c_str(); 38228041352SGreg Clayton else 383348fb385STodd Fiala shell_name++; 384348fb385STodd Fiala 385b9c1b51eSKate Stone if (strcmp(shell_name, "csh") == 0 || strcmp(shell_name, "tcsh") == 0 || 386b9c1b51eSKate Stone strcmp(shell_name, "zsh") == 0 || strcmp(shell_name, "sh") == 0) { 387348fb385STodd Fiala // These shells seem to re-exec themselves. Add another resume. 388348fb385STodd Fiala ++resume_count; 389ecc11474SStephen Wilson } 39013e8e1c3SJohnny Chen 391348fb385STodd Fiala return resume_count; 392348fb385STodd Fiala } 393348fb385STodd Fiala 394b9c1b51eSKate Stone bool PlatformLinux::CanDebugProcess() { 395b9c1b51eSKate Stone if (IsHost()) { 396b36f9178SPavel Labath return true; 397b9c1b51eSKate Stone } else { 398015d818bSTodd Fiala // If we're connected, we can debug. 399015d818bSTodd Fiala return IsConnected(); 400015d818bSTodd Fiala } 401348fb385STodd Fiala } 402015d818bSTodd Fiala 403b9c1b51eSKate Stone // For local debugging, Linux will override the debug logic to use llgs-launch 404b9c1b51eSKate Stone // rather than 405b9c1b51eSKate Stone // lldb-launch, llgs-attach. This differs from current lldb-launch, 406b9c1b51eSKate Stone // debugserver-attach 407348fb385STodd Fiala // approach on MacOSX. 40813e8e1c3SJohnny Chen lldb::ProcessSP 409b9c1b51eSKate Stone PlatformLinux::DebugProcess(ProcessLaunchInfo &launch_info, Debugger &debugger, 410b9c1b51eSKate Stone Target *target, // Can be NULL, if NULL create a new 411b9c1b51eSKate Stone // target, else use existing one 412b9c1b51eSKate Stone Error &error) { 413db264a6dSTamas Berghammer Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM)); 414348fb385STodd Fiala if (log) 415b9c1b51eSKate Stone log->Printf("PlatformLinux::%s entered (target %p)", __FUNCTION__, 416b9c1b51eSKate Stone static_cast<void *>(target)); 41728041352SGreg Clayton 418348fb385STodd Fiala // If we're a remote host, use standard behavior from parent class. 419348fb385STodd Fiala if (!IsHost()) 4208012cadbSGreg Clayton return PlatformPOSIX::DebugProcess(launch_info, debugger, target, error); 421348fb385STodd Fiala 422348fb385STodd Fiala // 423b9c1b51eSKate Stone // For local debugging, we'll insist on having ProcessGDBRemote create the 424b9c1b51eSKate Stone // process. 425348fb385STodd Fiala // 426348fb385STodd Fiala 427348fb385STodd Fiala ProcessSP process_sp; 428348fb385STodd Fiala 429348fb385STodd Fiala // Make sure we stop at the entry point 430348fb385STodd Fiala launch_info.GetFlags().Set(eLaunchFlagDebug); 431348fb385STodd Fiala 432348fb385STodd Fiala // We always launch the process we are going to debug in a separate process 433348fb385STodd Fiala // group, since then we can handle ^C interrupts ourselves w/o having to worry 434348fb385STodd Fiala // about the target getting them as well. 435348fb385STodd Fiala launch_info.SetLaunchInSeparateProcessGroup(true); 436348fb385STodd Fiala 437348fb385STodd Fiala // Ensure we have a target. 438b9c1b51eSKate Stone if (target == nullptr) { 439348fb385STodd Fiala if (log) 440348fb385STodd Fiala log->Printf("PlatformLinux::%s creating new target", __FUNCTION__); 441348fb385STodd Fiala 442348fb385STodd Fiala TargetSP new_target_sp; 443a47464b2SZachary Turner error = debugger.GetTargetList().CreateTarget(debugger, "", "", false, 444a47464b2SZachary Turner nullptr, new_target_sp); 445b9c1b51eSKate Stone if (error.Fail()) { 446348fb385STodd Fiala if (log) 447b9c1b51eSKate Stone log->Printf("PlatformLinux::%s failed to create new target: %s", 448b9c1b51eSKate Stone __FUNCTION__, error.AsCString()); 449348fb385STodd Fiala return process_sp; 450348fb385STodd Fiala } 451348fb385STodd Fiala 45228041352SGreg Clayton target = new_target_sp.get(); 453b9c1b51eSKate Stone if (!target) { 454348fb385STodd Fiala error.SetErrorString("CreateTarget() returned nullptr"); 455348fb385STodd Fiala if (log) 456b9c1b51eSKate Stone log->Printf("PlatformLinux::%s failed: %s", __FUNCTION__, 457b9c1b51eSKate Stone error.AsCString()); 458348fb385STodd Fiala return process_sp; 459348fb385STodd Fiala } 460b9c1b51eSKate Stone } else { 461348fb385STodd Fiala if (log) 462348fb385STodd Fiala log->Printf("PlatformLinux::%s using provided target", __FUNCTION__); 463348fb385STodd Fiala } 464348fb385STodd Fiala 465348fb385STodd Fiala // Mark target as currently selected target. 46628041352SGreg Clayton debugger.GetTargetList().SetSelectedTarget(target); 46728041352SGreg Clayton 468348fb385STodd Fiala // Now create the gdb-remote process. 469348fb385STodd Fiala if (log) 470b9c1b51eSKate Stone log->Printf( 471b9c1b51eSKate Stone "PlatformLinux::%s having target create process with gdb-remote plugin", 472b9c1b51eSKate Stone __FUNCTION__); 473b9c1b51eSKate Stone process_sp = target->CreateProcess( 474b9c1b51eSKate Stone launch_info.GetListenerForProcess(debugger), "gdb-remote", nullptr); 47528041352SGreg Clayton 476b9c1b51eSKate Stone if (!process_sp) { 477348fb385STodd Fiala error.SetErrorString("CreateProcess() failed for gdb-remote process"); 478348fb385STodd Fiala if (log) 479b9c1b51eSKate Stone log->Printf("PlatformLinux::%s failed: %s", __FUNCTION__, 480b9c1b51eSKate Stone error.AsCString()); 481348fb385STodd Fiala return process_sp; 482b9c1b51eSKate Stone } else { 483348fb385STodd Fiala if (log) 484b9c1b51eSKate Stone log->Printf("PlatformLinux::%s successfully created process", 485b9c1b51eSKate Stone __FUNCTION__); 486348fb385STodd Fiala } 487348fb385STodd Fiala 488348fb385STodd Fiala // Adjust launch for a hijacker. 489348fb385STodd Fiala ListenerSP listener_sp; 490b9c1b51eSKate Stone if (!launch_info.GetHijackListener()) { 491348fb385STodd Fiala if (log) 492348fb385STodd Fiala log->Printf("PlatformLinux::%s setting up hijacker", __FUNCTION__); 493348fb385STodd Fiala 494b9c1b51eSKate Stone listener_sp = 495b9c1b51eSKate Stone Listener::MakeListener("lldb.PlatformLinux.DebugProcess.hijack"); 496348fb385STodd Fiala launch_info.SetHijackListener(listener_sp); 497583bbb1dSJim Ingham process_sp->HijackProcessEvents(listener_sp); 498348fb385STodd Fiala } 499348fb385STodd Fiala 500348fb385STodd Fiala // Log file actions. 501b9c1b51eSKate Stone if (log) { 502b9c1b51eSKate Stone log->Printf( 503b9c1b51eSKate Stone "PlatformLinux::%s launching process with the following file actions:", 504b9c1b51eSKate Stone __FUNCTION__); 505348fb385STodd Fiala 506348fb385STodd Fiala StreamString stream; 507348fb385STodd Fiala size_t i = 0; 508348fb385STodd Fiala const FileAction *file_action; 509b9c1b51eSKate Stone while ((file_action = launch_info.GetFileActionAtIndex(i++)) != nullptr) { 510348fb385STodd Fiala file_action->Dump(stream); 511c156427dSZachary Turner log->PutCString(stream.GetData()); 512348fb385STodd Fiala stream.Clear(); 513348fb385STodd Fiala } 514348fb385STodd Fiala } 515348fb385STodd Fiala 516348fb385STodd Fiala // Do the launch. 517348fb385STodd Fiala error = process_sp->Launch(launch_info); 518b9c1b51eSKate Stone if (error.Success()) { 519348fb385STodd Fiala // Handle the hijacking of process events. 520b9c1b51eSKate Stone if (listener_sp) { 521b9c1b51eSKate Stone const StateType state = process_sp->WaitForProcessToStop( 522e3e21cfcSPavel Labath llvm::None, NULL, false, listener_sp); 523348fb385STodd Fiala 524b9c1b51eSKate Stone if (state == eStateStopped) { 525348fb385STodd Fiala if (log) 526348fb385STodd Fiala log->Printf("PlatformLinux::%s pid %" PRIu64 " state %s\n", 527348fb385STodd Fiala __FUNCTION__, process_sp->GetID(), StateAsCString(state)); 528b9c1b51eSKate Stone } else { 529348fb385STodd Fiala if (log) 530b9c1b51eSKate Stone log->Printf("PlatformLinux::%s pid %" PRIu64 531b9c1b51eSKate Stone " state is not stopped - %s\n", 532348fb385STodd Fiala __FUNCTION__, process_sp->GetID(), StateAsCString(state)); 533348fb385STodd Fiala } 534348fb385STodd Fiala } 535348fb385STodd Fiala 536b9c1b51eSKate Stone // Hook up process PTY if we have one (which we should for local debugging 537b9c1b51eSKate Stone // with llgs). 538348fb385STodd Fiala int pty_fd = launch_info.GetPTY().ReleaseMasterFileDescriptor(); 539b9c1b51eSKate Stone if (pty_fd != lldb_utility::PseudoTerminal::invalid_fd) { 540348fb385STodd Fiala process_sp->SetSTDIOFileDescriptor(pty_fd); 541348fb385STodd Fiala if (log) 542b9c1b51eSKate Stone log->Printf("PlatformLinux::%s pid %" PRIu64 543b9c1b51eSKate Stone " hooked up STDIO pty to process", 544b9c1b51eSKate Stone __FUNCTION__, process_sp->GetID()); 545b9c1b51eSKate Stone } else { 546348fb385STodd Fiala if (log) 547b9c1b51eSKate Stone log->Printf("PlatformLinux::%s pid %" PRIu64 548b9c1b51eSKate Stone " not using process STDIO pty", 549b9c1b51eSKate Stone __FUNCTION__, process_sp->GetID()); 55028041352SGreg Clayton } 551b9c1b51eSKate Stone } else { 552348fb385STodd Fiala if (log) 553b9c1b51eSKate Stone log->Printf("PlatformLinux::%s process launch failed: %s", __FUNCTION__, 554b9c1b51eSKate Stone error.AsCString()); 555b9c1b51eSKate Stone // FIXME figure out appropriate cleanup here. Do we delete the target? Do 556b9c1b51eSKate Stone // we delete the process? Does our caller do that? 55728041352SGreg Clayton } 558348fb385STodd Fiala 55928041352SGreg Clayton return process_sp; 56013e8e1c3SJohnny Chen } 5612094dbf4SJason Molenda 562b9c1b51eSKate Stone void PlatformLinux::CalculateTrapHandlerSymbolNames() { 5632094dbf4SJason Molenda m_trap_handlers.push_back(ConstString("_sigtramp")); 5642094dbf4SJason Molenda } 565af245d11STodd Fiala 566b9c1b51eSKate Stone uint64_t PlatformLinux::ConvertMmapFlagsToPlatform(const ArchSpec &arch, 567b9c1b51eSKate Stone unsigned flags) { 56896ad3de5SRobert Flack uint64_t flags_platform = 0; 569e0d8c422SMohit K. Bhakkad uint64_t map_anon = MAP_ANON; 570e0d8c422SMohit K. Bhakkad 571e0d8c422SMohit K. Bhakkad // To get correct flags for MIPS Architecture 572b9c1b51eSKate Stone if (arch.GetTriple().getArch() == llvm::Triple::mips64 || 573b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::mips64el || 574b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::mips || 575b9c1b51eSKate Stone arch.GetTriple().getArch() == llvm::Triple::mipsel) 576e0d8c422SMohit K. Bhakkad map_anon = 0x800; 577e0d8c422SMohit K. Bhakkad 57896ad3de5SRobert Flack if (flags & eMmapFlagsPrivate) 57996ad3de5SRobert Flack flags_platform |= MAP_PRIVATE; 58096ad3de5SRobert Flack if (flags & eMmapFlagsAnon) 581e0d8c422SMohit K. Bhakkad flags_platform |= map_anon; 58296ad3de5SRobert Flack return flags_platform; 58396ad3de5SRobert Flack } 5846e25aeeaSEnrico Granata 585b9c1b51eSKate Stone ConstString PlatformLinux::GetFullNameForDylib(ConstString basename) { 5866e25aeeaSEnrico Granata if (basename.IsEmpty()) 5876e25aeeaSEnrico Granata return basename; 5886e25aeeaSEnrico Granata 5896e25aeeaSEnrico Granata StreamString stream; 5906e25aeeaSEnrico Granata stream.Printf("lib%s.so", basename.GetCString()); 591c156427dSZachary Turner return ConstString(stream.GetString()); 5926e25aeeaSEnrico Granata } 593