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
180 lines
5.4 KiB
C++
180 lines
5.4 KiB
C++
//===-- DNBArchImpl.h -------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Created by Greg Clayton on 6/25/07.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef __DebugNubArchMachPPC_h__
|
|
#define __DebugNubArchMachPPC_h__
|
|
|
|
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
|
|
|
|
#include "DNBArch.h"
|
|
|
|
class MachThread;
|
|
|
|
class DNBArchMachPPC : public DNBArchProtocol
|
|
{
|
|
public:
|
|
DNBArchMachPPC(MachThread *thread) :
|
|
m_thread(thread),
|
|
m_state()
|
|
{
|
|
}
|
|
|
|
virtual ~DNBArchMachPPC()
|
|
{
|
|
}
|
|
|
|
virtual const DNBRegisterSetInfo *
|
|
GetRegisterSetInfo(nub_size_t *num_reg_sets) const;
|
|
virtual bool GetRegisterValue(int set, int reg, DNBRegisterValue *value) const;
|
|
virtual kern_return_t GetRegisterState (int set, bool force);
|
|
virtual kern_return_t SetRegisterState (int set);
|
|
virtual bool RegisterSetStateIsValid (int set) const;
|
|
|
|
virtual uint64_t GetPC(uint64_t failValue); // Get program counter
|
|
virtual kern_return_t SetPC(uint64_t value);
|
|
virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer
|
|
virtual bool ThreadWillResume();
|
|
virtual bool ThreadDidStop();
|
|
|
|
static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size);
|
|
static uint32_t GetCPUType();
|
|
|
|
protected:
|
|
|
|
|
|
kern_return_t EnableHardwareSingleStep (bool enable);
|
|
|
|
typedef enum RegisterSetTag
|
|
{
|
|
e_regSetALL = REGISTER_SET_ALL,
|
|
e_regSetGPR,
|
|
e_regSetFPR,
|
|
e_regSetEXC,
|
|
e_regSetVEC,
|
|
kNumRegisterSets
|
|
} RegisterSet;
|
|
|
|
typedef enum RegisterSetWordSizeTag
|
|
{
|
|
e_regSetWordSizeGPR = PPC_THREAD_STATE_COUNT,
|
|
e_regSetWordSizeFPR = PPC_FLOAT_STATE_COUNT,
|
|
e_regSetWordSizeEXC = PPC_EXCEPTION_STATE_COUNT,
|
|
e_regSetWordSizeVEC = PPC_VECTOR_STATE_COUNT
|
|
} RegisterSetWordSize;
|
|
|
|
enum
|
|
{
|
|
Read = 0,
|
|
Write = 1,
|
|
kNumErrors = 2
|
|
};
|
|
|
|
struct State
|
|
{
|
|
ppc_thread_state_t gpr;
|
|
ppc_float_state_t fpr;
|
|
ppc_exception_state_t exc;
|
|
ppc_vector_state_t vec;
|
|
kern_return_t gpr_errs[2]; // Read/Write errors
|
|
kern_return_t fpr_errs[2]; // Read/Write errors
|
|
kern_return_t exc_errs[2]; // Read/Write errors
|
|
kern_return_t vec_errs[2]; // Read/Write errors
|
|
|
|
State()
|
|
{
|
|
uint32_t i;
|
|
for (i=0; i<kNumErrors; i++)
|
|
{
|
|
gpr_errs[i] = -1;
|
|
fpr_errs[i] = -1;
|
|
exc_errs[i] = -1;
|
|
vec_errs[i] = -1;
|
|
}
|
|
}
|
|
void InvalidateAllRegisterStates()
|
|
{
|
|
SetError (e_regSetALL, Read, -1);
|
|
}
|
|
kern_return_t GetError (int set, uint32_t err_idx) const
|
|
{
|
|
if (err_idx < kNumErrors)
|
|
{
|
|
switch (set)
|
|
{
|
|
// When getting all errors, just OR all values together to see if
|
|
// we got any kind of error.
|
|
case e_regSetALL: return gpr_errs[err_idx] | fpr_errs[err_idx] | exc_errs[err_idx] | vec_errs[err_idx];
|
|
case e_regSetGPR: return gpr_errs[err_idx];
|
|
case e_regSetFPR: return fpr_errs[err_idx];
|
|
case e_regSetEXC: return exc_errs[err_idx];
|
|
case e_regSetVEC: return vec_errs[err_idx];
|
|
default: break;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
bool SetError (int set, uint32_t err_idx, kern_return_t err)
|
|
{
|
|
if (err_idx < kNumErrors)
|
|
{
|
|
switch (set)
|
|
{
|
|
case e_regSetALL:
|
|
gpr_errs[err_idx] = fpr_errs[err_idx] = exc_errs[err_idx] = vec_errs[err_idx] = err;
|
|
return true;
|
|
|
|
case e_regSetGPR:
|
|
gpr_errs[err_idx] = err;
|
|
return true;
|
|
|
|
case e_regSetFPR:
|
|
fpr_errs[err_idx] = err;
|
|
return true;
|
|
|
|
case e_regSetEXC:
|
|
exc_errs[err_idx] = err;
|
|
return true;
|
|
|
|
case e_regSetVEC:
|
|
vec_errs[err_idx] = err;
|
|
return true;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
bool RegsAreValid (int set) const
|
|
{
|
|
return GetError(set, Read) == KERN_SUCCESS;
|
|
}
|
|
};
|
|
|
|
kern_return_t GetGPRState (bool force);
|
|
kern_return_t GetFPRState (bool force);
|
|
kern_return_t GetEXCState (bool force);
|
|
kern_return_t GetVECState (bool force);
|
|
|
|
kern_return_t SetGPRState ();
|
|
kern_return_t SetFPRState ();
|
|
kern_return_t SetEXCState ();
|
|
kern_return_t SetVECState ();
|
|
|
|
protected:
|
|
MachThread * m_thread;
|
|
State m_state;
|
|
};
|
|
|
|
#endif // #if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__)
|
|
#endif // #ifndef __DebugNubArchMachPPC_h__
|