• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- LinuxProcMapsTest.cpp ---------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "gmock/gmock.h"
10 #include "gtest/gtest.h"
11 
12 #include "Plugins/Process/Utility/LinuxProcMaps.h"
13 #include "lldb/Target/MemoryRegionInfo.h"
14 #include "lldb/Utility/Status.h"
15 #include <tuple>
16 
17 using namespace lldb_private;
18 
19 typedef std::tuple<const char *, MemoryRegionInfos, const char *>
20     LinuxProcMapsTestParams;
21 
22 // Wrapper for convenience because Range is usually begin, size
make_range(lldb::addr_t begin,lldb::addr_t end)23 static MemoryRegionInfo::RangeType make_range(lldb::addr_t begin,
24                                               lldb::addr_t end) {
25   MemoryRegionInfo::RangeType range(begin, 0);
26   range.SetRangeEnd(end);
27   return range;
28 }
29 
30 class LinuxProcMapsTestFixture
31     : public ::testing::TestWithParam<LinuxProcMapsTestParams> {
32 protected:
33   Status error;
34   std::string err_str;
35   MemoryRegionInfos regions;
36   LinuxMapCallback callback;
37 
SetUp()38   void SetUp() override {
39     callback = [this](llvm::Expected<MemoryRegionInfo> Info) {
40       if (Info) {
41         err_str.clear();
42         regions.push_back(*Info);
43         return true;
44       }
45 
46       err_str = toString(Info.takeError());
47       return false;
48     };
49   }
50 
check_regions(LinuxProcMapsTestParams params)51   void check_regions(LinuxProcMapsTestParams params) {
52     EXPECT_THAT(std::get<1>(params), testing::ContainerEq(regions));
53     ASSERT_EQ(std::get<2>(params), err_str);
54   }
55 };
56 
TEST_P(LinuxProcMapsTestFixture,ParseMapRegions)57 TEST_P(LinuxProcMapsTestFixture, ParseMapRegions) {
58   auto params = GetParam();
59   ParseLinuxMapRegions(std::get<0>(params), callback);
60   check_regions(params);
61 }
62 
63 // Note: ConstString("") != ConstString(nullptr)
64 // When a region has no name, it will have the latter in the MemoryRegionInfo
65 INSTANTIATE_TEST_CASE_P(
66     ProcMapTests, LinuxProcMapsTestFixture,
67     ::testing::Values(
68         // Nothing in nothing out
69         std::make_tuple("", MemoryRegionInfos{}, ""),
70         // Various formatting error conditions
71         std::make_tuple("55a4512f7000/55a451b68000 rw-p 00000000 00:00 0",
72                         MemoryRegionInfos{},
73                         "malformed /proc/{pid}/maps entry, missing dash "
74                         "between address range"),
75         std::make_tuple("0-0 rw", MemoryRegionInfos{},
76                         "malformed /proc/{pid}/maps entry, missing some "
77                         "portion of permissions"),
78         std::make_tuple("0-0 z--p 00000000 00:00 0", MemoryRegionInfos{},
79                         "unexpected /proc/{pid}/maps read permission char"),
80         std::make_tuple("0-0 rz-p 00000000 00:00 0", MemoryRegionInfos{},
81                         "unexpected /proc/{pid}/maps write permission char"),
82         std::make_tuple("0-0 rwzp 00000000 00:00 0", MemoryRegionInfos{},
83                         "unexpected /proc/{pid}/maps exec permission char"),
84         // Stops at first parsing error
85         std::make_tuple(
86             "0-1 rw-p 00000000 00:00 0 [abc]\n"
87             "0-0 rwzp 00000000 00:00 0\n"
88             "2-3 r-xp 00000000 00:00 0 [def]\n",
89             MemoryRegionInfos{
90                 MemoryRegionInfo(make_range(0, 1), MemoryRegionInfo::eYes,
91                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
92                                  MemoryRegionInfo::eYes, ConstString("[abc]"),
93                                  MemoryRegionInfo::eDontKnow, 0,
94                                  MemoryRegionInfo::eDontKnow),
95             },
96             "unexpected /proc/{pid}/maps exec permission char"),
97         // Single entry
98         std::make_tuple(
99             "55a4512f7000-55a451b68000 rw-p 00000000 00:00 0    [heap]",
100             MemoryRegionInfos{
101                 MemoryRegionInfo(make_range(0x55a4512f7000, 0x55a451b68000),
102                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
103                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
104                                  ConstString("[heap]"),
105                                  MemoryRegionInfo::eDontKnow, 0,
106                                  MemoryRegionInfo::eDontKnow),
107             },
108             ""),
109         // Multiple entries
110         std::make_tuple(
111             "7fc090021000-7fc094000000 ---p 00000000 00:00 0\n"
112             "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 "
113             "[vsyscall]",
114             MemoryRegionInfos{
115                 MemoryRegionInfo(make_range(0x7fc090021000, 0x7fc094000000),
116                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eNo,
117                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
118                                  ConstString(nullptr),
119                                  MemoryRegionInfo::eDontKnow, 0,
120                                  MemoryRegionInfo::eDontKnow),
121                 MemoryRegionInfo(
122                     make_range(0xffffffffff600000, 0xffffffffff601000),
123                     MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
124                     MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
125                     ConstString("[vsyscall]"), MemoryRegionInfo::eDontKnow, 0,
126                     MemoryRegionInfo::eDontKnow),
127             },
128             "")), );
129 
130 class LinuxProcSMapsTestFixture : public LinuxProcMapsTestFixture {};
131 
132 INSTANTIATE_TEST_CASE_P(
133     ProcSMapTests, LinuxProcSMapsTestFixture,
134     ::testing::Values(
135         // Nothing in nothing out
136         std::make_tuple("", MemoryRegionInfos{}, ""),
137         // Uses the same parsing for first line, so same errors but referring to
138         // smaps
139         std::make_tuple("0/0 rw-p 00000000 00:00 0", MemoryRegionInfos{},
140                         "malformed /proc/{pid}/smaps entry, missing dash "
141                         "between address range"),
142         // Stop parsing at first error
143         std::make_tuple(
144             "1111-2222 rw-p 00000000 00:00 0 [foo]\n"
145             "0/0 rw-p 00000000 00:00 0",
146             MemoryRegionInfos{
147                 MemoryRegionInfo(make_range(0x1111, 0x2222),
148                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
149                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
150                                  ConstString("[foo]"),
151                                  MemoryRegionInfo::eDontKnow, 0,
152                                  MemoryRegionInfo::eDontKnow),
153             },
154             "malformed /proc/{pid}/smaps entry, missing dash between address "
155             "range"),
156         // Property line without a region is an error
157         std::make_tuple("Referenced:         2188 kB\n"
158                         "1111-2222 rw-p 00000000 00:00 0    [foo]\n"
159                         "3333-4444 rw-p 00000000 00:00 0    [bar]\n",
160                         MemoryRegionInfos{},
161                         "Found a property line without a corresponding mapping "
162                         "in /proc/{pid}/smaps"),
163         // Single region parses, has no flags
164         std::make_tuple(
165             "1111-2222 rw-p 00000000 00:00 0    [foo]",
166             MemoryRegionInfos{
167                 MemoryRegionInfo(make_range(0x1111, 0x2222),
168                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
169                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
170                                  ConstString("[foo]"),
171                                  MemoryRegionInfo::eDontKnow, 0,
172                                  MemoryRegionInfo::eDontKnow),
173             },
174             ""),
175         // Single region with flags, other lines ignored
176         std::make_tuple(
177             "1111-2222 rw-p 00000000 00:00 0    [foo]\n"
178             "Referenced:         2188 kB\n"
179             "AnonHugePages:         0 kB\n"
180             "VmFlags: mt",
181             MemoryRegionInfos{
182                 MemoryRegionInfo(
183                     make_range(0x1111, 0x2222), MemoryRegionInfo::eYes,
184                     MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
185                     MemoryRegionInfo::eYes, ConstString("[foo]"),
186                     MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eYes),
187             },
188             ""),
189         // Whitespace ignored
190         std::make_tuple(
191             "0-0 rw-p 00000000 00:00 0\n"
192             "VmFlags:      mt      ",
193             MemoryRegionInfos{
194                 MemoryRegionInfo(make_range(0, 0), MemoryRegionInfo::eYes,
195                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
196                                  MemoryRegionInfo::eYes, ConstString(nullptr),
197                                  MemoryRegionInfo::eDontKnow, 0,
198                                  MemoryRegionInfo::eYes),
199             },
200             ""),
201         // VmFlags line means it has flag info, but nothing is set
202         std::make_tuple(
203             "0-0 rw-p 00000000 00:00 0\n"
204             "VmFlags:         ",
205             MemoryRegionInfos{
206                 MemoryRegionInfo(make_range(0, 0), MemoryRegionInfo::eYes,
207                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
208                                  MemoryRegionInfo::eYes, ConstString(nullptr),
209                                  MemoryRegionInfo::eDontKnow, 0,
210                                  MemoryRegionInfo::eNo),
211             },
212             ""),
213         // Handle some pages not having a flags line
214         std::make_tuple(
215             "1111-2222 rw-p 00000000 00:00 0    [foo]\n"
216             "Referenced:         2188 kB\n"
217             "AnonHugePages:         0 kB\n"
218             "3333-4444 r-xp 00000000 00:00 0    [bar]\n"
219             "VmFlags: mt",
220             MemoryRegionInfos{
221                 MemoryRegionInfo(make_range(0x1111, 0x2222),
222                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
223                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
224                                  ConstString("[foo]"),
225                                  MemoryRegionInfo::eDontKnow, 0,
226                                  MemoryRegionInfo::eDontKnow),
227                 MemoryRegionInfo(
228                     make_range(0x3333, 0x4444), MemoryRegionInfo::eYes,
229                     MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
230                     MemoryRegionInfo::eYes, ConstString("[bar]"),
231                     MemoryRegionInfo::eDontKnow, 0, MemoryRegionInfo::eYes),
232             },
233             ""),
234         // Handle no pages having a flags line (older kernels)
235         std::make_tuple(
236             "1111-2222 rw-p 00000000 00:00 0\n"
237             "Referenced:         2188 kB\n"
238             "AnonHugePages:         0 kB\n"
239             "3333-4444 r-xp 00000000 00:00 0\n"
240             "KernelPageSize:        4 kB\n"
241             "MMUPageSize:           4 kB\n",
242             MemoryRegionInfos{
243                 MemoryRegionInfo(make_range(0x1111, 0x2222),
244                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
245                                  MemoryRegionInfo::eNo, MemoryRegionInfo::eYes,
246                                  ConstString(nullptr),
247                                  MemoryRegionInfo::eDontKnow, 0,
248                                  MemoryRegionInfo::eDontKnow),
249                 MemoryRegionInfo(make_range(0x3333, 0x4444),
250                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eNo,
251                                  MemoryRegionInfo::eYes, MemoryRegionInfo::eYes,
252                                  ConstString(nullptr),
253                                  MemoryRegionInfo::eDontKnow, 0,
254                                  MemoryRegionInfo::eDontKnow),
255             },
256             "")), );
257 
TEST_P(LinuxProcSMapsTestFixture,ParseSMapRegions)258 TEST_P(LinuxProcSMapsTestFixture, ParseSMapRegions) {
259   auto params = GetParam();
260   ParseLinuxSMapRegions(std::get<0>(params), callback);
261   check_regions(params);
262 }
263