Skip to content

Commit b0bc446

Browse files
authored
Merge pull request #8096 from jasonmolenda/large-watchpoint-use-watchpointresources
Large watchpoint use watchpointresources
2 parents 3e3a857 + e250557 commit b0bc446

File tree

21 files changed

+701
-314
lines changed

21 files changed

+701
-314
lines changed
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//===-- WatchpointAlgorithms.h ----------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLDB_BREAKPOINT_WATCHPOINTALGORITHMS_H
10+
#define LLDB_BREAKPOINT_WATCHPOINTALGORITHMS_H
11+
12+
#include "lldb/Breakpoint/WatchpointResource.h"
13+
#include "lldb/Utility/ArchSpec.h"
14+
#include "lldb/lldb-public.h"
15+
16+
#include <vector>
17+
18+
namespace lldb_private {
19+
20+
class WatchpointAlgorithms {
21+
22+
public:
23+
/// Convert a user's watchpoint request into an array of memory
24+
/// regions that can be watched by one hardware watchpoint register
25+
/// on the current target.
26+
///
27+
/// \param[in] addr
28+
/// The start address specified by the user.
29+
///
30+
/// \param[in] size
31+
/// The number of bytes the user wants to watch.
32+
///
33+
/// \param[in] read
34+
/// True if we are watching for read accesses.
35+
///
36+
/// \param[in] write
37+
/// True if we are watching for write accesses.
38+
/// \a read and \a write may both be true.
39+
/// There is no "modify" style for WatchpointResources -
40+
/// WatchpointResources are akin to the hardware watchpoint
41+
/// registers which are either in terms of read or write.
42+
/// "modify" distinction is done at the Watchpoint layer, where
43+
/// we check the actual range of bytes the user requested.
44+
///
45+
/// \param[in] supported_features
46+
/// The bit flags in this parameter are set depending on which
47+
/// WatchpointHardwareFeature enum values the current target supports.
48+
/// The eWatchpointHardwareFeatureUnknown bit may be set if we
49+
/// don't have specific information about what the remote stub
50+
/// can support, and a reasonablec default will be used.
51+
///
52+
/// \param[in] arch
53+
/// The ArchSpec of the current Target.
54+
///
55+
/// \return
56+
/// A vector of WatchpointResourceSP's, one per hardware watchpoint
57+
/// register needed. We may return more WatchpointResources than the
58+
/// target can watch at once; if all resources cannot be set, the
59+
/// watchpoint cannot be set.
60+
static std::vector<lldb::WatchpointResourceSP> AtomizeWatchpointRequest(
61+
lldb::addr_t addr, size_t size, bool read, bool write,
62+
lldb::WatchpointHardwareFeature supported_features, ArchSpec &arch);
63+
64+
struct Region {
65+
lldb::addr_t addr;
66+
size_t size;
67+
};
68+
69+
protected:
70+
/// Convert a user's watchpoint request into an array of addr+size that
71+
/// can be watched with power-of-2 style hardware watchpoints.
72+
///
73+
/// This is the default algorithm if we have no further information;
74+
/// most watchpoint implementations can be assumed to be able to watch up
75+
/// to pointer-size regions of memory in power-of-2 sizes and alingments.
76+
///
77+
/// \param[in] user_addr
78+
/// The user's start address.
79+
///
80+
/// \param[in] user_size
81+
/// The user's specified byte length.
82+
///
83+
/// \param[in] min_byte_size
84+
/// The minimum byte size supported on this target.
85+
/// In most cases, this will be 1. AArch64 MASK watchpoints can
86+
/// watch a minimum of 8 bytes (although Byte Address Select watchpoints
87+
/// can watch 1 to pointer-size bytes in a pointer-size aligned granule).
88+
///
89+
/// \param[in] max_byte_size
90+
/// The maximum byte size supported for one watchpoint on this target.
91+
///
92+
/// \param[in] address_byte_size
93+
/// The address byte size on this target.
94+
static std::vector<Region> PowerOf2Watchpoints(lldb::addr_t user_addr,
95+
size_t user_size,
96+
size_t min_byte_size,
97+
size_t max_byte_size,
98+
uint32_t address_byte_size);
99+
};
100+
101+
} // namespace lldb_private
102+
103+
#endif // LLDB_BREAKPOINT_WATCHPOINTALGORITHMS_H

lldb/include/lldb/Breakpoint/WatchpointResource.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,6 @@ class WatchpointResource
121121
/// A copy of the Watchpoints which own this resource.
122122
WatchpointCollection CopyConstituentsList();
123123

124-
// The ID of the WatchpointResource is set by the WatchpointResourceList
125-
// when the Resource has been set in the inferior and is being added
126-
// to the List, in an attempt to match the hardware watchpoint register
127-
// ordering. If a Process can correctly identify the hardware watchpoint
128-
// register index when it has created the Resource, it may initialize it
129-
// before it is inserted in the WatchpointResourceList.
130-
void SetID(lldb::wp_resource_id_t);
131-
132124
lldb::wp_resource_id_t GetID() const;
133125

134126
bool Contains(lldb::addr_t addr);

