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/tools/debugserver | |
| 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/tools/debugserver')
19 files changed, 467 insertions, 314 deletions
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. |

