xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/MapsTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1 /*
2  * Copyright (C) 2016 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 <inttypes.h>
18 #include <sys/mman.h>
19 
20 #include <android-base/file.h>
21 #include <android-base/stringprintf.h>
22 #include <gtest/gtest.h>
23 
24 #include <unwindstack/Maps.h>
25 
26 namespace unwindstack {
27 
VerifyLine(std::string line,MapInfo * info)28 static void VerifyLine(std::string line, MapInfo* info) {
29   BufferMaps maps(line.c_str());
30 
31   if (info == nullptr) {
32     ASSERT_FALSE(maps.Parse()) << "Failed on: " + line;
33   } else {
34     ASSERT_TRUE(maps.Parse()) << "Failed on: " + line;
35     MapInfo* element = maps.Get(0).get();
36     ASSERT_TRUE(element != nullptr) << "Failed on: " + line;
37     info->set_start(element->start());
38     info->set_end(element->end());
39     info->set_offset(element->offset());
40     info->set_flags(element->flags());
41     info->set_name(element->name());
42     info->set_elf_offset(element->elf_offset());
43   }
44 }
45 
TEST(MapsTest,map_add)46 TEST(MapsTest, map_add) {
47   Maps maps;
48 
49   maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
50   maps.Add(0x3000, 0x4000, 0, 0, "", 0x1234);
51   maps.Add(0x5000, 0x6000, 1, 2, "fake_map", static_cast<uint64_t>(-1));
52 
53   ASSERT_EQ(3U, maps.Total());
54   auto info1 = maps.Get(0);
55   auto info2 = maps.Get(1);
56   auto info3 = maps.Get(2);
57 
58   EXPECT_EQ(nullptr, info1->prev_map());
59   EXPECT_EQ(nullptr, info1->GetPrevRealMap());
60   EXPECT_EQ(info2, info1->next_map());
61   EXPECT_EQ(info3, info1->GetNextRealMap());
62 
63   EXPECT_EQ(info1, info2->prev_map());
64   EXPECT_EQ(nullptr, info2->GetPrevRealMap());
65   EXPECT_EQ(info3, info2->next_map());
66   EXPECT_EQ(nullptr, info2->GetNextRealMap());
67 
68   EXPECT_EQ(info2, info3->prev_map());
69   EXPECT_EQ(info1, info3->GetPrevRealMap());
70   EXPECT_EQ(nullptr, info3->next_map());
71   EXPECT_EQ(nullptr, info3->GetNextRealMap());
72 
73   ASSERT_EQ(0x1000U, info1->start());
74   ASSERT_EQ(0x2000U, info1->end());
75   ASSERT_EQ(0U, info1->offset());
76   ASSERT_EQ(PROT_READ, info1->flags());
77   ASSERT_EQ("fake_map", info1->name());
78   ASSERT_EQ(0U, info1->elf_offset());
79   ASSERT_EQ(0U, info1->load_bias().load());
80 }
81 
TEST(MapsTest,map_move)82 TEST(MapsTest, map_move) {
83   Maps maps;
84 
85   maps.Add(0x1000, 0x2000, 0, PROT_READ, "fake_map", 0);
86   maps.Add(0x3000, 0x4000, 0x10, 0, "", 0x1234);
87   maps.Add(0x5000, 0x6000, 1, 2, "fake_map2", static_cast<uint64_t>(-1));
88 
89   Maps maps2 = std::move(maps);
90 
91   ASSERT_EQ(3U, maps2.Total());
92   auto info = maps2.Get(0);
93   ASSERT_EQ(0x1000U, info->start());
94   ASSERT_EQ(0x2000U, info->end());
95   ASSERT_EQ(0U, info->offset());
96   ASSERT_EQ(PROT_READ, info->flags());
97   ASSERT_EQ("fake_map", info->name());
98   ASSERT_EQ(0U, info->elf_offset());
99   ASSERT_EQ(0U, info->load_bias().load());
100 }
101 
TEST(MapsTest,verify_parse_line)102 TEST(MapsTest, verify_parse_line) {
103   auto info = MapInfo::Create(0, 0, 0, 0, "");
104 
105   VerifyLine("01-02 rwxp 03 04:05 06\n", info.get());
106   EXPECT_EQ(1U, info->start());
107   EXPECT_EQ(2U, info->end());
108   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
109   EXPECT_EQ(3U, info->offset());
110   EXPECT_EQ("", info->name());
111 
112   VerifyLine("0a-0b ---s 0c 0d:0e 06 /fake/name\n", info.get());
113   EXPECT_EQ(0xaU, info->start());
114   EXPECT_EQ(0xbU, info->end());
115   EXPECT_EQ(0U, info->flags());
116   EXPECT_EQ(0xcU, info->offset());
117   EXPECT_EQ("/fake/name", info->name());
118 
119   VerifyLine("01-02   rwxp   03    04:05    06    /fake/name/again\n", info.get());
120   EXPECT_EQ(1U, info->start());
121   EXPECT_EQ(2U, info->end());
122   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
123   EXPECT_EQ(3U, info->offset());
124   EXPECT_EQ("/fake/name/again", info->name());
125 
126   VerifyLine("-00 rwxp 00 00:00 0\n", nullptr);
127   VerifyLine("00- rwxp 00 00:00 0\n", nullptr);
128   VerifyLine("00-00 rwxp 00 :00 0\n", nullptr);
129   VerifyLine("00-00 rwxp 00 00:00 \n", nullptr);
130   VerifyLine("x-00 rwxp 00 00:00 0\n", nullptr);
131   VerifyLine("00 -00 rwxp 00 00:00 0\n", nullptr);
132   VerifyLine("00-x rwxp 00 00:00 0\n", nullptr);
133   VerifyLine("00-x rwxp 00 00:00 0\n", nullptr);
134   VerifyLine("00-00x rwxp 00 00:00 0\n", nullptr);
135   VerifyLine("00-00 rwxp0 00 00:00 0\n", nullptr);
136   VerifyLine("00-00 rwxp0 00 00:00 0\n", nullptr);
137   VerifyLine("00-00 rwp 00 00:00 0\n", nullptr);
138   VerifyLine("00-00 rwxp 0000:00 0\n", nullptr);
139   VerifyLine("00-00 rwxp 00 00 :00 0\n", nullptr);
140   VerifyLine("00-00 rwxp 00 00: 00 0\n", nullptr);
141   VerifyLine("00-00 rwxp 00 00:000\n", nullptr);
142   VerifyLine("00-00 rwxp 00 00:00 0/fake\n", nullptr);
143   VerifyLine("00-00 xxxx 00 00:00 0 /fake\n", nullptr);
144   VerifyLine("00-00 ywxp 00 00:00 0 /fake\n", nullptr);
145   VerifyLine("00-00 ryxp 00 00:00 0 /fake\n", nullptr);
146   VerifyLine("00-00 rwyp 00 00:00 0 /fake\n", nullptr);
147   VerifyLine("00-00 rwx- 00 00:00 0 /fake\n", nullptr);
148   VerifyLine("0\n", nullptr);
149   VerifyLine("00\n", nullptr);
150   VerifyLine("00-\n", nullptr);
151   VerifyLine("00-0\n", nullptr);
152   VerifyLine("00-00\n", nullptr);
153   VerifyLine("00-00 \n", nullptr);
154   VerifyLine("00-00 -\n", nullptr);
155   VerifyLine("00-00 r\n", nullptr);
156   VerifyLine("00-00 --\n", nullptr);
157   VerifyLine("00-00 rw\n", nullptr);
158   VerifyLine("00-00 ---\n", nullptr);
159   VerifyLine("00-00 rwx\n", nullptr);
160   VerifyLine("00-00 ---s\n", nullptr);
161   VerifyLine("00-00 ---p\n", nullptr);
162   VerifyLine("00-00 ---s 0\n", nullptr);
163   VerifyLine("00-00 ---p 0 \n", nullptr);
164   VerifyLine("00-00 ---p 0 0\n", nullptr);
165   VerifyLine("00-00 ---p 0 0:\n", nullptr);
166   VerifyLine("00-00 ---p 0 0:0\n", nullptr);
167   VerifyLine("00-00 ---p 0 0:0 \n", nullptr);
168 
169   // Line to verify that the parser will detect a completely malformed line
170   // properly.
171   VerifyLine("7ffff7dda000-7ffff7dfd7ffff7ff3000-7ffff7ff4000 ---p 0000f000 fc:02 44171565\n",
172              nullptr);
173 }
174 
TEST(MapsTest,verify_large_values)175 TEST(MapsTest, verify_large_values) {
176   auto info = MapInfo::Create(0, 0, 0, 0, "");
177 #if defined(__LP64__)
178   VerifyLine("fabcdef012345678-f12345678abcdef8 rwxp f0b0d0f010305070 00:00 0\n", info.get());
179   EXPECT_EQ(0xfabcdef012345678UL, info->start());
180   EXPECT_EQ(0xf12345678abcdef8UL, info->end());
181   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
182   EXPECT_EQ(0xf0b0d0f010305070UL, info->offset());
183 #else
184   VerifyLine("f2345678-fabcdef8 rwxp f0305070 00:00 0\n", info.get());
185   EXPECT_EQ(0xf2345678UL, info->start());
186   EXPECT_EQ(0xfabcdef8UL, info->end());
187   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
188   EXPECT_EQ(0xf0305070UL, info->offset());
189 #endif
190 }
191 
TEST(MapsTest,parse_permissions)192 TEST(MapsTest, parse_permissions) {
193   BufferMaps maps(
194       "1000-2000 ---s 00000000 00:00 0\n"
195       "2000-3000 r--s 00000000 00:00 0\n"
196       "3000-4000 -w-s 00000000 00:00 0\n"
197       "4000-5000 --xp 00000000 00:00 0\n"
198       "5000-6000 rwxp 00000000 00:00 0\n");
199 
200   ASSERT_TRUE(maps.Parse());
201   ASSERT_EQ(5U, maps.Total());
202 
203   auto info = maps.Get(0);
204   ASSERT_TRUE(info != nullptr);
205   EXPECT_EQ(PROT_NONE, info->flags());
206   EXPECT_EQ(0x1000U, info->start());
207   EXPECT_EQ(0x2000U, info->end());
208   EXPECT_EQ(0U, info->offset());
209   EXPECT_EQ("", info->name());
210 
211   info = maps.Get(1);
212   ASSERT_TRUE(info != nullptr);
213   EXPECT_EQ(PROT_READ, info->flags());
214   EXPECT_EQ(0x2000U, info->start());
215   EXPECT_EQ(0x3000U, info->end());
216   EXPECT_EQ(0U, info->offset());
217   EXPECT_EQ("", info->name());
218 
219   info = maps.Get(2);
220   ASSERT_TRUE(info != nullptr);
221   EXPECT_EQ(PROT_WRITE, info->flags());
222   EXPECT_EQ(0x3000U, info->start());
223   EXPECT_EQ(0x4000U, info->end());
224   EXPECT_EQ(0U, info->offset());
225   EXPECT_EQ("", info->name());
226 
227   info = maps.Get(3);
228   ASSERT_TRUE(info != nullptr);
229   EXPECT_EQ(PROT_EXEC, info->flags());
230   EXPECT_EQ(0x4000U, info->start());
231   EXPECT_EQ(0x5000U, info->end());
232   EXPECT_EQ(0U, info->offset());
233   EXPECT_EQ("", info->name());
234 
235   info = maps.Get(4);
236   ASSERT_TRUE(info != nullptr);
237   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
238   EXPECT_EQ(0x5000U, info->start());
239   EXPECT_EQ(0x6000U, info->end());
240   EXPECT_EQ(0U, info->offset());
241   EXPECT_EQ("", info->name());
242 
243   ASSERT_TRUE(maps.Get(5) == nullptr);
244 }
245 
TEST(MapsTest,parse_name)246 TEST(MapsTest, parse_name) {
247   BufferMaps maps(
248       "7b29b000-7b29e000 rw-p 00000000 00:00 0\n"
249       "7b29e000-7b29f000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
250       "7b29f000-7b2a0000 rw-p 00000000 00:00 0");
251 
252   ASSERT_TRUE(maps.Parse());
253   ASSERT_EQ(3U, maps.Total());
254 
255   auto info = maps.Get(0);
256   ASSERT_TRUE(info != nullptr);
257   EXPECT_EQ("", info->name());
258   EXPECT_EQ(0x7b29b000U, info->start());
259   EXPECT_EQ(0x7b29e000U, info->end());
260   EXPECT_EQ(0U, info->offset());
261   EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags());
262 
263   info = maps.Get(1);
264   ASSERT_TRUE(info != nullptr);
265   EXPECT_EQ("/system/lib/fake.so", info->name());
266   EXPECT_EQ(0x7b29e000U, info->start());
267   EXPECT_EQ(0x7b29f000U, info->end());
268   EXPECT_EQ(0U, info->offset());
269   EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags());
270 
271   info = maps.Get(2);
272   ASSERT_TRUE(info != nullptr);
273   EXPECT_EQ("", info->name());
274   EXPECT_EQ(0x7b29f000U, info->start());
275   EXPECT_EQ(0x7b2a0000U, info->end());
276   EXPECT_EQ(0U, info->offset());
277   EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags());
278 
279   ASSERT_TRUE(maps.Get(3) == nullptr);
280 }
281 
TEST(MapsTest,parse_offset)282 TEST(MapsTest, parse_offset) {
283   BufferMaps maps(
284       "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
285       "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
286 
287   ASSERT_TRUE(maps.Parse());
288   ASSERT_EQ(2U, maps.Total());
289 
290   auto info = maps.Get(0);
291   ASSERT_TRUE(info != nullptr);
292   EXPECT_EQ(0U, info->offset());
293   EXPECT_EQ(0xa000U, info->start());
294   EXPECT_EQ(0xe000U, info->end());
295   EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags());
296   EXPECT_EQ("/system/lib/fake.so", info->name());
297 
298   info = maps.Get(1);
299   ASSERT_TRUE(info != nullptr);
300   EXPECT_EQ(0xa12345U, info->offset());
301   EXPECT_EQ(0xe000U, info->start());
302   EXPECT_EQ(0xf000U, info->end());
303   EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags());
304   EXPECT_EQ("/system/lib/fake.so", info->name());
305 
306   ASSERT_TRUE(maps.Get(2) == nullptr);
307 }
308 
TEST(MapsTest,iterate)309 TEST(MapsTest, iterate) {
310   BufferMaps maps(
311       "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
312       "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
313 
314   ASSERT_TRUE(maps.Parse());
315   ASSERT_EQ(2U, maps.Total());
316 
317   Maps::iterator it = maps.begin();
318   EXPECT_EQ(0xa000U, (*it)->start());
319   EXPECT_EQ(0xe000U, (*it)->end());
320   ++it;
321   EXPECT_EQ(0xe000U, (*it)->start());
322   EXPECT_EQ(0xf000U, (*it)->end());
323   ++it;
324   EXPECT_EQ(maps.end(), it);
325 }
326 
TEST(MapsTest,const_iterate)327 TEST(MapsTest, const_iterate) {
328   BufferMaps maps(
329       "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
330       "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
331 
332   ASSERT_TRUE(maps.Parse());
333   ASSERT_EQ(2U, maps.Total());
334 
335   Maps::const_iterator it = maps.begin();
336   EXPECT_EQ(0xa000U, (*it)->start());
337   EXPECT_EQ(0xe000U, (*it)->end());
338   ++it;
339   EXPECT_EQ(0xe000U, (*it)->start());
340   EXPECT_EQ(0xf000U, (*it)->end());
341   ++it;
342   EXPECT_EQ(maps.end(), it);
343 }
344 
TEST(MapsTest,device)345 TEST(MapsTest, device) {
346   BufferMaps maps(
347       "a000-e000 rw-p 00000000 00:00 0 /dev/\n"
348       "f000-f100 rw-p 00000000 00:00 0 /dev/does_not_exist\n"
349       "f100-f200 rw-p 00000000 00:00 0 /dev/ashmem/does_not_exist\n"
350       "f200-f300 rw-p 00000000 00:00 0 /devsomething/does_not_exist\n");
351 
352   ASSERT_TRUE(maps.Parse());
353   ASSERT_EQ(4U, maps.Total());
354 
355   auto info = maps.Get(0);
356   ASSERT_TRUE(info != nullptr);
357   EXPECT_TRUE(info->flags() & 0x8000);
358   EXPECT_EQ("/dev/", info->name());
359 
360   info = maps.Get(1);
361   EXPECT_TRUE(info->flags() & 0x8000);
362   EXPECT_EQ("/dev/does_not_exist", info->name());
363 
364   info = maps.Get(2);
365   EXPECT_FALSE(info->flags() & 0x8000);
366   EXPECT_EQ("/dev/ashmem/does_not_exist", info->name());
367 
368   info = maps.Get(3);
369   EXPECT_FALSE(info->flags() & 0x8000);
370   EXPECT_EQ("/devsomething/does_not_exist", info->name());
371 }
372 
TEST(MapsTest,file_smoke)373 TEST(MapsTest, file_smoke) {
374   TemporaryFile tf;
375   ASSERT_TRUE(tf.fd != -1);
376 
377   ASSERT_TRUE(
378       android::base::WriteStringToFile("7b29b000-7b29e000 r-xp a0000000 00:00 0   /fake.so\n"
379                                        "7b2b0000-7b2e0000 r-xp b0000000 00:00 0   /fake2.so\n"
380                                        "7b2e0000-7b2f0000 r-xp c0000000 00:00 0   /fake3.so\n",
381                                        tf.path, 0660, getuid(), getgid()));
382 
383   FileMaps maps(tf.path);
384 
385   ASSERT_TRUE(maps.Parse());
386   ASSERT_EQ(3U, maps.Total());
387 
388   auto info = maps.Get(0);
389   ASSERT_TRUE(info != nullptr);
390   EXPECT_EQ(0x7b29b000U, info->start());
391   EXPECT_EQ(0x7b29e000U, info->end());
392   EXPECT_EQ(0xa0000000U, info->offset());
393   EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags());
394   EXPECT_EQ("/fake.so", info->name());
395 
396   info = maps.Get(1);
397   ASSERT_TRUE(info != nullptr);
398   EXPECT_EQ(0x7b2b0000U, info->start());
399   EXPECT_EQ(0x7b2e0000U, info->end());
400   EXPECT_EQ(0xb0000000U, info->offset());
401   EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags());
402   EXPECT_EQ("/fake2.so", info->name());
403 
404   info = maps.Get(2);
405   ASSERT_TRUE(info != nullptr);
406   EXPECT_EQ(0x7b2e0000U, info->start());
407   EXPECT_EQ(0x7b2f0000U, info->end());
408   EXPECT_EQ(0xc0000000U, info->offset());
409   EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags());
410   EXPECT_EQ("/fake3.so", info->name());
411 
412   ASSERT_TRUE(maps.Get(3) == nullptr);
413 }
414 
TEST(MapsTest,file_no_map_name)415 TEST(MapsTest, file_no_map_name) {
416   TemporaryFile tf;
417   ASSERT_TRUE(tf.fd != -1);
418 
419   ASSERT_TRUE(
420       android::base::WriteStringToFile("7b29b000-7b29e000 r-xp a0000000 00:00 0\n"
421                                        "7b2b0000-7b2e0000 r-xp b0000000 00:00 0   /fake2.so\n"
422                                        "7b2e0000-7b2f0000 r-xp c0000000 00:00 0 \n",
423                                        tf.path, 0660, getuid(), getgid()));
424 
425   FileMaps maps(tf.path);
426 
427   ASSERT_TRUE(maps.Parse());
428   ASSERT_EQ(3U, maps.Total());
429 
430   auto info = maps.Get(0);
431   ASSERT_TRUE(info != nullptr);
432   EXPECT_EQ(0x7b29b000U, info->start());
433   EXPECT_EQ(0x7b29e000U, info->end());
434   EXPECT_EQ(0xa0000000U, info->offset());
435   EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags());
436   EXPECT_EQ("", info->name());
437 
438   info = maps.Get(1);
439   ASSERT_TRUE(info != nullptr);
440   EXPECT_EQ(0x7b2b0000U, info->start());
441   EXPECT_EQ(0x7b2e0000U, info->end());
442   EXPECT_EQ(0xb0000000U, info->offset());
443   EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags());
444   EXPECT_EQ("/fake2.so", info->name());
445 
446   info = maps.Get(2);
447   ASSERT_TRUE(info != nullptr);
448   EXPECT_EQ(0x7b2e0000U, info->start());
449   EXPECT_EQ(0x7b2f0000U, info->end());
450   EXPECT_EQ(0xc0000000U, info->offset());
451   EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags());
452   EXPECT_EQ("", info->name());
453 
454   ASSERT_TRUE(maps.Get(3) == nullptr);
455 }
456 
457 // Verify that a file that crosses a buffer is parsed correctly.
CreateEntry(size_t index)458 static std::string CreateEntry(size_t index) {
459   return android::base::StringPrintf("%08zx-%08zx rwxp 0000 00:00 0\n", index * 4096,
460                                      (index + 1) * 4096);
461 }
462 
TEST(MapsTest,file_buffer_cross)463 TEST(MapsTest, file_buffer_cross) {
464   constexpr size_t kBufferSize = 2048;
465   TemporaryFile tf;
466   ASSERT_TRUE(tf.fd != -1);
467 
468   // Compute how many to add in the first buffer.
469   size_t entry_len = CreateEntry(0).size();
470   size_t index;
471   std::string file_data;
472   for (index = 0; index < kBufferSize / entry_len; index++) {
473     file_data += CreateEntry(index);
474   }
475   // Add a long name to make sure that the first buffer does not contain a
476   // complete line.
477   // Remove the last newline.
478   size_t extra = 0;
479   size_t leftover = kBufferSize % entry_len;
480   size_t overlap1_index = 0;
481   std::string overlap1_name;
482   if (leftover == 0) {
483     // Exact match, add a long name to cross over the value.
484     overlap1_name = "/fake/name/is/long/on/purpose";
485     file_data.erase(file_data.size() - 1);
486     file_data += ' ' + overlap1_name + '\n';
487     extra = entry_len + overlap1_name.size() + 1;
488     overlap1_index = index;
489   }
490 
491   // Compute how many need to go in to hit the buffer boundary exactly.
492   size_t bytes_left_in_buffer = kBufferSize - extra;
493   size_t entries_to_add = bytes_left_in_buffer / entry_len + index;
494   for (; index < entries_to_add; index++) {
495     file_data += CreateEntry(index);
496   }
497 
498   // Now figure out how many bytes to add to get exactly to the buffer boundary.
499   leftover = bytes_left_in_buffer % entry_len;
500   std::string overlap2_name;
501   size_t overlap2_index = 0;
502   if (leftover != 0) {
503     file_data.erase(file_data.size() - 1);
504     file_data += ' ';
505     overlap2_name = std::string(leftover - 1, 'x');
506     file_data += overlap2_name + '\n';
507     overlap2_index = index - 1;
508   }
509 
510   // Now add a few entries on the next page.
511   for (size_t start = index; index < start + 10; index++) {
512     file_data += CreateEntry(index);
513   }
514 
515   ASSERT_TRUE(android::base::WriteStringToFile(file_data, tf.path, 0660, getuid(), getgid()));
516 
517   FileMaps maps(tf.path);
518   ASSERT_TRUE(maps.Parse());
519   EXPECT_EQ(index, maps.Total());
520   // Verify all of the maps.
521   for (size_t i = 0; i < index; i++) {
522     auto info = maps.Get(i);
523     ASSERT_TRUE(info != nullptr) << "Failed verifying index " + std::to_string(i);
524     EXPECT_EQ(i * 4096, info->start()) << "Failed verifying index " + std::to_string(i);
525     EXPECT_EQ((i + 1) * 4096, info->end()) << "Failed verifying index " + std::to_string(i);
526     EXPECT_EQ(0U, info->offset()) << "Failed verifying index " + std::to_string(i);
527     if (overlap1_index != 0 && i == overlap1_index) {
528       EXPECT_EQ(overlap1_name, info->name())
529           << "Failed verifying overlap1 name " + std::to_string(i);
530     } else if (overlap2_index != 0 && i == overlap2_index) {
531       EXPECT_EQ(overlap2_name, info->name())
532           << "Failed verifying overlap2 name " + std::to_string(i);
533     } else {
534       EXPECT_EQ("", info->name()) << "Failed verifying index " + std::to_string(i);
535     }
536   }
537 }
538 
TEST(MapsTest,file_should_fail)539 TEST(MapsTest, file_should_fail) {
540   TemporaryFile tf;
541   ASSERT_TRUE(tf.fd != -1);
542 
543   ASSERT_TRUE(android::base::WriteStringToFile(
544       "7ffff7dda000-7ffff7dfd7ffff7ff3000-7ffff7ff4000 ---p 0000f000 fc:02 44171565\n", tf.path,
545       0660, getuid(), getgid()));
546 
547   FileMaps maps(tf.path);
548 
549   ASSERT_FALSE(maps.Parse());
550 }
551 
552 // Create a maps file that is extremely large.
TEST(MapsTest,large_file)553 TEST(MapsTest, large_file) {
554   TemporaryFile tf;
555   ASSERT_TRUE(tf.fd != -1);
556 
557   std::string file_data;
558   uint64_t start = 0x700000;
559   for (size_t i = 0; i < 5000; i++) {
560     file_data +=
561         android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r-xp 1000 00:0 0 /fake%zu.so\n",
562                                     start + i * 4096, start + (i + 1) * 4096, i);
563   }
564 
565   ASSERT_TRUE(android::base::WriteStringToFile(file_data, tf.path, 0660, getuid(), getgid()));
566 
567   FileMaps maps(tf.path);
568 
569   ASSERT_TRUE(maps.Parse());
570   ASSERT_EQ(5000U, maps.Total());
571   for (size_t i = 0; i < 5000; i++) {
572     auto info = maps.Get(i);
573     EXPECT_EQ(start + i * 4096, info->start()) << "Failed at map " + std::to_string(i);
574     EXPECT_EQ(start + (i + 1) * 4096, info->end()) << "Failed at map " + std::to_string(i);
575     std::string name = "/fake" + std::to_string(i) + ".so";
576     EXPECT_EQ(name, info->name()) << "Failed at map " + std::to_string(i);
577   }
578 }
579 
TEST(MapsTest,find)580 TEST(MapsTest, find) {
581   BufferMaps maps(
582       "1000-2000 r--p 00000010 00:00 0 /system/lib/fake1.so\n"
583       "3000-4000 -w-p 00000020 00:00 0 /system/lib/fake2.so\n"
584       "6000-8000 --xp 00000030 00:00 0 /system/lib/fake3.so\n"
585       "a000-b000 rw-p 00000040 00:00 0 /system/lib/fake4.so\n"
586       "e000-f000 rwxp 00000050 00:00 0 /system/lib/fake5.so\n");
587   ASSERT_TRUE(maps.Parse());
588   ASSERT_EQ(5U, maps.Total());
589 
590   EXPECT_TRUE(maps.Find(0x500) == nullptr);
591   EXPECT_TRUE(maps.Find(0x2000) == nullptr);
592   EXPECT_TRUE(maps.Find(0x5010) == nullptr);
593   EXPECT_TRUE(maps.Find(0x9a00) == nullptr);
594   EXPECT_TRUE(maps.Find(0xf000) == nullptr);
595   EXPECT_TRUE(maps.Find(0xf010) == nullptr);
596 
597   auto info = maps.Find(0x1000);
598   ASSERT_TRUE(info != nullptr);
599   EXPECT_EQ(0x1000U, info->start());
600   EXPECT_EQ(0x2000U, info->end());
601   EXPECT_EQ(0x10U, info->offset());
602   EXPECT_EQ(PROT_READ, info->flags());
603   EXPECT_EQ("/system/lib/fake1.so", info->name());
604 
605   info = maps.Find(0x3020);
606   ASSERT_TRUE(info != nullptr);
607   EXPECT_EQ(0x3000U, info->start());
608   EXPECT_EQ(0x4000U, info->end());
609   EXPECT_EQ(0x20U, info->offset());
610   EXPECT_EQ(PROT_WRITE, info->flags());
611   EXPECT_EQ("/system/lib/fake2.so", info->name());
612 
613   info = maps.Find(0x6020);
614   ASSERT_TRUE(info != nullptr);
615   EXPECT_EQ(0x6000U, info->start());
616   EXPECT_EQ(0x8000U, info->end());
617   EXPECT_EQ(0x30U, info->offset());
618   EXPECT_EQ(PROT_EXEC, info->flags());
619   EXPECT_EQ("/system/lib/fake3.so", info->name());
620 
621   info = maps.Find(0xafff);
622   ASSERT_TRUE(info != nullptr);
623   EXPECT_EQ(0xa000U, info->start());
624   EXPECT_EQ(0xb000U, info->end());
625   EXPECT_EQ(0x40U, info->offset());
626   EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags());
627   EXPECT_EQ("/system/lib/fake4.so", info->name());
628 
629   info = maps.Find(0xe500);
630   ASSERT_TRUE(info != nullptr);
631   EXPECT_EQ(0xe000U, info->start());
632   EXPECT_EQ(0xf000U, info->end());
633   EXPECT_EQ(0x50U, info->offset());
634   EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags());
635   EXPECT_EQ("/system/lib/fake5.so", info->name());
636 }
637 
TEST(MapsTest,sort)638 TEST(MapsTest, sort) {
639   Maps maps;
640 
641   maps.Add(0x8000, 0x9000, 0, 0, "", 0);
642   maps.Add(0x7000, 0x8000, 0, 0, "lib.so", 0);
643   maps.Add(0x6000, 0x7000, 0, 0, "", 0);
644   maps.Add(0x5000, 0x6000, 0, 0, "lib.so", 0);
645   maps.Add(0x4000, 0x5000, 0, 0, "", 0);
646   maps.Add(0x3000, 0x4000, 0, 0, "", 0);
647   maps.Add(0x2000, 0x3000, 0, 0, "lib.so", 0);
648   maps.Add(0x1000, 0x2000, 0, 0, "", 0);
649 
650   maps.Sort();
651 
652   EXPECT_EQ(0x1000UL, maps.Get(0)->start());
653   EXPECT_EQ(nullptr, maps.Get(0)->prev_map());
654   EXPECT_EQ(maps.Get(1), maps.Get(0)->next_map());
655   EXPECT_EQ(nullptr, maps.Get(0)->GetPrevRealMap());
656   EXPECT_EQ(nullptr, maps.Get(0)->GetNextRealMap());
657 
658   EXPECT_EQ(0x2000UL, maps.Get(1)->start());
659   EXPECT_EQ(maps.Get(0), maps.Get(1)->prev_map());
660   EXPECT_EQ(maps.Get(2), maps.Get(1)->next_map());
661   EXPECT_EQ(nullptr, maps.Get(1)->GetPrevRealMap());
662   EXPECT_EQ(maps.Get(4), maps.Get(1)->GetNextRealMap());
663 
664   EXPECT_EQ(0x3000UL, maps.Get(2)->start());
665   EXPECT_EQ(maps.Get(1), maps.Get(2)->prev_map());
666   EXPECT_EQ(maps.Get(3), maps.Get(2)->next_map());
667   EXPECT_EQ(nullptr, maps.Get(2)->GetPrevRealMap());
668   EXPECT_EQ(nullptr, maps.Get(2)->GetNextRealMap());
669 
670   EXPECT_EQ(0x4000UL, maps.Get(3)->start());
671   EXPECT_EQ(maps.Get(2), maps.Get(3)->prev_map());
672   EXPECT_EQ(maps.Get(4), maps.Get(3)->next_map());
673   EXPECT_EQ(nullptr, maps.Get(3)->GetPrevRealMap());
674   EXPECT_EQ(nullptr, maps.Get(3)->GetNextRealMap());
675 
676   EXPECT_EQ(0x5000UL, maps.Get(4)->start());
677   EXPECT_EQ(maps.Get(3), maps.Get(4)->prev_map());
678   EXPECT_EQ(maps.Get(5), maps.Get(4)->next_map());
679   EXPECT_EQ(maps.Get(1), maps.Get(4)->GetPrevRealMap());
680   EXPECT_EQ(maps.Get(6), maps.Get(4)->GetNextRealMap());
681 
682   EXPECT_EQ(0x6000UL, maps.Get(5)->start());
683   EXPECT_EQ(maps.Get(4), maps.Get(5)->prev_map());
684   EXPECT_EQ(maps.Get(6), maps.Get(5)->next_map());
685   EXPECT_EQ(nullptr, maps.Get(5)->GetPrevRealMap());
686   EXPECT_EQ(nullptr, maps.Get(5)->GetNextRealMap());
687 
688   EXPECT_EQ(0x7000UL, maps.Get(6)->start());
689   EXPECT_EQ(maps.Get(5), maps.Get(6)->prev_map());
690   EXPECT_EQ(maps.Get(7), maps.Get(6)->next_map());
691   EXPECT_EQ(maps.Get(4), maps.Get(6)->GetPrevRealMap());
692   EXPECT_EQ(nullptr, maps.Get(6)->GetNextRealMap());
693 
694   EXPECT_EQ(0x8000UL, maps.Get(7)->start());
695   EXPECT_EQ(maps.Get(6), maps.Get(7)->prev_map());
696   EXPECT_EQ(nullptr, maps.Get(7)->next_map());
697   EXPECT_EQ(nullptr, maps.Get(7)->GetPrevRealMap());
698   EXPECT_EQ(nullptr, maps.Get(7)->GetNextRealMap());
699 }
700 
TEST(MapsTest,sort_empty)701 TEST(MapsTest, sort_empty) {
702   Maps maps;
703 
704   maps.Sort();
705 
706   EXPECT_EQ(0ULL, maps.Total());
707 }
708 
709 }  // namespace unwindstack
710