lldb/include/lldb/Breakpoint/WatchpointResourceList.h

Lines changed: 0 additions & 145 deletions
This file was deleted.

lldb/include/lldb/lldb-enumerations.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,32 @@ enum WatchpointWriteType {
448448
eWatchpointWriteTypeOnModify
449449
};
450450

451+
/// The hardware and native stub capabilities for a given target,
452+
/// for translating a user's watchpoint request into hardware
453+
/// capable watchpoint resources.
454+
FLAGS_ENUM(WatchpointHardwareFeature){
455+
/// lldb will fall back to a default that assumes the target
456+
/// can watch up to pointer-size power-of-2 regions, aligned to
457+
/// power-of-2.
458+
eWatchpointHardwareFeatureUnknown = (1u << 0),
459+
460+
/// Intel systems can watch 1, 2, 4, or 8 bytes (in 64-bit targets),
461+
/// aligned naturally.
462+
eWatchpointHardwareX86 = (1u << 1),
463+
464+
/// ARM systems with Byte Address Select watchpoints
465+
/// can watch any consecutive series of bytes up to the
466+
/// size of a pointer (4 or 8 bytes), at a pointer-size
467+
/// alignment.
468+
eWatchpointHardwareArmBAS = (1u << 2),
469+
470+
/// ARM systems with MASK watchpoints can watch any power-of-2
471+
/// sized region from 8 bytes to 2 gigabytes, aligned to that
472+
/// same power-of-2 alignment.
473+
eWatchpointHardwareArmMASK = (1u << 3),
474+
};
475+
LLDB_MARK_AS_BITMASK_ENUM(WatchpointHardwareFeature)
476+
451477
/// Programming language type.
452478
///
453479
/// These enumerations use the same language enumerations as the DWARF

lldb/packages/Python/lldbsuite/test/concurrent_base.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,12 @@ def do_thread_actions(
166166

167167
# Initialize the (single) watchpoint on the global variable (g_watchme)
168168
if num_watchpoint_threads + num_delay_watchpoint_threads > 0:
169-
self.runCmd("watchpoint set variable g_watchme")
169+
# The concurrent tests have multiple threads modifying a variable
170+
# with the same value. The default "modify" style watchpoint will
171+
# only report this as 1 hit for all threads, because they all wrote
172+
# the same value. The testsuite needs "write" style watchpoints to
173+
# get the correct number of hits reported.
174+
self.runCmd("watchpoint set variable -w write g_watchme")
170175
for w in self.inferior_target.watchpoint_iter():
171176
self.thread_watchpoint = w
172177
self.assertTrue(

lldb/source/Breakpoint/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ add_lldb_library(lldbBreakpoint NO_PLUGIN_DEPENDENCIES
2121
StoppointSite.cpp
2222
StopPointSiteList.cpp
2323
Watchpoint.cpp
24+
WatchpointAlgorithms.cpp
2425
WatchpointList.cpp
2526
WatchpointOptions.cpp
2627
WatchpointResource.cpp
27-
WatchpointResourceList.cpp
2828

2929
LINK_LIBS
3030
lldbCore

lldb/source/Breakpoint/Watchpoint.cpp

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,16 @@ Watchpoint::Watchpoint(Target &target, lldb::addr_t addr, uint32_t size,
4545
LLDB_LOG_ERROR(GetLog(LLDBLog::Watchpoints), std::move(err),
4646
"Failed to set type: {0}");
4747
} else {
48-
if (auto ts = *type_system_or_err)
49-
m_type =
50-
ts->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size);
51-
else
48+
if (auto ts = *type_system_or_err) {
49+
if (size <= target.GetArchitecture().GetAddressByteSize()) {
50+
m_type =
51+
ts->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8 * size);
52+
} else {
53+
CompilerType clang_uint8_type =
54+
ts->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 8);
55+
m_type = clang_uint8_type.GetArrayType(size);
56+
}
57+
} else
5258
LLDB_LOG_ERROR(GetLog(LLDBLog::Watchpoints), std::move(err),
5359
"Failed to set type: Typesystem is no longer live: {0}");
5460
}
@@ -352,6 +358,20 @@ void Watchpoint::DumpWithLevel(Stream *s,
352358
s->Printf("\n declare @ '%s'", m_decl_str.c_str());
353359
if (!m_watch_spec_str.empty())
354360
s->Printf("\n watchpoint spec = '%s'", m_watch_spec_str.c_str());
361+
if (IsEnabled()) {
362+
if (ProcessSP process_sp = m_target.GetProcessSP()) {
363+
auto &resourcelist = process_sp->GetWatchpointResourceList();
364+
size_t idx = 0;
365+
s->Printf("\n watchpoint resources:");
366+
for (WatchpointResourceSP &wpres : resourcelist.Sites()) {
367+
if (wpres->ConstituentsContains(this)) {
368+
s->Printf("\n #%zu: ", idx);
369+
wpres->Dump(s);
370+
}
371+
idx++;
372+
}
373+
}
374+
}
355375

356376
// Dump the snapshots we have taken.
357377
DumpSnapshots(s, " ");

0 commit comments

Comments
 (0)