diff options
20 files changed, 558 insertions, 369 deletions
diff --git a/lldb/include/lldb/Interpreter/Args.h b/lldb/include/lldb/Interpreter/Args.h index 580ebafba8f..a5b66ac387c 100644 --- a/lldb/include/lldb/Interpreter/Args.h +++ b/lldb/include/lldb/Interpreter/Args.h @@ -401,6 +401,9 @@ public: static const char * StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t &update); + static const char * + GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg); + // This one isn't really relevant to Arguments per se, but we're using the Args as a // general strings container, so... void diff --git a/lldb/include/lldb/Interpreter/CommandReturnObject.h b/lldb/include/lldb/Interpreter/CommandReturnObject.h index 8b44cb7ea18..ce062d38845 100644 --- a/lldb/include/lldb/Interpreter/CommandReturnObject.h +++ b/lldb/include/lldb/Interpreter/CommandReturnObject.h @@ -141,6 +141,10 @@ public: void AppendErrorWithFormat (const char *format, ...) __attribute__ ((format (printf, 2, 3))); + void + SetError (const Error &error, + const char *fallback_error_cstr); + lldb::ReturnStatus GetStatus(); diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 9d2e6ca2acb..76659b69914 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -305,7 +305,7 @@ namespace lldb_private { /// appriopriate error fill into the \a error object. //------------------------------------------------------------------ virtual lldb::ProcessSP - Attach (lldb::pid_t pid, + Attach (ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one Listener &listener, diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index e002932750a..95a41f45bc0 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -148,12 +148,6 @@ public: return m_executable.GetFilename().GetLength(); } - void - SetName (const char *name) - { - m_executable.GetFilename().SetCString (name); - } - FileSpec & GetExecutableFile () { @@ -591,7 +585,7 @@ public: } void - FinalizeFileActions (Target *target, Process *process); + FinalizeFileActions (Target *target); size_t GetNumFileActions () const @@ -671,21 +665,158 @@ public: m_plugin_name.clear(); } + const char * + GetShell () const + { + if (m_shell.empty()) + return NULL; + return m_shell.c_str(); + } + + void + SetShell (const char * path) + { + if (path && path[0]) + { + m_shell.assign (path); + m_flags.Set (lldb::eLaunchFlagLaunchInShell); + } + else + { + m_shell.clear(); + m_flags.Clear (lldb::eLaunchFlagLaunchInShell); + } + } + + uint32_t + GetResumeCount () const + { + return m_resume_count; + } + + void + SetResumeCount (uint32_t c) + { + m_resume_count = c; + } + void Clear () { ProcessInfo::Clear(); m_working_dir.clear(); m_plugin_name.clear(); + m_shell.clear(); m_flags.Clear(); m_file_actions.clear(); + m_resume_count = 0; } + bool + ConvertArgumentsForLaunchingInShell (Error &error, bool localhost); + protected: std::string m_working_dir; std::string m_plugin_name; + std::string m_shell; Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags std::vector<FileAction> m_file_actions; // File actions for any other files + uint32_t m_resume_count; // How many times do we resume after launching +}; + +//---------------------------------------------------------------------- +// ProcessLaunchInfo +// +// Describes any information that is required to launch a process. +//---------------------------------------------------------------------- + +class ProcessAttachInfo : public ProcessInstanceInfo +{ +public: + ProcessAttachInfo() : + ProcessInstanceInfo(), + m_plugin_name (), + m_resume_count (0), + m_wait_for_launch (false) + { + } + + ProcessAttachInfo (const ProcessLaunchInfo &launch_info) : + ProcessInstanceInfo(), + m_plugin_name (), + m_resume_count (0), + m_wait_for_launch (false) + { + ProcessInfo::operator= (launch_info); + SetProcessPluginName (launch_info.GetProcessPluginName()); + SetResumeCount (launch_info.GetResumeCount()); + } + + bool + GetWaitForLaunch () const + { + return m_wait_for_launch; + } + + void + SetWaitForLaunch (bool b) + { + m_wait_for_launch = b; + } + + uint32_t + GetResumeCount () const + { + return m_resume_count; + } + + void + SetResumeCount (uint32_t c) + { + m_resume_count = c; + } + + const char * + GetProcessPluginName () const + { + if (m_plugin_name.empty()) + return NULL; + return m_plugin_name.c_str(); + } + + void + SetProcessPluginName (const char *plugin) + { + if (plugin && plugin[0]) + m_plugin_name.assign (plugin); + else + m_plugin_name.clear(); + } + + void + Clear () + { + ProcessInstanceInfo::Clear(); + m_plugin_name.clear(); + m_resume_count = 0; + m_wait_for_launch = false; + } + + bool + ProcessInfoSpecified () const + { + if (GetExecutableFile()) + return true; + if (GetProcessID() != LLDB_INVALID_PROCESS_ID) + return true; + if (GetParentProcessID() != LLDB_INVALID_PROCESS_ID) + return true; + return false; + } +protected: + std::string m_plugin_name; + uint32_t m_resume_count; // How many times do we resume after launching + bool m_wait_for_launch; }; class ProcessLaunchCommandOptions : public Options @@ -744,12 +875,12 @@ public: } ProcessInstanceInfoMatch (const char *process_name, - lldb_private::NameMatchType process_name_match_type) : + lldb_private::NameMatchType process_name_match_type) : m_match_info (), m_name_match_type (process_name_match_type), m_match_all_users (false) { - m_match_info.SetName (process_name); + m_match_info.GetExecutableFile().SetFile(process_name, false); } ProcessInstanceInfo & @@ -1316,11 +1447,12 @@ public: Launch (const ProcessLaunchInfo &launch_info); //------------------------------------------------------------------ - /// Attach to an existing process using a process ID. + /// Attach to an existing process using the process attach info. /// /// This function is not meant to be overridden by Process - /// subclasses. It will first call Process::WillAttach (lldb::pid_t) - /// and if that returns \b true, Process::DoAttach (lldb::pid_t) will + /// subclasses. It will first call WillAttach (lldb::pid_t) + /// or WillAttach (const char *), and if that returns \b + /// true, DoAttach (lldb::pid_t) or DoAttach (const char *) will /// be called to actually do the attach. If DoAttach returns \b /// true, then Process::DidAttach() will be called. /// @@ -1332,28 +1464,8 @@ public: /// LLDB_INVALID_PROCESS_ID if attaching fails. //------------------------------------------------------------------ virtual Error - Attach (lldb::pid_t pid, uint32_t exec_count); + Attach (ProcessAttachInfo &attach_info); - //------------------------------------------------------------------ - /// Attach to an existing process by process name. - /// - /// This function is not meant to be overridden by Process - /// subclasses. It will first call - /// Process::WillAttach (const char *) and if that returns \b - /// true, Process::DoAttach (const char *) will be called to - /// actually do the attach. If DoAttach returns \b true, then - /// Process::DidAttach() will be called. - /// - /// @param[in] process_name - /// A process name to match against the current process list. - /// - /// @return - /// Returns \a pid if attaching was successful, or - /// LLDB_INVALID_PROCESS_ID if attaching fails. - //------------------------------------------------------------------ - virtual Error - Attach (const char *process_name, bool wait_for_launch); - virtual Error ConnectRemote (const char *remote_url); diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index fb23b43e4e8..c75f75fe02d 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -112,6 +112,7 @@ class NamedOption; class PathMappingList; class Platform; class Process; +class ProcessAttachInfo; class ProcessModID; class ProcessInfo; class ProcessInstanceInfo; @@ -128,7 +129,7 @@ class ScriptInterpreter; #ifndef LLDB_DISABLE_PYTHON class ScriptInterpreterPython; struct ScriptSummaryFormat; -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif class SearchFilter; class Section; class SectionImpl; @@ -161,7 +162,7 @@ class SyntheticChildren; class SyntheticChildrenFrontEnd; #ifndef LLDB_DISABLE_PYTHON class SyntheticScriptProvider; -#endif // #ifndef LLDB_DISABLE_PYTHON +#endif class Target; class TargetList; class Thread; diff --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp index 66abd086c40..5a98c9f96d6 100644 --- a/lldb/source/API/SBProcess.cpp +++ b/lldb/source/API/SBProcess.cpp @@ -169,7 +169,9 @@ SBProcess::RemoteAttachToProcessWithID (lldb::pid_t pid, lldb::SBError& error) Mutex::Locker api_locker (m_opaque_sp->GetTarget().GetAPIMutex()); if (m_opaque_sp->GetState() == eStateConnected) { - error.SetError (m_opaque_sp->Attach (pid, 0)); + ProcessAttachInfo attach_info; + attach_info.SetProcessID (pid); + error.SetError (m_opaque_sp->Attach (attach_info)); } else { diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 58d89b197ae..c393635c3c6 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -337,7 +337,9 @@ SBTarget::AttachToProcessWithID if (sb_process.IsValid()) { - error.SetError (sb_process->Attach (pid, 0)); + ProcessAttachInfo attach_info; + attach_info.SetProcessID (pid); + error.SetError (sb_process->Attach (attach_info)); // If we are doing synchronous mode, then wait for the // process to stop! if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false) @@ -409,7 +411,10 @@ SBTarget::AttachToProcessWithName if (sb_process.IsValid()) { - error.SetError (sb_process->Attach (name, wait_for)); + ProcessAttachInfo attach_info; + attach_info.GetExecutableFile().SetFile(name, false); + attach_info.SetWaitForLaunch(wait_for); + error.SetError (sb_process->Attach (attach_info)); // If we are doing synchronous mode, then wait for the // process to stop! if (m_opaque_sp->GetDebugger().GetAsyncExecution () == false) diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index e2136d32cac..c9f776ed7ee 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -653,27 +653,27 @@ protected: break; case 'n': - match_info.GetProcessInfo().SetName (option_arg); + match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); match_info.SetNameMatchType (eNameMatchEquals); break; case 'e': - match_info.GetProcessInfo().SetName (option_arg); + match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); match_info.SetNameMatchType (eNameMatchEndsWith); break; case 's': - match_info.GetProcessInfo().SetName (option_arg); + match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); match_info.SetNameMatchType (eNameMatchStartsWith); break; case 'c': - match_info.GetProcessInfo().SetName (option_arg); + match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); match_info.SetNameMatchType (eNameMatchContains); break; case 'r': - match_info.GetProcessInfo().SetName (option_arg); + match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false); match_info.SetNameMatchType (eNameMatchRegularExpression); break; diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index e7d392da030..e048182d04b 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -212,12 +212,32 @@ public: } } - if (launch_args.GetArgumentCount() > 0) + if (launch_args.GetArgumentCount() == 0) + { + const Args &process_args = target->GetRunArguments(); + if (process_args.GetArgumentCount() > 0) + m_options.launch_info.GetArguments().AppendArguments (process_args); + } + else { m_options.launch_info.GetArguments().AppendArguments (launch_args); } - + if (target->GetDisableASLR()) + m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); + + if (target->GetDisableSTDIO()) + m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); + + m_options.launch_info.GetFlags().Set (eLaunchFlagDebug); + + Args environment; + target->GetEnvironmentAsArgs (environment); + if (environment.GetArgumentCount() > 0) + m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); + + m_options.launch_info.FinalizeFileActions (target); + if (state == eStateConnected) { if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) @@ -228,78 +248,18 @@ public: } else { - const char *plugin_name = m_options.launch_info.GetProcessPluginName(); - - if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) - { + if (!m_options.launch_info.GetArchitecture().IsValid()) m_options.launch_info.GetArchitecture() = target->GetArchitecture(); - process = target->GetPlatform()->DebugProcess (m_options.launch_info, - debugger, - target, - debugger.GetListener(), - error).get(); - } - else - { - process = target->CreateProcess (debugger.GetListener(), plugin_name).get(); - - if (launch_args.GetArgumentCount() == 0) - { - const Args &process_args = target->GetRunArguments(); - if (process_args.GetArgumentCount() > 0) - m_options.launch_info.GetArguments().AppendArguments (process_args); - } - - Args environment; - target->GetEnvironmentAsArgs (environment); - m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); - - if (target->GetDisableASLR()) - m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); - - if (m_options.launch_info.GetNumFileActions() == 0) - { - // Only use the settings value if the user hasn't specified any options that would override it. - if (target->GetDisableSTDIO()) - m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); - - const char *path; - path = target->GetStandardErrorPath(); - if (path) - { - ProcessLaunchInfo::FileAction file_action; - const bool read = true; - const bool write = true; - if (file_action.Open(STDERR_FILENO, path, read, write)) - m_options.launch_info.AppendFileAction (file_action); - } - path = target->GetStandardInputPath(); - if (path) - { - ProcessLaunchInfo::FileAction file_action; - const bool read = true; - const bool write = false; - if (file_action.Open(STDIN_FILENO, path, read, write)) - m_options.launch_info.AppendFileAction (file_action); - } + process = target->GetPlatform()->DebugProcess (m_options.launch_info, + debugger, + target, + debugger.GetListener(), + error).get(); - path = target->GetStandardOutputPath(); - if (path) - { - ProcessLaunchInfo::FileAction file_action; - const bool read = false; - const bool write = true; - if (file_action.Open(STDOUT_FILENO, path, read, write)) - m_options.launch_info.AppendFileAction (file_action); - } - } - error = process->Launch (m_options.launch_info); - } if (process == NULL) { - result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n"); - result.SetStatus (eReturnStatusFailed); + result.SetError (error, "failed to launch or debug process"); return false; } } @@ -326,7 +286,7 @@ public: state = process->WaitForProcessToStop (NULL); if (!StateIsStoppedState(state)) { - result.AppendErrorWithFormat ("Process isn't stopped: %s", StateAsCString(state)); + result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state)); } result.SetDidChangeProcessState (true); result.SetStatus (eReturnStatusSuccessFinishResult); @@ -338,13 +298,13 @@ public: } else { - result.AppendErrorWithFormat ("Process resume at entry point failed: %s", error.AsCString()); + result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString()); result.SetStatus (eReturnStatusFailed); } } else { - result.AppendErrorWithFormat ("Initial process state wasn't stopped: %s", StateAsCString(state)); + result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state)); result.SetStatus (eReturnStatusFailed); } } @@ -423,23 +383,29 @@ public: switch (short_option) { case 'p': - pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); - if (!success || pid == LLDB_INVALID_PROCESS_ID) { - error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); + lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); + if (!success || pid == LLDB_INVALID_PROCESS_ID) + { + error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); + } + else + { + attach_info.SetProcessID (pid); + } } break; case 'P': - plugin_name = option_arg; + attach_info.SetProcessPluginName (option_arg); break; case 'n': - name.assign(option_arg); + attach_info.GetExecutableFile().SetFile(option_arg, false); break; case 'w': - waitfor = true; + attach_info.SetWaitForLaunch(true); break; default: @@ -452,9 +418,7 @@ public: void OptionParsingStarting () { - pid = LLDB_INVALID_PROCESS_ID; - name.clear(); - waitfor = false; + attach_info.Clear(); } const OptionDefinition* @@ -497,7 +461,7 @@ public: ProcessInstanceInfoMatch match_info; if (partial_name) { - match_info.GetProcessInfo().SetName(partial_name); + match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); match_info.SetNameMatchType(eNameMatchStartsWith); } platform_sp->FindProcesses (match_info, process_infos); @@ -522,10 +486,7 @@ public: // Instance variables to hold the values for command options. - lldb::pid_t pid; - std::string plugin_name; - std::string name; - bool waitfor; + ProcessAttachInfo attach_info; }; CommandObjectProcessAttach (CommandInterpreter &interpreter) : @@ -601,55 +562,37 @@ public: { if (state != eStateConnected) { - const char *plugin_name = NULL; - - if (!m_options.plugin_name.empty()) - plugin_name = m_options.plugin_name.c_str(); - + const char *plugin_name = m_options.attach_info.GetProcessPluginName(); process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); } if (process) { Error error; - int attach_pid = m_options.pid; - - const char *wait_name = NULL; - - if (m_options.name.empty()) + // If no process info was specified, then use the target executable + // name as the process to attach to by default + if (!m_options.attach_info.ProcessInfoSpecified ()) { if (old_exec_module_sp) + m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetFileSpec().GetFilename(); + + if (!m_options.attach_info.ProcessInfoSpecified ()) { - wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); + error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option"); } } - else - { - wait_name = m_options.name.c_str(); - } - - // If we are waiting for a process with this name to show up, do that first. - if (m_options.waitfor) - { - - if (wait_name == NULL) - { - result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); - result.SetStatus (eReturnStatusFailed); - return false; - } - result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name); - error = process->Attach (wait_name, m_options.waitfor); + if (error.Success()) + { + error = process->Attach (m_options.attach_info); + if (error.Success()) { result.SetStatus (eReturnStatusSuccessContinuingNoResult); } else { - result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", - wait_name, - error.AsCString()); + result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); result.SetStatus (eReturnStatusFailed); return false; } @@ -658,70 +601,11 @@ public: // FIXME: in the async case it will now be possible to get to the command // interpreter with a state eStateAttaching. Make sure we handle that correctly. StateType state = process->WaitForProcessToStop (NULL); - + result.SetDidChangeProcessState (true); result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state)); result.SetStatus (eReturnStatusSuccessFinishNoResult); } - else - { - // If the process was specified by name look it up, so we can warn if there are multiple - // processes with this pid. - - if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) - { - ProcessInstanceInfoList process_infos; - PlatformSP platform_sp (m_interpreter.GetPlatform (true)); - if (platform_sp) - { - ProcessInstanceInfoMatch match_info (wait_name, eNameMatchEquals); - platform_sp->FindProcesses (match_info, process_infos); - } - if (process_infos.GetSize() > 1) - { - result.AppendErrorWithFormat("More than one process named %s\n", wait_name); - result.SetStatus (eReturnStatusFailed); - return false; - } - else if (process_infos.GetSize() == 0) - { - result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); - result.SetStatus (eReturnStatusFailed); - return false; - } - else - { - attach_pid = process_infos.GetProcessIDAtIndex (0); - } - } - - if (attach_pid != LLDB_INVALID_PROCESS_ID) - { - error = process->Attach (attach_pid, 0); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - else - { - result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", - attach_pid, - error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - StateType state = process->WaitForProcessToStop (NULL); - - result.SetDidChangeProcessState (true); - result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state)); - result.SetStatus (eReturnStatusSuccessFinishNoResult); - } - else - { - result.AppendErrorWithFormat ("No PID specified for attach\n"); - result.SetStatus (eReturnStatusFailed); - - } - } } } diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index 048555a4e9c..529525d6ea6 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -59,6 +59,12 @@ #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 #endif +extern "C" +{ + int __pthread_chdir(const char *path); + int __pthread_fchdir (int fildes); +} + using namespace lldb; using namespace lldb_private; @@ -431,25 +437,6 @@ tell application \"Terminal\"\n\ do script the_shell_script\n\ end tell\n"; -static const char * -GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg) -{ - safe_arg.assign (unsafe_arg); - size_t prev_pos = 0; - while (prev_pos < safe_arg.size()) - { - // Escape spaces and quotes - size_t pos = safe_arg.find_first_of(" '\"", prev_pos); - if (pos != std::string::npos) - { - safe_arg.insert (pos, 1, '\\'); - prev_pos = pos + 2; - } - else - break; - } - return safe_arg.c_str(); -} static Error LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &launch_info) @@ -499,44 +486,22 @@ LaunchInNewTerminalWithAppleScript (const char *exe_path, ProcessLaunchInfo &lau if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) command.PutCString(" --disable-aslr"); - if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) + command.PutCString(" -- "); + + const char **argv = launch_info.GetArguments().GetConstArgumentVector (); + if (argv) { - const char *shell_executable = "/bin/bash"; //getenv("SHELL"); - std::string safe_arg; - if (launch_info.GetArchitecture().IsValid()) - command.Printf(" -- %s -c 'exec /usr/bin/arch -arch %s", shell_executable, launch_info.GetArchitecture().GetArchitectureName()); - else - command.Printf(" -- %s -c 'exec ", shell_executable); - const char **argv = launch_info.GetArguments().GetConstArgumentVector (); - if (argv) + for (size_t i=0; argv[i] != NULL; ++i) { - for (size_t i=0; argv[i] != NULL; ++i) - { - const char *arg = GetShellSafeArgument (i == 0 ? exe_path : argv[i], safe_arg); - command.Printf(" %s", arg); - } + if (i==0) + command.Printf(" '%s'", exe_path); + else + command.Printf(" '%s'", argv[i]); } - command.PutChar('\''); } else { - command.PutCString(" -- "); - - const char **argv = launch_info.GetArguments().GetConstArgumentVector (); - if (argv) - { - for (size_t i=0; argv[i] != NULL; ++i) - { - if (i==0) - command.Printf(" '%s'", exe_path); - else - command.Printf(" '%s'", argv[i]); - } - } - else - { - command.Printf(" '%s'", exe_path); - } + command.Printf(" '%s'", exe_path); } command.PutCString (" ; echo Process exited with status $?"); @@ -1007,11 +972,11 @@ GetMacOSXProcessName (const ProcessInstanceInfoMatch *match_info_ptr, match_info_ptr->GetNameMatchType(), match_info_ptr->GetProcessInfo().GetName())) { - process_info.SetName (process_name); + process_info.GetExecutableFile().SetFile (process_name, false); return true; } } - process_info.SetName (NULL); + process_info.GetExecutableFile().Clear(); return false; } @@ -1306,6 +1271,11 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info) if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR)) flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag +//#ifdef POSIX_SPAWN_CLOEXEC_DEFAULT +// // Close all files exception those with file actions if this is supported. +// flags |= POSIX_SPAWN_CLOEXEC_DEFAULT; +//#endif + error.SetError( ::posix_spawnattr_setflags (&attr, flags), eErrorTypePOSIX); if (error.Fail() || log) error.PutToLog(log.get(), "::posix_spawnattr_setflags ( &attr, flags=0x%8.8x )", flags); @@ -1347,6 +1317,13 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info) } + const char *working_dir = launch_info.GetWorkingDirectory(); + if (working_dir) + { + // No more thread specific current working directory + __pthread_chdir (working_dir); + } + const size_t num_file_actions = launch_info.GetNumFileActions (); if (num_file_actions > 0) { @@ -1410,6 +1387,12 @@ Host::LaunchProcess (ProcessLaunchInfo &launch_info) envp); } + if (working_dir) + { + // No more thread specific current working directory + __pthread_fchdir (-1); + } + if (pid != LLDB_INVALID_PROCESS_ID) { // If all went well, then set the process ID into the launch info diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp index 50b43b1678c..f32b25c9127 100644 --- a/lldb/source/Interpreter/Args.cpp +++ b/lldb/source/Interpreter/Args.cpp @@ -864,6 +864,26 @@ Args::StringToVersion (const char *s, uint32_t &major, uint32_t &minor, uint32_t return 0; } +const char * +Args::GetShellSafeArgument (const char *unsafe_arg, std::string &safe_arg) +{ + safe_arg.assign (unsafe_arg); + size_t prev_pos = 0; + while (prev_pos < safe_arg.size()) + { + // Escape spaces and quotes + size_t pos = safe_arg.find_first_of(" '\"", prev_pos); + if (pos != std::string::npos) + { + safe_arg.insert (pos, 1, '\\'); + prev_pos = pos + 2; + } + else + break; + } + return safe_arg.c_str(); +} + int32_t Args::StringToOptionEnum (const char *s, OptionEnumValueElement *enum_values, int32_t fail_value, Error &error) diff --git a/lldb/source/Interpreter/CommandReturnObject.cpp b/lldb/source/Interpreter/CommandReturnObject.cpp index eb6fae4ce1b..51e6ee6e5fe 100644 --- a/lldb/source/Interpreter/CommandReturnObject.cpp +++ b/lldb/source/Interpreter/CommandReturnObject.cpp @@ -13,6 +13,7 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Core/Error.h" #include "lldb/Core/StreamString.h" using namespace lldb; @@ -134,6 +135,15 @@ CommandReturnObject::AppendError (const char *in_string, int len) GetErrorStream().Printf ("error: %*.*s\n", len, len, in_string); } +void +CommandReturnObject::SetError (const Error &error, const char *fallback_error_cstr) +{ + const char *error_cstr = error.AsCString(); + if (error_cstr == NULL) + error_cstr = fallback_error_cstr; + AppendError (error_cstr); + SetStatus (eReturnStatusFailed); +} // Similar to AppendError, but do not prepend 'Error: ' to message, and // don't append "\n" to the end of it. diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp index 8baaefc929f..408a57f391a 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp @@ -395,8 +395,15 @@ Error PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info) { Error error; + if (IsHost()) { + if (launch_info.GetFlags().Test (eLaunchFlagLaunchInShell)) + { + const bool is_localhost = true; + if (!launch_info.ConvertArgumentsForLaunchingInShell (error, is_localhost)) + return error; + } error = Platform::LaunchProcess (launch_info); } else @@ -410,13 +417,14 @@ PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info) } lldb::ProcessSP -PlatformDarwin::Attach (lldb::pid_t pid, +PlatformDarwin::Attach (ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, Listener &listener, Error &error) { lldb::ProcessSP process_sp; + if (IsHost()) { if (target == NULL) @@ -438,18 +446,17 @@ PlatformDarwin::Attach (lldb::pid_t pid, if (target && error.Success()) { debugger.GetTargetList().SetSelectedTarget(target); - // The darwin always currently uses the GDB remote debugger plug-in - // so even when debugging locally we are debugging remotely! - process_sp = target->CreateProcess (listener, "gdb-remote"); + + process_sp = target->CreateProcess (listener, attach_info.GetProcessPluginName()); if (process_sp) - error = process_sp->Attach (pid, 2); + error = process_sp->Attach (attach_info); } } else { if (m_remote_platform_sp) - process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error); + process_sp = m_remote_platform_sp->Attach (attach_info, debugger, target, listener, error); else error.SetErrorString ("the platform is not currently connected"); } diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h index 9b3e771193e..5ed533da3a3 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h @@ -79,7 +79,7 @@ public: LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); virtual lldb::ProcessSP - Attach (lldb::pid_t pid, + Attach (lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one lldb_private::Listener &listener, diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp index 69fa4487e3e..387737b7ab6 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp @@ -337,7 +337,7 @@ PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info) } lldb::ProcessSP -PlatformRemoteGDBServer::Attach (lldb::pid_t pid, +PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info, Debugger &debugger, Target *target, // Can be NULL, if NULL create a new target, else use existing one Listener &listener, @@ -391,7 +391,7 @@ PlatformRemoteGDBServer::Attach (lldb::pid_t pid, assert (connect_url_len < sizeof(connect_url)); error = process_sp->ConnectRemote (connect_url); if (error.Success()) - error = process_sp->Attach(pid, 0); + error = process_sp->Attach(attach_info); } } } diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h index 36c48c24b60..e141f7fc080 100644 --- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h +++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h @@ -94,7 +94,7 @@ public: LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info); virtual lldb::ProcessSP - Attach (lldb::pid_t pid, + Attach (lldb_private::ProcessAttachInfo &attach_info, lldb_private::Debugger &debugger, lldb_private::Target *target, // Can be NULL, if NULL create a new target, else use existing one lldb_private::Listener &listener, diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 85f56dd3ffb..5dd4dc68027 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1243,7 +1243,7 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot extractor.GetStringRef().swap(value); extractor.SetFilePos(0); extractor.GetHexByteString (value); - process_info.SetName (value.c_str()); + process_info.GetExecutableFile().SetFile (value.c_str(), false); } } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index 9712d6f2ccd..2fbac25c933 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -335,7 +335,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa StringExtractor extractor; extractor.GetStringRef().swap(value); extractor.GetHexByteString (value); - match_info.GetProcessInfo().SetName (value.c_str()); + match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false); } else if (key.compare("name_match") == 0) { diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp index 0213ac61485..3b780428836 100644 --- a/lldb/source/Target/Platform.cpp +++ b/lldb/source/Target/Platform.cpp @@ -577,16 +577,10 @@ Platform::DebugProcess (ProcessLaunchInfo &launch_info, error = LaunchProcess (launch_info); if (error.Success()) { - lldb::pid_t pid = launch_info.GetProcessID(); - if (pid != LLDB_INVALID_PROCESS_ID) + if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) { - process_sp = Attach (pid, debugger, target, listener, error); - -// if (process_sp) -// { -// if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry)) -// process_sp->Resume(); -// } + ProcessAttachInfo attach_info (launch_info); + process_sp = Attach (attach_info, debugger, target, listener, error); } } return process_sp; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 6ee9dbf85de..e70788e93ac 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -251,7 +251,7 @@ ProcessInfo::SetArguments (const Args& args, } void -ProcessLaunchInfo::FinalizeFileActions (Target *target, Process *process) +ProcessLaunchInfo::FinalizeFileActions (Target *target) { // If notthing was specified, then check the process for any default // settings that were set with "settings set" @@ -304,6 +304,87 @@ ProcessLaunchInfo::FinalizeFileActions (Target *target, Process *process) } } + +bool +ProcessLaunchInfo::ConvertArgumentsForLaunchingInShell (Error &error, bool localhost) +{ + error.Clear(); + + if (GetFlags().Test (eLaunchFlagLaunchInShell)) + { + const char *shell_executable = GetShell(); + if (shell_executable) + { + char shell_resolved_path[PATH_MAX]; + + if (localhost) + { + FileSpec shell_filespec (shell_executable, true); + + if (!shell_filespec.Exists()) + { + // Resolve the path in case we just got "bash", "sh" or "tcsh" + if (!shell_filespec.ResolveExecutableLocation ()) + { + error.SetErrorStringWithFormat("invalid shell path '%s'", shell_executable); + return false; + } + } + shell_filespec.GetPath (shell_resolved_path, sizeof(shell_resolved_path)); + shell_executable = shell_resolved_path; + } + + Args shell_arguments; + std::string safe_arg; + shell_arguments.AppendArgument (shell_executable); + StreamString shell_command; + shell_arguments.AppendArgument ("-c"); + shell_command.PutCString ("exec"); + if (GetArchitecture().IsValid()) + { + shell_command.Printf(" /usr/bin/arch -arch %s", GetArchitecture().GetArchitectureName()); + // Set the resume count to 2: + // 1 - stop in shell + // 2 - stop in /usr/bin/arch + // 3 - then we will stop in our program + SetResumeCount(2); + } + else + { + // Set the resume count to 1: + // 1 - stop in shell + // 2 - then we will stop in our program + SetResumeCount(1); + } + + const char **argv = GetArguments().GetConstArgumentVector (); + if (argv) + { + for (size_t i=0; argv[i] != NULL; ++i) + { + const char *arg = Args::GetShellSafeArgument (argv[i], safe_arg); + shell_command.Printf(" %s", arg); + } + } + shell_arguments.AppendArgument (shell_command.GetString().c_str()); + + m_executable.SetFile(shell_executable, false); + m_arguments = shell_arguments; + return true; + } + else + { + error.SetErrorString ("invalid shell path"); + } + } + else + { + error.SetErrorString ("not launching in shell"); + } + return false; +} + + bool ProcessLaunchInfo::FileAction::Open (int fd, const char *path, bool read, bool write) { @@ -312,11 +393,11 @@ ProcessLaunchInfo::FileAction::Open (int fd, const char *path, bool read, bool w m_action = eFileActionOpen; m_fd = fd; if (read && write) - m_arg = O_RDWR; + m_arg = O_NOCTTY | O_CREAT | O_RDWR; else if (read) - m_arg = O_RDONLY; + m_arg = O_NOCTTY | O_RDONLY; else - m_arg = O_WRONLY; + m_arg = O_NOCTTY | O_CREAT | O_WRONLY; m_path.assign (path); return true; } @@ -404,8 +485,12 @@ ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions else { int oflag = info->m_arg; + mode_t mode = 0; + if (oflag & O_CREAT) + mode = 0640; + error.SetError (::posix_spawn_file_actions_addopen (file_actions, info->m_fd, info->m_path.c_str(), @@ -496,7 +581,10 @@ ProcessLaunchCommandOptions::SetOptionValue (uint32_t option_idx, const char *op break; case 'c': - launch_info.GetFlags().Set (eLaunchFlagLaunchInShell); + if (option_arg && option_arg[0]) + launch_info.SetShell (option_arg); + else + launch_info.SetShell ("/bin/bash"); break; case 'v': @@ -520,7 +608,7 @@ ProcessLaunchCommandOptions::g_option_table[] = { LLDB_OPT_SET_ALL, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."}, { LLDB_OPT_SET_ALL, false, "arch", 'a', required_argument, NULL, 0, eArgTypeArchitecture, "Set the architecture for the process to launch when ambiguous."}, { LLDB_OPT_SET_ALL, false, "environment", 'v', required_argument, NULL, 0, eArgTypeNone, "Specify an environment variable name/value stirng (--environement NAME=VALUE). Can be specified multiple times for subsequent environment entries."}, -{ LLDB_OPT_SET_ALL, false, "shell", 'c', no_argument, NULL, 0, eArgTypeNone, "Run the process in a shell (not supported on all platforms)."}, +{ LLDB_OPT_SET_ALL, false, "shell", 'c', optional_argument, NULL, 0, eArgTypePath, "Run the process in a shell (not supported on all platforms)."}, { LLDB_OPT_SET_1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."}, { LLDB_OPT_SET_1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."}, @@ -2229,91 +2317,103 @@ Process::AttachCompletionHandler::GetExitString () } Error -Process::Attach (lldb::pid_t attach_pid, uint32_t exec_count) +Process::Attach (ProcessAttachInfo &attach_info) { - m_abi_sp.reset(); m_process_input_reader.reset(); - m_dyld_ap.reset(); m_os_ap.reset(); - - Error error (WillAttachToProcessWithID(attach_pid)); - if (error.Success()) - { - SetPublicState (eStateAttaching); - - error = DoAttachToProcessWithID (attach_pid); - if (error.Success()) - { - - SetNextEventAction(new Process::AttachCompletionHandler(this, exec_count)); - StartPrivateStateThread(); - } - else - { - if (GetID() != LLDB_INVALID_PROCESS_ID) - { - SetID (LLDB_INVALID_PROCESS_ID); - const char *error_string = error.AsCString(); - if (error_string == NULL) - error_string = "attach failed"; - - SetExitStatus(-1, error_string); - } - } - } - return error; -} - -Error -Process::Attach (const char *process_name, bool wait_for_launch) -{ - m_abi_sp.reset(); - m_process_input_reader.reset(); - // Find the process and its architecture. Make sure it matches the architecture - // of the current Target, and if not adjust it. + lldb::pid_t attach_pid = attach_info.GetProcessID(); Error error; - - if (!wait_for_launch) + if (attach_pid == LLDB_INVALID_PROCESS_ID) { - ProcessInstanceInfoList process_infos; - PlatformSP platform_sp (m_target.GetPlatform ()); - assert (platform_sp.get()); + char process_name[PATH_MAX]; - if (platform_sp) + if (attach_info.GetExecutableFile().GetPath (process_name, sizeof(process_name))) { - ProcessInstanceInfoMatch match_info; - match_info.GetProcessInfo().SetName(process_name); - match_info.SetNameMatchType (eNameMatchEquals); - platform_sp->FindProcesses (match_info, process_infos); - if (process_infos.GetSize() > 1) + const bool wait_for_launch = attach_info.GetWaitForLaunch(); + + if (wait_for_launch) { - error.SetErrorStringWithFormat ("more than one process named %s", process_name); + error = WillAttachToProcessWithName(process_name, wait_for_launch); + if (error.Success()) + { + SetPublicState (eStateAttaching); + error = DoAttachToProcessWithName (process_name, wait_for_launch); + if (error.Fail()) + { + if (GetID() != LLDB_INVALID_PROCESS_ID) + { + SetID (LLDB_INVALID_PROCESS_ID); + if (error.AsCString() == NULL) + error.SetErrorString("attach failed"); + + SetExitStatus(-1, error.AsCString()); + } + } + else + { + SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount())); + StartPrivateStateThread(); + } + return error; + } } - else if (process_infos.GetSize() == 0) + else { - error.SetErrorStringWithFormat ("could not find a process named %s", process_name); + ProcessInstanceInfoList process_infos; + PlatformSP platform_sp (m_target.GetPlatform ()); + + if (platform_sp) + { + ProcessInstanceInfoMatch match_info; + match_info.GetProcessInfo() = attach_info; + match_info.SetNameMatchType (eNameMatchEquals); + platform_sp->FindProcesses (match_info, process_infos); + const uint32_t num_matches = process_infos.GetSize(); + if (num_matches == 1) + { + attach_pid = process_infos.GetProcessIDAtIndex(0); + // Fall through and attach using the above process ID + } + else + { + match_info.GetProcessInfo().GetExecutableFile().GetPath (process_name, sizeof(process_name)); + if (num_matches > 1) + error.SetErrorStringWithFormat ("more than one process named %s", process_name); + else + error.SetErrorStringWithFormat ("could not find a process named %s", process_name); + } + } + else + { + error.SetErrorString ("invalid platform, can't find processes by name"); + return error; + } } } else - { - error.SetErrorString ("invalid platform"); + { + error.SetErrorString ("invalid process name"); } } - - if (error.Success()) + + if (attach_pid != LLDB_INVALID_PROCESS_ID) { - m_dyld_ap.reset(); - m_os_ap.reset(); - - error = WillAttachToProcessWithName(process_name, wait_for_launch); + error = WillAttachToProcessWithID(attach_pid); if (error.Success()) { SetPublicState (eStateAttaching); - error = DoAttachToProcessWithName (process_name, wait_for_launch); - if (error.Fail()) + + error = DoAttachToProcessWithID (attach_pid); + if (error.Success()) + { + + SetNextEventAction(new Process::AttachCompletionHandler(this, attach_info.GetResumeCount())); + StartPrivateStateThread(); + } + else { if (GetID() != LLDB_INVALID_PROCESS_ID) { @@ -2325,16 +2425,80 @@ Process::Attach (const char *process_name, bool wait_for_launch) SetExitStatus(-1, error_string); } } - else - { - SetNextEventAction(new Process::AttachCompletionHandler(this, 0)); - StartPrivateStateThread(); - } } } return error; } +//Error +//Process::Attach (const char *process_name, bool wait_for_launch) +//{ +// m_abi_sp.reset(); +// m_process_input_reader.reset(); +// +// // Find the process and its architecture. Make sure it matches the architecture +// // of the current Target, and if not adjust it. +// Error error; +// +// if (!wait_for_launch) +// { +// ProcessInstanceInfoList process_infos; +// PlatformSP platform_sp (m_target.GetPlatform ()); +// assert (platform_sp.get()); +// +// if (platform_sp) +// { +// ProcessInstanceInfoMatch match_info; +// match_info.GetProcessInfo().SetName(process_name); +// match_info.SetNameMatchType (eNameMatchEquals); +// platform_sp->FindProcesses (match_info, process_infos); +// if (process_infos.GetSize() > 1) +// { +// error.SetErrorStringWithFormat ("more than one process named %s", process_name); +// } +// else if (process_infos.GetSize() == 0) +// { +// error.SetErrorStringWithFormat ("could not find a process named %s", process_name); +// } +// } +// else +// { +// error.SetErrorString ("invalid platform"); +// } +// } +// +// if (error.Success()) +// { +// m_dyld_ap.reset(); +// m_os_ap.reset(); +// +// error = WillAttachToProcessWithName(process_name, wait_for_launch); +// if (error.Success()) +// { +// SetPublicState (eStateAttaching); +// error = DoAttachToProcessWithName (process_name, wait_for_launch); +// if (error.Fail()) +// { +// if (GetID() != LLDB_INVALID_PROCESS_ID) +// { +// SetID (LLDB_INVALID_PROCESS_ID); +// const char *error_string = error.AsCString(); +// if (error_string == NULL) +// error_string = "attach failed"; +// +// SetExitStatus(-1, error_string); +// } +// } +// else +// { +// SetNextEventAction(new Process::AttachCompletionHandler(this, 0)); +// StartPrivateStateThread(); +// } +// } +// } +// return error; +//} + void Process::CompleteAttach () { |