xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/LocalUpdatableMapsTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
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