1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "maps_info.h"
17
18 #include <algorithm>
19 #include <cstring>
20 #include <sstream>
21
22 #include "hhlog.h"
23 #include "utilities.h"
24
25 namespace OHOS {
26 namespace Developtools {
27 namespace Hiebpf {
GetMaps(uint32_t pid,std::vector<MapsItem> & mapsItems)28 void MapsInfo::GetMaps(uint32_t pid, std::vector<MapsItem> &mapsItems)
29 {
30 mapsItems.clear();
31 std::string mapPath = "/proc/" + std::to_string(pid) + "/maps";
32 std::string mapContent = ReadFileToString(mapPath);
33 if (mapContent.empty()) {
34 HHLOGE(true, "%s no content", mapPath.c_str());
35 return;
36 }
37
38 std::istringstream s(mapContent);
39 std::string line;
40 while (std::getline(s, line)) {
41 HHLOGD(true, "mmap line: %s", line.c_str());
42 ParseMapsLine(pid, line, mapsItems);
43 }
44
45 return;
46 }
47
GetBinary(const MapsItem & map,std::vector<uint8_t> & buf)48 uint32_t MapsInfo::GetBinary(const MapsItem &map, std::vector<uint8_t> &buf)
49 {
50 uint32_t fixLen = sizeof(map.start_) + sizeof(map.end_) + sizeof(map.offset_) + sizeof(map.pid_);
51 uint32_t len = fixLen + sizeof(uint32_t) + map.fileName_.size() + 1;
52 buf.resize(len);
53
54 const uint8_t *rp = reinterpret_cast<const uint8_t *>(&map);
55 uint8_t *wp = buf.data();
56 std::copy(rp, rp + fixLen, wp); // start + end + offset
57 wp += fixLen;
58 *(reinterpret_cast<uint32_t *>(wp)) = map.fileName_.size() + 1; // fileNameLen
59 wp += sizeof(uint32_t);
60 std::copy(map.fileName_.c_str(), map.fileName_.c_str() + map.fileName_.size() + 1, wp); // fileName
61
62 return buf.size();
63 }
64
65 constexpr const int MMAP_LINE_TOKEN_INDEX_ADDR = 0;
66 constexpr const int MMAP_LINE_TOKEN_INDEX_FLAG = 1;
67 constexpr const int MMAP_LINE_TOKEN_INDEX_OFFSET = 2;
68 constexpr const int MMAP_LINE_TOKEN_INDEX_DEV = 3;
69 constexpr const int MMAP_LINE_TOKEN_INDEX_INODE = 4;
70 constexpr const int MMAP_LINE_TOKEN_INDEX_NAME = 5;
71 constexpr const int MMAP_LINE_TOKEN_NUMBER = 6;
ParseMapsLine(uint32_t pid,std::string & line,std::vector<MapsItem> & maps)72 void MapsInfo::ParseMapsLine(uint32_t pid, std::string &line, std::vector<MapsItem> &maps)
73 {
74 // b0023000-b0024000 r-xp 00000000 b3:05 959 /system/lib/libdl.so
75 // 0 1 2 3 4 5
76 std::vector<std::string> mapTokens = StringSplit(line, " ");
77 if (mapTokens.size() < MMAP_LINE_TOKEN_NUMBER) {
78 // maybe file name is empty
79 return;
80 }
81 // check device
82 std::vector<std::string> dev = StringSplit(mapTokens[MMAP_LINE_TOKEN_INDEX_DEV], ":");
83 if (0 == std::stoi(dev[0], nullptr, NUMBER_FORMAT_HEX_BASE)) {
84 return;
85 }
86
87 // check file name
88 if (!IsLegalFileName(mapTokens[MMAP_LINE_TOKEN_INDEX_NAME])) {
89 return;
90 }
91
92 MapsItem &mapItem = maps.emplace_back();
93
94 std::vector<std::string> addr = StringSplit(mapTokens[MMAP_LINE_TOKEN_INDEX_ADDR], "-");
95 mapItem.start_ = std::stoull(addr[0], nullptr, NUMBER_FORMAT_HEX_BASE);
96 mapItem.end_ = std::stoull(addr[1], nullptr, NUMBER_FORMAT_HEX_BASE);
97 mapItem.offset_ = std::stoull(mapTokens[MMAP_LINE_TOKEN_INDEX_OFFSET],
98 nullptr, NUMBER_FORMAT_HEX_BASE);;
99 mapItem.pid_ = pid;
100 mapItem.fileName_ = mapTokens[MMAP_LINE_TOKEN_INDEX_NAME];
101 }
102
IsLegalFileName(const std::string & fileName)103 bool MapsInfo::IsLegalFileName(const std::string &fileName)
104 {
105 if (fileName.find(':') != std::string::npos or
106 fileName.front() == '[' or fileName.back() == ']' or
107 std::strncmp(fileName.c_str(), "/dev/", sizeof("/dev/")) == 0 or
108 std::strncmp(fileName.c_str(), "/memfd:", sizeof("/memfd:")) == 0 or
109 std::strncmp(fileName.c_str(), "//anon", sizeof("//anon")) == 0 or
110 StringEndsWith(fileName, ".ttf")) {
111 return false;
112 }
113 return true;
114 }
115 } // namespace Hiebpf
116 } // namespace Developtools
117 } // namespace OHOS