xref: /llvm-project/lldb/unittests/Breakpoint/WatchpointAlgorithmsTests.cpp (revision 7dd790db8b77c4a833c06632e903dc4f13877a64)
1 //===-- WatchpointAlgorithmsTests.cpp -------------------------------------===//
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 #include "gtest/gtest.h"
10 
11 #include "lldb/Breakpoint/WatchpointAlgorithms.h"
12 
13 #include <utility>
14 #include <vector>
15 
16 using namespace lldb;
17 using namespace lldb_private;
18 
19 class WatchpointAlgorithmsTest : public WatchpointAlgorithms {
20 public:
21   using WatchpointAlgorithms::PowerOf2Watchpoints;
22   using WatchpointAlgorithms::Region;
23 };
24 
25 struct testcase {
26   WatchpointAlgorithmsTest::Region user; // What the user requested
27   std::vector<WatchpointAlgorithmsTest::Region>
28       hw; // The hardware watchpoints we'll use
29 };
30 
check_testcase(testcase test,std::vector<WatchpointAlgorithmsTest::Region> result,size_t min_byte_size,size_t max_byte_size,uint32_t address_byte_size)31 void check_testcase(testcase test,
32                     std::vector<WatchpointAlgorithmsTest::Region> result,
33                     size_t min_byte_size, size_t max_byte_size,
34                     uint32_t address_byte_size) {
35 
36   EXPECT_EQ(result.size(), test.hw.size());
37   for (size_t i = 0; i < result.size(); i++) {
38     EXPECT_EQ(result[i].addr, test.hw[i].addr);
39     EXPECT_EQ(result[i].size, test.hw[i].size);
40   }
41 }
42 
TEST(WatchpointAlgorithmsTests,PowerOf2Watchpoints)43 TEST(WatchpointAlgorithmsTests, PowerOf2Watchpoints) {
44 
45   // clang-format off
46   std::vector<testcase> doubleword_max = {
47 #if defined(__LP64__)
48     // These two tests don't work if lldb is built on
49     // a 32-bit system (likely with a 32-bit size_t).
50     // A 32-bit lldb debugging a 64-bit process isn't
51     // critical right now.
52     {
53       {0x7fffffffe83b, 1},
54       {{0x7fffffffe83b, 1}}
55     },
56     {
57       {0x7fffffffe838, 2},
58       {{0x7fffffffe838, 2}}
59     },
60 #endif
61     {
62       {0x1012, 8},
63       {{0x1010, 8}, {0x1018, 8}}
64     },
65     {
66       {0x1002, 4},
67       {{0x1000, 8}}
68     },
69     {
70       {0x1006, 4},
71       {{0x1004, 4}, {0x1008, 4}}
72     },
73     {
74       {0x1006, 8},
75       {{0x1000, 8}, {0x1008, 8}}
76     },
77     {
78       {0x1000, 24},
79       {{0x1000, 8}, {0x1008, 8}, {0x1010, 8}}
80     },
81     {
82       {0x1014, 26},
83       {{0x1010, 8}, {0x1018, 8}, {0x1020, 8}, {0x1028, 8}}
84     },
85   };
86   // clang-format on
87   for (testcase test : doubleword_max) {
88     addr_t user_addr = test.user.addr;
89     size_t user_size = test.user.size;
90     size_t min_byte_size = 1;
91     size_t max_byte_size = 8;
92     size_t address_byte_size = 8;
93     auto result = WatchpointAlgorithmsTest::PowerOf2Watchpoints(
94         user_addr, user_size, min_byte_size, max_byte_size, address_byte_size);
95 
96     check_testcase(test, result, min_byte_size, max_byte_size,
97                    address_byte_size);
98   }
99 
100   // clang-format off
101   std::vector<testcase> word_max = {
102     {
103       {0x00411050, 4},
104       {{0x00411050, 4}}
105     },
106     {
107       {0x1002, 4},
108       {{0x1000, 4}, {0x1004, 4}}
109     },
110   };
111   // clang-format on
112   for (testcase test : word_max) {
113     addr_t user_addr = test.user.addr;
114     size_t user_size = test.user.size;
115     size_t min_byte_size = 1;
116     size_t max_byte_size = 4;
117     size_t address_byte_size = 4;
118     auto result = WatchpointAlgorithmsTest::PowerOf2Watchpoints(
119         user_addr, user_size, min_byte_size, max_byte_size, address_byte_size);
120 
121     check_testcase(test, result, min_byte_size, max_byte_size,
122                    address_byte_size);
123   }
124 
125   // clang-format off
126   std::vector<testcase> twogig_max = {
127     {
128       {0x1010, 16},
129       {{0x1010, 16}}
130     },
131     {
132       {0x1010, 24},
133       {{0x1000, 64}}
134     },
135 
136     // We increase 36 to the aligned 64 byte size, but
137     // 0x1000-0x1040 doesn't cover the requested region.  Then
138     // we expand to 128 bytes starting at 0x1000 that does
139     // cover it.  Is this a good tradeoff for a 36 byte region?
140     {
141       {0x1024, 36},
142       {{0x1000, 128}}
143     },
144     {
145       {0x1000, 192},
146       {{0x1000, 256}}
147     },
148     {
149       {0x1080, 192},
150       {{0x1000, 512}}
151     },
152 
153     // In this case, our aligned size is 128, and increasing it to 256
154     // still can't watch the requested region.  The algorithm
155     // falls back to using two 128 byte watchpoints.
156     // The alternative would be to use a 1024B watchpoint
157     // starting at 0x1000, to watch this 120 byte user request.
158     //
159     // This still isn't ideal.  The user is asking to watch 0x12e0-1358
160     // and could be optimally handled by a
161     // 16-byte watchpoint at 0x12e0 and a 128-byte watchpoint at 0x1300
162     {
163       {0x12e0, 120},
164       {{0x1280, 128}, {0x1300, 128}}
165     },
166   };
167   // clang-format on
168   for (testcase test : twogig_max) {
169     addr_t user_addr = test.user.addr;
170     size_t user_size = test.user.size;
171     size_t min_byte_size = 1;
172     size_t max_byte_size = INT32_MAX;
173     size_t address_byte_size = 8;
174     auto result = WatchpointAlgorithmsTest::PowerOf2Watchpoints(
175         user_addr, user_size, min_byte_size, max_byte_size, address_byte_size);
176 
177     check_testcase(test, result, min_byte_size, max_byte_size,
178                    address_byte_size);
179   }
180 
181 }
182