1 /*
2 * Copyright (C) 2019 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 <stdint.h>
18 #include <sys/mman.h>
19
20 #include <string>
21 #include <vector>
22
23 #include <gtest/gtest.h>
24
25 #include <android-base/file.h>
26 #include <unwindstack/Maps.h>
27
28 namespace unwindstack {
29
30 class TestUpdatableMaps : public LocalUpdatableMaps {
31 public:
TestUpdatableMaps()32 TestUpdatableMaps() : LocalUpdatableMaps() {}
33 virtual ~TestUpdatableMaps() = default;
34
GetMapsFile() const35 const std::string GetMapsFile() const override { return maps_file_; }
36
TestSetMapsFile(const std::string & maps_file)37 void TestSetMapsFile(const std::string& maps_file) { maps_file_ = maps_file; }
38
39 private:
40 std::string maps_file_;
41 };
42
43 class LocalUpdatableMapsTest : public ::testing::Test {
44 protected:
GetDefaultMapString()45 static const std::string GetDefaultMapString() {
46 return "3000-4000 r-xp 00000 00:00 0\n8000-9000 r-xp 00000 00:00 0\n";
47 }
48
SetUp()49 void SetUp() override {
50 TemporaryFile tf;
51 ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path));
52
53 maps_.TestSetMapsFile(tf.path);
54 ASSERT_TRUE(maps_.Parse());
55 ASSERT_EQ(2U, maps_.Total());
56
57 auto map_info = maps_.Get(0);
58 ASSERT_TRUE(map_info != nullptr);
59 EXPECT_EQ(0x3000U, map_info->start());
60 EXPECT_EQ(0x4000U, map_info->end());
61 EXPECT_EQ(0U, map_info->offset());
62 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
63 EXPECT_TRUE(map_info->name().empty());
64
65 map_info = maps_.Get(1);
66 ASSERT_TRUE(map_info != nullptr);
67 EXPECT_EQ(0x8000U, map_info->start());
68 EXPECT_EQ(0x9000U, map_info->end());
69 EXPECT_EQ(0U, map_info->offset());
70 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
71 EXPECT_TRUE(map_info->name().empty());
72 }
73
74 TestUpdatableMaps maps_;
75 };
76
TEST_F(LocalUpdatableMapsTest,same_map)77 TEST_F(LocalUpdatableMapsTest, same_map) {
78 TemporaryFile tf;
79 ASSERT_TRUE(android::base::WriteStringToFile(GetDefaultMapString(), tf.path));
80
81 maps_.TestSetMapsFile(tf.path);
82 ASSERT_TRUE(maps_.Reparse());
83 ASSERT_EQ(2U, maps_.Total());
84
85 auto map_info = maps_.Get(0);
86 ASSERT_TRUE(map_info != nullptr);
87 EXPECT_EQ(0x3000U, map_info->start());
88 EXPECT_EQ(0x4000U, map_info->end());
89 EXPECT_EQ(0U, map_info->offset());
90 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
91 EXPECT_TRUE(map_info->name().empty());
92 EXPECT_EQ(nullptr, map_info->prev_map());
93 EXPECT_EQ(maps_.Get(1), map_info->next_map());
94
95 map_info = maps_.Get(1);
96 ASSERT_TRUE(map_info != nullptr);
97 EXPECT_EQ(0x8000U, map_info->start());
98 EXPECT_EQ(0x9000U, map_info->end());
99 EXPECT_EQ(0U, map_info->offset());
100 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
101 EXPECT_TRUE(map_info->name().empty());
102 EXPECT_EQ(maps_.Get(0), map_info->prev_map());
103 EXPECT_EQ(nullptr, map_info->next_map());
104 }
105
TEST_F(LocalUpdatableMapsTest,same_map_new_perms)106 TEST_F(LocalUpdatableMapsTest, same_map_new_perms) {
107 TemporaryFile tf;
108 ASSERT_TRUE(
109 android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n"
110 "8000-9000 r-xp 00000 00:00 0\n",
111 tf.path));
112
113 maps_.TestSetMapsFile(tf.path);
114 ASSERT_TRUE(maps_.Reparse());
115 ASSERT_EQ(2U, maps_.Total());
116
117 auto map_info = maps_.Get(0);
118 ASSERT_TRUE(map_info != nullptr);
119 EXPECT_EQ(0x3000U, map_info->start());
120 EXPECT_EQ(0x4000U, map_info->end());
121 EXPECT_EQ(0U, map_info->offset());
122 EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, map_info->flags());
123 EXPECT_TRUE(map_info->name().empty());
124 EXPECT_EQ(nullptr, map_info->prev_map());
125 EXPECT_EQ(maps_.Get(1), map_info->next_map());
126
127 map_info = maps_.Get(1);
128 ASSERT_TRUE(map_info != nullptr);
129 EXPECT_EQ(0x8000U, map_info->start());
130 EXPECT_EQ(0x9000U, map_info->end());
131 EXPECT_EQ(0U, map_info->offset());
132 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
133 EXPECT_TRUE(map_info->name().empty());
134 EXPECT_EQ(maps_.Get(0), map_info->prev_map());
135 EXPECT_EQ(nullptr, map_info->next_map());
136 }
137
TEST_F(LocalUpdatableMapsTest,same_map_new_name)138 TEST_F(LocalUpdatableMapsTest, same_map_new_name) {
139 TemporaryFile tf;
140 ASSERT_TRUE(
141 android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
142 "8000-9000 r-xp 00000 00:00 0\n",
143 tf.path));
144
145 maps_.TestSetMapsFile(tf.path);
146 ASSERT_TRUE(maps_.Reparse());
147 ASSERT_EQ(2U, maps_.Total());
148
149 auto map_info = maps_.Get(0);
150 ASSERT_TRUE(map_info != nullptr);
151 EXPECT_EQ(0x3000U, map_info->start());
152 EXPECT_EQ(0x4000U, map_info->end());
153 EXPECT_EQ(0U, map_info->offset());
154 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
155 EXPECT_EQ("/fake/lib.so", map_info->name());
156 EXPECT_EQ(nullptr, map_info->prev_map());
157 EXPECT_EQ(maps_.Get(1), map_info->next_map());
158
159 map_info = maps_.Get(1);
160 ASSERT_TRUE(map_info != nullptr);
161 EXPECT_EQ(0x8000U, map_info->start());
162 EXPECT_EQ(0x9000U, map_info->end());
163 EXPECT_EQ(0U, map_info->offset());
164 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
165 EXPECT_TRUE(map_info->name().empty());
166 EXPECT_EQ(maps_.Get(0), map_info->prev_map());
167 EXPECT_EQ(nullptr, map_info->next_map());
168 }
169
TEST_F(LocalUpdatableMapsTest,only_add_maps)170 TEST_F(LocalUpdatableMapsTest, only_add_maps) {
171 TemporaryFile tf;
172 ASSERT_TRUE(
173 android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n"
174 "3000-4000 r-xp 00000 00:00 0\n"
175 "8000-9000 r-xp 00000 00:00 0\n"
176 "a000-f000 r-xp 00000 00:00 0\n",
177 tf.path));
178
179 maps_.TestSetMapsFile(tf.path);
180 ASSERT_TRUE(maps_.Reparse());
181 ASSERT_EQ(4U, maps_.Total());
182
183 auto map_info = maps_.Get(0);
184 ASSERT_TRUE(map_info != nullptr);
185 EXPECT_EQ(0x1000U, map_info->start());
186 EXPECT_EQ(0x2000U, map_info->end());
187 EXPECT_EQ(0U, map_info->offset());
188 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
189 EXPECT_TRUE(map_info->name().empty());
190 EXPECT_EQ(nullptr, map_info->prev_map());
191 EXPECT_EQ(maps_.Get(1), map_info->next_map());
192
193 map_info = maps_.Get(1);
194 ASSERT_TRUE(map_info != nullptr);
195 EXPECT_EQ(0x3000U, map_info->start());
196 EXPECT_EQ(0x4000U, map_info->end());
197 EXPECT_EQ(0U, map_info->offset());
198 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
199 EXPECT_TRUE(map_info->name().empty());
200 EXPECT_EQ(maps_.Get(0), map_info->prev_map());
201 EXPECT_EQ(maps_.Get(2), map_info->next_map());
202
203 map_info = maps_.Get(2);
204 ASSERT_TRUE(map_info != nullptr);
205 EXPECT_EQ(0x8000U, map_info->start());
206 EXPECT_EQ(0x9000U, map_info->end());
207 EXPECT_EQ(0U, map_info->offset());
208 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
209 EXPECT_TRUE(map_info->name().empty());
210 EXPECT_EQ(maps_.Get(1), map_info->prev_map());
211 EXPECT_EQ(maps_.Get(3), map_info->next_map());
212
213 map_info = maps_.Get(3);
214 ASSERT_TRUE(map_info != nullptr);
215 EXPECT_EQ(0xa000U, map_info->start());
216 EXPECT_EQ(0xf000U, map_info->end());
217 EXPECT_EQ(0U, map_info->offset());
218 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
219 EXPECT_TRUE(map_info->name().empty());
220 EXPECT_EQ(maps_.Get(2), map_info->prev_map());
221 EXPECT_EQ(nullptr, map_info->next_map());
222 }
223
TEST_F(LocalUpdatableMapsTest,all_new_maps)224 TEST_F(LocalUpdatableMapsTest, all_new_maps) {
225 TemporaryFile tf;
226 ASSERT_TRUE(
227 android::base::WriteStringToFile("1000-2000 r-xp 00000 00:00 0\n"
228 "a000-f000 r-xp 00000 00:00 0\n",
229 tf.path));
230
231 maps_.TestSetMapsFile(tf.path);
232 ASSERT_TRUE(maps_.Reparse());
233 ASSERT_EQ(2U, maps_.Total());
234
235 auto map_info = maps_.Get(0);
236 ASSERT_TRUE(map_info != nullptr);
237 EXPECT_EQ(0x1000U, map_info->start());
238 EXPECT_EQ(0x2000U, map_info->end());
239 EXPECT_EQ(0U, map_info->offset());
240 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
241 EXPECT_TRUE(map_info->name().empty());
242 EXPECT_EQ(nullptr, map_info->prev_map());
243 EXPECT_EQ(maps_.Get(1), map_info->next_map());
244
245 map_info = maps_.Get(1);
246 ASSERT_TRUE(map_info != nullptr);
247 EXPECT_EQ(0xa000U, map_info->start());
248 EXPECT_EQ(0xf000U, map_info->end());
249 EXPECT_EQ(0U, map_info->offset());
250 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
251 EXPECT_TRUE(map_info->name().empty());
252 EXPECT_EQ(maps_.Get(0), map_info->prev_map());
253 EXPECT_EQ(nullptr, map_info->next_map());
254 }
255
TEST_F(LocalUpdatableMapsTest,add_map_prev_name_updated)256 TEST_F(LocalUpdatableMapsTest, add_map_prev_name_updated) {
257 TemporaryFile tf;
258 ASSERT_TRUE(
259 android::base::WriteStringToFile("3000-4000 rwxp 00000 00:00 0\n"
260 "8000-9000 r-xp 00000 00:00 0\n"
261 "9000-a000 r-xp 00000 00:00 0\n",
262 tf.path));
263
264 maps_.TestSetMapsFile(tf.path);
265 ASSERT_TRUE(maps_.Reparse());
266 ASSERT_EQ(3U, maps_.Total());
267
268 auto map_info = maps_.Get(2);
269 ASSERT_TRUE(map_info != nullptr);
270 EXPECT_EQ(0x9000U, map_info->start());
271 EXPECT_EQ(0xA000U, map_info->end());
272 EXPECT_EQ(0U, map_info->offset());
273 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
274 EXPECT_TRUE(map_info->name().empty());
275
276 // Check all of the prev and next pointers.
277 EXPECT_EQ(nullptr, maps_.Get(0)->prev_map());
278 EXPECT_EQ(maps_.Get(1), maps_.Get(0)->next_map());
279 EXPECT_EQ(maps_.Get(0), maps_.Get(1)->prev_map());
280 EXPECT_EQ(maps_.Get(2), maps_.Get(1)->next_map());
281 EXPECT_EQ(maps_.Get(1), maps_.Get(2)->prev_map());
282 EXPECT_EQ(nullptr, maps_.Get(2)->next_map());
283 }
284
TEST_F(LocalUpdatableMapsTest,add_map_prev_real_name_updated)285 TEST_F(LocalUpdatableMapsTest, add_map_prev_real_name_updated) {
286 TemporaryFile tf;
287 ASSERT_TRUE(
288 android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
289 "4000-5000 ---p 00000 00:00 0\n"
290 "7000-8000 r-xp 00000 00:00 0 /fake/lib.so\n"
291 "8000-9000 ---p 00000 00:00 0\n",
292 tf.path));
293
294 maps_.TestSetMapsFile(tf.path);
295 bool any_changed;
296 ASSERT_TRUE(maps_.Reparse(&any_changed));
297 ASSERT_EQ(4U, maps_.Total());
298 ASSERT_TRUE(any_changed);
299
300 // Try again and assert there are no changes this time.
301 ASSERT_TRUE(maps_.Reparse(&any_changed));
302 ASSERT_EQ(4U, maps_.Total());
303 ASSERT_FALSE(any_changed);
304
305 auto map_info = maps_.Get(2);
306 ASSERT_TRUE(map_info != nullptr);
307 EXPECT_EQ(0x7000U, map_info->start());
308 EXPECT_EQ(0x8000U, map_info->end());
309 EXPECT_EQ(0U, map_info->offset());
310 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
311 EXPECT_EQ(maps_.Get(0), map_info->GetPrevRealMap());
312 EXPECT_EQ(maps_.Get(1), map_info->prev_map());
313 EXPECT_EQ(maps_.Get(3), map_info->next_map());
314 EXPECT_EQ("/fake/lib.so", map_info->name());
315
316 map_info = maps_.Get(3);
317 ASSERT_TRUE(map_info != nullptr);
318 EXPECT_EQ(0x8000U, map_info->start());
319 EXPECT_EQ(0x9000U, map_info->end());
320 EXPECT_EQ(0U, map_info->offset());
321 EXPECT_TRUE(map_info->IsBlank());
322 EXPECT_EQ(nullptr, map_info->GetPrevRealMap());
323 EXPECT_EQ(maps_.Get(2), map_info->prev_map());
324 EXPECT_EQ(maps_.Get(4), map_info->next_map());
325 EXPECT_TRUE(map_info->name().empty());
326
327 ASSERT_TRUE(
328 android::base::WriteStringToFile("3000-4000 r-xp 00000 00:00 0 /fake/lib.so\n"
329 "4000-5000 ---p 00000 00:00 0\n"
330 "7000-8000 r-xp 00000 00:00 0 /fake/lib.so\n"
331 "8000-9000 ---p 00000 00:00 0\n"
332 "9000-a000 r-xp 00000 00:00 0 /fake/lib2.so\n"
333 "a000-b000 r-xp 00000 00:00 0 /fake/lib3.so\n",
334 tf.path));
335
336 maps_.TestSetMapsFile(tf.path);
337 ASSERT_TRUE(maps_.Reparse(&any_changed));
338 ASSERT_EQ(6U, maps_.Total());
339 ASSERT_TRUE(any_changed);
340
341 // Try again and assert there are no changes this time.
342 ASSERT_TRUE(maps_.Reparse(&any_changed));
343 ASSERT_EQ(6U, maps_.Total());
344 ASSERT_FALSE(any_changed);
345
346 map_info = maps_.Get(2);
347 ASSERT_TRUE(map_info != nullptr);
348 EXPECT_EQ(0x7000U, map_info->start());
349 EXPECT_EQ(0x8000U, map_info->end());
350 EXPECT_EQ(0U, map_info->offset());
351 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
352 EXPECT_EQ("/fake/lib.so", map_info->name());
353 EXPECT_EQ(maps_.Get(1), map_info->prev_map());
354 EXPECT_EQ(maps_.Get(0), map_info->GetPrevRealMap());
355 EXPECT_EQ(maps_.Get(3), map_info->next_map());
356
357 map_info = maps_.Get(4);
358 ASSERT_TRUE(map_info != nullptr);
359 EXPECT_EQ(0x9000U, map_info->start());
360 EXPECT_EQ(0xA000U, map_info->end());
361 EXPECT_EQ(0U, map_info->offset());
362 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
363 EXPECT_EQ("/fake/lib2.so", map_info->name());
364 EXPECT_EQ(maps_.Get(3), map_info->prev_map());
365 EXPECT_EQ(nullptr, map_info->GetPrevRealMap());
366 EXPECT_EQ(maps_.Get(5), map_info->next_map());
367
368 map_info = maps_.Get(5);
369 ASSERT_TRUE(map_info != nullptr);
370 EXPECT_EQ(0xA000U, map_info->start());
371 EXPECT_EQ(0xB000U, map_info->end());
372 EXPECT_EQ(0U, map_info->offset());
373 EXPECT_EQ(PROT_READ | PROT_EXEC, map_info->flags());
374 EXPECT_EQ("/fake/lib3.so", map_info->name());
375 EXPECT_EQ(maps_.Get(4), map_info->prev_map());
376 EXPECT_EQ(nullptr, map_info->GetPrevRealMap());
377 EXPECT_EQ(nullptr, map_info->next_map());
378 }
379
380 } // namespace unwindstack
381