Index: third_party/crazy_linker/crazy_linker/src/crazy_linker_proc_maps_unittest.cpp |
diff --git a/third_party/crazy_linker/crazy_linker/src/crazy_linker_proc_maps_unittest.cpp b/third_party/crazy_linker/crazy_linker/src/crazy_linker_proc_maps_unittest.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..57b2bd44183e6e8d7def18c9c566872642972242 |
--- /dev/null |
+++ b/third_party/crazy_linker/crazy_linker/src/crazy_linker_proc_maps_unittest.cpp |
@@ -0,0 +1,218 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "crazy_linker_proc_maps.h" |
+ |
+#include <minitest/minitest.h> |
+#include "crazy_linker_system_mock.h" |
+ |
+namespace crazy { |
+ |
+namespace { |
+ |
+const char kProcMaps0[] = |
+ "4000b000-4000c000 r--p 00000000 00:00 0\n" |
+ "4005c000-40081000 r-xp 00000000 b3:01 141 /system/bin/mksh\n" |
+ "40082000-40083000 r--p 00025000 b3:01 141 /system/bin/mksh\n" |
+ "40083000-40084000 rw-p 00026000 b3:01 141 /system/bin/mksh\n" |
+ "40084000-40088000 rw-p 00000000 00:00 0\n" |
+ "40088000-40090000 r--s 00000000 00:0b 1704 /dev/__properties__\n" |
+ "400eb000-400ec000 r--p 00000000 00:00 0\n" |
+ "40141000-40150000 r-xp 00000000 b3:01 126 /system/bin/linker\n" |
+ "40150000-40151000 r--p 0000e000 b3:01 126 /system/bin/linker\n" |
+ "40151000-40152000 rw-p 0000f000 b3:01 126 /system/bin/linker\n" |
+ "40152000-40153000 rw-p 00000000 00:00 0\n" |
+ "40231000-40277000 r-xp 00001000 b3:01 638 /system/lib/libc.so\n" |
+ "40277000-40279000 r--p 00046000 b3:01 638 /system/lib/libc.so\n" |
+ "40279000-4027b000 rw-p 00048000 b3:01 638 /system/lib/libc.so\n" |
+ "4027b000-40289000 rw-p 00000000 00:00 0\n" |
+ "41e6b000-41e72000 rw-p 00000000 00:00 0 [heap]\n" |
+ "be91b000-be93c000 rw-p 00000000 00:00 0 [stack]\n" |
+ "ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]\n" |
+ ; |
+ |
+class ScopedTestEnv { |
+public: |
+ ScopedTestEnv() : sys_() { |
+ sys_.AddRegularFile("/proc/self/maps", |
+ kProcMaps0, |
+ sizeof(kProcMaps0) - 1); |
+ } |
+ |
+ ~ScopedTestEnv() {} |
+ |
+private: |
+ SystemMock sys_; |
+}; |
+ |
+} // namespace |
+ |
+TEST(ProcMaps, FindElfBinaryForAddress) { |
+ ScopedTestEnv env; |
+ char path[512]; |
+ uintptr_t load_address; |
+ |
+ |
+ EXPECT_TRUE( |
+ FindElfBinaryForAddress(reinterpret_cast<void*>(0x400694c2), |
+ &load_address, path, sizeof(path))); |
+ EXPECT_EQ(0x4005c000, load_address); |
+ EXPECT_STREQ("/system/bin/mksh", path); |
+} |
+ |
+TEST(ProcMaps, FindElfBinaryForAddressWithBadAddress) { |
+ ScopedTestEnv env; |
+ char path[512]; |
+ uintptr_t load_address; |
+ |
+ EXPECT_FALSE( |
+ FindElfBinaryForAddress(reinterpret_cast<void*>(0x50000000), |
+ &load_address, |
+ path, |
+ sizeof(path))); |
+} |
+ |
+TEST(ProcMaps, FindProtectionFlagsForAddress) { |
+ ScopedTestEnv env; |
+ static const struct { |
+ uintptr_t address; |
+ bool success; |
+ int prot; |
+ } kData[] = { |
+ { 0x4000afff, false, 0 }, |
+ { 0x4000b000, true, PROT_READ }, |
+ { 0x4000bfff, true, PROT_READ }, |
+ { 0x4000c000, false, 0 }, |
+ { 0x4005bfff, false, 0 }, |
+ { 0x4005c000, true, PROT_READ | PROT_EXEC }, |
+ { 0x40067832, true, PROT_READ | PROT_EXEC }, |
+ { 0x40082000, true, PROT_READ }, |
+ { 0x40083000, true, PROT_READ | PROT_WRITE }, |
+ { 0x40084000, true, PROT_READ | PROT_WRITE }, |
+ }; |
+ |
+ int prot; |
+ for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { |
+ void* address = reinterpret_cast<void*>(kData[n].address); |
+ TEST_TEXT << minitest::Format("Checking address %p", address); |
+ EXPECT_EQ(kData[n].success, |
+ FindProtectionFlagsForAddress(address, &prot)); |
+ if (kData[n].success) { |
+ TEST_TEXT << minitest::Format("Checking address %p", address); |
+ EXPECT_EQ(kData[n].prot, prot); |
+ } |
+ } |
+} |
+ |
+TEST(ProcMaps, FindLoadAddressForFile) { |
+ ScopedTestEnv env; |
+ static const struct { |
+ bool success; |
+ uintptr_t address; |
+ uintptr_t offset; |
+ const char* name; |
+ } kData[] = { |
+ { true, 0x4005c000, 0, "mksh" }, |
+ { true, 0x40141000, 0, "/system/bin/linker" }, |
+ { false, 0, 0, "[heap]" }, |
+ { false, 0, 0, "bin/mksh" }, |
+ { true, 0x4005c000, 0, "/system/bin/mksh" }, |
+ { true, 0x40231000, 0x1000000, "libc.so" }, |
+ }; |
+ for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { |
+ uintptr_t address, offset; |
+ TEST_TEXT << "Checking " << kData[n].name; |
+ bool success = FindLoadAddressForFile(kData[n].name, |
+ &address, &offset); |
+ EXPECT_EQ(kData[n].success, success); |
+ if (success) { |
+ TEST_TEXT << "Checking " << kData[n].name; |
+ EXPECT_EQ(kData[n].address, address); |
+ |
+ TEST_TEXT << "Checking " << kData[n].name; |
+ EXPECT_EQ(kData[n].offset, offset); |
+ } |
+ } |
+} |
+ |
+TEST(ProcMaps, GetNextEntry) { |
+ ScopedTestEnv env; |
+ // "4000b000-4000c000 r--p 00000000 00:00 0\n" |
+ // "4005c000-40081000 r-xp 00000000 b3:01 141 /system/bin/mksh\n" |
+ // "40082000-40083000 r--p 00025000 b3:01 141 /system/bin/mksh\n" |
+ // "40083000-40084000 rw-p 00026000 b3:01 141 /system/bin/mksh\n" |
+ // "40084000-40088000 rw-p 00000000 00:00 0\n" |
+ // "40088000-40090000 r--s 00000000 00:0b 1704 /dev/__properties__\n" |
+ // "400eb000-400ec000 r--p 00000000 00:00 0\n" |
+ // "40141000-40150000 r-xp 00000000 b3:01 126 /system/bin/linker\n" |
+ // "40150000-40151000 r--p 0000e000 b3:01 126 /system/bin/linker\n" |
+ // "40151000-40152000 rw-p 0000f000 b3:01 126 /system/bin/linker\n" |
+ // "40152000-40153000 rw-p 00000000 00:00 0\n" |
+ // "40231000-40277000 r-xp 00001000 b3:01 638 /system/lib/libc.so\n" |
+ // "40277000-40279000 r--p 00046000 b3:01 638 /system/lib/libc.so\n" |
+ // "40279000-4027b000 rw-p 00048000 b3:01 638 /system/lib/libc.so\n" |
+ // "4027b000-40289000 rw-p 00000000 00:00 0\n" |
+ // "41e6b000-41e72000 rw-p 00000000 00:00 0 [heap]\n" |
+ // "be91b000-be93c000 rw-p 00000000 00:00 0 [stack]\n" |
+ // "ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]\n" |
+ static const struct { |
+ size_t vma_start; |
+ size_t vma_end; |
+ int prot_flags; |
+ size_t load_offset; |
+ const char* path; |
+ } kData[] = { |
+ { 0x4000b000, 0x4000c000, PROT_READ, 0, NULL }, |
+ { 0x4005c000, 0x40081000, PROT_READ|PROT_EXEC, 0, "/system/bin/mksh" }, |
+ { 0x40082000, 0x40083000, PROT_READ, 0x25000 * PAGE_SIZE, "/system/bin/mksh" }, |
+ { 0x40083000, 0x40084000, PROT_READ|PROT_WRITE, 0x26000 * PAGE_SIZE, "/system/bin/mksh" }, |
+ { 0x40084000, 0x40088000, PROT_READ|PROT_WRITE, 0, NULL }, |
+ { 0x40088000, 0x40090000, PROT_READ, 0, "/dev/__properties__" }, |
+ { 0x400eb000, 0x400ec000, PROT_READ, 0, NULL }, |
+ { 0x40141000, 0x40150000, PROT_READ|PROT_EXEC, 0, "/system/bin/linker" }, |
+ { 0x40150000, 0x40151000, PROT_READ, 0xe000 * PAGE_SIZE, "/system/bin/linker" }, |
+ { 0x40151000, 0x40152000, PROT_READ|PROT_WRITE, 0xf000 * PAGE_SIZE, "/system/bin/linker" }, |
+ { 0x40152000, 0x40153000, PROT_READ|PROT_WRITE, 0, NULL }, |
+ { 0x40231000, 0x40277000, PROT_READ|PROT_EXEC, 0x1000 * PAGE_SIZE, "/system/lib/libc.so" }, |
+ { 0x40277000, 0x40279000, PROT_READ, 0x46000 * PAGE_SIZE, "/system/lib/libc.so" }, |
+ { 0x40279000, 0x4027b000, PROT_READ|PROT_WRITE, 0x48000 * PAGE_SIZE, "/system/lib/libc.so" }, |
+ { 0x4027b000, 0x40289000, PROT_READ|PROT_WRITE, 0, NULL }, |
+ { 0x41e6b000, 0x41e72000, PROT_READ|PROT_WRITE, 0, "[heap]" }, |
+ { 0xbe91b000, 0xbe93c000, PROT_READ|PROT_WRITE, 0, "[stack]" }, |
+ { 0xffff0000, 0xffff1000, PROT_READ|PROT_EXEC, 0, "[vectors]" }, |
+ }; |
+ |
+ ProcMaps self_maps; |
+ ProcMaps::Entry entry; |
+ |
+ for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { |
+ minitest::internal::String text = |
+ minitest::Format("Checking entry #%d %p-%p", |
+ n + 1, |
+ kData[n].vma_start, |
+ kData[n].vma_end); |
+ TEST_TEXT << text; |
+ EXPECT_TRUE(self_maps.GetNextEntry(&entry)); |
+ TEST_TEXT << text; |
+ EXPECT_EQ(kData[n].vma_start, entry.vma_start); |
+ TEST_TEXT << text; |
+ EXPECT_EQ(kData[n].vma_end, entry.vma_end); |
+ TEST_TEXT << text; |
+ EXPECT_EQ(kData[n].prot_flags, entry.prot_flags); |
+ TEST_TEXT << text; |
+ EXPECT_EQ(kData[n].load_offset, entry.load_offset); |
+ |
+ if (!kData[n].path) { |
+ TEST_TEXT << text; |
+ EXPECT_FALSE(entry.path); |
+ } else { |
+ EXPECT_MEMEQ(kData[n].path, strlen(kData[n].path), |
+ entry.path, entry.path_len); |
+ } |
+ } |
+ EXPECT_FALSE(self_maps.GetNextEntry(&entry)); |
+} |
+ |
+ |
+} // namespace crazy |