1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "crazy_linker_proc_maps.h" 6 7 #include <limits.h> 8 #include <minitest/minitest.h> 9 #include "crazy_linker_system_mock.h" 10 11 namespace crazy { 12 13 namespace { 14 15 const char kProcMaps0[] = 16 "4000b000-4000c000 r--p 00000000 00:00 0\n" 17 "4005c000-40081000 r-xp 00000000 b3:01 141 /system/bin/mksh\n" 18 "40082000-40083000 r--p 00025000 b3:01 141 /system/bin/mksh\n" 19 "40083000-40084000 rw-p 00026000 b3:01 141 /system/bin/mksh\n" 20 "40084000-40088000 rw-p 00000000 00:00 0\n" 21 "40088000-40090000 r--s 00000000 00:0b 1704 /dev/__properties__\n" 22 "400eb000-400ec000 r--p 00000000 00:00 0\n" 23 "40141000-40150000 r-xp 00000000 b3:01 126 /system/bin/linker\n" 24 "40150000-40151000 r--p 0000e000 b3:01 126 /system/bin/linker\n" 25 "40151000-40152000 rw-p 0000f000 b3:01 126 /system/bin/linker\n" 26 "40152000-40153000 rw-p 00000000 00:00 0\n" 27 "40231000-40277000 r-xp 00001000 b3:01 638 /system/lib/libc.so\n" 28 "40277000-40279000 r--p 00046000 b3:01 638 /system/lib/libc.so\n" 29 "40279000-4027b000 rw-p 00048000 b3:01 638 /system/lib/libc.so\n" 30 "4027b000-40289000 rw-p 00000000 00:00 0\n" 31 "41e6b000-41e72000 rw-p 00000000 00:00 0 [heap]\n" 32 "be91b000-be93c000 rw-p 00000000 00:00 0 [stack]\n" 33 "ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]\n"; 34 35 class ScopedTestEnv { 36 public: 37 ScopedTestEnv() : sys_() { 38 sys_.AddRegularFile("/proc/self/maps", kProcMaps0, sizeof(kProcMaps0) - 1); 39 } 40 41 ~ScopedTestEnv() {} 42 43 private: 44 SystemMock sys_; 45 }; 46 47 } // namespace 48 49 TEST(ProcMaps, FindElfBinaryForAddress) { 50 ScopedTestEnv env; 51 char path[512]; 52 uintptr_t load_address; 53 54 EXPECT_TRUE(FindElfBinaryForAddress( 55 reinterpret_cast<void*>(0x400694c2), &load_address, path, sizeof(path))); 56 EXPECT_EQ(0x4005c000, load_address); 57 EXPECT_STREQ("/system/bin/mksh", path); 58 } 59 60 TEST(ProcMaps, FindElfBinaryForAddressWithBadAddress) { 61 ScopedTestEnv env; 62 char path[512]; 63 uintptr_t load_address; 64 65 EXPECT_FALSE(FindElfBinaryForAddress( 66 reinterpret_cast<void*>(0x50000000), &load_address, path, sizeof(path))); 67 } 68 69 TEST(ProcMaps, FindProtectionFlagsForAddress) { 70 ScopedTestEnv env; 71 static const struct { 72 uintptr_t address; 73 bool success; 74 int prot; 75 } kData[] = {{0x4000afff, false, 0}, 76 {0x4000b000, true, PROT_READ}, 77 {0x4000bfff, true, PROT_READ}, 78 {0x4000c000, false, 0}, 79 {0x4005bfff, false, 0}, 80 {0x4005c000, true, PROT_READ | PROT_EXEC}, 81 {0x40067832, true, PROT_READ | PROT_EXEC}, 82 {0x40082000, true, PROT_READ}, 83 {0x40083000, true, PROT_READ | PROT_WRITE}, 84 {0x40084000, true, PROT_READ | PROT_WRITE}, }; 85 86 int prot; 87 for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { 88 void* address = reinterpret_cast<void*>(kData[n].address); 89 TEST_TEXT << minitest::Format("Checking address %p", address); 90 EXPECT_EQ(kData[n].success, FindProtectionFlagsForAddress(address, &prot)); 91 if (kData[n].success) { 92 TEST_TEXT << minitest::Format("Checking address %p", address); 93 EXPECT_EQ(kData[n].prot, prot); 94 } 95 } 96 } 97 98 TEST(ProcMaps, FindLoadAddressForFile) { 99 ScopedTestEnv env; 100 static const struct { 101 bool success; 102 uintptr_t address; 103 uintptr_t offset; 104 const char* name; 105 } kData[] = {{true, 0x4005c000, 0, "mksh"}, 106 {true, 0x40141000, 0, "/system/bin/linker"}, 107 {false, 0, 0, "[heap]"}, 108 {false, 0, 0, "bin/mksh"}, 109 {true, 0x4005c000, 0, "/system/bin/mksh"}, 110 {true, 0x40231000, 0x1000000, "libc.so"}, }; 111 for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { 112 uintptr_t address, offset; 113 TEST_TEXT << "Checking " << kData[n].name; 114 bool success = FindLoadAddressForFile(kData[n].name, &address, &offset); 115 EXPECT_EQ(kData[n].success, success); 116 if (success) { 117 TEST_TEXT << "Checking " << kData[n].name; 118 EXPECT_EQ(kData[n].address, address); 119 120 TEST_TEXT << "Checking " << kData[n].name; 121 EXPECT_EQ(kData[n].offset, offset); 122 } 123 } 124 } 125 126 TEST(ProcMaps, GetNextEntry) { 127 ScopedTestEnv env; 128 // "4000b000-4000c000 r--p 00000000 00:00 0\n" 129 // "4005c000-40081000 r-xp 00000000 b3:01 141 /system/bin/mksh\n" 130 // "40082000-40083000 r--p 00025000 b3:01 141 /system/bin/mksh\n" 131 // "40083000-40084000 rw-p 00026000 b3:01 141 /system/bin/mksh\n" 132 // "40084000-40088000 rw-p 00000000 00:00 0\n" 133 // "40088000-40090000 r--s 00000000 00:0b 1704 134 // /dev/__properties__\n" 135 // "400eb000-400ec000 r--p 00000000 00:00 0\n" 136 // "40141000-40150000 r-xp 00000000 b3:01 126 /system/bin/linker\n" 137 // "40150000-40151000 r--p 0000e000 b3:01 126 /system/bin/linker\n" 138 // "40151000-40152000 rw-p 0000f000 b3:01 126 /system/bin/linker\n" 139 // "40152000-40153000 rw-p 00000000 00:00 0\n" 140 // "40231000-40277000 r-xp 00001000 b3:01 638 141 // /system/lib/libc.so\n" 142 // "40277000-40279000 r--p 00046000 b3:01 638 143 // /system/lib/libc.so\n" 144 // "40279000-4027b000 rw-p 00048000 b3:01 638 145 // /system/lib/libc.so\n" 146 // "4027b000-40289000 rw-p 00000000 00:00 0\n" 147 // "41e6b000-41e72000 rw-p 00000000 00:00 0 [heap]\n" 148 // "be91b000-be93c000 rw-p 00000000 00:00 0 [stack]\n" 149 // "ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]\n" 150 static const struct { 151 size_t vma_start; 152 size_t vma_end; 153 int prot_flags; 154 size_t load_offset; 155 const char* path; 156 } kData[] = { 157 {0x4000b000, 0x4000c000, PROT_READ, 0, NULL}, 158 {0x4005c000, 0x40081000, PROT_READ | PROT_EXEC, 0, "/system/bin/mksh"}, 159 {0x40082000, 0x40083000, PROT_READ, 160 0x25000 * PAGE_SIZE, "/system/bin/mksh"}, 161 {0x40083000, 0x40084000, PROT_READ | PROT_WRITE, 162 0x26000 * PAGE_SIZE, "/system/bin/mksh"}, 163 {0x40084000, 0x40088000, PROT_READ | PROT_WRITE, 0, NULL}, 164 {0x40088000, 0x40090000, PROT_READ, 0, "/dev/__properties__"}, 165 {0x400eb000, 0x400ec000, PROT_READ, 0, NULL}, 166 {0x40141000, 0x40150000, PROT_READ | PROT_EXEC, 167 0, "/system/bin/linker"}, 168 {0x40150000, 0x40151000, PROT_READ, 169 0xe000 * PAGE_SIZE, "/system/bin/linker"}, 170 {0x40151000, 0x40152000, PROT_READ | PROT_WRITE, 171 0xf000 * PAGE_SIZE, "/system/bin/linker"}, 172 {0x40152000, 0x40153000, PROT_READ | PROT_WRITE, 0, NULL}, 173 {0x40231000, 0x40277000, PROT_READ | PROT_EXEC, 174 0x1000 * PAGE_SIZE, "/system/lib/libc.so"}, 175 {0x40277000, 0x40279000, PROT_READ, 176 0x46000 * PAGE_SIZE, "/system/lib/libc.so"}, 177 {0x40279000, 0x4027b000, PROT_READ | PROT_WRITE, 178 0x48000 * PAGE_SIZE, "/system/lib/libc.so"}, 179 {0x4027b000, 0x40289000, PROT_READ | PROT_WRITE, 0, NULL}, 180 {0x41e6b000, 0x41e72000, PROT_READ | PROT_WRITE, 0, "[heap]"}, 181 {0xbe91b000, 0xbe93c000, PROT_READ | PROT_WRITE, 0, "[stack]"}, 182 {0xffff0000, 0xffff1000, PROT_READ | PROT_EXEC, 0, "[vectors]"}, }; 183 184 ProcMaps self_maps; 185 ProcMaps::Entry entry; 186 187 for (size_t n = 0; n < ARRAY_LEN(kData); ++n) { 188 minitest::internal::String text = 189 minitest::Format("Checking entry #%d %p-%p", 190 n + 1, 191 kData[n].vma_start, 192 kData[n].vma_end); 193 TEST_TEXT << text; 194 EXPECT_TRUE(self_maps.GetNextEntry(&entry)); 195 TEST_TEXT << text; 196 EXPECT_EQ(kData[n].vma_start, entry.vma_start); 197 TEST_TEXT << text; 198 EXPECT_EQ(kData[n].vma_end, entry.vma_end); 199 TEST_TEXT << text; 200 EXPECT_EQ(kData[n].prot_flags, entry.prot_flags); 201 TEST_TEXT << text; 202 EXPECT_EQ(kData[n].load_offset, entry.load_offset); 203 204 if (!kData[n].path) { 205 TEST_TEXT << text; 206 EXPECT_FALSE(entry.path); 207 } else { 208 EXPECT_MEMEQ( 209 kData[n].path, strlen(kData[n].path), entry.path, entry.path_len); 210 } 211 } 212 EXPECT_FALSE(self_maps.GetNextEntry(&entry)); 213 } 214 215 } // namespace crazy 216