• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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