106f6ba60Sopenharmony_ci 206f6ba60Sopenharmony_ci/* 306f6ba60Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 406f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 506f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 606f6ba60Sopenharmony_ci * You may obtain a copy of the License at 706f6ba60Sopenharmony_ci * 806f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 906f6ba60Sopenharmony_ci * 1006f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1106f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1206f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1306f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1406f6ba60Sopenharmony_ci * limitations under the License. 1506f6ba60Sopenharmony_ci */ 1606f6ba60Sopenharmony_ci 1706f6ba60Sopenharmony_ci#include <iostream> 1806f6ba60Sopenharmony_ci#include <fstream> 1906f6ba60Sopenharmony_ci#include <sstream> 2006f6ba60Sopenharmony_ci#include <unistd.h> 2106f6ba60Sopenharmony_ci#include <fcntl.h> 2206f6ba60Sopenharmony_ci#include <vector> 2306f6ba60Sopenharmony_ci 2406f6ba60Sopenharmony_ciusing namespace std; 2506f6ba60Sopenharmony_ci 2606f6ba60Sopenharmony_ciconstexpr uint64_t PFN_MASK = ((1ULL << 55) - 1); 2706f6ba60Sopenharmony_ciconstexpr uint64_t PAGE_SIZE = 1024 * 4; 2806f6ba60Sopenharmony_ciconstexpr int ARG_MINIMUM = 2; 2906f6ba60Sopenharmony_ciconstexpr int IN_RAM_OFFSET = 63; 3006f6ba60Sopenharmony_ciconstexpr int IN_SWAP_OFFSET = 54; 3106f6ba60Sopenharmony_ciconstexpr int SHARED_OFFSET = 53; 3206f6ba60Sopenharmony_ciconstexpr int EXCLUSIVE_OFFSET = 52; 3306f6ba60Sopenharmony_ciconstexpr int SOFTDIRTY_OFFSET = 51; 3406f6ba60Sopenharmony_cistruct MapInfo { 3506f6ba60Sopenharmony_ci uint64_t startAddr; // 起始地址 3606f6ba60Sopenharmony_ci uint64_t endAddr; // 结束地址 3706f6ba60Sopenharmony_ci char read; 3806f6ba60Sopenharmony_ci char write; 3906f6ba60Sopenharmony_ci char execute; 4006f6ba60Sopenharmony_ci char shared; 4106f6ba60Sopenharmony_ci uint64_t offset; // 文件偏移量 4206f6ba60Sopenharmony_ci string dev; // 设备号 4306f6ba60Sopenharmony_ci string inode; // inode 号 4406f6ba60Sopenharmony_ci std::string pathname; // 文件路径 4506f6ba60Sopenharmony_ci}; 4606f6ba60Sopenharmony_ci 4706f6ba60Sopenharmony_cistruct PageInfo { 4806f6ba60Sopenharmony_ci unsigned int inRam; 4906f6ba60Sopenharmony_ci unsigned int inSwap; 5006f6ba60Sopenharmony_ci unsigned int shared; 5106f6ba60Sopenharmony_ci unsigned int exclusive; 5206f6ba60Sopenharmony_ci unsigned int softdirty; 5306f6ba60Sopenharmony_ci unsigned long pfn; 5406f6ba60Sopenharmony_ci uint64_t address; 5506f6ba60Sopenharmony_ci}; 5606f6ba60Sopenharmony_ci 5706f6ba60Sopenharmony_cinamespace { 5806f6ba60Sopenharmony_civoid PrintUsage(const string& program) 5906f6ba60Sopenharmony_ci{ 6006f6ba60Sopenharmony_ci cout << "Usage: " << program << " pid" <<endl; 6106f6ba60Sopenharmony_ci} 6206f6ba60Sopenharmony_ci 6306f6ba60Sopenharmony_ciint ParseMapsLine(const string& line, MapInfo& mapping) 6406f6ba60Sopenharmony_ci{ 6506f6ba60Sopenharmony_ci std::istringstream iss(line); 6606f6ba60Sopenharmony_ci std::string token; 6706f6ba60Sopenharmony_ci uint64_t start, end; 6806f6ba60Sopenharmony_ci 6906f6ba60Sopenharmony_ci // 读取起始地址和结束地址 7006f6ba60Sopenharmony_ci if (!(iss >> hex >> start)) { 7106f6ba60Sopenharmony_ci return -1; 7206f6ba60Sopenharmony_ci } 7306f6ba60Sopenharmony_ci iss.ignore(1); // 忽略 '-' 7406f6ba60Sopenharmony_ci if (!(iss >> hex >> end)) { 7506f6ba60Sopenharmony_ci return -1; 7606f6ba60Sopenharmony_ci } 7706f6ba60Sopenharmony_ci mapping.startAddr = start; 7806f6ba60Sopenharmony_ci mapping.endAddr = end; 7906f6ba60Sopenharmony_ci 8006f6ba60Sopenharmony_ci // 读取权限并转换为整数 8106f6ba60Sopenharmony_ci iss >> mapping.read; 8206f6ba60Sopenharmony_ci iss >> mapping.write; 8306f6ba60Sopenharmony_ci iss >> mapping.execute; 8406f6ba60Sopenharmony_ci iss >> mapping.shared; 8506f6ba60Sopenharmony_ci // 读取偏移量 8606f6ba60Sopenharmony_ci if (!(iss >> mapping.offset)) { 8706f6ba60Sopenharmony_ci return -1; 8806f6ba60Sopenharmony_ci } 8906f6ba60Sopenharmony_ci // 读取设备号 9006f6ba60Sopenharmony_ci if (!(iss >> mapping.dev)) { 9106f6ba60Sopenharmony_ci return -1; 9206f6ba60Sopenharmony_ci } 9306f6ba60Sopenharmony_ci // 读取 inode 号 9406f6ba60Sopenharmony_ci if (!(iss >> mapping.inode)) { 9506f6ba60Sopenharmony_ci return -1; 9606f6ba60Sopenharmony_ci } 9706f6ba60Sopenharmony_ci // 读取文件路径 9806f6ba60Sopenharmony_ci if (!getline(iss, mapping.pathname)) { 9906f6ba60Sopenharmony_ci mapping.pathname = "[anno]"; 10006f6ba60Sopenharmony_ci }; 10106f6ba60Sopenharmony_ci return 0; 10206f6ba60Sopenharmony_ci} 10306f6ba60Sopenharmony_ci 10406f6ba60Sopenharmony_civoid ParsePagemap(uint64_t entry, PageInfo & pginfo) 10506f6ba60Sopenharmony_ci{ 10606f6ba60Sopenharmony_ci pginfo.inRam = (entry >> IN_RAM_OFFSET) & 0x1; 10706f6ba60Sopenharmony_ci pginfo.inSwap = (entry >> IN_SWAP_OFFSET) & 0x1; 10806f6ba60Sopenharmony_ci pginfo.shared = (entry >> SHARED_OFFSET) & 0x1; 10906f6ba60Sopenharmony_ci pginfo.exclusive = (entry >> EXCLUSIVE_OFFSET) & 0x1; 11006f6ba60Sopenharmony_ci pginfo.softdirty = (entry >> SOFTDIRTY_OFFSET) & 0x1; 11106f6ba60Sopenharmony_ci pginfo.pfn = entry & PFN_MASK; 11206f6ba60Sopenharmony_ci} 11306f6ba60Sopenharmony_ci 11406f6ba60Sopenharmony_civoid PrintPage(const MapInfo& mapping, const PageInfo& page) 11506f6ba60Sopenharmony_ci{ 11606f6ba60Sopenharmony_ci cout << hex << page.address << '-' << hex << (page.address + PAGE_SIZE) << " "; 11706f6ba60Sopenharmony_ci cout << mapping.read << mapping.write << mapping.execute << mapping.shared << " "; 11806f6ba60Sopenharmony_ci if (page.inRam) { 11906f6ba60Sopenharmony_ci cout << hex << page.pfn; 12006f6ba60Sopenharmony_ci } else if (page.inSwap) { 12106f6ba60Sopenharmony_ci cout << "[in swap]"; 12206f6ba60Sopenharmony_ci } else { 12306f6ba60Sopenharmony_ci cout << "[not present]"; 12406f6ba60Sopenharmony_ci } 12506f6ba60Sopenharmony_ci cout<< " " << mapping.pathname << endl; 12606f6ba60Sopenharmony_ci} 12706f6ba60Sopenharmony_ci 12806f6ba60Sopenharmony_cibool IsValidPid(const string& pid_str) 12906f6ba60Sopenharmony_ci{ 13006f6ba60Sopenharmony_ci if (pid_str.empty()) { 13106f6ba60Sopenharmony_ci return -1; 13206f6ba60Sopenharmony_ci } 13306f6ba60Sopenharmony_ci bool ret = all_of(pid_str.begin(), pid_str.end(), [](char c) { 13406f6ba60Sopenharmony_ci return isdigit(c); 13506f6ba60Sopenharmony_ci }); 13606f6ba60Sopenharmony_ci return ret; 13706f6ba60Sopenharmony_ci} 13806f6ba60Sopenharmony_ci} // namespace 13906f6ba60Sopenharmony_ci 14006f6ba60Sopenharmony_ciint main(int argc, char* argv[]) 14106f6ba60Sopenharmony_ci{ 14206f6ba60Sopenharmony_ci if (argc != ARG_MINIMUM) { 14306f6ba60Sopenharmony_ci PrintUsage(argv[0]); 14406f6ba60Sopenharmony_ci return -1; 14506f6ba60Sopenharmony_ci } 14606f6ba60Sopenharmony_ci string pid_str = argv[1]; 14706f6ba60Sopenharmony_ci if (!IsValidPid(pid_str)) { 14806f6ba60Sopenharmony_ci PrintUsage(argv[0]); 14906f6ba60Sopenharmony_ci return -1; 15006f6ba60Sopenharmony_ci } 15106f6ba60Sopenharmony_ci int pid = stoi(argv[1]); 15206f6ba60Sopenharmony_ci string mapsPath = "/proc/" + to_string(pid) + "/maps"; 15306f6ba60Sopenharmony_ci ifstream maps_file(mapsPath, ios::binary); 15406f6ba60Sopenharmony_ci if (!maps_file) { 15506f6ba60Sopenharmony_ci cerr << "Failed to open maps file" << endl; 15606f6ba60Sopenharmony_ci return -1; 15706f6ba60Sopenharmony_ci } 15806f6ba60Sopenharmony_ci 15906f6ba60Sopenharmony_ci string pagemapPath = "/proc/" + to_string(pid) + "/pagemap"; 16006f6ba60Sopenharmony_ci int pagemapFd = open(pagemapPath.c_str(), O_RDONLY); 16106f6ba60Sopenharmony_ci if (pagemapFd == -1) { 16206f6ba60Sopenharmony_ci perror("Error opening file"); 16306f6ba60Sopenharmony_ci return -1; 16406f6ba60Sopenharmony_ci } 16506f6ba60Sopenharmony_ci cout << "Address Range\t" << "Permissions\t" << "PFN\t" << "Path" << endl; 16606f6ba60Sopenharmony_ci string line; 16706f6ba60Sopenharmony_ci while (getline(maps_file, line)) { 16806f6ba60Sopenharmony_ci MapInfo mapping; 16906f6ba60Sopenharmony_ci bool ret = ParseMapsLine(line, mapping); 17006f6ba60Sopenharmony_ci if (ret != 0) { 17106f6ba60Sopenharmony_ci close(pagemapFd); 17206f6ba60Sopenharmony_ci return ret; 17306f6ba60Sopenharmony_ci } 17406f6ba60Sopenharmony_ci for (uint64_t tmpAddr = mapping.startAddr; tmpAddr < mapping.endAddr; tmpAddr += PAGE_SIZE) { 17506f6ba60Sopenharmony_ci // 计算文件中要读取的偏移量 17606f6ba60Sopenharmony_ci uint64_t offset = (tmpAddr / PAGE_SIZE) * sizeof(unsigned long long); 17706f6ba60Sopenharmony_ci uint64_t entry; 17806f6ba60Sopenharmony_ci if (pread(pagemapFd, &entry, sizeof(entry), offset) != sizeof(entry)) { 17906f6ba60Sopenharmony_ci perror("pread"); 18006f6ba60Sopenharmony_ci break; 18106f6ba60Sopenharmony_ci } 18206f6ba60Sopenharmony_ci PageInfo page; 18306f6ba60Sopenharmony_ci ParsePagemap(entry, page); 18406f6ba60Sopenharmony_ci page.address = tmpAddr; 18506f6ba60Sopenharmony_ci PrintPage(mapping, page); 18606f6ba60Sopenharmony_ci } 18706f6ba60Sopenharmony_ci } 18806f6ba60Sopenharmony_ci maps_file.close(); 18906f6ba60Sopenharmony_ci close(pagemapFd); 19006f6ba60Sopenharmony_ci return 0; 19106f6ba60Sopenharmony_ci}