diff options
author | Christopher Ferris <cferris@google.com> | 2017-12-04 14:23:58 -0800 |
---|---|---|
committer | Christopher Ferris <cferris@google.com> | 2017-12-04 14:27:34 -0800 |
commit | e714ed27747a433938a02a766b8c8047a5c3b6ce (patch) | |
tree | 837a3f6d160ab764b8dc2cc3652d8ff60f7c6f06 /libunwindstack/tests/MemoryRemoteTest.cpp | |
parent | b4fda18d8353cd4b27aefac832f392ad264facc4 (diff) |
Switch MemoryRemote to use ptrace.
Some processes will fail to read when using process_vm_read, so switch
back to ptrace for now. For example, the system_server process only
gets two frames without this fix.
Fix up some of the remote memory read unit tests to allow passing
even when using ptrace.
Bug: 70160908
Test: All unit tests pass, debuggerd -b <system_server pid> works.
Change-Id: I37c67bf9c480d7268c9fe32dad6a8d78a4020b85
Diffstat (limited to 'libunwindstack/tests/MemoryRemoteTest.cpp')
-rw-r--r-- | libunwindstack/tests/MemoryRemoteTest.cpp | 86 |
1 files changed, 68 insertions, 18 deletions
diff --git a/libunwindstack/tests/MemoryRemoteTest.cpp b/libunwindstack/tests/MemoryRemoteTest.cpp index 8aa4c3f1b..8aa860522 100644 --- a/libunwindstack/tests/MemoryRemoteTest.cpp +++ b/libunwindstack/tests/MemoryRemoteTest.cpp @@ -79,14 +79,13 @@ TEST_F(MemoryRemoteTest, read) { ASSERT_TRUE(Detach(pid)); } -TEST_F(MemoryRemoteTest, Read) { +TEST_F(MemoryRemoteTest, read_partial) { char* mapping = static_cast<char*>( - mmap(nullptr, 2 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); - + mmap(nullptr, 4 * getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); ASSERT_NE(MAP_FAILED, mapping); - - mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE); - memset(mapping + getpagesize() - 1024, 0x4c, 1024); + memset(mapping, 0x4c, 4 * getpagesize()); + ASSERT_EQ(0, mprotect(mapping + getpagesize(), getpagesize(), PROT_NONE)); + ASSERT_EQ(0, munmap(mapping + 3 * getpagesize(), getpagesize())); pid_t pid; if ((pid = fork()) == 0) { @@ -97,19 +96,31 @@ TEST_F(MemoryRemoteTest, Read) { ASSERT_LT(0, pid); TestScopedPidReaper reap(pid); + // Unmap from our process. + ASSERT_EQ(0, munmap(mapping, 3 * getpagesize())); + ASSERT_TRUE(Attach(pid)); MemoryRemote remote(pid); std::vector<uint8_t> dst(4096); - ASSERT_EQ(1024U, remote.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024), - dst.data(), 4096)); - for (size_t i = 0; i < 1024; i++) { + size_t bytes = + remote.Read(reinterpret_cast<uint64_t>(mapping + getpagesize() - 1024), dst.data(), 4096); + // Some read methods can read PROT_NONE maps, allow that. + ASSERT_LE(1024U, bytes); + for (size_t i = 0; i < bytes; i++) { + ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; + } + + // Now verify that reading stops at the end of a map. + bytes = + remote.Read(reinterpret_cast<uint64_t>(mapping + 3 * getpagesize() - 1024), dst.data(), 4096); + ASSERT_EQ(1024U, bytes); + for (size_t i = 0; i < bytes; i++) { ASSERT_EQ(0x4cU, dst[i]) << "Failed at byte " << i; } ASSERT_TRUE(Detach(pid)); - ASSERT_EQ(0, munmap(mapping, 2 * getpagesize())); } TEST_F(MemoryRemoteTest, read_fail) { @@ -192,12 +203,13 @@ TEST_F(MemoryRemoteTest, read_illegal) { ASSERT_TRUE(Detach(pid)); } -TEST_F(MemoryRemoteTest, read_hole) { +TEST_F(MemoryRemoteTest, read_mprotect_hole) { + size_t page_size = getpagesize(); void* mapping = - mmap(nullptr, 3 * 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ASSERT_NE(MAP_FAILED, mapping); - memset(mapping, 0xFF, 3 * 4096); - mprotect(static_cast<char*>(mapping) + 4096, 4096, PROT_NONE); + memset(mapping, 0xFF, 3 * page_size); + ASSERT_EQ(0, mprotect(static_cast<char*>(mapping) + page_size, page_size, PROT_NONE)); pid_t pid; if ((pid = fork()) == 0) { @@ -207,15 +219,53 @@ TEST_F(MemoryRemoteTest, read_hole) { ASSERT_LT(0, pid); TestScopedPidReaper reap(pid); + ASSERT_EQ(0, munmap(mapping, 3 * page_size)); + + ASSERT_TRUE(Attach(pid)); + + MemoryRemote remote(pid); + std::vector<uint8_t> dst(getpagesize() * 4, 0xCC); + size_t read_size = remote.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), page_size * 3); + // Some read methods can read PROT_NONE maps, allow that. + ASSERT_LE(page_size, read_size); + for (size_t i = 0; i < read_size; ++i) { + ASSERT_EQ(0xFF, dst[i]); + } + for (size_t i = read_size; i < dst.size(); ++i) { + ASSERT_EQ(0xCC, dst[i]); + } +} + +TEST_F(MemoryRemoteTest, read_munmap_hole) { + size_t page_size = getpagesize(); + void* mapping = + mmap(nullptr, 3 * getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + ASSERT_NE(MAP_FAILED, mapping); + memset(mapping, 0xFF, 3 * page_size); + ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + page_size, page_size)); + + pid_t pid; + if ((pid = fork()) == 0) { + while (true) + ; + exit(1); + } + ASSERT_LT(0, pid); + TestScopedPidReaper reap(pid); + + ASSERT_EQ(0, munmap(mapping, page_size)); + ASSERT_EQ(0, munmap(static_cast<char*>(mapping) + 2 * page_size, page_size)); + ASSERT_TRUE(Attach(pid)); MemoryRemote remote(pid); - std::vector<uint8_t> dst(4096 * 3, 0xCC); - ASSERT_EQ(4096U, remote.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), 4096 * 3)); - for (size_t i = 0; i < 4096; ++i) { + std::vector<uint8_t> dst(getpagesize() * 4, 0xCC); + size_t read_size = remote.Read(reinterpret_cast<uintptr_t>(mapping), dst.data(), page_size * 3); + ASSERT_EQ(page_size, read_size); + for (size_t i = 0; i < read_size; ++i) { ASSERT_EQ(0xFF, dst[i]); } - for (size_t i = 4096; i < 4096 * 3; ++i) { + for (size_t i = read_size; i < dst.size(); ++i) { ASSERT_EQ(0xCC, dst[i]); } } |