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