1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdlib.h>
18
19 #include <memory>
20 #include <string>
21
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <android-base/stringprintf.h>
25 #include <gtest/gtest.h>
26 #include <unwindstack/Memory.h>
27
28 #include "libdebuggerd/utility.h"
29
30 #include "log_fake.h"
31
GetMemoryString(uintptr_t addr,const std::vector<uint64_t> & data)32 std::string GetMemoryString(uintptr_t addr, const std::vector<uint64_t>& data) {
33 // Must be even number of data values.
34 CHECK((data.size() & 1) == 0);
35
36 std::string str;
37 for (size_t i = 0; i < data.size(); i += 2) {
38 str += " ";
39 std::string ascii_str = "";
40 for (size_t j = 0; j < 2; j++) {
41 for (size_t k = 0; k < 8; k++) {
42 uint8_t c = (data[i + j] >> (k * 8)) & 0xff;
43 if (c >= 0x20 && c < 0x7f) {
44 ascii_str += c;
45 } else {
46 ascii_str += '.';
47 }
48 }
49 }
50 #if defined(__LP64__)
51 str += android::base::StringPrintf("%016zx %016zx %016zx ", addr, data[i], data[i + 1]);
52 #else
53 str += android::base::StringPrintf(
54 "%08zx %08zx %08zx %08zx %08zx ", addr, static_cast<uintptr_t>(data[i] & 0xffffffff),
55 static_cast<uintptr_t>(data[i] >> 32), static_cast<uintptr_t>(data[i + 1] & 0xffffffff),
56 static_cast<uintptr_t>(data[i + 1] >> 32));
57 #endif
58 str += ascii_str + "\n";
59 addr += 0x10;
60 }
61 return str;
62 }
63
GetDefaultData()64 const std::vector<uint64_t>& GetDefaultData() {
65 static std::vector<uint64_t> data(
66 {0x0706050403020100UL, 0x0f0e0d0c0b0a0908UL, 0x1716151413121110UL, 0x1f1e1d1c1b1a1918UL,
67 0x2726252423222120UL, 0x2f2e2d2c2b2a2928UL, 0x3736353433323130UL, 0x3f3e3d3c3b3a3938UL,
68 0x4746454443424140UL, 0x4f4e4d4c4b4a4948UL, 0x5756555453525150UL, 0x5f5e5d5c5b5a5958UL,
69 0x6766656463626160UL, 0x6f6e6d6c6b6a6968UL, 0x7776757473727170UL, 0x7f7e7d7c7b7a7978UL,
70 0x8786858483828180UL, 0x8f8e8d8c8b8a8988UL, 0x9796959493929190UL, 0x9f9e9d9c9b9a9998UL,
71 0xa7a6a5a4a3a2a1a0UL, 0xafaeadacabaaa9a8UL, 0xb7b6b5b4b3b2b1b0UL, 0xbfbebdbcbbbab9b8UL,
72 0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL, 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL,
73 0xe7e6e5e4e3e2e1e0UL, 0xefeeedecebeae9e8UL, 0xf7f6f5f4f3f2f1f0UL, 0xfffefdfcfbfaf9f8UL});
74 return data;
75 }
76
GetFullDumpString()77 std::string GetFullDumpString() {
78 std::string str = "\nmemory near r1:\n";
79 str += GetMemoryString(0x12345650U, GetDefaultData());
80 return str;
81 }
82
GetPartialDumpString()83 std::string GetPartialDumpString() {
84 std::string str = "\nmemory near pc:\n";
85 std::vector<uint64_t> data = GetDefaultData();
86 data.resize(12);
87 str += GetMemoryString(0x123455e0U, data);
88 return str;
89 }
90
91 class MemoryMock : public unwindstack::Memory {
92 public:
93 virtual ~MemoryMock() = default;
94
Read(uint64_t addr,void * buffer,size_t bytes)95 virtual size_t Read(uint64_t addr, void* buffer, size_t bytes) override {
96 size_t offset = 0;
97 if (last_read_addr_ > 0) {
98 offset = addr - last_read_addr_;
99 }
100 size_t bytes_available = 0;
101 if (offset < buffer_.size()) {
102 bytes_available = buffer_.size() - offset;
103 }
104
105 if (partial_read_) {
106 bytes = std::min(bytes, bytes_partial_read_);
107 bytes_partial_read_ -= bytes;
108 partial_read_ = bytes_partial_read_;
109 } else if (bytes > bytes_available) {
110 bytes = bytes_available;
111 }
112
113 if (bytes > 0) {
114 memcpy(buffer, buffer_.data() + offset, bytes);
115 }
116
117 last_read_addr_ = addr;
118 return bytes;
119 }
120
SetReadData(uint8_t * buffer,size_t bytes)121 void SetReadData(uint8_t* buffer, size_t bytes) {
122 buffer_.resize(bytes);
123 memcpy(buffer_.data(), buffer, bytes);
124 bytes_partial_read_ = 0;
125 last_read_addr_ = 0;
126 }
127
SetPartialReadAmount(size_t bytes)128 void SetPartialReadAmount(size_t bytes) {
129 if (bytes > buffer_.size()) {
130 abort();
131 }
132 partial_read_ = true;
133 bytes_partial_read_ = bytes;
134 }
135
136 private:
137 std::vector<uint8_t> buffer_;
138 bool partial_read_ = false;
139 size_t bytes_partial_read_ = 0;
140 uintptr_t last_read_addr_ = 0;
141 };
142
143 class DumpMemoryTest : public ::testing::Test {
144 protected:
SetUp()145 virtual void SetUp() {
146 memory_mock_ = std::make_unique<MemoryMock>();
147
148 char tmp_file[256];
149 const char data_template[] = "/data/local/tmp/debuggerd_memory_testXXXXXX";
150 memcpy(tmp_file, data_template, sizeof(data_template));
151 int tombstone_fd = mkstemp(tmp_file);
152 if (tombstone_fd == -1) {
153 const char tmp_template[] = "/tmp/debuggerd_memory_testXXXXXX";
154 memcpy(tmp_file, tmp_template, sizeof(tmp_template));
155 tombstone_fd = mkstemp(tmp_file);
156 if (tombstone_fd == -1) {
157 abort();
158 }
159 }
160 if (unlink(tmp_file) == -1) {
161 abort();
162 }
163
164 log_.tfd = tombstone_fd;
165 log_.amfd_data = nullptr;
166 log_.crashed_tid = 12;
167 log_.current_tid = 12;
168 log_.should_retrieve_logcat = false;
169
170 resetLogs();
171 }
172
TearDown()173 virtual void TearDown() {
174 if (log_.tfd >= 0) {
175 close(log_.tfd);
176 }
177 memory_mock_.reset();
178 }
179
180 std::unique_ptr<MemoryMock> memory_mock_;
181
182 log_t log_;
183 };
184
TEST_F(DumpMemoryTest,aligned_addr)185 TEST_F(DumpMemoryTest, aligned_addr) {
186 uint8_t buffer[256];
187 for (size_t i = 0; i < sizeof(buffer); i++) {
188 buffer[i] = i;
189 }
190 memory_mock_->SetReadData(buffer, sizeof(buffer));
191
192 dump_memory(&log_, memory_mock_.get(), 0x12345678, "memory near r1");
193
194 std::string tombstone_contents;
195 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
196 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
197 ASSERT_EQ(GetFullDumpString(), tombstone_contents);
198
199 // Verify that the log buf is empty, and no error messages.
200 ASSERT_STREQ("", getFakeLogBuf().c_str());
201 ASSERT_STREQ("", getFakeLogPrint().c_str());
202 }
203
TEST_F(DumpMemoryTest,partial_read)204 TEST_F(DumpMemoryTest, partial_read) {
205 uint8_t buffer[256];
206 for (size_t i = 0; i < sizeof(buffer); i++) {
207 buffer[i] = i;
208 }
209 memory_mock_->SetReadData(buffer, sizeof(buffer));
210 memory_mock_->SetPartialReadAmount(96);
211
212 dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
213
214 std::string tombstone_contents;
215 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
216 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
217 ASSERT_EQ(GetFullDumpString(), tombstone_contents);
218
219 // Verify that the log buf is empty, and no error messages.
220 ASSERT_STREQ("", getFakeLogBuf().c_str());
221 ASSERT_STREQ("", getFakeLogPrint().c_str());
222 }
223
TEST_F(DumpMemoryTest,unaligned_addr)224 TEST_F(DumpMemoryTest, unaligned_addr) {
225 uint8_t buffer[256];
226 for (size_t i = 0; i < sizeof(buffer); i++) {
227 buffer[i] = i;
228 }
229 memory_mock_->SetReadData(buffer, sizeof(buffer));
230
231 dump_memory(&log_, memory_mock_.get(), 0x12345679, "memory near r1");
232
233 std::string tombstone_contents;
234 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
235 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
236 ASSERT_EQ(GetFullDumpString(), tombstone_contents);
237
238 // Verify that the log buf is empty, and no error messages.
239 ASSERT_STREQ("", getFakeLogBuf().c_str());
240 ASSERT_STREQ("", getFakeLogPrint().c_str());
241 }
242
TEST_F(DumpMemoryTest,memory_unreadable)243 TEST_F(DumpMemoryTest, memory_unreadable) {
244 dump_memory(&log_, memory_mock_.get(), 0xa2345678, "memory near pc");
245
246 std::string tombstone_contents;
247 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
248 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
249 ASSERT_STREQ("", tombstone_contents.c_str());
250
251 // Verify that the log buf is empty, and no error messages.
252 ASSERT_STREQ("", getFakeLogBuf().c_str());
253 ASSERT_STREQ("", getFakeLogPrint().c_str());
254 }
255
TEST_F(DumpMemoryTest,memory_partially_unreadable)256 TEST_F(DumpMemoryTest, memory_partially_unreadable) {
257 uint8_t buffer[104];
258 for (size_t i = 0; i < sizeof(buffer); i++) {
259 buffer[i] = i;
260 }
261 memory_mock_->SetReadData(buffer, sizeof(buffer));
262
263 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
264
265 std::string tombstone_contents;
266 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
267 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
268 ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
269
270 // Verify that the log buf is empty, and no error messages.
271 ASSERT_STREQ("", getFakeLogBuf().c_str());
272 ASSERT_STREQ("", getFakeLogPrint().c_str());
273 }
274
TEST_F(DumpMemoryTest,memory_partially_unreadable_unaligned_return)275 TEST_F(DumpMemoryTest, memory_partially_unreadable_unaligned_return) {
276 uint8_t buffer[104];
277 for (size_t i = 0; i < sizeof(buffer); i++) {
278 buffer[i] = i;
279 }
280 memory_mock_->SetReadData(buffer, sizeof(buffer));
281 memory_mock_->SetPartialReadAmount(102);
282
283 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
284
285 std::string tombstone_contents;
286 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
287 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
288 ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
289
290 #if defined(__LP64__)
291 ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 8\n", getFakeLogPrint().c_str());
292 #else
293 ASSERT_STREQ("6 DEBUG Bytes read 102, is not a multiple of 4\n", getFakeLogPrint().c_str());
294 #endif
295
296 // Verify that the log buf is empty, and no error messages.
297 ASSERT_STREQ("", getFakeLogBuf().c_str());
298 }
299
TEST_F(DumpMemoryTest,memory_partially_unreadable_two_unaligned_reads)300 TEST_F(DumpMemoryTest, memory_partially_unreadable_two_unaligned_reads) {
301 uint8_t buffer[106];
302 for (size_t i = 0; i < sizeof(buffer); i++) {
303 buffer[i] = i;
304 }
305 memory_mock_->SetReadData(buffer, sizeof(buffer));
306 memory_mock_->SetPartialReadAmount(45);
307
308 dump_memory(&log_, memory_mock_.get(), 0x12345600, "memory near pc");
309
310 std::string tombstone_contents;
311 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
312 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
313 ASSERT_EQ(GetPartialDumpString(), tombstone_contents);
314
315 #if defined(__LP64__)
316 ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 8\n"
317 "6 DEBUG Bytes after second read 106, is not a multiple of 8\n",
318 getFakeLogPrint().c_str());
319 #else
320 ASSERT_STREQ("6 DEBUG Bytes read 45, is not a multiple of 4\n"
321 "6 DEBUG Bytes after second read 106, is not a multiple of 4\n",
322 getFakeLogPrint().c_str());
323 #endif
324
325 // Verify that the log buf is empty, and no error messages.
326 ASSERT_STREQ("", getFakeLogBuf().c_str());
327 }
328
TEST_F(DumpMemoryTest,address_low_fence)329 TEST_F(DumpMemoryTest, address_low_fence) {
330 uint8_t buffer[256];
331 memset(buffer, 0, sizeof(buffer));
332 memory_mock_->SetReadData(buffer, sizeof(buffer));
333
334 dump_memory(&log_, memory_mock_.get(), 0x1000, "memory near r1");
335
336 std::string tombstone_contents;
337 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
338 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
339 std::string expected_dump = "\nmemory near r1:\n";
340 expected_dump += GetMemoryString(0x1000, std::vector<uint64_t>(32, 0UL));
341 ASSERT_EQ(expected_dump, tombstone_contents);
342
343 // Verify that the log buf is empty, and no error messages.
344 ASSERT_STREQ("", getFakeLogBuf().c_str());
345 ASSERT_STREQ("", getFakeLogPrint().c_str());
346 }
347
TEST_F(DumpMemoryTest,memory_address_too_high)348 TEST_F(DumpMemoryTest, memory_address_too_high) {
349 uint8_t buffer[256];
350 memset(buffer, 0, sizeof(buffer));
351 memory_mock_->SetReadData(buffer, sizeof(buffer));
352
353 #if defined(__LP64__)
354 dump_memory(&log_, memory_mock_.get(), -32, "memory near r1");
355 dump_memory(&log_, memory_mock_.get(), -208, "memory near r1");
356 #else
357 dump_memory(&log_, memory_mock_.get(), 0x100000000 - 32, "memory near r1");
358 dump_memory(&log_, memory_mock_.get(), 0x100000000 - 208, "memory near r1");
359 #endif
360
361 std::string tombstone_contents;
362 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
363 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
364 ASSERT_STREQ("", tombstone_contents.c_str());
365
366 // Verify that the log buf is empty, and no error messages.
367 ASSERT_STREQ("", getFakeLogBuf().c_str());
368 ASSERT_STREQ("", getFakeLogPrint().c_str());
369 }
370
TEST_F(DumpMemoryTest,memory_address_nearly_too_high)371 TEST_F(DumpMemoryTest, memory_address_nearly_too_high) {
372 uint8_t buffer[256];
373 for (size_t i = 0; i < sizeof(buffer); i++) {
374 buffer[i] = i;
375 }
376 memory_mock_->SetReadData(buffer, sizeof(buffer));
377
378 #if defined(__LP64__)
379 dump_memory(&log_, memory_mock_.get(), -224, "memory near r4");
380 #else
381 dump_memory(&log_, memory_mock_.get(), 0x100000000 - 224, "memory near r4");
382 #endif
383
384 std::string tombstone_contents;
385 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
386 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
387 std::string expected_dump = "\nmemory near r4:\n";
388 uintptr_t addr;
389 #if defined(__aarch64__)
390 addr = 0x00ffffffffffff00UL;
391 #elif defined(__LP64__)
392 addr = 0xffffffffffffff00UL;
393 #else
394 addr = 0xffffff00UL;
395 #endif
396 expected_dump += GetMemoryString(addr, GetDefaultData());
397 ASSERT_EQ(expected_dump, tombstone_contents);
398
399 // Verify that the log buf is empty, and no error messages.
400 ASSERT_STREQ("", getFakeLogBuf().c_str());
401 ASSERT_STREQ("", getFakeLogPrint().c_str());
402 }
403
TEST_F(DumpMemoryTest,first_read_empty)404 TEST_F(DumpMemoryTest, first_read_empty) {
405 uint8_t buffer[256];
406 for (size_t i = 0; i < sizeof(buffer); i++) {
407 buffer[i] = i;
408 }
409 memory_mock_->SetReadData(buffer, sizeof(buffer));
410 memory_mock_->SetPartialReadAmount(0);
411
412 size_t page_size = sysconf(_SC_PAGE_SIZE);
413 uintptr_t addr = 0x10000020 + page_size - 120;
414 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
415
416 std::string tombstone_contents;
417 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
418 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
419 std::string expected_dump = "\nmemory near r4:\n";
420 expected_dump += GetMemoryString(
421 0x10000000 + page_size,
422 std::vector<uint64_t>{
423 0x8786858483828180UL, 0x8f8e8d8c8b8a8988UL, 0x9796959493929190UL, 0x9f9e9d9c9b9a9998UL,
424 0xa7a6a5a4a3a2a1a0UL, 0xafaeadacabaaa9a8UL, 0xb7b6b5b4b3b2b1b0UL, 0xbfbebdbcbbbab9b8UL,
425 0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL, 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL,
426 0xe7e6e5e4e3e2e1e0UL, 0xefeeedecebeae9e8UL, 0xf7f6f5f4f3f2f1f0UL, 0xfffefdfcfbfaf9f8UL});
427 ASSERT_EQ(expected_dump, tombstone_contents);
428
429 // Verify that the log buf is empty, and no error messages.
430 ASSERT_STREQ("", getFakeLogBuf().c_str());
431 ASSERT_STREQ("", getFakeLogPrint().c_str());
432 }
433
TEST_F(DumpMemoryTest,first_read_empty_second_read_stops)434 TEST_F(DumpMemoryTest, first_read_empty_second_read_stops) {
435 uint8_t buffer[224];
436 for (size_t i = 0; i < sizeof(buffer); i++) {
437 buffer[i] = i;
438 }
439 memory_mock_->SetReadData(buffer, sizeof(buffer));
440 memory_mock_->SetPartialReadAmount(0);
441
442 size_t page_size = sysconf(_SC_PAGE_SIZE);
443 uintptr_t addr = 0x10000020 + page_size - 192;
444 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
445
446 std::string tombstone_contents;
447 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
448 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
449 std::string expected_dump = "\nmemory near r4:\n";
450 expected_dump += GetMemoryString(
451 0x10000000 + page_size, std::vector<uint64_t>{0xc7c6c5c4c3c2c1c0UL, 0xcfcecdcccbcac9c8UL,
452 0xd7d6d5d4d3d2d1d0UL, 0xdfdedddcdbdad9d8UL});
453 ASSERT_EQ(expected_dump, tombstone_contents);
454
455 // Verify that the log buf is empty, and no error messages.
456 ASSERT_STREQ("", getFakeLogBuf().c_str());
457 ASSERT_STREQ("", getFakeLogPrint().c_str());
458 }
459
TEST_F(DumpMemoryTest,first_read_empty_next_page_out_of_range)460 TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range) {
461 uint8_t buffer[256];
462 for (size_t i = 0; i < sizeof(buffer); i++) {
463 buffer[i] = i;
464 }
465 memory_mock_->SetReadData(buffer, sizeof(buffer));
466 memory_mock_->SetPartialReadAmount(0);
467
468 uintptr_t addr = 0x10000020;
469 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
470
471 std::string tombstone_contents;
472 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
473 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
474 ASSERT_STREQ("", tombstone_contents.c_str());
475
476 // Verify that the log buf is empty, and no error messages.
477 ASSERT_STREQ("", getFakeLogBuf().c_str());
478 ASSERT_STREQ("", getFakeLogPrint().c_str());
479 }
480
TEST_F(DumpMemoryTest,first_read_empty_next_page_out_of_range_fence_post)481 TEST_F(DumpMemoryTest, first_read_empty_next_page_out_of_range_fence_post) {
482 uint8_t buffer[256];
483 for (size_t i = 0; i < sizeof(buffer); i++) {
484 buffer[i] = i;
485 }
486 memory_mock_->SetReadData(buffer, sizeof(buffer));
487 memory_mock_->SetPartialReadAmount(0);
488
489 size_t page_size = sysconf(_SC_PAGE_SIZE);
490 uintptr_t addr = 0x10000020 + page_size - 256;
491
492 dump_memory(&log_, memory_mock_.get(), addr, "memory near r4");
493
494 std::string tombstone_contents;
495 ASSERT_TRUE(lseek(log_.tfd, 0, SEEK_SET) == 0);
496 ASSERT_TRUE(android::base::ReadFdToString(log_.tfd, &tombstone_contents));
497 ASSERT_STREQ("", tombstone_contents.c_str());
498
499 // Verify that the log buf is empty, and no error messages.
500 ASSERT_STREQ("", getFakeLogBuf().c_str());
501 ASSERT_STREQ("", getFakeLogPrint().c_str());
502 }
503