Fix handling concurrent watchpoint events so that they are reported
correctly in LLDB.
If multiple watchpoints are hit concurrently, the NetBSD kernel reports
them as series of SIGTRAPs with a thread specified, and the debugger
investigates DR6 in order to establish which watchpoint was hit. This
is normally fine.
However, LLDB disables and reenables the watchpoint on all threads after
each hit, which results in the hit status from DR6 being wiped.
As a result, it can't establish which watchpoint was hit in successive
SIGTRAP processing.
In order to workaround this problem, clear DR6 only if the breakpoint
is overwritten with a new one. More specifically, move cleaning DR6
from ClearHardwareWatchpoint() to SetHardwareWatchpointWithIndex(),
and do that only if the newly requested watchpoint is different
from the one being set previously. This ensures that the disable-enable
logic of LLDB does not clear watchpoint hit status for the remaining
threads.
This also involves refactoring of watchpoint logic. With the old logic,
clearing watchpoint involved wiping dr6 & dr7, and setting it setting
dr{0..3} & dr7. With the new logic, only enable bit is cleared
from dr7, and the remaining bits are cleared/overwritten while setting
new watchpoint.
Differential Revision: https://reviews.llvm.org/D70025
49 lines
1.7 KiB
C++
49 lines
1.7 KiB
C++
//===-- NativeRegisterContextNetBSD.h ---------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef lldb_NativeRegisterContextNetBSD_h
|
|
#define lldb_NativeRegisterContextNetBSD_h
|
|
|
|
#include "lldb/Host/common/NativeThreadProtocol.h"
|
|
|
|
#include "Plugins/Process/Utility/NativeRegisterContextRegisterInfo.h"
|
|
|
|
namespace lldb_private {
|
|
namespace process_netbsd {
|
|
|
|
class NativeProcessNetBSD;
|
|
|
|
class NativeRegisterContextNetBSD : public NativeRegisterContextRegisterInfo {
|
|
public:
|
|
NativeRegisterContextNetBSD(NativeThreadProtocol &native_thread,
|
|
RegisterInfoInterface *reg_info_interface_p);
|
|
|
|
// This function is implemented in the NativeRegisterContextNetBSD_*
|
|
// subclasses to create a new instance of the host specific
|
|
// NativeRegisterContextNetBSD. The implementations can't collide as only one
|
|
// NativeRegisterContextNetBSD_* variant should be compiled into the final
|
|
// executable.
|
|
static NativeRegisterContextNetBSD *
|
|
CreateHostNativeRegisterContextNetBSD(const ArchSpec &target_arch,
|
|
NativeThreadProtocol &native_thread);
|
|
virtual Status
|
|
CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD &source) = 0;
|
|
|
|
virtual Status ClearWatchpointHit(uint32_t wp_index) = 0;
|
|
|
|
protected:
|
|
Status DoRegisterSet(int req, void *buf);
|
|
virtual NativeProcessNetBSD &GetProcess();
|
|
virtual ::pid_t GetProcessPid();
|
|
};
|
|
|
|
} // namespace process_netbsd
|
|
} // namespace lldb_private
|
|
|
|
#endif // #ifndef lldb_NativeRegisterContextNetBSD_h
|