diff options
author | Jim Ingham <jingham@apple.com> | 2010-08-09 23:31:02 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2010-08-09 23:31:02 +0000 |
commit | 5aee162f978eac7ffb6363d25b193e51edfbc0b1 (patch) | |
tree | affe5547d828a14a967f9b5deff564248940554b | |
parent | 394a69ed528c403248c6354baeedaf0533b33afc (diff) | |
download | bcm5719-llvm-5aee162f978eac7ffb6363d25b193e51edfbc0b1.tar.gz bcm5719-llvm-5aee162f978eac7ffb6363d25b193e51edfbc0b1.zip |
Change Target & Process so they can really be initialized with an invalid architecture.
Arrange that this then gets properly set on attach, or when a "file" is set.
Add a completer for "process attach -n".
Caveats: there isn't currently a way to handle multiple processes with the same name. That
will have to wait on a way to pass annotations along with the completion strings.
llvm-svn: 110624
24 files changed, 778 insertions, 196 deletions
diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 5298cac5e3e..5b38cf9920f 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -13,6 +13,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Section.h" #include "lldb/Core/UUID.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/TimeValue.h" #include "lldb/Symbol/CompileUnit.h" @@ -46,6 +47,7 @@ class Module : { public: friend class ModuleList; + friend bool ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch); enum { @@ -343,6 +345,16 @@ public: const TimeValue & GetModificationTime () const; + + //------------------------------------------------------------------ + /// Tells whether this module is capable of being the main executable + /// for a process. + /// + /// @return + /// \b true if it is, \b false otherwise. + //------------------------------------------------------------------ + bool + IsExecutable (); //------------------------------------------------------------------ /// Get the number of compile units for this module. @@ -547,7 +559,7 @@ protected: //------------------------------------------------------------------ mutable Mutex m_mutex; ///< A mutex to keep this object happy in multi-threaded environments. TimeValue m_mod_time; ///< The modification time for this module when it was created. - const ArchSpec m_arch; ///< The architecture for this module. + ArchSpec m_arch; ///< The architecture for this module. UUID m_uuid; ///< Each module is assumed to have a unique identifier to help match it up to debug symbols. FileSpec m_file; ///< The file representation on disk for this module (if there is one). Flags m_flags; ///< Flags for this module to track what has been parsed already. @@ -592,7 +604,9 @@ protected: ResolveSymbolContextForAddress (lldb::addr_t vm_addr, bool vm_addr_is_file_addr, uint32_t resolve_scope, Address& so_addr, SymbolContext& sc); void SymbolIndicesToSymbolContextList (Symtab *symtab, std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list); - + + bool SetArchitecture (const ArchSpec &new_arch); + private: DISALLOW_COPY_AND_ASSIGN (Module); diff --git a/lldb/include/lldb/Host/Host.h b/lldb/include/lldb/Host/Host.h index 5f52085ae6d..3aeae36973d 100644 --- a/lldb/include/lldb/Host/Host.h +++ b/lldb/include/lldb/Host/Host.h @@ -13,6 +13,7 @@ #include "lldb/lldb-private.h" +#include "lldb/Core/StringList.h" namespace lldb_private { @@ -273,6 +274,16 @@ public: static bool ResolveExecutableInBundle (FileSpec *file); + + static uint32_t + ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids); + + static ArchSpec + GetArchSpecForExistingProcess (lldb::pid_t pid); + + static ArchSpec + GetArchSpecForExistingProcess (const char *process_name); + }; } // namespace lldb_private diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index ffc8d5438c1..715c81da5aa 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -51,6 +51,8 @@ class ObjectFile: public PluginInterface, public ModuleChild { +friend class lldb_private::Module; + public: //------------------------------------------------------------------ /// Construct with a parent module, offset, and header data. @@ -159,7 +161,17 @@ public: //------------------------------------------------------------------ virtual uint32_t GetDependentModules (FileSpecList& file_list) = 0; - + + //------------------------------------------------------------------ + /// Tells whether this object file is capable of being the main executable + /// for a process. + /// + /// @return + /// \b true if it is, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + IsExecutable () const = 0; + //------------------------------------------------------------------ /// Returns the offset into a file at which this object resides. /// @@ -290,6 +302,20 @@ protected: lldb::addr_t m_offset; ///< The offset in bytes into the file, or the address in memory lldb::addr_t m_length; ///< The length of this object file if it is known (can be zero if length is unknown or can't be determined). DataExtractor m_data; ///< The data for this object file so things can be parsed lazily. + + //------------------------------------------------------------------ + /// Sets the architecture for a module. At present the architecture + /// can only be set if it is invalid. It is not allowed to switch from + /// one concrete architecture to another. + /// + /// @param[in] new_arch + /// The architecture this module will be set to. + /// + /// @return + /// Returns \b true if the architecture was changed, \b + /// false otherwise. + //------------------------------------------------------------------ + bool SetModulesArchitecture (const ArchSpec &new_arch); private: DISALLOW_COPY_AND_ASSIGN (ObjectFile); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 0bdcb65355e..d44a00c8c9d 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -20,6 +20,7 @@ #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Error.h" #include "lldb/Core/Event.h" +#include "lldb/Core/StringList.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Core/ThreadSafeSTLMap.h" #include "lldb/Core/PluginInterface.h" @@ -313,6 +314,58 @@ public: //------------------------------------------------------------------ virtual Error Attach (const char *process_name, bool wait_for_launch); + + //------------------------------------------------------------------ + /// List the processes matching the given partial name. + /// + /// FIXME: Is it too heavyweight to create an entire process object to do this? + /// The problem is for remote processes we're going to have to set up the same transport + /// to get this data as to actually attach. So we need to factor out transport + /// and process before we can do this separately from the process. + /// + /// @param[in] name + /// A partial name to match against the current process list. + /// + /// @param[out] matches + /// The list of process names matching \a name. + /// + /// @param[in] pids + /// A vector filled with the pids that correspond to the names in \a matches. + /// + /// @return + /// Returns the number of matching processes. + //------------------------------------------------------------------ + + virtual uint32_t + ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids); + + //------------------------------------------------------------------ + /// Find the architecture of a process by pid. + /// + /// FIXME: See comment for ListProcessesMatchingName. + /// + /// @param[in] pid + /// A pid to inspect. + /// + /// @return + /// Returns the architecture of the process or an invalid architecture if the process can't be found. + //------------------------------------------------------------------ + virtual ArchSpec + GetArchSpecForExistingProcess (lldb::pid_t pid); + + //------------------------------------------------------------------ + /// Find the architecture of a process by name. + /// + /// FIXME: See comment for ListProcessesMatchingName. + /// + /// @param[in] process_name + /// The process name to inspect. + /// + /// @return + /// Returns the architecture of the process or an invalid architecture if the process can't be found. + //------------------------------------------------------------------ + virtual ArchSpec + GetArchSpecForExistingProcess (const char *process_name); uint32_t GetAddressByteSize(); diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index fe18fdda890..ef584fb1a38 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -253,6 +253,27 @@ public: ArchSpec GetArchitecture () const; + + //------------------------------------------------------------------ + /// Set the architecture for this target. + /// + /// If the current target has no Images read in, then this just sets the architecture, which will + /// be used to select the architecture of the ExecutableModule when that is set. + /// If the current target has an ExecutableModule, then calling SetArchitecture with a different + /// architecture from the currently selected one will reset the ExecutableModule to that slice + /// of the file backing the ExecutableModule. If the file backing the ExecutableModule does not + /// contain a fork of this architecture, then this code will return false, and the architecture + /// won't be changed. + /// If the input arch_spec is the same as the already set architecture, this is a no-op. + /// + /// @param[in] arch_spec + /// The new architecture. + /// + /// @return + /// \b true if the architecture was successfully set, \bfalse otherwise. + //------------------------------------------------------------------ + bool + SetArchitecture (const ArchSpec &arch_spec); Debugger & GetDebugger () @@ -300,6 +321,7 @@ protected: // Member variables. //------------------------------------------------------------------ Debugger & m_debugger; + ArchSpec m_arch_spec; ModuleList m_images; ///< The list of images for this process (shared libraries and anything dynamically loaded). BreakpointList m_breakpoint_list; BreakpointList m_internal_breakpoint_list; diff --git a/lldb/source/Commands/CommandObjectFile.cpp b/lldb/source/Commands/CommandObjectFile.cpp index 2700e2075ec..25576e1fe82 100644 --- a/lldb/source/Commands/CommandObjectFile.cpp +++ b/lldb/source/Commands/CommandObjectFile.cpp @@ -126,31 +126,14 @@ CommandObjectFile::Execute TargetSP target_sp; - ArchSpec arch; - if (m_options.m_arch.IsValid()) - arch = m_options.m_arch; - else - { - arch = lldb_private::GetDefaultArchitecture (); - if (!arch.IsValid()) - arch = LLDB_ARCH_DEFAULT; - } + ArchSpec arch = m_options.m_arch; Debugger &debugger = interpreter.GetDebugger(); - Error error = debugger.GetTargetList().CreateTarget (debugger, file_spec, arch, NULL, true, target_sp); - - if (error.Fail() && !m_options.m_arch.IsValid()) - { - if (arch == LLDB_ARCH_DEFAULT_32BIT) - arch = LLDB_ARCH_DEFAULT_64BIT; - else - arch = LLDB_ARCH_DEFAULT_32BIT; - error = debugger.GetTargetList().CreateTarget (debugger, file_spec, arch, NULL, true, target_sp); - } + Error error = debugger.GetTargetList().CreateTarget (debugger, file_spec, m_options.m_arch, NULL, true, target_sp); if (target_sp) { debugger.GetTargetList().SetCurrentTarget(target_sp.get()); - result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, arch.AsCString()); + result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().AsCString()); result.SetStatus (eReturnStatusSuccessFinishNoResult); } else diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index 20b008ff5a5..7f4d536321b 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -279,110 +279,6 @@ class CommandObjectProcessAttach : public CommandObject { public: - CommandObjectProcessAttach () : - CommandObject ("process attach", - "Attaches to a process.", - "process attach <cmd-options>") - { - SetHelpLong("Currently, you must set the executable file before you can attach " - "to a process.\n"); - } - - ~CommandObjectProcessAttach () - { - } - - bool - Execute (CommandInterpreter &interpreter, - Args& command, - CommandReturnObject &result) - { - Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); - if (target == NULL) - { - result.AppendError ("invalid target, set executable file using 'file' command"); - result.SetStatus (eReturnStatusFailed); - return false; - } - - // If our listener is NULL, users aren't allows to launch - - Process *process = interpreter.GetDebugger().GetExecutionContext().process; - if (process) - { - if (process->IsAlive()) - { - result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID()); - result.SetStatus (eReturnStatusFailed); - return false; - } - } - - if (command.GetArgumentCount()) - { - result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); - result.SetStatus (eReturnStatusFailed); - } - else - { - const char *plugin_name = NULL; - - if (!m_options.plugin_name.empty()) - plugin_name = m_options.plugin_name.c_str(); - - process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); - - if (process) - { - Error error; - int attach_pid = m_options.pid; - - if (attach_pid != LLDB_INVALID_PROCESS_ID) - { - error = process->Attach (attach_pid); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - else - { - result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", - attach_pid, - error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - else if (!m_options.name.empty()) - { - error = process->Attach (m_options.name.c_str(), m_options.waitfor); - if (error.Success()) - { - result.SetStatus (eReturnStatusSuccessContinuingNoResult); - } - else - { - if (m_options.waitfor) - result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", - m_options.name.c_str(), - error.AsCString()); - else - result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n", - m_options.name.c_str(), - error.AsCString()); - result.SetStatus (eReturnStatusFailed); - } - } - } - } - return result.Succeeded(); - } - - Options * - GetOptions () - { - return &m_options; - } - class CommandOptions : public Options { public: @@ -448,6 +344,68 @@ public: return g_option_table; } + virtual bool + HandleOptionArgumentCompletion (CommandInterpreter &interpreter, + Args &input, + int cursor_index, + int char_pos, + OptionElementVector &opt_element_vector, + int opt_element_index, + int match_start_point, + int max_return_elements, + bool &word_complete, + StringList &matches) + { + int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; + int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; + + // We are only completing the name option for now... + + const lldb::OptionDefinition *opt_defs = GetDefinitions(); + if (opt_defs[opt_defs_index].short_option == 'n') + { + // Are we in the name? + + // Look to see if there is a -P argument provided, and if so use that plugin, otherwise + // use the default plugin. + Process *process = interpreter.GetDebugger().GetExecutionContext().process; + bool need_to_delete_process = false; + + const char *partial_name = NULL; + partial_name = input.GetArgumentAtIndex(opt_arg_pos); + + if (process && process->IsAlive()) + return true; + + Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); + if (target == NULL) + { + // No target has been set yet, for now do host completion. Otherwise I don't know how we would + // figure out what the right target to use is... + std::vector<lldb::pid_t> pids; + Host::ListProcessesMatchingName (partial_name, matches, pids); + return true; + } + if (!process) + { + process = target->CreateProcess (interpreter.GetDebugger().GetListener(), partial_name).get(); + need_to_delete_process = true; + } + + if (process) + { + matches.Clear(); + std::vector<lldb::pid_t> pids; + process->ListProcessesMatchingName (NULL, matches, pids); + if (need_to_delete_process) + target->DeleteCurrentProcess(); + return true; + } + } + + return false; + } + // Options table: Required for subclasses of Options. static lldb::OptionDefinition g_option_table[]; @@ -460,6 +418,211 @@ public: bool waitfor; }; + CommandObjectProcessAttach () : + CommandObject ("process attach", + "Attaches to a process.", + "process attach <cmd-options>") + { + SetHelpLong("Currently, you must set the executable file before you can attach " + "to a process.\n"); + } + + ~CommandObjectProcessAttach () + { + } + + bool + Execute (CommandInterpreter &interpreter, + Args& command, + CommandReturnObject &result) + { + Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); + + Process *process = interpreter.GetDebugger().GetExecutionContext().process; + if (process) + { + if (process->IsAlive()) + { + result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", + process->GetID()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + + if (target == NULL) + { + // If there isn't a current target create one. + TargetSP new_target_sp; + FileSpec emptyFileSpec; + ArchSpec emptyArchSpec; + Error error; + + error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(), + emptyFileSpec, + emptyArchSpec, + NULL, + false, + new_target_sp); + target = new_target_sp.get(); + if (target == NULL || error.Fail()) + { + result.AppendError(error.AsCString("Error creating empty target")); + return false; + } + interpreter.GetDebugger().GetTargetList().SetCurrentTarget(target); + } + + // Record the old executable module, we want to issue a warning if the process of attaching changed the + // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) + + ModuleSP old_exec_module_sp = target->GetExecutableModule(); + ArchSpec old_arch_spec = target->GetArchitecture(); + + if (command.GetArgumentCount()) + { + result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); + result.SetStatus (eReturnStatusFailed); + } + else + { + const char *plugin_name = NULL; + + if (!m_options.plugin_name.empty()) + plugin_name = m_options.plugin_name.c_str(); + + process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); + + if (process) + { + Error error; + int attach_pid = m_options.pid; + + // If we are waiting for a process with this name to show up, do that first. + if (m_options.waitfor) + { + if (m_options.name.empty()) + { + result.AppendError("Invalid arguments: must supply a process name with the waitfor option.\n"); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + { + error = process->Attach (m_options.name.c_str(), m_options.waitfor); + if (error.Success()) + { + result.SetStatus (eReturnStatusSuccessContinuingNoResult); + } + else + { + result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", + m_options.name.c_str(), + error.AsCString()); + result.SetStatus (eReturnStatusFailed); + return false; + } + } + } + else + { + // If the process was specified by name look it up, so we can warn if there are multiple + // processes with this pid. + + if (attach_pid == LLDB_INVALID_PROCESS_ID && !m_options.name.empty()) + { + std::vector<lldb::pid_t> pids; + StringList matches; + + process->ListProcessesMatchingName(m_options.name.c_str(), matches, pids); + if (matches.GetSize() > 1) + { + result.AppendErrorWithFormat("More than one process named %s\n", m_options.name.c_str()); + result.SetStatus (eReturnStatusFailed); + return false; + } + else if (matches.GetSize() == 0) + { + result.AppendErrorWithFormat("Could not find a process named %s\n", m_options.name.c_str()); + result.SetStatus (eReturnStatusFailed); + return false; + } + else + { + attach_pid = pids[0]; + } + + } + + if (attach_pid != LLDB_INVALID_PROCESS_ID) + { + error = process->Attach (attach_pid); + if (error.Success()) + { + result.SetStatus (eReturnStatusSuccessContinuingNoResult); + } + else + { + result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", + attach_pid, + error.AsCString()); + result.SetStatus (eReturnStatusFailed); + } + } + else + { + result.AppendErrorWithFormat ("No PID specified for attach\n", + attach_pid, + error.AsCString()); + result.SetStatus (eReturnStatusFailed); + + } + } + } + } + + if (result.Succeeded()) + { + // Okay, we're done. Last step is to warn if the executable module has changed: + if (!old_exec_module_sp) + { + char new_path[PATH_MAX + 1]; + target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); + + result.AppendMessageWithFormat("Executable module set to \"%s\".\n", + new_path); + } + else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) + { + char old_path[PATH_MAX + 1]; + char new_path[PATH_MAX + 1]; + + old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); + target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); + + result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", + old_path, new_path); + } + + if (!old_arch_spec.IsValid()) + { + result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); + } + else if (old_arch_spec != target->GetArchitecture()) + { + result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", + old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); + } + } + return result.Succeeded(); + } + + Options * + GetOptions () + { + return &m_options; + } + protected: CommandOptions m_options; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 9887cc96336..1e9187baf1a 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -43,7 +43,6 @@ Module::Module(const FileSpec& file_spec, const ArchSpec& arch, const ConstStrin m_object_name.IsEmpty() ? "" : "(", m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), m_object_name.IsEmpty() ? "" : ")"); - } Module::~Module() @@ -516,3 +515,30 @@ Module::GetModificationTime () const { return m_mod_time; } + +bool +Module::IsExecutable () +{ + if (GetObjectFile() == NULL) + return false; + else + return GetObjectFile()->IsExecutable(); +} + +bool +Module::SetArchitecture (const ArchSpec &new_arch) +{ + if (m_arch == new_arch) + return true; + else if (!m_arch.IsValid()) + { + m_arch = new_arch; + return true; + } + else + { + return false; + } + +} + diff --git a/lldb/source/Host/macosx/Host.mm b/lldb/source/Host/macosx/Host.mm index b2ca2bb6ce9..8481564e22f 100644 --- a/lldb/source/Host/macosx/Host.mm +++ b/lldb/source/Host/macosx/Host.mm @@ -15,6 +15,8 @@ #include <stddef.h> #include <sys/sysctl.h> #include <unistd.h> +#include <libproc.h> +#include <sys/proc_info.h> #include <map> #include <string> @@ -802,3 +804,86 @@ Host::WillTerminate () } } +uint32_t +Host::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids) +{ + + int num_pids; + int size_of_pids; + int *pid_list; + uint32_t num_matches = 0; + + size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); + if (size_of_pids == -1) + return 0; + + num_pids = size_of_pids/sizeof(int); + pid_list = (int *) malloc(size_of_pids); + size_of_pids = proc_listpids(PROC_ALL_PIDS, 0, pid_list, size_of_pids); + if (size_of_pids == -1) + return 0; + + pid_t our_pid = getpid(); + + for (int i = 0; i < num_pids; i++) + { + struct proc_bsdinfo bsd_info; + int error = proc_pidinfo (pid_list[i], PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE); + if (error == 0) + continue; + + // Don't offer to attach to zombie processes, already traced or exiting + // processes, and of course, ourselves... It looks like passing the second arg of + // 0 to proc_listpids will exclude zombies anyway, but that's not documented so... + if ((bsd_info.pbi_flags & (PROC_FLAG_TRACED | PROC_FLAG_INEXIT) != 0) + || (bsd_info.pbi_status == SZOMB) + || (bsd_info.pbi_pid == our_pid)) + continue; + char pid_name[MAXCOMLEN * 2 + 1]; + int name_len; + name_len = proc_name(bsd_info.pbi_pid, pid_name, MAXCOMLEN * 2); + if (name_len == 0) + continue; + + if (strstr(pid_name, name) != pid_name) + continue; + matches.AppendString (pid_name); + pids.push_back (bsd_info.pbi_pid); + num_matches++; + } + + return num_matches; +} + +ArchSpec +Host::GetArchSpecForExistingProcess (lldb::pid_t pid) +{ + ArchSpec return_spec; + + struct proc_bsdinfo bsd_info; + int error = proc_pidinfo (pid, PROC_PIDTBSDINFO, (uint64_t) 0, &bsd_info, PROC_PIDTBSDINFO_SIZE); + if (error == 0) + return return_spec; + if (bsd_info.pbi_flags & PROC_FLAG_LP64) + return_spec.SetArch(LLDB_ARCH_DEFAULT_64BIT); + else + return_spec.SetArch(LLDB_ARCH_DEFAULT_32BIT); + + return return_spec; +} + +ArchSpec +Host::GetArchSpecForExistingProcess (const char *process_name) +{ + ArchSpec returnSpec; + StringList matches; + std::vector<lldb::pid_t> pids; + if (ListProcessesMatchingName(process_name, matches, pids)) + { + if (matches.GetSize() == 1) + { + return GetArchSpecForExistingProcess(pids[0]); + } + } + return returnSpec; +} diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index fea069e5fc3..de6a51f7e40 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -1016,8 +1016,7 @@ DynamicLoaderMacOSXDYLD::SetNotificationBreakpoint () return m_break_id != LLDB_INVALID_BREAK_ID; } -//----------------------------------------------------------------------Target.h - +//---------------------------------------------------------------------- // Member function that gets called when the process state changes. //---------------------------------------------------------------------- void diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp index f9bf3eb8cb1..3a6860fe6de 100644 --- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp @@ -199,7 +199,18 @@ ObjectFile * ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file) { uint32_t arch_idx = 0; - const ArchSpec arch = m_module->GetArchitecture(); + ArchSpec arch; + // If the module hasn't specified an architecture yet, set it to the default + // architecture: + if (!m_module->GetArchitecture().IsValid()) + { + arch = lldb_private::GetDefaultArchitecture (); + if (!arch.IsValid()) + arch = LLDB_ARCH_DEFAULT; + } + else + arch = m_module->GetArchitecture(); + ArchSpec curr_arch; for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 032fb75c06d..1568639c811 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -145,6 +145,13 @@ ObjectFileELF::~ObjectFileELF() { } +bool +ObjectFileELF::IsExecutable() const +{ + // FIXME: How is this marked in ELF? + return false; +} + ByteOrder ObjectFileELF::GetByteOrder() const { diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 7c941a70e0e..dcee1ad5d09 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -86,6 +86,9 @@ public: virtual lldb::ByteOrder GetByteOrder() const; + virtual bool + IsExecutable () const; + virtual size_t GetAddressByteSize() const; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index c0d7eecef23..9d05fac4d2e 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -161,7 +161,8 @@ ObjectFileMachO::ParseHeader () m_data.GetU32(&offset, &m_header.cputype, 6); ArchSpec mach_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype); - if (mach_arch == m_module->GetArchitecture()) + + if (SetModulesArchitecture (mach_arch)) { // Read in all only the load command data DataBufferSP data_sp(m_file.ReadFileContents(m_offset, m_header.sizeofcmds + MachHeaderSizeFromMagic(m_header.magic))); @@ -184,6 +185,11 @@ ObjectFileMachO::GetByteOrder () const return m_data.GetByteOrder (); } +bool +ObjectFileMachO::IsExecutable() const +{ + return m_header.filetype == HeaderFileTypeExecutable; +} size_t ObjectFileMachO::GetAddressByteSize () const diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index d00ae0d73c0..d3000f45e87 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -66,6 +66,9 @@ public: virtual lldb::ByteOrder GetByteOrder () const; + + virtual bool + IsExecutable () const; virtual size_t GetAddressByteSize () const; diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp index 817c8380fcd..334c21e60ca 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp @@ -2208,5 +2208,10 @@ ProcessMacOSX::Initialize() } } +uint32_t +ProcessMacOSX::ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids) +{ + return Host::ListProcessesMatchingName (name, matches, pids); +} diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h index 6f1f3362679..20628622a8a 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h @@ -18,6 +18,7 @@ // Other libraries and framework includes #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Core/StringList.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" @@ -110,6 +111,9 @@ public: virtual void DidAttach (); + + virtual uint32_t + ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids); //------------------------------------------------------------------ // PluginInterface protocol diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 759f20dafb4..1c6b164ca61 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -93,7 +93,8 @@ ProcessGDBRemote::CanDebug(Target &target) ModuleSP exe_module_sp(target.GetExecutableModule()); if (exe_module_sp.get()) return exe_module_sp->GetFileSpec().Exists(); - return false; + // However, if there is no executable module, we return true since we might be preparing to attach. + return true; } //---------------------------------------------------------------------- @@ -106,7 +107,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_stdio_communication ("gdb-remote.stdio"), m_stdio_mutex (Mutex::eMutexTypeRecursive), m_stdout_data (), - m_arch_spec (), m_byte_order (eByteOrderHost), m_gdb_comm(), m_debugserver_pid (LLDB_INVALID_PROCESS_ID), @@ -124,7 +124,8 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_max_memory_size (512), m_libunwind_target_type (UNW_TARGET_UNSPECIFIED), m_libunwind_addr_space (NULL), - m_waiting_for_attach (false) + m_waiting_for_attach (false), + m_local_debugserver (true) { } @@ -563,11 +564,9 @@ ProcessGDBRemote::DidLaunchOrAttach () { m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS; - Module * exe_module = GetTarget().GetExecutableModule ().get(); + Module * exe_module = GetTarget().GetExecutableModule ().get(); assert(exe_module); - m_arch_spec = exe_module->GetArchitecture(); - ObjectFile *exe_objfile = exe_module->GetObjectFile(); assert(exe_objfile); @@ -580,8 +579,9 @@ ProcessGDBRemote::DidLaunchOrAttach () // See if the GDB server supports the qHostInfo information const char *vendor = m_gdb_comm.GetVendorString().AsCString(); const char *os_type = m_gdb_comm.GetOSString().AsCString(); + ArchSpec arch_spec = GetTarget().GetArchitecture(); - if (m_arch_spec.IsValid() && m_arch_spec == ArchSpec ("arm")) + if (arch_spec.IsValid() && arch_spec == ArchSpec ("arm")) { // For ARM we can't trust the arch of the process as it could // have an armv6 object file, but be running on armv7 kernel. @@ -589,7 +589,7 @@ ProcessGDBRemote::DidLaunchOrAttach () } if (!inferior_arch.IsValid()) - inferior_arch = m_arch_spec; + inferior_arch = arch_spec; if (vendor == NULL) vendor = Host::GetVendorString().AsCString("apple"); @@ -622,11 +622,11 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid) Error error; // Clear out and clean up from any current state Clear(); - // HACK: require arch be set correctly at the target level until we can - // figure out a good way to determine the arch of what we are attaching to - m_arch_spec = m_target.GetArchitecture(); - + ArchSpec arch_spec = GetTarget().GetArchitecture(); + //Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS); + + if (attach_pid != LLDB_INVALID_PROCESS_ID) { SetPrivateState (eStateAttaching); @@ -638,7 +638,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid) NULL, LLDB_INVALID_PROCESS_ID, NULL, false, - m_arch_spec); + arch_spec); if (error.Fail()) { @@ -724,7 +724,6 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait Clear(); // HACK: require arch be set correctly at the target level until we can // figure out a good way to determine the arch of what we are attaching to - m_arch_spec = m_target.GetArchitecture(); //Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS); if (process_name && process_name[0]) @@ -732,6 +731,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait SetPrivateState (eStateAttaching); char host_port[128]; + ArchSpec arch_spec = GetTarget().GetArchitecture(); snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ()); error = StartDebugserverProcess (host_port, NULL, @@ -739,7 +739,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait NULL, LLDB_INVALID_PROCESS_ID, NULL, false, - m_arch_spec); + arch_spec); if (error.Fail()) { const char *error_string = error.AsCString(); @@ -840,9 +840,26 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait void ProcessGDBRemote::DidAttach () { - DidLaunchOrAttach (); + // If we haven't got an executable module yet, then we should make a dynamic loader, and + // see if it can find the executable module for us. If we do have an executable module, + // make sure it matches the process we've just attached to. + + ModuleSP exe_module_sp = GetTarget().GetExecutableModule(); + if (!m_dynamic_loader_ap.get()) + { + m_dynamic_loader_ap.reset(DynamicLoader::FindPlugin(this, "dynamic-loader.macosx-dyld")); + } + if (m_dynamic_loader_ap.get()) m_dynamic_loader_ap->DidAttach(); + + Module * new_exe_module = GetTarget().GetExecutableModule().get(); + if (new_exe_module == NULL) + { + + } + + DidLaunchOrAttach (); } Error @@ -876,7 +893,7 @@ ProcessGDBRemote::GetSoftwareBreakpointTrapOpcode (BreakpointSite* bp_site) static const uint8_t g_ppc_breakpoint_opcode[] = { 0x7F, 0xC0, 0x00, 0x08 }; static const uint8_t g_i386_breakpoint_opcode[] = { 0xCC }; - ArchSpec::CPU arch_cpu = m_arch_spec.GetGenericCPUType(); + ArchSpec::CPU arch_cpu = GetTarget().GetArchitecture().GetGenericCPUType(); switch (arch_cpu) { case ArchSpec::eCPU_i386: @@ -1060,13 +1077,16 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) void ProcessGDBRemote::RefreshStateAfterStop () { + // FIXME - add a variable to tell that we're in the middle of attaching if we + // need to know that. // We must be attaching if we don't already have a valid architecture - if (!m_arch_spec.IsValid()) - { - Module *exe_module = GetTarget().GetExecutableModule().get(); - if (exe_module) - m_arch_spec = exe_module->GetArchitecture(); - } +// if (!GetTarget().GetArchitecture().IsValid()) +// { +// Module *exe_module = GetTarget().GetExecutableModule().get(); +// if (exe_module) +// m_arch_spec = exe_module->GetArchitecture(); +// } + // Let all threads recover from stopping and do any clean up based // on the previous thread state (if any). m_thread_list.RefreshStateAfterStop(); @@ -2251,3 +2271,19 @@ ProcessGDBRemote::GetDispatchQueueNameForThread return dispatch_queue_name.c_str(); } +uint32_t +ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids) +{ + // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver + // process and ask it for the list of processes. But if we are local, we can let the Host do it. + if (m_local_debugserver) + { + return Host::ListProcessesMatchingName (name, matches, pids); + } + else + { + // FIXME: Implement talking to the remote debugserver. + return 0; + } + +} diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 79872b4db4c..d1fb7bf9155 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -21,6 +21,7 @@ #include "lldb/Core/Error.h" #include "lldb/Core/InputReader.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/StringList.h" #include "lldb/Core/ThreadSafeValue.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" @@ -67,6 +68,9 @@ public: virtual bool CanDebug (lldb_private::Target &target); + virtual uint32_t + ListProcessesMatchingName (const char *name, lldb_private::StringList &matches, std::vector<lldb::pid_t> &pids); + //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one //------------------------------------------------------------------ @@ -262,17 +266,6 @@ protected: void AppendSTDOUT (const char* s, size_t len); - lldb_private::ArchSpec& - GetArchSpec() - { - return m_arch_spec; - } - const lldb_private::ArchSpec& - GetArchSpec() const - { - return m_arch_spec; - } - void Clear ( ); @@ -328,7 +321,6 @@ protected: lldb_private::Communication m_stdio_communication; lldb_private::Mutex m_stdio_mutex; // Multithreaded protection for stdio std::string m_stdout_data; - lldb_private::ArchSpec m_arch_spec; lldb::ByteOrder m_byte_order; GDBRemoteCommunication m_gdb_comm; lldb::pid_t m_debugserver_pid; @@ -349,6 +341,7 @@ protected: lldb_private::unw_targettype_t m_libunwind_target_type; lldb_private::unw_addr_space_t m_libunwind_addr_space; // libunwind address space object for this process. bool m_waiting_for_attach; + bool m_local_debugserver; // Is the debugserver process we are talking to local or on another machine. void ResetGDBRemoteState (); diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index 8d224488641..d4225cf4e46 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -90,3 +90,10 @@ ObjectFile::FindPlugin (Module* module, const FileSpec* file, lldb::addr_t file_ } return NULL; } + +bool +ObjectFile::SetModulesArchitecture (const ArchSpec &new_arch) +{ + return m_module->SetArchitecture (new_arch); +} + diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 9f5c42a73f6..148eabe1ea3 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -1048,6 +1048,24 @@ Process::CompleteAttach () if (state == eStateStopped || state == eStateCrashed) { DidAttach (); + // Figure out which one is the executable, and set that in our target: + ModuleList &modules = GetTarget().GetImages(); + + size_t num_modules = modules.GetSize(); + for (int i = 0; i < num_modules; i++) + { + ModuleSP module_sp = modules.GetModuleAtIndex(i); + if (module_sp->IsExecutable()) + { + ModuleSP exec_module = GetTarget().GetExecutableModule(); + if (!exec_module || exec_module != module_sp) + { + + GetTarget().SetExecutableModule (module_sp, false); + } + break; + } + } // This delays passing the stopped event to listeners till DidLaunch gets // a chance to complete... @@ -1073,6 +1091,16 @@ Process::Attach (lldb::pid_t attach_pid) m_target_triple.Clear(); m_abi_sp.reset(); + // Find the process and its architecture. Make sure it matches the architecture + // of the current Target, and if not adjust it. + + ArchSpec attach_spec = GetArchSpecForExistingProcess (attach_pid); + if (attach_spec != GetTarget().GetArchitecture()) + { + // Set the architecture on the target. + GetTarget().SetArchitecture(attach_spec); + } + Error error (WillAttachToProcessWithID(attach_pid)); if (error.Success()) { @@ -1102,6 +1130,16 @@ Process::Attach (const char *process_name, bool wait_for_launch) { m_target_triple.Clear(); m_abi_sp.reset(); + + // Find the process and its architecture. Make sure it matches the architecture + // of the current Target, and if not adjust it. + + ArchSpec attach_spec = GetArchSpecForExistingProcess (process_name); + if (attach_spec != GetTarget().GetArchitecture()) + { + // Set the architecture on the target. + GetTarget().SetArchitecture(attach_spec); + } Error error (WillAttachToProcessWithName(process_name, wait_for_launch)); if (error.Success()) @@ -1863,3 +1901,22 @@ Process::GetObjCObjectPrinter() return m_objc_object_printer; } +uint32_t +Process::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids) +{ + return 0; +} + +ArchSpec +Process::GetArchSpecForExistingProcess (lldb::pid_t pid) +{ + return Host::GetArchSpecForExistingProcess (pid); +} + +ArchSpec +Process::GetArchSpecForExistingProcess (const char *process_name) +{ + return Host::GetArchSpecForExistingProcess (process_name); +} + + diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index 9d48e8188d4..54fc6daeaf7 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -79,7 +79,7 @@ public: &m_thread.GetProcess(), &m_thread, m_thread.GetStackFrameAtIndex(0).get(), - false); + true); m_should_stop = bp_site_sp->ShouldStop (&context); } diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index fdff5ad3818..c8ed3c568c4 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -373,6 +373,10 @@ Target::SetExecutableModule (ModuleSP& executable_sp, bool get_dependent_files) m_images.Append(executable_sp); // The first image is our exectuable file ArchSpec exe_arch = executable_sp->GetArchitecture(); + // If we haven't set an architecture yet, reset our architecture based on what we found in the executable module. + if (!m_arch_spec.IsValid()) + m_arch_spec = exe_arch; + FileSpecList dependent_files; ObjectFile * executable_objfile = executable_sp->GetObjectFile(); if (executable_objfile == NULL) @@ -426,18 +430,63 @@ Target::GetImages () ArchSpec Target::GetArchitecture () const { - ArchSpec arch; - if (m_images.GetSize() > 0) + return m_arch_spec; +} + +bool +Target::SetArchitecture (const ArchSpec &arch_spec) +{ + if (m_arch_spec == arch_spec) { - Module *exe_module = m_images.GetModulePointerAtIndex(0); - if (exe_module) - arch = exe_module->GetArchitecture(); + // If we're setting the architecture to our current architecture, we + // don't need to do anything. + return true; + } + else if (!m_arch_spec.IsValid()) + { + // If we haven't got a valid arch spec, then we just need to set it. + m_arch_spec = arch_spec; + return true; + } + else + { + // If we have an executable file, try to reset the executable to the desired architecture + m_arch_spec = arch_spec; + ModuleSP executable_sp = GetExecutableModule (); + m_images.Clear(); + m_scratch_ast_context_ap.reset(); + m_triple.Clear(); + // Need to do something about unsetting breakpoints. + + if (executable_sp) + { + FileSpec exec_file_spec = executable_sp->GetFileSpec(); + Error error = ModuleList::GetSharedModule(exec_file_spec, + arch_spec, + NULL, + NULL, + 0, + executable_sp, + NULL, + NULL); + + if (!error.Fail() && executable_sp) + { + SetExecutableModule (executable_sp, true); + return true; + } + else + { + return false; + } + } + else + { + return false; + } } - return arch; } - - bool Target::GetTargetTriple(ConstString &triple) { diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp index 4e2952ec0a3..ac169465e28 100644 --- a/lldb/source/Target/TargetList.cpp +++ b/lldb/source/Target/TargetList.cpp @@ -60,30 +60,50 @@ TargetList::CreateTarget file.GetFilename().AsCString(), arch.AsCString(), uuid_ptr); - ModuleSP exe_module_sp; - FileSpec resolved_file(file); - if (!Host::ResolveExecutableInBundle (&resolved_file)) - resolved_file = file; - - Error error = ModuleList::GetSharedModule(resolved_file, - arch, - uuid_ptr, - NULL, - 0, - exe_module_sp, - NULL, - NULL); - if (exe_module_sp) + Error error; + + if (!file) { target_sp.reset(new Target(debugger)); - target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); + target_sp->SetArchitecture(arch); + } + else + { + ModuleSP exe_module_sp; + FileSpec resolved_file(file); + if (!Host::ResolveExecutableInBundle (&resolved_file)) + resolved_file = file; - if (target_sp.get()) + error = ModuleList::GetSharedModule(resolved_file, + arch, + uuid_ptr, + NULL, + 0, + exe_module_sp, + NULL, + NULL); + if (exe_module_sp) { - Mutex::Locker locker(m_target_list_mutex); - m_current_target_idx = m_target_list.size(); - m_target_list.push_back(target_sp); + if (exe_module_sp->GetObjectFile() == NULL) + { + error.SetErrorStringWithFormat("%s%s%s: doesn't contain architecture %s", + file.GetDirectory().AsCString(), + file.GetDirectory() ? "/" : "", + file.GetFilename().AsCString(), + arch.AsCString()); + return error; + } + target_sp.reset(new Target(debugger)); + target_sp->SetExecutableModule (exe_module_sp, get_dependent_files); } + } + + if (target_sp.get()) + { + Mutex::Locker locker(m_target_list_mutex); + m_current_target_idx = m_target_list.size(); + m_target_list.push_back(target_sp); + } // target_sp.reset(new Target); // // Let the target resolve any funky bundle paths before we try and get @@ -107,7 +127,6 @@ TargetList::CreateTarget // m_target_list.push_back(target_sp); // } // } - } else { target_sp.reset(); |