summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'libunwindstack/tests/MemoryRemoteTest.cpp')
-rw-r--r--libunwindstack/tests/MemoryRemoteTest.cpp144
1 files changed, 134 insertions, 10 deletions
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp
index a66d0c550..8aa860522 100644
--- a/libunwindstack/tests/MemoryRemoteTest.cpp
+++ b/libunwindstack/tests/MemoryRemoteTest.cpp
@@ -71,7 +71,7 @@ TEST_F(MemoryRemoteTest, read) {
71 MemoryRemote remote(pid); 71 MemoryRemote remote(pid);
72 72
73 std::vector<uint8_t> dst(1024); 73 std::vector<uint8_t> dst(1024);
74 ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024)); 74 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src.data()), dst.data(), 1024));
75 for (size_t i = 0; i < 1024; i++) { 75 for (size_t i = 0; i < 1024; i++) {
76 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; 76 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
77 } 77 }
@@ -79,6 +79,50 @@ TEST_F(MemoryRemoteTest, read) {
79 ASSERT_TRUE(Detach(pid)); 79 ASSERT_TRUE(Detach(pid));
80} 80}
81 81
82TEST_F(MemoryRemoteTest, read_partial) {
83 char* mapping = static_cast<char*>(
84 mmap(nullptr, 4 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
85 ASSERT_NE(MAP_FAILED, mapping);
86 memset(mapping, 0x4c, 4 * getpagesize());
87 ASSERT_EQ(0, mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE));
88 ASSERT_EQ(0, munmap(mapping + 3 * getpagesize(), getpagesize()));
89
90 pid_t pid;
91 if ((pid = fork()) == 0) {
92 while (true)
93 ;
94 exit(1);
95 }
96 ASSERT_LT(0, pid);
97 TestScopedPidReaper reap(pid);
98
99 // Unmap from our process.
100 ASSERT_EQ(0, munmap(mapping, 3 * getpagesize()));
101
102 ASSERT_TRUE(Attach(pid));
103
104 MemoryRemote remote(pid);
105
106 std::vector<uint8_t> dst(4096);
107 size_t bytes =
108 remote.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024), dst.data(), 4096);
109 // Some read methods can read PROT_NONE maps, allow that.
110 ASSERT_LE(1024U, bytes);
111 for (size_t i = 0; i < bytes; i++) {
112 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
113 }
114
115 // Now verify that reading stops at the end of a map.
116 bytes =
117 remote.Read(reinterpret_cast<uint64_t>(mapping + 3 * getpagesize() - 1024), dst.data(), 4096);
118 ASSERT_EQ(1024U, bytes);
119 for (size_t i = 0; i < bytes; i++) {
120 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
121 }
122
123 ASSERT_TRUE(Detach(pid));
124}
125
82TEST_F(MemoryRemoteTest, read_fail) { 126TEST_F(MemoryRemoteTest, read_fail) {
83 int pagesize = getpagesize(); 127 int pagesize = getpagesize();
84 void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0); 128 void* src = mmap(nullptr, pagesize * 2, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1, 0);
@@ -101,17 +145,17 @@ TEST_F(MemoryRemoteTest, read_fail) {
101 MemoryRemote remote(pid); 145 MemoryRemote remote(pid);
102 146
103 std::vector<uint8_t> dst(pagesize); 147 std::vector<uint8_t> dst(pagesize);
104 ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src), dst.data(), pagesize)); 148 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src), dst.data(), pagesize));
105 for (size_t i = 0; i < 1024; i++) { 149 for (size_t i = 0; i < 1024; i++) {
106 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; 150 ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i;
107 } 151 }
108 152
109 ASSERT_FALSE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1)); 153 ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize, dst.data(), 1));
110 ASSERT_TRUE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1)); 154 ASSERT_TRUE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 1, dst.data(), 1));
111 ASSERT_FALSE(remote.Read(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8)); 155 ASSERT_FALSE(remote.ReadFully(reinterpret_cast<uint64_t>(src) + pagesize - 4, dst.data(), 8));
112 156
113 // Check overflow condition is caught properly. 157 // Check overflow condition is caught properly.
114 ASSERT_FALSE(remote.Read(UINT64_MAX - 100, dst.data(), 200)); 158 ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
115 159
116 ASSERT_EQ(0, munmap(src, pagesize)); 160 ASSERT_EQ(0, munmap(src, pagesize));
117 161
@@ -119,11 +163,24 @@ TEST_F(MemoryRemoteTest, read_fail) {
119} 163}
120 164
121TEST_F(MemoryRemoteTest, read_overflow) { 165TEST_F(MemoryRemoteTest, read_overflow) {
122 MemoryFakeRemote remote; 166 pid_t pid;
167 if ((pid = fork()) == 0) {
168 while (true)
169 ;
170 exit(1);
171 }
172 ASSERT_LT(0, pid);
173 TestScopedPidReaper reap(pid);
174
175 ASSERT_TRUE(Attach(pid));
176
177 MemoryRemote remote(pid);
123 178
124 // Check overflow condition is caught properly. 179 // Check overflow condition is caught properly.
125 std::vector<uint8_t> dst(200); 180 std::vector<uint8_t> dst(200);
126 ASSERT_FALSE(remote.Read(UINT64_MAX - 100, dst.data(), 200)); 181 ASSERT_FALSE(remote.ReadFully(UINT64_MAX - 100, dst.data(), 200));
182
183 ASSERT_TRUE(Detach(pid));
127} 184}
128 185
129TEST_F(MemoryRemoteTest, read_illegal) { 186TEST_F(MemoryRemoteTest, read_illegal) {
@@ -140,10 +197,77 @@ TEST_F(MemoryRemoteTest, read_illegal) {
140 MemoryRemote remote(pid); 197 MemoryRemote remote(pid);
141 198
142 std::vector<uint8_t> dst(100); 199 std::vector<uint8_t> dst(100);
143 ASSERT_FALSE(remote.Read(0, dst.data(), 1)); 200 ASSERT_FALSE(remote.ReadFully(0, dst.data(), 1));
144 ASSERT_FALSE(remote.Read(0, dst.data(), 100)); 201 ASSERT_FALSE(remote.ReadFully(0, dst.data(), 100));
145 202
146 ASSERT_TRUE(Detach(pid)); 203 ASSERT_TRUE(Detach(pid));
147} 204}
148 205
206TEST_F(MemoryRemoteTest, read_mprotect_hole) {
207 size_t page_size = getpagesize();
208 void* mapping =
209 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
210 ASSERT_NE(MAP_FAILED, mapping);
211 memset(mapping, 0xFF, 3 * page_size);
212 ASSERT_EQ(0, mprotect(static_cast<char*>(mapping) + page_size, page_size, PROT_NONE));
213
214 pid_t pid;
215 if ((pid = fork()) == 0) {
216 while (true);
217 exit(1);
218 }
219 ASSERT_LT(0, pid);
220 TestScopedPidReaper reap(pid);
221
222 ASSERT_EQ(0, munmap(mapping, 3 * page_size));
223
224 ASSERT_TRUE(Attach(pid));
225
226 MemoryRemote remote(pid);
227 std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
228 size_t read_size = remote.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), page_size * 3);
229 // Some read methods can read PROT_NONE maps, allow that.
230 ASSERT_LE(page_size, read_size);
231 for (size_t i = 0; i < read_size; ++i) {
232 ASSERT_EQ(0xFF, dst[i]);
233 }
234 for (size_t i = read_size; i < dst.size(); ++i) {
235 ASSERT_EQ(0xCC, dst[i]);
236 }
237}
238
239TEST_F(MemoryRemoteTest, read_munmap_hole) {
240 size_t page_size = getpagesize();
241 void* mapping =
242 mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
243 ASSERT_NE(MAP_FAILED, mapping);
244 memset(mapping, 0xFF, 3 * page_size);
245 ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + page_size, page_size));
246
247 pid_t pid;
248 if ((pid = fork()) == 0) {
249 while (true)
250 ;
251 exit(1);
252 }
253 ASSERT_LT(0, pid);
254 TestScopedPidReaper reap(pid);
255
256 ASSERT_EQ(0, munmap(mapping, page_size));
257 ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + 2 * page_size, page_size));
258
259 ASSERT_TRUE(Attach(pid));
260
261 MemoryRemote remote(pid);
262 std::vector<uint8_t> dst(getpagesize() * 4, 0xCC);
263 size_t read_size = remote.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), page_size * 3);
264 ASSERT_EQ(page_size, read_size);
265 for (size_t i = 0; i < read_size; ++i) {
266 ASSERT_EQ(0xFF, dst[i]);
267 }
268 for (size_t i = read_size; i < dst.size(); ++i) {
269 ASSERT_EQ(0xCC, dst[i]);
270 }
271}
272
149} // namespace unwindstack 273} // namespace unwindstack