summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Core/ConnectionFileDescriptor.h3
-rw-r--r--lldb/include/lldb/Core/ConnectionMachPort.h2
-rw-r--r--lldb/include/lldb/Core/Debugger.h10
-rw-r--r--lldb/include/lldb/Core/Module.h8
-rw-r--r--lldb/include/lldb/Host/Host.h16
-rw-r--r--lldb/include/lldb/Interpreter/Args.h5
-rw-r--r--lldb/include/lldb/Interpreter/CommandInterpreter.h122
-rw-r--r--lldb/include/lldb/Target/Platform.h110
-rw-r--r--lldb/include/lldb/Target/Process.h545
-rw-r--r--lldb/include/lldb/lldb-enumerations.h9
-rw-r--r--lldb/include/lldb/lldb-forward.h6
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj15
-rw-r--r--lldb/source/API/SBTarget.cpp118
-rw-r--r--lldb/source/Commands/CommandObjectArgs.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectBreakpoint.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectDisassemble.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectFile.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp6
-rw-r--r--lldb/source/Commands/CommandObjectImage.cpp54
-rw-r--r--lldb/source/Commands/CommandObjectMemory.cpp6
-rw-r--r--lldb/source/Commands/CommandObjectPlatform.cpp262
-rw-r--r--lldb/source/Commands/CommandObjectProcess.cpp104
-rw-r--r--lldb/source/Commands/CommandObjectRegister.cpp4
-rw-r--r--lldb/source/Commands/CommandObjectSource.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectThread.cpp16
-rw-r--r--lldb/source/Core/ConnectionFileDescriptor.cpp35
-rw-r--r--lldb/source/Core/Debugger.cpp46
-rw-r--r--lldb/source/Core/Module.cpp3
-rw-r--r--lldb/source/Core/ModuleList.cpp42
-rw-r--r--lldb/source/Host/common/Host.cpp4
-rw-r--r--lldb/source/Host/macosx/Host.mm357
-rw-r--r--lldb/source/Host/macosx/Symbols.cpp17
-rw-r--r--lldb/source/Host/macosx/cfcpp/CFCString.h2
-rw-r--r--lldb/source/Interpreter/Args.cpp41
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp90
-rw-r--r--lldb/source/Interpreter/CommandObject.cpp2
-rw-r--r--lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp16
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp116
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h16
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp6
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h6
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp132
-rw-r--r--lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h17
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp140
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h18
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp191
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h75
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp467
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h50
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp190
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp289
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h22
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp9
-rw-r--r--lldb/source/Symbol/ObjectFile.cpp4
-rw-r--r--lldb/source/Target/Platform.cpp70
-rw-r--r--lldb/source/Target/Process.cpp429
-rw-r--r--lldb/source/Utility/StringExtractorGDBRemote.cpp86
-rw-r--r--lldb/source/Utility/StringExtractorGDBRemote.h16
-rw-r--r--lldb/test/abbreviation_tests/TestAbbreviations.py2
-rwxr-xr-xlldb/test/dotest.py4
-rw-r--r--lldb/test/foundation/TestFoundationDisassembly.py4
-rw-r--r--lldb/test/foundation/TestObjCMethods.py10
-rw-r--r--lldb/tools/darwin-debug/darwin-debug.cpp2
-rw-r--r--lldb/tools/debugserver/source/MacOSX/CFString.h2
-rw-r--r--lldb/tools/debugserver/source/RNBSocket.cpp98
-rw-r--r--lldb/tools/debugserver/source/RNBSocket.h13
-rw-r--r--lldb/tools/debugserver/source/debugserver.cpp86
-rw-r--r--lldb/tools/lldb-platform/lldb-platform.cpp2
69 files changed, 3408 insertions, 1256 deletions
diff --git a/lldb/include/lldb/Core/ConnectionFileDescriptor.h b/lldb/include/lldb/Core/ConnectionFileDescriptor.h
index b679892d203..84b084d4638 100644
--- a/lldb/include/lldb/Core/ConnectionFileDescriptor.h
+++ b/lldb/include/lldb/Core/ConnectionFileDescriptor.h
@@ -59,6 +59,9 @@ protected:
NamedSocketAccept (const char *socket_name, Error *error_ptr);
lldb::ConnectionStatus
+ NamedSocketConnect (const char *socket_name, Error *error_ptr);
+
+ lldb::ConnectionStatus
Close (int& fd, Error *error);
int m_fd; // Socket we use to communicate once conn established
diff --git a/lldb/include/lldb/Core/ConnectionMachPort.h b/lldb/include/lldb/Core/ConnectionMachPort.h
index 80adac79ba8..4339758c5c4 100644
--- a/lldb/include/lldb/Core/ConnectionMachPort.h
+++ b/lldb/include/lldb/Core/ConnectionMachPort.h
@@ -88,4 +88,4 @@ private:
#endif // liblldb_ConnectionMachPort_h_
-#endif // #if defined(__APPLE__) \ No newline at end of file
+#endif // #if defined(__APPLE__)
diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h
index c9833919278..6d7a29a3974 100644
--- a/lldb/include/lldb/Core/Debugger.h
+++ b/lldb/include/lldb/Core/Debugger.h
@@ -388,15 +388,6 @@ public:
bool
PopInputReader (const lldb::InputReaderSP& reader_sp);
- ExecutionContext &
- GetExecutionContext()
- {
- return m_exe_ctx;
- }
-
- void
- UpdateExecutionContext (ExecutionContext *override_context);
-
static lldb::DebuggerSP
FindDebuggerWithID (lldb::user_id_t id);
@@ -447,7 +438,6 @@ protected:
Listener m_listener;
SourceManager m_source_manager;
std::auto_ptr<CommandInterpreter> m_command_interpreter_ap;
- ExecutionContext m_exe_ctx;
std::stack<lldb::InputReaderSP> m_input_readers;
std::string m_input_reader_data;
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h
index d4caf735f01..424908ec64d 100644
--- a/lldb/include/lldb/Core/Module.h
+++ b/lldb/include/lldb/Core/Module.h
@@ -391,8 +391,11 @@ public:
const ConstString &
GetObjectName() const;
- off_t
- GetObjectOffset() const;
+ uint64_t
+ GetObjectOffset() const
+ {
+ return m_object_offset;
+ }
//------------------------------------------------------------------
/// Get the object file representation for the current architecture.
@@ -598,6 +601,7 @@ protected:
FileSpec m_file; ///< The file representation on disk for this module (if there is one).
FileSpec m_platform_file;///< The path to the module on the platform on which it is being debugged
ConstString m_object_name; ///< The name an object within this module that is selected, or empty of the module is represented by \a m_file.
+ uint64_t m_object_offset;
std::auto_ptr<ObjectFile> m_objfile_ap; ///< A pointer to the object file parser for this module.
std::auto_ptr<SymbolVendor> m_symfile_ap; ///< A pointer to the symbol vendor for this module.
ClangASTContext m_ast; ///< The AST context for this module.
diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h
index a4ec50aa489..db154a8effd 100644
--- a/lldb/include/lldb/Host/Host.h
+++ b/lldb/include/lldb/Host/Host.h
@@ -343,23 +343,17 @@ public:
SetCrashDescription (const char *description);
static uint32_t
- FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &proc_infos);
+ FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &proc_infos);
static bool
- GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
+ GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
static lldb::pid_t
LaunchApplication (const FileSpec &app_file_spec);
- static lldb::pid_t
- LaunchInNewTerminal (const char *tty_name, // Optional partial or full tty name ("/dev/ttys000" or "ttys000")
- const char **argv, // argv[0] is executable, argv[1] and on are the arguments
- const char **envp,
- const char *working_dir,
- const ArchSpec *arch_spec,
- bool stop_at_entry,
- bool disable_aslr);
+ static Error
+ LaunchProcess (ProcessLaunchInfo &launch_info);
static bool
OpenFileInExternalEditor (const FileSpec &file_spec,
diff --git a/lldb/include/lldb/Interpreter/Args.h b/lldb/include/lldb/Interpreter/Args.h
index 0b9c909ecaf..e706194a83e 100644
--- a/lldb/include/lldb/Interpreter/Args.h
+++ b/lldb/include/lldb/Interpreter/Args.h
@@ -82,6 +82,11 @@ public:
Args (const char *command, size_t len);
+ Args (const Args &rhs);
+
+ const Args &
+ operator= (const Args &rhs);
+
//------------------------------------------------------------------
/// Destructor.
//------------------------------------------------------------------
diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h
index b96d1e3ee49..ae3260a2910 100644
--- a/lldb/include/lldb/Interpreter/CommandInterpreter.h
+++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h
@@ -39,7 +39,8 @@ public:
};
void
- SourceInitFile (bool in_cwd, CommandReturnObject &result);
+ SourceInitFile (bool in_cwd,
+ CommandReturnObject &result);
CommandInterpreter (Debugger &debugger,
lldb::ScriptLanguage script_language,
@@ -49,13 +50,16 @@ public:
~CommandInterpreter ();
lldb::CommandObjectSP
- GetCommandSPExact (const char *cmd, bool include_aliases);
+ GetCommandSPExact (const char *cmd,
+ bool include_aliases);
CommandObject *
- GetCommandObjectExact (const char *cmd_cstr, bool include_aliases);
+ GetCommandObjectExact (const char *cmd_cstr,
+ bool include_aliases);
CommandObject *
- GetCommandObject (const char *cmd, StringList *matches = NULL);
+ GetCommandObject (const char *cmd,
+ StringList *matches = NULL);
bool
CommandExists (const char *cmd);
@@ -67,7 +71,8 @@ public:
UserCommandExists (const char *cmd);
void
- AddAlias (const char *alias_name, lldb::CommandObjectSP& command_obj_sp);
+ AddAlias (const char *alias_name,
+ lldb::CommandObjectSP& command_obj_sp);
bool
RemoveAlias (const char *alias_name);
@@ -82,14 +87,19 @@ public:
RemoveAliasOptions (const char *alias_name);
void
- AddOrReplaceAliasOptions (const char *alias_name, OptionArgVectorSP &option_arg_vector_sp);
+ AddOrReplaceAliasOptions (const char *alias_name,
+ OptionArgVectorSP &option_arg_vector_sp);
bool
- StripFirstWord (std::string &command_string, std::string &next_word);
+ StripFirstWord (std::string &command_string,
+ std::string &next_word);
void
- BuildAliasResult (const char *alias_name, std::string &raw_input_string, std::string &alias_result,
- CommandObject *&alias_cmd_obj, CommandReturnObject &result);
+ BuildAliasResult (const char *alias_name,
+ std::string &raw_input_string,
+ std::string &alias_result,
+ CommandObject *&alias_cmd_obj,
+ CommandReturnObject &result);
bool
HandleCommand (const char *command_line,
@@ -151,12 +161,12 @@ public:
//------------------------------------------------------------------
void
HandleCommandsFromFile (FileSpec &file,
- ExecutionContext *context,
- bool stop_on_continue,
- bool stop_on_error,
- bool echo_commands,
- bool print_results,
- CommandReturnObject &result);
+ ExecutionContext *context,
+ bool stop_on_continue,
+ bool stop_on_error,
+ bool echo_commands,
+ bool print_results,
+ CommandReturnObject &result);
CommandObject *
GetCommandObjectForCommand (std::string &command_line);
@@ -177,11 +187,11 @@ public:
int
HandleCompletion (const char *current_line,
- const char *cursor,
- const char *last_char,
- int match_start_point,
- int max_return_elements,
- StringList &matches);
+ const char *cursor,
+ const char *last_char,
+ int match_start_point,
+ int max_return_elements,
+ StringList &matches);
// This version just returns matches, and doesn't compute the substring. It is here so the
// Help command can call it for the first argument.
@@ -190,22 +200,26 @@ public:
int
HandleCompletionMatches (Args &input,
- int &cursor_index,
- int &cursor_char_position,
- int match_start_point,
- int max_return_elements,
- bool &word_complete,
- StringList &matches);
+ int &cursor_index,
+ int &cursor_char_position,
+ int match_start_point,
+ int max_return_elements,
+ bool &word_complete,
+ StringList &matches);
int
- GetCommandNamesMatchingPartialString (const char *cmd_cstr, bool include_aliases, StringList &matches);
+ GetCommandNamesMatchingPartialString (const char *cmd_cstr,
+ bool include_aliases,
+ StringList &matches);
void
GetHelp (CommandReturnObject &result);
void
- GetAliasHelp (const char *alias_name, const char *command_name, StreamString &help_string);
+ GetAliasHelp (const char *alias_name,
+ const char *command_name,
+ StreamString &help_string);
void
OutputFormattedHelpText (Stream &stream,
@@ -219,6 +233,18 @@ public:
{
return m_debugger;
}
+
+ ExecutionContext &
+ GetExecutionContext()
+ {
+ return m_exe_ctx;
+ }
+
+ void
+ UpdateExecutionContext (ExecutionContext *override_context);
+
+ lldb::PlatformSP
+ GetPlatform (bool prefer_target_platform);
const char *
ProcessEmbeddedScriptCommands (const char *arg);
@@ -245,7 +271,8 @@ public:
Initialize ();
void
- CrossRegisterCommand (const char * dest_cmd, const char * object_type);
+ CrossRegisterCommand (const char *dest_cmd,
+ const char *object_type);
void
SetScriptLanguage (lldb::ScriptLanguage lang);
@@ -264,8 +291,11 @@ public:
HasAliasOptions ();
void
- BuildAliasCommandArgs (CommandObject *alias_cmd_obj, const char *alias_name, Args &cmd_args,
- std::string &raw_input_string, CommandReturnObject &result);
+ BuildAliasCommandArgs (CommandObject *alias_cmd_obj,
+ const char *alias_name,
+ Args &cmd_args,
+ std::string &raw_input_string,
+ CommandReturnObject &result);
int
GetOptionArgumentPosition (const char *in_string);
@@ -284,10 +314,12 @@ public:
#ifndef SWIG
void
- AddLogChannel (const char *name, const Log::Callbacks &log_callbacks);
+ AddLogChannel (const char *name,
+ const Log::Callbacks &log_callbacks);
bool
- GetLogChannelCallbacks (const char *channel, Log::Callbacks &log_callbacks);
+ GetLogChannelCallbacks (const char *channel,
+ Log::Callbacks &log_callbacks);
bool
RemoveLogChannel (const char *name);
@@ -297,11 +329,16 @@ public:
FindLongestCommandWord (CommandObject::CommandMap &dict);
void
- FindCommandsForApropos (const char *word, StringList &commands_found, StringList &commands_help);
+ FindCommandsForApropos (const char *word,
+ StringList &commands_found,
+ StringList &commands_help);
void
- AproposAllSubCommands (CommandObject *cmd_obj, const char *prefix, const char *search_word,
- StringList &commands_found, StringList &commands_help);
+ AproposAllSubCommands (CommandObject *cmd_obj,
+ const char *prefix,
+ const char *search_word,
+ StringList &commands_found,
+ StringList &commands_help);
protected:
friend class Debugger;
@@ -314,15 +351,16 @@ protected:
private:
- Debugger &m_debugger; // The debugger session that this interpreter is associated with
+ Debugger &m_debugger; // The debugger session that this interpreter is associated with
+ ExecutionContext m_exe_ctx; // The current execution context to use when handling commands
bool m_synchronous_execution;
bool m_skip_lldbinit_files;
- CommandObject::CommandMap m_command_dict; // Stores basic built-in commands (they cannot be deleted, removed or overwritten).
- CommandObject::CommandMap m_alias_dict; // Stores user aliases/abbreviations for commands
- CommandObject::CommandMap m_user_dict; // Stores user-defined commands
- OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias.
+ CommandObject::CommandMap m_command_dict; // Stores basic built-in commands (they cannot be deleted, removed or overwritten).
+ CommandObject::CommandMap m_alias_dict; // Stores user aliases/abbreviations for commands
+ CommandObject::CommandMap m_user_dict; // Stores user-defined commands
+ OptionArgMap m_alias_options; // Stores any options (with or without arguments) that go with any alias.
std::vector<std::string> m_command_history;
- std::string m_repeat_command; // Stores the command that will be executed for an empty command string.
+ std::string m_repeat_command; // Stores the command that will be executed for an empty command string.
std::auto_ptr<ScriptInterpreter> m_script_interpreter_ap;
char m_comment_char;
};
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 60af2c93185..0da89f20631 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -123,6 +123,11 @@ namespace lldb_private {
bool
GetOSKernelDescription (std::string &s);
+ // Returns the the hostname if we are connected, else the short plugin
+ // name.
+ const char *
+ GetName ();
+
virtual const char *
GetHostname ();
@@ -252,83 +257,47 @@ namespace lldb_private {
BreakpointSite *bp_site) = 0;
//------------------------------------------------------------------
- /// Launch a new process.
- ///
- /// Launch a new process by spawning a new process using the
- /// target object's executable module's file as the file to launch.
- /// Arguments are given in \a argv, and the environment variables
- /// are in \a envp. Standard input and output files can be
- /// optionally re-directed to \a stdin_path, \a stdout_path, and
- /// \a stderr_path.
- ///
- /// This function is not meant to be overridden by Process
- /// subclasses. It will first call Process::WillLaunch (Module *)
- /// and if that returns \b true, Process::DoLaunch (Module*,
- /// char const *[],char const *[],const char *,const char *,
- /// const char *) will be called to actually do the launching. If
- /// DoLaunch returns \b true, then Process::DidLaunch() will be
- /// called.
- ///
- /// @param[in] argv
- /// The argument array.
- ///
- /// @param[in] envp
- /// The environment array.
- ///
- /// @param[in] launch_flags
- /// Flags to modify the launch (@see lldb::LaunchFlags)
- ///
- /// @param[in] stdin_path
- /// The path to use when re-directing the STDIN of the new
- /// process. If all stdXX_path arguments are NULL, a pseudo
- /// terminal will be used.
- ///
- /// @param[in] stdout_path
- /// The path to use when re-directing the STDOUT of the new
- /// process. If all stdXX_path arguments are NULL, a pseudo
- /// terminal will be used.
- ///
- /// @param[in] stderr_path
- /// The path to use when re-directing the STDERR of the new
- /// process. If all stdXX_path arguments are NULL, a pseudo
- /// terminal will be used.
- ///
- /// @param[in] working_directory
- /// The working directory to have the child process run in
- ///
- /// @return
- /// An error object. Call GetID() to get the process ID if
- /// the error object is success.
+ /// Launch a new process on a platform, not necessarily for
+ /// debugging, it could be just for running the process.
//------------------------------------------------------------------
-// virtual lldb::ProcessSP
-// Launch (char const *argv[],
-// char const *envp[],
-// uint32_t launch_flags,
-// const char *stdin_path,
-// const char *stdout_path,
-// const char *stderr_path,
-// const char *working_directory,
-// Error &error) = 0;
+ virtual Error
+ LaunchProcess (ProcessLaunchInfo &launch_info);
+
+ //------------------------------------------------------------------
+ /// Subclasses should NOT need to implement this function as it uses
+ /// the Platform::LaunchProcess() followed by Platform::Attach ()
+ //------------------------------------------------------------------
+ lldb::ProcessSP
+ DebugProcess (ProcessLaunchInfo &launch_info,
+ Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Listener &listener,
+ Error &error);
//------------------------------------------------------------------
/// Attach to an existing process using a process ID.
///
- /// 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
- /// be called to actually do the attach. If DoAttach returns \b
- /// true, then Process::DidAttach() will be called.
+ /// Each platform subclass needs to implement this function and
+ /// attempt to attach to the process with the process ID of \a pid.
+ /// The platform subclass should return an appropriate ProcessSP
+ /// subclass that is attached to the process, or an empty shared
+ /// pointer with an appriopriate error.
///
/// @param[in] pid
/// The process ID that we should attempt to attach to.
///
/// @return
- /// Returns \a pid if attaching was successful, or
- /// LLDB_INVALID_PROCESS_ID if attaching fails.
+ /// An appropriate ProcessSP containing a valid shared pointer
+ /// to the default Process subclass for the platform that is
+ /// attached to the process, or an empty shared pointer with an
+ /// appriopriate error fill into the \a error object.
//------------------------------------------------------------------
-// virtual lldb::ProcessSP
-// Attach (lldb::pid_t pid,
-// Error &error) = 0;
+ virtual lldb::ProcessSP
+ Attach (lldb::pid_t pid,
+ Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Listener &listener,
+ Error &error) = 0;
//------------------------------------------------------------------
/// Attach to an existing process by process name.
@@ -357,11 +326,11 @@ namespace lldb_private {
// Subclasses will need to fill in the remote case.
//------------------------------------------------------------------
virtual uint32_t
- FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &proc_infos);
+ FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &proc_infos);
virtual bool
- GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc_info);
+ GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &proc_info);
const std::string &
GetRemoteURL () const
@@ -529,7 +498,8 @@ namespace lldb_private {
public:
PlatformList() :
m_mutex (Mutex::eMutexTypeRecursive),
- m_platforms ()
+ m_platforms (),
+ m_selected_platform_sp()
{
}
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index cee05307a18..98612ff23ae 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -11,8 +11,11 @@
#define liblldb_Process_h_
// C Includes
+#include <spawn.h>
+
// C++ Includes
#include <list>
+#include <iosfwd>
#include <vector>
// Other libraries and framework includes
@@ -39,7 +42,9 @@
namespace lldb_private {
-
+//----------------------------------------------------------------------
+// ProcessInstanceSettings
+//----------------------------------------------------------------------
class ProcessInstanceSettings : public InstanceSettings
{
public:
@@ -224,35 +229,38 @@ private:
bool m_got_host_env;
};
-
+//----------------------------------------------------------------------
+// ProcessInfo
+//
+// A base class for information for a process. This can be used to fill
+// out information for a process prior to launching it, or it can be
+// used for an instance of a process and can be filled in with the
+// existing values for that process.
+//----------------------------------------------------------------------
class ProcessInfo
{
public:
ProcessInfo () :
m_executable (),
- m_args (),
- m_real_uid (UINT32_MAX),
- m_real_gid (UINT32_MAX),
- m_effective_uid (UINT32_MAX),
- m_effective_gid (UINT32_MAX),
+ m_arguments (),
+ m_environment (),
+ m_uid (LLDB_INVALID_UID),
+ m_gid (LLDB_INVALID_UID),
m_arch(),
- m_pid (LLDB_INVALID_PROCESS_ID),
- m_parent_pid (LLDB_INVALID_PROCESS_ID)
+ m_pid (LLDB_INVALID_PROCESS_ID)
{
}
-
+
ProcessInfo (const char *name,
const ArchSpec &arch,
lldb::pid_t pid) :
- m_executable (),
- m_args (),
- m_real_uid (UINT32_MAX),
- m_real_gid (UINT32_MAX),
- m_effective_uid (UINT32_MAX),
- m_effective_gid (UINT32_MAX),
+ m_executable (name, false),
+ m_arguments (),
+ m_environment(),
+ m_uid (LLDB_INVALID_UID),
+ m_gid (LLDB_INVALID_UID),
m_arch (arch),
- m_pid (pid),
- m_parent_pid (LLDB_INVALID_PROCESS_ID)
+ m_pid (pid)
{
}
@@ -260,14 +268,12 @@ public:
Clear ()
{
m_executable.Clear();
- m_args.Clear();
- m_real_uid = UINT32_MAX;
- m_real_gid = UINT32_MAX;
- m_effective_uid = UINT32_MAX;
- m_effective_gid = UINT32_MAX;
+ m_arguments.Clear();
+ m_environment.Clear();
+ m_uid = LLDB_INVALID_UID;
+ m_gid = LLDB_INVALID_UID;
m_arch.Clear();
m_pid = LLDB_INVALID_PROCESS_ID;
- m_parent_pid = LLDB_INVALID_PROCESS_ID;
}
const char *
@@ -275,7 +281,7 @@ public:
{
return m_executable.GetFilename().GetCString();
}
-
+
size_t
GetNameLength() const
{
@@ -293,97 +299,61 @@ public:
{
return m_executable;
}
-
+
const FileSpec &
GetExecutableFile () const
{
return m_executable;
}
-
- uint32_t
- GetRealUserID() const
- {
- return m_real_uid;
- }
uint32_t
- GetRealGroupID() const
- {
- return m_real_gid;
- }
-
- uint32_t
- GetEffectiveUserID() const
+ GetUserID() const
{
- return m_effective_uid;
+ return m_uid;
}
-
+
uint32_t
- GetEffectiveGroupID() const
+ GetGroupID() const
{
- return m_effective_gid;
+ return m_gid;
}
bool
- RealUserIDIsValid () const
+ UserIDIsValid () const
{
- return m_real_uid != UINT32_MAX;
+ return m_uid != UINT32_MAX;
}
bool
- RealGroupIDIsValid () const
+ GroupIDIsValid () const
{
- return m_real_gid != UINT32_MAX;
+ return m_gid != UINT32_MAX;
}
- bool
- EffectiveUserIDIsValid () const
- {
- return m_effective_uid != UINT32_MAX;
- }
-
- bool
- EffectiveGroupIDIsValid () const
- {
- return m_effective_gid != UINT32_MAX;
- }
-
void
- SetRealUserID (uint32_t uid)
+ SetUserID (uint32_t uid)
{
- m_real_uid = uid;
- }
-
- void
- SetRealGroupID (uint32_t gid)
- {
- m_real_gid = gid;
- }
-
- void
- SetEffectiveUserID (uint32_t uid)
- {
- m_effective_uid = uid;
+ m_uid = uid;
}
void
- SetEffectiveGroupID (uint32_t gid)
+ SetGroupID (uint32_t gid)
{
- m_effective_gid = gid;
+ m_gid = gid;
}
-
+
ArchSpec &
GetArchitecture ()
{
return m_arch;
}
-
+
const ArchSpec &
GetArchitecture () const
{
return m_arch;
}
-
+
lldb::pid_t
GetProcessID () const
{
@@ -401,6 +371,120 @@ public:
{
return m_pid != LLDB_INVALID_PROCESS_ID;
}
+
+ void
+ Dump (Stream &s, Platform *platform) const;
+
+ Args &
+ GetArguments ()
+ {
+ return m_arguments;
+ }
+
+ const Args &
+ GetArguments () const
+ {
+ return m_arguments;
+ }
+
+ void
+ SetArgumentsFromArgs (const Args& args,
+ bool first_arg_is_executable,
+ bool first_arg_is_executable_and_argument);
+
+ Args &
+ GetEnvironmentEntries ()
+ {
+ return m_environment;
+ }
+
+ const Args &
+ GetEnvironmentEntries () const
+ {
+ return m_environment;
+ }
+
+protected:
+ FileSpec m_executable;
+ Args m_arguments;
+ Args m_environment;
+ uint32_t m_uid;
+ uint32_t m_gid;
+ ArchSpec m_arch;
+ lldb::pid_t m_pid;
+};
+
+//----------------------------------------------------------------------
+// ProcessInstanceInfo
+//
+// Describes an existing process and any discoverable information that
+// pertains to that process.
+//----------------------------------------------------------------------
+class ProcessInstanceInfo : public ProcessInfo
+{
+public:
+ ProcessInstanceInfo () :
+ ProcessInfo (),
+ m_euid (UINT32_MAX),
+ m_egid (UINT32_MAX),
+ m_parent_pid (LLDB_INVALID_PROCESS_ID)
+ {
+ }
+
+ ProcessInstanceInfo (const char *name,
+ const ArchSpec &arch,
+ lldb::pid_t pid) :
+ ProcessInfo (name, arch, pid),
+ m_euid (UINT32_MAX),
+ m_egid (UINT32_MAX),
+ m_parent_pid (LLDB_INVALID_PROCESS_ID)
+ {
+ }
+
+ void
+ Clear ()
+ {
+ ProcessInfo::Clear();
+ m_euid = UINT32_MAX;
+ m_egid = UINT32_MAX;
+ m_parent_pid = LLDB_INVALID_PROCESS_ID;
+ }
+
+ uint32_t
+ GetEffectiveUserID() const
+ {
+ return m_euid;
+ }
+
+ uint32_t
+ GetEffectiveGroupID() const
+ {
+ return m_egid;
+ }
+
+ bool
+ EffectiveUserIDIsValid () const
+ {
+ return m_euid != UINT32_MAX;
+ }
+
+ bool
+ EffectiveGroupIDIsValid () const
+ {
+ return m_egid != UINT32_MAX;
+ }
+
+ void
+ SetEffectiveUserID (uint32_t uid)
+ {
+ m_euid = uid;
+ }
+
+ void
+ SetEffectiveGroupID (uint32_t gid)
+ {
+ m_egid = gid;
+ }
lldb::pid_t
GetParentProcessID () const
@@ -424,46 +508,272 @@ public:
Dump (Stream &s, Platform *platform) const;
static void
- DumpTableHeader (Stream &s, Platform *platform, bool verbose = false);
+ DumpTableHeader (Stream &s, Platform *platform, bool show_args, bool verbose);
+
+ void
+ DumpAsTableRow (Stream &s, Platform *platform, bool show_args, bool verbose) const;
+
+protected:
+ uint32_t m_euid;
+ uint32_t m_egid;
+ lldb::pid_t m_parent_pid;
+};
+
+
+//----------------------------------------------------------------------
+// ProcessLaunchInfo
+//
+// Describes any information that is required to launch a process.
+//----------------------------------------------------------------------
+
+class ProcessLaunchInfo : public ProcessInfo
+{
+public:
+
+ class FileAction
+ {
+ public:
+
+ FileAction () :
+ m_action (eFileActionNone),
+ m_fd (-1),
+ m_arg (-1),
+ m_path ()
+ {
+ }
+
+ void
+ Clear()
+ {
+ m_action = eFileActionNone;
+ m_fd = -1;
+ m_arg = -1;
+ m_path.clear();
+ }
+
+ bool
+ Close (int fd);
+
+ bool
+ Duplicate (int fd, int dup_fd);
+
+ bool
+ Open (int fd, const char *path, bool read, bool write);
+
+ static bool
+ AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions,
+ const FileAction *info,
+ Log *log,
+ Error& error);
+
+ protected:
+ enum Action
+ {
+ eFileActionNone,
+ eFileActionClose,
+ eFileActionDuplicate,
+ eFileActionOpen
+ };
+
+ Action m_action; // The action for this file
+ int m_fd; // An existing file descriptor
+ int m_arg; // oflag for eFileActionOpen*, dup_fd for eFileActionDuplicate
+ std::string m_path; // A file path to use for opening after fork or posix_spawn
+ };
+
+ ProcessLaunchInfo () :
+ ProcessInfo(),
+ m_flags (),
+ m_stdin_info (),
+ m_stdout_info (),
+ m_stderr_info ()
+ {
+ }
+
+ void
+ AppendFileAction (const FileAction &info)
+ {
+ m_file_actions.push_back(info);
+ }
+
+ void
+ AppendCloseFileAction (int fd)
+ {
+ FileAction file_action;
+ file_action.Close (fd);
+ AppendFileAction (file_action);
+ }
+
+ void
+ AppendDuplciateFileAction (int fd, int dup_fd)
+ {
+ FileAction file_action;
+ file_action.Duplicate (fd, dup_fd);
+ AppendFileAction (file_action);
+ }
+
+ void
+ AppendOpenFileAction (int fd, const char *path, bool read, bool write)
+ {
+ FileAction file_action;
+ file_action.Open (fd, path, read, write);
+ AppendFileAction (file_action);
+ }
+
+ void
+ AppendSuppressFileAction (int fd, bool read, bool write)
+ {
+ FileAction file_action;
+ file_action.Open (fd, "/dev/null", read, write);
+ AppendFileAction (file_action);
+ }
+
+ size_t
+ GetNumFileActions () const
+ {
+ return m_file_actions.size();
+ }
+
+ const FileAction *
+ GetFileActionAtIndex (size_t idx) const
+ {
+ if (idx < m_file_actions.size())
+ return &m_file_actions[idx];
+ return NULL;
+ }
+
+ Flags &
+ GetFlags ()
+ {
+ return m_flags;
+ }
+
+ const Flags &
+ GetFlags () const
+ {
+ return m_flags;
+ }
+
+ const char *
+ GetWorkingDirectory () const
+ {
+ if (m_working_dir.empty())
+ return NULL;
+ return m_working_dir.c_str();
+ }
void
- DumpAsTableRow (Stream &s, Platform *platform, bool verbose = false) const;
+ SetWorkingDirectory (const char *working_dir)
+ {
+ if (working_dir && working_dir[0])
+ m_working_dir.assign (working_dir);
+ else
+ m_working_dir.clear();
+ }
- StringList &
- GetArguments()
+ void
+ SwapWorkingDirectory (std::string &working_dir)
{
- return m_args;
+ m_working_dir.swap (working_dir);
+ }
+
+
+ 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();
}
- const StringList &
- GetArguments() const
+ void
+ Clear ()
{
- return m_args;
+ ProcessInfo::Clear();
+ m_working_dir.clear();
+ m_plugin_name.clear();
+ m_flags.Clear();
+ m_stdin_info.Clear();
+ m_stdout_info.Clear();
+ m_stderr_info.Clear();
+ m_file_actions.clear();
}
protected:
- FileSpec m_executable;
- StringList m_args;
- uint32_t m_real_uid;
- uint32_t m_real_gid;
- uint32_t m_effective_uid;
- uint32_t m_effective_gid;
- ArchSpec m_arch;
- lldb::pid_t m_pid;
- lldb::pid_t m_parent_pid;
+ std::string m_working_dir;
+ std::string m_plugin_name;
+ Flags m_flags; // Bitwise OR of bits from lldb::LaunchFlags
+ FileAction m_stdin_info; // File action for stdin
+ FileAction m_stdout_info; // File action for stdout
+ FileAction m_stderr_info; // File action for stderr
+ std::vector<FileAction> m_file_actions; // File actions for any other files
};
-class ProcessInfoMatch
+class ProcessLaunchCommandOptions : public Options
{
public:
- ProcessInfoMatch () :
+
+ ProcessLaunchCommandOptions (CommandInterpreter &interpreter) :
+ Options(interpreter)
+ {
+ // Keep default values of all options in one place: ResetOptionValues ()
+ ResetOptionValues ();
+ }
+
+ ~ProcessLaunchCommandOptions ()
+ {
+ }
+
+ Error
+ SetOptionValue (int option_idx, const char *option_arg);
+
+ void
+ ResetOptionValues ()
+ {
+ launch_info.Clear();
+ }
+
+ const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+
+ // Instance variables to hold the values for command options.
+
+ ProcessLaunchInfo launch_info;
+};
+
+//----------------------------------------------------------------------
+// ProcessInstanceInfoMatch
+//
+// A class to help matching one ProcessInstanceInfo to another.
+//----------------------------------------------------------------------
+
+class ProcessInstanceInfoMatch
+{
+public:
+ ProcessInstanceInfoMatch () :
m_match_info (),
m_name_match_type (lldb_private::eNameMatchIgnore),
m_match_all_users (false)
{
}
- ProcessInfoMatch (const char *process_name,
+ ProcessInstanceInfoMatch (const char *process_name,
lldb_private::NameMatchType process_name_match_type) :
m_match_info (),
m_name_match_type (process_name_match_type),
@@ -472,13 +782,13 @@ public:
m_match_info.SetName (process_name);
}
- ProcessInfo &
+ ProcessInstanceInfo &
GetProcessInfo ()
{
return m_match_info;
}
- const ProcessInfo &
+ const ProcessInstanceInfo &
GetProcessInfo () const
{
return m_match_info;
@@ -512,7 +822,7 @@ public:
NameMatches (const char *process_name) const;
bool
- Matches (const ProcessInfo &proc_info) const;
+ Matches (const ProcessInstanceInfo &proc_info) const;
bool
MatchAllProcesses () const;
@@ -520,15 +830,15 @@ public:
Clear ();
protected:
- ProcessInfo m_match_info;
+ ProcessInstanceInfo m_match_info;
lldb_private::NameMatchType m_name_match_type;
bool m_match_all_users;
};
-class ProcessInfoList
+class ProcessInstanceInfoList
{
public:
- ProcessInfoList () :
+ ProcessInstanceInfoList () :
m_infos()
{
}
@@ -546,7 +856,7 @@ public:
}
void
- Append (const ProcessInfo &info)
+ Append (const ProcessInstanceInfo &info)
{
m_infos.push_back (info);
}
@@ -576,7 +886,7 @@ public:
}
bool
- GetInfoAtIndex (uint32_t idx, ProcessInfo &info)
+ GetInfoAtIndex (uint32_t idx, ProcessInstanceInfo &info)
{
if (idx < m_infos.size())
{
@@ -587,7 +897,7 @@ public:
}
// You must ensure "idx" is valid before calling this function
- const ProcessInfo &
+ const ProcessInstanceInfo &
GetProcessInfoAtIndex (uint32_t idx) const
{
assert (idx < m_infos.size());
@@ -595,7 +905,7 @@ public:
}
protected:
- typedef std::vector<ProcessInfo> collection;
+ typedef std::vector<ProcessInstanceInfo> collection;
collection m_infos;
};
@@ -1732,6 +2042,20 @@ public:
size_t size,
Error &error);
+ //------------------------------------------------------------------
+ /// Read a NULL terminated C string from memory
+ ///
+ /// This function will read a cache page at a time until the NULL
+ /// C stirng terminator is found. It will stop reading if the NULL
+ /// termination byte isn't found before reading \a cstr_max_len
+ /// bytes, and the results are always guaranteed to be NULL
+ /// terminated (at most cstr_max_len - 1 bytes will be read).
+ //------------------------------------------------------------------
+ size_t
+ ReadCStringFromMemory (lldb::addr_t vm_addr,
+ char *cstr,
+ size_t cstr_max_len);
+
size_t
ReadMemoryFromInferior (lldb::addr_t vm_addr,
void *buf,
@@ -2292,6 +2616,11 @@ protected:
size_t dst_len,
Error &error);
+ uint32_t
+ GetMemoryCacheLineSize() const
+ {
+ return m_cache_line_byte_size ;
+ }
protected:
typedef std::map<lldb::addr_t, lldb::DataBufferSP> collection;
//------------------------------------------------------------------
diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h
index 454893f1370..6e055ab751d 100644
--- a/lldb/include/lldb/lldb-enumerations.h
+++ b/lldb/include/lldb/lldb-enumerations.h
@@ -39,9 +39,12 @@ namespace lldb {
typedef enum LaunchFlags
{
eLaunchFlagNone = 0u,
- eLaunchFlagDisableASLR = (1u << 0), ///< Disable Address Space Layout Randomization
- eLaunchFlagDisableSTDIO = (1u << 1), ///< Disable stdio for inferior process (e.g. for a GUI app)
- eLaunchFlagLaunchInTTY = (1u << 2) ///< Launch the process in a new TTY if supported by the host
+ eLaunchFlagExec = (1u << 0), ///< Exec when launching and turn the calling process into a new process
+ eLaunchFlagDebug = (1u << 1), ///< Stop as soon as the process launches to allow the process to be debugged
+ eLaunchFlagStopAtEntry = (1u << 2), ///< Stop at the program entry point instead of auto-continuing when launching or attaching at entry point
+ eLaunchFlagDisableASLR = (1u << 3), ///< Disable Address Space Layout Randomization
+ eLaunchFlagDisableSTDIO = (1u << 4), ///< Disable stdio for inferior process (e.g. for a GUI app)
+ eLaunchFlagLaunchInTTY = (1u << 5) ///< Launch the process in a new TTY if supported by the host
} LaunchFlags;
//----------------------------------------------------------------------
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index a4251c21468..ed6e8b36d3b 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -103,8 +103,10 @@ class PathMappingList;
class Platform;
class Process;
class ProcessInfo;
-class ProcessInfoList;
-class ProcessInfoMatch;
+class ProcessInstanceInfo;
+class ProcessInstanceInfoList;
+class ProcessInstanceInfoMatch;
+class ProcessLaunchInfo;
class RegisterContext;
class RegisterLocation;
class RegisterLocationList;
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index 0019e971159..92250ab243d 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -62,6 +62,7 @@
26680336116005EF008E1FE4 /* SBBreakpointLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16CC7114086A1007A7B3F /* SBBreakpointLocation.cpp */; };
26680337116005F1008E1FE4 /* SBBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9AF16A9C11402D5B007A7B3F /* SBBreakpoint.cpp */; };
2668035C11601108008E1FE4 /* LLDB.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26680207115FD0ED008E1FE4 /* LLDB.framework */; };
+ 266E8C6A13528ABC000C2042 /* lldb-platform in Resources */ = {isa = PBXBuildFile; fileRef = 26DC6A101337FE6900FF7998 /* lldb-platform */; };
2671A0CE134825F6003A87BB /* ConnectionMachPort.h in Headers */ = {isa = PBXBuildFile; fileRef = 2671A0CD134825F6003A87BB /* ConnectionMachPort.h */; };
2671A0D013482601003A87BB /* ConnectionMachPort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2671A0CF13482601003A87BB /* ConnectionMachPort.cpp */; };
26744EF11338317700EF765A /* GDBRemoteCommunicationClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26744EED1338317700EF765A /* GDBRemoteCommunicationClient.cpp */; };
@@ -446,6 +447,13 @@
remoteGlobalIDString = 26680206115FD0ED008E1FE4;
remoteInfo = LLDB;
};
+ 266E8C6C13528AD2000C2042 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 26DC6A0F1337FE6900FF7998;
+ remoteInfo = "lldb-platform";
+ };
2689011413353E9B00698AC0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
@@ -2579,6 +2587,7 @@
buildRules = (
);
dependencies = (
+ 266E8C6D13528AD2000C2042 /* PBXTargetDependency */,
2689011513353E9B00698AC0 /* PBXTargetDependency */,
262CFC7211A450CB00946C6C /* PBXTargetDependency */,
26368AF6126B95FA00E8659F /* PBXTargetDependency */,
@@ -2688,6 +2697,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 266E8C6A13528ABC000C2042 /* lldb-platform in Resources */,
262CFC7711A4510000946C6C /* debugserver in Resources */,
26368AF7126B960500E8659F /* darwin-debug in Resources */,
);
@@ -3143,6 +3153,11 @@
target = 26680206115FD0ED008E1FE4 /* LLDB */;
targetProxy = 266803611160110D008E1FE4 /* PBXContainerItemProxy */;
};
+ 266E8C6D13528AD2000C2042 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 26DC6A0F1337FE6900FF7998 /* lldb-platform */;
+ targetProxy = 266E8C6C13528AD2000C2042 /* PBXContainerItemProxy */;
+ };
2689011513353E9B00698AC0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 2689FFC913353D7A00698AC0 /* lldb-core */;
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index a54a15ec936..551a49680e1 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -204,65 +204,65 @@ SBTarget::Launch
}
}
- 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<const char *> 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 ((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<const char *> 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 (listener.IsValid())
sb_process.SetProcess (m_opaque_sp->CreateProcess (listener.ref()));
diff --git a/lldb/source/Commands/CommandObjectArgs.cpp b/lldb/source/Commands/CommandObjectArgs.cpp
index 6064ec8dbc6..0ed4a06e564 100644
--- a/lldb/source/Commands/CommandObjectArgs.cpp
+++ b/lldb/source/Commands/CommandObjectArgs.cpp
@@ -105,7 +105,7 @@ CommandObjectArgs::Execute
ConstString target_triple;
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (!process)
{
result.AppendError ("Args found no process.");
@@ -131,7 +131,7 @@ CommandObjectArgs::Execute
return false;
}
- Thread *thread = m_interpreter.GetDebugger().GetExecutionContext ().thread;
+ Thread *thread = m_interpreter.GetExecutionContext ().thread;
if (!thread)
{
diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp
index c8287015643..d5a4345ba2e 100644
--- a/lldb/source/Commands/CommandObjectBreakpoint.cpp
+++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp
@@ -322,7 +322,7 @@ CommandObjectBreakpointSet::Execute
FileSpec file;
if (m_options.m_filename.empty())
{
- StackFrame *cur_frame = m_interpreter.GetDebugger().GetExecutionContext().frame;
+ StackFrame *cur_frame = m_interpreter.GetExecutionContext().frame;
if (cur_frame == NULL)
{
result.AppendError ("Attempting to set breakpoint by line number alone with no selected frame.");
diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp
index 1301fd9f4da..dea764074e1 100644
--- a/lldb/source/Commands/CommandObjectDisassemble.cpp
+++ b/lldb/source/Commands/CommandObjectDisassemble.cpp
@@ -128,7 +128,7 @@ CommandObjectDisassemble::CommandOptions::SetOptionValue (int option_idx, const
break;
case 'a':
- arch.SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
+ arch.SetTriple (option_arg, m_interpreter.GetPlatform (true).get());
break;
default:
@@ -257,7 +257,7 @@ CommandObjectDisassemble::Execute
if (m_options.show_mixed && m_options.num_lines_context == 0)
m_options.num_lines_context = 1;
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (!m_options.func_name.empty())
{
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 31ecaf106d2..c96b247ce12 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -295,7 +295,7 @@ CommandObjectExpression::ExecuteRawCommandString
CommandReturnObject &result
)
{
- m_exe_ctx = m_interpreter.GetDebugger().GetExecutionContext();
+ m_exe_ctx = m_interpreter.GetExecutionContext();
m_options.Reset();
diff --git a/lldb/source/Commands/CommandObjectFile.cpp b/lldb/source/Commands/CommandObjectFile.cpp
index e0c81bbf983..1177f5aafbc 100644
--- a/lldb/source/Commands/CommandObjectFile.cpp
+++ b/lldb/source/Commands/CommandObjectFile.cpp
@@ -58,7 +58,7 @@ CommandObjectFile::CommandOptions::SetOptionValue (int option_idx, const char *o
{
case 'a':
{
- PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+ PlatformSP platform_sp (m_interpreter.GetPlatform (false));
ArchSpec option_arch (option_arg, platform_sp.get());
if (option_arch.IsValid())
m_arch = option_arch;
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index aaaee06c4be..57286ac3014 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -69,7 +69,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.frame)
{
exe_ctx.frame->DumpUsingSettingsFormat (&result.GetOutputStream());
@@ -188,7 +188,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- ExecutionContext exe_ctx (m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
if (exe_ctx.thread)
{
const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount();
@@ -445,7 +445,7 @@ public:
CommandReturnObject &result
)
{
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.frame == NULL)
{
result.AppendError ("you must be stopped in a valid stack frame to view frame variables.");
diff --git a/lldb/source/Commands/CommandObjectImage.cpp b/lldb/source/Commands/CommandObjectImage.cpp
index 3d005a80526..ca109d59576 100644
--- a/lldb/source/Commands/CommandObjectImage.cpp
+++ b/lldb/source/Commands/CommandObjectImage.cpp
@@ -87,7 +87,7 @@ DumpCompileUnitLineTable
LineTable *line_table = sc.comp_unit->GetLineTable();
if (line_table)
line_table->GetDescription (&strm,
- interpreter.GetDebugger().GetExecutionContext().target,
+ interpreter.GetExecutionContext().target,
lldb::eDescriptionLevelBrief);
else
strm << "No line table";
@@ -165,7 +165,7 @@ DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module,
{
Symtab *symtab = objfile->GetSymtab();
if (symtab)
- symtab->Dump(&strm, interpreter.GetDebugger().GetExecutionContext().target, sort_order);
+ symtab->Dump(&strm, interpreter.GetExecutionContext().target, sort_order);
}
}
}
@@ -183,9 +183,11 @@ DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *modul
{
strm.PutCString ("Sections for '");
strm << module->GetFileSpec();
+ if (module->GetObjectName())
+ strm << '(' << module->GetObjectName() << ')';
strm.Printf ("' (%s):\n", module->GetArchitecture().GetArchitectureName());
strm.IndentMore();
- section_list->Dump(&strm, interpreter.GetDebugger().GetExecutionContext().target, true, UINT32_MAX);
+ section_list->Dump(&strm, interpreter.GetExecutionContext().target, true, UINT32_MAX);
strm.IndentLess();
}
}
@@ -224,7 +226,7 @@ LookupAddressInModule
lldb::addr_t addr = raw_addr - offset;
Address so_addr;
SymbolContext sc;
- Target *target = interpreter.GetDebugger().GetExecutionContext().target;
+ Target *target = interpreter.GetExecutionContext().target;
if (target && !target->GetSectionLoadList().IsEmpty())
{
if (!target->GetSectionLoadList().ResolveLoadAddress (addr, so_addr))
@@ -242,7 +244,7 @@ LookupAddressInModule
if (offset)
strm.Printf("File Address: 0x%llx\n", addr);
- ExecutionContextScope *exe_scope = interpreter.GetDebugger().GetExecutionContext().GetBestExecutionContextScope();
+ ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope();
strm.IndentMore();
strm.Indent (" Address: ");
so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset);
@@ -309,7 +311,7 @@ LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *mod
{
Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
strm.Indent ();
- symbol->Dump (&strm, interpreter.GetDebugger().GetExecutionContext().target, i);
+ symbol->Dump (&strm, interpreter.GetExecutionContext().target, i);
}
strm.IndentLess ();
return num_matches;
@@ -338,9 +340,9 @@ DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolCont
{
if (sc.line_entry.range.GetBaseAddress().IsValid())
{
- lldb::addr_t vm_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(interpreter.GetDebugger().GetExecutionContext().target);
+ lldb::addr_t vm_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(interpreter.GetExecutionContext().target);
int addr_size = sizeof (addr_t);
- Process *process = interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = interpreter.GetExecutionContext().process;
if (process)
addr_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
if (vm_addr != LLDB_INVALID_ADDRESS)
@@ -351,7 +353,7 @@ DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolCont
strm.PutCString(" in ");
}
}
- sc.DumpStopContext(&strm, interpreter.GetDebugger().GetExecutionContext().process, sc.line_entry.range.GetBaseAddress(), true, true, false);
+ sc.DumpStopContext(&strm, interpreter.GetExecutionContext().process, sc.line_entry.range.GetBaseAddress(), true, true, false);
}
}
strm.IndentLess ();
@@ -1050,7 +1052,7 @@ public:
}
else
{
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
uint32_t total_num_dumped = 0;
uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
@@ -1233,9 +1235,11 @@ public:
Module *module = target->GetImages().GetModulePointerAtIndex(image_idx);
strm.Printf("[%3u] ", image_idx);
+ bool dump_object_name = false;
if (m_options.m_format_array.empty())
{
DumpFullpath(strm, &module->GetFileSpec(), 0);
+ dump_object_name = true;
}
else
{
@@ -1254,6 +1258,7 @@ public:
case 'f':
DumpFullpath (strm, &module->GetFileSpec(), width);
+ dump_object_name = true;
break;
case 'd':
@@ -1262,6 +1267,7 @@ public:
case 'b':
DumpBasename (strm, &module->GetFileSpec(), width);
+ dump_object_name = true;
break;
case 's':
@@ -1277,6 +1283,7 @@ public:
DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
else
DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
+ dump_object_name = true;
break;
}
}
@@ -1291,8 +1298,15 @@ public:
default:
break;
}
+
}
}
+ if (dump_object_name)
+ {
+ const char *object_name = module->GetObjectName().GetCString();
+ if (object_name)
+ strm.Printf ("(%s)", object_name);
+ }
strm.EOL();
}
result.SetStatus (eReturnStatusSuccessFinishResult);
@@ -1682,16 +1696,16 @@ protected:
OptionDefinition
CommandObjectImageLookup::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddress, "Lookup an address in one or more executable images."},
-{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."},
-{ LLDB_OPT_SET_2, true, "symbol", 's', required_argument, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more executable images."},
-{ LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."},
-{ LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more executable images."},
-{ LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."},
-{ LLDB_OPT_SET_3, false, "no-inlines", 'i', no_argument, NULL, 0, eArgTypeNone, "Check inline line entries (must be used in conjunction with --file)."},
-{ LLDB_OPT_SET_4, true, "function", 'n', required_argument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more executable images."},
-{ LLDB_OPT_SET_5, true, "type", 't', required_argument, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more executable images."},
-{ LLDB_OPT_SET_ALL, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."},
+{ LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddress, "Lookup an address in one or more executable images."},
+{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."},
+{ LLDB_OPT_SET_2, true, "symbol", 's', required_argument, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more executable images."},
+{ LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."},
+{ LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more executable images."},
+{ LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."},
+{ LLDB_OPT_SET_3, false, "no-inlines", 'i', no_argument, NULL, 0, eArgTypeNone, "Check inline line entries (must be used in conjunction with --file)."},
+{ LLDB_OPT_SET_4, true, "function", 'n', required_argument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more executable images."},
+{ LLDB_OPT_SET_5, true, "type", 't', required_argument, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more executable images."},
+{ LLDB_OPT_SET_ALL, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."},
{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
};
diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp
index c731c61836c..7993f5462eb 100644
--- a/lldb/source/Commands/CommandObjectMemory.cpp
+++ b/lldb/source/Commands/CommandObjectMemory.cpp
@@ -240,7 +240,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError("need a process to read memory");
@@ -415,7 +415,7 @@ CommandObjectMemoryRead::CommandOptions::g_option_table[] =
{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
{ SET1 , false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes to use when displaying with the selected format."},
{ SET1 , false, "num-per-line", 'l', required_argument, NULL, 0, eArgTypeNumberPerLine,"The number of items per line to display."},
-{ SET1 , false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of total items to display."},
+{ SET1 | SET2, false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of total items to display."},
{ SET1 | SET2, false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename, "Dump memory read results into a file."},
{ SET1 | SET2, false, "append", 'a', no_argument, NULL, 0, eArgTypeNone, "Append memory read results to 'outfile'."},
{ SET2, false, "binary", 'b', no_argument, NULL, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
@@ -591,7 +591,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError("need a process to read memory");
diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp
index a72b0db4d14..730a1b3dd01 100644
--- a/lldb/source/Commands/CommandObjectPlatform.cpp
+++ b/lldb/source/Commands/CommandObjectPlatform.cpp
@@ -413,6 +413,134 @@ public:
return result.Succeeded();
}
};
+//----------------------------------------------------------------------
+// "platform process launch"
+//----------------------------------------------------------------------
+class CommandObjectPlatformProcessLaunch : public CommandObject
+{
+public:
+ CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
+ CommandObject (interpreter,
+ "platform process launch",
+ "Launch a new process on a remote platform.",
+ "platform process launch program",
+ 0),
+ m_options (interpreter)
+ {
+ }
+
+ virtual
+ ~CommandObjectPlatformProcessLaunch ()
+ {
+ }
+
+ virtual bool
+ Execute (Args& args, CommandReturnObject &result)
+ {
+ PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
+
+ if (platform_sp)
+ {
+ Error error;
+ const uint32_t argc = args.GetArgumentCount();
+ Target *target = m_interpreter.GetExecutionContext().target;
+ ModuleSP exe_module_sp;
+ if (target)
+ {
+ exe_module_sp = target->GetExecutableModule();
+ if (exe_module_sp)
+ {
+ m_options.launch_info.GetExecutableFile () = exe_module_sp->GetFileSpec();
+ char exe_path[PATH_MAX];
+ if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
+ m_options.launch_info.GetArguments().AppendArgument (exe_path);
+ m_options.launch_info.GetArchitecture() = exe_module_sp->GetArchitecture();
+ }
+ }
+
+ if (argc > 0)
+ {
+ if (m_options.launch_info.GetExecutableFile ())
+ {
+ // We already have an executable file, so we will use this
+ // and all arguments to this function are extra arguments
+ m_options.launch_info.GetArguments().AppendArguments (args);
+ }
+ else
+ {
+ // We don't have any file yet, so the first argument is our
+ // executable, and the rest are program arguments
+ const bool first_arg_is_executable = true;
+ m_options.launch_info.SetArgumentsFromArgs (args,
+ first_arg_is_executable,
+ first_arg_is_executable);
+ }
+ }
+
+ if (m_options.launch_info.GetExecutableFile ())
+ {
+ Debugger &debugger = m_interpreter.GetDebugger();
+
+ if (argc == 0)
+ {
+ lldb::UserSettingsControllerSP process_usc_sp (Process::GetSettingsController ());
+ if (process_usc_sp)
+ {
+ SettableVariableType type;
+ StringList settings_args (process_usc_sp->GetVariable ("process.run-args",
+ type,
+ m_interpreter.GetDebugger().GetInstanceName().GetCString(),
+ error));
+ if (error.Success())
+ {
+ const size_t num_settings_args = settings_args.GetSize();
+ for (size_t i=0; i<num_settings_args; ++i)
+ m_options.launch_info.GetArguments().AppendArgument (settings_args.GetStringAtIndex(i));
+ }
+ }
+ }
+
+ ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
+ debugger,
+ target,
+ debugger.GetListener(),
+ error));
+ if (process_sp && process_sp->IsAlive())
+ {
+ result.SetStatus (eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+ if (error.Success())
+ result.AppendError ("process launch failed");
+ else
+ result.AppendError (error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ }
+ else
+ {
+ result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ else
+ {
+ result.AppendError ("no platform is selected\n");
+ }
+ return result.Succeeded();
+ }
+
+ virtual Options *
+ GetOptions ()
+ {
+ return &m_options;
+ }
+
+protected:
+ ProcessLaunchCommandOptions m_options;
+};
+
//----------------------------------------------------------------------
@@ -454,11 +582,11 @@ public:
lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
if (pid != LLDB_INVALID_PROCESS_ID)
{
- ProcessInfo proc_info;
+ ProcessInstanceInfo proc_info;
if (platform_sp->GetProcessInfo (pid, proc_info))
{
- ProcessInfo::DumpTableHeader (ostrm, platform_sp.get());
- proc_info.DumpAsTableRow(ostrm, platform_sp.get());
+ ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
+ proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
result.SetStatus (eReturnStatusSuccessFinishResult);
}
else
@@ -469,24 +597,25 @@ public:
}
else
{
- ProcessInfoList proc_infos;
+ ProcessInstanceInfoList proc_infos;
const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
- if (matches == 0)
+ const char *match_desc = NULL;
+ const char *match_name = m_options.match_info.GetProcessInfo().GetName();
+ if (match_name && match_name[0])
{
- const char *match_desc = NULL;
- const char *match_name = m_options.match_info.GetProcessInfo().GetName();
- if (match_name && match_name[0])
+ switch (m_options.match_info.GetNameMatchType())
{
- switch (m_options.match_info.GetNameMatchType())
- {
- case eNameMatchIgnore: break;
- case eNameMatchEquals: match_desc = "match"; break;
- case eNameMatchContains: match_desc = "contains"; break;
- case eNameMatchStartsWith: match_desc = "starts with"; break;
- case eNameMatchEndsWith: match_desc = "end with"; break;
- case eNameMatchRegularExpression: match_desc = "match the regular expression"; break;
- }
+ case eNameMatchIgnore: break;
+ case eNameMatchEquals: match_desc = "matched"; break;
+ case eNameMatchContains: match_desc = "contained"; break;
+ case eNameMatchStartsWith: match_desc = "started with"; break;
+ case eNameMatchEndsWith: match_desc = "ended with"; break;
+ case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
}
+ }
+
+ if (matches == 0)
+ {
if (match_desc)
result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
match_desc,
@@ -498,11 +627,19 @@ public:
}
else
{
-
- ProcessInfo::DumpTableHeader (ostrm, platform_sp.get());
+ result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
+ matches,
+ matches > 1 ? "es were" : " was",
+ platform_sp->GetName());
+ if (match_desc)
+ result.AppendMessageWithFormat (" whose name %s \"%s\"",
+ match_desc,
+ match_name);
+ result.AppendMessageWithFormat ("\n");
+ ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
for (uint32_t i=0; i<matches; ++i)
{
- proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get());
+ proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
}
}
}
@@ -567,7 +704,7 @@ protected:
break;
case 'u':
- match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
break;
@@ -579,7 +716,7 @@ protected:
break;
case 'g':
- match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
if (!success)
error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
break;
@@ -596,26 +733,37 @@ protected:
case 'n':
match_info.GetProcessInfo().SetName (option_arg);
- if (match_info.GetNameMatchType() == eNameMatchIgnore)
- match_info.SetNameMatchType (eNameMatchEquals);
+ match_info.SetNameMatchType (eNameMatchEquals);
break;
case 'e':
+ match_info.GetProcessInfo().SetName (option_arg);
match_info.SetNameMatchType (eNameMatchEndsWith);
break;
case 's':
+ match_info.GetProcessInfo().SetName (option_arg);
match_info.SetNameMatchType (eNameMatchStartsWith);
break;
case 'c':
+ match_info.GetProcessInfo().SetName (option_arg);
match_info.SetNameMatchType (eNameMatchContains);
break;
case 'r':
+ match_info.GetProcessInfo().SetName (option_arg);
match_info.SetNameMatchType (eNameMatchRegularExpression);
break;
+ case 'A':
+ show_args = true;
+ break;
+
+ case 'v':
+ verbose = true;
+ break;
+
default:
error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
break;
@@ -628,6 +776,8 @@ protected:
ResetOptionValues ()
{
match_info.Clear();
+ show_args = false;
+ verbose = false;
}
const OptionDefinition*
@@ -642,7 +792,9 @@ protected:
// Instance variables to hold the values for command options.
- ProcessInfoMatch match_info;
+ ProcessInstanceInfoMatch match_info;
+ bool show_args;
+ bool verbose;
};
CommandOptions m_options;
};
@@ -650,49 +802,23 @@ protected:
OptionDefinition
CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
{
-{ LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes that match the supplied name." },
-{ LLDB_OPT_SET_2, false, "ends-with" , 'e', no_argument , NULL, 0, eArgTypeNone , "Process names must end with the name supplied with the --name option." },
-{ LLDB_OPT_SET_3, false, "starts-with" , 's', no_argument , NULL, 0, eArgTypeNone , "Process names must start with the name supplied with the --name option." },
-{ LLDB_OPT_SET_4, false, "contains" , 'c', no_argument , NULL, 0, eArgTypeNone , "Process names must contain the name supplied with the --name option." },
-{ LLDB_OPT_SET_5, false, "regex" , 'r', no_argument , NULL, 0, eArgTypeNone , "Process names must match name supplied with the --name option as a regular expression." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5|
- LLDB_OPT_SET_6, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5|
- LLDB_OPT_SET_6, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5|
- LLDB_OPT_SET_6, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5|
- LLDB_OPT_SET_6, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5|
- LLDB_OPT_SET_6, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." },
-{ LLDB_OPT_SET_2|
- LLDB_OPT_SET_3|
- LLDB_OPT_SET_4|
- LLDB_OPT_SET_5|
- LLDB_OPT_SET_6, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
-{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
+{ LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
+{ LLDB_OPT_SET_2, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
+{ LLDB_OPT_SET_3, true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that end with a string." },
+{ LLDB_OPT_SET_4, true , "starts-with" , 's', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that start with a string." },
+{ LLDB_OPT_SET_5, true , "contains" , 'c', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that contain a string." },
+{ LLDB_OPT_SET_6, true , "regex" , 'r', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that match a regular expression." },
+{ ~LLDB_OPT_SET_1, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
+{ ~LLDB_OPT_SET_1, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." },
+{ ~LLDB_OPT_SET_1, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." },
+{ ~LLDB_OPT_SET_1, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." },
+{ ~LLDB_OPT_SET_1, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." },
+{ ~LLDB_OPT_SET_1, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
+{ LLDB_OPT_SET_ALL, false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
+{ LLDB_OPT_SET_ALL, false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." },
+{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
};
-
//----------------------------------------------------------------------
// "platform process info"
//----------------------------------------------------------------------
@@ -746,7 +872,7 @@ public:
lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
if (success)
{
- ProcessInfo proc_info;
+ ProcessInstanceInfo proc_info;
if (platform_sp->GetProcessInfo (pid, proc_info))
{
ostrm.Printf ("Process information for process %i:\n", pid);
@@ -805,7 +931,7 @@ public:
"platform process [attach|launch|list] ...")
{
// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
-// LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
+ LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 116309d94d5..1fc573b9266 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -175,7 +175,7 @@ public:
exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
StateType state = eStateInvalid;
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process)
{
state = process->GetState();
@@ -266,7 +266,10 @@ public:
if (process->GetDisableASLR())
launch_flags |= eLaunchFlagDisableASLR;
-
+
+ if (m_options.in_new_tty)
+ launch_flags |= eLaunchFlagLaunchInTTY;
+
if (m_options.no_stdio)
launch_flags |= eLaunchFlagDisableSTDIO;
else if (!m_options.in_new_tty
@@ -287,52 +290,35 @@ public:
if (!m_options.working_dir.empty())
working_dir = m_options.working_dir.c_str();
- if (m_options.in_new_tty)
+ const char * stdin_path = NULL;
+ const char * stdout_path = NULL;
+ const char * stderr_path = NULL;
+
+ // Were any standard input/output/error paths given on the command line?
+ if (m_options.stdin_path.empty() &&
+ m_options.stdout_path.empty() &&
+ m_options.stderr_path.empty())
{
-
- lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
- inferior_argv,
- inferior_envp,
- working_dir,
- &exe_module->GetArchitecture(),
- true,
- process->GetDisableASLR());
-
- if (pid != LLDB_INVALID_PROCESS_ID)
- error = process->Attach (pid);
+ // No standard file handles were given on the command line, check
+ // with the process object in case they were give using "set settings"
+ stdin_path = process->GetStandardInputPath();
+ stdout_path = process->GetStandardOutputPath();
+ stderr_path = process->GetStandardErrorPath();
}
else
{
- const char * stdin_path = NULL;
- const char * stdout_path = NULL;
- const char * stderr_path = NULL;
-
- // Were any standard input/output/error paths given on the command line?
- if (m_options.stdin_path.empty() &&
- m_options.stdout_path.empty() &&
- m_options.stderr_path.empty())
- {
- // No standard file handles were given on the command line, check
- // with the process object in case they were give using "set settings"
- stdin_path = process->GetStandardInputPath();
- stdout_path = process->GetStandardOutputPath();
- stderr_path = process->GetStandardErrorPath();
- }
- else
- {
- stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
- stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
- stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
- }
-
- error = process->Launch (inferior_argv,
- inferior_envp,
- launch_flags,
- stdin_path,
- stdout_path,
- stderr_path,
- working_dir);
+ stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
+ stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
+ stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
}
+
+ error = process->Launch (inferior_argv,
+ inferior_envp,
+ launch_flags,
+ stdin_path,
+ stdout_path,
+ stderr_path,
+ working_dir);
if (error.Success())
{
@@ -521,11 +507,11 @@ public:
const char *partial_name = NULL;
partial_name = input.GetArgumentAtIndex(opt_arg_pos);
- PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform ());
+ PlatformSP platform_sp (m_interpreter.GetPlatform (true));
if (platform_sp)
{
- ProcessInfoList process_infos;
- ProcessInfoMatch match_info;
+ ProcessInstanceInfoList process_infos;
+ ProcessInstanceInfoMatch match_info;
if (partial_name)
{
match_info.GetProcessInfo().SetName(partial_name);
@@ -579,7 +565,7 @@ public:
Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
bool synchronous_execution = m_interpreter.GetSynchronous ();
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
StateType state = eStateInvalid;
if (process)
{
@@ -707,11 +693,11 @@ public:
if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
{
- ProcessInfoList process_infos;
- PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform ());
+ ProcessInstanceInfoList process_infos;
+ PlatformSP platform_sp (m_interpreter.GetPlatform (true));
if (platform_sp)
{
- ProcessInfoMatch match_info (wait_name, eNameMatchEquals);
+ ProcessInstanceInfoMatch match_info (wait_name, eNameMatchEquals);
platform_sp->FindProcesses (match_info, process_infos);
}
if (process_infos.GetSize() > 1)
@@ -860,7 +846,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
bool synchronous_execution = m_interpreter.GetSynchronous ();
if (process == NULL)
@@ -947,7 +933,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("must have a valid process in order to detach");
@@ -1057,7 +1043,7 @@ public:
TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
Error error;
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process)
{
if (process->IsAlive())
@@ -1172,7 +1158,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("must have a valid process in order to load a shared library");
@@ -1230,7 +1216,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("must have a valid process in order to load a shared library");
@@ -1307,7 +1293,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("no process to signal");
@@ -1382,7 +1368,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("no process to halt");
@@ -1444,7 +1430,7 @@ public:
Execute (Args& command,
CommandReturnObject &result)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("no process to kill");
@@ -1507,7 +1493,7 @@ public:
{
Stream &output_stream = result.GetOutputStream();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.process)
{
const StateType state = exe_ctx.process->GetState();
diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp
index d50d7d71ecf..2607854ed2e 100644
--- a/lldb/source/Commands/CommandObjectRegister.cpp
+++ b/lldb/source/Commands/CommandObjectRegister.cpp
@@ -75,7 +75,7 @@ public:
{
Stream &output_stream = result.GetOutputStream();
DataExtractor reg_data;
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
if (reg_context)
@@ -274,7 +274,7 @@ public:
)
{
DataExtractor reg_data;
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
RegisterContext *reg_context = exe_ctx.GetRegisterContext ();
if (reg_context)
diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp
index 9fbf6024a39..29b17dc1d42 100644
--- a/lldb/source/Commands/CommandObjectSource.cpp
+++ b/lldb/source/Commands/CommandObjectSource.cpp
@@ -272,7 +272,7 @@ public:
result.SetStatus (eReturnStatusFailed);
}
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (!m_options.symbol_name.empty())
{
diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index abb6f5f1cef..f321000768d 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -362,7 +362,7 @@ public:
if (command.GetArgumentCount() == 0)
{
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.thread)
{
if (DisplayFramesForExecutionContext (exe_ctx.thread,
@@ -386,7 +386,7 @@ public:
}
else if (command.GetArgumentCount() == 1 && ::strcmp (command.GetArgumentAtIndex(0), "all") == 0)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
uint32_t num_threads = process->GetThreadList().GetSize();
for (uint32_t i = 0; i < num_threads; i++)
{
@@ -412,7 +412,7 @@ public:
else
{
uint32_t num_args = command.GetArgumentCount();
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
std::vector<ThreadSP> thread_sps;
for (uint32_t i = 0; i < num_args; i++)
@@ -610,7 +610,7 @@ public:
CommandReturnObject &result
)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
bool synchronous_execution = m_interpreter.GetSynchronous();
if (process == NULL)
@@ -851,7 +851,7 @@ public:
return false;
}
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("no process exists. Cannot continue");
@@ -1115,7 +1115,7 @@ public:
return false;
}
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("need a valid process to step");
@@ -1308,7 +1308,7 @@ public:
CommandReturnObject &result
)
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("no process");
@@ -1378,7 +1378,7 @@ public:
{
Stream &strm = result.GetOutputStream();
result.SetStatus (eReturnStatusSuccessFinishNoResult);
- ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
+ ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
if (exe_ctx.process)
{
const StateType state = exe_ctx.process->GetState();
diff --git a/lldb/source/Core/ConnectionFileDescriptor.cpp b/lldb/source/Core/ConnectionFileDescriptor.cpp
index e5b27bc8624..ce306c90e4d 100644
--- a/lldb/source/Core/ConnectionFileDescriptor.cpp
+++ b/lldb/source/Core/ConnectionFileDescriptor.cpp
@@ -459,6 +459,41 @@ ConnectionFileDescriptor::NamedSocketAccept (const char *socket_name, Error *err
}
ConnectionStatus
+ConnectionFileDescriptor::NamedSocketConnect (const char *socket_name, Error *error_ptr)
+{
+ Close (m_fd, NULL);
+ m_is_socket = true;
+
+ // Open the socket that was passed in as an option
+ struct sockaddr_un saddr_un;
+ m_fd = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (m_fd == -1)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorToErrno();
+ return eConnectionStatusError;
+ }
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, socket_name, sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+#if defined(__APPLE__) || defined(__FreeBSD__)
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+#endif
+
+ if (::connect (m_fd, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ {
+ if (error_ptr)
+ error_ptr->SetErrorToErrno();
+ Close (m_fd, NULL);
+ return eConnectionStatusError;
+ }
+ if (error_ptr)
+ error_ptr->Clear();
+ return eConnectionStatusSuccess;
+}
+
+ConnectionStatus
ConnectionFileDescriptor::SocketListen (uint16_t listen_port_num, Error *error_ptr)
{
lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_CONNECTION,
diff --git a/lldb/source/Core/Debugger.cpp b/lldb/source/Core/Debugger.cpp
index ca0dde920bd..073986ac3a9 100644
--- a/lldb/source/Core/Debugger.cpp
+++ b/lldb/source/Core/Debugger.cpp
@@ -229,7 +229,6 @@ Debugger::Debugger () :
m_listener ("lldb.Debugger"),
m_source_manager (),
m_command_interpreter_ap (new CommandInterpreter (*this, eScriptLanguageDefault, false)),
- m_exe_ctx (),
m_input_readers (),
m_input_reader_data ()
{
@@ -556,51 +555,6 @@ Debugger::ActivateInputReader (const InputReaderSP &reader_sp)
}
}
-void
-Debugger::UpdateExecutionContext (ExecutionContext *override_context)
-{
- m_exe_ctx.Clear();
-
- if (override_context != NULL)
- {
- m_exe_ctx.target = override_context->target;
- m_exe_ctx.process = override_context->process;
- m_exe_ctx.thread = override_context->thread;
- m_exe_ctx.frame = override_context->frame;
- }
- else
- {
- TargetSP target_sp (GetSelectedTarget());
- if (target_sp)
- {
- m_exe_ctx.target = target_sp.get();
- m_exe_ctx.process = target_sp->GetProcessSP().get();
- if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning())
- {
- m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get();
- if (m_exe_ctx.thread == NULL)
- {
- m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
- // If we didn't have a selected thread, select one here.
- if (m_exe_ctx.thread != NULL)
- m_exe_ctx.process->GetThreadList().SetSelectedThreadByID(m_exe_ctx.thread->GetID());
- }
- if (m_exe_ctx.thread)
- {
- m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get();
- if (m_exe_ctx.frame == NULL)
- {
- m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
- // If we didn't have a selected frame select one here.
- if (m_exe_ctx.frame != NULL)
- m_exe_ctx.thread->SetSelectedFrame(m_exe_ctx.frame);
- }
- }
- }
- }
- }
-}
-
DebuggerSP
Debugger::FindDebuggerWithID (lldb::user_id_t id)
{
diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp
index 7ceff588d16..0b314651a89 100644
--- a/lldb/source/Core/Module.cpp
+++ b/lldb/source/Core/Module.cpp
@@ -28,6 +28,7 @@ Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstStrin
m_file (file_spec),
m_platform_file(),
m_object_name (),
+ m_object_offset (object_offset),
m_objfile_ap (),
m_symfile_ap (),
m_ast (),
@@ -534,7 +535,7 @@ Module::GetObjectFile()
m_did_load_objfile = true;
Timer scoped_timer(__PRETTY_FUNCTION__,
"Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString(""));
- m_objfile_ap.reset(ObjectFile::FindPlugin(this, &m_file, 0, m_file.GetByteSize()));
+ m_objfile_ap.reset(ObjectFile::FindPlugin(this, &m_file, m_object_offset, m_file.GetByteSize()));
}
return m_objfile_ap.get();
}
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index e2e0aa2a075..18f3bbf5bc7 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -63,36 +63,46 @@ ModuleList::~ModuleList()
void
ModuleList::Append (ModuleSP &module_sp)
{
- Mutex::Locker locker(m_modules_mutex);
- m_modules.push_back(module_sp);
+ if (module_sp)
+ {
+ Mutex::Locker locker(m_modules_mutex);
+ m_modules.push_back(module_sp);
+ }
}
bool
ModuleList::AppendIfNeeded (ModuleSP &module_sp)
{
- Mutex::Locker locker(m_modules_mutex);
- collection::iterator pos, end = m_modules.end();
- for (pos = m_modules.begin(); pos != end; ++pos)
+ if (module_sp)
{
- if (pos->get() == module_sp.get())
- return false; // Already in the list
+ Mutex::Locker locker(m_modules_mutex);
+ collection::iterator pos, end = m_modules.end();
+ for (pos = m_modules.begin(); pos != end; ++pos)
+ {
+ if (pos->get() == module_sp.get())
+ return false; // Already in the list
+ }
+ // Only push module_sp on the list if it wasn't already in there.
+ m_modules.push_back(module_sp);
+ return true;
}
- // Only push module_sp on the list if it wasn't already in there.
- m_modules.push_back(module_sp);
- return true;
+ return false;
}
bool
ModuleList::Remove (ModuleSP &module_sp)
{
- Mutex::Locker locker(m_modules_mutex);
- collection::iterator pos, end = m_modules.end();
- for (pos = m_modules.begin(); pos != end; ++pos)
+ if (module_sp)
{
- if (pos->get() == module_sp.get())
+ Mutex::Locker locker(m_modules_mutex);
+ collection::iterator pos, end = m_modules.end();
+ for (pos = m_modules.begin(); pos != end; ++pos)
{
- m_modules.erase (pos);
- return true;
+ if (pos->get() == module_sp.get())
+ {
+ m_modules.erase (pos);
+ return true;
+ }
}
}
return false;
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp
index 5d984020da2..a6654722779 100644
--- a/lldb/source/Host/common/Host.cpp
+++ b/lldb/source/Host/common/Host.cpp
@@ -1138,14 +1138,14 @@ Host::GetOSKernelDescription (std::string &s)
}
uint32_t
-Host::FindProcesses (const ProcessInfoMatch &match_info, ProcessInfoList &process_infos)
+Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
{
process_infos.Clear();
return process_infos.GetSize();
}
bool
-Host::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
process_info.Clear();
return false;
diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm
index 65d60d748ec..28d8d81bb67 100644
--- a/lldb/source/Host/macosx/Host.mm
+++ b/lldb/source/Host/macosx/Host.mm
@@ -14,6 +14,7 @@
#include <grp.h>
#include <libproc.h>
#include <pwd.h>
+#include <spawn.h>
#include <stdio.h>
#include <sys/proc.h>
#include <sys/stat.h>
@@ -25,12 +26,15 @@
#include "lldb/Core/Communication.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/DataExtractor.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/Endian.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/CleanUp.h"
#include "cfcpp/CFCBundle.h"
#include "cfcpp/CFCMutableArray.h"
@@ -47,6 +51,10 @@
#include <Carbon/Carbon.h>
#include <Foundation/Foundation.h>
+#ifndef _POSIX_SPAWN_DISABLE_ASLR
+#define _POSIX_SPAWN_DISABLE_ASLR 0x0100
+#endif
+
using namespace lldb;
using namespace lldb_private;
@@ -414,57 +422,64 @@ tell application \"Terminal\"\n\
do script the_shell_script\n\
end tell\n";
-lldb::pid_t
-LaunchInNewTerminalWithAppleScript
-(
- const char *tty_name,
- const char **argv,
- const char **envp,
- const char *working_dir,
- const ArchSpec *arch_spec,
- bool stop_at_entry,
- bool disable_aslr
-)
+static Error
+LaunchInNewTerminalWithAppleScript (const char *exe_path,
+ ProcessLaunchInfo &launch_info)
{
- if (!argv || !argv[0])
- return LLDB_INVALID_PROCESS_ID;
+ Error error;
+ if (exe_path == NULL || exe_path[0] == '\0')
+ {
+ error.SetErrorString ("invalid executable path");
+ return error;
+ }
- std::string unix_socket_name;
-
- char temp_file_path[PATH_MAX] = "/tmp/XXXXXX";
- if (::mktemp (temp_file_path) == NULL)
- return LLDB_INVALID_PROCESS_ID;
-
- unix_socket_name.assign (temp_file_path);
+ char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
+ if (::mktemp (unix_socket_name) == NULL)
+ {
+ error.SetErrorString ("failed to make temporary path for a unix socket");
+ return error;
+ }
StreamString command;
FileSpec darwin_debug_file_spec;
if (!Host::GetLLDBPath (ePathTypeSupportExecutableDir, darwin_debug_file_spec))
- return LLDB_INVALID_PROCESS_ID;
+ {
+ error.SetErrorString ("can't locate the 'darwin-debug' executable");
+ return error;
+ }
+
darwin_debug_file_spec.GetFilename().SetCString("darwin-debug");
if (!darwin_debug_file_spec.Exists())
- return LLDB_INVALID_PROCESS_ID;
+ {
+ error.SetErrorStringWithFormat ("the 'darwin-debug' executable doesn't exists at %s/%s",
+ darwin_debug_file_spec.GetDirectory().GetCString(),
+ darwin_debug_file_spec.GetFilename().GetCString());
+ return error;
+ }
char launcher_path[PATH_MAX];
darwin_debug_file_spec.GetPath(launcher_path, sizeof(launcher_path));
- if (arch_spec)
- command.Printf("arch -arch %s ", arch_spec->GetArchitectureName());
+ const ArchSpec &arch_spec = launch_info.GetArchitecture();
+ if (arch_spec.IsValid())
+ command.Printf("arch -arch %s ", arch_spec.GetArchitectureName());
- command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name.c_str());
+ command.Printf("'%s' --unix-socket=%s", launcher_path, unix_socket_name);
- if (arch_spec && arch_spec->IsValid())
- command.Printf(" --arch=%s", arch_spec->GetArchitectureName());
+ if (arch_spec.IsValid())
+ command.Printf(" --arch=%s", arch_spec.GetArchitectureName());
+ const char *working_dir = launch_info.GetWorkingDirectory();
if (working_dir)
command.Printf(" --working-dir '%s'", working_dir);
- if (disable_aslr)
+ if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
command.PutCString(" --disable-aslr");
- command.PutCString(" --");
+ command.Printf(" -- '%s'", exe_path);
+ const char **argv = launch_info.GetArguments().GetConstArgumentVector ();
if (argv)
{
for (size_t i=0; argv[i] != NULL; ++i)
@@ -477,17 +492,17 @@ LaunchInNewTerminalWithAppleScript
StreamString applescript_source;
const char *tty_command = command.GetString().c_str();
- if (tty_name && tty_name[0])
- {
- applescript_source.Printf (applscript_in_existing_tty,
- tty_command,
- tty_name);
- }
- else
- {
+// if (tty_name && tty_name[0])
+// {
+// applescript_source.Printf (applscript_in_existing_tty,
+// tty_command,
+// tty_name);
+// }
+// else
+// {
applescript_source.Printf (applscript_in_new_tty,
tty_command);
- }
+// }
@@ -501,11 +516,15 @@ LaunchInNewTerminalWithAppleScript
// Sleep and wait a bit for debugserver to start to listen...
ConnectionFileDescriptor file_conn;
char connect_url[128];
- ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name.c_str());
+ ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
// Spawn a new thread to accept incoming connection on the connect_url
- // so we can grab the pid from the inferior
- lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name.c_str(),
+ // so we can grab the pid from the inferior. We have to do this because we
+ // are sending an AppleScript that will launch a process in Terminal.app,
+ // in a shell and the shell will fork/exec a couple of times before we get
+ // to the process that we wanted to launch. So when our process actually
+ // gets launched, we will handshake with it and get the process ID for it.
+ lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
AcceptPIDFromInferior,
connect_url,
&lldb_error);
@@ -526,33 +545,14 @@ LaunchInNewTerminalWithAppleScript
WaitForProcessToSIGSTOP (pid, 5);
}
}
- ::unlink (unix_socket_name.c_str());
+ ::unlink (unix_socket_name);
[applescript release];
- return pid;
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ launch_info.SetProcessID (pid);
+ return error;
}
-#define LLDB_HOST_USE_APPLESCRIPT
-
-lldb::pid_t
-Host::LaunchInNewTerminal
-(
- const char *tty_name,
- const char **argv,
- const char **envp,
- const char *working_dir,
- const ArchSpec *arch_spec,
- bool stop_at_entry,
- bool disable_aslr
-)
-{
-#if defined (LLDB_HOST_USE_APPLESCRIPT)
- return LaunchInNewTerminalWithAppleScript (tty_name, argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
-#else
- return LaunchInNewTerminalWithCommandFile (argv, envp, working_dir, arch_spec, stop_at_entry, disable_aslr);
-#endif
-}
-
// On MacOSX CrashReporter will display a string for each shared library if
// the shared library has an exported symbol named "__crashreporter_info__".
@@ -914,8 +914,8 @@ Host::GetOSVersion
}
static bool
-GetMacOSXProcessName (const ProcessInfoMatch *match_info_ptr,
- ProcessInfo &process_info)
+GetMacOSXProcessName (const ProcessInstanceInfoMatch *match_info_ptr,
+ ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid())
{
@@ -938,7 +938,7 @@ GetMacOSXProcessName (const ProcessInfoMatch *match_info_ptr,
static bool
-GetMacOSXProcessCPUType (ProcessInfo &process_info)
+GetMacOSXProcessCPUType (ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid())
{
@@ -970,8 +970,8 @@ GetMacOSXProcessCPUType (ProcessInfo &process_info)
}
static bool
-GetMacOSXProcessArgs (const ProcessInfoMatch *match_info_ptr,
- ProcessInfo &process_info)
+GetMacOSXProcessArgs (const ProcessInstanceInfoMatch *match_info_ptr,
+ ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid())
{
@@ -1006,13 +1006,13 @@ GetMacOSXProcessArgs (const ProcessInfoMatch *match_info_ptr,
++offset;
}
// Now extract all arguments
- StringList &proc_args = process_info.GetArguments();
+ Args &proc_args = process_info.GetArguments();
for (int i=0; i<argc; ++i)
{
start_offset = offset;
cstr = data.GetCStr(&offset);
if (cstr)
- proc_args.AppendString (cstr, offset - start_offset);
+ proc_args.AppendArgument(cstr);
}
return true;
}
@@ -1023,7 +1023,7 @@ GetMacOSXProcessArgs (const ProcessInfoMatch *match_info_ptr,
}
static bool
-GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
+GetMacOSXProcessUserAndGroup (ProcessInstanceInfo &process_info)
{
if (process_info.ProcessIDIsValid())
{
@@ -1040,8 +1040,8 @@ GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
if (proc_kinfo_size > 0)
{
process_info.SetParentProcessID (proc_kinfo.kp_eproc.e_ppid);
- process_info.SetRealUserID (proc_kinfo.kp_eproc.e_pcred.p_ruid);
- process_info.SetRealGroupID (proc_kinfo.kp_eproc.e_pcred.p_rgid);
+ process_info.SetUserID (proc_kinfo.kp_eproc.e_pcred.p_ruid);
+ process_info.SetGroupID (proc_kinfo.kp_eproc.e_pcred.p_rgid);
process_info.SetEffectiveUserID (proc_kinfo.kp_eproc.e_ucred.cr_uid);
if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
process_info.SetEffectiveGroupID (proc_kinfo.kp_eproc.e_ucred.cr_groups[0]);
@@ -1052,8 +1052,8 @@ GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
}
}
process_info.SetParentProcessID (LLDB_INVALID_PROCESS_ID);
- process_info.SetRealUserID (UINT32_MAX);
- process_info.SetRealGroupID (UINT32_MAX);
+ process_info.SetUserID (UINT32_MAX);
+ process_info.SetGroupID (UINT32_MAX);
process_info.SetEffectiveUserID (UINT32_MAX);
process_info.SetEffectiveGroupID (UINT32_MAX);
return false;
@@ -1061,7 +1061,7 @@ GetMacOSXProcessUserAndGroup (ProcessInfo &process_info)
uint32_t
-Host::FindProcesses (const ProcessInfoMatch &match_info, ProcessInfoList &process_infos)
+Host::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos)
{
std::vector<struct kinfo_proc> kinfos;
@@ -1104,11 +1104,11 @@ Host::FindProcesses (const ProcessInfoMatch &match_info, ProcessInfoList &proces
kinfo.kp_proc.p_flag & P_TRANSLATED) // Skip translated ppc (Rosetta)
continue;
- ProcessInfo process_info;
+ ProcessInstanceInfo process_info;
process_info.SetProcessID (kinfo.kp_proc.p_pid);
process_info.SetParentProcessID (kinfo.kp_eproc.e_ppid);
- process_info.SetRealUserID (kinfo.kp_eproc.e_pcred.p_ruid);
- process_info.SetRealGroupID (kinfo.kp_eproc.e_pcred.p_rgid);
+ process_info.SetUserID (kinfo.kp_eproc.e_pcred.p_ruid);
+ process_info.SetGroupID (kinfo.kp_eproc.e_pcred.p_rgid);
process_info.SetEffectiveUserID (kinfo.kp_eproc.e_ucred.cr_uid);
if (kinfo.kp_eproc.e_ucred.cr_ngroups > 0)
process_info.SetEffectiveGroupID (kinfo.kp_eproc.e_ucred.cr_groups[0]);
@@ -1130,7 +1130,7 @@ Host::FindProcesses (const ProcessInfoMatch &match_info, ProcessInfoList &proces
}
bool
-Host::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+Host::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
process_info.SetProcessID(pid);
if (GetMacOSXProcessArgs (NULL, process_info))
@@ -1144,3 +1144,194 @@ Host::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
}
+Error
+Host::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_HOST | LIBLLDB_LOG_PROCESS));
+ char exe_path[PATH_MAX];
+ PlatformSP host_platform_sp (Platform::GetDefaultPlatform ());
+
+ const ArchSpec &arch_spec = launch_info.GetArchitecture();
+
+ FileSpec exe_spec(launch_info.GetExecutableFile());
+
+ FileSpec::FileType file_type = exe_spec.GetFileType();
+ if (file_type != FileSpec::eFileTypeRegular)
+ {
+ lldb::ModuleSP exe_module_sp;
+ error = host_platform_sp->ResolveExecutable (exe_spec,
+ arch_spec,
+ exe_module_sp);
+
+ if (error.Fail())
+ return error;
+
+ if (exe_module_sp)
+ exe_spec = exe_module_sp->GetFileSpec();
+ }
+
+ if (exe_spec.Exists())
+ {
+ exe_spec.GetPath (exe_path, sizeof(exe_path));
+ }
+ else
+ {
+ launch_info.GetExecutableFile().GetPath (exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat ("executable doesn't exist: '%s'", exe_path);
+ return error;
+ }
+
+
+ if (launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
+ {
+#if !defined(__arm__)
+ return LaunchInNewTerminalWithAppleScript (exe_path, launch_info);
+#else
+ error.SetErrorString ("launching a processs in a new terminal is not supported on iOS devices");
+ return error;
+#endif
+ }
+
+ Error local_err; // Errors that don't affect the spawning.
+ posix_spawnattr_t attr;
+ error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
+
+ if (error.Fail() || log)
+ error.PutToLog(log.get(), "::posix_spawnattr_init ( &attr )");
+ if (error.Fail())
+ return error;
+
+ // Make a quick class that will cleanup the posix spawn attributes in case
+ // we return in the middle of this function.
+ lldb_utility::CleanUp <posix_spawnattr_t *, int> posix_spawnattr_cleanup(&attr, posix_spawnattr_destroy);
+
+ short flags = 0;
+ if (launch_info.GetFlags().Test (eLaunchFlagExec))
+ flags |= POSIX_SPAWN_SETEXEC; // Darwin specific posix_spawn flag
+
+ if (launch_info.GetFlags().Test (eLaunchFlagDebug))
+ flags |= POSIX_SPAWN_START_SUSPENDED; // Darwin specific posix_spawn flag
+
+ if (launch_info.GetFlags().Test (eLaunchFlagDisableASLR))
+ flags |= _POSIX_SPAWN_DISABLE_ASLR; // Darwin specific posix_spawn flag
+
+ 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);
+ if (error.Fail())
+ return error;
+
+#if !defined(__arm__)
+
+ // We don't need to do this for ARM, and we really shouldn't now that we
+ // have multiple CPU subtypes and no posix_spawnattr call that allows us
+ // to set which CPU subtype to launch...
+ cpu_type_t cpu = arch_spec.GetMachOCPUType();
+ if (cpu != 0 &&
+ cpu != UINT32_MAX &&
+ cpu != LLDB_INVALID_CPUTYPE)
+ {
+ size_t ocount = 0;
+ error.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu, &ocount), eErrorTypePOSIX);
+ if (error.Fail() || log)
+ error.PutToLog(log.get(), "::posix_spawnattr_setbinpref_np ( &attr, 1, cpu_type = 0x%8.8x, count => %zu )", cpu, ocount);
+
+ if (error.Fail() || ocount != 1)
+ return error;
+ }
+
+#endif
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ const char *tmp_argv[2];
+ char * const *argv = (char * const*)launch_info.GetArguments().GetConstArgumentVector();
+ char * const *envp = (char * const*)launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+ if (argv == NULL)
+ {
+ // posix_spawn gets very unhappy if it doesn't have at least the program
+ // name in argv[0]. One of the side affects I have noticed is the environment
+ // variables don't make it into the child process if "argv == NULL"!!!
+ tmp_argv[0] = exe_path;
+ tmp_argv[1] = NULL;
+ argv = (char * const*)tmp_argv;
+ }
+
+
+ const size_t num_file_actions = launch_info.GetNumFileActions ();
+ if (num_file_actions > 0)
+ {
+ posix_spawn_file_actions_t file_actions;
+ error.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
+ if (error.Fail() || log)
+ error.PutToLog(log.get(), "::posix_spawn_file_actions_init ( &file_actions )");
+ if (error.Fail())
+ return error;
+
+ // Make a quick class that will cleanup the posix spawn attributes in case
+ // we return in the middle of this function.
+ lldb_utility::CleanUp <posix_spawn_file_actions_t *, int> posix_spawn_file_actions_cleanup (&file_actions, posix_spawn_file_actions_destroy);
+
+ for (size_t i=0; i<num_file_actions; ++i)
+ {
+ const ProcessLaunchInfo::FileAction *launch_file_action = launch_info.GetFileActionAtIndex(i);
+ if (launch_file_action)
+ {
+ if (!ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (&file_actions,
+ launch_file_action,
+ log.get(),
+ error))
+ return error;
+ }
+ }
+
+ error.SetError (::posix_spawnp (&pid,
+ exe_path,
+ &file_actions,
+ &attr,
+ argv,
+ envp),
+ eErrorTypePOSIX);
+
+ if (error.Fail() || log)
+ error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )",
+ pid,
+ exe_path,
+ &file_actions,
+ &attr,
+ argv,
+ envp);
+ }
+ else
+ {
+ error.SetError (::posix_spawnp (&pid,
+ exe_path,
+ NULL,
+ &attr,
+ argv,
+ envp),
+ eErrorTypePOSIX);
+
+ if (error.Fail() || log)
+ error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = NULL, attr = %p, argv = %p, envp = %p )",
+ pid,
+ exe_path,
+ &attr,
+ argv,
+ envp);
+ }
+
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ // If all went well, then set the process ID into the launch info
+ launch_info.SetProcessID(pid);
+ }
+ else
+ {
+ // Invalid process ID, something didn't go well
+ if (error.Success())
+ error.SetErrorString ("process launch failed for unknown reasons");
+ }
+ return error;
+}
+
+
diff --git a/lldb/source/Host/macosx/Symbols.cpp b/lldb/source/Host/macosx/Symbols.cpp
index 7a32e08a476..c6d2f08db07 100644
--- a/lldb/source/Host/macosx/Symbols.cpp
+++ b/lldb/source/Host/macosx/Symbols.cpp
@@ -25,8 +25,8 @@
#include "lldb/Core/UUID.h"
#include "lldb/Host/Endian.h"
#include "lldb/Utility/CleanUp.h"
-
#include "Host/macosx/cfcpp/CFCReleaser.h"
+#include "Host/macosx/cfcpp/CFCString.h"
#include "mach/machine.h"
using namespace lldb;
@@ -352,11 +352,18 @@ LocateMacOSXFilesUsingDebugSymbols
CFCReleaser<CFDictionaryRef> dict(::DBGCopyDSYMPropertyLists (dsym_url.get()));;
if (dict.get())
{
- CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (dict.get(), CFSTR("DBGSymbolRichExecutable")));
- if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
+ char uuid_cstr_buf[64];
+ const char *uuid_cstr = uuid->GetAsCString (uuid_cstr_buf, sizeof(uuid_cstr_buf));
+ CFCString uuid_cfstr (uuid_cstr);
+ CFDictionaryRef uuid_dict = static_cast<CFDictionaryRef>(::CFDictionaryGetValue (dict.get(), uuid_cfstr.get()));
+ if (uuid_dict)
{
- ++items_found;
- out_dsym_fspec->SetFile(path, false);
+ CFStringRef exec_cf_path = static_cast<CFStringRef>(::CFDictionaryGetValue (uuid_dict, CFSTR("DBGSymbolRichExecutable")));
+ if (exec_cf_path && ::CFStringGetFileSystemRepresentation (exec_cf_path, path, sizeof(path)))
+ {
+ ++items_found;
+ out_exec_fspec->SetFile(path, path[0] == '~');
+ }
}
}
}
diff --git a/lldb/source/Host/macosx/cfcpp/CFCString.h b/lldb/source/Host/macosx/cfcpp/CFCString.h
index 521d2c0a51b..27c090313ec 100644
--- a/lldb/source/Host/macosx/cfcpp/CFCString.h
+++ b/lldb/source/Host/macosx/cfcpp/CFCString.h
@@ -21,7 +21,7 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
CFCString (CFStringRef cf_str = NULL);
- CFCString (const char *s, CFStringEncoding encoding);
+ CFCString (const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8);
CFCString (const CFCString& rhs);
CFCString& operator= (const CFCString& rhs);
virtual ~CFCString ();
diff --git a/lldb/source/Interpreter/Args.cpp b/lldb/source/Interpreter/Args.cpp
index df276baff6f..13ecd116adc 100644
--- a/lldb/source/Interpreter/Args.cpp
+++ b/lldb/source/Interpreter/Args.cpp
@@ -28,7 +28,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
Args::Args (const char *command) :
m_args(),
- m_argv()
+ m_argv(),
+ m_args_quote_char()
{
if (command)
SetCommandString (command);
@@ -37,13 +38,49 @@ Args::Args (const char *command) :
Args::Args (const char *command, size_t len) :
m_args(),
- m_argv()
+ m_argv(),
+ m_args_quote_char()
{
if (command && len)
SetCommandString (command, len);
}
//----------------------------------------------------------------------
+// We have to be very careful on the copy constructor of this class
+// to make sure we copy all of the string values, but we can't copy the
+// rhs.m_argv into m_argv since it will point to the "const char *" c
+// strings in rhs.m_args. We need to copy the string list and update our
+// own m_argv appropriately.
+//----------------------------------------------------------------------
+Args::Args (const Args &rhs) :
+ m_args (rhs.m_args),
+ m_argv (),
+ m_args_quote_char(rhs.m_args_quote_char)
+{
+ UpdateArgvFromArgs();
+}
+
+//----------------------------------------------------------------------
+// We have to be very careful on the copy constructor of this class
+// to make sure we copy all of the string values, but we can't copy the
+// rhs.m_argv into m_argv since it will point to the "const char *" c
+// strings in rhs.m_args. We need to copy the string list and update our
+// own m_argv appropriately.
+//----------------------------------------------------------------------
+const Args &
+Args::operator= (const Args &rhs)
+{
+ // Make sure we aren't assigning to self
+ if (this != &rhs)
+ {
+ m_args = rhs.m_args;
+ m_args_quote_char = rhs.m_args_quote_char;
+ UpdateArgvFromArgs();
+ }
+ return *this;
+}
+
+//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
Args::~Args ()
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index 98786f7c5cc..6dcc4a1eea5 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -100,22 +100,23 @@ CommandInterpreter::Initialize ()
HandleCommand ("command alias continue process continue", false, result);
HandleCommand ("command alias expr expression", false, result);
HandleCommand ("command alias exit quit", false, result);
- HandleCommand ("command alias b regexp-break", false, result);
+ HandleCommand ("command alias b _regexp-break", false, result);
HandleCommand ("command alias bt thread backtrace", false, result);
HandleCommand ("command alias si thread step-inst", false, result);
HandleCommand ("command alias step thread step-in", false, result);
HandleCommand ("command alias s thread step-in", false, result);
HandleCommand ("command alias next thread step-over", false, result);
HandleCommand ("command alias n thread step-over", false, result);
+ HandleCommand ("command alias f thread step-out", false, result);
HandleCommand ("command alias finish thread step-out", false, result);
HandleCommand ("command alias x memory read", false, result);
HandleCommand ("command alias l source list", false, result);
HandleCommand ("command alias list source list", false, result);
- HandleCommand ("command alias p frame variable", false, result);
+ HandleCommand ("command alias p expression --", false, result);
HandleCommand ("command alias print expression --", false, result);
HandleCommand ("command alias po expression -o --", false, result);
- HandleCommand ("command alias up regexp-up", false, result);
- HandleCommand ("command alias down regexp-down", false, result);
+ HandleCommand ("command alias up _regexp-up", false, result);
+ HandleCommand ("command alias down _regexp-down", false, result);
}
@@ -183,15 +184,15 @@ CommandInterpreter::LoadCommandDictionary ()
std::auto_ptr<CommandObjectRegexCommand>
break_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "regexp-break",
+ "_regexp-break",
"Set a breakpoint using a regular expression to specify the location.",
- "regexp-break [<filename>:<linenum>]\nregexp-break [<address>]\nregexp-break <...>", 2));
+ "_regexp-break [<filename>:<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 2));
if (break_regex_cmd_ap.get())
{
if (break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2") &&
break_regex_cmd_ap->AddRegexCommand("^(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1") &&
break_regex_cmd_ap->AddRegexCommand("^[\"']?([-+]\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'") &&
- break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list") &&
+ break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full") &&
break_regex_cmd_ap->AddRegexCommand("^(-.*)$", "breakpoint set %1") &&
break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'") &&
break_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1'"))
@@ -203,9 +204,9 @@ CommandInterpreter::LoadCommandDictionary ()
std::auto_ptr<CommandObjectRegexCommand>
down_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "regexp-down",
- "Go down \"n\" frames in the stack (1 frame by default).",
- "down [n]", 2));
+ "_regexp-down",
+ "Go down \"n\" frames in the stack (1 frame by default).",
+ "_regexp-down [n]", 2));
if (down_regex_cmd_ap.get())
{
if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") &&
@@ -218,9 +219,9 @@ CommandInterpreter::LoadCommandDictionary ()
std::auto_ptr<CommandObjectRegexCommand>
up_regex_cmd_ap(new CommandObjectRegexCommand (*this,
- "regexp-up",
- "Go up \"n\" frames in the stack (1 frame by default).",
- "up [n]", 2));
+ "_regexp-up",
+ "Go up \"n\" frames in the stack (1 frame by default).",
+ "_regexp-up [n]", 2));
if (up_regex_cmd_ap.get())
{
if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") &&
@@ -759,7 +760,7 @@ CommandInterpreter::HandleCommand (const char *command_line,
Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line);
- m_debugger.UpdateExecutionContext (override_context);
+ UpdateExecutionContext (override_context);
bool empty_command = false;
bool comment_command = false;
@@ -1542,6 +1543,18 @@ CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result)
}
}
+PlatformSP
+CommandInterpreter::GetPlatform (bool prefer_target_platform)
+{
+ PlatformSP platform_sp;
+ if (prefer_target_platform && m_exe_ctx.target)
+ platform_sp = m_exe_ctx.target->GetPlatform();
+
+ if (!platform_sp)
+ platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform();
+ return platform_sp;
+}
+
void
CommandInterpreter::HandleCommands (const StringList &commands,
ExecutionContext *override_context,
@@ -1562,7 +1575,7 @@ CommandInterpreter::HandleCommands (const StringList &commands,
// cause series of commands that change the context, then do an operation that relies on that context to fail.
if (override_context != NULL)
- m_debugger.UpdateExecutionContext (override_context);
+ UpdateExecutionContext (override_context);
if (!stop_on_continue)
{
@@ -1842,3 +1855,50 @@ CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList
}
}
+
+
+void
+CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context)
+{
+ m_exe_ctx.Clear();
+
+ if (override_context != NULL)
+ {
+ m_exe_ctx.target = override_context->target;
+ m_exe_ctx.process = override_context->process;
+ m_exe_ctx.thread = override_context->thread;
+ m_exe_ctx.frame = override_context->frame;
+ }
+ else
+ {
+ TargetSP target_sp (m_debugger.GetSelectedTarget());
+ if (target_sp)
+ {
+ m_exe_ctx.target = target_sp.get();
+ m_exe_ctx.process = target_sp->GetProcessSP().get();
+ if (m_exe_ctx.process && m_exe_ctx.process->IsAlive() && !m_exe_ctx.process->IsRunning())
+ {
+ m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetSelectedThread().get();
+ if (m_exe_ctx.thread == NULL)
+ {
+ m_exe_ctx.thread = m_exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
+ // If we didn't have a selected thread, select one here.
+ if (m_exe_ctx.thread != NULL)
+ m_exe_ctx.process->GetThreadList().SetSelectedThreadByID(m_exe_ctx.thread->GetID());
+ }
+ if (m_exe_ctx.thread)
+ {
+ m_exe_ctx.frame = m_exe_ctx.thread->GetSelectedFrame().get();
+ if (m_exe_ctx.frame == NULL)
+ {
+ m_exe_ctx.frame = m_exe_ctx.thread->GetStackFrameAtIndex (0).get();
+ // If we didn't have a selected frame select one here.
+ if (m_exe_ctx.frame != NULL)
+ m_exe_ctx.thread->SetSelectedFrame(m_exe_ctx.frame);
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp
index f93ed6e0344..16c68ec1b22 100644
--- a/lldb/source/Interpreter/CommandObject.cpp
+++ b/lldb/source/Interpreter/CommandObject.cpp
@@ -219,7 +219,7 @@ CommandObject::ExecuteWithOptions (Args& args, CommandReturnObject &result)
if (GetFlags().AnySet (CommandObject::eFlagProcessMustBeLaunched | CommandObject::eFlagProcessMustBePaused))
{
- Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
+ Process *process = m_interpreter.GetExecutionContext().process;
if (process == NULL)
{
result.AppendError ("Process must exist.");
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
index 0b06b4c3bfc..104099450fa 100644
--- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
+++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp
@@ -295,7 +295,7 @@ DynamicLoaderMacOSXDYLD::ReadDYLDInfoFromMemoryAndSetNotificationCallback(lldb::
// it again (since Target::SetExecutableModule() will clear the
// images). So append the dyld module back to the list if it is
/// unique!
- if (m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp))
+ if (dyld_module_sp && m_process->GetTarget().GetImages().AppendIfNeeded (dyld_module_sp))
UpdateImageLoadAddress(dyld_module_sp.get(), m_dyld);
return true;
@@ -603,6 +603,7 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
uint32_t idx;
uint32_t i = 0;
+ // Since we can't downsize a vector, we must do this using the swap method
DYLDImageInfo::collection old_dyld_all_image_infos;
old_dyld_all_image_infos.swap(m_dyld_image_infos);
@@ -639,7 +640,10 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
m_dyld_image_infos[i].mod_date = info_data_ref.GetPointer(&info_data_offset);
char raw_path[PATH_MAX];
- m_process->ReadMemory (path_addr, raw_path, sizeof(raw_path), error);
+ m_process->ReadCStringFromMemory (path_addr, raw_path, sizeof(raw_path));
+ char raw_path2[PATH_MAX];// TODO: remove after assertion doesn't assert
+ m_process->ReadMemory (path_addr, raw_path2, sizeof(raw_path2), error);// TODO: remove after assertion doesn't assert
+ assert (strcmp (raw_path, raw_path2) == 0);// TODO: remove after assertion doesn't assert
m_dyld_image_infos[i].file_spec.SetFile(raw_path, true);
}
assert(i == m_dyld_all_image_infos.dylib_info_count);
@@ -653,10 +657,6 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
}
}
}
- else
- {
- m_dyld_image_infos.clear();
- }
// If our new list is smaller than our old list, we have unloaded
// some shared libraries
@@ -763,9 +763,9 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos()
{
commpage_image_module_sp = m_process->GetTarget().GetSharedModule (m_dyld_image_infos[idx].file_spec,
arch,
- &m_dyld_image_infos[idx].uuid,
+ NULL,
&commpage_dbstr,
- objfile->GetOffset() + commpage_section->GetOffset());
+ objfile->GetOffset() + commpage_section->GetFileOffset());
}
if (commpage_image_module_sp)
UpdateCommPageLoadAddress (commpage_image_module_sp.get());
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
index 63cb4ac25ee..d3a11e43e84 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.cpp
@@ -14,6 +14,7 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Target.h"
@@ -50,17 +51,47 @@ PlatformDarwin::ResolveExecutable (const FileSpec &exe_file,
Error error;
// Nothing special to do here, just use the actual file and architecture
+ char exe_path[PATH_MAX];
FileSpec resolved_exe_file (exe_file);
- // If we have "ls" as the exe_file, resolve the executable loation based on
- // the current path variables
- if (!resolved_exe_file.Exists())
- resolved_exe_file.ResolveExecutableLocation ();
+ if (IsHost())
+ {
+ // If we have "ls" as the exe_file, resolve the executable loation based on
+ // the current path variables
+ if (!resolved_exe_file.Exists())
+ {
+ exe_file.GetPath (exe_path, sizeof(exe_path));
+ resolved_exe_file.SetFile(exe_path, true);
+ }
- // Resolve any executable within a bundle on MacOSX
- Host::ResolveExecutableInBundle (resolved_exe_file);
+ if (!resolved_exe_file.Exists())
+ resolved_exe_file.ResolveExecutableLocation ();
- if (resolved_exe_file.Exists())
+ // Resolve any executable within a bundle on MacOSX
+ Host::ResolveExecutableInBundle (resolved_exe_file);
+
+ if (resolved_exe_file.Exists())
+ error.Clear();
+ else
+ {
+ exe_file.GetPath (exe_path, sizeof(exe_path));
+ error.SetErrorStringWithFormat ("enable to find executable for '%s'", exe_path);
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ {
+ error = m_remote_platform_sp->ResolveExecutable (exe_file,
+ exe_arch,
+ exe_module_sp);
+ }
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+
+
+ if (error.Success())
{
if (exe_arch.IsValid())
{
@@ -321,7 +352,7 @@ PlatformDarwin::DisconnectRemote ()
bool
-PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
bool sucess = false;
if (IsHost())
@@ -339,8 +370,8 @@ PlatformDarwin::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
uint32_t
-PlatformDarwin::FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &process_infos)
+PlatformDarwin::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
{
uint32_t match_count = 0;
if (IsHost())
@@ -357,6 +388,71 @@ PlatformDarwin::FindProcesses (const ProcessInfoMatch &match_info,
return match_count;
}
+Error
+PlatformDarwin::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ if (IsHost())
+ {
+ error = Platform::LaunchProcess (launch_info);
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ error = m_remote_platform_sp->LaunchProcess (launch_info);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return error;
+}
+
+lldb::ProcessSP
+PlatformDarwin::Attach (lldb::pid_t pid,
+ Debugger &debugger,
+ Target *target,
+ Listener &listener,
+ Error &error)
+{
+ lldb::ProcessSP process_sp;
+ if (IsHost())
+ {
+ if (target == NULL)
+ {
+ TargetSP new_target_sp;
+ FileSpec emptyFileSpec;
+ ArchSpec emptyArchSpec;
+
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ emptyFileSpec,
+ emptyArchSpec,
+ false,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+ else
+ error.Clear();
+
+ 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");
+
+ if (process_sp)
+ error = process_sp->Attach (pid);
+ }
+ }
+ else
+ {
+ if (m_remote_platform_sp)
+ process_sp = m_remote_platform_sp->Attach (pid, debugger, target, listener, error);
+ else
+ error.SetErrorString ("the platform is not currently connected");
+ }
+ return process_sp;
+}
+
const char *
PlatformDarwin::GetUserName (uint32_t uid)
{
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
index 74647360694..38804edad18 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwin.h
@@ -69,12 +69,22 @@ public:
virtual bool
GetProcessInfo (lldb::pid_t pid,
- lldb_private::ProcessInfo &proc_info);
+ lldb_private::ProcessInstanceInfo &proc_info);
virtual uint32_t
- FindProcesses (const lldb_private::ProcessInfoMatch &match_info,
- lldb_private::ProcessInfoList &process_infos);
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos);
+ virtual lldb_private::Error
+ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
+
+ virtual lldb::ProcessSP
+ Attach (lldb::pid_t pid,
+ 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,
+ lldb_private::Error &error);
+
protected:
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
index 2ae4a903353..3e0b2b14906 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.cpp
@@ -447,8 +447,8 @@ PlatformRemoteiOS::GetSharedModule (const FileSpec &platform_file,
uint32_t
-PlatformRemoteiOS::FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &process_infos)
+PlatformRemoteiOS::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
{
// TODO: if connected, send a packet to get the remote process infos by name
process_infos.Clear();
@@ -456,7 +456,7 @@ PlatformRemoteiOS::FindProcesses (const ProcessInfoMatch &match_info,
}
bool
-PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+PlatformRemoteiOS::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
// TODO: if connected, send a packet to get the remote process info
process_info.Clear();
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
index 63ac8520de4..08968f4f110 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteiOS.h
@@ -103,12 +103,12 @@ public:
bool *did_create_ptr);
virtual uint32_t
- FindProcesses (const lldb_private::ProcessInfoMatch &match_info,
- lldb_private::ProcessInfoList &process_infos);
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos);
virtual bool
GetProcessInfo (lldb::pid_t pid,
- lldb_private::ProcessInfo &proc_info);
+ lldb_private::ProcessInstanceInfo &proc_info);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx,
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index a6bcb9bf07e..f8b67a31280 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -17,6 +17,7 @@
// Project includes
#include "lldb/Breakpoint/BreakpointLocation.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
+#include "lldb/Core/Debugger.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleList.h"
@@ -112,7 +113,8 @@ PlatformRemoteGDBServer::GetFile (const FileSpec &platform_file,
/// Default Constructor
//------------------------------------------------------------------
PlatformRemoteGDBServer::PlatformRemoteGDBServer () :
- Platform(false) // This is a remote platform
+ Platform(false), // This is a remote platform
+ m_gdb_client(true)
{
}
@@ -267,17 +269,139 @@ PlatformRemoteGDBServer::GetGroupName (uint32_t gid)
}
uint32_t
-PlatformRemoteGDBServer::FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &process_infos)
+PlatformRemoteGDBServer::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
{
return m_gdb_client.FindProcesses (match_info, process_infos);
}
bool
-PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+PlatformRemoteGDBServer::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
return m_gdb_client.GetProcessInfo (pid, process_info);
}
+Error
+PlatformRemoteGDBServer::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ m_gdb_client.SetSTDIN ("/dev/null");
+ m_gdb_client.SetSTDOUT ("/dev/null");
+ m_gdb_client.SetSTDERR ("/dev/null");
+ m_gdb_client.SetDisableASLR (launch_info.GetFlags().Test (eLaunchFlagDisableASLR));
+
+ const char *working_dir = launch_info.GetWorkingDirectory();
+ if (working_dir && working_dir[0])
+ {
+ m_gdb_client.SetWorkingDir (working_dir);
+ }
+
+ // Send the environment and the program + arguments after we connect
+ const char **argv = launch_info.GetArguments().GetConstArgumentVector();
+ const char **envp = launch_info.GetEnvironmentEntries().GetConstArgumentVector();
+
+ if (envp)
+ {
+ const char *env_entry;
+ for (int i=0; (env_entry = envp[i]); ++i)
+ {
+ if (m_gdb_client.SendEnvironmentPacket(env_entry) != 0)
+ break;
+ }
+ }
+ const uint32_t old_packet_timeout = m_gdb_client.SetPacketTimeout (3000); // TODO: lower this to 5 seconds prior to checkin!!!
+ int arg_packet_err = m_gdb_client.SendArgumentsPacket (argv);
+ m_gdb_client.SetPacketTimeout (old_packet_timeout);
+ if (arg_packet_err == 0)
+ {
+ std::string error_str;
+ if (m_gdb_client.GetLaunchSuccess (error_str))
+ {
+ pid = m_gdb_client.GetCurrentProcessID ();
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ launch_info.SetProcessID (pid);
+ }
+ else
+ {
+ error.SetErrorString (error_str.c_str());
+ }
+ }
+ else
+ {
+ error.SetErrorStringWithFormat("'A' packet returned an error: %i.\n", arg_packet_err);
+ }
+ return error;
+}
+
+lldb::ProcessSP
+PlatformRemoteGDBServer::Attach (lldb::pid_t pid,
+ Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Listener &listener,
+ Error &error)
+{
+ lldb::ProcessSP process_sp;
+ if (IsRemote())
+ {
+ if (IsConnected())
+ {
+ uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort();
+
+ if (port == 0)
+ {
+ error.SetErrorStringWithFormat ("unable to launch a GDB server on '%s'", GetHostname ());
+ }
+ else
+ {
+ if (target == NULL)
+ {
+ TargetSP new_target_sp;
+ FileSpec emptyFileSpec;
+ ArchSpec emptyArchSpec;
+
+ error = debugger.GetTargetList().CreateTarget (debugger,
+ emptyFileSpec,
+ emptyArchSpec,
+ false,
+ new_target_sp);
+ target = new_target_sp.get();
+ }
+ else
+ error.Clear();
+
+ 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");
+
+ if (process_sp)
+ {
+ char connect_url[256];
+ const int connect_url_len = ::snprintf (connect_url,
+ sizeof(connect_url),
+ "connect://%s:%u",
+ GetHostname (),
+ port);
+ assert (connect_url_len < sizeof(connect_url));
+ error = process_sp->ConnectRemote (connect_url);
+ if (error.Success())
+ error = process_sp->Attach(pid);
+ }
+ }
+ }
+ }
+ else
+ {
+ error.SetErrorString("not connected to remote gdb server");
+ }
+ }
+ return process_sp;
+}
+
diff --git a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index a016e01d008..36c48c24b60 100644
--- a/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/lldb/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -83,11 +83,22 @@ public:
lldb_private::FileSpec &local_file);
virtual bool
- GetProcessInfo (lldb::pid_t pid, lldb_private::ProcessInfo &proc_info);
+ GetProcessInfo (lldb::pid_t pid,
+ lldb_private::ProcessInstanceInfo &proc_info);
virtual uint32_t
- FindProcesses (const lldb_private::ProcessInfoMatch &match_info,
- lldb_private::ProcessInfoList &process_infos);
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos);
+
+ virtual lldb_private::Error
+ LaunchProcess (lldb_private::ProcessLaunchInfo &launch_info);
+
+ virtual lldb::ProcessSP
+ Attach (lldb::pid_t pid,
+ 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,
+ lldb_private::Error &error);
virtual bool
GetSupportedArchitectureAtIndex (uint32_t idx, lldb_private::ArchSpec &arch);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index 3b8d6056063..93e4166af2c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -17,25 +17,33 @@
// Other libraries and framework includes
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Host/FileSpec.h"
+#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
+#define DEBUGSERVER_BASENAME "debugserver"
+
using namespace lldb;
using namespace lldb_private;
//----------------------------------------------------------------------
// GDBRemoteCommunication constructor
//----------------------------------------------------------------------
-GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) :
+GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
+ const char *listener_name,
+ bool is_platform) :
Communication(comm_name),
m_packet_timeout (60),
m_rx_packet_listener (listener_name),
m_sequence_mutex (Mutex::eMutexTypeRecursive),
m_public_is_running (false),
m_private_is_running (false),
- m_send_acks (true)
+ m_send_acks (true),
+ m_is_platform (is_platform)
{
m_rx_packet_listener.StartListeningForEvents(this,
Communication::eBroadcastBitPacketAvailable |
@@ -328,3 +336,131 @@ GDBRemoteCommunication::AppendBytesToCache (const uint8_t *src, size_t src_len,
}
}
+Error
+GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
+ const char *unix_socket_name, // For handshaking
+ lldb_private::ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ // If we locate debugserver, keep that located version around
+ static FileSpec g_debugserver_file_spec;
+
+ // This function will fill in the launch information for the debugserver
+ // instance that gets launched.
+ launch_info.Clear();
+
+ char debugserver_path[PATH_MAX];
+ FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
+
+ // Always check to see if we have an environment override for the path
+ // to the debugserver to use and use it if we do.
+ const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
+ if (env_debugserver_path)
+ debugserver_file_spec.SetFile (env_debugserver_path, false);
+ else
+ debugserver_file_spec = g_debugserver_file_spec;
+ bool debugserver_exists = debugserver_file_spec.Exists();
+ if (!debugserver_exists)
+ {
+ // The debugserver binary is in the LLDB.framework/Resources
+ // directory.
+ if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
+ {
+ debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
+ debugserver_exists = debugserver_file_spec.Exists();
+ if (debugserver_exists)
+ {
+ g_debugserver_file_spec = debugserver_file_spec;
+ }
+ else
+ {
+ g_debugserver_file_spec.Clear();
+ debugserver_file_spec.Clear();
+ }
+ }
+ }
+
+ if (debugserver_exists)
+ {
+ debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
+
+ Args &debugserver_args = launch_info.GetArguments();
+ debugserver_args.Clear();
+ char arg_cstr[PATH_MAX];
+
+ // Start args with "debugserver /file/path -r --"
+ debugserver_args.AppendArgument(debugserver_path);
+ debugserver_args.AppendArgument(debugserver_url);
+ // use native registers, not the GDB registers
+ debugserver_args.AppendArgument("--native-regs");
+ // make debugserver run in its own session so signals generated by
+ // special terminal key sequences (^C) don't affect debugserver
+ debugserver_args.AppendArgument("--setsid");
+
+ if (unix_socket_name && unix_socket_name[0])
+ {
+ debugserver_args.AppendArgument("--unix-socket");
+ debugserver_args.AppendArgument(unix_socket_name);
+ }
+
+ const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
+ if (env_debugserver_log_file)
+ {
+ ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
+ debugserver_args.AppendArgument(arg_cstr);
+ }
+
+ const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
+ if (env_debugserver_log_flags)
+ {
+ ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
+ debugserver_args.AppendArgument(arg_cstr);
+ }
+ // debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
+ // debugserver_args.AppendArgument("--log-flags=0x802e0e");
+
+ // We currently send down all arguments, attach pids, or attach
+ // process names in dedicated GDB server packets, so we don't need
+ // to pass them as arguments. This is currently because of all the
+ // things we need to setup prior to launching: the environment,
+ // current working dir, file actions, etc.
+#if 0
+ // Now append the program arguments
+ if (inferior_argv)
+ {
+ // Terminate the debugserver args so we can now append the inferior args
+ debugserver_args.AppendArgument("--");
+
+ for (int i = 0; inferior_argv[i] != NULL; ++i)
+ debugserver_args.AppendArgument (inferior_argv[i]);
+ }
+ else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+ {
+ ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
+ debugserver_args.AppendArgument (arg_cstr);
+ }
+ else if (attach_name && attach_name[0])
+ {
+ if (wait_for_launch)
+ debugserver_args.AppendArgument ("--waitfor");
+ else
+ debugserver_args.AppendArgument ("--attach");
+ debugserver_args.AppendArgument (attach_name);
+ }
+#endif
+
+ // Close STDIN, STDOUT and STDERR. We might need to redirect them
+ // to "/dev/null" if we run into any problems.
+// launch_info.AppendCloseFileAction (STDIN_FILENO);
+// launch_info.AppendCloseFileAction (STDOUT_FILENO);
+// launch_info.AppendCloseFileAction (STDERR_FILENO);
+
+ error = Host::LaunchProcess(launch_info);
+ }
+ else
+ {
+ error.SetErrorStringWithFormat ("Unable to locate " DEBUGSERVER_BASENAME ".\n");
+ }
+ return error;
+}
+
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index f53d036a518..77e3e1a5d7c 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -37,7 +37,9 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- GDBRemoteCommunication(const char *comm_name, const char *listener_name);
+ GDBRemoteCommunication(const char *comm_name,
+ const char *listener_name,
+ bool is_platform);
virtual
~GDBRemoteCommunication();
@@ -119,6 +121,15 @@ public:
return old_packet_timeout;
}
+ //------------------------------------------------------------------
+ // Start a debugserver instance on the current host using the
+ // supplied connection URL.
+ //------------------------------------------------------------------
+ lldb_private::Error
+ StartDebugserverProcess (const char *connect_url,
+ const char *unix_socket_name,
+ lldb_private::ProcessLaunchInfo &launch_info);
+
protected:
typedef std::list<std::string> packet_collection;
@@ -142,10 +153,13 @@ protected:
lldb_private::Predicate<bool> m_public_is_running;
lldb_private::Predicate<bool> m_private_is_running;
bool m_send_acks;
-
+ bool m_is_platform; // Set to true if this class represents a platform,
+ // false if this class represents a debug session for
+ // a single process
+
private:
//------------------------------------------------------------------
// For GDBRemoteCommunication only
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 2cebb10c0fb..d4f6592f5bd 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -34,8 +34,8 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// GDBRemoteCommunicationClient constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
- GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"),
+GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
+ GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet", is_platform),
m_supports_not_sending_acks (eLazyBoolCalculate),
m_supports_thread_suffix (eLazyBoolCalculate),
m_supports_vCont_all (eLazyBoolCalculate),
@@ -49,6 +49,14 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
m_supports_qGroupName (true),
+ m_supports_qThreadStopInfo (true),
+ m_supports_z0 (true),
+ m_supports_z1 (true),
+ m_supports_z2 (true),
+ m_supports_z3 (true),
+ m_supports_z4 (true),
+ m_curr_tid (LLDB_INVALID_THREAD_ID),
+ m_curr_tid_run (LLDB_INVALID_THREAD_ID),
m_async_mutex (Mutex::eMutexTypeRecursive),
m_async_packet_predicate (false),
m_async_packet (),
@@ -126,6 +134,12 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_qfProcessInfo = true;
m_supports_qUserName = true;
m_supports_qGroupName = true;
+ m_supports_qThreadStopInfo = true;
+ m_supports_z0 = true;
+ m_supports_z1 = true;
+ m_supports_z2 = true;
+ m_supports_z3 = true;
+ m_supports_z4 = true;
m_host_arch.Clear();
}
@@ -1119,7 +1133,7 @@ GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
}
bool
-GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInfo &process_info)
+GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info)
{
if (response.IsNormalResponse())
{
@@ -1139,7 +1153,7 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
}
else if (name.compare("uid") == 0)
{
- process_info.SetRealUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+ process_info.SetUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
}
else if (name.compare("euid") == 0)
{
@@ -1147,7 +1161,7 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
}
else if (name.compare("gid") == 0)
{
- process_info.SetRealGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
+ process_info.SetGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0));
}
else if (name.compare("egid") == 0)
{
@@ -1180,7 +1194,7 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
}
bool
-GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
process_info.Clear();
@@ -1205,8 +1219,8 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInfo &proc
}
uint32_t
-GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &process_infos)
+GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
{
process_infos.Clear();
@@ -1261,10 +1275,10 @@ GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info,
packet.Printf("pid:%u;",match_info.GetProcessInfo().GetProcessID());
if (match_info.GetProcessInfo().ParentProcessIDIsValid())
packet.Printf("parent_pid:%u;",match_info.GetProcessInfo().GetParentProcessID());
- if (match_info.GetProcessInfo().RealUserIDIsValid())
- packet.Printf("uid:%u;",match_info.GetProcessInfo().GetRealUserID());
- if (match_info.GetProcessInfo().RealGroupIDIsValid())
- packet.Printf("gid:%u;",match_info.GetProcessInfo().GetRealGroupID());
+ if (match_info.GetProcessInfo().UserIDIsValid())
+ packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID());
+ if (match_info.GetProcessInfo().GroupIDIsValid())
+ packet.Printf("gid:%u;",match_info.GetProcessInfo().GetGroupID());
if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID());
if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
@@ -1291,7 +1305,7 @@ GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info,
do
{
- ProcessInfo process_info;
+ ProcessInstanceInfo process_info;
if (!DecodeProcessInfoResponse (response, process_info))
break;
process_infos.Append(process_info);
@@ -1447,3 +1461,154 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
}
return false;
}
+
+uint16_t
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort ()
+{
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qLaunchGDBServer", strlen("qLaunchGDBServer"), response, false))
+ {
+ std::string name;
+ std::string value;
+ uint16_t port = 0;
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ while (response.GetNameColonValue(name, value))
+ {
+ if (name.size() == 4 && name.compare("port") == 0)
+ port = Args::StringToUInt32(value.c_str(), 0, 0);
+ if (name.size() == 3 && name.compare("pid") == 0)
+ pid = Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
+ }
+ return port;
+ }
+ return 0;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThread (int tid)
+{
+ if (m_curr_tid == tid)
+ return true;
+
+ char packet[32];
+ int packet_len;
+ if (tid <= 0)
+ packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
+ assert (packet_len + 1 < sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsOKResponse())
+ {
+ m_curr_tid = tid;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::SetCurrentThreadForRun (int tid)
+{
+ if (m_curr_tid_run == tid)
+ return true;
+
+ char packet[32];
+ int packet_len;
+ if (tid <= 0)
+ packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
+ else
+ packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
+
+ assert (packet_len + 1 < sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsOKResponse())
+ {
+ m_curr_tid_run = tid;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response)
+{
+ if (SendPacketAndWaitForResponse("?", 1, response, false))
+ return response.IsNormalResponse();
+ return false;
+}
+
+bool
+GDBRemoteCommunicationClient::GetThreadStopInfo (uint32_t tid, StringExtractorGDBRemote &response)
+{
+ if (m_supports_qThreadStopInfo)
+ {
+ char packet[256];
+ int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", tid);
+ assert (packet_len < sizeof(packet));
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ {
+ if (response.IsUnsupportedResponse())
+ m_supports_qThreadStopInfo = false;
+ else if (response.IsNormalResponse())
+ return true;
+ else
+ return false;
+ }
+ }
+ if (SetCurrentThread (tid))
+ return GetStopReply (response);
+ return false;
+}
+
+
+uint8_t
+GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length)
+{
+ switch (type)
+ {
+ case eBreakpointSoftware: if (!m_supports_z0) return UINT8_MAX; break;
+ case eBreakpointHardware: if (!m_supports_z1) return UINT8_MAX; break;
+ case eWatchpointWrite: if (!m_supports_z2) return UINT8_MAX; break;
+ case eWatchpointRead: if (!m_supports_z3) return UINT8_MAX; break;
+ case eWatchpointReadWrite: if (!m_supports_z4) return UINT8_MAX; break;
+ default: return UINT8_MAX;
+ }
+
+ char packet[64];
+ const int packet_len = ::snprintf (packet,
+ sizeof(packet),
+ "%c%i,%llx,%x",
+ insert ? 'Z' : 'z',
+ type,
+ addr,
+ length);
+
+ assert (packet_len + 1 < sizeof(packet));
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, true))
+ {
+ if (response.IsOKResponse())
+ return 0;
+ if (response.IsUnsupportedResponse())
+ {
+ switch (type)
+ {
+ case eBreakpointSoftware: m_supports_z0 = false; break;
+ case eBreakpointHardware: m_supports_z1 = false; break;
+ case eWatchpointWrite: m_supports_z2 = false; break;
+ case eWatchpointRead: m_supports_z3 = false; break;
+ case eWatchpointReadWrite: m_supports_z4 = false; break;
+ default: break;
+ }
+ }
+ else if (response.IsErrorResponse())
+ return response.GetError();
+ }
+ return UINT8_MAX;
+}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index ae1674a4d1f..5c24d642470 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -18,13 +18,22 @@
#include "GDBRemoteCommunication.h"
+typedef enum
+{
+ eBreakpointSoftware = 0,
+ eBreakpointHardware,
+ eWatchpointWrite,
+ eWatchpointRead,
+ eWatchpointReadWrite
+} GDBStoppointType;
+
class GDBRemoteCommunicationClient : public GDBRemoteCommunication
{
public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- GDBRemoteCommunicationClient();
+ GDBRemoteCommunicationClient(bool is_platform);
virtual
~GDBRemoteCommunicationClient();
@@ -74,6 +83,9 @@ public:
bool
GetLaunchSuccess (std::string &error_str);
+ uint16_t
+ LaunchGDBserverAndGetPort ();
+
//------------------------------------------------------------------
/// Sends a GDB remote protocol 'A' packet that delivers program
/// arguments to the remote server.
@@ -214,11 +226,11 @@ public:
bool
GetProcessInfo (lldb::pid_t pid,
- lldb_private::ProcessInfo &process_info);
+ lldb_private::ProcessInstanceInfo &process_info);
uint32_t
- FindProcesses (const lldb_private::ProcessInfoMatch &process_match_info,
- lldb_private::ProcessInfoList &process_infos);
+ FindProcesses (const lldb_private::ProcessInstanceInfoMatch &process_match_info,
+ lldb_private::ProcessInstanceInfoList &process_infos);
bool
GetUserName (uint32_t uid, std::string &name);
@@ -246,6 +258,33 @@ public:
return old_packet_timeout;
}
+ bool
+ GetStopReply (StringExtractorGDBRemote &response);
+
+ bool
+ GetThreadStopInfo (uint32_t tid,
+ StringExtractorGDBRemote &response);
+
+ bool
+ SupportsGDBStoppointPacket (GDBStoppointType type)
+ {
+ switch (type)
+ {
+ case eBreakpointSoftware: return m_supports_z0;
+ case eBreakpointHardware: return m_supports_z1;
+ case eWatchpointWrite: return m_supports_z2;
+ case eWatchpointRead: return m_supports_z3;
+ case eWatchpointReadWrite: return m_supports_z4;
+ default: break;
+ }
+ return false;
+ }
+ uint8_t
+ SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint
+ bool insert, // Insert or remove?
+ lldb::addr_t addr, // Address of breakpoint or watchpoint
+ uint32_t length); // Byte Size of breakpoint or watchpoint
+
void
TestPacketSpeed (const uint32_t num_packets);
@@ -257,6 +296,13 @@ public:
bool
SendSpeedTestPacket (uint32_t send_size,
uint32_t recv_size);
+
+ bool
+ SetCurrentThread (int tid);
+
+ bool
+ SetCurrentThreadForRun (int tid);
+
protected:
//------------------------------------------------------------------
@@ -271,10 +317,21 @@ protected:
lldb_private::LazyBool m_supports_vCont_s;
lldb_private::LazyBool m_supports_vCont_S;
lldb_private::LazyBool m_qHostInfo_is_valid;
- bool m_supports_qProcessInfoPID;
- bool m_supports_qfProcessInfo;
- bool m_supports_qUserName;
- bool m_supports_qGroupName;
+ bool
+ m_supports_qProcessInfoPID:1,
+ m_supports_qfProcessInfo:1,
+ m_supports_qUserName:1,
+ m_supports_qGroupName:1,
+ m_supports_qThreadStopInfo:1,
+ m_supports_z0:1,
+ m_supports_z1:1,
+ m_supports_z2:1,
+ m_supports_z3:1,
+ m_supports_z4:1;
+
+ lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
+ lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
+
// If we need to send a packet while the target is running, the m_async_XXX
// member variables take care of making this happen.
@@ -294,7 +351,7 @@ protected:
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
- lldb_private::ProcessInfo &process_info);
+ lldb_private::ProcessInstanceInfo &process_info);
private:
//------------------------------------------------------------------
// For GDBRemoteCommunicationClient only
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index c2431380fd9..9379077335d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -21,6 +21,7 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Process.h"
// Project includes
#include "Utility/StringExtractorGDBRemote.h"
@@ -33,9 +34,15 @@ using namespace lldb_private;
//----------------------------------------------------------------------
// GDBRemoteCommunicationServer constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServer::GDBRemoteCommunicationServer() :
- GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet"),
- m_async_thread (LLDB_INVALID_HOST_THREAD)
+GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
+ GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
+ m_async_thread (LLDB_INVALID_HOST_THREAD),
+ m_process_launch_info (),
+ m_process_launch_error (),
+ m_proc_infos (),
+ m_proc_infos_index (0),
+ m_lo_port_num (0),
+ m_hi_port_num (0)
{
}
@@ -82,45 +89,76 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout
const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
switch (packet_type)
{
- case StringExtractorGDBRemote::eServerPacketType_nack:
- case StringExtractorGDBRemote::eServerPacketType_ack:
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_invalid:
- error.SetErrorString("invalid packet");
- quit = true;
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_interrupt:
- error.SetErrorString("interrupt received");
- interrupt = true;
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_unimplemented:
- return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
-
- case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
- return Handle_qHostInfo (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
- return Handle_qProcessInfoPID (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
- return Handle_qfProcessInfo (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
- return Handle_qsProcessInfo (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qUserName:
- return Handle_qUserName (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qGroupName:
- return Handle_qGroupName (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
- return Handle_qSpeedTest (packet);
- case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
- return Handle_QStartNoAckMode (packet);
+ case StringExtractorGDBRemote::eServerPacketType_nack:
+ case StringExtractorGDBRemote::eServerPacketType_ack:
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_invalid:
+ error.SetErrorString("invalid packet");
+ quit = true;
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_interrupt:
+ error.SetErrorString("interrupt received");
+ interrupt = true;
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_unimplemented:
+ return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
+
+ case StringExtractorGDBRemote::eServerPacketType_A:
+ return Handle_A (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
+ return Handle_qfProcessInfo (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
+ return Handle_qsProcessInfo (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qC:
+ return Handle_qC (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
+ return Handle_qHostInfo (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
+ return Handle_qLaunchGDBServer (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
+ return Handle_qLaunchSuccess (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qGroupName:
+ return Handle_qGroupName (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
+ return Handle_qProcessInfoPID (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
+ return Handle_qSpeedTest (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_qUserName:
+ return Handle_qUserName (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
+ return Handle_QEnvironment (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
+ return Handle_QSetDisableASLR (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
+ return Handle_QSetSTDIN (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
+ return Handle_QSetSTDOUT (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
+ return Handle_QSetSTDERR (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
+ return Handle_QSetWorkingDir (packet);
+
+ case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
+ return Handle_QStartNoAckMode (packet);
}
return true;
}
@@ -236,13 +274,13 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
}
static void
-CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response)
+CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response)
{
response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;",
proc_info.GetProcessID(),
proc_info.GetParentProcessID(),
- proc_info.GetRealUserID(),
- proc_info.GetRealGroupID(),
+ proc_info.GetUserID(),
+ proc_info.GetGroupID(),
proc_info.GetEffectiveUserID(),
proc_info.GetEffectiveGroupID());
response.PutCString ("name:");
@@ -262,11 +300,11 @@ bool
GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
{
// Packet format: "qProcessInfoPID:%i" where %i is the pid
- packet.SetFilePos(strlen ("qProcessInfoPID:"));
+ packet.SetFilePos(::strlen ("qProcessInfoPID:"));
lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
if (pid != LLDB_INVALID_PROCESS_ID)
{
- ProcessInfo proc_info;
+ ProcessInstanceInfo proc_info;
if (Host::GetProcessInfo(pid, proc_info))
{
StreamString response;
@@ -283,8 +321,8 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
m_proc_infos_index = 0;
m_proc_infos.Clear();
- ProcessInfoMatch match_info;
- packet.SetFilePos(strlen ("qfProcessInfo"));
+ ProcessInstanceInfoMatch match_info;
+ packet.SetFilePos(::strlen ("qfProcessInfo"));
if (packet.GetChar() == ':')
{
@@ -337,11 +375,11 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
}
else if (key.compare("uid") == 0)
{
- match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("gid") == 0)
{
- match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
+ match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success));
}
else if (key.compare("euid") == 0)
{
@@ -395,7 +433,7 @@ bool
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
// Packet format: "qUserName:%i" where %i is the uid
- packet.SetFilePos(strlen ("qUserName:"));
+ packet.SetFilePos(::strlen ("qUserName:"));
uint32_t uid = packet.GetU32 (UINT32_MAX);
if (uid != UINT32_MAX)
{
@@ -415,7 +453,7 @@ bool
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
// Packet format: "qGroupName:%i" where %i is the gid
- packet.SetFilePos(strlen ("qGroupName:"));
+ packet.SetFilePos(::strlen ("qGroupName:"));
uint32_t gid = packet.GetU32 (UINT32_MAX);
if (gid != UINT32_MAX)
{
@@ -433,7 +471,7 @@ GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packe
bool
GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
{
- packet.SetFilePos(strlen ("qSpeedTest:"));
+ packet.SetFilePos(::strlen ("qSpeedTest:"));
std::string key;
std::string value;
@@ -466,6 +504,327 @@ GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packe
}
return SendErrorResponse (7);
}
+
+
+static void *
+AcceptPortFromInferior (void *arg)
+{
+ const char *connect_url = (const char *)arg;
+ ConnectionFileDescriptor file_conn;
+ Error error;
+ if (file_conn.Connect (connect_url, &error) == eConnectionStatusSuccess)
+ {
+ char pid_str[256];
+ ::memset (pid_str, 0, sizeof(pid_str));
+ ConnectionStatus status;
+ const size_t pid_str_len = file_conn.Read (pid_str, sizeof(pid_str), status, NULL);
+ if (pid_str_len > 0)
+ {
+ int pid = atoi (pid_str);
+ return (void *)(intptr_t)pid;
+ }
+ }
+ return NULL;
+}
+//
+//static bool
+//WaitForProcessToSIGSTOP (const lldb::pid_t pid, const int timeout_in_seconds)
+//{
+// const int time_delta_usecs = 100000;
+// const int num_retries = timeout_in_seconds/time_delta_usecs;
+// for (int i=0; i<num_retries; i++)
+// {
+// struct proc_bsdinfo bsd_info;
+// int error = ::proc_pidinfo (pid, PROC_PIDTBSDINFO,
+// (uint64_t) 0,
+// &bsd_info,
+// PROC_PIDTBSDINFO_SIZE);
+//
+// switch (error)
+// {
+// case EINVAL:
+// case ENOTSUP:
+// case ESRCH:
+// case EPERM:
+// return false;
+//
+// default:
+// break;
+//
+// case 0:
+// if (bsd_info.pbi_status == SSTOP)
+// return true;
+// }
+// ::usleep (time_delta_usecs);
+// }
+// return false;
+//}
+
+bool
+GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
+{
+ // The 'A' packet is the most over designed packet ever here with
+ // redundant argument indexes, redundant argument lengths and needed hex
+ // encoded argument string values. Really all that is needed is a comma
+ // separated hex encoded argument value list, but we will stay true to the
+ // documented version of the 'A' packet here...
+
+ packet.SetFilePos(1); // Skip the 'A'
+ bool success = true;
+ while (success && packet.GetBytesLeft() > 0)
+ {
+ // Decode the decimal argument string length. This length is the
+ // number of hex nibbles in the argument string value.
+ const uint32_t arg_len = packet.GetU32(UINT32_MAX);
+ if (arg_len == UINT32_MAX)
+ success = false;
+ else
+ {
+ // Make sure the argument hex string length is followed by a comma
+ if (packet.GetChar() != ',')
+ success = false;
+ else
+ {
+ // Decode the argument index. We ignore this really becuase
+ // who would really send down the arguments in a random order???
+ const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
+ if (arg_idx == UINT32_MAX)
+ success = false;
+ else
+ {
+ // Make sure the argument index is followed by a comma
+ if (packet.GetChar() != ',')
+ success = false;
+ else
+ {
+ // Decode the argument string value from hex bytes
+ // back into a UTF8 string and make sure the length
+ // matches the one supplied in the packet
+ std::string arg;
+ if (packet.GetHexByteString(arg) != (arg_len / 2))
+ success = false;
+ else
+ {
+ // If there are any bytes lft
+ if (packet.GetBytesLeft())
+ {
+ if (packet.GetChar() != ',')
+ success = false;
+ }
+
+ if (success)
+ {
+ if (arg_idx == 0)
+ m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
+ m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (success)
+ {
+ m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
+ m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
+ if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ {
+ return SendOKResponse ();
+ }
+ }
+ return SendErrorResponse (8);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
+{
+ lldb::pid_t pid = m_process_launch_info.GetProcessID();
+ StreamString response;
+ response.Printf("QC%x", pid);
+ if (m_is_platform)
+ {
+ // If we launch a process and this GDB server is acting as a platform,
+ // then we need to clear the process launch state so we can start
+ // launching another process. In order to launch a process a bunch or
+ // packets need to be sent: environment packets, working directory,
+ // disable ASLR, and many more settings. When we launch a process we
+ // then need to know when to clear this information. Currently we are
+ // selecting the 'qC' packet as that packet which seems to make the most
+ // sense.
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ m_process_launch_info.Clear();
+ }
+ }
+ return SendPacket (response);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
+{
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ if (m_is_platform)
+ {
+ // Sleep and wait a bit for debugserver to start to listen...
+ ConnectionFileDescriptor file_conn;
+ char connect_url[PATH_MAX];
+ Error error;
+ char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX";
+ if (::mktemp (unix_socket_name) == NULL)
+ {
+ error.SetErrorString ("failed to make temporary path for a unix socket");
+ }
+ else
+ {
+ ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
+ // Spawn a new thread to accept the port that gets bound after
+ // binding to port 0 (zero).
+ lldb::thread_t accept_thread = Host::ThreadCreate (unix_socket_name,
+ AcceptPortFromInferior,
+ connect_url,
+ &error);
+
+ if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
+ {
+ // Spawn a debugserver and try to get
+ ProcessLaunchInfo debugserver_launch_info;
+ error = StartDebugserverProcess ("localhost:0",
+ unix_socket_name,
+ debugserver_launch_info);
+
+ lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
+ if (error.Success())
+ {
+ bool success = false;
+
+ thread_result_t accept_thread_result = NULL;
+ if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
+ {
+ if (accept_thread_result)
+ {
+ uint16_t port = (intptr_t)accept_thread_result;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%u;port:%u;", debugserver_pid, port);
+ assert (response_len < sizeof(response));
+ //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
+ success = SendPacket (response, response_len) > 0;
+ }
+ }
+ ::unlink (unix_socket_name);
+
+ if (!success)
+ {
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ ::kill (debugserver_pid, SIGINT);
+ }
+ return success;
+ }
+ }
+ }
+ }
+ return SendErrorResponse (13);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
+{
+ if (m_process_launch_error.Success())
+ return SendOKResponse();
+ StreamString response;
+ response.PutChar('E');
+ response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
+ return SendPacket (response);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QEnvironment:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0)
+ {
+ m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
+ return SendOKResponse ();
+ }
+ return SendErrorResponse (9);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QSetDisableASLR:"));
+ if (packet.GetU32(0))
+ m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+ else
+ m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
+ return SendOKResponse ();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QSetWorkingDir:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ m_process_launch_info.SwapWorkingDirectory (path);
+ return SendOKResponse ();
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QSetSTDIN:"));
+ ProcessLaunchInfo::FileAction file_action;
+ std::string path;
+ packet.GetHexByteString(path);
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDIN_FILENO, path.c_str(), read, write))
+ {
+ m_process_launch_info.AppendFileAction(file_action);
+ return SendOKResponse ();
+ }
+ return SendErrorResponse (10);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QSetSTDOUT:"));
+ ProcessLaunchInfo::FileAction file_action;
+ std::string path;
+ packet.GetHexByteString(path);
+ const bool read = true;
+ const bool write = false;
+ if (file_action.Open(STDOUT_FILENO, path.c_str(), read, write))
+ {
+ m_process_launch_info.AppendFileAction(file_action);
+ return SendOKResponse ();
+ }
+ return SendErrorResponse (11);
+}
+
+bool
+GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("QSetSTDERR:"));
+ ProcessLaunchInfo::FileAction file_action;
+ std::string path;
+ packet.GetHexByteString(path);
+ const bool read = true;
+ const bool write = true;
+ if (file_action.Open(STDERR_FILENO, path.c_str(), read, write))
+ {
+ m_process_launch_info.AppendFileAction(file_action);
+ return SendOKResponse ();
+ }
+ return SendErrorResponse (12);
+}
+
bool
GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
{
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 02440a2db96..1fddaeb5fea 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -31,7 +31,7 @@ public:
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
- GDBRemoteCommunicationServer();
+ GDBRemoteCommunicationServer(bool is_platform);
virtual
~GDBRemoteCommunicationServer();
@@ -53,10 +53,26 @@ public:
bool
HandshakeWithClient (lldb_private::Error *error_ptr);
+ // Set both ports to zero to let the platform automatically bind to
+ // a port chosen by the OS.
+ void
+ SetPortRange (uint16_t lo_port_num, uint16_t hi_port_num)
+ {
+ m_lo_port_num = lo_port_num;
+ m_hi_port_num = hi_port_num;
+ }
+
protected:
+ //typedef std::map<uint16_t, lldb::pid_t> PortToPIDMap;
+
lldb::thread_t m_async_thread;
- lldb_private::ProcessInfoList m_proc_infos;
+ lldb_private::ProcessLaunchInfo m_process_launch_info;
+ lldb_private::Error m_process_launch_error;
+ lldb_private::ProcessInstanceInfoList m_proc_infos;
uint32_t m_proc_infos_index;
+ uint16_t m_lo_port_num;
+ uint16_t m_hi_port_num;
+ //PortToPIDMap m_port_to_pid_map;
size_t
SendUnimplementedResponse (const char *packet);
@@ -68,9 +84,18 @@ protected:
SendOKResponse ();
bool
+ Handle_A (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
+
+ bool
Handle_qHostInfo (StringExtractorGDBRemote &packet);
bool
+ Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+
+ bool
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
bool
@@ -79,6 +104,9 @@ protected:
bool
Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
+ bool
+ Handle_qC (StringExtractorGDBRemote &packet);
+
bool
Handle_qUserName (StringExtractorGDBRemote &packet);
@@ -89,8 +117,26 @@ protected:
Handle_qSpeedTest (StringExtractorGDBRemote &packet);
bool
+ Handle_QEnvironment (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
+
+ bool
Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
+ bool
+ Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
+
+ bool
+ Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+
private:
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 0a1f87279f8..841efa207db 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -220,7 +220,7 @@ GDBRemoteRegisterContext::ReadRegisterBytes (uint32_t reg, DataExtractor &data)
if (gdb_comm.GetSequenceMutex (locker))
{
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
{
char packet[64];
StringExtractorGDBRemote response;
@@ -329,7 +329,7 @@ GDBRemoteRegisterContext::WriteRegisterBytes (uint32_t reg, DataExtractor &data,
if (gdb_comm.GetSequenceMutex (locker))
{
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
{
uint32_t offset, end_offset;
StreamString packet;
@@ -407,7 +407,7 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
{
char packet[32];
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
{
int packet_len = 0;
if (thread_suffix_supported)
@@ -449,7 +449,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
if (gdb_comm.GetSequenceMutex (locker))
{
const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- if (thread_suffix_supported || GetGDBProcess().SetCurrentGDBRemoteThread(m_thread.GetID()))
+ if (thread_suffix_supported || GetGDBProcess().GetGDBRemote().SetCurrentThread(m_thread.GetID()))
{
if (gdb_comm.SendPacketAndWaitForResponse((const char *)data_sp->GetBytes(),
data_sp->GetByteSize(),
@@ -474,91 +474,102 @@ GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, ui
void
GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
{
- static RegisterInfo
- g_register_infos[] =
- {
- // NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
- // ====== ======= == ==== ============= ============ =============== =============== ========= ===== ===========
- { "r0", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 0 }},
- { "r1", NULL, 4, 4, eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 1 }},
- { "r2", NULL, 4, 8, eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 2 }},
- { "r3", NULL, 4, 12, eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 3 }},
- { "r4", NULL, 4, 16, eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 4 }},
- { "r5", NULL, 4, 20, eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 5 }},
- { "r6", NULL, 4, 24, eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 6 }},
- { "r7", NULL, 4, 28, eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, 7 }},
- { "r8", NULL, 4, 32, eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 8 }},
- { "r9", NULL, 4, 36, eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 9 }},
- { "r10", NULL, 4, 40, eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 10 }},
- { "r11", NULL, 4, 44, eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 11 }},
- { "r12", NULL, 4, 48, eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 12 }},
- { "sp", "r13", 4, 52, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 13 }},
- { "lr", "r14", 4, 56, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, 14 }},
- { "pc", "r15", 4, 60, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 15 }},
-// { NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 16 }},
-// { NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 17 }},
-// { NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 18 }},
-// { NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 19 }},
-// { NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 20 }},
-// { NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 21 }},
-// { NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 22 }},
-// { NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 23 }},
-// { NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 24 }},
- { "cpsr", "psr", 4, 172, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 25 }},
- { "s0", NULL, 4, 176, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 26 }},
- { "s1", NULL, 4, 180, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 27 }},
- { "s2", NULL, 4, 184, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 28 }},
- { "s3", NULL, 4, 188, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 29 }},
- { "s4", NULL, 4, 192, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 30 }},
- { "s5", NULL, 4, 196, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 31 }},
- { "s6", NULL, 4, 200, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 32 }},
- { "s7", NULL, 4, 204, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 33 }},
- { "s8", NULL, 4, 208, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 34 }},
- { "s9", NULL, 4, 212, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 35 }},
- { "s10", NULL, 4, 216, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 36 }},
- { "s11", NULL, 4, 220, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 37 }},
- { "s12", NULL, 4, 224, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 38 }},
- { "s13", NULL, 4, 228, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 39 }},
- { "s14", NULL, 4, 232, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 40 }},
- { "s15", NULL, 4, 236, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 41 }},
- { "s16", NULL, 4, 240, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 42 }},
- { "s17", NULL, 4, 244, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 43 }},
- { "s18", NULL, 4, 248, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 44 }},
- { "s19", NULL, 4, 252, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 45 }},
- { "s20", NULL, 4, 256, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 46 }},
- { "s21", NULL, 4, 260, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 47 }},
- { "s22", NULL, 4, 264, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 48 }},
- { "s23", NULL, 4, 268, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 49 }},
- { "s24", NULL, 4, 272, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 50 }},
- { "s25", NULL, 4, 276, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 51 }},
- { "s26", NULL, 4, 280, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 52 }},
- { "s27", NULL, 4, 284, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 53 }},
- { "s28", NULL, 4, 288, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 54 }},
- { "s29", NULL, 4, 292, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 55 }},
- { "s30", NULL, 4, 296, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 56 }},
- { "s31", NULL, 4, 300, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 57 }},
- { "fpscr", NULL, 4, 304, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58 }},
- { "d16", NULL, 8, 308, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 59 }},
- { "d17", NULL, 8, 316, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 60 }},
- { "d18", NULL, 8, 324, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 61 }},
- { "d19", NULL, 8, 332, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 62 }},
- { "d20", NULL, 8, 340, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 63 }},
- { "d21", NULL, 8, 348, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 64 }},
- { "d22", NULL, 8, 356, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 65 }},
- { "d23", NULL, 8, 364, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 66 }},
- { "d24", NULL, 8, 372, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 67 }},
- { "d25", NULL, 8, 380, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 68 }},
- { "d26", NULL, 8, 388, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 69 }},
- { "d27", NULL, 8, 396, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 70 }},
- { "d28", NULL, 8, 404, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 71 }},
- { "d29", NULL, 8, 412, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 72 }},
- { "d30", NULL, 8, 420, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 73 }},
- { "d31", NULL, 8, 428, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 74 }},
+ static RegisterInfo g_register_infos[] = {
+// NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB
+// ====== ====== === === ============= ============ =================== =================== ====================== === ====
+ { "r0", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, 0, 0 }},
+ { "r1", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, 1, 1 }},
+ { "r2", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, 2, 2 }},
+ { "r3", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, 3, 3 }},
+ { "r4", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }},
+ { "r5", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }},
+ { "r6", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }},
+ { "r7", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }},
+ { "r8", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }},
+ { "r9", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }},
+ { "r10", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }},
+ { "r11", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }},
+ { "r12", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }},
+ { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }},
+ { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }},
+ { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }},
+ { "f0", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }},
+ { "f1", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }},
+ { "f2", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }},
+ { "f3", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }},
+ { "f4", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }},
+ { "f5", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }},
+ { "f6", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }},
+ { "f7", NULL, 12, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }},
+ { "fps", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }},
+ { "cpsr", "psr", 4, 0, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }},
+ { "s0", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }},
+ { "s1", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }},
+ { "s2", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }},
+ { "s3", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }},
+ { "s4", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }},
+ { "s5", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }},
+ { "s6", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }},
+ { "s7", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }},
+ { "s8", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }},
+ { "s9", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }},
+ { "s10", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }},
+ { "s11", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }},
+ { "s12", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }},
+ { "s13", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }},
+ { "s14", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }},
+ { "s15", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }},
+ { "s16", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }},
+ { "s17", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }},
+ { "s18", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }},
+ { "s19", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }},
+ { "s20", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }},
+ { "s21", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }},
+ { "s22", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }},
+ { "s23", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }},
+ { "s24", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }},
+ { "s25", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }},
+ { "s26", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }},
+ { "s27", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }},
+ { "s28", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }},
+ { "s29", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }},
+ { "s30", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }},
+ { "s31", NULL, 4, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }},
+ { "fpscr",NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }},
+ { "d16", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }},
+ { "d17", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }},
+ { "d18", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }},
+ { "d19", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }},
+ { "d20", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }},
+ { "d21", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }},
+ { "d22", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }},
+ { "d23", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }},
+ { "d24", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }},
+ { "d25", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }},
+ { "d26", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }},
+ { "d27", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }},
+ { "d28", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }},
+ { "d29", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }},
+ { "d30", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }},
+ { "d31", NULL, 8, 0, eEncodingIEEE754, eFormatHex, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }},
};
+
static const uint32_t num_registers = sizeof (g_register_infos)/sizeof (RegisterInfo);
static ConstString gpr_reg_set ("General Purpose Registers");
+ static ConstString sfp_reg_set ("Software Floating Point Registers");
static ConstString vfp_reg_set ("Floating Point Registers");
- for (uint32_t i=0; i<num_registers; ++i)
+ uint32_t i;
+ // Calculate the offsets of the registers
+ if (g_register_infos[2].byte_offset == 0)
+ {
+ uint32_t byte_offset = 0;
+ for (i=0; i<num_registers; ++i)
+ {
+ g_register_infos[i].byte_offset = byte_offset;
+ byte_offset += g_register_infos[i].byte_size;
+ }
+ }
+ for (i=0; i<num_registers; ++i)
{
ConstString name;
ConstString alt_name;
@@ -566,8 +577,13 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
name.SetCString(g_register_infos[i].name);
if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
alt_name.SetCString(g_register_infos[i].alt_name);
-
- AddRegister (g_register_infos[i], name, alt_name, i < 26 ? gpr_reg_set : vfp_reg_set);
+
+ if (i <= 15 || i == 25)
+ AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set);
+ else if (i <= 24)
+ AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set);
+ else
+ AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set);
}
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index ec07fbee072..79f77e219d1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -114,16 +114,13 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
Process (target, listener),
m_flags (0),
m_stdio_mutex (Mutex::eMutexTypeRecursive),
- m_gdb_comm(),
+ m_gdb_comm(false),
m_debugserver_pid (LLDB_INVALID_PROCESS_ID),
m_debugserver_thread (LLDB_INVALID_HOST_THREAD),
m_last_stop_packet (),
m_register_info (),
m_async_broadcaster ("lldb.process.gdb-remote.async-broadcaster"),
m_async_thread (LLDB_INVALID_HOST_THREAD),
- m_curr_tid (LLDB_INVALID_THREAD_ID),
- m_curr_tid_run (LLDB_INVALID_THREAD_ID),
- m_z0_supported (1),
m_continue_c_tids (),
m_continue_C_tids (),
m_continue_s_tids (),
@@ -430,7 +427,6 @@ ProcessGDBRemote::DoLaunch
ObjectFile * object_file = module->GetObjectFile();
if (object_file)
{
- ArchSpec inferior_arch(module->GetArchitecture());
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
char connect_url[128];
@@ -439,13 +435,7 @@ ProcessGDBRemote::DoLaunch
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
- error = StartDebugserverProcess (host_port,
- NULL,
- NULL,
- LLDB_INVALID_PROCESS_ID,
- NULL,
- false,
- inferior_arch);
+ error = StartDebugserverProcess (host_port);
if (error.Fail())
return error;
@@ -700,8 +690,6 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
Error error;
// Clear out and clean up from any current state
Clear();
- const ArchSpec &arch_spec = GetTarget().GetArchitecture();
-
if (attach_pid != LLDB_INVALID_PROCESS_ID)
{
// Make sure we aren't already connected?
@@ -712,13 +700,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
- error = StartDebugserverProcess (host_port, // debugserver_url
- NULL, // inferior_argv
- NULL, // inferior_envp
- LLDB_INVALID_PROCESS_ID, // Don't send any attach to pid options to debugserver
- NULL, // Don't send any attach by process name option to debugserver
- false, // Don't send any attach wait_for_launch flag as an option to debugserver
- arch_spec);
+ error = StartDebugserverProcess (host_port);
if (error.Fail())
{
@@ -778,21 +760,12 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
-
- const ArchSpec &arch_spec = GetTarget().GetArchitecture();
-
char host_port[128];
snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
char connect_url[128];
snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
- error = StartDebugserverProcess (host_port, // debugserver_url
- NULL, // inferior_argv
- NULL, // inferior_envp
- LLDB_INVALID_PROCESS_ID, // Don't send any attach to pid options to debugserver
- NULL, // Don't send any attach by process name option to debugserver
- false, // Don't send any attach wait_for_launch flag as an option to debugserver
- arch_spec);
+ error = StartDebugserverProcess (host_port);
if (error.Fail())
{
const char *error_string = error.AsCString();
@@ -925,7 +898,7 @@ ProcessGDBRemote::DoResume ()
if (num_continue_c_tids == num_threads)
{
// All threads are resuming...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.PutChar ('c');
}
else if (num_continue_c_tids == 1 &&
@@ -934,7 +907,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 0 )
{
// Only one thread is continuing
- SetCurrentGDBRemoteThreadForRun (m_continue_c_tids.front());
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
continue_packet.PutChar ('c');
}
else
@@ -960,7 +933,7 @@ ProcessGDBRemote::DoResume ()
if (!continue_packet_error)
{
// Add threads continuing with the same signo...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.Printf("C%2.2x", continue_signo);
}
}
@@ -970,7 +943,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 0 )
{
// Only one thread is continuing with signal
- SetCurrentGDBRemoteThreadForRun (m_continue_C_tids.front().first);
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
continue_packet.Printf("C%2.2x", m_continue_C_tids.front().second);
}
else
@@ -985,7 +958,7 @@ ProcessGDBRemote::DoResume ()
if (num_continue_s_tids == num_threads)
{
// All threads are resuming...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.PutChar ('s');
}
else if (num_continue_c_tids == 0 &&
@@ -994,7 +967,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 0 )
{
// Only one thread is stepping
- SetCurrentGDBRemoteThreadForRun (m_continue_s_tids.front());
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
continue_packet.PutChar ('s');
}
else
@@ -1021,7 +994,7 @@ ProcessGDBRemote::DoResume ()
if (!continue_packet_error)
{
// Add threads stepping with the same signo...
- SetCurrentGDBRemoteThreadForRun (-1);
+ m_gdb_comm.SetCurrentThreadForRun (-1);
continue_packet.Printf("S%2.2x", step_signo);
}
}
@@ -1031,7 +1004,7 @@ ProcessGDBRemote::DoResume ()
num_continue_S_tids == 1 )
{
// Only one thread is stepping with signal
- SetCurrentGDBRemoteThreadForRun (m_continue_S_tids.front().first);
+ m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
}
else
@@ -1667,40 +1640,28 @@ ProcessGDBRemote::EnableBreakpoint (BreakpointSite *bp_site)
{
// Try and set hardware breakpoint, and if that fails, fall through
// and set a software breakpoint?
- }
-
- if (m_z0_supported)
- {
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "Z0,%llx,%zx", addr, bp_op_size);
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
+ if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointHardware))
{
- if (response.IsUnsupportedResponse())
- {
- // Disable z packet support and try again
- m_z0_supported = 0;
- return EnableBreakpoint (bp_site);
- }
- else if (response.IsOKResponse())
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0)
{
bp_site->SetEnabled(true);
- bp_site->SetType (BreakpointSite::eExternal);
+ bp_site->SetType (BreakpointSite::eHardware);
return error;
}
- else
- {
- uint8_t error_byte = response.GetError();
- if (error_byte)
- error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
- }
}
}
- else
+
+ if (m_gdb_comm.SupportsGDBStoppointPacket (eBreakpointSoftware))
{
- return EnableSoftwareBreakpoint (bp_site);
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0)
+ {
+ bp_site->SetEnabled(true);
+ bp_site->SetType (BreakpointSite::eExternal);
+ return error;
+ }
}
+
+ return EnableSoftwareBreakpoint (bp_site);
}
if (log)
@@ -1731,44 +1692,25 @@ ProcessGDBRemote::DisableBreakpoint (BreakpointSite *bp_site)
{
const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
- if (bp_site->IsHardware())
- {
- // TODO: disable hardware breakpoint...
- }
- else
+ BreakpointSite::Type bp_type = bp_site->GetType();
+ switch (bp_type)
{
- if (m_z0_supported)
- {
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "z0,%llx,%zx", addr, bp_op_size);
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
- {
- if (response.IsUnsupportedResponse())
- {
- error.SetErrorString("Breakpoint site was set with Z packet, yet remote debugserver states z packets are not supported.");
- }
- else if (response.IsOKResponse())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DisableBreakpoint (site_id = %d) addr = 0x%8.8llx -- SUCCESS", site_id, (uint64_t)addr);
- bp_site->SetEnabled(false);
- return error;
- }
- else
- {
- uint8_t error_byte = response.GetError();
- if (error_byte)
- error.SetErrorStringWithFormat("%x packet failed with error: %i (0x%2.2x).\n", packet, error_byte, error_byte);
- }
- }
- }
- else
- {
- return DisableSoftwareBreakpoint (bp_site);
- }
+ case BreakpointSite::eSoftware:
+ error = DisableSoftwareBreakpoint (bp_site);
+ break;
+
+ case BreakpointSite::eHardware:
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+ error.SetErrorToGenericError();
+ break;
+
+ case BreakpointSite::eExternal:
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, false, addr, bp_op_size))
+ error.SetErrorToGenericError();
+ break;
}
+ if (error.Success())
+ bp_site->SetEnabled(false);
}
else
{
@@ -1869,16 +1811,7 @@ ProcessGDBRemote::DoSignal (int signo)
}
Error
-ProcessGDBRemote::StartDebugserverProcess
-(
- const char *debugserver_url, // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
- char const *inferior_argv[], // Arguments for the inferior program including the path to the inferior itself as the first argument
- char const *inferior_envp[], // Environment to pass along to the inferior program
- lldb::pid_t attach_pid, // If inferior inferior_argv == NULL, and attach_pid != LLDB_INVALID_PROCESS_ID send this pid as an argument to debugserver
- const char *attach_name, // Wait for the next process to launch whose basename matches "attach_name"
- bool wait_for_launch, // Wait for the process named "attach_name" to launch
- const ArchSpec& inferior_arch // The arch of the inferior that we will launch
-)
+ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url) // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
{
Error error;
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
@@ -1886,8 +1819,9 @@ ProcessGDBRemote::StartDebugserverProcess
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
- FileSpec debugserver_file_spec;
+ ProcessLaunchInfo launch_info;
char debugserver_path[PATH_MAX];
+ FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
// Always check to see if we have an environment override for the path
// to the debugserver to use and use it if we do.
@@ -1922,25 +1856,10 @@ ProcessGDBRemote::StartDebugserverProcess
debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
m_stdio_communication.Clear();
- posix_spawnattr_t attr;
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error local_err; // Errors that don't affect the spawning.
- if (log)
- log->Printf ("%s ( path='%s', argv=%p, envp=%p, arch=%s )",
- __FUNCTION__,
- debugserver_path,
- inferior_argv,
- inferior_envp,
- inferior_arch.GetArchitectureName());
- error.SetError( ::posix_spawnattr_init (&attr), eErrorTypePOSIX);
- if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnattr_init ( &attr )");
- if (error.Fail())
- return error;
-
- Args debugserver_args;
+ Args &debugserver_args = launch_info.GetArguments();
char arg_cstr[PATH_MAX];
// Start args with "debugserver /file/path -r --"
@@ -1968,6 +1887,12 @@ ProcessGDBRemote::StartDebugserverProcess
// debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
// debugserver_args.AppendArgument("--log-flags=0x802e0e");
+ // We currently send down all arguments, attach pids, or attach
+ // process names in dedicated GDB server packets, so we don't need
+ // to pass them as arguments. This is currently because of all the
+ // things we need to setup prior to launching: the environment,
+ // current working dir, file actions, etc.
+#if 0
// Now append the program arguments
if (inferior_argv)
{
@@ -1990,20 +1915,18 @@ ProcessGDBRemote::StartDebugserverProcess
debugserver_args.AppendArgument ("--attach");
debugserver_args.AppendArgument (attach_name);
}
-
- Error file_actions_err;
- posix_spawn_file_actions_t file_actions;
-#if DONT_CLOSE_DEBUGSERVER_STDIO
- file_actions_err.SetErrorString ("Remove this after uncommenting the code block below.");
-#else
- file_actions_err.SetError( ::posix_spawn_file_actions_init (&file_actions), eErrorTypePOSIX);
- if (file_actions_err.Success())
- {
- ::posix_spawn_file_actions_addclose (&file_actions, STDIN_FILENO);
- ::posix_spawn_file_actions_addclose (&file_actions, STDOUT_FILENO);
- ::posix_spawn_file_actions_addclose (&file_actions, STDERR_FILENO);
- }
#endif
+
+ ProcessLaunchInfo::FileAction file_action;
+
+ // Close STDIN, STDOUT and STDERR. We might need to redirect them
+ // to "/dev/null" if we run into any problems.
+ file_action.Close (STDIN_FILENO);
+ launch_info.AppendFileAction (file_action);
+ file_action.Close (STDOUT_FILENO);
+ launch_info.AppendFileAction (file_action);
+ file_action.Close (STDERR_FILENO);
+ launch_info.AppendFileAction (file_action);
if (log)
{
@@ -2012,28 +1935,15 @@ ProcessGDBRemote::StartDebugserverProcess
log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
}
- error.SetError (::posix_spawnp (&m_debugserver_pid,
- debugserver_path,
- file_actions_err.Success() ? &file_actions : NULL,
- &attr,
- debugserver_args.GetArgumentVector(),
- (char * const*)inferior_envp),
- eErrorTypePOSIX);
-
-
- ::posix_spawnattr_destroy (&attr);
-
- if (file_actions_err.Success())
- ::posix_spawn_file_actions_destroy (&file_actions);
+ error = Host::LaunchProcess(launch_info);
- // We have seen some cases where posix_spawnp was returning a valid
- // looking pid even when an error was returned, so clear it out
- if (error.Fail())
+ if (error.Success ())
+ m_debugserver_pid = launch_info.GetProcessID();
+ else
m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
if (error.Fail() || log)
- error.PutToLog(log.get(), "::posix_spawnp ( pid => %i, path = '%s', file_actions = %p, attr = %p, argv = %p, envp = %p )", m_debugserver_pid, debugserver_path, NULL, &attr, inferior_argv, inferior_envp);
-
+ error.PutToLog(log.get(), "Host::LaunchProcess (launch_info) => pid=%i, path='%s'", m_debugserver_pid, debugserver_path);
}
else
{
@@ -2143,71 +2053,8 @@ ProcessGDBRemote::Initialize()
}
bool
-ProcessGDBRemote::SetCurrentGDBRemoteThread (int tid)
-{
- if (m_curr_tid == tid)
- return true;
-
- char packet[32];
- int packet_len;
- if (tid <= 0)
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%i", tid);
- else
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%x", tid);
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
- {
- if (response.IsOKResponse())
- {
- m_curr_tid = tid;
- return true;
- }
- }
- return false;
-}
-
-bool
-ProcessGDBRemote::SetCurrentGDBRemoteThreadForRun (int tid)
-{
- if (m_curr_tid_run == tid)
- return true;
-
- char packet[32];
- int packet_len;
- if (tid <= 0)
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%i", tid);
- else
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%x", tid);
-
- assert (packet_len + 1 < sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
- {
- if (response.IsOKResponse())
- {
- m_curr_tid_run = tid;
- return true;
- }
- }
- return false;
-}
-
-void
-ProcessGDBRemote::ResetGDBRemoteState ()
-{
- // Reset and GDB remote state
- m_curr_tid = LLDB_INVALID_THREAD_ID;
- m_curr_tid_run = LLDB_INVALID_THREAD_ID;
- m_z0_supported = 1;
-}
-
-
-bool
ProcessGDBRemote::StartAsyncThread ()
{
- ResetGDBRemoteState ();
-
LogSP log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
if (log)
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index e9ab4df70f0..cf03604a182 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -215,12 +215,6 @@ protected:
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
- bool
- SetCurrentGDBRemoteThread (int tid);
-
- bool
- SetCurrentGDBRemoteThreadForRun (int tid);
-
//----------------------------------------------------------------------
// Accessors
//----------------------------------------------------------------------
@@ -275,13 +269,7 @@ protected:
UpdateThreadListIfNeeded ();
lldb_private::Error
- StartDebugserverProcess (const char *debugserver_url, // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
- char const *inferior_argv[],
- char const *inferior_envp[],
- lldb::pid_t attach_pid, // If inferior inferior_argv == NULL, then attach to this pid
- const char *attach_pid_name, // Wait for the next process to launch whose basename matches "attach_wait_name"
- bool wait_for_launch, // Wait for the process named "attach_wait_name" to launch
- const lldb_private::ArchSpec& arch_spec);
+ StartDebugserverProcess (const char *debugserver_url);
void
KillDebugserverProcess ();
@@ -313,11 +301,6 @@ protected:
GDBRemoteDynamicRegisterInfo m_register_info;
lldb_private::Broadcaster m_async_broadcaster;
lldb::thread_t m_async_thread;
- // Current GDB remote state. Any members added here need to be reset to
- // proper default values in ResetGDBRemoteState ().
- lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
- lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
- uint32_t m_z0_supported:1; // Set to non-zero if Z0 and z0 packets are supported
typedef std::vector<lldb::tid_t> tid_collection;
typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
tid_collection m_continue_c_tids; // 'c' for continue
@@ -330,9 +313,6 @@ protected:
bool m_local_debugserver; // Is the debugserver process we are talking to local or on another machine.
std::vector<lldb::user_id_t> m_thread_observation_bps;
- void
- ResetGDBRemoteState ();
-
bool
StartAsyncThread ();
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 9955409226a..351b6eb2bc9 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -261,13 +261,10 @@ ThreadGDBRemote::GetPrivateStopReason ()
m_thread_stop_reason_stop_id = process_stop_id;
m_actual_stop_info_sp.reset();
- char packet[256];
- ::snprintf(packet, sizeof(packet), "qThreadStopInfo%x", GetID());
StringExtractorGDBRemote stop_packet;
- if (GetGDBProcess().GetGDBRemote().SendPacketAndWaitForResponse(packet, stop_packet, false))
- {
- GetGDBProcess().SetThreadStopInfo (stop_packet);
- }
+ ProcessGDBRemote &gdb_process = GetGDBProcess();
+ if (gdb_process.GetGDBRemote().GetThreadStopInfo(GetID(), stop_packet))
+ gdb_process.SetThreadStopInfo (stop_packet);
}
return m_actual_stop_info_sp;
}
diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp
index 458420893ae..a2568a3bbf4 100644
--- a/lldb/source/Symbol/ObjectFile.cpp
+++ b/lldb/source/Symbol/ObjectFile.cpp
@@ -61,8 +61,8 @@ ObjectFile::FindPlugin (Module* module, const FileSpec* file, lldb::addr_t file_
// No need to delegate further if (file_offset, file_size) exceeds the total file size.
// This is the base case.
- if (file_offset + file_size > file->GetByteSize())
- return NULL;
+// if (file_offset + file_size > file->GetByteSize())
+// return NULL;
DataBufferSP file_header_data_sp(file->ReadFileContents(file_offset, 512));
uint32_t idx;
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index cddd37ff6be..34c7337979e 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -14,9 +14,11 @@
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Error.h"
+#include "lldb/Core/Log.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
using namespace lldb;
@@ -165,6 +167,9 @@ Platform::Platform (bool is_host) :
m_max_uid_name_len (0),
m_max_gid_name_len (0)
{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p Platform::Platform()", this);
}
//------------------------------------------------------------------
@@ -175,6 +180,9 @@ Platform::Platform (bool is_host) :
//------------------------------------------------------------------
Platform::~Platform()
{
+ LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
+ if (log)
+ log->Printf ("%p Platform::~Platform()", this);
}
void
@@ -300,6 +308,15 @@ Platform::GetOSKernelDescription (std::string &s)
}
const char *
+Platform::GetName ()
+{
+ const char *name = GetHostname();
+ if (name == NULL || name[0] == '\0')
+ name = GetShortPluginName();
+ return name;
+}
+
+const char *
Platform::GetHostname ()
{
if (IsHost() && m_name.empty())
@@ -498,21 +515,66 @@ Platform::DisconnectRemote ()
}
bool
-Platform::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info)
+Platform::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
{
// Take care of the host case so that each subclass can just
- // call Platform::GetProcessInfo (pid, process_info)
+ // call this function to get the host functionality.
if (IsHost())
return Host::GetProcessInfo (pid, process_info);
return false;
}
uint32_t
-Platform::FindProcesses (const ProcessInfoMatch &match_info,
- ProcessInfoList &process_infos)
+Platform::FindProcesses (const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos)
{
+ // Take care of the host case so that each subclass can just
+ // call this function to get the host functionality.
uint32_t match_count = 0;
if (IsHost())
match_count = Host::FindProcesses (match_info, process_infos);
return match_count;
}
+
+
+Error
+Platform::LaunchProcess (ProcessLaunchInfo &launch_info)
+{
+ Error error;
+ // Take care of the host case so that each subclass can just
+ // call this function to get the host functionality.
+ if (IsHost())
+ error = Host::LaunchProcess (launch_info);
+ else
+ error.SetErrorString ("base lldb_private::Platform class can't launch remote processes");
+ return error;
+}
+
+lldb::ProcessSP
+Platform::DebugProcess (ProcessLaunchInfo &launch_info,
+ Debugger &debugger,
+ Target *target, // Can be NULL, if NULL create a new target, else use existing one
+ Listener &listener,
+ Error &error)
+{
+ ProcessSP process_sp;
+ // Make sure we stop at the entry point
+ launch_info.GetFlags ().Set (eLaunchFlagDebug);
+ error = LaunchProcess (launch_info);
+ if (error.Success())
+ {
+ lldb::pid_t pid = launch_info.GetProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ {
+ process_sp = Attach (pid, debugger, target, listener, error);
+
+// if (process_sp)
+// {
+// if (launch_info.GetFlags().IsClear (eLaunchFlagStopAtEntry))
+// process_sp->Resume();
+// }
+ }
+ }
+ return process_sp;
+}
+
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 940ff2bd949..c33dd183ec9 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -40,7 +40,7 @@ using namespace lldb;
using namespace lldb_private;
void
-ProcessInfo::Dump (Stream &s, Platform *platform) const
+ProcessInstanceInfo::Dump (Stream &s, Platform *platform) const
{
const char *cstr;
if (m_pid != LLDB_INVALID_PROCESS_ID)
@@ -56,59 +56,80 @@ ProcessInfo::Dump (Stream &s, Platform *platform) const
m_executable.Dump(&s);
s.EOL();
}
- const uint32_t argc = m_args.GetSize();
+ const uint32_t argc = m_arguments.GetArgumentCount();
if (argc > 0)
{
for (uint32_t i=0; i<argc; i++)
{
+ const char *arg = m_arguments.GetArgumentAtIndex(i);
if (i < 10)
- s.Printf (" arg[%u] = %s\n", i, m_args.GetStringAtIndex(i));
+ s.Printf (" arg[%u] = %s\n", i, arg);
else
- s.Printf ("arg[%u] = %s\n", i, m_args.GetStringAtIndex(i));
+ s.Printf ("arg[%u] = %s\n", i, arg);
}
}
+
+ const uint32_t envc = m_environment.GetArgumentCount();
+ if (envc > 0)
+ {
+ for (uint32_t i=0; i<envc; i++)
+ {
+ const char *env = m_environment.GetArgumentAtIndex(i);
+ if (i < 10)
+ s.Printf (" env[%u] = %s\n", i, env);
+ else
+ s.Printf ("env[%u] = %s\n", i, env);
+ }
+ }
+
if (m_arch.IsValid())
s.Printf (" arch = %s\n", m_arch.GetTriple().str().c_str());
- if (m_real_uid != UINT32_MAX)
+ if (m_uid != UINT32_MAX)
{
- cstr = platform->GetUserName (m_real_uid);
- s.Printf (" uid = %-5u (%s)\n", m_real_uid, cstr ? cstr : "");
+ cstr = platform->GetUserName (m_uid);
+ s.Printf (" uid = %-5u (%s)\n", m_uid, cstr ? cstr : "");
}
- if (m_real_gid != UINT32_MAX)
+ if (m_gid != UINT32_MAX)
{
- cstr = platform->GetGroupName (m_real_gid);
- s.Printf (" gid = %-5u (%s)\n", m_real_gid, cstr ? cstr : "");
+ cstr = platform->GetGroupName (m_gid);
+ s.Printf (" gid = %-5u (%s)\n", m_gid, cstr ? cstr : "");
}
- if (m_effective_uid != UINT32_MAX)
+ if (m_euid != UINT32_MAX)
{
- cstr = platform->GetUserName (m_effective_uid);
- s.Printf (" euid = %-5u (%s)\n", m_effective_uid, cstr ? cstr : "");
+ cstr = platform->GetUserName (m_euid);
+ s.Printf (" euid = %-5u (%s)\n", m_euid, cstr ? cstr : "");
}
- if (m_effective_gid != UINT32_MAX)
+ if (m_egid != UINT32_MAX)
{
- cstr = platform->GetGroupName (m_effective_gid);
- s.Printf (" egid = %-5u (%s)\n", m_effective_gid, cstr ? cstr : "");
+ cstr = platform->GetGroupName (m_egid);
+ s.Printf (" egid = %-5u (%s)\n", m_egid, cstr ? cstr : "");
}
}
void
-ProcessInfo::DumpTableHeader (Stream &s, Platform *platform, bool verbose)
+ProcessInstanceInfo::DumpTableHeader (Stream &s, Platform *platform, bool show_args, bool verbose)
{
+ const char *label;
+ if (show_args || verbose)
+ label = "ARGUMENTS";
+ else
+ label = "NAME";
+
if (verbose)
{
- s.PutCString ("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE NAME\n");
+ s.Printf ("PID PARENT USER GROUP EFF USER EFF GROUP TRIPLE %s\n", label);
s.PutCString ("====== ====== ========== ========== ========== ========== ======================== ============================\n");
}
else
{
- s.PutCString ("PID PARENT USER ARCH NAME\n");
+ s.Printf ("PID PARENT USER ARCH %s\n", label);
s.PutCString ("====== ====== ========== ======= ============================\n");
}
}
void
-ProcessInfo::DumpAsTableRow (Stream &s, Platform *platform, bool verbose) const
+ProcessInstanceInfo::DumpAsTableRow (Stream &s, Platform *platform, bool show_args, bool verbose) const
{
if (m_pid != LLDB_INVALID_PROCESS_ID)
{
@@ -118,49 +139,49 @@ ProcessInfo::DumpAsTableRow (Stream &s, Platform *platform, bool verbose) const
if (verbose)
{
- cstr = platform->GetUserName (m_real_uid);
+ cstr = platform->GetUserName (m_uid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
- s.Printf ("%-10u ", m_real_uid);
+ s.Printf ("%-10u ", m_uid);
- cstr = platform->GetGroupName (m_real_gid);
+ cstr = platform->GetGroupName (m_gid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
- s.Printf ("%-10u ", m_real_gid);
+ s.Printf ("%-10u ", m_gid);
- cstr = platform->GetUserName (m_effective_uid);
+ cstr = platform->GetUserName (m_euid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
- s.Printf ("%-10u ", m_effective_uid);
+ s.Printf ("%-10u ", m_euid);
- cstr = platform->GetGroupName (m_effective_gid);
+ cstr = platform->GetGroupName (m_egid);
if (cstr && cstr[0]) // Watch for empty string that indicates lookup failed
s.Printf ("%-10s ", cstr);
else
- s.Printf ("%-10u ", m_effective_gid);
+ s.Printf ("%-10u ", m_egid);
s.Printf ("%-24s ", m_arch.IsValid() ? m_arch.GetTriple().str().c_str() : "");
}
else
{
s.Printf ("%-10s %.*-7s ",
- platform->GetUserName (m_effective_uid),
+ platform->GetUserName (m_euid),
(int)m_arch.GetTriple().getArchName().size(),
m_arch.GetTriple().getArchName().data());
}
- if (verbose)
+ if (verbose || show_args)
{
- const uint32_t argc = m_args.GetSize();
+ const uint32_t argc = m_arguments.GetArgumentCount();
if (argc > 0)
{
for (uint32_t i=0; i<argc; i++)
{
if (i > 0)
s.PutChar (' ');
- s.PutCString (m_args.GetStringAtIndex(i));
+ s.PutCString (m_arguments.GetArgumentAtIndex(i));
}
}
}
@@ -173,8 +194,263 @@ ProcessInfo::DumpAsTableRow (Stream &s, Platform *platform, bool verbose) const
}
}
+
+void
+ProcessInfo::SetArgumentsFromArgs (const Args& args,
+ bool first_arg_is_executable,
+ bool first_arg_is_executable_and_argument)
+{
+ // Copy all arguments
+ m_arguments = args;
+
+ // Is the first argument the executable?
+ if (first_arg_is_executable)
+ {
+ const char *first_arg = args.GetArgumentAtIndex (0);
+ if (first_arg)
+ {
+ // Yes the first argument is an executable, set it as the executable
+ // in the launch options. Don't resolve the file path as the path
+ // could be a remote platform path
+ const bool resolve = false;
+ m_executable.SetFile(first_arg, resolve);
+
+ // If argument zero is an executable and shouldn't be included
+ // in the arguments, remove it from the front of the arguments
+ if (first_arg_is_executable_and_argument == false)
+ m_arguments.DeleteArgumentAtIndex (0);
+ }
+ }
+}
+
+bool
+ProcessLaunchInfo::FileAction::Open (int fd, const char *path, bool read, bool write)
+{
+ if ((read || write) && fd >= 0 && path && path[0])
+ {
+ m_action = eFileActionOpen;
+ m_fd = fd;
+ if (read && write)
+ m_arg = O_RDWR;
+ else if (read)
+ m_arg = O_RDONLY;
+ else
+ m_arg = O_WRONLY;
+ m_path.assign (path);
+ return true;
+ }
+ else
+ {
+ Clear();
+ }
+ return false;
+}
+
bool
-ProcessInfoMatch::NameMatches (const char *process_name) const
+ProcessLaunchInfo::FileAction::Close (int fd)
+{
+ Clear();
+ if (fd >= 0)
+ {
+ m_action = eFileActionClose;
+ m_fd = fd;
+ }
+ return m_fd >= 0;
+}
+
+
+bool
+ProcessLaunchInfo::FileAction::Duplicate (int fd, int dup_fd)
+{
+ Clear();
+ if (fd >= 0 && dup_fd >= 0)
+ {
+ m_action = eFileActionDuplicate;
+ m_fd = fd;
+ m_arg = dup_fd;
+ }
+ return m_fd >= 0;
+}
+
+
+
+bool
+ProcessLaunchInfo::FileAction::AddPosixSpawnFileAction (posix_spawn_file_actions_t *file_actions,
+ const FileAction *info,
+ Log *log,
+ Error& error)
+{
+ if (info == NULL)
+ return false;
+
+ switch (info->m_action)
+ {
+ case eFileActionNone:
+ error.Clear();
+ break;
+
+ case eFileActionClose:
+ if (info->m_fd == -1)
+ error.SetErrorString ("invalid fd for posix_spawn_file_actions_addclose(...)");
+ else
+ {
+ error.SetError (::posix_spawn_file_actions_addclose (file_actions, info->m_fd),
+ eErrorTypePOSIX);
+ if (log && (error.Fail() || log))
+ error.PutToLog(log, "posix_spawn_file_actions_addclose (action=%p, fd=%i)",
+ file_actions, info->m_fd);
+ }
+ break;
+
+ case eFileActionDuplicate:
+ if (info->m_fd == -1)
+ error.SetErrorString ("invalid fd for posix_spawn_file_actions_adddup2(...)");
+ else if (info->m_arg == -1)
+ error.SetErrorString ("invalid duplicate fd for posix_spawn_file_actions_adddup2(...)");
+ else
+ {
+ error.SetError (::posix_spawn_file_actions_adddup2 (file_actions, info->m_fd, info->m_arg),
+ eErrorTypePOSIX);
+ if (log && (error.Fail() || log))
+ error.PutToLog(log, "posix_spawn_file_actions_adddup2 (action=%p, fd=%i, dup_fd=%i)",
+ file_actions, info->m_fd, info->m_arg);
+ }
+ break;
+
+ case eFileActionOpen:
+ if (info->m_fd == -1)
+ error.SetErrorString ("invalid fd in posix_spawn_file_actions_addopen(...)");
+ else
+ {
+ int oflag = info->m_arg;
+ mode_t mode = 0;
+
+ error.SetError (::posix_spawn_file_actions_addopen (file_actions,
+ info->m_fd,
+ info->m_path.c_str(),
+ oflag,
+ mode),
+ eErrorTypePOSIX);
+ if (error.Fail() || log)
+ error.PutToLog(log,
+ "posix_spawn_file_actions_addopen (action=%p, fd=%i, path='%s', oflag=%i, mode=%i)",
+ file_actions, info->m_fd, info->m_path.c_str(), oflag, mode);
+ }
+ break;
+
+ default:
+ error.SetErrorStringWithFormat ("invalid file action: %i", info->m_action);
+ break;
+ }
+ return error.Success();
+}
+
+Error
+ProcessLaunchCommandOptions::SetOptionValue (int option_idx, const char *option_arg)
+{
+ Error error;
+ char short_option = (char) m_getopt_table[option_idx].val;
+
+ switch (short_option)
+ {
+ case 's': // Stop at program entry point
+ launch_info.GetFlags().Set (eLaunchFlagStopAtEntry);
+ break;
+
+ case 'e': // STDERR for read + write
+ {
+ ProcessLaunchInfo::FileAction action;
+ if (action.Open(STDERR_FILENO, option_arg, true, true))
+ launch_info.AppendFileAction (action);
+ }
+ break;
+
+ case 'i': // STDIN for read only
+ {
+ ProcessLaunchInfo::FileAction action;
+ if (action.Open(STDIN_FILENO, option_arg, true, false))
+ launch_info.AppendFileAction (action);
+ }
+ break;
+
+ case 'o': // Open STDOUT for write only
+ {
+ ProcessLaunchInfo::FileAction action;
+ if (action.Open(STDOUT_FILENO, option_arg, false, true))
+ launch_info.AppendFileAction (action);
+ }
+ break;
+
+ case 'p': // Process plug-in name
+ launch_info.SetProcessPluginName (option_arg);
+ break;
+
+ case 'n': // Disable STDIO
+ {
+ ProcessLaunchInfo::FileAction action;
+ if (action.Open(STDERR_FILENO, "/dev/null", true, true))
+ launch_info.AppendFileAction (action);
+ if (action.Open(STDOUT_FILENO, "/dev/null", false, true))
+ launch_info.AppendFileAction (action);
+ if (action.Open(STDIN_FILENO, "/dev/null", true, false))
+ launch_info.AppendFileAction (action);
+ }
+ break;
+
+ case 'w':
+ launch_info.SetWorkingDirectory (option_arg);
+ break;
+
+ case 't': // Open process in new terminal window
+ launch_info.GetFlags().Set (eLaunchFlagLaunchInTTY);
+ break;
+
+ case 'a':
+ launch_info.GetArchitecture().SetTriple (option_arg,
+ m_interpreter.GetPlatform(true).get());
+ break;
+
+ case 'A':
+ launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
+ break;
+
+ case 'v':
+ launch_info.GetEnvironmentEntries().AppendArgument(option_arg);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
+ break;
+
+ }
+ return error;
+}
+
+OptionDefinition
+ProcessLaunchCommandOptions::g_option_table[] =
+{
+{ LLDB_OPT_SET_ALL, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
+{ LLDB_OPT_SET_ALL, false, "disable-aslr", 'A', no_argument, NULL, 0, eArgTypeNone, "Disable address space layout randomization when launching a process."},
+{ LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
+{ 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_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>."},
+{ LLDB_OPT_SET_1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
+
+{ LLDB_OPT_SET_2 , false, "tty", 't', no_argument, NULL, 0, eArgTypeNone, "Start the process in a terminal (not supported on all platforms)."},
+
+{ LLDB_OPT_SET_3 , false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
+
+{ 0 , false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
+};
+
+
+
+bool
+ProcessInstanceInfoMatch::NameMatches (const char *process_name) const
{
if (m_name_match_type == eNameMatchIgnore || process_name == NULL)
return true;
@@ -186,7 +462,7 @@ ProcessInfoMatch::NameMatches (const char *process_name) const
}
bool
-ProcessInfoMatch::Matches (const ProcessInfo &proc_info) const
+ProcessInstanceInfoMatch::Matches (const ProcessInstanceInfo &proc_info) const
{
if (!NameMatches (proc_info.GetName()))
return false;
@@ -199,12 +475,12 @@ ProcessInfoMatch::Matches (const ProcessInfo &proc_info) const
m_match_info.GetParentProcessID() != proc_info.GetParentProcessID())
return false;
- if (m_match_info.RealUserIDIsValid () &&
- m_match_info.GetRealUserID() != proc_info.GetRealUserID())
+ if (m_match_info.UserIDIsValid () &&
+ m_match_info.GetUserID() != proc_info.GetUserID())
return false;
- if (m_match_info.RealGroupIDIsValid () &&
- m_match_info.GetRealGroupID() != proc_info.GetRealGroupID())
+ if (m_match_info.GroupIDIsValid () &&
+ m_match_info.GetGroupID() != proc_info.GetGroupID())
return false;
if (m_match_info.EffectiveUserIDIsValid () &&
@@ -222,7 +498,7 @@ ProcessInfoMatch::Matches (const ProcessInfo &proc_info) const
}
bool
-ProcessInfoMatch::MatchAllProcesses () const
+ProcessInstanceInfoMatch::MatchAllProcesses () const
{
if (m_name_match_type != eNameMatchIgnore)
return false;
@@ -233,10 +509,10 @@ ProcessInfoMatch::MatchAllProcesses () const
if (m_match_info.ParentProcessIDIsValid())
return false;
- if (m_match_info.RealUserIDIsValid ())
+ if (m_match_info.UserIDIsValid ())
return false;
- if (m_match_info.RealGroupIDIsValid ())
+ if (m_match_info.GroupIDIsValid ())
return false;
if (m_match_info.EffectiveUserIDIsValid ())
@@ -256,7 +532,7 @@ ProcessInfoMatch::MatchAllProcesses () const
}
void
-ProcessInfoMatch::Clear()
+ProcessInstanceInfoMatch::Clear()
{
m_match_info.Clear();
m_name_match_type = eNameMatchIgnore;
@@ -1504,6 +1780,46 @@ Process::ReadMemory (addr_t addr, void *buf, size_t size, Error &error)
size_t
+Process::ReadCStringFromMemory (addr_t addr, char *dst, size_t dst_max_len)
+{
+ size_t total_cstr_len = 0;
+ if (dst && dst_max_len)
+ {
+ // NULL out everything just to be safe
+ memset (dst, 0, dst_max_len);
+ Error error;
+ addr_t curr_addr = addr;
+ const size_t cache_line_size = m_memory_cache.GetMemoryCacheLineSize();
+ size_t bytes_left = dst_max_len - 1;
+ char *curr_dst = dst;
+
+ while (bytes_left > 0)
+ {
+ addr_t cache_line_bytes_left = cache_line_size - (curr_addr % cache_line_size);
+ addr_t bytes_to_read = std::min<addr_t>(bytes_left, cache_line_bytes_left);
+ size_t bytes_read = ReadMemory (curr_addr, curr_dst, bytes_to_read, error);
+
+ if (bytes_read == 0)
+ {
+ dst[total_cstr_len] = '\0';
+ break;
+ }
+ const size_t len = strlen(curr_dst);
+
+ total_cstr_len += len;
+
+ if (len < bytes_to_read)
+ break;
+
+ curr_dst += bytes_read;
+ curr_addr += bytes_read;
+ bytes_left -= bytes_read;
+ }
+ }
+ return total_cstr_len;
+}
+
+size_t
Process::ReadMemoryFromInferior (addr_t addr, void *buf, size_t size, Error &error)
{
if (buf == NULL || size == 0)
@@ -1894,7 +2210,7 @@ Process::Attach (lldb::pid_t attach_pid)
// Find the process and its architecture. Make sure it matches the architecture
// of the current Target, and if not adjust it.
- ProcessInfo process_info;
+ ProcessInstanceInfo process_info;
PlatformSP platform_sp (m_target.GetDebugger().GetPlatformList().GetSelectedPlatform ());
if (platform_sp)
{
@@ -1947,11 +2263,11 @@ Process::Attach (const char *process_name, bool wait_for_launch)
if (!wait_for_launch)
{
- ProcessInfoList process_infos;
+ ProcessInstanceInfoList process_infos;
PlatformSP platform_sp (m_target.GetDebugger().GetPlatformList().GetSelectedPlatform ());
if (platform_sp)
{
- ProcessInfoMatch match_info;
+ ProcessInstanceInfoMatch match_info;
match_info.GetProcessInfo().SetName(process_name);
match_info.SetNameMatchType (eNameMatchEquals);
platform_sp->FindProcesses (match_info, process_infos);
@@ -1965,7 +2281,7 @@ Process::Attach (const char *process_name, bool wait_for_launch)
}
else
{
- ProcessInfo process_info;
+ ProcessInstanceInfo process_info;
if (process_infos.GetInfoAtIndex (0, process_info))
{
const ArchSpec &process_arch = process_info.GetArchitecture();
@@ -2034,7 +2350,7 @@ Process::CompleteAttach ()
for (int i = 0; i < num_modules; i++)
{
ModuleSP module_sp (modules.GetModuleAtIndex(i));
- if (module_sp->IsExecutable())
+ if (module_sp && module_sp->IsExecutable())
{
ModuleSP target_exe_module_sp (m_target.GetExecutableModule());
if (target_exe_module_sp != module_sp)
@@ -2391,8 +2707,12 @@ Process::StartPrivateStateThread ()
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS));
+ bool already_running = PrivateStateThreadIsValid ();
if (log)
- log->Printf ("Process::%s ( )", __FUNCTION__);
+ log->Printf ("Process::%s()%s ", __FUNCTION__, already_running ? " already running" : " starting private state thread");
+
+ if (already_running)
+ return true;
// Create a thread that watches our internal state and controls which
// events make it to clients (into the DCProcess event queue).
@@ -2417,7 +2737,8 @@ Process::ResumePrivateStateThread ()
void
Process::StopPrivateStateThread ()
{
- ControlPrivateStateThread (eBroadcastInternalStateControlStop);
+ if (PrivateStateThreadIsValid ())
+ ControlPrivateStateThread (eBroadcastInternalStateControlStop);
}
void
@@ -2702,7 +3023,7 @@ Process::ProcessEventData::Dump (Stream *s) const
if (m_process_sp)
s->Printf(" process = %p (pid = %u), ", m_process_sp.get(), m_process_sp->GetID());
- s->Printf("state = %s", StateAsCString(GetState()));;
+ s->Printf("state = %s", StateAsCString(GetState()));
}
const Process::ProcessEventData *
@@ -3005,7 +3326,7 @@ Process::UpdateInstanceName ()
sstr.Printf ("%s", module_sp->GetFileSpec().GetFilename().AsCString());
GetSettingsController()->RenameInstanceSettings (GetInstanceName().AsCString(),
- sstr.GetData());
+ sstr.GetData());
}
}
@@ -3661,7 +3982,11 @@ ProcessInstanceSettings::UpdateInstanceSettingsVariable (const ConstString &var_
UserSettingsController::UpdateStringArrayVariable (op, index_value, m_run_args, value, err);
else if (var_name == EnvVarsVarName())
{
- GetHostEnvironmentIfNeeded ();
+ // This is nice for local debugging, but it is isn't correct for
+ // remote debugging. We need to stop process.env-vars from being
+ // populated with the host environment and add this as a launch option
+ // and get the correct environment from the Target's platform.
+ // GetHostEnvironmentIfNeeded ();
UserSettingsController::UpdateDictionaryVariable (op, index_value, m_env_vars, value, err);
}
else if (var_name == InputPathVarName())
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp
index 3c0a9cab86f..7e06a0f59bc 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.cpp
+++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp
@@ -53,48 +53,90 @@ StringExtractorGDBRemote::GetResponseType () const
StringExtractorGDBRemote::ServerPacketType
StringExtractorGDBRemote::GetServerPacketType () const
{
+#define PACKET_MATCHES(s) ((packet_size == (sizeof(s)-1)) && (strcmp((packet_cstr),(s)) == 0))
+#define PACKET_STARTS_WITH(s) ((packet_size >= (sizeof(s)-1)) && ::strncmp(packet_cstr, s, (sizeof(s)-1))==0)
+
// Empty is not a supported packet...
if (m_packet.empty())
return eServerPacketType_invalid;
+ const size_t packet_size = m_packet.size();
const char *packet_cstr = m_packet.c_str();
switch (m_packet[0])
{
case '\x03':
- if (m_packet.size() == 1)
- return eServerPacketType_interrupt;
+ if (packet_size == 1) return eServerPacketType_interrupt;
break;
case '-':
- if (m_packet.size() == 1)
- return eServerPacketType_nack;
+ if (packet_size == 1) return eServerPacketType_nack;
break;
case '+':
- if (m_packet.size() == 1)
- return eServerPacketType_ack;
+ if (packet_size == 1) return eServerPacketType_ack;
break;
+ case 'A':
+ return eServerPacketType_A;
+
case 'Q':
- if (strcmp (packet_cstr, "QStartNoAckMode") == 0)
- return eServerPacketType_QStartNoAckMode;
+ switch (packet_cstr[1])
+ {
+ case 'E':
+ if (PACKET_STARTS_WITH ("QEnvironment:")) return eServerPacketType_QEnvironment;
+ break;
+
+ case 'S':
+ if (PACKET_MATCHES ("QStartNoAckMode")) return eServerPacketType_QStartNoAckMode;
+ else if (PACKET_STARTS_WITH ("QSetDisableASLR:")) return eServerPacketType_QSetDisableASLR;
+ else if (PACKET_STARTS_WITH ("QSetSTDIN:")) return eServerPacketType_QSetSTDIN;
+ else if (PACKET_STARTS_WITH ("QSetSTDOUT:")) return eServerPacketType_QSetSTDOUT;
+ else if (PACKET_STARTS_WITH ("QSetSTDERR:")) return eServerPacketType_QSetSTDERR;
+ else if (PACKET_STARTS_WITH ("QSetWorkingDir:")) return eServerPacketType_QSetWorkingDir;
+ break;
+ }
break;
case 'q':
- if (packet_cstr[1] == 'S' && 0 == ::strncmp(packet_cstr, "qSpeedTest:", strlen("qSpeedTest:")))
- return eServerPacketType_qSpeedTest;
- else if (packet_cstr[1] == 'H' && 0 == ::strcmp (packet_cstr, "qHostInfo"))
- return eServerPacketType_qHostInfo;
- else if (packet_cstr[1] == 'P' && 0 == ::strncmp(packet_cstr, "qProcessInfoPID:", strlen("qProcessInfoPID:")))
- return eServerPacketType_qProcessInfoPID;
- else if (packet_cstr[1] == 'f' && 0 == ::strncmp(packet_cstr, "qfProcessInfo", strlen("qfProcessInfo")))
- return eServerPacketType_qfProcessInfo;
- else if (packet_cstr[1] == 'U' && 0 == ::strncmp(packet_cstr, "qUserName:", strlen("qUserName:")))
- return eServerPacketType_qUserName;
- else if (packet_cstr[1] == 'G' && 0 == ::strncmp(packet_cstr, "qGroupName:", strlen("qGroupName:")))
- return eServerPacketType_qGroupName;
- else if (packet_cstr[1] == 's' && 0 == ::strcmp (packet_cstr, "qsProcessInfo"))
- return eServerPacketType_qsProcessInfo;
+ switch (packet_cstr[1])
+ {
+ case 's':
+ if (PACKET_MATCHES ("qsProcessInfo")) return eServerPacketType_qsProcessInfo;
+ break;
+
+ case 'f':
+ if (PACKET_STARTS_WITH ("qfProcessInfo")) return eServerPacketType_qfProcessInfo;
+ break;
+
+ case 'C':
+ if (packet_size == 2) return eServerPacketType_qC;
+ break;
+
+ case 'G':
+ if (PACKET_STARTS_WITH ("qGroupName:")) return eServerPacketType_qGroupName;
+ break;
+
+ case 'H':
+ if (PACKET_MATCHES ("qHostInfo")) return eServerPacketType_qHostInfo;
+ break;
+
+ case 'L':
+ if (PACKET_MATCHES ("qLaunchGDBServer")) return eServerPacketType_qLaunchGDBServer;
+ if (PACKET_MATCHES ("qLaunchSuccess")) return eServerPacketType_qLaunchSuccess;
+ break;
+
+ case 'P':
+ if (PACKET_STARTS_WITH ("qProcessInfoPID:")) return eServerPacketType_qProcessInfoPID;
+ break;
+
+ case 'S':
+ if (PACKET_STARTS_WITH ("qSpeedTest:")) return eServerPacketType_qSpeedTest;
+ break;
+
+ case 'U':
+ if (PACKET_STARTS_WITH ("qUserName:")) return eServerPacketType_qUserName;
+ break;
+ }
break;
}
return eServerPacketType_unimplemented;
diff --git a/lldb/source/Utility/StringExtractorGDBRemote.h b/lldb/source/Utility/StringExtractorGDBRemote.h
index 36fd0344a09..5a24d894b10 100644
--- a/lldb/source/Utility/StringExtractorGDBRemote.h
+++ b/lldb/source/Utility/StringExtractorGDBRemote.h
@@ -46,13 +46,23 @@ public:
eServerPacketType_invalid,
eServerPacketType_unimplemented,
eServerPacketType_interrupt, // CTRL+c packet or "\x03"
- eServerPacketType_qHostInfo,
- eServerPacketType_qProcessInfoPID,
+ eServerPacketType_A, // Program arguments packet
eServerPacketType_qfProcessInfo,
eServerPacketType_qsProcessInfo,
- eServerPacketType_qUserName,
+ eServerPacketType_qC,
eServerPacketType_qGroupName,
+ eServerPacketType_qHostInfo,
+ eServerPacketType_qLaunchGDBServer,
+ eServerPacketType_qLaunchSuccess,
+ eServerPacketType_qProcessInfoPID,
eServerPacketType_qSpeedTest,
+ eServerPacketType_qUserName,
+ eServerPacketType_QEnvironment,
+ eServerPacketType_QSetDisableASLR,
+ eServerPacketType_QSetSTDIN,
+ eServerPacketType_QSetSTDOUT,
+ eServerPacketType_QSetSTDERR,
+ eServerPacketType_QSetWorkingDir,
eServerPacketType_QStartNoAckMode
};
diff --git a/lldb/test/abbreviation_tests/TestAbbreviations.py b/lldb/test/abbreviation_tests/TestAbbreviations.py
index 9cbdae6ebe5..6f46346c54d 100644
--- a/lldb/test/abbreviation_tests/TestAbbreviations.py
+++ b/lldb/test/abbreviation_tests/TestAbbreviations.py
@@ -74,7 +74,7 @@ class AbbreviationsTestCase(TestBase):
self.expect("fil " + exe,
patterns = [ "Current executable set to .*a.out.*" ])
- self.expect("regexp-b product",
+ self.expect("_regexp-b product",
substrs = [ "breakpoint set --name 'product'",
"Breakpoint created: 1: name = 'product', locations = 1" ])
diff --git a/lldb/test/dotest.py b/lldb/test/dotest.py
index 18b2e268b62..ecb4b722286 100755
--- a/lldb/test/dotest.py
+++ b/lldb/test/dotest.py
@@ -216,9 +216,9 @@ $ ./dotest.py -v -p ObjC
Collected 4 tests
test_break_with_dsym (TestObjCMethods.FoundationTestCase)
-Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'. ... ok
+Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
test_break_with_dwarf (TestObjCMethods.FoundationTestCase)
-Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'. ... ok
+Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'. ... ok
test_data_type_and_expr_with_dsym (TestObjCMethods.FoundationTestCase)
Lookup objective-c data types and evaluate expressions. ... ok
test_data_type_and_expr_with_dwarf (TestObjCMethods.FoundationTestCase)
diff --git a/lldb/test/foundation/TestFoundationDisassembly.py b/lldb/test/foundation/TestFoundationDisassembly.py
index 8722fab23a8..a51e2375b4c 100644
--- a/lldb/test/foundation/TestFoundationDisassembly.py
+++ b/lldb/test/foundation/TestFoundationDisassembly.py
@@ -70,7 +70,7 @@ class FoundationDisassembleTestCase(TestBase):
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
# Stop at +[NSString stringWithFormat:].
- self.expect("regexp-break +[NSString stringWithFormat:]", BREAKPOINT_CREATED,
+ self.expect("_regexp-break +[NSString stringWithFormat:]", BREAKPOINT_CREATED,
substrs = ["Breakpoint created: 1: name = '+[NSString stringWithFormat:]', locations = 1"])
# Stop at -[MyString initWithNSString:].
@@ -82,7 +82,7 @@ class FoundationDisassembleTestCase(TestBase):
startstr = "Breakpoint created: 3: name = 'description', locations = 1")
# Stop at -[NSAutoreleasePool release].
- self.expect("regexp-break -[NSAutoreleasePool release]", BREAKPOINT_CREATED,
+ self.expect("_regexp-break -[NSAutoreleasePool release]", BREAKPOINT_CREATED,
substrs = ["Breakpoint created: 4: name = '-[NSAutoreleasePool release]', locations = 1"])
self.runCmd("run", RUN_SUCCEEDED)
diff --git a/lldb/test/foundation/TestObjCMethods.py b/lldb/test/foundation/TestObjCMethods.py
index b8415fee209..9485cb57327 100644
--- a/lldb/test/foundation/TestObjCMethods.py
+++ b/lldb/test/foundation/TestObjCMethods.py
@@ -14,12 +14,12 @@ class FoundationTestCase(TestBase):
mydir = "foundation"
def test_break_with_dsym(self):
- """Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'."""
+ """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'."""
self.buildDsym()
self.break_on_objc_methods()
def test_break_with_dwarf(self):
- """Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'."""
+ """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'."""
self.buildDwarf()
self.break_on_objc_methods()
@@ -50,12 +50,12 @@ class FoundationTestCase(TestBase):
self.print_ivars_correctly()
def break_on_objc_methods(self):
- """Test setting objc breakpoints using 'regexp-break' and 'breakpoint set'."""
+ """Test setting objc breakpoints using '_regexp-break' and 'breakpoint set'."""
exe = os.path.join(os.getcwd(), "a.out")
self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
# Stop at +[NSString stringWithFormat:].
- self.expect("regexp-break +[NSString stringWithFormat:]", BREAKPOINT_CREATED,
+ self.expect("_regexp-break +[NSString stringWithFormat:]", BREAKPOINT_CREATED,
substrs = ["Breakpoint created: 1: name = '+[NSString stringWithFormat:]', locations = 1"])
# Stop at -[MyString initWithNSString:].
@@ -67,7 +67,7 @@ class FoundationTestCase(TestBase):
startstr = "Breakpoint created: 3: name = 'description', locations = 1")
# Stop at -[NSAutoreleasePool release].
- self.expect("regexp-break -[NSAutoreleasePool release]", BREAKPOINT_CREATED,
+ self.expect("_regexp-break -[NSAutoreleasePool release]", BREAKPOINT_CREATED,
substrs = ["Breakpoint created: 4: name = '-[NSAutoreleasePool release]', locations = 1"])
self.runCmd("run", RUN_SUCCEEDED)
diff --git a/lldb/tools/darwin-debug/darwin-debug.cpp b/lldb/tools/darwin-debug/darwin-debug.cpp
index 689c3864aff..9be32595246 100644
--- a/lldb/tools/darwin-debug/darwin-debug.cpp
+++ b/lldb/tools/darwin-debug/darwin-debug.cpp
@@ -246,7 +246,7 @@ int main (int argc, char *const *argv, char *const *envp, const char **apple)
printf ("argv[%u] = '%s'\n", i, argv[i]);
#endif
- // Open the socket that was passed in as an argument
+ // Open the socket that was passed in as an option
struct sockaddr_un saddr_un;
int s = ::socket (AF_UNIX, SOCK_STREAM, 0);
if (s < 0)
diff --git a/lldb/tools/debugserver/source/MacOSX/CFString.h b/lldb/tools/debugserver/source/MacOSX/CFString.h
index 2b96b8237fc..73945a28a65 100644
--- a/lldb/tools/debugserver/source/MacOSX/CFString.h
+++ b/lldb/tools/debugserver/source/MacOSX/CFString.h
@@ -24,7 +24,7 @@ public:
// Constructors and Destructors
//------------------------------------------------------------------
CFString (CFStringRef cf_str = NULL);
- CFString (const char *s, CFStringEncoding encoding);
+ CFString (const char *s, CFStringEncoding encoding = kCFStringEncodingUTF8);
CFString (const CFString& rhs);
CFString& operator= (const CFString& rhs);
virtual ~CFString ();
diff --git a/lldb/tools/debugserver/source/RNBSocket.cpp b/lldb/tools/debugserver/source/RNBSocket.cpp
index 139a4150adf..5af9810d0e4 100644
--- a/lldb/tools/debugserver/source/RNBSocket.cpp
+++ b/lldb/tools/debugserver/source/RNBSocket.cpp
@@ -31,78 +31,90 @@
This function blocks while waiting for that connection. */
rnb_err_t
-RNBSocket::Listen (in_port_t listen_port_num)
+RNBSocket::Listen (in_port_t port, PortBoundCallback callback, const void *callback_baton)
{
//DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s called", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
// Disconnect without saving errno
Disconnect (false);
DNBError err;
- int listen_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (listen_port == -1)
+ int listen_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (listen_fd == -1)
err.SetError(errno, DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_port);
+ err.LogThreaded("::socket ( domain = AF_INET, type = SOCK_STREAM, protocol = IPPROTO_TCP ) => socket = %i", listen_fd);
if (err.Fail())
return rnb_err;
// enable local address reuse
- SetSocketOption (listen_port, SOL_SOCKET, SO_REUSEADDR, 1);
+ SetSocketOption (listen_fd, SOL_SOCKET, SO_REUSEADDR, 1);
struct sockaddr_in sa;
::memset (&sa, 0, sizeof sa);
sa.sin_len = sizeof sa;
sa.sin_family = AF_INET;
- sa.sin_port = htons (listen_port_num);
+ sa.sin_port = htons (port);
sa.sin_addr.s_addr = htonl (INADDR_ANY);
- int error = ::bind (listen_port, (struct sockaddr *) &sa, sizeof(sa));
+ int error = ::bind (listen_fd, (struct sockaddr *) &sa, sizeof(sa));
if (error == -1)
err.SetError(errno, DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_port);
+ err.LogThreaded("::bind ( socket = %i, (struct sockaddr *) &sa, sizeof(sa)) )", listen_fd);
if (err.Fail())
{
- ClosePort (listen_port, false);
+ ClosePort (listen_fd, false);
return rnb_err;
}
- error = ::listen (listen_port, 1);
+ if (callback && port == 0)
+ {
+ // We were asked to listen on port zero which means we
+ // must now read the actual port that was given to us
+ // as port zero is a special code for "find an open port
+ // for me".
+ socklen_t sa_len = sizeof (sa);
+ if (getsockname(listen_fd, (struct sockaddr *)&sa, &sa_len) == 0)
+ {
+ port = ntohs (sa.sin_port);
+ callback (callback_baton, port);
+ }
+ }
+
+ error = ::listen (listen_fd, 1);
if (error == -1)
err.SetError(errno, DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_port);
+ err.LogThreaded("::listen ( socket = %i, backlog = 1 )", listen_fd);
if (err.Fail())
{
- ClosePort (listen_port, false);
+ ClosePort (listen_fd, false);
return rnb_err;
}
- m_conn_port = ::accept (listen_port, NULL, 0);
- if (m_conn_port == -1)
+ m_fd = ::accept (listen_fd, NULL, 0);
+ if (m_fd == -1)
err.SetError(errno, DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_port);
+ err.LogThreaded("::accept ( socket = %i, address = NULL, address_len = 0 )", listen_fd);
+
+ ClosePort (listen_fd, false);
if (err.Fail())
{
- ClosePort (listen_port, false);
return rnb_err;
}
else
{
- // We are done with the listen port
- ClosePort (listen_port, false);
-
// Keep our TCP packets coming without any delays.
- SetSocketOption (m_conn_port, IPPROTO_TCP, TCP_NODELAY, 1);
+ SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
}
return rnb_success;
@@ -114,12 +126,12 @@ RNBSocket::Connect (const char *host, uint16_t port)
Disconnect (false);
// Create the socket
- m_conn_port = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (m_conn_port == -1)
+ m_fd = ::socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (m_fd == -1)
return rnb_err;
// Enable local address reuse
- SetSocketOption (m_conn_port, SOL_SOCKET, SO_REUSEADDR, 1);
+ SetSocketOption (m_fd, SOL_SOCKET, SO_REUSEADDR, 1);
struct sockaddr_in sa;
::memset (&sa, 0, sizeof (sa));
@@ -146,14 +158,14 @@ RNBSocket::Connect (const char *host, uint16_t port)
}
}
- if (-1 == ::connect (m_conn_port, (const struct sockaddr *)&sa, sizeof(sa)))
+ if (-1 == ::connect (m_fd, (const struct sockaddr *)&sa, sizeof(sa)))
{
Disconnect (false);
return rnb_err;
}
// Keep our TCP packets coming without any delays.
- SetSocketOption (m_conn_port, IPPROTO_TCP, TCP_NODELAY, 1);
+ SetSocketOption (m_fd, IPPROTO_TCP, TCP_NODELAY, 1);
return rnb_success;
}
@@ -165,13 +177,13 @@ RNBSocket::ConnectToService()
// Disconnect from any previous connections
Disconnect(false);
- m_conn_port = ::lockdown_checkin (NULL, NULL);
- if (m_conn_port == -1)
+ m_fd = ::lockdown_checkin (NULL, NULL);
+ if (m_fd == -1)
{
DNBLogThreadedIf(LOG_RNB_COMM, "::lockdown_checkin(NULL, NULL) failed");
return rnb_not_connected;
}
- m_conn_port_from_lockdown = true;
+ m_fd_from_lockdown = true;
return rnb_success;
}
#endif
@@ -180,8 +192,8 @@ rnb_err_t
RNBSocket::OpenFile (const char *path)
{
DNBError err;
- m_conn_port = open (path, O_RDWR);
- if (m_conn_port == -1)
+ m_fd = open (path, O_RDWR);
+ if (m_fd == -1)
{
err.SetError(errno, DNBError::POSIX);
err.LogThreaded ("can't open file '%s'", path);
@@ -191,11 +203,11 @@ RNBSocket::OpenFile (const char *path)
{
struct termios stdin_termios;
- if (::tcgetattr (m_conn_port, &stdin_termios) == 0)
+ if (::tcgetattr (m_fd, &stdin_termios) == 0)
{
stdin_termios.c_lflag &= ~ECHO; // Turn off echoing
stdin_termios.c_lflag &= ~ICANON; // Get one char at a time
- ::tcsetattr (m_conn_port, TCSANOW, &stdin_termios);
+ ::tcsetattr (m_fd, TCSANOW, &stdin_termios);
}
}
return rnb_success;
@@ -210,9 +222,9 @@ RNBSocket::SetSocketOption(int fd, int level, int option_name, int option_value)
rnb_err_t
RNBSocket::Disconnect (bool save_errno)
{
- if (m_conn_port_from_lockdown)
- m_conn_port_from_lockdown = false;
- return ClosePort (m_conn_port, save_errno);
+ if (m_fd_from_lockdown)
+ m_fd_from_lockdown = false;
+ return ClosePort (m_fd, save_errno);
}
@@ -225,29 +237,29 @@ RNBSocket::Read (std::string &p)
// Note that BUF is on the stack so we must be careful to keep any
// writes to BUF from overflowing or we'll have security issues.
- if (m_conn_port == -1)
+ if (m_fd == -1)
return rnb_err;
//DNBLogThreadedIf(LOG_RNB_COMM, "%8u RNBSocket::%s calling read()", (uint32_t)m_timer.ElapsedMicroSeconds(true), __FUNCTION__);
DNBError err;
- int bytesread = read (m_conn_port, buf, sizeof (buf));
+ int bytesread = read (m_fd, buf, sizeof (buf));
if (bytesread <= 0)
err.SetError(errno, DNBError::POSIX);
else
p.append(buf, bytesread);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::read ( %i, %p, %zu ) => %i", m_conn_port, buf, sizeof (buf), bytesread);
+ err.LogThreaded("::read ( %i, %p, %zu ) => %i", m_fd, buf, sizeof (buf), bytesread);
// Our port went away - we have to mark this so IsConnected will return the truth.
if (bytesread == 0)
{
- m_conn_port = -1;
+ m_fd = -1;
return rnb_not_connected;
}
else if (bytesread == -1)
{
- m_conn_port = -1;
+ m_fd = -1;
return rnb_err;
}
// Strip spaces from the end of the buffer
@@ -262,16 +274,16 @@ RNBSocket::Read (std::string &p)
rnb_err_t
RNBSocket::Write (const void *buffer, size_t length)
{
- if (m_conn_port == -1)
+ if (m_fd == -1)
return rnb_err;
DNBError err;
- int bytessent = send (m_conn_port, buffer, length, 0);
+ int bytessent = send (m_fd, buffer, length, 0);
if (bytessent < 0)
err.SetError(errno, DNBError::POSIX);
if (err.Fail() || DNBLogCheckLogBit(LOG_RNB_COMM))
- err.LogThreaded("::send ( socket = %i, buffer = %p, length = %zu, flags = 0 ) => %i", m_conn_port, buffer, length, bytessent);
+ err.LogThreaded("::send ( socket = %i, buffer = %p, length = %zu, flags = 0 ) => %i", m_fd, buffer, length, bytessent);
if (bytessent < 0)
return rnb_err;
diff --git a/lldb/tools/debugserver/source/RNBSocket.h b/lldb/tools/debugserver/source/RNBSocket.h
index 56608bb17fc..5fd6ac2a570 100644
--- a/lldb/tools/debugserver/source/RNBSocket.h
+++ b/lldb/tools/debugserver/source/RNBSocket.h
@@ -23,10 +23,11 @@
class RNBSocket
{
public:
+ typedef void (*PortBoundCallback) (const void *baton, in_port_t port);
RNBSocket () :
- m_conn_port (-1),
- m_conn_port_from_lockdown (false),
+ m_fd (-1),
+ m_fd_from_lockdown (false),
m_timer (true) // Make a thread safe timer
{
}
@@ -35,7 +36,7 @@ public:
Disconnect (false);
}
- rnb_err_t Listen (in_port_t listen_port_num);
+ rnb_err_t Listen (in_port_t port, PortBoundCallback callback, const void *callback_baton);
rnb_err_t Connect (const char *host, uint16_t port);
#if defined (__arm__)
@@ -46,7 +47,7 @@ public:
rnb_err_t Read (std::string &p);
rnb_err_t Write (const void *buffer, size_t length);
- bool IsConnected () const { return m_conn_port != -1; }
+ bool IsConnected () const { return m_fd != -1; }
void SaveErrno (int curr_errno);
DNBTimer& Timer() { return m_timer; }
@@ -58,8 +59,8 @@ private:
protected:
rnb_err_t ClosePort (int& fd, bool save_errno);
- int m_conn_port; // Socket we use to communicate once conn established
- bool m_conn_port_from_lockdown;
+ int m_fd; // Socket we use to communicate once conn established
+ bool m_fd_from_lockdown;
DNBTimer m_timer;
};
diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp
index 6e08d5dd8dc..12a873ef8e3 100644
--- a/lldb/tools/debugserver/source/debugserver.cpp
+++ b/lldb/tools/debugserver/source/debugserver.cpp
@@ -17,6 +17,12 @@
#include <string>
#include <vector>
#include <asl.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <sys/un.h>
+#include <sys/types.h>
#include "CFString.h"
#include "DNB.h"
@@ -608,13 +614,68 @@ RNBRunLoopPlatform (RNBRemote *remote)
// Returns 1 for success 0 for failure.
//----------------------------------------------------------------------
+static void
+PortWasBoundCallback (const void *baton, in_port_t port)
+{
+ //::printf ("PortWasBoundCallback (baton = %p, port = %u)\n", baton, port);
+
+ const char *unix_socket_name = (const char *)baton;
+
+ if (unix_socket_name && unix_socket_name[0])
+ {
+ // We were given a unix socket name to use to communicate the port
+ // that we ended up binding to back to our parent process
+ struct sockaddr_un saddr_un;
+ int s = ::socket (AF_UNIX, SOCK_STREAM, 0);
+ if (s < 0)
+ {
+ perror("error: socket (AF_UNIX, SOCK_STREAM, 0)");
+ exit(1);
+ }
+
+ saddr_un.sun_family = AF_UNIX;
+ ::strncpy(saddr_un.sun_path, unix_socket_name, sizeof(saddr_un.sun_path) - 1);
+ saddr_un.sun_path[sizeof(saddr_un.sun_path) - 1] = '\0';
+ saddr_un.sun_len = SUN_LEN (&saddr_un);
+
+ if (::connect (s, (struct sockaddr *)&saddr_un, SUN_LEN (&saddr_un)) < 0)
+ {
+ perror("error: connect (socket, &saddr_un, saddr_un_len)");
+ exit(1);
+ }
+
+ //::printf ("connect () sucess!!\n");
+
+
+ // We were able to connect to the socket, now write our PID so whomever
+ // launched us will know this process's ID
+ RNBLogSTDOUT ("Listening to port %i...\n", port);
+
+ char pid_str[64];
+ const int pid_str_len = ::snprintf (pid_str, sizeof(pid_str), "%u", port);
+ const int bytes_sent = ::send (s, pid_str, pid_str_len, 0);
+
+ if (pid_str_len != bytes_sent)
+ {
+ perror("error: send (s, pid_str, pid_str_len, 0)");
+ exit (1);
+ }
+
+ //::printf ("send () sucess!!\n");
+
+ // We are done with the socket
+ close (s);
+ }
+}
+
static int
-StartListening (RNBRemote *remote, int listen_port)
+StartListening (RNBRemote *remote, int listen_port, const char *unix_socket_name)
{
if (!remote->Comm().IsConnected())
{
- RNBLogSTDOUT ("Listening to port %i...\n", listen_port);
- if (remote->Comm().Listen(listen_port) != rnb_success)
+ if (listen_port != 0)
+ RNBLogSTDOUT ("Listening to port %i...\n", listen_port);
+ if (remote->Comm().Listen(listen_port, PortWasBoundCallback, unix_socket_name) != rnb_success)
{
RNBLogSTDERR ("Failed to get connection from a remote gdb process.\n");
return 0;
@@ -709,6 +770,7 @@ static struct option g_long_options[] =
{ "disable-aslr", no_argument, NULL, 'D' }, // Use _POSIX_SPAWN_DISABLE_ASLR to avoid shared library randomization
{ "working-dir", required_argument, NULL, 'W' }, // The working directory that the inferior process should have (only if debugserver launches the process)
{ "platform", required_argument, NULL, 'p' }, // Put this executable into a remote platform mode
+ { "unix-socket", required_argument, NULL, 'u' }, // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use
{ NULL, 0, NULL, 0 }
};
@@ -757,7 +819,8 @@ main (int argc, char *argv[])
std::string waitfor_pid_name; // Wait for a process that starts with this name
std::string attach_pid_name;
std::string arch_name;
- std::string working_dir; // The new working directory to use for the inferior
+ std::string working_dir; // The new working directory to use for the inferior
+ std::string unix_socket_name; // If we need to handshake with our parent process, an option will be passed down that specifies a unix socket name to use
useconds_t waitfor_interval = 1000; // Time in usecs between process lists polls when waiting for a process by name, default 1 msec.
useconds_t waitfor_duration = 0; // Time in seconds to wait for a process by name, 0 means wait forever.
bool no_stdio = false;
@@ -768,7 +831,7 @@ main (int argc, char *argv[])
RNBRunLoopMode start_mode = eRNBRunLoopModeExit;
- while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:n", g_long_options, &long_option_index)) != -1)
+ while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:nu:", g_long_options, &long_option_index)) != -1)
{
DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n",
ch, (uint8_t)ch,
@@ -967,6 +1030,11 @@ main (int argc, char *argv[])
case 'p':
start_mode = eRNBRunLoopModePlatformMode;
break;
+
+ case 'u':
+ unix_socket_name.assign (optarg);
+ break;
+
}
}
@@ -1171,7 +1239,7 @@ main (int argc, char *argv[])
#endif
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
@@ -1282,7 +1350,7 @@ main (int argc, char *argv[])
{
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
@@ -1307,7 +1375,7 @@ main (int argc, char *argv[])
{
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
@@ -1334,7 +1402,7 @@ main (int argc, char *argv[])
case eRNBRunLoopModePlatformMode:
if (listen_port != INT32_MAX)
{
- if (!StartListening (remote, listen_port))
+ if (!StartListening (remote, listen_port, unix_socket_name.c_str()))
mode = eRNBRunLoopModeExit;
}
else if (str[0] == '/')
diff --git a/lldb/tools/lldb-platform/lldb-platform.cpp b/lldb/tools/lldb-platform/lldb-platform.cpp
index be8359717fa..2dc54af2f7b 100644
--- a/lldb/tools/lldb-platform/lldb-platform.cpp
+++ b/lldb/tools/lldb-platform/lldb-platform.cpp
@@ -180,7 +180,7 @@ main (int argc, char *argv[])
argv += optind;
- GDBRemoteCommunicationServer gdb_server;
+ GDBRemoteCommunicationServer gdb_server (true);
if (!listen_host_post.empty())
{
std::auto_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
OpenPOWER on IntegriCloud