xref: /aosp_15_r20/system/libprocinfo/process_map_test.cpp (revision e7c5e80fc9b28c04f5db9de8d2855377d05126c5)
1*e7c5e80fSMitch Phillips /*
2*e7c5e80fSMitch Phillips  * Copyright (C) 2018 The Android Open Source Project
3*e7c5e80fSMitch Phillips  *
4*e7c5e80fSMitch Phillips  * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c5e80fSMitch Phillips  * you may not use this file except in compliance with the License.
6*e7c5e80fSMitch Phillips  * You may obtain a copy of the License at
7*e7c5e80fSMitch Phillips  *
8*e7c5e80fSMitch Phillips  *      http://www.apache.org/licenses/LICENSE-2.0
9*e7c5e80fSMitch Phillips  *
10*e7c5e80fSMitch Phillips  * Unless required by applicable law or agreed to in writing, software
11*e7c5e80fSMitch Phillips  * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c5e80fSMitch Phillips  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c5e80fSMitch Phillips  * See the License for the specific language governing permissions and
14*e7c5e80fSMitch Phillips  * limitations under the License.
15*e7c5e80fSMitch Phillips  */
16*e7c5e80fSMitch Phillips 
17*e7c5e80fSMitch Phillips #include <procinfo/process_map.h>
18*e7c5e80fSMitch Phillips 
19*e7c5e80fSMitch Phillips #include <inttypes.h>
20*e7c5e80fSMitch Phillips #include <sys/mman.h>
21*e7c5e80fSMitch Phillips #include <unistd.h>
22*e7c5e80fSMitch Phillips 
23*e7c5e80fSMitch Phillips #include <string>
24*e7c5e80fSMitch Phillips #include <vector>
25*e7c5e80fSMitch Phillips 
26*e7c5e80fSMitch Phillips #include <android-base/file.h>
27*e7c5e80fSMitch Phillips #include <android-base/stringprintf.h>
28*e7c5e80fSMitch Phillips 
29*e7c5e80fSMitch Phillips #include <gtest/gtest.h>
30*e7c5e80fSMitch Phillips 
31*e7c5e80fSMitch Phillips using android::procinfo::MapInfo;
32*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFile)33*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFile) {
34*e7c5e80fSMitch Phillips   std::string map_file = android::base::GetExecutableDirectory() + "/testdata/maps";
35*e7c5e80fSMitch Phillips   std::vector<android::procinfo::MapInfo> maps;
36*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::procinfo::ReadMapFile(
37*e7c5e80fSMitch Phillips       map_file, [&](const android::procinfo::MapInfo& mapinfo) { maps.emplace_back(mapinfo); }));
38*e7c5e80fSMitch Phillips   ASSERT_EQ(2043u, maps.size());
39*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[0].start, 0x12c00000ULL);
40*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[0].end, 0x2ac00000ULL);
41*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[0].flags, PROT_READ | PROT_WRITE);
42*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[0].pgoff, 0ULL);
43*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[0].inode, 10267643UL);
44*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[0].name, "[anon:dalvik-main space (region space)]");
45*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[876].start, 0x70e6c4f000ULL);
46*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[876].end, 0x70e6c6b000ULL);
47*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[876].flags, PROT_READ | PROT_EXEC);
48*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[876].pgoff, 0ULL);
49*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[876].inode, 2407UL);
50*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[876].name, "/system/lib64/libutils.so");
51*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[1260].start, 0x70e96fa000ULL);
52*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[1260].end, 0x70e96fb000ULL);
53*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[1260].flags, PROT_READ);
54*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[1260].pgoff, 0ULL);
55*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[1260].inode, 10266154UL);
56*e7c5e80fSMitch Phillips   ASSERT_EQ(maps[1260].name,
57*e7c5e80fSMitch Phillips             "[anon:dalvik-classes.dex extracted in memory from "
58*e7c5e80fSMitch Phillips             "/data/app/com.google.sample.tunnel-HGGRU03Gu1Mwkf_-RnFmvw==/base.apk]");
59*e7c5e80fSMitch Phillips }
60*e7c5e80fSMitch Phillips 
TEST(process_map,ReadProcessMaps)61*e7c5e80fSMitch Phillips TEST(process_map, ReadProcessMaps) {
62*e7c5e80fSMitch Phillips   std::vector<android::procinfo::MapInfo> maps;
63*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::procinfo::ReadProcessMaps(
64*e7c5e80fSMitch Phillips       getpid(), [&](const android::procinfo::MapInfo& mapinfo) { maps.emplace_back(mapinfo); }));
65*e7c5e80fSMitch Phillips   ASSERT_GT(maps.size(), 0u);
66*e7c5e80fSMitch Phillips   maps.clear();
67*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::procinfo::ReadProcessMaps(getpid(), &maps));
68*e7c5e80fSMitch Phillips   ASSERT_GT(maps.size(), 0u);
69*e7c5e80fSMitch Phillips }
70*e7c5e80fSMitch Phillips 
71*e7c5e80fSMitch Phillips extern "C" void malloc_disable();
72*e7c5e80fSMitch Phillips extern "C" void malloc_enable();
73*e7c5e80fSMitch Phillips 
74*e7c5e80fSMitch Phillips struct TestMapInfo {
75*e7c5e80fSMitch Phillips   TestMapInfo() = default;
TestMapInfoTestMapInfo76*e7c5e80fSMitch Phillips   TestMapInfo(uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
77*e7c5e80fSMitch Phillips               const char* new_name, bool isShared)
78*e7c5e80fSMitch Phillips       : start(start), end(end), flags(flags), pgoff(pgoff), inode(inode), isShared(isShared) {
79*e7c5e80fSMitch Phillips     strcpy(name, new_name);
80*e7c5e80fSMitch Phillips   }
81*e7c5e80fSMitch Phillips   uint64_t start = 0;
82*e7c5e80fSMitch Phillips   uint64_t end = 0;
83*e7c5e80fSMitch Phillips   uint16_t flags = 0;
84*e7c5e80fSMitch Phillips   uint64_t pgoff = 0;
85*e7c5e80fSMitch Phillips   ino_t inode = 0;
86*e7c5e80fSMitch Phillips   char name[100] = {};
87*e7c5e80fSMitch Phillips   bool isShared = false;
88*e7c5e80fSMitch Phillips };
89*e7c5e80fSMitch Phillips 
VerifyReadMapFileAsyncSafe(const char * maps_data,const std::vector<TestMapInfo> & expected_info)90*e7c5e80fSMitch Phillips void VerifyReadMapFileAsyncSafe(const char* maps_data,
91*e7c5e80fSMitch Phillips                                 const std::vector<TestMapInfo>& expected_info) {
92*e7c5e80fSMitch Phillips   TemporaryFile tf;
93*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::base::WriteStringToFd(maps_data, tf.fd));
94*e7c5e80fSMitch Phillips 
95*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> saved_info(expected_info.size());
96*e7c5e80fSMitch Phillips   size_t num_maps = 0;
97*e7c5e80fSMitch Phillips 
98*e7c5e80fSMitch Phillips   auto callback = [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, ino_t inode,
99*e7c5e80fSMitch Phillips                       const char* name, bool shared) {
100*e7c5e80fSMitch Phillips     if (num_maps != saved_info.size()) {
101*e7c5e80fSMitch Phillips       TestMapInfo& saved = saved_info[num_maps];
102*e7c5e80fSMitch Phillips       saved.start = start;
103*e7c5e80fSMitch Phillips       saved.end = end;
104*e7c5e80fSMitch Phillips       saved.flags = flags;
105*e7c5e80fSMitch Phillips       saved.pgoff = pgoff;
106*e7c5e80fSMitch Phillips       saved.inode = inode;
107*e7c5e80fSMitch Phillips       strcpy(saved.name, name);
108*e7c5e80fSMitch Phillips       saved.isShared = shared;
109*e7c5e80fSMitch Phillips     }
110*e7c5e80fSMitch Phillips     num_maps++;
111*e7c5e80fSMitch Phillips   };
112*e7c5e80fSMitch Phillips 
113*e7c5e80fSMitch Phillips   std::vector<char> buffer(64 * 1024);
114*e7c5e80fSMitch Phillips 
115*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
116*e7c5e80fSMitch Phillips   // Any allocations will block after this call.
117*e7c5e80fSMitch Phillips   malloc_disable();
118*e7c5e80fSMitch Phillips #endif
119*e7c5e80fSMitch Phillips 
120*e7c5e80fSMitch Phillips   bool parsed =
121*e7c5e80fSMitch Phillips       android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer.data(), buffer.size(), callback);
122*e7c5e80fSMitch Phillips 
123*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
124*e7c5e80fSMitch Phillips   malloc_enable();
125*e7c5e80fSMitch Phillips #endif
126*e7c5e80fSMitch Phillips 
127*e7c5e80fSMitch Phillips   ASSERT_TRUE(parsed) << "Parsing of data failed:\n" << maps_data;
128*e7c5e80fSMitch Phillips   ASSERT_EQ(expected_info.size(), num_maps);
129*e7c5e80fSMitch Phillips   for (size_t i = 0; i < expected_info.size(); i++) {
130*e7c5e80fSMitch Phillips     const TestMapInfo& expected = expected_info[i];
131*e7c5e80fSMitch Phillips     const TestMapInfo& saved = saved_info[i];
132*e7c5e80fSMitch Phillips     EXPECT_EQ(expected.start, saved.start);
133*e7c5e80fSMitch Phillips     EXPECT_EQ(expected.end, saved.end);
134*e7c5e80fSMitch Phillips     EXPECT_EQ(expected.flags, saved.flags);
135*e7c5e80fSMitch Phillips     EXPECT_EQ(expected.pgoff, saved.pgoff);
136*e7c5e80fSMitch Phillips     EXPECT_EQ(expected.inode, saved.inode);
137*e7c5e80fSMitch Phillips     EXPECT_STREQ(expected.name, saved.name);
138*e7c5e80fSMitch Phillips     EXPECT_EQ(expected.isShared, saved.isShared);
139*e7c5e80fSMitch Phillips   }
140*e7c5e80fSMitch Phillips }
141*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_invalid)142*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_invalid) {
143*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> expected_info;
144*e7c5e80fSMitch Phillips 
145*e7c5e80fSMitch Phillips   VerifyReadMapFileAsyncSafe("12c00000-2ac00000", expected_info);
146*e7c5e80fSMitch Phillips }
147*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_single)148*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_single) {
149*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> expected_info;
150*e7c5e80fSMitch Phillips   expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643,
151*e7c5e80fSMitch Phillips                              "/lib/fake.so", false);
152*e7c5e80fSMitch Phillips 
153*e7c5e80fSMitch Phillips   VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so",
154*e7c5e80fSMitch Phillips                              expected_info);
155*e7c5e80fSMitch Phillips }
156*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_single_with_newline)157*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_single_with_newline) {
158*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> expected_info;
159*e7c5e80fSMitch Phillips   expected_info.emplace_back(0x12c00000, 0x2ac00000, PROT_READ | PROT_WRITE, 0x100, 10267643,
160*e7c5e80fSMitch Phillips                              "/lib/fake.so", false);
161*e7c5e80fSMitch Phillips 
162*e7c5e80fSMitch Phillips   VerifyReadMapFileAsyncSafe("12c00000-2ac00000 rw-p 00000100 00:05 10267643 /lib/fake.so\n",
163*e7c5e80fSMitch Phillips                              expected_info);
164*e7c5e80fSMitch Phillips }
165*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_single_no_library)166*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_single_no_library) {
167*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> expected_info;
168*e7c5e80fSMitch Phillips   expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 0xb00, 101, "",
169*e7c5e80fSMitch Phillips                              false);
170*e7c5e80fSMitch Phillips 
171*e7c5e80fSMitch Phillips   VerifyReadMapFileAsyncSafe("a0000-c0000 rwxp 00000b00 00:05 101", expected_info);
172*e7c5e80fSMitch Phillips }
173*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_multiple)174*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_multiple) {
175*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> expected_info;
176*e7c5e80fSMitch Phillips   expected_info.emplace_back(0xa0000, 0xc0000, PROT_READ | PROT_WRITE | PROT_EXEC, 1, 100, "",
177*e7c5e80fSMitch Phillips                              false);
178*e7c5e80fSMitch Phillips   expected_info.emplace_back(0xd0000, 0xe0000, PROT_READ, 2, 101, "/lib/libsomething1.so", false);
179*e7c5e80fSMitch Phillips   expected_info.emplace_back(0xf0000, 0x100000, PROT_WRITE, 3, 102, "/lib/libsomething2.so", false);
180*e7c5e80fSMitch Phillips   expected_info.emplace_back(0x110000, 0x120000, PROT_EXEC, 4, 103, "[anon:something or another]",
181*e7c5e80fSMitch Phillips                              false);
182*e7c5e80fSMitch Phillips   expected_info.emplace_back(0x130000, 0x140000, PROT_READ, 5, 104, "/lib/libsomething3.so", true);
183*e7c5e80fSMitch Phillips 
184*e7c5e80fSMitch Phillips   std::string map_data =
185*e7c5e80fSMitch Phillips       "0a0000-0c0000 rwxp 00000001 00:05 100\n"
186*e7c5e80fSMitch Phillips       "0d0000-0e0000 r--p 00000002 00:05 101  /lib/libsomething1.so\n"
187*e7c5e80fSMitch Phillips       "0f0000-100000 -w-p 00000003 00:05 102  /lib/libsomething2.so\n"
188*e7c5e80fSMitch Phillips       "110000-120000 --xp 00000004 00:05 103  [anon:something or another]\n"
189*e7c5e80fSMitch Phillips       "130000-140000 r--s 00000005 00:05 104  /lib/libsomething3.so\n";
190*e7c5e80fSMitch Phillips 
191*e7c5e80fSMitch Phillips   VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info);
192*e7c5e80fSMitch Phillips }
193*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_multiple_reads)194*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_multiple_reads) {
195*e7c5e80fSMitch Phillips   std::vector<TestMapInfo> expected_info;
196*e7c5e80fSMitch Phillips   std::string map_data;
197*e7c5e80fSMitch Phillips   uint64_t start = 0xa0000;
198*e7c5e80fSMitch Phillips   for (size_t i = 0; i < 10000; i++) {
199*e7c5e80fSMitch Phillips     map_data += android::base::StringPrintf("%" PRIx64 "-%" PRIx64 " r--p %zx 01:20 %zu fake.so\n",
200*e7c5e80fSMitch Phillips                                             start, start + 0x1000, i, 1000 + i);
201*e7c5e80fSMitch Phillips     expected_info.emplace_back(start, start + 0x1000, PROT_READ, i, 1000 + i, "fake.so", false);
202*e7c5e80fSMitch Phillips   }
203*e7c5e80fSMitch Phillips 
204*e7c5e80fSMitch Phillips   VerifyReadMapFileAsyncSafe(map_data.c_str(), expected_info);
205*e7c5e80fSMitch Phillips }
206*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_buffer_nullptr)207*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_buffer_nullptr) {
208*e7c5e80fSMitch Phillips   size_t num_calls = 0;
209*e7c5e80fSMitch Phillips   auto callback = [&](const android::procinfo::MapInfo&) { num_calls++; };
210*e7c5e80fSMitch Phillips 
211*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
212*e7c5e80fSMitch Phillips   // Any allocations will block after this call.
213*e7c5e80fSMitch Phillips   malloc_disable();
214*e7c5e80fSMitch Phillips #endif
215*e7c5e80fSMitch Phillips 
216*e7c5e80fSMitch Phillips   bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", nullptr, 10, callback);
217*e7c5e80fSMitch Phillips 
218*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
219*e7c5e80fSMitch Phillips   malloc_enable();
220*e7c5e80fSMitch Phillips #endif
221*e7c5e80fSMitch Phillips 
222*e7c5e80fSMitch Phillips   ASSERT_FALSE(parsed);
223*e7c5e80fSMitch Phillips   EXPECT_EQ(0UL, num_calls);
224*e7c5e80fSMitch Phillips }
225*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_buffer_size_zero)226*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_buffer_size_zero) {
227*e7c5e80fSMitch Phillips   size_t num_calls = 0;
228*e7c5e80fSMitch Phillips   auto callback = [&](const android::procinfo::MapInfo&) { num_calls++; };
229*e7c5e80fSMitch Phillips 
230*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
231*e7c5e80fSMitch Phillips   // Any allocations will block after this call.
232*e7c5e80fSMitch Phillips   malloc_disable();
233*e7c5e80fSMitch Phillips #endif
234*e7c5e80fSMitch Phillips 
235*e7c5e80fSMitch Phillips   char buffer[10];
236*e7c5e80fSMitch Phillips   bool parsed = android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, 0, callback);
237*e7c5e80fSMitch Phillips 
238*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
239*e7c5e80fSMitch Phillips   malloc_enable();
240*e7c5e80fSMitch Phillips #endif
241*e7c5e80fSMitch Phillips 
242*e7c5e80fSMitch Phillips   ASSERT_FALSE(parsed);
243*e7c5e80fSMitch Phillips   EXPECT_EQ(0UL, num_calls);
244*e7c5e80fSMitch Phillips }
245*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_buffer_too_small_no_calls)246*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_no_calls) {
247*e7c5e80fSMitch Phillips   size_t num_calls = 0;
248*e7c5e80fSMitch Phillips   auto callback = [&](const android::procinfo::MapInfo&) { num_calls++; };
249*e7c5e80fSMitch Phillips 
250*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
251*e7c5e80fSMitch Phillips   // Any allocations will block after this call.
252*e7c5e80fSMitch Phillips   malloc_disable();
253*e7c5e80fSMitch Phillips #endif
254*e7c5e80fSMitch Phillips 
255*e7c5e80fSMitch Phillips   char buffer[10];
256*e7c5e80fSMitch Phillips   bool parsed =
257*e7c5e80fSMitch Phillips       android::procinfo::ReadMapFileAsyncSafe("/proc/self/maps", buffer, sizeof(buffer), callback);
258*e7c5e80fSMitch Phillips 
259*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
260*e7c5e80fSMitch Phillips   malloc_enable();
261*e7c5e80fSMitch Phillips #endif
262*e7c5e80fSMitch Phillips 
263*e7c5e80fSMitch Phillips   ASSERT_FALSE(parsed);
264*e7c5e80fSMitch Phillips   EXPECT_EQ(0UL, num_calls);
265*e7c5e80fSMitch Phillips }
266*e7c5e80fSMitch Phillips 
TEST(process_map,ReadMapFileAsyncSafe_buffer_too_small_could_parse)267*e7c5e80fSMitch Phillips TEST(process_map, ReadMapFileAsyncSafe_buffer_too_small_could_parse) {
268*e7c5e80fSMitch Phillips   TemporaryFile tf;
269*e7c5e80fSMitch Phillips   ASSERT_TRUE(android::base::WriteStringToFd(
270*e7c5e80fSMitch Phillips       "0a0000-0c0000 rwxp 00000001 00:05 100    /fake/lib.so\n", tf.fd));
271*e7c5e80fSMitch Phillips 
272*e7c5e80fSMitch Phillips   size_t num_calls = 0;
273*e7c5e80fSMitch Phillips   auto callback = [&](const android::procinfo::MapInfo&) { num_calls++; };
274*e7c5e80fSMitch Phillips 
275*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
276*e7c5e80fSMitch Phillips   // Any allocations will block after this call.
277*e7c5e80fSMitch Phillips   malloc_disable();
278*e7c5e80fSMitch Phillips #endif
279*e7c5e80fSMitch Phillips 
280*e7c5e80fSMitch Phillips   char buffer[39];
281*e7c5e80fSMitch Phillips   bool parsed = android::procinfo::ReadMapFileAsyncSafe(tf.path, buffer, sizeof(buffer), callback);
282*e7c5e80fSMitch Phillips 
283*e7c5e80fSMitch Phillips #if defined(__BIONIC__)
284*e7c5e80fSMitch Phillips   malloc_enable();
285*e7c5e80fSMitch Phillips #endif
286*e7c5e80fSMitch Phillips 
287*e7c5e80fSMitch Phillips   ASSERT_FALSE(parsed);
288*e7c5e80fSMitch Phillips   EXPECT_EQ(0UL, num_calls);
289*e7c5e80fSMitch Phillips }
290*e7c5e80fSMitch Phillips 
291*e7c5e80fSMitch Phillips class ProcessMapMappedFileSize : public ::testing::Test {
292*e7c5e80fSMitch Phillips   protected:
SetUp()293*e7c5e80fSMitch Phillips     void SetUp() override {
294*e7c5e80fSMitch Phillips       ASSERT_NE(tf.fd, -1) << "open failed: " << strerror(errno);
295*e7c5e80fSMitch Phillips       ASSERT_EQ(ftruncate(tf.fd, kFileSize), 0) << "ftruncate failed: " << strerror(errno);
296*e7c5e80fSMitch Phillips     }
297*e7c5e80fSMitch Phillips 
TearDown()298*e7c5e80fSMitch Phillips     void TearDown() override {
299*e7c5e80fSMitch Phillips       ASSERT_EQ(munmap(reinterpret_cast<void*>(map.start), map.end-map.start), 0)
300*e7c5e80fSMitch Phillips                 << "munmap failed: " << strerror(errno);
301*e7c5e80fSMitch Phillips     }
302*e7c5e80fSMitch Phillips 
PageAlign(uint64_t x)303*e7c5e80fSMitch Phillips     uint64_t PageAlign(uint64_t x) {
304*e7c5e80fSMitch Phillips       const uint64_t kPageSize = getpagesize();
305*e7c5e80fSMitch Phillips       return (x + kPageSize - 1) & ~(kPageSize - 1);
306*e7c5e80fSMitch Phillips     }
307*e7c5e80fSMitch Phillips 
CreateFileMapping(uint64_t size,uint64_t offset)308*e7c5e80fSMitch Phillips     bool CreateFileMapping(uint64_t size, uint64_t offset) {
309*e7c5e80fSMitch Phillips       void *addr = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, tf.fd, offset);
310*e7c5e80fSMitch Phillips       if (addr == MAP_FAILED) {
311*e7c5e80fSMitch Phillips         return false;
312*e7c5e80fSMitch Phillips       }
313*e7c5e80fSMitch Phillips 
314*e7c5e80fSMitch Phillips       map.start = reinterpret_cast<uint64_t>(addr);
315*e7c5e80fSMitch Phillips       map.end = PageAlign(map.start + size);
316*e7c5e80fSMitch Phillips       map.pgoff = offset;
317*e7c5e80fSMitch Phillips 
318*e7c5e80fSMitch Phillips       return true;
319*e7c5e80fSMitch Phillips     }
320*e7c5e80fSMitch Phillips 
321*e7c5e80fSMitch Phillips     TemporaryFile tf;
322*e7c5e80fSMitch Phillips     const size_t kFileSize = 65536;
323*e7c5e80fSMitch Phillips     android::procinfo::MapInfo map = android::procinfo::MapInfo(0 /* start */, 0 /* end */,
324*e7c5e80fSMitch Phillips                                                                 PROT_READ, 0 /* pgoff */,
325*e7c5e80fSMitch Phillips                                                                 0 /* inode */, tf.path, false);
326*e7c5e80fSMitch Phillips };
327*e7c5e80fSMitch Phillips 
TEST_F(ProcessMapMappedFileSize,map_size_greater_than_file_size)328*e7c5e80fSMitch Phillips TEST_F(ProcessMapMappedFileSize, map_size_greater_than_file_size) {
329*e7c5e80fSMitch Phillips   uint64_t size = 2 * kFileSize;
330*e7c5e80fSMitch Phillips   uint64_t offset = 0;
331*e7c5e80fSMitch Phillips 
332*e7c5e80fSMitch Phillips   ASSERT_TRUE(CreateFileMapping(size, offset));
333*e7c5e80fSMitch Phillips   uint64_t mapped_file_size = android::procinfo::MappedFileSize(map);
334*e7c5e80fSMitch Phillips 
335*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, kFileSize);
336*e7c5e80fSMitch Phillips }
337*e7c5e80fSMitch Phillips 
TEST_F(ProcessMapMappedFileSize,map_size_less_than_file_size)338*e7c5e80fSMitch Phillips TEST_F(ProcessMapMappedFileSize, map_size_less_than_file_size) {
339*e7c5e80fSMitch Phillips   uint64_t size = kFileSize / 2;
340*e7c5e80fSMitch Phillips   uint64_t offset = 0;
341*e7c5e80fSMitch Phillips 
342*e7c5e80fSMitch Phillips   ASSERT_TRUE(CreateFileMapping(size, offset));
343*e7c5e80fSMitch Phillips   uint64_t mapped_file_size = android::procinfo::MappedFileSize(map);
344*e7c5e80fSMitch Phillips 
345*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, size);
346*e7c5e80fSMitch Phillips }
347*e7c5e80fSMitch Phillips 
TEST_F(ProcessMapMappedFileSize,map_size_equal_file_size)348*e7c5e80fSMitch Phillips TEST_F(ProcessMapMappedFileSize, map_size_equal_file_size) {
349*e7c5e80fSMitch Phillips   uint64_t size = kFileSize;
350*e7c5e80fSMitch Phillips   uint64_t offset = 0;
351*e7c5e80fSMitch Phillips 
352*e7c5e80fSMitch Phillips   ASSERT_TRUE(CreateFileMapping(size, offset));
353*e7c5e80fSMitch Phillips   uint64_t mapped_file_size = android::procinfo::MappedFileSize(map);
354*e7c5e80fSMitch Phillips 
355*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, kFileSize);
356*e7c5e80fSMitch Phillips 
357*e7c5e80fSMitch Phillips }
358*e7c5e80fSMitch Phillips 
TEST_F(ProcessMapMappedFileSize,offset_greater_than_file_size)359*e7c5e80fSMitch Phillips TEST_F(ProcessMapMappedFileSize, offset_greater_than_file_size) {
360*e7c5e80fSMitch Phillips   uint64_t size = kFileSize;
361*e7c5e80fSMitch Phillips   uint64_t offset = kFileSize * 2;
362*e7c5e80fSMitch Phillips 
363*e7c5e80fSMitch Phillips   ASSERT_TRUE(CreateFileMapping(size, offset));
364*e7c5e80fSMitch Phillips   uint64_t mapped_file_size = android::procinfo::MappedFileSize(map);
365*e7c5e80fSMitch Phillips 
366*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, 0UL);
367*e7c5e80fSMitch Phillips }
368*e7c5e80fSMitch Phillips 
TEST_F(ProcessMapMappedFileSize,invalid_map_name)369*e7c5e80fSMitch Phillips TEST_F(ProcessMapMappedFileSize, invalid_map_name) {
370*e7c5e80fSMitch Phillips   uint64_t size = kFileSize;
371*e7c5e80fSMitch Phillips   uint64_t offset = 0;
372*e7c5e80fSMitch Phillips 
373*e7c5e80fSMitch Phillips   ASSERT_TRUE(CreateFileMapping(size, offset));
374*e7c5e80fSMitch Phillips 
375*e7c5e80fSMitch Phillips   // Name is empty
376*e7c5e80fSMitch Phillips   map.name = "";
377*e7c5e80fSMitch Phillips   uint64_t mapped_file_size = android::procinfo::MappedFileSize(map);
378*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, 0UL);
379*e7c5e80fSMitch Phillips 
380*e7c5e80fSMitch Phillips   // Is device path
381*e7c5e80fSMitch Phillips   map.name = "/dev/";
382*e7c5e80fSMitch Phillips   mapped_file_size = android::procinfo::MappedFileSize(map);
383*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, 0UL);
384*e7c5e80fSMitch Phillips 
385*e7c5e80fSMitch Phillips   // Does not start with '/'
386*e7c5e80fSMitch Phillips   map.name = "[anon:bss]";
387*e7c5e80fSMitch Phillips   mapped_file_size = android::procinfo::MappedFileSize(map);
388*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, 0UL);
389*e7c5e80fSMitch Phillips 
390*e7c5e80fSMitch Phillips   // File non-existent
391*e7c5e80fSMitch Phillips   map.name = "/tmp/non_existent_file";
392*e7c5e80fSMitch Phillips   mapped_file_size = android::procinfo::MappedFileSize(map);
393*e7c5e80fSMitch Phillips   ASSERT_EQ(mapped_file_size, 0UL);
394*e7c5e80fSMitch Phillips }
395*e7c5e80fSMitch Phillips 
CreateMapWithOnlyName(const char * name)396*e7c5e80fSMitch Phillips static MapInfo CreateMapWithOnlyName(const char* name) {
397*e7c5e80fSMitch Phillips   return MapInfo(0, 0, 0, UINT64_MAX, 0, name, false);
398*e7c5e80fSMitch Phillips }
399*e7c5e80fSMitch Phillips 
TEST(process_map,TaggedMappingNames)400*e7c5e80fSMitch Phillips TEST(process_map, TaggedMappingNames) {
401*e7c5e80fSMitch Phillips   MapInfo info = CreateMapWithOnlyName(
402*e7c5e80fSMitch Phillips       "[anon:mt:/data/local/tmp/debuggerd_test/arm64/debuggerd_test64+108000]");
403*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/data/local/tmp/debuggerd_test/arm64/debuggerd_test64");
404*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0x108000ull);
405*e7c5e80fSMitch Phillips 
406*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/data/local/tmp/debuggerd_test/arm64/debuggerd_test64+0]");
407*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/data/local/tmp/debuggerd_test/arm64/debuggerd_test64");
408*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0x0ull);
409*e7c5e80fSMitch Phillips 
410*e7c5e80fSMitch Phillips   info =
411*e7c5e80fSMitch Phillips       CreateMapWithOnlyName("[anon:mt:/data/local/tmp/debuggerd_test/arm64/debuggerd_test64+0000]");
412*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/data/local/tmp/debuggerd_test/arm64/debuggerd_test64");
413*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0x0ull);
414*e7c5e80fSMitch Phillips 
415*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName(
416*e7c5e80fSMitch Phillips       "[anon:mt:...ivetest64/bionic-unit-tests/bionic-loader-test-libs/libdlext_test.so+e000]");
417*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "...ivetest64/bionic-unit-tests/bionic-loader-test-libs/libdlext_test.so");
418*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xe000ull);
419*e7c5e80fSMitch Phillips 
420*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/x+e000]");
421*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/x");
422*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xe000ull);
423*e7c5e80fSMitch Phillips 
424*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/x+0]");
425*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/x");
426*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0x0ull);
427*e7c5e80fSMitch Phillips 
428*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/x+1]");
429*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/x");
430*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0x1ull);
431*e7c5e80fSMitch Phillips 
432*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/x+f]");
433*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/x");
434*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xfull);
435*e7c5e80fSMitch Phillips 
436*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/with/plus+/x+f]");
437*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/with/plus+/x");
438*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xfull);
439*e7c5e80fSMitch Phillips 
440*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/+with/mu+ltiple/plus+/x+f]");
441*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/+with/mu+ltiple/plus+/x");
442*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xfull);
443*e7c5e80fSMitch Phillips 
444*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:/bin/trailing/plus++f]");
445*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "/bin/trailing/plus+");
446*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xfull);
447*e7c5e80fSMitch Phillips 
448*e7c5e80fSMitch Phillips   info = CreateMapWithOnlyName("[anon:mt:++f]");
449*e7c5e80fSMitch Phillips   ASSERT_EQ(info.name, "+");
450*e7c5e80fSMitch Phillips   ASSERT_EQ(info.pgoff, 0xfull);
451*e7c5e80fSMitch Phillips }
452*e7c5e80fSMitch Phillips 
TEST(process_map,AlmostTaggedMappingNames)453*e7c5e80fSMitch Phillips TEST(process_map, AlmostTaggedMappingNames) {
454*e7c5e80fSMitch Phillips   for (const char* almost_tagged_name :
455*e7c5e80fSMitch Phillips        {"[anon:mt:/bin/x+]",
456*e7c5e80fSMitch Phillips         "[anon:mt:/bin/x]"
457*e7c5e80fSMitch Phillips         "[anon:mt:+]",
458*e7c5e80fSMitch Phillips         "[anon:mt", "[anon:mt:/bin/x+1", "[anon:mt:/bin/x+e000",
459*e7c5e80fSMitch Phillips         "anon:mt:/data/local/tmp/debuggerd_test/arm64/debuggerd_test64+e000]"}) {
460*e7c5e80fSMitch Phillips     MapInfo info = CreateMapWithOnlyName(almost_tagged_name);
461*e7c5e80fSMitch Phillips     ASSERT_EQ(info.name, almost_tagged_name);
462*e7c5e80fSMitch Phillips     ASSERT_EQ(info.pgoff, UINT64_MAX) << almost_tagged_name;
463*e7c5e80fSMitch Phillips   }
464*e7c5e80fSMitch Phillips }
465