diff options
| author | Greg Clayton <gclayton@apple.com> | 2010-11-18 05:57:03 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2010-11-18 05:57:03 +0000 |
| commit | 3af9ea56d30ca97a5ce31cb1024501b324f8fa47 (patch) | |
| tree | 6c613eee05c2d066b9a58e727f079725ffc34964 /lldb/source | |
| parent | 19ca5608db90bf06bfaba3e1b28af6ed68165d7d (diff) | |
| download | bcm5719-llvm-3af9ea56d30ca97a5ce31cb1024501b324f8fa47.tar.gz bcm5719-llvm-3af9ea56d30ca97a5ce31cb1024501b324f8fa47.zip | |
Fixed Process::Halt() as it was broken for "process halt" after recent changes
to the DoHalt down in ProcessGDBRemote. I also moved the functionality that
was in ProcessGDBRemote::DoHalt up into Process::Halt so not every class has
to implement a tricky halt/resume on the internal state thread. The
functionality is the same as it was before with two changes:
- when we eat the event we now just reuse the event we consume when the private
state thread is paused and set the interrupted bool on the event if needed
- we also properly update the Process::m_public_state with the state of the
event we consume.
Prior to this, if you issued a "process halt" it would eat the event, not
update the process state, and then produce a new event with the interrupted
bit set and send it. Anyone listening to the event would get the stopped event
with a process that whose state was set to "running".
Fixed debugserver to not have to be spawned with the architecture of the
inferior process. This worked fine for launching processes, but when attaching
to processes by name or pid without a file in lldb, it would fail.
Now debugserver can support multiple architectures for a native debug session
on the current host. This currently means i386 and x86_64 are supported in
the same binary and a x86_64 debugserver can attach to a i386 executable.
This change involved a lot of changes to make sure we dynamically detect the
correct registers for the inferior process.
llvm-svn: 119680
Diffstat (limited to 'lldb/source')
7 files changed, 171 insertions, 97 deletions
diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index bc268b8e905..227a981b809 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -59,8 +59,10 @@ DynamicLoaderMacOSXDYLD::DynamicLoaderMacOSXDYLD (Process* process) : m_dyld(), m_dyld_all_image_infos_addr(LLDB_INVALID_ADDRESS), m_dyld_all_image_infos(), + m_dyld_all_image_infos_stop_id (UINT32_MAX), m_break_id(LLDB_INVALID_BREAK_ID), m_dyld_image_infos(), + m_dyld_image_infos_stop_id (UINT32_MAX), m_mutex(Mutex::eMutexTypeRecursive) { } @@ -83,10 +85,8 @@ void DynamicLoaderMacOSXDYLD::DidAttach () { PrivateInitialize(m_process); - if (NeedToLocateDYLD ()) - LocateDYLD (); + LocateDYLD (); SetNotificationBreakpoint (); - UpdateAllImageInfos(); } //------------------------------------------------------------------ @@ -99,10 +99,8 @@ void DynamicLoaderMacOSXDYLD::DidLaunch () { PrivateInitialize(m_process); - if (NeedToLocateDYLD ()) - LocateDYLD (); + LocateDYLD (); SetNotificationBreakpoint (); - UpdateAllImageInfos(); } @@ -401,12 +399,23 @@ bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () { Mutex::Locker locker(m_mutex); + + // the all image infos is already valid for this process stop ID + if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id) + return true; + m_dyld_all_image_infos.Clear(); if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { - const ByteOrder endian = m_process->GetByteOrder(); - const uint32_t addr_size = m_process->GetAddressByteSize(); + ByteOrder byte_order = m_process->GetByteOrder(); + uint32_t addr_size = 4; + if (m_dyld_all_image_infos_addr > UINT32_MAX) + addr_size = 8; + uint8_t buf[256]; + DataExtractor data (buf, sizeof(buf), byte_order, addr_size); + uint32_t offset = 0; + const size_t count_v2 = sizeof (uint32_t) + // version sizeof (uint32_t) + // infoArrayCount addr_size + // infoArray @@ -434,9 +443,23 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () Error error; if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4) { - DataExtractor data(buf, 4, endian, addr_size); - uint32_t offset = 0; m_dyld_all_image_infos.version = data.GetU32(&offset); + // If anything in the high byte is set, we probably got the byte + // order incorrect (the process might not have it set correctly + // yet due to attaching to a program without a specified file). + if (m_dyld_all_image_infos.version & 0xff000000) + { + // We have guessed the wrong byte order. Swap it and try + // reading the version again. + if (byte_order == eByteOrderLittle) + byte_order = eByteOrderBig; + else + byte_order = eByteOrderLittle; + + data.SetByteOrder (byte_order); + offset = 0; + m_dyld_all_image_infos.version = data.GetU32(&offset); + } } else { @@ -451,8 +474,7 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error); if (bytes_read == count) { - DataExtractor data(buf, count, endian, addr_size); - uint32_t offset = 0; + offset = 0; m_dyld_all_image_infos.version = data.GetU32(&offset); m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); @@ -486,6 +508,7 @@ DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset; } } + m_dyld_all_image_infos_stop_id = m_process->GetStopID(); return true; } } @@ -504,6 +527,9 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() if (ReadAllImageInfosStructure ()) { Mutex::Locker locker(m_mutex); + if (m_process->GetStopID() == m_dyld_image_infos_stop_id) + m_dyld_image_infos.size(); + uint32_t idx; uint32_t i = 0; DYLDImageInfo::collection old_dyld_all_image_infos; @@ -511,8 +537,8 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() // If we made it here, we are assuming that the all dylib info data should // be valid, lets read the info array. - const ByteOrder endian = m_process->GetByteOrder(); - const uint32_t addr_size = m_process->GetAddressByteSize(); + const ByteOrder endian = m_dyld.GetByteOrder(); + const uint32_t addr_size = m_dyld.GetAddressByteSize(); if (m_dyld_all_image_infos.dylib_info_count > 0) { @@ -605,6 +631,7 @@ DynamicLoaderMacOSXDYLD::UpdateAllImageInfos() if (log) PutToLog(log.get()); } + m_dyld_image_infos_stop_id = m_process->GetStopID(); } else { diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h index 34ea8a46781..d8dbe711b3d 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h @@ -266,6 +266,41 @@ protected: return uuid.IsValid(); } + uint32_t + GetAddressByteSize () + { + if (header.cputype) + { + if (header.cputype & llvm::MachO::CPUArchABI64) + return 8; + else + return 4; + } + return 0; + } + + lldb::ByteOrder + GetByteOrder() + { + switch (header.magic) + { + case llvm::MachO::HeaderMagic32: // MH_MAGIC + case llvm::MachO::HeaderMagic64: // MH_MAGIC_64 + return lldb::eByteOrderHost; + + case llvm::MachO::HeaderMagic32Swapped: // MH_CIGAM + case llvm::MachO::HeaderMagic64Swapped: // MH_CIGAM_64 + if (lldb::eByteOrderHost == lldb::eByteOrderLittle) + return lldb::eByteOrderBig; + else + return lldb::eByteOrderLittle; + default: + assert (!"invalid header.magic value"); + break; + } + return lldb::eByteOrderHost; + } + const Segment * FindSegment (const lldb_private::ConstString &name) const; @@ -348,8 +383,10 @@ protected: DYLDImageInfo m_dyld; // Info about the curent dyld being used lldb::addr_t m_dyld_all_image_infos_addr; DYLDAllImageInfos m_dyld_all_image_infos; + uint32_t m_dyld_all_image_infos_stop_id; lldb::user_id_t m_break_id; DYLDImageInfo::collection m_dyld_image_infos; // Current shared libraries information + uint32_t m_dyld_image_infos_stop_id; // The process stop ID that "m_dyld_image_infos" is valid for mutable lldb_private::Mutex m_mutex; lldb_private::Process::Notifications m_notification_callbacks; diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp index 259c08072a1..b3933169841 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.cpp @@ -235,9 +235,7 @@ ProcessMacOSX::ProcessMacOSX(Target& target, Listener &listener) : m_exception_messages (), m_exception_messages_mutex (Mutex::eMutexTypeRecursive), m_arch_spec (), - m_dynamic_loader_ap (), -// m_wait_thread (LLDB_INVALID_HOST_THREAD), - m_byte_order (eByteOrderHost) + m_dynamic_loader_ap () { } @@ -676,6 +674,7 @@ ProcessMacOSX::RefreshStateAfterStop () Error ProcessMacOSX::DoHalt (bool &caused_stop) { + caused_stop = true; return Signal (SIGSTOP); } diff --git a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h index 92d2c9c1653..4f8bdb930b7 100644 --- a/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h +++ b/lldb/source/Plugins/Process/MacOSX-User/source/ProcessMacOSX.h @@ -247,8 +247,6 @@ protected: lldb_private::Mutex m_exception_messages_mutex; // Multithreaded protection for m_exception_messages lldb_private::ArchSpec m_arch_spec; std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap; -// lldb::thread_t m_wait_thread; - lldb::ByteOrder m_byte_order; //---------------------------------------------------------------------- // Child process control diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index fcbd523699f..5496a02343a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -105,7 +105,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_dynamic_loader_ap (), m_flags (0), m_stdio_mutex (Mutex::eMutexTypeRecursive), - m_byte_order (eByteOrderHost), m_gdb_comm(), m_debugserver_pid (LLDB_INVALID_PROCESS_ID), m_debugserver_thread (LLDB_INVALID_HOST_THREAD), @@ -339,13 +338,13 @@ ProcessGDBRemote::WillLaunch (Module* module) } Error -ProcessGDBRemote::WillAttach (lldb::pid_t pid) +ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid) { return WillLaunchOrAttach (); } Error -ProcessGDBRemote::WillAttach (const char *process_name, bool wait_for_launch) +ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) { return WillLaunchOrAttach (); } @@ -556,8 +555,6 @@ ProcessGDBRemote::ConnectToDebugserver (const char *host_port) if (response.IsOKPacket()) m_gdb_comm.SetAckMode (false); } - - BuildDynamicRegisterInfo (); } return error; } @@ -574,22 +571,23 @@ ProcessGDBRemote::DidLaunchOrAttach () { m_dispatch_queue_offsets_addr = LLDB_INVALID_ADDRESS; - Module * exe_module = GetTarget().GetExecutableModule ().get(); + BuildDynamicRegisterInfo (); + + m_byte_order = m_gdb_comm.GetByteOrder(); + + Module * exe_module = GetTarget().GetExecutableModule().get(); assert(exe_module); ObjectFile *exe_objfile = exe_module->GetObjectFile(); assert(exe_objfile); - m_byte_order = exe_objfile->GetByteOrder(); - assert (m_byte_order != eByteOrderInvalid); - StreamString strm; ArchSpec inferior_arch; // 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(); + ArchSpec arch_spec (GetTarget().GetArchitecture()); if (arch_spec.IsValid() && arch_spec == ArchSpec ("arm")) { @@ -858,25 +856,8 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait void ProcessGDBRemote::DidAttach () { - // 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 (); } @@ -1124,45 +1105,26 @@ Error ProcessGDBRemote::DoHalt (bool &caused_stop) { Error error; - caused_stop = false; if (m_gdb_comm.IsRunning()) { - PausePrivateStateThread(); + caused_stop = true; bool timed_out = false; Mutex::Locker locker; - if (m_gdb_comm.SendInterrupt (locker, 2, &timed_out)) - { - EventSP event_sp; - TimeValue timeout_time; - timeout_time = TimeValue::Now(); - timeout_time.OffsetWithSeconds(2); - - StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp); - - if (!StateIsStoppedState (state)) - { - LogSP log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); - if (log) - log->Printf("ProcessGDBRemote::DoHalt() failed to stop after sending interrupt"); - error.SetErrorString ("Did not get stopped event after interrupt succeeded."); - } - else - caused_stop = true; - } - else + if (!m_gdb_comm.SendInterrupt (locker, 2, &timed_out)) { if (timed_out) error.SetErrorString("timed out sending interrupt packet"); else error.SetErrorString("unknown error sending interrupt packet"); } - - // Resume the private state thread at this point. - ResumePrivateStateThread(); - } + else + { + caused_stop = false; + } + return error; } @@ -1265,12 +1227,6 @@ ProcessGDBRemote::DoDestroy () return error; } -ByteOrder -ProcessGDBRemote::GetByteOrder () const -{ - return m_byte_order; -} - //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 1e85e9918a7..546f1054536 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -90,10 +90,10 @@ public: DidLaunch (); virtual lldb_private::Error - WillAttach (lldb::pid_t pid); + WillAttachToProcessWithID (lldb::pid_t pid); virtual lldb_private::Error - WillAttach (const char *process_name, bool wait_for_launch); + WillAttachToProcessWithName (const char *process_name, bool wait_for_launch); lldb_private::Error WillLaunchOrAttach (); @@ -215,9 +215,6 @@ public: virtual lldb_private::Error DisableWatchpoint (lldb_private::WatchpointLocation *wp_loc); - virtual lldb::ByteOrder - GetByteOrder () const; - virtual lldb_private::DynamicLoader * GetDynamicLoader (); @@ -322,7 +319,6 @@ protected: std::auto_ptr<lldb_private::DynamicLoader> m_dynamic_loader_ap; lldb_private::Flags m_flags; // Process specific flags (see eFlags enums) lldb_private::Mutex m_stdio_mutex; // Multithreaded protection for stdio - lldb::ByteOrder m_byte_order; GDBRemoteCommunication m_gdb_comm; lldb::pid_t m_debugserver_pid; lldb::thread_t m_debugserver_thread; diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 749ae3ceb88..a86a4e10187 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -85,12 +85,19 @@ Process::Process(Target &target, Listener &listener) : m_exit_string (), m_thread_list (this), m_notifications (), - m_persistent_vars(), - m_listener(listener), + m_image_tokens (), + m_listener (listener), + m_breakpoint_site_list (), + m_persistent_vars (), + m_dynamic_checkers_ap (), m_unix_signals (), + m_target_triple (), + m_byte_order (eByteOrderHost), + m_addr_byte_size (0), + m_abi_sp (), m_process_input_reader (), m_stdio_communication ("lldb.process.stdio"), - m_stdio_comm_mutex (Mutex::eMutexTypeRecursive), + m_stdio_communication_mutex (Mutex::eMutexTypeRecursive), m_stdout_data () { UpdateInstanceName(); @@ -1438,19 +1445,71 @@ Process::Halt () if (error.Success()) { - bool caused_stop; + + bool caused_stop = false; + EventSP event_sp; + + // Pause our private state thread so we can ensure no one else eats + // the stop event out from under us. + PausePrivateStateThread(); + + // Ask the process subclass to actually halt our process error = DoHalt(caused_stop); if (error.Success()) { - DidHalt(); + // If "caused_stop" is true, then DoHalt stopped the process. If + // "caused_stop" is false, the process was already stopped. + // If the DoHalt caused the process to stop, then we want to catch + // this event and set the interrupted bool to true before we pass + // this along so clients know that the process was interrupted by + // a halt command. if (caused_stop) { - ProcessEventData *new_data = new ProcessEventData (GetTarget().GetProcessSP(), eStateStopped); - new_data->SetInterrupted(true); - BroadcastEvent (eBroadcastBitStateChanged, new_data); + // Wait for 2 seconds for the process to stop. + TimeValue timeout_time; + timeout_time = TimeValue::Now(); + timeout_time.OffsetWithSeconds(2); + StateType state = WaitForStateChangedEventsPrivate (&timeout_time, event_sp); + + if (state == eStateInvalid) + { + // We timeout out and didn't get a stop event... + error.SetErrorString ("Halt timed out."); + } + else + { + // Since we are eating the event, we need to update our state + // otherwise the process state will not match reality... + SetPublicState(state); + + if (StateIsStoppedState (state)) + { + // We caused the process to interrupt itself, so mark this + // as such in the stop event so clients can tell an interrupted + // process from a natural stop + ProcessEventData::SetInterruptedInEvent (event_sp.get(), true); + } + else + { + LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf("Process::Halt() failed to stop, state is: %s", StateAsCString(state)); + error.SetErrorString ("Did not get stopped event after halt."); + } + } } + DidHalt(); + } - + // Resume our private state thread before we post the event (if any) + ResumePrivateStateThread(); + + // Post any event we might have consumed. If all goes well, we will have + // stopped the process, intercepted the event and set the interrupted + // bool in the event. + if (event_sp) + BroadcastEvent(event_sp); + } return error; } @@ -1530,7 +1589,9 @@ Process::GetTarget () const uint32_t Process::GetAddressByteSize() { - return m_target.GetArchitecture().GetAddressByteSize(); + if (m_addr_byte_size == 0) + return m_target.GetArchitecture().GetAddressByteSize(); + return m_addr_byte_size; } bool @@ -1603,8 +1664,8 @@ Process::ShouldBroadcastEvent (Event *event_ptr) // If no thread has an opinion, we don't report it. if (ProcessEventData::GetInterruptedFromEvent (event_ptr)) { - if (log) - log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s", event_ptr, StateAsCString(state)); + if (log) + log->Printf ("Process::ShouldBroadcastEvent (%p) stopped due to an interrupt, state: %s", event_ptr, StateAsCString(state)); return true; } else @@ -2074,7 +2135,7 @@ Process::GetArchSpecForExistingProcess (const char *process_name) void Process::AppendSTDOUT (const char * s, size_t len) { - Mutex::Locker locker (m_stdio_comm_mutex); + Mutex::Locker locker (m_stdio_communication_mutex); m_stdout_data.append (s, len); BroadcastEventIfUnique (eBroadcastBitSTDOUT); |

