From 2289fa48209997bbda285c8ba2f25fa0f4eac39f Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Sat, 30 Apr 2011 01:09:13 +0000 Subject: [PATCH] Added the ability to set the Platform path for a module through the SBModule interface. Added a quick way to set the platform though the SBDebugger interface. I will actually an a SBPlatform support soon, but for now this will do. ConnectionFileDescriptor can be passed a url formatted as: "fd://" where is a file descriptor in the current process. This is handy if you have services, deamons, or other tools that can spawn processes and give you a file handle. llvm-svn: 130565 --- lldb/include/lldb/API/SBDebugger.h | 5 + lldb/include/lldb/API/SBModule.h | 6 + lldb/lldb.xcodeproj/project.pbxproj | 4 + lldb/source/API/SBDebugger.cpp | 20 +++ lldb/source/API/SBModule.cpp | 46 ++++++ lldb/source/API/SBTarget.cpp | 156 ++++++------------ lldb/source/Core/ConnectionFileDescriptor.cpp | 40 +++++ .../Process/gdb-remote/ProcessGDBRemote.cpp | 9 +- lldb/source/Target/Process.cpp | 10 +- 9 files changed, 180 insertions(+), 116 deletions(-) diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 75e7d25b0a08..a1dd5834c6ca 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -116,6 +116,11 @@ public: lldb::SBSourceManager & GetSourceManager (); + + // REMOVE: just for a quick fix, need to expose platforms through + // SBPlatform from this class. + lldb::SBError + SetCurrentPlatform (const char *platform_name); // FIXME: Once we get the set show stuff in place, the driver won't need // an interface to the Set/Get UseExternalEditor. diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h index 280dd31693d3..4b6f82259d7c 100644 --- a/lldb/include/lldb/API/SBModule.h +++ b/lldb/include/lldb/API/SBModule.h @@ -36,6 +36,12 @@ public: lldb::SBFileSpec GetFileSpec () const; + lldb::SBFileSpec + GetPlatformFileSpec () const; + + bool + SetPlatformFileSpec (const lldb::SBFileSpec &platform_file); + const uint8_t * GetUUIDBytes () const; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 3c93e5aabb4e..9932d37019c4 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -385,6 +385,8 @@ 26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BD407E135D2ADF00237D80 /* FileLineResolver.cpp */; }; 26C72C94124322890068DC16 /* SBStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 26C72C93124322890068DC16 /* SBStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26C72C961243229A0068DC16 /* SBStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C72C951243229A0068DC16 /* SBStream.cpp */; }; + 26D265A2136B40EE002EEE45 /* SharingPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 261B5A5311C3F2AD00AABD0A /* SharingPtr.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 26D265BC136B4269002EEE45 /* lldb-public.h in Headers */ = {isa = PBXBuildFile; fileRef = 26651A14133BEC76005B64B7 /* lldb-public.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26D5E15F135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D5E15E135BAEA2006EA0A7 /* OptionGroupArchitecture.cpp */; }; 26D5E163135BB054006EA0A7 /* OptionGroupPlatform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D5E162135BB054006EA0A7 /* OptionGroupPlatform.cpp */; }; 26DC6A171337FE8000FF7998 /* liblldb-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2689FFCA13353D7A00698AC0 /* liblldb-core.a */; }; @@ -2639,6 +2641,8 @@ 2617447A11685869005ADD65 /* SBType.h in Headers */, 9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */, 9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */, + 26D265A2136B40EE002EEE45 /* SharingPtr.h in Headers */, + 26D265BC136B4269002EEE45 /* lldb-public.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp index 700098e2f4e0..84b13ab641e9 100644 --- a/lldb/source/API/SBDebugger.cpp +++ b/lldb/source/API/SBDebugger.cpp @@ -15,6 +15,7 @@ #include "lldb/API/SBBroadcaster.h" #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBCommandReturnObject.h" +#include "lldb/API/SBError.h" #include "lldb/API/SBEvent.h" #include "lldb/API/SBFrame.h" #include "lldb/API/SBInputReader.h" @@ -811,3 +812,22 @@ SBDebugger::GetID() return m_opaque_sp->GetID(); return LLDB_INVALID_UID; } + + +SBError +SBDebugger::SetCurrentPlatform (const char *platform_name) +{ + SBError sb_error; + if (m_opaque_sp) + { + PlatformSP platform_sp (Platform::Create (platform_name, sb_error.ref())); + + if (platform_sp) + { + bool make_selected = true; + m_opaque_sp->GetPlatformList().Append (platform_sp, make_selected); + } + } + return sb_error; +} + diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index e7e95be1e8bd..427850ec46c2 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -71,6 +71,52 @@ SBModule::GetFileSpec () const return file_spec; } +lldb::SBFileSpec +SBModule::GetPlatformFileSpec () const +{ + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + SBFileSpec file_spec; + if (m_opaque_sp) + file_spec.SetFileSpec(m_opaque_sp->GetPlatformFileSpec()); + + if (log) + { + log->Printf ("SBModule(%p)::GetPlatformFileSpec () => SBFileSpec(%p)", + m_opaque_sp.get(), file_spec.get()); + } + + return file_spec; + +} + +bool +SBModule::SetPlatformFileSpec (const lldb::SBFileSpec &platform_file) +{ + bool result = false; + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); + + if (m_opaque_sp) + { + m_opaque_sp->SetPlatformFileSpec(*platform_file); + result = true; + } + + if (log) + { + log->Printf ("SBModule(%p)::SetPlatformFileSpec (SBFileSpec(%p (%s%s%s)) => %i", + m_opaque_sp.get(), + platform_file.get(), + platform_file->GetDirectory().GetCString(), + platform_file->GetDirectory() ? "/" : "", + platform_file->GetFilename().GetCString(), + result); + } + return result; +} + + + const uint8_t * SBModule::GetUUIDBytes () const { diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 551a49680e1f..ab70e6c0af28 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -183,126 +183,74 @@ SBTarget::Launch if (getenv("LLDB_LAUNCH_FLAG_DISABLE_ASLR")) launch_flags |= eLaunchFlagDisableASLR; - static const char *g_launch_tty = NULL; - static bool g_got_launch_tty = false; - if (!g_got_launch_tty) + StateType state = eStateInvalid; + sb_process.SetProcess (m_opaque_sp->GetProcessSP()); + if (sb_process.IsValid()) { - // Get the LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY only once - g_got_launch_tty = true; - g_launch_tty = ::getenv ("LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY"); - if (g_launch_tty) - { - // LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY is a path to a terminal to reuse - // if the first character is '/', else it is a boolean value. - if (g_launch_tty[0] != '/') - { - if (Args::StringToBoolean(g_launch_tty, false, NULL)) - g_launch_tty = ""; - else - g_launch_tty = NULL; - } - } + state = sb_process->GetState(); + + if (sb_process->IsAlive() && state != eStateConnected) + { + if (state == eStateAttaching) + error.SetErrorString ("process attach is in progress"); + else + error.SetErrorString ("a process is already being debugged"); + sb_process.Clear(); + return sb_process; + } } -// if ((launch_flags & eLaunchFlagLaunchInTTY) || g_launch_tty) -// { -// ArchSpec arch (m_opaque_sp->GetArchitecture ()); -// -// Module *exe_module = m_opaque_sp->GetExecutableModule().get(); -// if (exe_module) -// { -// char exec_file_path[PATH_MAX]; -// exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)); -// if (exe_module->GetFileSpec().Exists()) -// { -// // Make a new argument vector -// std::vector exec_path_plus_argv; -// // Append the resolved executable path -// exec_path_plus_argv.push_back (exec_file_path); -// -// // Push all args if there are any -// if (argv) -// { -// for (int i = 0; argv[i]; ++i) -// exec_path_plus_argv.push_back(argv[i]); -// } -// -// // Push a NULL to terminate the args. -// exec_path_plus_argv.push_back(NULL); -// -// -// const char *tty_name = NULL; -// if (g_launch_tty && g_launch_tty[0] == '/') -// tty_name = g_launch_tty; -// -// lldb::pid_t pid = Host::LaunchInNewTerminal (tty_name, -// &exec_path_plus_argv[0], -// envp, -// working_directory, -// &arch, -// true, -// launch_flags & eLaunchFlagDisableASLR); -// -// if (pid != LLDB_INVALID_PROCESS_ID) -// { -// sb_process = AttachToProcessWithID(listener, pid, error); -// } -// else -// { -// error.SetErrorStringWithFormat("failed to launch process in terminal"); -// } -// } -// else -// { -// error.SetErrorStringWithFormat("executable doesn't exist: \"%s\"", exec_file_path); -// } -// } -// else -// { -// error.SetErrorStringWithFormat("invalid executable"); -// } -// } -// else + if (state == eStateConnected) + { + // If we are already connected, then we have already specified the + // listener, so if a valid listener is supplied, we need to error out + // to let the client know. + if (listener.IsValid()) + { + error.SetErrorString ("process is connected and already has a listener, pass empty listener"); + sb_process.Clear(); + return sb_process; + } + } + else { if (listener.IsValid()) sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref())); else sb_process.SetProcess (m_opaque_sp->CreateProcess (m_opaque_sp->GetDebugger().GetListener())); + } - if (sb_process.IsValid()) + if (sb_process.IsValid()) + { + if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO")) + launch_flags |= eLaunchFlagDisableSTDIO; + + error.SetError (sb_process->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory)); + if (error.Success()) { - - if (getenv("LLDB_LAUNCH_FLAG_DISABLE_STDIO")) - launch_flags |= eLaunchFlagDisableSTDIO; + // We we are stopping at the entry point, we can return now! + if (stop_at_entry) + return sb_process; - - error.SetError (sb_process->Launch (argv, envp, launch_flags, stdin_path, stdout_path, stderr_path, working_directory)); - if (error.Success()) + // Make sure we are stopped at the entry + StateType state = sb_process->WaitForProcessToStop (NULL); + if (state == eStateStopped) { - // We we are stopping at the entry point, we can return now! - if (stop_at_entry) - return sb_process; - - // Make sure we are stopped at the entry - StateType state = sb_process->WaitForProcessToStop (NULL); - if (state == eStateStopped) + // resume the process to skip the entry point + error.SetError (sb_process->Resume()); + if (error.Success()) { - // resume the process to skip the entry point - error.SetError (sb_process->Resume()); - if (error.Success()) - { - // If we are doing synchronous mode, then wait for the - // process to stop yet again! - if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false) - sb_process->WaitForProcessToStop (NULL); - } + // If we are doing synchronous mode, then wait for the + // process to stop yet again! + if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false) + sb_process->WaitForProcessToStop (NULL); } } } - else - { - error.SetErrorString ("unable to create lldb_private::Process"); - } + } + else + { + error.SetErrorString ("unable to create lldb_private::Process"); } } else diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp index ce306c90e4d7..2a9b16b7d639 100644 --- a/lldb/source/Core/ConnectionFileDescriptor.cpp +++ b/lldb/source/Core/ConnectionFileDescriptor.cpp @@ -97,6 +97,46 @@ ConnectionFileDescriptor::Connect (const char *s, Error *error_ptr) { return SocketConnect (s + strlen("connect://"), error_ptr); } + else if (strstr(s, "fd://")) + { + // Just passing a native file descriptor within this current process + // that is already opened (possibly from a service or other source). + s += strlen ("fd://"); + bool success = false; + m_fd = Args::StringToSInt32 (s, -1, 0, &success); + if (success) + { + // We have what looks to be a valid file descriptor, but we + // should make it is. We currently are doing this by trying to + // get the flags from the file descriptor and making sure it + // isn't a bad fd. We also need to enable non blocking mode for + // the fd if it already isn't. + errno = 0; + int flags = ::fcntl (m_fd, F_GETFL, 0); + if (flags == -1 || errno == EBADF) + { + if (error_ptr) + error_ptr->SetErrorStringWithFormat ("stale file descriptor: %s", s); + m_fd = -1; + return eConnectionStatusError; + } + else + { + if ((flags & O_NONBLOCK) == 0) + { + flags |= O_NONBLOCK; + ::fcntl (m_fd, F_SETFL, flags); + } + m_should_close_fd = true; + return eConnectionStatusSuccess; + } + } + + if (error_ptr) + error_ptr->SetErrorStringWithFormat ("invalid file descriptor: \"fd://%s\"", s); + m_fd = -1; + return eConnectionStatusError; + } else if (strstr(s, "file://")) { // file:///PATH diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 79f77e219d1f..afd6af6a5c2b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -352,14 +352,7 @@ ProcessGDBRemote::DoConnectRemote (const char *remote_url) if (error.Fail()) return error; - if (strncmp (remote_url, "connect://", strlen ("connect://")) == 0) - { - error = ConnectToDebugserver (remote_url); - } - else - { - error.SetErrorStringWithFormat ("unsupported remote url: %s", remote_url); - } + error = ConnectToDebugserver (remote_url); if (error.Fail()) return error; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 5ad5ac22445c..8e96c716e74f 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -2065,8 +2065,10 @@ Process::Launch Module *exe_module = m_target.GetExecutableModule().get(); if (exe_module) { - char exec_file_path[PATH_MAX]; - exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)); + char local_exec_file_path[PATH_MAX]; + char platform_exec_file_path[PATH_MAX]; + exe_module->GetFileSpec().GetPath(local_exec_file_path, sizeof(local_exec_file_path)); + exe_module->GetPlatformFileSpec().GetPath(platform_exec_file_path, sizeof(platform_exec_file_path)); if (exe_module->GetFileSpec().Exists()) { if (PrivateStateThreadIsValid ()) @@ -2089,7 +2091,7 @@ Process::Launch // Make a new argument vector std::vector exec_path_plus_argv; // Append the resolved executable path - exec_path_plus_argv.push_back (exec_file_path); + exec_path_plus_argv.push_back (platform_exec_file_path); // Push all args if there are any if (argv) @@ -2156,7 +2158,7 @@ Process::Launch } else { - error.SetErrorStringWithFormat("File doesn't exist: '%s'.\n", exec_file_path); + error.SetErrorStringWithFormat("File doesn't exist: '%s'.\n", local_exec_file_path); } } return error;