forked from OSchip/llvm-project
[LLDB][MIPS] Hardware Watchpoints for MIPS
Reviewers: clayborg, jingham. Subscribers: jaydeep, bhushan, dsanders, sagar, lldb-commits. Differential Revision: http://reviews.llvm.org/D9142 llvm-svn: 239991
This commit is contained in:
parent
58e5bdb091
commit
3579996399
|
@ -2011,6 +2011,27 @@ NativeProcessLinux::MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid)
|
|||
break;
|
||||
|
||||
case SI_KERNEL:
|
||||
#if defined __mips__
|
||||
// For mips there is no special signal for watchpoint
|
||||
// So we check for watchpoint in kernel trap
|
||||
if (thread_sp)
|
||||
{
|
||||
// If a watchpoint was hit, report it
|
||||
uint32_t wp_index;
|
||||
Error error = thread_sp->GetRegisterContext()->GetWatchpointHitIndex(wp_index, NULL);
|
||||
if (error.Fail() && log)
|
||||
log->Printf("NativeProcessLinux::%s() "
|
||||
"received error while checking for watchpoint hits, "
|
||||
"pid = %" PRIu64 " error = %s",
|
||||
__FUNCTION__, pid, error.AsCString());
|
||||
if (wp_index != LLDB_INVALID_INDEX32)
|
||||
{
|
||||
MonitorWatchpoint(pid, thread_sp, wp_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// NO BREAK
|
||||
#endif
|
||||
case TRAP_BRKPT:
|
||||
MonitorBreakpoint(pid, thread_sp);
|
||||
break;
|
||||
|
|
|
@ -26,6 +26,53 @@
|
|||
#include "Plugins/Process/Utility/RegisterContextLinux_mips64.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextLinux_mips.h"
|
||||
|
||||
#include <sys/ptrace.h>
|
||||
#include <asm/ptrace.h>
|
||||
|
||||
#ifndef PTRACE_GET_WATCH_REGS
|
||||
enum pt_watch_style
|
||||
{
|
||||
pt_watch_style_mips32,
|
||||
pt_watch_style_mips64
|
||||
};
|
||||
struct mips32_watch_regs
|
||||
{
|
||||
uint32_t watchlo[8];
|
||||
uint16_t watchhi[8];
|
||||
uint16_t watch_masks[8];
|
||||
uint32_t num_valid;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct mips64_watch_regs
|
||||
{
|
||||
uint64_t watchlo[8];
|
||||
uint16_t watchhi[8];
|
||||
uint16_t watch_masks[8];
|
||||
uint32_t num_valid;
|
||||
} __attribute__((aligned(8)));
|
||||
|
||||
struct pt_watch_regs
|
||||
{
|
||||
enum pt_watch_style style;
|
||||
union
|
||||
{
|
||||
struct mips32_watch_regs mips32;
|
||||
struct mips64_watch_regs mips64;
|
||||
};
|
||||
};
|
||||
|
||||
#define PTRACE_GET_WATCH_REGS 0xd0
|
||||
#define PTRACE_SET_WATCH_REGS 0xd1
|
||||
#endif
|
||||
|
||||
#define W (1 << 0)
|
||||
#define R (1 << 1)
|
||||
#define I (1 << 2)
|
||||
|
||||
#define IRW (I | R | W)
|
||||
|
||||
struct pt_watch_regs default_watch_regs;
|
||||
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::process_linux;
|
||||
|
||||
|
@ -281,6 +328,47 @@ namespace
|
|||
const RegisterValue &m_value;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @class ReadWatchPointRegOperation
|
||||
/// @brief Implements NativeProcessLinux::ReadWatchPointRegisterValue.
|
||||
class ReadWatchPointRegOperation : public Operation
|
||||
{
|
||||
public:
|
||||
ReadWatchPointRegOperation (
|
||||
lldb::tid_t tid,
|
||||
void* watch_readback) :
|
||||
m_tid(tid),
|
||||
m_watch_readback(watch_readback)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(NativeProcessLinux *monitor) override;
|
||||
|
||||
private:
|
||||
lldb::tid_t m_tid;
|
||||
void* m_watch_readback;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// @class SetWatchPointRegOperation
|
||||
/// @brief Implements NativeProcessLinux::SetWatchPointRegisterValue.
|
||||
class SetWatchPointRegOperation : public Operation
|
||||
{
|
||||
public:
|
||||
SetWatchPointRegOperation (
|
||||
lldb::tid_t tid,
|
||||
void* watch_reg_value) :
|
||||
m_tid(tid),
|
||||
m_watch_reg_value(watch_reg_value)
|
||||
{
|
||||
}
|
||||
|
||||
void Execute(NativeProcessLinux *monitor) override;
|
||||
|
||||
private:
|
||||
lldb::tid_t m_tid;
|
||||
void* m_watch_reg_value;
|
||||
};
|
||||
} // end of anonymous namespace
|
||||
|
||||
void
|
||||
|
@ -310,6 +398,18 @@ WriteRegOperation::Execute(NativeProcessLinux *monitor)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ReadWatchPointRegOperation::Execute(NativeProcessLinux *monitor)
|
||||
{
|
||||
NativeProcessLinux::PtraceWrapper(PTRACE_GET_WATCH_REGS, m_tid, m_watch_readback, NULL, NULL, m_error);
|
||||
}
|
||||
|
||||
void
|
||||
SetWatchPointRegOperation::Execute(NativeProcessLinux *monitor)
|
||||
{
|
||||
NativeProcessLinux::PtraceWrapper(PTRACE_SET_WATCH_REGS, m_tid, m_watch_reg_value, NULL, NULL, m_error);
|
||||
}
|
||||
|
||||
NativeRegisterContextLinux*
|
||||
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
|
||||
NativeThreadProtocol &native_thread,
|
||||
|
@ -373,6 +473,10 @@ NativeRegisterContextLinux_mips64::NativeRegisterContextLinux_mips64 (const Arch
|
|||
|
||||
// Clear out the FPR state.
|
||||
::memset(&m_fpr, 0, sizeof(FPR_mips));
|
||||
|
||||
// init h/w watchpoint addr map
|
||||
for (int index = 0;index <= MAX_NUM_WP; index++)
|
||||
hw_addr_map[index] = LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -655,11 +759,216 @@ NativeRegisterContextLinux_mips64::IsFPR(uint32_t reg_index) const
|
|||
return (m_reg_info.first_fpr <= reg_index && reg_index <= m_reg_info.last_fpr);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GetWatchHi (struct pt_watch_regs *regs, uint32_t index)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
if (regs->style == pt_watch_style_mips32)
|
||||
return regs->mips32.watchhi[index];
|
||||
else if (regs->style == pt_watch_style_mips64)
|
||||
return regs->mips64.watchhi[index];
|
||||
else
|
||||
log->Printf("Invalid watch register style");
|
||||
}
|
||||
|
||||
static void
|
||||
SetWatchHi (struct pt_watch_regs *regs, uint32_t index, uint16_t value)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
if (regs->style == pt_watch_style_mips32)
|
||||
regs->mips32.watchhi[index] = value;
|
||||
else if (regs->style == pt_watch_style_mips64)
|
||||
regs->mips64.watchhi[index] = value;
|
||||
else
|
||||
log->Printf("Invalid watch register style");
|
||||
}
|
||||
|
||||
static lldb::addr_t
|
||||
GetWatchLo (struct pt_watch_regs *regs, uint32_t index)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
if (regs->style == pt_watch_style_mips32)
|
||||
return regs->mips32.watchlo[index];
|
||||
else if (regs->style == pt_watch_style_mips64)
|
||||
return regs->mips64.watchlo[index];
|
||||
else
|
||||
log->Printf("Invalid watch register style");
|
||||
}
|
||||
|
||||
static void
|
||||
SetWatchLo (struct pt_watch_regs *regs, uint32_t index, uint64_t value)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
if (regs->style == pt_watch_style_mips32)
|
||||
regs->mips32.watchlo[index] = (uint32_t) value;
|
||||
else if (regs->style == pt_watch_style_mips64)
|
||||
regs->mips64.watchlo[index] = value;
|
||||
else
|
||||
log->Printf("Invalid watch register style");
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GetIRWMask (struct pt_watch_regs *regs, uint32_t index)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
if (regs->style == pt_watch_style_mips32)
|
||||
return regs->mips32.watch_masks[index] & IRW;
|
||||
else if (regs->style == pt_watch_style_mips64)
|
||||
return regs->mips64.watch_masks[index] & IRW;
|
||||
else
|
||||
log->Printf("Invalid watch register style");
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
GetRegMask (struct pt_watch_regs *regs, uint32_t index)
|
||||
{
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
if (regs->style == pt_watch_style_mips32)
|
||||
return regs->mips32.watch_masks[index] & ~IRW;
|
||||
else if (regs->style == pt_watch_style_mips64)
|
||||
return regs->mips64.watch_masks[index] & ~IRW;
|
||||
else
|
||||
log->Printf("Invalid watch register style");
|
||||
}
|
||||
|
||||
static lldb::addr_t
|
||||
GetRangeMask (lldb::addr_t mask)
|
||||
{
|
||||
lldb::addr_t mask_bit = 1;
|
||||
while (mask_bit < mask)
|
||||
{
|
||||
mask = mask | mask_bit;
|
||||
mask_bit <<= 1;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
static int
|
||||
GetVacantWatchIndex (struct pt_watch_regs *regs, lldb::addr_t addr, uint32_t size, uint32_t irw, uint32_t num_valid)
|
||||
{
|
||||
lldb::addr_t last_byte = addr + size - 1;
|
||||
lldb::addr_t mask = GetRangeMask (addr ^ last_byte) | IRW;
|
||||
lldb::addr_t base_addr = addr & ~mask;
|
||||
|
||||
// Check if this address is already watched by previous watch points.
|
||||
lldb::addr_t lo;
|
||||
uint16_t hi;
|
||||
uint32_t vacant_watches = 0;
|
||||
for (uint32_t index = 0; index < num_valid; index++)
|
||||
{
|
||||
lo = GetWatchLo (regs, index);
|
||||
if (lo != 0 && irw == ((uint32_t) lo & irw))
|
||||
{
|
||||
hi = GetWatchHi (regs, index) | IRW;
|
||||
lo &= ~(lldb::addr_t) hi;
|
||||
if (addr >= lo && last_byte <= (lo + hi))
|
||||
return index;
|
||||
}
|
||||
else
|
||||
vacant_watches++;
|
||||
}
|
||||
|
||||
// Now try to find a vacant index
|
||||
if(vacant_watches > 0)
|
||||
{
|
||||
vacant_watches = 0;
|
||||
for (uint32_t index = 0; index < num_valid; index++)
|
||||
{
|
||||
lo = GetWatchLo (regs, index);
|
||||
if (lo == 0
|
||||
&& irw == (GetIRWMask (regs, index) & irw))
|
||||
{
|
||||
if (mask <= (GetRegMask (regs, index) | IRW))
|
||||
{
|
||||
// It fits, we can use it.
|
||||
SetWatchLo (regs, index, base_addr | irw);
|
||||
SetWatchHi (regs, index, mask & ~IRW);
|
||||
return index;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It doesn't fit, but has the proper IRW capabilities
|
||||
vacant_watches++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vacant_watches > 1)
|
||||
{
|
||||
// Split this watchpoint accross several registers
|
||||
struct pt_watch_regs regs_copy;
|
||||
regs_copy = *regs;
|
||||
lldb::addr_t break_addr;
|
||||
uint32_t segment_size;
|
||||
for (uint32_t index = 0; index < num_valid; index++)
|
||||
{
|
||||
lo = GetWatchLo (®s_copy, index);
|
||||
hi = GetRegMask (®s_copy, index) | IRW;
|
||||
if (lo == 0 && irw == (hi & irw))
|
||||
{
|
||||
lo = addr & ~(lldb::addr_t) hi;
|
||||
break_addr = lo + hi + 1;
|
||||
if (break_addr >= addr + size)
|
||||
segment_size = size;
|
||||
else
|
||||
segment_size = break_addr - addr;
|
||||
mask = GetRangeMask (addr ^ (addr + segment_size - 1));
|
||||
SetWatchLo (®s_copy, index, (addr & ~mask) | irw);
|
||||
SetWatchHi (®s_copy, index, mask & ~IRW);
|
||||
if (break_addr >= addr + size)
|
||||
{
|
||||
*regs = regs_copy;
|
||||
return index;
|
||||
}
|
||||
size = addr + size - break_addr;
|
||||
addr = break_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContextLinux_mips64::IsWatchpointHit (uint32_t wp_index, bool &is_hit)
|
||||
{
|
||||
if (wp_index >= NumSupportedHardwareWatchpoints())
|
||||
return Error("Watchpoint index out of range");
|
||||
|
||||
// reading the current state of watch regs
|
||||
struct pt_watch_regs watch_readback;
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
|
||||
Error error = process_p->DoOperation(GetReadWatchPointRegisterValueOperation(m_thread.GetID(),(void*)&watch_readback));
|
||||
|
||||
if (GetWatchHi (&watch_readback, wp_index) & (IRW))
|
||||
{
|
||||
// clear hit flag in watchhi
|
||||
SetWatchHi (&watch_readback, wp_index, (GetWatchHi (&watch_readback, wp_index) & ~(IRW)));
|
||||
process_p->DoOperation(GetWriteWatchPointRegisterValueOperation(m_thread.GetID(), (void*)&watch_readback));
|
||||
|
||||
is_hit = true;
|
||||
return error;
|
||||
}
|
||||
is_hit = false;
|
||||
return Error("MIPS TODO: NativeRegisterContextLinux_mips64::IsWatchpointHit not implemented");
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContextLinux_mips64::GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) {
|
||||
uint32_t num_hw_wps = NumSupportedHardwareWatchpoints();
|
||||
for (wp_index = 0; wp_index < num_hw_wps; ++wp_index)
|
||||
{
|
||||
bool is_hit;
|
||||
Error error = IsWatchpointHit(wp_index, is_hit);
|
||||
if (error.Fail()) {
|
||||
wp_index = LLDB_INVALID_INDEX32;
|
||||
} else if (is_hit) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
wp_index = LLDB_INVALID_INDEX32;
|
||||
return Error();
|
||||
}
|
||||
|
||||
Error
|
||||
|
@ -670,17 +979,45 @@ NativeRegisterContextLinux_mips64::IsWatchpointVacant (uint32_t wp_index, bool &
|
|||
}
|
||||
|
||||
bool
|
||||
NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint (uint32_t wp_index)
|
||||
NativeRegisterContextLinux_mips64::ClearHardwareWatchpoint(uint32_t wp_index)
|
||||
{
|
||||
if (wp_index >= NumSupportedHardwareWatchpoints())
|
||||
return false;
|
||||
|
||||
struct pt_watch_regs regs;
|
||||
// First reading the current state of watch regs
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
|
||||
process_p->DoOperation(GetReadWatchPointRegisterValueOperation(m_thread.GetID(),(void*)®s));
|
||||
|
||||
if (regs.style == pt_watch_style_mips32)
|
||||
{
|
||||
regs.mips32.watchlo[wp_index] = default_watch_regs.mips32.watchlo[wp_index];
|
||||
regs.mips32.watchhi[wp_index] = default_watch_regs.mips32.watchhi[wp_index];
|
||||
regs.mips32.watch_masks[wp_index] = default_watch_regs.mips32.watch_masks[wp_index];
|
||||
}
|
||||
else // pt_watch_style_mips64
|
||||
{
|
||||
regs.mips64.watchlo[wp_index] = default_watch_regs.mips64.watchlo[wp_index];
|
||||
regs.mips64.watchhi[wp_index] = default_watch_regs.mips64.watchhi[wp_index];
|
||||
regs.mips64.watch_masks[wp_index] = default_watch_regs.mips64.watch_masks[wp_index];
|
||||
}
|
||||
|
||||
Error error = process_p->DoOperation(GetWriteWatchPointRegisterValueOperation(m_thread.GetID(), (void*)®s));
|
||||
if(!error.Fail())
|
||||
{
|
||||
hw_addr_map[wp_index] = LLDB_INVALID_ADDRESS;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints ()
|
||||
NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints()
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorString ("MIPS TODO: NativeRegisterContextLinux_mips64::ClearAllHardwareWatchpoints not implemented");
|
||||
return error;
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
|
||||
return process_p->DoOperation(GetWriteWatchPointRegisterValueOperation(m_thread.GetID(), (void*)&default_watch_regs));
|
||||
}
|
||||
|
||||
Error
|
||||
|
@ -696,19 +1033,70 @@ uint32_t
|
|||
NativeRegisterContextLinux_mips64::SetHardwareWatchpoint (
|
||||
lldb::addr_t addr, size_t size, uint32_t watch_flags)
|
||||
{
|
||||
struct pt_watch_regs regs;
|
||||
|
||||
// First reading the current state of watch regs
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
|
||||
process_p->DoOperation(GetReadWatchPointRegisterValueOperation(m_thread.GetID(),(void*)®s));
|
||||
|
||||
// Try if a new watch point fits in this state
|
||||
int index = GetVacantWatchIndex (®s, addr, size, watch_flags, NumSupportedHardwareWatchpoints());
|
||||
|
||||
// New watchpoint doesn't fit
|
||||
if (!index)
|
||||
return LLDB_INVALID_INDEX32;
|
||||
|
||||
|
||||
// It fits, so we go ahead with updating the state of watch regs
|
||||
process_p->DoOperation(GetWriteWatchPointRegisterValueOperation(m_thread.GetID(), (void*)®s));
|
||||
|
||||
// Storing exact address
|
||||
hw_addr_map[index] = addr;
|
||||
return index;
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContextLinux_mips64::GetWatchpointAddress (uint32_t wp_index)
|
||||
{
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
if (wp_index >= NumSupportedHardwareWatchpoints())
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
|
||||
return hw_addr_map[wp_index];
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContextLinux_mips64::NumSupportedHardwareWatchpoints ()
|
||||
{
|
||||
return 0;
|
||||
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
|
||||
struct pt_watch_regs regs;
|
||||
static int num_valid = 0;
|
||||
if (!num_valid)
|
||||
{
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
if (!process_sp)
|
||||
{
|
||||
printf ("NativeProcessProtocol is NULL");
|
||||
return 0;
|
||||
}
|
||||
|
||||
NativeProcessLinux *const process_p = reinterpret_cast<NativeProcessLinux*> (process_sp.get ());
|
||||
process_p->DoOperation(GetReadWatchPointRegisterValueOperation(m_thread.GetID(),(void*)®s));
|
||||
default_watch_regs = regs; // Keeping default watch regs values for future use
|
||||
switch (regs.style)
|
||||
{
|
||||
case pt_watch_style_mips32:
|
||||
num_valid = regs.mips32.num_valid; // Using num_valid as cache
|
||||
return num_valid;
|
||||
case pt_watch_style_mips64:
|
||||
num_valid = regs.mips64.num_valid;
|
||||
return num_valid;
|
||||
default:
|
||||
log->Printf("NativeRegisterContextLinux_mips64::%s Error: Unrecognized watch register style", __FUNCTION__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return num_valid;
|
||||
}
|
||||
|
||||
NativeProcessLinux::OperationUP
|
||||
|
@ -728,4 +1116,16 @@ NativeRegisterContextLinux_mips64::GetWriteRegisterValueOperation(uint32_t offse
|
|||
return NativeProcessLinux::OperationUP(new WriteRegOperation(m_thread.GetID(), offset, reg_name, value));
|
||||
}
|
||||
|
||||
NativeProcessLinux::OperationUP
|
||||
NativeRegisterContextLinux_mips64::GetReadWatchPointRegisterValue(lldb::tid_t tid, void* watch_readback)
|
||||
{
|
||||
return NativeProcessLinux::OperationUP(new ReadWatchPointRegOperation(m_thread.GetID(), watch_readback));
|
||||
}
|
||||
|
||||
NativeProcessLinux::OperationUP
|
||||
NativeRegisterContextLinux_mips64::GetWriteWatchPointRegisterValue(lldb::tid_t tid, void* watch_reg_value)
|
||||
{
|
||||
return NativeProcessLinux::OperationUP(new SetWatchPointRegOperation(m_thread.GetID(), watch_readback));
|
||||
}
|
||||
|
||||
#endif // defined (__mips__)
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#include "Plugins/Process/Utility/RegisterContext_mips64.h"
|
||||
#include "Plugins/Process/Utility/lldb-mips64-register-enums.h"
|
||||
|
||||
#define MAX_NUM_WP 8
|
||||
|
||||
namespace lldb_private {
|
||||
namespace process_linux {
|
||||
|
||||
|
@ -55,6 +57,9 @@ namespace process_linux {
|
|||
Error
|
||||
IsWatchpointHit (uint32_t wp_index, bool &is_hit) override;
|
||||
|
||||
Error
|
||||
GetWatchpointHitIndex(uint32_t &wp_index, lldb::addr_t trap_addr) override;
|
||||
|
||||
Error
|
||||
IsWatchpointVacant (uint32_t wp_index, bool &is_vacant) override;
|
||||
|
||||
|
@ -90,6 +95,14 @@ namespace process_linux {
|
|||
const char* reg_name,
|
||||
const RegisterValue &value) override;
|
||||
|
||||
NativeProcessLinux::OperationUP
|
||||
GetReadWatchPointRegisterValue(lldb::tid_t tid,
|
||||
void* watch_readback);
|
||||
|
||||
NativeProcessLinux::OperationUP
|
||||
GetWriteWatchPointRegisterValue(lldb::tid_t tid,
|
||||
void* watch_readback);
|
||||
|
||||
bool
|
||||
IsFR0();
|
||||
|
||||
|
@ -123,6 +136,8 @@ namespace process_linux {
|
|||
uint64_t m_gpr_mips64[k_num_gpr_registers_mips64];
|
||||
|
||||
FPR_mips m_fpr;
|
||||
|
||||
lldb::addr_t hw_addr_map[MAX_NUM_WP];
|
||||
};
|
||||
|
||||
} // namespace process_linux
|
||||
|
|
|
@ -185,7 +185,11 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &
|
|||
else
|
||||
response.Printf("watchpoint_exceptions_received:after;");
|
||||
#else
|
||||
response.Printf("watchpoint_exceptions_received:after;");
|
||||
if (host_arch.GetMachine() == llvm::Triple::mips64 ||
|
||||
host_arch.GetMachine() == llvm::Triple::mips64el)
|
||||
response.Printf("watchpoint_exceptions_received:before;");
|
||||
else
|
||||
response.Printf("watchpoint_exceptions_received:after;");
|
||||
#endif
|
||||
|
||||
switch (lldb::endian::InlHostByteOrder())
|
||||
|
|
Loading…
Reference in New Issue