xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/MapInfoTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
18*eb293b8fSAndroid Build Coastguard Worker #include <sys/mman.h>
19*eb293b8fSAndroid Build Coastguard Worker 
20*eb293b8fSAndroid Build Coastguard Worker #include <thread>
21*eb293b8fSAndroid Build Coastguard Worker 
22*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
23*eb293b8fSAndroid Build Coastguard Worker 
24*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/MapInfo.h>
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Maps.h>
26*eb293b8fSAndroid Build Coastguard Worker 
27*eb293b8fSAndroid Build Coastguard Worker #include "ElfFake.h"
28*eb293b8fSAndroid Build Coastguard Worker 
29*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
30*eb293b8fSAndroid Build Coastguard Worker 
TEST(MapInfoTest,maps_constructor_const_char)31*eb293b8fSAndroid Build Coastguard Worker TEST(MapInfoTest, maps_constructor_const_char) {
32*eb293b8fSAndroid Build Coastguard Worker   auto prev_map = MapInfo::Create(0, 0, 0, 0, "");
33*eb293b8fSAndroid Build Coastguard Worker   auto map_info = MapInfo::Create(prev_map, 1, 2, 3, 4, "map");
34*eb293b8fSAndroid Build Coastguard Worker 
35*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(prev_map.get(), map_info->prev_map().get());
36*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(1UL, map_info->start());
37*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(2UL, map_info->end());
38*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(3UL, map_info->offset());
39*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(4UL, map_info->flags());
40*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ("map", map_info->name());
41*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(UINT64_MAX, map_info->load_bias());
42*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0UL, map_info->elf_offset());
43*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(map_info->elf().get() == nullptr);
44*eb293b8fSAndroid Build Coastguard Worker }
45*eb293b8fSAndroid Build Coastguard Worker 
TEST(MapInfoTest,maps_constructor_string)46*eb293b8fSAndroid Build Coastguard Worker TEST(MapInfoTest, maps_constructor_string) {
47*eb293b8fSAndroid Build Coastguard Worker   std::string name("string_map");
48*eb293b8fSAndroid Build Coastguard Worker   auto prev_map = MapInfo::Create(0, 0, 0, 0, "");
49*eb293b8fSAndroid Build Coastguard Worker   auto map_info = MapInfo::Create(prev_map, 1, 2, 3, 4, name);
50*eb293b8fSAndroid Build Coastguard Worker 
51*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(prev_map, map_info->prev_map());
52*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(1UL, map_info->start());
53*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(2UL, map_info->end());
54*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(3UL, map_info->offset());
55*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(4UL, map_info->flags());
56*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ("string_map", map_info->name());
57*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(UINT64_MAX, map_info->load_bias());
58*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0UL, map_info->elf_offset());
59*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(map_info->elf().get() == nullptr);
60*eb293b8fSAndroid Build Coastguard Worker }
61*eb293b8fSAndroid Build Coastguard Worker 
TEST(MapInfoTest,real_map_check)62*eb293b8fSAndroid Build Coastguard Worker TEST(MapInfoTest, real_map_check) {
63*eb293b8fSAndroid Build Coastguard Worker   auto map1 = MapInfo::Create(0, 0x1000, 0, PROT_READ, "fake.so");
64*eb293b8fSAndroid Build Coastguard Worker   auto map2 = MapInfo::Create(map1, 0, 0, 0, 0, "");
65*eb293b8fSAndroid Build Coastguard Worker   auto map3 = MapInfo::Create(map2, 0x1000, 0x2000, 0x1000, PROT_READ | PROT_EXEC, "fake.so");
66*eb293b8fSAndroid Build Coastguard Worker 
67*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->prev_map());
68*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
69*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map2, map1->next_map());
70*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
71*eb293b8fSAndroid Build Coastguard Worker 
72*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map1, map2->prev_map());
73*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map2->GetPrevRealMap());
74*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map2->next_map());
75*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map2->GetNextRealMap());
76*eb293b8fSAndroid Build Coastguard Worker 
77*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map2, map3->prev_map());
78*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map1, map3->GetPrevRealMap());
79*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->next_map());
80*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
81*eb293b8fSAndroid Build Coastguard Worker 
82*eb293b8fSAndroid Build Coastguard Worker   // Verify that if the middle map is not blank, then the Get{Next,Prev}RealMap
83*eb293b8fSAndroid Build Coastguard Worker   // functions return nullptrs.
84*eb293b8fSAndroid Build Coastguard Worker   map2->set_offset(1);
85*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
86*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetNextRealMap());
87*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetPrevRealMap());
88*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
89*eb293b8fSAndroid Build Coastguard Worker   map2->set_offset(0);
90*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
91*eb293b8fSAndroid Build Coastguard Worker 
92*eb293b8fSAndroid Build Coastguard Worker   map2->set_flags(1);
93*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
94*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetNextRealMap());
95*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetPrevRealMap());
96*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
97*eb293b8fSAndroid Build Coastguard Worker   map2->set_flags(0);
98*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
99*eb293b8fSAndroid Build Coastguard Worker 
100*eb293b8fSAndroid Build Coastguard Worker   map2->set_name("something");
101*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
102*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetNextRealMap());
103*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetPrevRealMap());
104*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
105*eb293b8fSAndroid Build Coastguard Worker   map2->set_name("");
106*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
107*eb293b8fSAndroid Build Coastguard Worker 
108*eb293b8fSAndroid Build Coastguard Worker   // Verify if the map has the name [page size compat] it's still considered blank.
109*eb293b8fSAndroid Build Coastguard Worker   map2->set_name("[page size compat]");
110*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
111*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
112*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map1, map3->GetPrevRealMap());
113*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
114*eb293b8fSAndroid Build Coastguard Worker   map2->set_name("");
115*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
116*eb293b8fSAndroid Build Coastguard Worker 
117*eb293b8fSAndroid Build Coastguard Worker   // Verify that if the Get{Next,Prev}RealMap names must match.
118*eb293b8fSAndroid Build Coastguard Worker   map1->set_name("another");
119*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
120*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetNextRealMap());
121*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetPrevRealMap());
122*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
123*eb293b8fSAndroid Build Coastguard Worker   map1->set_name("fake.so");
124*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
125*eb293b8fSAndroid Build Coastguard Worker 
126*eb293b8fSAndroid Build Coastguard Worker   map3->set_name("another");
127*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetPrevRealMap());
128*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map1->GetNextRealMap());
129*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetPrevRealMap());
130*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(nullptr, map3->GetNextRealMap());
131*eb293b8fSAndroid Build Coastguard Worker   map3->set_name("fake.so");
132*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(map3, map1->GetNextRealMap());
133*eb293b8fSAndroid Build Coastguard Worker }
134*eb293b8fSAndroid Build Coastguard Worker 
TEST(MapInfoTest,get_function_name)135*eb293b8fSAndroid Build Coastguard Worker TEST(MapInfoTest, get_function_name) {
136*eb293b8fSAndroid Build Coastguard Worker   std::shared_ptr<Memory> empty;
137*eb293b8fSAndroid Build Coastguard Worker   ElfFake* elf = new ElfFake(empty);
138*eb293b8fSAndroid Build Coastguard Worker   ElfInterfaceFake* interface = new ElfInterfaceFake(empty);
139*eb293b8fSAndroid Build Coastguard Worker   elf->FakeSetInterface(interface);
140*eb293b8fSAndroid Build Coastguard Worker   interface->FakePushFunctionData(FunctionData("function", 1000));
141*eb293b8fSAndroid Build Coastguard Worker 
142*eb293b8fSAndroid Build Coastguard Worker   auto map_info = MapInfo::Create(1, 2, 3, 4, "");
143*eb293b8fSAndroid Build Coastguard Worker   map_info->set_elf(elf);
144*eb293b8fSAndroid Build Coastguard Worker 
145*eb293b8fSAndroid Build Coastguard Worker   SharedString name;
146*eb293b8fSAndroid Build Coastguard Worker   uint64_t offset;
147*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(map_info->GetFunctionName(1000, &name, &offset));
148*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ("function", name);
149*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(1000UL, offset);
150*eb293b8fSAndroid Build Coastguard Worker }
151*eb293b8fSAndroid Build Coastguard Worker 
TEST(MapInfoTest,multiple_thread_get_elf_fields)152*eb293b8fSAndroid Build Coastguard Worker TEST(MapInfoTest, multiple_thread_get_elf_fields) {
153*eb293b8fSAndroid Build Coastguard Worker   auto map_info = MapInfo::Create(0, 0, 0, 0, "");
154*eb293b8fSAndroid Build Coastguard Worker 
155*eb293b8fSAndroid Build Coastguard Worker   static constexpr size_t kNumConcurrentThreads = 100;
156*eb293b8fSAndroid Build Coastguard Worker   MapInfo::ElfFields* elf_fields[kNumConcurrentThreads];
157*eb293b8fSAndroid Build Coastguard Worker 
158*eb293b8fSAndroid Build Coastguard Worker   std::atomic_bool wait;
159*eb293b8fSAndroid Build Coastguard Worker   wait = true;
160*eb293b8fSAndroid Build Coastguard Worker   // Create all of the threads and have them do the call at the same time
161*eb293b8fSAndroid Build Coastguard Worker   // to make it likely that a race will occur.
162*eb293b8fSAndroid Build Coastguard Worker   std::vector<std::thread*> threads;
163*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
164*eb293b8fSAndroid Build Coastguard Worker     std::thread* thread = new std::thread([i, &wait, &map_info, &elf_fields]() {
165*eb293b8fSAndroid Build Coastguard Worker       while (wait)
166*eb293b8fSAndroid Build Coastguard Worker         ;
167*eb293b8fSAndroid Build Coastguard Worker       elf_fields[i] = &map_info->GetElfFields();
168*eb293b8fSAndroid Build Coastguard Worker     });
169*eb293b8fSAndroid Build Coastguard Worker     threads.push_back(thread);
170*eb293b8fSAndroid Build Coastguard Worker   }
171*eb293b8fSAndroid Build Coastguard Worker 
172*eb293b8fSAndroid Build Coastguard Worker   // Set them all going and wait for the threads to finish.
173*eb293b8fSAndroid Build Coastguard Worker   wait = false;
174*eb293b8fSAndroid Build Coastguard Worker   for (auto thread : threads) {
175*eb293b8fSAndroid Build Coastguard Worker     thread->join();
176*eb293b8fSAndroid Build Coastguard Worker     delete thread;
177*eb293b8fSAndroid Build Coastguard Worker   }
178*eb293b8fSAndroid Build Coastguard Worker 
179*eb293b8fSAndroid Build Coastguard Worker   // Now verify that all of elf fields are exactly the same and valid.
180*eb293b8fSAndroid Build Coastguard Worker   MapInfo::ElfFields* expected_elf_fields = &map_info->GetElfFields();
181*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(expected_elf_fields != nullptr);
182*eb293b8fSAndroid Build Coastguard Worker   for (size_t i = 0; i < kNumConcurrentThreads; i++) {
183*eb293b8fSAndroid Build Coastguard Worker     EXPECT_EQ(expected_elf_fields, elf_fields[i]) << "Thread " << i << " mismatched.";
184*eb293b8fSAndroid Build Coastguard Worker   }
185*eb293b8fSAndroid Build Coastguard Worker }
186*eb293b8fSAndroid Build Coastguard Worker 
TEST(MapInfoTest,elf_file_not_readable)187*eb293b8fSAndroid Build Coastguard Worker TEST(MapInfoTest, elf_file_not_readable) {
188*eb293b8fSAndroid Build Coastguard Worker   auto map_info_readable = MapInfo::Create(0, 0x1000, 0, PROT_READ, "fake.so");
189*eb293b8fSAndroid Build Coastguard Worker   map_info_readable->set_memory_backed_elf(true);
190*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(map_info_readable->ElfFileNotReadable());
191*eb293b8fSAndroid Build Coastguard Worker 
192*eb293b8fSAndroid Build Coastguard Worker   auto map_info_no_name = MapInfo::Create(0, 0x1000, 0, PROT_READ, "");
193*eb293b8fSAndroid Build Coastguard Worker   map_info_no_name->set_memory_backed_elf(true);
194*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(map_info_no_name->ElfFileNotReadable());
195*eb293b8fSAndroid Build Coastguard Worker 
196*eb293b8fSAndroid Build Coastguard Worker   auto map_info_bracket = MapInfo::Create(0, 0x2000, 0, PROT_READ, "[vdso]");
197*eb293b8fSAndroid Build Coastguard Worker   map_info_bracket->set_memory_backed_elf(true);
198*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(map_info_bracket->ElfFileNotReadable());
199*eb293b8fSAndroid Build Coastguard Worker 
200*eb293b8fSAndroid Build Coastguard Worker   auto map_info_memfd = MapInfo::Create(0, 0x3000, 0, PROT_READ, "/memfd:jit-cache");
201*eb293b8fSAndroid Build Coastguard Worker   map_info_memfd->set_memory_backed_elf(true);
202*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(map_info_memfd->ElfFileNotReadable());
203*eb293b8fSAndroid Build Coastguard Worker }
204*eb293b8fSAndroid Build Coastguard Worker 
205*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
206