Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,40 @@ class NativeRegisterContextNetBSD_x86_64 : public NativeRegisterContextNetBSD {

Error WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;

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;

bool ClearHardwareWatchpoint(uint32_t wp_index) override;

Error ClearAllHardwareWatchpoints() override;

Error SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
uint32_t watch_flags, uint32_t wp_index);

uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size,
uint32_t watch_flags) override;

lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;

uint32_t NumSupportedHardwareWatchpoints() override;

protected:
void *GetGPRBuffer() override { return &m_gpr_x86_64; }
void *GetFPRBuffer() override { return &m_fpr_x86_64; }
void *GetDBRBuffer() override { return &m_dbr_x86_64; }

private:
// Private member types.
enum { GPRegSet, FPRegSet };
enum { GPRegSet, FPRegSet, DBRegSet };

// Private member variables.
struct reg m_gpr_x86_64;
struct fpreg m_fpr_x86_64;
struct dbreg m_dbr_x86_64;

int GetSetForNativeRegNum(int reg_num) const;

Expand Down
71 changes: 67 additions & 4 deletions lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/State.h"
#include "lldb/Utility/LLDBAssert.h"

#include <sstream>

using namespace lldb;
using namespace lldb_private;
Expand Down Expand Up @@ -68,6 +71,23 @@ void NativeThreadNetBSD::SetStoppedByExec() {
m_stop_info.details.signal.signo = SIGTRAP;
}

void NativeThreadNetBSD::SetStoppedByWatchpoint(uint32_t wp_index) {
SetStopped();

lldbassert(wp_index != LLDB_INVALID_INDEX32 && "wp_index cannot be invalid");

std::ostringstream ostr;
ostr << GetRegisterContext()->GetWatchpointAddress(wp_index) << " ";
ostr << wp_index;

ostr << " " << GetRegisterContext()->GetWatchpointHitAddress(wp_index);

m_stop_description = ostr.str();

m_stop_info.reason = StopReason::eStopReasonWatchpoint;
m_stop_info.details.signal.signo = SIGTRAP;
}

void NativeThreadNetBSD::SetStopped() {
const StateType new_state = StateType::eStateStopped;
m_state = new_state;
Expand Down Expand Up @@ -142,18 +162,61 @@ NativeRegisterContextSP NativeThreadNetBSD::GetRegisterContext() {

Error NativeThreadNetBSD::SetWatchpoint(lldb::addr_t addr, size_t size,
uint32_t watch_flags, bool hardware) {
return Error("Unimplemented");
if (!hardware)
return Error("not implemented");
if (m_state == eStateLaunching)
return Error();
Error error = RemoveWatchpoint(addr);
if (error.Fail())
return error;
NativeRegisterContextSP reg_ctx = GetRegisterContext();
uint32_t wp_index = reg_ctx->SetHardwareWatchpoint(addr, size, watch_flags);
if (wp_index == LLDB_INVALID_INDEX32)
return Error("Setting hardware watchpoint failed.");
m_watchpoint_index_map.insert({addr, wp_index});
return Error();
}

Error NativeThreadNetBSD::RemoveWatchpoint(lldb::addr_t addr) {
return Error("Unimplemented");
auto wp = m_watchpoint_index_map.find(addr);
if (wp == m_watchpoint_index_map.end())
return Error();
uint32_t wp_index = wp->second;
m_watchpoint_index_map.erase(wp);
if (GetRegisterContext()->ClearHardwareWatchpoint(wp_index))
return Error();
return Error("Clearing hardware watchpoint failed.");
}

Error NativeThreadNetBSD::SetHardwareBreakpoint(lldb::addr_t addr,
size_t size) {
return Error("Unimplemented");
if (m_state == eStateLaunching)
return Error();

Error error = RemoveHardwareBreakpoint(addr);
if (error.Fail())
return error;

NativeRegisterContextSP reg_ctx = GetRegisterContext();
uint32_t bp_index = reg_ctx->SetHardwareBreakpoint(addr, size);

if (bp_index == LLDB_INVALID_INDEX32)
return Error("Setting hardware breakpoint failed.");

m_hw_break_index_map.insert({addr, bp_index});
return Error();
}

Error NativeThreadNetBSD::RemoveHardwareBreakpoint(lldb::addr_t addr) {
return Error("Unimplemented");
auto bp = m_hw_break_index_map.find(addr);
if (bp == m_hw_break_index_map.end())
return Error();

uint32_t bp_index = bp->second;
if (GetRegisterContext()->ClearHardwareBreakpoint(bp_index)) {
m_hw_break_index_map.erase(bp);
return Error();
}

return Error("Clearing hardware breakpoint failed.");
}
7 changes: 7 additions & 0 deletions lldb/source/Plugins/Process/NetBSD/NativeThreadNetBSD.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@

#include "lldb/Host/common/NativeThreadProtocol.h"

#include <map>
#include <string>

namespace lldb_private {
namespace process_netbsd {

Expand Down Expand Up @@ -53,6 +56,7 @@ class NativeThreadNetBSD : public NativeThreadProtocol {
void SetStoppedByBreakpoint();
void SetStoppedByTrace();
void SetStoppedByExec();
void SetStoppedByWatchpoint(uint32_t wp_index);
void SetStopped();
void SetRunning();
void SetStepping();
Expand All @@ -64,6 +68,9 @@ class NativeThreadNetBSD : public NativeThreadProtocol {
ThreadStopInfo m_stop_info;
NativeRegisterContextSP m_reg_context_sp;
std::string m_stop_description;
using WatchpointIndexMap = std::map<lldb::addr_t, uint32_t>;
WatchpointIndexMap m_watchpoint_index_map;
WatchpointIndexMap m_hw_break_index_map;
};

typedef std::shared_ptr<NativeThreadNetBSD> NativeThreadNetBSDSP;
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Process/Utility/RegisterInfos_x86_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@
DR_OFFSET(i), eEncodingUint, eFormatHex, \
{LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, \
LLDB_INVALID_REGNUM }, \
lldb_##reg##i##_x86_64 }, \
nullptr, nullptr, nullptr, 0 \
}

Expand Down