diff options
29 files changed, 688 insertions, 419 deletions
diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h index 86a19ae0568..a41a3588907 100644 --- a/lldb/include/lldb/API/SBThread.h +++ b/lldb/include/lldb/API/SBThread.h @@ -35,6 +35,30 @@ public: lldb::StopReason GetStopReason(); +// +// // Get the number of words associated with the stop reason. +// size_t +// GetStopReasonDataCount(); +// +// //-------------------------------------------------------------------------- +// // Get information associated with a stop reason. +// // +// // Breakpoint and watchpoint stop reasons will have data that consists of +// // pairs of breakpoint/watchpoint IDs followed by the breakpoint/watchpoint +// // location IDs (they always come in pairs). +// // +// // Stop Reason Count Data Type +// // ======================== ===== ========================================== +// // eStopReasonNone 0 +// // eStopReasonTrace 0 +// // eStopReasonBreakpoint N duple: {breakpoint id, location id} +// // eStopReasonWatchpoint N duple: {watchpoint id, location id} +// // eStopReasonSignal 1 unix signal number +// // eStopReasonException N exception data +// // eStopReasonPlanComplete 0 +// //-------------------------------------------------------------------------- +// uint64_t +// GetStopReasonDataAtIndex(uint32_t idx); size_t GetStopDescription (char *dst, size_t dst_len); diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 07f4d3de8e0..5b3b56b798d 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -628,6 +628,12 @@ public: uint32_t GetAddressByteSize(); + void + SetAddressByteSize (uint32_t addr_byte_size) + { + m_addr_byte_size = addr_byte_size; + } + //------------------------------------------------------------------ /// Get the image information address for the current process. /// @@ -1007,12 +1013,12 @@ public: //------------------------------------------------------------------ /// Halts a running process. /// - /// DoHalt should consume any process events that were delivered in the - /// process of implementing the halt. + /// DoHalt should consume any process events that were delivered in + /// the process of implementing the halt. /// /// @param[out] caused_stop - /// If true, then this Halt caused the stop, otherwise, the process was - /// already stopped. + /// If true, then this Halt caused the stop, otherwise, the + /// process was already stopped. /// /// @return /// Returns \b true if the process successfully halts, \b false @@ -1633,8 +1639,17 @@ public: /// @return /// A valid ByteOrder enumeration, or eByteOrderInvalid. //------------------------------------------------------------------ - virtual lldb::ByteOrder - GetByteOrder () const = 0; + lldb::ByteOrder + GetByteOrder () const + { + return m_byte_order; + } + + void + SetByteOrder (lldb::ByteOrder byte_order) + { + m_byte_order = byte_order; + } const ConstString & GetTargetTriple () @@ -1720,10 +1735,12 @@ protected: std::auto_ptr<DynamicCheckerFunctions> m_dynamic_checkers_ap; ///< The functions used by the expression parser to validate data that expressions use. UnixSignals m_unix_signals; /// This is the current signal set for this process. ConstString m_target_triple; + lldb::ByteOrder m_byte_order; /// The byte order of the process. Should be set in DidLaunch/DidAttach. + uint32_t m_addr_byte_size; /// The size in bytes of an address/pointer for the inferior process. Should be set in DidLaunch/DidAttach. lldb::ABISP m_abi_sp; lldb::InputReaderSP m_process_input_reader; lldb_private::Communication m_stdio_communication; - lldb_private::Mutex m_stdio_comm_mutex; + lldb_private::Mutex m_stdio_communication_mutex; std::string m_stdout_data; typedef std::map<lldb::LanguageType, lldb::LanguageRuntimeSP> LanguageRuntimeCollection; diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index ef4258c918c..2c13f0ca302 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -2452,6 +2452,7 @@ isa = PBXProject; buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "lldb" */; compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( en, @@ -2941,7 +2942,7 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES; GCC_WARN_UNUSED_VARIABLE = YES; - ONLY_ACTIVE_ARCH = YES; + ONLY_ACTIVE_ARCH = NO; PREBINDING = NO; VALID_ARCHS = "x86_64 i386"; }; 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); diff --git a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj index db7ad2692bb..3e8a4f84947 100644 --- a/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj +++ b/lldb/tools/debugserver/debugserver.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 264D5D571293835600ED4C01 /* DNBArch.cpp */; }; 2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2660D9CC1192280900958FBD /* StringExtractor.cpp */; }; 26CE05A7115C360D0022F371 /* DNBError.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26C637DE0C71334A0024798E /* DNBError.cpp */; }; 26CE05A8115C36170022F371 /* DNBThreadResumeActions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 260E7331114BFFE600D1DFB3 /* DNBThreadResumeActions.cpp */; }; @@ -48,6 +49,7 @@ 260E7332114BFFE600D1DFB3 /* DNBThreadResumeActions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DNBThreadResumeActions.h; sourceTree = "<group>"; }; 260FC7320E5B290400043FC9 /* debugnub-exports */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "debugnub-exports"; sourceTree = SOURCE_ROOT; }; 26242C390DDBD33C0054A4CC /* debugserver-entitlements.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "debugserver-entitlements.plist"; sourceTree = "<group>"; }; + 264D5D571293835600ED4C01 /* DNBArch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNBArch.cpp; sourceTree = "<group>"; }; 26593A060D4931CC001C9FE3 /* ChangeLog */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; }; 2660D9CC1192280900958FBD /* StringExtractor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringExtractor.cpp; path = ../../source/Utility/StringExtractor.cpp; sourceTree = SOURCE_ROOT; }; 2660D9CD1192280900958FBD /* StringExtractor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringExtractor.h; path = ../../source/Utility/StringExtractor.h; sourceTree = SOURCE_ROOT; }; @@ -190,6 +192,7 @@ 26C637D70C71334A0024798E /* DNB.h */, 26C637D60C71334A0024798E /* DNB.cpp */, 26C637D80C71334A0024798E /* DNBArch.h */, + 264D5D571293835600ED4C01 /* DNBArch.cpp */, 26C637DA0C71334A0024798E /* DNBBreakpoint.h */, 26C637D90C71334A0024798E /* DNBBreakpoint.cpp */, 26C637DC0C71334A0024798E /* DNBDataRef.h */, @@ -441,6 +444,7 @@ 26CE05C5115C36590022F371 /* CFBundle.cpp in Sources */, 26CE05F1115C387C0022F371 /* PseudoTerminal.cpp in Sources */, 2660D9CE1192280900958FBD /* StringExtractor.cpp in Sources */, + 264D5D581293835600ED4C01 /* DNBArch.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index 948125b9714..17a17d32f0d 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -265,10 +265,8 @@ DNBProcessAttachByName (const char *name, struct timespec *timeout, char *err_st DNBLogError ("%6u - %s\n", matching_proc_infos[i].kp_proc.p_pid, matching_proc_infos[i].kp_proc.p_comm); return INVALID_NUB_PROCESS; } - else - { - return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len); - } + + return DNBProcessAttach (matching_proc_infos[0].kp_proc.p_pid, timeout, err_str, err_len); } nub_process_t @@ -294,15 +292,20 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_ while (pid != INVALID_NUB_PROCESS) { // Wait for process to start up and hit entry point - DNBLogThreadedIf (LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged " - "| eEventProcessStoppedStateChanged, true, INFINITE)...", - __FUNCTION__, pid); + DNBLogThreadedIf (LOG_PROCESS, + "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE)...", + __FUNCTION__, + pid); nub_event_t set_events = DNBProcessWaitForEvents (pid, - eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, - true, timeout); - DNBLogThreadedIf (LOG_PROCESS, "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged " - "| eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", - __FUNCTION__, pid, set_events); + eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, + true, + timeout); + + DNBLogThreadedIf (LOG_PROCESS, + "%s DNBProcessWaitForEvent (%4.4x, eEventProcessRunningStateChanged | eEventProcessStoppedStateChanged, true, INFINITE) => 0x%8.8x", + __FUNCTION__, + pid, + set_events); if (set_events == 0) { @@ -320,29 +323,30 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_ switch (pid_state) { - default: - case eStateInvalid: - case eStateUnloaded: - case eStateAttaching: - case eStateLaunching: - case eStateSuspended: - break; // Ignore - - case eStateRunning: - case eStateStepping: - // Still waiting to stop at entry point... - break; - - case eStateStopped: - case eStateCrashed: - return pid; - case eStateDetached: - case eStateExited: - if (err_str && err_len > 0) - snprintf(err_str, err_len, "process exited"); - return INVALID_NUB_PROCESS; - } - } + default: + case eStateInvalid: + case eStateUnloaded: + case eStateAttaching: + case eStateLaunching: + case eStateSuspended: + break; // Ignore + + case eStateRunning: + case eStateStepping: + // Still waiting to stop at entry point... + break; + + case eStateStopped: + case eStateCrashed: + return pid; + + case eStateDetached: + case eStateExited: + if (err_str && err_len > 0) + snprintf(err_str, err_len, "process exited"); + return INVALID_NUB_PROCESS; + } + } DNBProcessResetEvents(pid, set_events); } @@ -352,7 +356,7 @@ DNBProcessAttach (nub_process_t attach_pid, struct timespec *timeout, char *err_ } static size_t -GetAllInfos(std::vector<struct kinfo_proc>& proc_infos) +GetAllInfos (std::vector<struct kinfo_proc>& proc_infos) { size_t size; int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; @@ -1722,7 +1726,7 @@ DNBProcessGetSharedLibraryInfo (nub_process_t pid, nub_bool_t only_changed, stru const DNBRegisterSetInfo * DNBGetRegisterSetInfo (nub_size_t *num_reg_sets) { - return DNBArch::GetRegisterSetInfo (num_reg_sets); + return DNBArchProtocol::GetRegisterSetInfo (num_reg_sets); } @@ -1998,3 +2002,20 @@ DNBResolveExecutablePath (const char *path, char *resolved_path, size_t resolved return false; } + +void +DNBInitialize() +{ + DNBLogThreadedIf (LOG_PROCESS, "DNBInitialize ()"); +#if defined (__i386__) || defined (__x86_64__) + DNBArchImplI386::Initialize(); + DNBArchImplX86_64::Initialize(); +#elif defined (__arm__) + DNBArchMachARM::Initialize(); +#endif +} + +void +DNBTerminate() +{ +} diff --git a/lldb/tools/debugserver/source/DNB.h b/lldb/tools/debugserver/source/DNB.h index 4dadff2473b..921bbbfc23d 100644 --- a/lldb/tools/debugserver/source/DNB.h +++ b/lldb/tools/debugserver/source/DNB.h @@ -25,6 +25,9 @@ extern "C" { typedef bool (*DNBShouldCancelCallback) (void *); +void DNBInitialize (); +void DNBTerminate (); + //---------------------------------------------------------------------- // Process control //---------------------------------------------------------------------- diff --git a/lldb/tools/debugserver/source/DNBArch.h b/lldb/tools/debugserver/source/DNBArch.h index 3eb2362aa0f..a0f18cd39c8 100644 --- a/lldb/tools/debugserver/source/DNBArch.h +++ b/lldb/tools/debugserver/source/DNBArch.h @@ -22,13 +22,39 @@ struct DNBRegisterValue; struct DNBRegisterSetInfo; +class DNBArchProtocol; +class MachThread; + +typedef DNBArchProtocol * (* DNBArchCallbackCreate)(MachThread *thread); +typedef const DNBRegisterSetInfo * (* DNBArchCallbackGetRegisterSetInfo)(nub_size_t *num_reg_sets); +typedef const uint8_t * const (* DNBArchCallbackGetBreakpointOpcode)(nub_size_t byte_size); + +typedef struct DNBArchPluginInfoTag +{ + uint32_t cpu_type; + DNBArchCallbackCreate Create; + DNBArchCallbackGetRegisterSetInfo GetRegisterSetInfo; + DNBArchCallbackGetBreakpointOpcode GetBreakpointOpcode; +} DNBArchPluginInfo; class DNBArchProtocol { public: - static const DNBRegisterSetInfo * + static DNBArchProtocol * + Create (MachThread *thread); + + static const DNBRegisterSetInfo * GetRegisterSetInfo (nub_size_t *num_reg_sets); + static const uint8_t * const + GetBreakpointOpcode (nub_size_t byte_size); + + static void + RegisterArchPlugin (const DNBArchPluginInfo &arch_info); + + static void + SetDefaultArchitecture (uint32_t cpu_type); + virtual bool GetRegisterValue (int set, int reg, DNBRegisterValue *value) = 0; virtual bool SetRegisterValue (int set, int reg, const DNBRegisterValue *value) = 0; virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len) = 0; @@ -39,6 +65,7 @@ public: virtual bool RegisterSetStateIsValid (int set) const = 0; virtual uint64_t GetPC (uint64_t failValue) = 0; // Get program counter + virtual kern_return_t SetPC (uint64_t value) = 0; virtual uint64_t GetSP (uint64_t failValue) = 0; // Get stack pointer virtual void ThreadWillResume () = 0; virtual bool ThreadDidStop () = 0; diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp index c5c1e7f6f0c..3ca7fe8abeb 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.cpp @@ -115,6 +115,7 @@ MachProcess::MachProcess() : m_image_infos_baton(NULL) { DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); + bzero(&m_arch_plugin_info, sizeof(m_arch_plugin_info)); } MachProcess::~MachProcess() @@ -208,7 +209,15 @@ MachProcess::GetThreadInfo(nub_thread_t tid) const const DNBRegisterSetInfo * MachProcess::GetRegisterSetInfo(nub_thread_t tid, nub_size_t *num_reg_sets ) const { - return DNBArch::GetRegisterSetInfo (num_reg_sets); + MachThread *thread = m_thread_list.GetThreadByID (tid); + if (thread) + { + DNBArchProtocol *arch = thread->GetArchProtocol(); + if (arch) + return arch->GetRegisterSetInfo (num_reg_sets); + } + *num_reg_sets = 0; + return NULL; } bool @@ -766,7 +775,7 @@ MachProcess::DisableBreakpoint(nub_break_t breakID, bool remove) const nub_size_t break_op_size = bp->ByteSize(); assert (break_op_size > 0); - const uint8_t * const break_op = DNBArch::SoftwareBreakpointOpcode(bp->ByteSize()); + const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (bp->ByteSize()); if (break_op_size > 0) { // Clear a software breakoint instruction @@ -954,7 +963,7 @@ MachProcess::EnableBreakpoint(nub_break_t breakID) const nub_size_t break_op_size = bp->ByteSize(); assert (break_op_size != 0); - const uint8_t * const break_op = DNBArch::SoftwareBreakpointOpcode(break_op_size); + const uint8_t * const break_op = DNBArchProtocol::GetBreakpointOpcode (break_op_size); if (break_op_size > 0) { // Save the original opcode by reading it @@ -1507,7 +1516,14 @@ MachProcess::LaunchForDebug break; case eLaunchFlavorPosixSpawn: - m_pid = MachProcess::PosixSpawnChildForPTraceDebugging (path, argv, envp, stdio_path, this, disable_aslr, launch_err); + m_pid = MachProcess::PosixSpawnChildForPTraceDebugging (path, + m_arch_plugin_info.cpu_type, + argv, + envp, + stdio_path, + this, + disable_aslr, + launch_err); break; #if defined (__arm__) @@ -1590,6 +1606,7 @@ pid_t MachProcess::PosixSpawnChildForPTraceDebugging ( const char *path, + cpu_type_t cpu_type, char const *argv[], char const *envp[], const char *stdio_path, @@ -1628,7 +1645,6 @@ MachProcess::PosixSpawnChildForPTraceDebugging // 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_type = DNBArch::GetCPUType(); size_t ocount = 0; err.SetError( ::posix_spawnattr_setbinpref_np (&attr, 1, &cpu_type, &ocount), DNBError::POSIX); if (err.Fail() || DNBLogCheckLogBit(LOG_PROCESS)) diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index fa0979d7e20..cff08bb4d68 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -48,7 +48,7 @@ public: pid_t AttachForDebug (pid_t pid, char *err_str, size_t err_len); pid_t LaunchForDebug (const char *path, char const *argv[], char const *envp[], const char *stdio_path, nub_launch_flavor_t launch_flavor, int disable_aslr, DNBError &err); static pid_t ForkChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], MachProcess* process, DNBError &err); - static pid_t PosixSpawnChildForPTraceDebugging (const char *path, char const *argv[], char const *envp[], const char *stdio_path, MachProcess* process, int disable_aslr, DNBError& err); + static pid_t PosixSpawnChildForPTraceDebugging (const char *path, cpu_type_t cpu_type, char const *argv[], char const *envp[], const char *stdio_path, MachProcess* process, int disable_aslr, DNBError& err); nub_addr_t GetDYLDAllImageInfosAddress (); static const void * PrepareForAttach (const char *path, nub_launch_flavor_t launch_flavor, bool waitfor, DNBError &err_str); static void CleanupAfterAttach (const void *attach_token, bool success, DNBError &err_str); @@ -254,6 +254,7 @@ private: DNBCallbackCopyExecutableImageInfos m_image_infos_callback; void * m_image_infos_baton; + DNBArchPluginInfo m_arch_plugin_info; }; diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp index ca2bf9b3b3a..ddd7746dad4 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.cpp @@ -31,14 +31,9 @@ MachThread::MachThread (MachProcess *process, thread_t thread) : m_state_mutex (PTHREAD_MUTEX_RECURSIVE), m_breakID (INVALID_NUB_BREAK_ID), m_suspendCount (0), - m_arch (this), - m_regSets () + m_arch_ap (DNBArchProtocol::Create (this)), + m_reg_sets (m_arch_ap->GetRegisterSetInfo (&n_num_reg_sets)) { - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *regSetInfo = m_arch.GetRegisterSetInfo(&num_reg_sets); - if (num_reg_sets > 0) - m_regSets.assign(regSetInfo, regSetInfo + num_reg_sets); - // Get the thread state so we know if a thread is in a state where we can't // muck with it and also so we get the suspend count correct in case it was // already suspended @@ -251,34 +246,34 @@ MachThread::ThreadIDIsValid(thread_t thread) bool MachThread::GetRegisterState(int flavor, bool force) { - return m_arch.GetRegisterState(flavor, force) == KERN_SUCCESS; + return m_arch_ap->GetRegisterState(flavor, force) == KERN_SUCCESS; } bool MachThread::SetRegisterState(int flavor) { - return m_arch.SetRegisterState(flavor) == KERN_SUCCESS; + return m_arch_ap->SetRegisterState(flavor) == KERN_SUCCESS; } uint64_t MachThread::GetPC(uint64_t failValue) { // Get program counter - return m_arch.GetPC(failValue); + return m_arch_ap->GetPC(failValue); } bool MachThread::SetPC(uint64_t value) { // Set program counter - return m_arch.SetPC(value); + return m_arch_ap->SetPC(value); } uint64_t MachThread::GetSP(uint64_t failValue) { // Get stack pointer - return m_arch.GetSP(failValue); + return m_arch_ap->GetSP(failValue); } nub_process_t @@ -342,7 +337,7 @@ MachThread::ThreadWillResume(const DNBThreadResumeAction *thread_action) Resume(); break; } - m_arch.ThreadWillResume(); + m_arch_ap->ThreadWillResume(); m_stop_exception.Clear(); } @@ -372,7 +367,7 @@ MachThread::ShouldStop(bool &step_more) } else { - if (m_arch.StepNotComplete()) + if (m_arch_ap->StepNotComplete()) { step_more = true; return false; @@ -426,7 +421,7 @@ MachThread::ThreadDidStop() // When this method gets called, the process state is still in the // state it was in while running so we can act accordingly. - m_arch.ThreadDidStop(); + m_arch_ap->ThreadDidStop(); // We may have suspended this thread so the primary thread could step @@ -499,7 +494,7 @@ MachThread::NotifyException(MachException::Data& exc) { m_stop_exception = exc; } - bool handled = m_arch.NotifyException(exc); + bool handled = m_arch_ap->NotifyException(exc); if (!handled) { handled = true; @@ -551,25 +546,25 @@ MachThread::SetState(nub_state_t state) uint32_t MachThread::GetNumRegistersInSet(int regSet) const { - if (regSet < m_regSets.size()) - return m_regSets[regSet].num_registers; + if (regSet < n_num_reg_sets) + return m_reg_sets[regSet].num_registers; return 0; } const char * MachThread::GetRegisterSetName(int regSet) const { - if (regSet < m_regSets.size()) - return m_regSets[regSet].name; + if (regSet < n_num_reg_sets) + return m_reg_sets[regSet].name; return NULL; } const DNBRegisterInfo * MachThread::GetRegisterInfo(int regSet, int regIndex) const { - if (regSet < m_regSets.size()) - if (regIndex < m_regSets[regSet].num_registers) - return &m_regSets[regSet].registers[regIndex]; + if (regSet < n_num_reg_sets) + if (regIndex < m_reg_sets[regSet].num_registers) + return &m_reg_sets[regSet].registers[regIndex]; return NULL; } void @@ -577,19 +572,19 @@ MachThread::DumpRegisterState(int regSet) { if (regSet == REGISTER_SET_ALL) { - for (regSet = 1; regSet < m_regSets.size(); regSet++) + for (regSet = 1; regSet < n_num_reg_sets; regSet++) DumpRegisterState(regSet); } else { - if (m_arch.RegisterSetStateIsValid(regSet)) + if (m_arch_ap->RegisterSetStateIsValid(regSet)) { const size_t numRegisters = GetNumRegistersInSet(regSet); size_t regIndex = 0; DNBRegisterValueClass reg; for (regIndex = 0; regIndex < numRegisters; ++regIndex) { - if (m_arch.GetRegisterValue(regSet, regIndex, ®)) + if (m_arch_ap->GetRegisterValue(regSet, regIndex, ®)) { reg.Dump(NULL, NULL); } @@ -605,39 +600,39 @@ MachThread::DumpRegisterState(int regSet) const DNBRegisterSetInfo * MachThread::GetRegisterSetInfo(nub_size_t *num_reg_sets ) const { - *num_reg_sets = m_regSets.size(); - return &m_regSets[0]; + *num_reg_sets = n_num_reg_sets; + return &m_reg_sets[0]; } bool MachThread::GetRegisterValue ( uint32_t set, uint32_t reg, DNBRegisterValue *value ) { - return m_arch.GetRegisterValue(set, reg, value); + return m_arch_ap->GetRegisterValue(set, reg, value); } bool MachThread::SetRegisterValue ( uint32_t set, uint32_t reg, const DNBRegisterValue *value ) { - return m_arch.SetRegisterValue(set, reg, value); + return m_arch_ap->SetRegisterValue(set, reg, value); } nub_size_t MachThread::GetRegisterContext (void *buf, nub_size_t buf_len) { - return m_arch.GetRegisterContext(buf, buf_len); + return m_arch_ap->GetRegisterContext(buf, buf_len); } nub_size_t MachThread::SetRegisterContext (const void *buf, nub_size_t buf_len) { - return m_arch.SetRegisterContext(buf, buf_len); + return m_arch_ap->SetRegisterContext(buf, buf_len); } uint32_t MachThread::EnableHardwareBreakpoint (const DNBBreakpoint *bp) { if (bp != NULL && bp->IsBreakpoint()) - return m_arch.EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); + return m_arch_ap->EnableHardwareBreakpoint(bp->Address(), bp->ByteSize()); return INVALID_NUB_HW_INDEX; } @@ -645,7 +640,7 @@ uint32_t MachThread::EnableHardwareWatchpoint (const DNBBreakpoint *wp) { if (wp != NULL && wp->IsWatchpoint()) - return m_arch.EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite()); + return m_arch_ap->EnableHardwareWatchpoint(wp->Address(), wp->ByteSize(), wp->WatchpointRead(), wp->WatchpointWrite()); return INVALID_NUB_HW_INDEX; } @@ -653,7 +648,7 @@ bool MachThread::DisableHardwareBreakpoint (const DNBBreakpoint *bp) { if (bp != NULL && bp->IsHardware()) - return m_arch.DisableHardwareBreakpoint(bp->GetHardwareIndex()); + return m_arch_ap->DisableHardwareBreakpoint(bp->GetHardwareIndex()); return false; } @@ -661,7 +656,7 @@ bool MachThread::DisableHardwareWatchpoint (const DNBBreakpoint *wp) { if (wp != NULL && wp->IsHardware()) - return m_arch.DisableHardwareWatchpoint(wp->GetHardwareIndex()); + return m_arch_ap->DisableHardwareWatchpoint(wp->GetHardwareIndex()); return false; } diff --git a/lldb/tools/debugserver/source/MacOSX/MachThread.h b/lldb/tools/debugserver/source/MacOSX/MachThread.h index f7f2ce8b1ab..0b2a8bf1ff9 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThread.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThread.h @@ -95,6 +95,13 @@ public: GetBasicInfo (); const char * GetBasicInfoAsString () const; const char * GetName (); + + DNBArchProtocol* + GetArchProtocol() + { + return m_arch_ap.get(); + } + protected: static bool GetBasicInfo(thread_t threadID, struct thread_basic_info *basic_info); @@ -113,8 +120,9 @@ protected: struct thread_basic_info m_basicInfo; // Basic information for a thread used to see if a thread is valid uint32_t m_suspendCount; // The current suspend count MachException::Data m_stop_exception; // The best exception that describes why this thread is stopped - DNBArch m_arch; // Arch specific information for register state and more - std::vector<DNBRegisterSetInfo> m_regSets; // Register set information for this thread + std::auto_ptr<DNBArchProtocol> m_arch_ap; // Arch specific information for register state and more + const DNBRegisterSetInfo *const m_reg_sets; // Register set information for this thread + nub_size_t n_num_reg_sets; #ifdef THREAD_IDENTIFIER_INFO_COUNT thread_identifier_info_data_t m_ident_info; struct proc_threadinfo m_proc_threadinfo; diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp index db2a00a304a..7a5e9bb8588 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp @@ -12,6 +12,9 @@ //===----------------------------------------------------------------------===// #include "MachThreadList.h" + +#include <sys/sysctl.h> + #include "DNBLog.h" #include "DNBThreadResumeActions.h" #include "MachProcess.h" @@ -104,6 +107,15 @@ MachThreadList::GetThreadInfo(nub_thread_t tid) const return NULL; } +MachThread * +MachThreadList::GetThreadByID (nub_thread_t tid) const +{ + uint32_t idx = GetThreadIndexByID(tid); + if (idx < m_threads.size()) + return m_threads[idx].get(); + return NULL; +} + bool MachThreadList::GetRegisterValue ( nub_thread_t tid, uint32_t reg_set_idx, uint32_t reg_idx, DNBRegisterValue *reg_value ) const { @@ -202,9 +214,28 @@ uint32_t MachThreadList::UpdateThreadList(MachProcess *process, bool update) { // locker will keep a mutex locked until it goes out of scope - DNBLogThreadedIf(LOG_THREAD | LOG_VERBOSE, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u )", process->ProcessID(), update); + DNBLogThreadedIf (LOG_THREAD, "MachThreadList::UpdateThreadList (pid = %4.4x, update = %u) process stop count = %u", process->ProcessID(), update, process->StopCount()); PTHREAD_MUTEX_LOCKER (locker, m_threads_mutex); +#if defined (__i386__) || defined (__x86_64__) + if (process->StopCount() == 0) + { + int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process->ProcessID() }; + struct kinfo_proc processInfo; + size_t bufsize = sizeof(processInfo); + bool is_64_bit = false; + if (sysctl(mib, (unsigned)(sizeof(mib)/sizeof(int)), &processInfo, &bufsize, NULL, 0) == 0 && bufsize > 0) + { + if (processInfo.kp_proc.p_flag & P_LP64) + is_64_bit = true; + } + if (is_64_bit) + DNBArchProtocol::SetDefaultArchitecture(CPU_TYPE_X86_64); + else + DNBArchProtocol::SetDefaultArchitecture(CPU_TYPE_I386); + } +#endif + if (m_threads.empty() || update) { thread_array_t thread_list = NULL; diff --git a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h index 5c813886569..1a17618a7e3 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachThreadList.h +++ b/lldb/tools/debugserver/source/MacOSX/MachThreadList.h @@ -55,6 +55,8 @@ public: bool DisableHardwareWatchpoint (const DNBBreakpoint *wp) const; uint32_t GetThreadIndexForThreadStoppedWithSignal (const int signo) const; + MachThread * GetThreadByID (nub_thread_t tid) const; + protected: typedef std::vector<MachThreadSP> collection; typedef collection::iterator iterator; diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h index f012caa1828..9aff44e5dbc 100644 --- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h @@ -235,6 +235,5 @@ protected: }; -typedef DNBArchMachARM DNBArch; #endif // #if defined (__arm__) #endif // #ifndef __DebugNubArchMachARM_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 0a0601f6378..1222b809904 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__i386__) +#if defined (__i386__) || defined (__x86_64__) #include <sys/cdefs.h> @@ -20,8 +20,6 @@ #include "MachThread.h" #include "MachProcess.h" -static const uint8_t g_breakpoint_opcode[] = { 0xCC }; - enum { gpr_eax = 0, @@ -187,21 +185,6 @@ enum gdb_mm7 = 48 }; - -const uint8_t * const -DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size) -{ - if (byte_size == 1) - return g_breakpoint_opcode; - return NULL; -} - -uint32_t -DNBArchImplI386::GetCPUType() -{ - return CPU_TYPE_I386; -} - uint64_t DNBArchImplI386::GetPC(uint64_t failValue) { @@ -589,6 +572,21 @@ DNBArchImplI386::g_reg_sets[] = const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); +DNBArchProtocol * +DNBArchImplI386::Create (MachThread *thread) +{ + return new DNBArchImplI386 (thread); +} + +const uint8_t * const +DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size) +{ + static const uint8_t g_breakpoint_opcode[] = { 0xCC }; + if (byte_size == 1) + return g_breakpoint_opcode; + return NULL; +} + const DNBRegisterSetInfo * DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) { @@ -596,6 +594,22 @@ DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) return g_reg_sets; } + +void +DNBArchImplI386::Initialize() +{ + DNBArchPluginInfo arch_plugin_info = + { + CPU_TYPE_I386, + DNBArchImplI386::Create, + DNBArchImplI386::GetRegisterSetInfo, + DNBArchImplI386::SoftwareBreakpointOpcode + }; + + // Register this arch plug-in with the main protocol class + DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); +} + bool DNBArchImplI386::GetRegisterValue(int set, int reg, DNBRegisterValue *value) { diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 2b47e09cdf3..e0fcc199b5e 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -14,7 +14,7 @@ #ifndef __DNBArchImplI386_h__ #define __DNBArchImplI386_h__ -#if defined (__i386__) +#if defined (__i386__) || defined (__x86_64__) #include "DNBArch.h" #include <mach/mach_types.h> @@ -34,9 +34,8 @@ public: virtual ~DNBArchImplI386() { } - - static const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets); + + static void Initialize(); virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value); virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value); @@ -53,9 +52,6 @@ public: virtual bool ThreadDidStop(); virtual bool NotifyException(MachException::Data& exc); - static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size); - static uint32_t GetCPUType(); - protected: kern_return_t EnableHardwareSingleStep (bool enable); @@ -186,11 +182,18 @@ protected: kern_return_t SetFPUState (); kern_return_t SetEXCState (); + static DNBArchProtocol * + Create (MachThread *thread); + + static const uint8_t * const + SoftwareBreakpointOpcode (nub_size_t byte_size); + + static const DNBRegisterSetInfo * + GetRegisterSetInfo(nub_size_t *num_reg_sets); + MachThread *m_thread; State m_state; }; -typedef DNBArchImplI386 DNBArch; - -#endif // #if defined (__i386__) +#endif // #if defined (__i386__) || defined (__x86_64__) #endif // #ifndef __DNBArchImplI386_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h index 6263407460a..a787d14d8d4 100644 --- a/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h +++ b/lldb/tools/debugserver/source/MacOSX/ppc/DNBArchImpl.h @@ -175,6 +175,5 @@ protected: State m_state; }; -typedef DNBArchMachPPC DNBArch; #endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) #endif // #ifndef __DebugNubArchMachPPC_h__ diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 1f18156650c..fde3be6ab5d 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#if defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #include <sys/cdefs.h> @@ -20,22 +20,6 @@ #include "MachThread.h" #include "MachProcess.h" -static const uint8_t g_breakpoint_opcode[] = { 0xCC }; - -const uint8_t * const -DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size) -{ - if (byte_size == 1) - return g_breakpoint_opcode; - return NULL; -} - -uint32_t -DNBArchImplX86_64::GetCPUType() -{ - return CPU_TYPE_X86_64; -} - uint64_t DNBArchImplX86_64::GetPC(uint64_t failValue) { @@ -718,13 +702,43 @@ DNBArchImplX86_64::g_reg_sets[] = const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo); +DNBArchProtocol * +DNBArchImplX86_64::Create (MachThread *thread) +{ + return new DNBArchImplX86_64 (thread); +} + +const uint8_t * const +DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size) +{ + static const uint8_t g_breakpoint_opcode[] = { 0xCC }; + if (byte_size == 1) + return g_breakpoint_opcode; + return NULL; +} + const DNBRegisterSetInfo * -DNBArchImplX86_64::GetRegisterSetInfo (nub_size_t *num_reg_sets) +DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets) { *num_reg_sets = k_num_register_sets; return g_reg_sets; } +void +DNBArchImplX86_64::Initialize() +{ + DNBArchPluginInfo arch_plugin_info = + { + CPU_TYPE_X86_64, + DNBArchImplX86_64::Create, + DNBArchImplX86_64::GetRegisterSetInfo, + DNBArchImplX86_64::SoftwareBreakpointOpcode + }; + + // Register this arch plug-in with the main protocol class + DNBArchProtocol::RegisterArchPlugin (arch_plugin_info); +} + bool DNBArchImplX86_64::GetRegisterValue(int set, int reg, DNBRegisterValue *value) { @@ -1032,4 +1046,4 @@ DNBArchImplX86_64::RegisterSetStateIsValid (int set) const -#endif // #if defined (__i386__) +#endif // #if defined (__i386__) || defined (__x86_64__) diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index def263fec5e..584943c85c7 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -14,8 +14,7 @@ #ifndef __DNBArchImplX86_64_h__ #define __DNBArchImplX86_64_h__ -//#if defined (__i386__) -#if defined(__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #include "DNBArch.h" #include <mach/mach_types.h> #include <mach/thread_status.h> @@ -35,9 +34,7 @@ public: { } - static const DNBRegisterSetInfo * - GetRegisterSetInfo(nub_size_t *num_reg_sets); - + static void Initialize(); virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value); virtual bool SetRegisterValue(int set, int reg, const DNBRegisterValue *value); virtual nub_size_t GetRegisterContext (void *buf, nub_size_t buf_len); @@ -54,9 +51,6 @@ public: virtual bool ThreadDidStop(); virtual bool NotifyException(MachException::Data& exc); - static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size); - static uint32_t GetCPUType(); - protected: kern_return_t EnableHardwareSingleStep (bool enable); @@ -189,11 +183,18 @@ protected: kern_return_t SetFPUState (); kern_return_t SetEXCState (); + static DNBArchProtocol * + Create (MachThread *thread); + + static const uint8_t * const + SoftwareBreakpointOpcode (nub_size_t byte_size); + + static const DNBRegisterSetInfo * + GetRegisterSetInfo(nub_size_t *num_reg_sets); + MachThread *m_thread; State m_state; }; -typedef DNBArchImplX86_64 DNBArch; - -#endif // #if defined (__x86_64__) +#endif // #if defined (__i386__) || defined (__x86_64__) #endif // #ifndef __DNBArchImplX86_64_h__ diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 7b2ba3335be..bb8c59ea0eb 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -60,11 +60,10 @@ extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); -RNBRemote::RNBRemote (bool use_native_regs) : - m_ctx(), - m_comm(), - m_extended_mode(false), - m_noack_mode(false), +RNBRemote::RNBRemote (bool use_native_regs, const char *arch) : + m_ctx (), + m_comm (), + m_arch (), m_continue_thread(-1), m_thread(-1), m_mutex(), @@ -75,10 +74,14 @@ RNBRemote::RNBRemote (bool use_native_regs) : m_rx_pthread(0), m_breakpoints(), m_max_payload_size(DEFAULT_GDB_REMOTE_PROTOCOL_BUFSIZE - 4), + m_extended_mode(false), + m_noack_mode(false), m_use_native_regs (use_native_regs) { DNBLogThreadedIf (LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); CreatePacketTable (); + if (arch && arch[0]) + m_arch.assign (arch); } @@ -803,12 +806,10 @@ RegisterEntryNotAvailable (register_map_entry_t *reg_entry) reg_entry->nub_info.reg_gdb = INVALID_NUB_REGNUM; } -#if defined (__arm__) //---------------------------------------------------------------------- // ARM regiseter sets as gdb knows them //---------------------------------------------------------------------- - register_map_entry_t g_gdb_register_map_arm[] = { @@ -873,32 +874,6 @@ g_gdb_register_map_arm[] = { 58, 4, "fpscr", {0}, NULL, 0} }; -void -RNBRemote::InitializeRegisters (int use_native_registers) -{ - if (use_native_registers) - { - RNBRemote::InitializeNativeRegisters(); - } - else - { - const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t); - for (uint32_t i=0; i<num_regs; ++i) - { - if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info)) - { - RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]); - assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE); - } - } - g_reg_entries = g_gdb_register_map_arm; - g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t); - } -} - - -#elif defined (__i386__) - register_map_entry_t g_gdb_register_map_i386[] = { @@ -945,32 +920,6 @@ g_gdb_register_map_i386[] = { 40, 4, "mxcsr" , {0}, NULL, 0 }, }; -void -RNBRemote::InitializeRegisters (int use_native_registers) -{ - if (use_native_registers) - { - RNBRemote::InitializeNativeRegisters(); - } - else - { - const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t); - for (uint32_t i=0; i<num_regs; ++i) - { - if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info)) - { - RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]); - assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE); - } - } - g_reg_entries = g_gdb_register_map_i386; - g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t); - } -} - - -#elif defined (__x86_64__) - register_map_entry_t g_gdb_register_map_x86_64[] = { @@ -1033,86 +982,113 @@ g_gdb_register_map_x86_64[] = { 56, 4, "mxcsr" , {0}, NULL, 0 } }; -void -RNBRemote::InitializeRegisters (int use_native_registers) -{ - if (use_native_registers) - { - RNBRemote::InitializeNativeRegisters(); - } - else - { - const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t); - for (uint32_t i=0; i<num_regs; ++i) - { - if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info)) - { - RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]); - assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE); - } - } - g_reg_entries = g_gdb_register_map_x86_64; - g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t); - } -} - - -#else void -RNBRemote::InitializeRegisters (int use_native_registers) +RNBRemote::Initialize() { - // No choice, we don't have a GDB register definition for this arch. - RNBRemote::InitializeNativeRegisters(); + DNBInitialize(); } -#endif - -void -RNBRemote::InitializeNativeRegisters() +bool +RNBRemote::InitializeRegisters () { - if (g_dynamic_register_map.empty()) - { - nub_size_t num_reg_sets = 0; - const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets); - - assert (num_reg_sets > 0 && reg_sets != NULL); + pid_t pid = m_ctx.ProcessID(); + if (pid == INVALID_NUB_PROCESS) + return false; - uint32_t regnum = 0; - for (nub_size_t set = 0; set < num_reg_sets; ++set) + if (m_use_native_regs) + { + DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting native registers from DNB interface (%s)", __FUNCTION__, m_arch.c_str()); + // Discover the registers by querying the DNB interface and letting it + // state the registers that it would like to export. This allows the + // registers to be discovered using multiple qRegisterInfo calls to get + // all register information after the architecture for the process is + // determined. + if (g_dynamic_register_map.empty()) { - if (reg_sets[set].registers == NULL) - continue; + nub_size_t num_reg_sets = 0; + const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo (&num_reg_sets); - for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg) + assert (num_reg_sets > 0 && reg_sets != NULL); + + uint32_t regnum = 0; + for (nub_size_t set = 0; set < num_reg_sets; ++set) { - register_map_entry_t reg_entry = { - regnum++, // register number starts at zero and goes up with no gaps - reg_sets[set].registers[reg].size, // register size in bytes - reg_sets[set].registers[reg].name, // register name - reg_sets[set].registers[reg], // DNBRegisterInfo - NULL, // Value to print if case we fail to reg this register (if this is NULL, we will return an error) - reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM}; - - g_dynamic_register_map.push_back (reg_entry); + if (reg_sets[set].registers == NULL) + continue; + + for (uint32_t reg=0; reg < reg_sets[set].num_registers; ++reg) + { + register_map_entry_t reg_entry = { + regnum++, // register number starts at zero and goes up with no gaps + reg_sets[set].registers[reg].size, // register size in bytes + reg_sets[set].registers[reg].name, // register name + reg_sets[set].registers[reg], // DNBRegisterInfo + NULL, // Value to print if case we fail to reg this register (if this is NULL, we will return an error) + reg_sets[set].registers[reg].reg_generic != INVALID_NUB_REGNUM}; + + g_dynamic_register_map.push_back (reg_entry); + } } + g_reg_entries = g_dynamic_register_map.data(); + g_num_reg_entries = g_dynamic_register_map.size(); } - g_reg_entries = g_dynamic_register_map.data(); - g_num_reg_entries = g_dynamic_register_map.size(); + return true; } -} - - -const register_map_entry_t * -register_mapping_by_regname (const char *n) -{ - for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) + else { - if (strcmp (g_reg_entries[reg].gdb_name, n) == 0) - return &g_reg_entries[reg]; + DNBLogThreadedIf (LOG_RNB_PROC, "RNBRemote::%s() getting gdb registers (%s)", __FUNCTION__, m_arch.c_str()); +#if defined (__i386__) || defined (__x86_64__) + if (m_arch.compare("x86_64") == 0) + { + const size_t num_regs = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t); + for (uint32_t i=0; i<num_regs; ++i) + { + if (!DNBGetRegisterInfoByName (g_gdb_register_map_x86_64[i].gdb_name, &g_gdb_register_map_x86_64[i].nub_info)) + { + RegisterEntryNotAvailable (&g_gdb_register_map_x86_64[i]); + assert (g_gdb_register_map_x86_64[i].gdb_size < MAX_REGISTER_BYTE_SIZE); + } + } + g_reg_entries = g_gdb_register_map_x86_64; + g_num_reg_entries = sizeof (g_gdb_register_map_x86_64) / sizeof (register_map_entry_t); + return true; + } + else if (m_arch.compare("i386") == 0) + { + const size_t num_regs = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t); + for (uint32_t i=0; i<num_regs; ++i) + { + if (!DNBGetRegisterInfoByName (g_gdb_register_map_i386[i].gdb_name, &g_gdb_register_map_i386[i].nub_info)) + { + RegisterEntryNotAvailable (&g_gdb_register_map_i386[i]); + assert (g_gdb_register_map_i386[i].gdb_size <= MAX_REGISTER_BYTE_SIZE); + } + } + g_reg_entries = g_gdb_register_map_i386; + g_num_reg_entries = sizeof (g_gdb_register_map_i386) / sizeof (register_map_entry_t); + return true; + } +#elif defined (__arm__) + if (m_arch.find ("arm") == 0) + { + const size_t num_regs = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t); + for (uint32_t i=0; i<num_regs; ++i) + { + if (!DNBGetRegisterInfoByName (g_gdb_register_map_arm[i].gdb_name, &g_gdb_register_map_arm[i].nub_info)) + { + RegisterEntryNotAvailable (&g_gdb_register_map_arm[i]); + assert (g_gdb_register_map_arm[i].gdb_size <= MAX_REGISTER_BYTE_SIZE); + } + } + g_reg_entries = g_gdb_register_map_arm; + g_num_reg_entries = sizeof (g_gdb_register_map_arm) / sizeof (register_map_entry_t); + return true; + } +#endif } - return NULL; + return false; } /* The inferior has stopped executing; send a packet @@ -1121,7 +1097,7 @@ register_mapping_by_regname (const char *n) void RNBRemote::NotifyThatProcessStopped (void) { - RNBRemote::HandlePacket_last_signal (""); + RNBRemote::HandlePacket_last_signal (NULL); return; } @@ -1396,6 +1372,9 @@ RNBRemote::HandlePacket_qC (const char *p) rnb_err_t RNBRemote::HandlePacket_qRegisterInfo (const char *p) { + if (g_num_reg_entries == 0) + InitializeRegisters (); + p += strlen ("qRegisterInfo"); nub_size_t num_reg_sets = 0; @@ -1951,6 +1930,9 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) if (thread_ident_info.dispatch_qaddr != 0) ostrm << std::hex << "qaddr:" << thread_ident_info.dispatch_qaddr << ';'; } + if (g_num_reg_entries == 0) + InitializeRegisters (); + DNBRegisterValue reg_value; for (uint32_t reg = 0; reg < g_num_reg_entries; reg++) { @@ -2002,45 +1984,45 @@ RNBRemote::HandlePacket_last_signal (const char *unused) case eStateSuspended: case eStateStopped: case eStateCrashed: - { - nub_thread_t tid = DNBProcessGetCurrentThread (pid); - // Make sure we set the current thread so g and p packets return - // the data the gdb will expect. - SetCurrentThread (tid); + { + nub_thread_t tid = DNBProcessGetCurrentThread (pid); + // Make sure we set the current thread so g and p packets return + // the data the gdb will expect. + SetCurrentThread (tid); - SendStopReplyPacketForThread (tid); - } + SendStopReplyPacketForThread (tid); + } break; case eStateInvalid: case eStateUnloaded: case eStateExited: - { - char pid_exited_packet[16] = ""; - int pid_status = 0; - // Process exited with exit status - if (!DNBProcessGetExitStatus(pid, &pid_status)) - pid_status = 0; - - if (pid_status) { - if (WIFEXITED (pid_status)) - snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status)); - else if (WIFSIGNALED (pid_status)) - snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status)); - else if (WIFSTOPPED (pid_status)) - snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status)); - } + char pid_exited_packet[16] = ""; + int pid_status = 0; + // Process exited with exit status + if (!DNBProcessGetExitStatus(pid, &pid_status)) + pid_status = 0; - // If we have an empty exit packet, lets fill one in to be safe. - if (!pid_exited_packet[0]) - { - strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1); - pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0'; - } + if (pid_status) + { + if (WIFEXITED (pid_status)) + snprintf (pid_exited_packet, sizeof(pid_exited_packet), "W%02x", WEXITSTATUS (pid_status)); + else if (WIFSIGNALED (pid_status)) + snprintf (pid_exited_packet, sizeof(pid_exited_packet), "X%02x", WEXITSTATUS (pid_status)); + else if (WIFSTOPPED (pid_status)) + snprintf (pid_exited_packet, sizeof(pid_exited_packet), "S%02x", WSTOPSIG (pid_status)); + } - return SendPacket (pid_exited_packet); - } + // If we have an empty exit packet, lets fill one in to be safe. + if (!pid_exited_packet[0]) + { + strncpy (pid_exited_packet, "W00", sizeof(pid_exited_packet)-1); + pid_exited_packet[sizeof(pid_exited_packet)-1] = '\0'; + } + + return SendPacket (pid_exited_packet); + } break; } return rnb_success; @@ -2244,6 +2226,10 @@ RNBRemote::HandlePacket_g (const char *p) { return SendPacket ("E11"); } + + if (g_num_reg_entries == 0) + InitializeRegisters (); + nub_process_t pid = m_ctx.ProcessID (); nub_thread_t tid = GetCurrentThread(); @@ -2283,6 +2269,10 @@ RNBRemote::HandlePacket_G (const char *p) { return SendPacket ("E11"); } + + if (g_num_reg_entries == 0) + InitializeRegisters (); + StringExtractor packet(p); packet.SetFilePos(1); // Skip the 'G' @@ -2872,6 +2862,9 @@ RNBRemote::HandlePacket_z (const char *p) rnb_err_t RNBRemote::HandlePacket_p (const char *p) { + if (g_num_reg_entries == 0) + InitializeRegisters (); + if (p == NULL || *p == '\0') { return HandlePacket_ILLFORMED ("No thread specified in p packet"); @@ -2931,6 +2924,9 @@ RNBRemote::HandlePacket_p (const char *p) rnb_err_t RNBRemote::HandlePacket_P (const char *p) { + if (g_num_reg_entries == 0) + InitializeRegisters (); + if (p == NULL || *p == '\0') { return HandlePacket_ILLFORMED ("Empty P packet"); diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h index 30ab7e67302..fab42bc9693 100644 --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -106,10 +106,12 @@ public: typedef rnb_err_t (RNBRemote::*HandlePacketCallback)(const char *p); - RNBRemote(bool use_native_regs); - ~RNBRemote(); + RNBRemote (bool use_native_regs, const char *arch); + ~RNBRemote (); - static void InitializeRegisters (int use_native); + void Initialize(); + + bool InitializeRegisters (); rnb_err_t HandleAsyncPacket(PacketEnum *type = NULL); rnb_err_t HandleReceivedPacket(PacketEnum *type = NULL); @@ -194,9 +196,6 @@ private: protected: - static void - InitializeNativeRegisters (); - rnb_err_t GetCommData (); void CommDataReceived(const std::string& data); struct Packet @@ -273,8 +272,7 @@ protected: typedef BreakpointMap::const_iterator BreakpointMapConstIter; RNBContext m_ctx; // process context RNBSocket m_comm; // communication port - bool m_extended_mode; // are we in extended mode? - bool m_noack_mode; // are we in no-ack mode? + std::string m_arch; nub_thread_t m_continue_thread; // thread to continue; 0 for any, -1 for all nub_thread_t m_thread; // thread for other ops; 0 for any, -1 for all PThreadMutex m_mutex; // Mutex that protects @@ -286,7 +284,9 @@ protected: BreakpointMap m_breakpoints; BreakpointMap m_watchpoints; uint32_t m_max_payload_size; // the maximum sized payload we should send to gdb - bool m_use_native_regs; + bool m_extended_mode:1, // are we in extended mode? + m_noack_mode:1, // are we in no-ack mode? + m_use_native_regs:1; // Use native registers by querying DNB layer for register definitions? }; /* We translate the /usr/include/mach/exception_types.h exception types diff --git a/lldb/tools/debugserver/source/debugserver.cpp b/lldb/tools/debugserver/source/debugserver.cpp index a3cae284d4f..e8c28cc5eae 100644 --- a/lldb/tools/debugserver/source/debugserver.cpp +++ b/lldb/tools/debugserver/source/debugserver.cpp @@ -334,7 +334,6 @@ RNBRunLoopLaunchAttaching (RNBRemoteSP &remote, nub_process_t attach_pid, nub_pr } else { - ctx.SetProcessID(pid); return eRNBRunLoopModeInferiorExecuting; } @@ -644,6 +643,7 @@ show_usage_and_exit (int exit_code) static struct option g_long_options[] = { { "attach", required_argument, NULL, 'a' }, + { "arch", required_argument, NULL, 'A' }, { "debug", no_argument, NULL, 'g' }, { "verbose", no_argument, NULL, 'v' }, { "lockdown", no_argument, &g_lockdown_opt, 1 }, // short option "-k" @@ -695,6 +695,7 @@ 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 stdio_path; + std::string arch_name; 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. @@ -704,7 +705,7 @@ main (int argc, char *argv[]) RNBRunLoopMode start_mode = eRNBRunLoopModeExit; - while ((ch = getopt_long(argc, argv, "a:d:gi:vktl:f:w:x:rs:", g_long_options, &long_option_index)) != -1) + while ((ch = getopt_long(argc, argv, "a:A:d:gi:vktl:f:w:x:rs:", g_long_options, &long_option_index)) != -1) { DNBLogDebug("option: ch == %c (0x%2.2x) --%s%c%s\n", ch, (uint8_t)ch, @@ -716,6 +717,11 @@ main (int argc, char *argv[]) case 0: // Any optional that auto set themselves will return 0 break; + case 'A': + if (optarg && optarg[0]) + arch_name.assign(optarg); + break; + case 'a': if (optarg && optarg[0]) { @@ -869,12 +875,28 @@ main (int argc, char *argv[]) break; } } + + if (arch_name.empty()) + { +#if defined (__i386__) + arch_name.assign ("i386"); +#elif defined (__x86_64__) + arch_name.assign ("x86_64"); +#elif defined (__arm__) + arch_name.assign ("arm"); +#endif + } + if (arch_name.empty()) + { + fprintf(stderr, "error: no architecture was specified\n"); + exit (8); + } // Skip any options we consumed with getopt_long argc -= optind; argv += optind; - g_remoteSP.reset (new RNBRemote (use_native_registers)); + g_remoteSP.reset (new RNBRemote (use_native_registers, arch_name.c_str())); RNBRemote *remote = g_remoteSP.get(); if (remote == NULL) @@ -883,6 +905,8 @@ main (int argc, char *argv[]) return -1; } + g_remoteSP->Initialize(); + RNBContext& ctx = remote->Context(); @@ -911,11 +935,6 @@ main (int argc, char *argv[]) DNBLogDebug("argv[%i] = %s", i, argv[i]); } - // Now that we have read in the options and enabled logging, initialize - // the rest of RNBRemote - RNBRemote::InitializeRegisters (use_native_registers); - - // as long as we're dropping remotenub in as a replacement for gdbserver, // explicitly note that this is not gdbserver. |