• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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:
ScopedTestEnv()37   ScopedTestEnv() : sys_() {
38     sys_.AddRegularFile("/proc/self/maps", kProcMaps0, sizeof(kProcMaps0) - 1);
39   }
40 
~ScopedTestEnv()41   ~ScopedTestEnv() {}
42 
43  private:
44   SystemMock sys_;
45 };
46 
47 }  // namespace
48 
TEST(ProcMaps,FindElfBinaryForAddress)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 
TEST(ProcMaps,FindElfBinaryForAddressWithBadAddress)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 
TEST(ProcMaps,FindProtectionFlagsForAddress)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 
TEST(ProcMaps,FindLoadAddressForFile)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 
TEST(ProcMaps,GetNextEntry)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