1323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui/* 2323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * Copyright (C) 2015 The Android Open Source Project 3323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * 4323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * Licensed under the Apache License, Version 2.0 (the "License"); 5323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * you may not use this file except in compliance with the License. 6323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * You may obtain a copy of the License at 7323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * 8323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * http://www.apache.org/licenses/LICENSE-2.0 9323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * 10323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * Unless required by applicable law or agreed to in writing, software 11323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * distributed under the License is distributed on an "AS IS" BASIS, 12323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * See the License for the specific language governing permissions and 14323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui * limitations under the License. 15323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui */ 16323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 17323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui#include "environment.h" 18323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 197d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui#include <inttypes.h> 207d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui#include <stdio.h> 21323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui#include <stdlib.h> 22c84856093e8bf4350d30fc521dc0f1c800c5270bYabin Cui 23c84856093e8bf4350d30fc521dc0f1c800c5270bYabin Cui#include <limits> 24cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui#include <set> 257d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui#include <unordered_map> 26323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui#include <vector> 27323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 2866dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/file.h> 2966dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/logging.h> 300bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui#include <android-base/parseint.h> 3166dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/strings.h> 3266dd09e8e2407082ce93bf0784de641298131912Elliott Hughes#include <android-base/stringprintf.h> 33323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 3492c688b1f744dbded59f2df547f31db1638e316bYabin Cui#if defined(__ANDROID__) 3592c688b1f744dbded59f2df547f31db1638e316bYabin Cui#include <sys/system_properties.h> 3692c688b1f744dbded59f2df547f31db1638e316bYabin Cui#endif 3792c688b1f744dbded59f2df547f31db1638e316bYabin Cui 388f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui#include "read_elf.h" 39323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui#include "utils.h" 40323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 41ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cuiclass LineReader { 42ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui public: 43ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui LineReader(FILE* fp) : fp_(fp), buf_(nullptr), bufsize_(0) { 44ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui } 45ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui 46ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui ~LineReader() { 47ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui free(buf_); 48ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui fclose(fp_); 49ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui } 50ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui 51ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui char* ReadLine() { 52ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui if (getline(&buf_, &bufsize_, fp_) != -1) { 53ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui return buf_; 54ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui } 55ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui return nullptr; 56ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui } 57ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui 58ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui size_t MaxLineSize() { 59ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui return bufsize_; 60ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui } 61ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui 62ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui private: 63ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui FILE* fp_; 64ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui char* buf_; 65ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui size_t bufsize_; 66ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui}; 67ffaa912ca48e87d25d516780c15cdd7c50de43dbYabin Cui 68323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cuistd::vector<int> GetOnlineCpus() { 69323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui std::vector<int> result; 70323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui FILE* fp = fopen("/sys/devices/system/cpu/online", "re"); 71323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui if (fp == nullptr) { 72323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui PLOG(ERROR) << "can't open online cpu information"; 73323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui return result; 74323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 75323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 76323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui LineReader reader(fp); 77323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui char* line; 78323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui if ((line = reader.ReadLine()) != nullptr) { 79cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui result = GetCpusFromString(line); 80323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 81323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui CHECK(!result.empty()) << "can't get online cpu information"; 82323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui return result; 83323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui} 84323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui 85cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cuistd::vector<int> GetCpusFromString(const std::string& s) { 86cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui std::set<int> cpu_set; 87323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui bool have_dash = false; 88323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui const char* p = s.c_str(); 89323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui char* endp; 90cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui int last_cpu; 91323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui long cpu; 92323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui // Parse line like: 0,1-3, 5, 7-8 93323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui while ((cpu = strtol(p, &endp, 10)) != 0 || endp != p) { 94cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui if (have_dash && !cpu_set.empty()) { 95cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui for (int t = last_cpu + 1; t < cpu; ++t) { 96cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui cpu_set.insert(t); 97323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 98323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 99323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui have_dash = false; 100cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui cpu_set.insert(cpu); 101cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui last_cpu = cpu; 102323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui p = endp; 103323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui while (!isdigit(*p) && *p != '\0') { 104323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui if (*p == '-') { 105323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui have_dash = true; 106323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 107323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui ++p; 108323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 109323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui } 110cb4c17ea53269ced994a2d849cbafb1afd5296e1Yabin Cui return std::vector<int>(cpu_set.begin(), cpu_set.end()); 111323e945313b190373b3fcfe578e25ee8390a76d3Yabin Cui} 1127d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 1137d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cuibool ProcessKernelSymbols(const std::string& symbol_file, 1147d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::function<bool(const KernelSymbol&)> callback) { 1157d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui FILE* fp = fopen(symbol_file.c_str(), "re"); 1167d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (fp == nullptr) { 1177d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui PLOG(ERROR) << "failed to open file " << symbol_file; 1187d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return false; 1197d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1207d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui LineReader reader(fp); 1217d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char* line; 1227d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui while ((line = reader.ReadLine()) != nullptr) { 1237d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui // Parse line like: ffffffffa005c4e4 d __warned.41698 [libsas] 1247d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char name[reader.MaxLineSize()]; 1257d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char module[reader.MaxLineSize()]; 1267d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui strcpy(module, ""); 1277d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 1287d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui KernelSymbol symbol; 1297d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (sscanf(line, "%" PRIx64 " %c %s%s", &symbol.addr, &symbol.type, name, module) < 3) { 1307d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui continue; 1317d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1327d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui symbol.name = name; 1337d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui size_t module_len = strlen(module); 1347d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (module_len > 2 && module[0] == '[' && module[module_len - 1] == ']') { 1357d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui module[module_len - 1] = '\0'; 1367d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui symbol.module = &module[1]; 1377d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } else { 1387d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui symbol.module = nullptr; 1397d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1407d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 1417d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (callback(symbol)) { 1427d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return true; 1437d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1447d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1457d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return false; 1467d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 1477d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 1489fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cuistatic std::vector<KernelMmap> GetLoadedModules() { 1499fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui std::vector<KernelMmap> result; 1507d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui FILE* fp = fopen("/proc/modules", "re"); 1517d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (fp == nullptr) { 1527d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui // There is no /proc/modules on Android devices, so we don't print error if failed to open it. 1537d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui PLOG(DEBUG) << "failed to open file /proc/modules"; 1547d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return result; 1557d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1567d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui LineReader reader(fp); 1577d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char* line; 1587d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui while ((line = reader.ReadLine()) != nullptr) { 1597d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui // Parse line like: nf_defrag_ipv6 34768 1 nf_conntrack_ipv6, Live 0xffffffffa0fe5000 1607d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char name[reader.MaxLineSize()]; 1617d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui uint64_t addr; 1627d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (sscanf(line, "%s%*lu%*u%*s%*s 0x%" PRIx64, name, &addr) == 2) { 1639fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui KernelMmap map; 1647d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui map.name = name; 1657d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui map.start_addr = addr; 1667d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui result.push_back(map); 1677d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1687d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1697d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return result; 1707d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 1717d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 1727d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cuistatic std::string GetLinuxVersion() { 1737d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string content; 1747d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (android::base::ReadFileToString("/proc/version", &content)) { 1757d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char s[content.size() + 1]; 1767d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (sscanf(content.c_str(), "Linux version %s", s) == 1) { 1777d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return s; 1787d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1797d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1807d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui PLOG(FATAL) << "can't read linux version"; 1817d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return ""; 1827d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 1837d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 1847d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cuistatic void GetAllModuleFiles(const std::string& path, 1857d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::unordered_map<std::string, std::string>* module_file_map) { 1867d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::vector<std::string> files; 1877d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::vector<std::string> subdirs; 1887d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui GetEntriesInDir(path, &files, &subdirs); 1897d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui for (auto& name : files) { 1907d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (android::base::EndsWith(name, ".ko")) { 1917d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string module_name = name.substr(0, name.size() - 3); 1927d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::replace(module_name.begin(), module_name.end(), '-', '_'); 193ec12ed9010128483993a87d68edc02d3a89d56cfYabin Cui module_file_map->insert(std::make_pair(module_name, path + "/" + name)); 1947d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1957d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1967d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui for (auto& name : subdirs) { 1977d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui GetAllModuleFiles(path + "/" + name, module_file_map); 1987d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 1997d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 2007d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 2019fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cuistatic std::vector<KernelMmap> GetModulesInUse() { 2027d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui // TODO: There is no /proc/modules or /lib/modules on Android, find methods work on it. 2039fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui std::vector<KernelMmap> module_mmaps = GetLoadedModules(); 2047d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string linux_version = GetLinuxVersion(); 2057d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string module_dirpath = "/lib/modules/" + linux_version + "/kernel"; 2067d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::unordered_map<std::string, std::string> module_file_map; 2077d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui GetAllModuleFiles(module_dirpath, &module_file_map); 2087d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui for (auto& module : module_mmaps) { 2097d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui auto it = module_file_map.find(module.name); 2107d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (it != module_file_map.end()) { 2117d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui module.filepath = it->second; 2127d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2137d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2147d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return module_mmaps; 2157d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 2167d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 2179fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cuivoid GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<KernelMmap>* module_mmaps) { 2187d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME; 2199fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui kernel_mmap->start_addr = 0; 2209fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui kernel_mmap->filepath = kernel_mmap->name; 2217d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui *module_mmaps = GetModulesInUse(); 2229fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui for (auto& map : *module_mmaps) { 2239fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui if (map.filepath.empty()) { 2249fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui map.filepath = "[" + map.name + "]"; 2259fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui } 2269fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui } 2279fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui 2287d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (module_mmaps->size() == 0) { 229c84856093e8bf4350d30fc521dc0f1c800c5270bYabin Cui kernel_mmap->len = std::numeric_limits<unsigned long long>::max() - kernel_mmap->start_addr; 2307d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } else { 2317d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::sort( 2327d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui module_mmaps->begin(), module_mmaps->end(), 2339fbb28cc4a05cbc9d571664cc31896899011bcdeYabin Cui [](const KernelMmap& m1, const KernelMmap& m2) { return m1.start_addr < m2.start_addr; }); 2347d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui // When not having enough privilege, all addresses are read as 0. 2357d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (kernel_mmap->start_addr == (*module_mmaps)[0].start_addr) { 2367d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui kernel_mmap->len = 0; 2377d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } else { 2387d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui kernel_mmap->len = (*module_mmaps)[0].start_addr - kernel_mmap->start_addr - 1; 2397d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2407d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui for (size_t i = 0; i + 1 < module_mmaps->size(); ++i) { 2417d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if ((*module_mmaps)[i].start_addr == (*module_mmaps)[i + 1].start_addr) { 2427d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui (*module_mmaps)[i].len = 0; 2437d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } else { 2447d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui (*module_mmaps)[i].len = 2457d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui (*module_mmaps)[i + 1].start_addr - (*module_mmaps)[i].start_addr - 1; 2467d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2477d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 248c84856093e8bf4350d30fc521dc0f1c800c5270bYabin Cui module_mmaps->back().len = 249c84856093e8bf4350d30fc521dc0f1c800c5270bYabin Cui std::numeric_limits<unsigned long long>::max() - module_mmaps->back().start_addr; 2507d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2517d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 2527d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 2537d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cuistatic bool ReadThreadNameAndTgid(const std::string& status_file, std::string* comm, pid_t* tgid) { 2547d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui FILE* fp = fopen(status_file.c_str(), "re"); 2557d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (fp == nullptr) { 2567d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return false; 2577d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2587d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui bool read_comm = false; 2597d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui bool read_tgid = false; 2607d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui LineReader reader(fp); 2617d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char* line; 2627d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui while ((line = reader.ReadLine()) != nullptr) { 2637d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char s[reader.MaxLineSize()]; 2647d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (sscanf(line, "Name:%s", s) == 1) { 2657d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui *comm = s; 2667d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui read_comm = true; 2677d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } else if (sscanf(line, "Tgid:%d", tgid) == 1) { 2687d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui read_tgid = true; 2697d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2707d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (read_comm && read_tgid) { 2717d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return true; 2727d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2737d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 2747d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return false; 2757d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 2767d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 277b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cuistatic std::vector<pid_t> GetThreadsInProcess(pid_t pid) { 278b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui std::vector<pid_t> result; 2797d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string task_dirname = android::base::StringPrintf("/proc/%d/task", pid); 2807d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::vector<std::string> subdirs; 2817d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui GetEntriesInDir(task_dirname, nullptr, &subdirs); 2820bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui for (const auto& name : subdirs) { 28338e573ee1958959253ba8f3af7567adb4cbeea55Yabin Cui int tid; 2840bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui if (!android::base::ParseInt(name.c_str(), &tid, 0)) { 2857d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui continue; 2867d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 287b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui result.push_back(tid); 288b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 289b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return result; 290b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui} 291b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui 292b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cuistatic bool GetThreadComm(pid_t pid, std::vector<ThreadComm>* thread_comms) { 293b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui std::vector<pid_t> tids = GetThreadsInProcess(pid); 294b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui for (auto& tid : tids) { 295b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui std::string status_file = android::base::StringPrintf("/proc/%d/task/%d/status", pid, tid); 2967d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string comm; 2977d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui pid_t tgid; 298b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui // It is possible that the process or thread exited before we can read its status. 2997d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (!ReadThreadNameAndTgid(status_file, &comm, &tgid)) { 300b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui continue; 3017d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 30241d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui CHECK_EQ(pid, tgid); 3037d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui ThreadComm thread; 3047d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.tid = tid; 30541d4ba9f6f2781155a0519a784606d5382cda88fYabin Cui thread.pid = pid; 3067d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.comm = comm; 3077d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread_comms->push_back(thread); 3087d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3097d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return true; 3107d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 3117d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 3127d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cuibool GetThreadComms(std::vector<ThreadComm>* thread_comms) { 3137d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread_comms->clear(); 3147d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::vector<std::string> subdirs; 3157d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui GetEntriesInDir("/proc", nullptr, &subdirs); 3167d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui for (auto& name : subdirs) { 31738e573ee1958959253ba8f3af7567adb4cbeea55Yabin Cui int pid; 3180bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui if (!android::base::ParseInt(name.c_str(), &pid, 0)) { 3197d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui continue; 3207d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3217d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (!GetThreadComm(pid, thread_comms)) { 3227d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return false; 3237d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3247d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3257d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return true; 3267d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 3277d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui 3287d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cuibool GetThreadMmapsInProcess(pid_t pid, std::vector<ThreadMmap>* thread_mmaps) { 3297d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui std::string map_file = android::base::StringPrintf("/proc/%d/maps", pid); 3307d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui FILE* fp = fopen(map_file.c_str(), "re"); 3317d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (fp == nullptr) { 3327d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui PLOG(DEBUG) << "can't open file " << map_file; 3337d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return false; 3347d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3357d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread_mmaps->clear(); 3367d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui LineReader reader(fp); 3377d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char* line; 3387d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui while ((line = reader.ReadLine()) != nullptr) { 3397d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui // Parse line like: 00400000-00409000 r-xp 00000000 fc:00 426998 /usr/lib/gvfs/gvfsd-http 3407d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui uint64_t start_addr, end_addr, pgoff; 3417d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char type[reader.MaxLineSize()]; 3427d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui char execname[reader.MaxLineSize()]; 3437d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui strcpy(execname, ""); 3447d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (sscanf(line, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %*x:%*x %*u %s\n", &start_addr, 3457d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui &end_addr, type, &pgoff, execname) < 4) { 3467d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui continue; 3477d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3487d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui if (strcmp(execname, "") == 0) { 3497d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui strcpy(execname, DEFAULT_EXECNAME_FOR_THREAD_MMAP); 3507d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3517d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui ThreadMmap thread; 3527d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.start_addr = start_addr; 3537d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.len = end_addr - start_addr; 3547d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.pgoff = pgoff; 3557d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.name = execname; 3567d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread.executable = (type[2] == 'x'); 3577d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui thread_mmaps->push_back(thread); 3587d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui } 3597d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui return true; 3607d59bb49fb47fbc82ef5c77d7aebf7174fd996e1Yabin Cui} 3618f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 3628f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cuibool GetKernelBuildId(BuildId* build_id) { 3638f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui return GetBuildIdFromNoteFile("/sys/kernel/notes", build_id); 3648f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui} 3658f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui 3668f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cuibool GetModuleBuildId(const std::string& module_name, BuildId* build_id) { 3678f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui std::string notefile = "/sys/module/" + module_name + "/notes/.note.gnu.build-id"; 3688f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui return GetBuildIdFromNoteFile(notefile, build_id); 3698f6225147c5b6cb2159a7f5cb0dab952ee0759dfYabin Cui} 370b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui 371b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cuibool GetValidThreadsFromProcessString(const std::string& pid_str, std::set<pid_t>* tid_set) { 372b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui std::vector<std::string> strs = android::base::Split(pid_str, ","); 3730bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui for (const auto& s : strs) { 37438e573ee1958959253ba8f3af7567adb4cbeea55Yabin Cui int pid; 3750bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui if (!android::base::ParseInt(s.c_str(), &pid, 0)) { 376b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui LOG(ERROR) << "Invalid pid '" << s << "'"; 377b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return false; 378b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 379b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui std::vector<pid_t> tids = GetThreadsInProcess(pid); 380b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui if (tids.empty()) { 381b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui LOG(ERROR) << "Non existing process '" << pid << "'"; 382b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return false; 383b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 384b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui tid_set->insert(tids.begin(), tids.end()); 385b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 386b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return true; 387b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui} 388b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui 389b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cuibool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) { 390b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui std::vector<std::string> strs = android::base::Split(tid_str, ","); 3910bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui for (const auto& s : strs) { 39238e573ee1958959253ba8f3af7567adb4cbeea55Yabin Cui int tid; 3930bd2a5cef3cf787552c55f643631b6ba77637711Yabin Cui if (!android::base::ParseInt(s.c_str(), &tid, 0)) { 394b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui LOG(ERROR) << "Invalid tid '" << s << "'"; 395b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return false; 396b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 397b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui if (!IsDir(android::base::StringPrintf("/proc/%d", tid))) { 398b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui LOG(ERROR) << "Non existing thread '" << tid << "'"; 399b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return false; 400b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 401b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui tid_set->insert(tid); 402b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui } 403b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui return true; 404b032de7a9e1975a838cd6df2e7c8df3c7f70a3ceYabin Cui} 405d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui 406d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cuibool GetExecPath(std::string* exec_path) { 407d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui char path[PATH_MAX]; 408d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui ssize_t path_len = readlink("/proc/self/exe", path, sizeof(path)); 409d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui if (path_len <= 0 || path_len >= static_cast<ssize_t>(sizeof(path))) { 410d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui PLOG(ERROR) << "readlink failed"; 411d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui return false; 412d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui } 413d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui path[path_len] = '\0'; 414d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui *exec_path = path; 415d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui return true; 416d713f959ec1fe07ed993e2c9f4166b52aa98a58cYabin Cui} 41792c688b1f744dbded59f2df547f31db1638e316bYabin Cui 41892c688b1f744dbded59f2df547f31db1638e316bYabin Cui/* 41992c688b1f744dbded59f2df547f31db1638e316bYabin Cui * perf event paranoia level: 42092c688b1f744dbded59f2df547f31db1638e316bYabin Cui * -1 - not paranoid at all 42192c688b1f744dbded59f2df547f31db1638e316bYabin Cui * 0 - disallow raw tracepoint access for unpriv 42292c688b1f744dbded59f2df547f31db1638e316bYabin Cui * 1 - disallow cpu events for unpriv 42392c688b1f744dbded59f2df547f31db1638e316bYabin Cui * 2 - disallow kernel profiling for unpriv 42492c688b1f744dbded59f2df547f31db1638e316bYabin Cui * 3 - disallow user profiling for unpriv 42592c688b1f744dbded59f2df547f31db1638e316bYabin Cui */ 42692c688b1f744dbded59f2df547f31db1638e316bYabin Cuistatic bool ReadPerfEventParanoid(int* value) { 42792c688b1f744dbded59f2df547f31db1638e316bYabin Cui std::string s; 42892c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid", &s)) { 42992c688b1f744dbded59f2df547f31db1638e316bYabin Cui PLOG(ERROR) << "failed to read /proc/sys/kernel/perf_event_paranoid"; 43092c688b1f744dbded59f2df547f31db1638e316bYabin Cui return false; 43192c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 43292c688b1f744dbded59f2df547f31db1638e316bYabin Cui s = android::base::Trim(s); 43392c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (!android::base::ParseInt(s.c_str(), value)) { 43492c688b1f744dbded59f2df547f31db1638e316bYabin Cui PLOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_paranoid: " << s; 43592c688b1f744dbded59f2df547f31db1638e316bYabin Cui return false; 43692c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 43792c688b1f744dbded59f2df547f31db1638e316bYabin Cui return true; 43892c688b1f744dbded59f2df547f31db1638e316bYabin Cui} 43992c688b1f744dbded59f2df547f31db1638e316bYabin Cui 44092c688b1f744dbded59f2df547f31db1638e316bYabin Cuistatic const char* GetLimitLevelDescription(int limit_level) { 44192c688b1f744dbded59f2df547f31db1638e316bYabin Cui switch (limit_level) { 44292c688b1f744dbded59f2df547f31db1638e316bYabin Cui case -1: return "unlimited"; 44392c688b1f744dbded59f2df547f31db1638e316bYabin Cui case 0: return "disallowing raw tracepoint access for unpriv"; 44492c688b1f744dbded59f2df547f31db1638e316bYabin Cui case 1: return "disallowing cpu events for unpriv"; 44592c688b1f744dbded59f2df547f31db1638e316bYabin Cui case 2: return "disallowing kernel profiling for unpriv"; 44692c688b1f744dbded59f2df547f31db1638e316bYabin Cui case 3: return "disallowing user profiling for unpriv"; 44792c688b1f744dbded59f2df547f31db1638e316bYabin Cui default: return "unknown level"; 44892c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 44992c688b1f744dbded59f2df547f31db1638e316bYabin Cui} 45092c688b1f744dbded59f2df547f31db1638e316bYabin Cui 45192c688b1f744dbded59f2df547f31db1638e316bYabin Cuibool CheckPerfEventLimit() { 45292c688b1f744dbded59f2df547f31db1638e316bYabin Cui // root is not limited by /proc/sys/kernel/perf_event_paranoid. 45392c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (IsRoot()) { 45492c688b1f744dbded59f2df547f31db1638e316bYabin Cui return true; 45592c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 45692c688b1f744dbded59f2df547f31db1638e316bYabin Cui int limit_level; 45792c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (!ReadPerfEventParanoid(&limit_level)) { 45892c688b1f744dbded59f2df547f31db1638e316bYabin Cui return false; 45992c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 46092c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (limit_level <= 1) { 46192c688b1f744dbded59f2df547f31db1638e316bYabin Cui return true; 46292c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 46392c688b1f744dbded59f2df547f31db1638e316bYabin Cui#if defined(__ANDROID__) 46492c688b1f744dbded59f2df547f31db1638e316bYabin Cui // Try to enable perf_event_paranoid by setprop security.perf_harden=0. 46592c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (__system_property_set("security.perf_harden", "0") == 0) { 46692c688b1f744dbded59f2df547f31db1638e316bYabin Cui sleep(1); 46792c688b1f744dbded59f2df547f31db1638e316bYabin Cui if (ReadPerfEventParanoid(&limit_level) && limit_level <= 1) { 46892c688b1f744dbded59f2df547f31db1638e316bYabin Cui return true; 46992c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 47092c688b1f744dbded59f2df547f31db1638e316bYabin Cui } 47192c688b1f744dbded59f2df547f31db1638e316bYabin Cui LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level 47292c688b1f744dbded59f2df547f31db1638e316bYabin Cui << ", " << GetLimitLevelDescription(limit_level) << "."; 47392c688b1f744dbded59f2df547f31db1638e316bYabin Cui LOG(WARNING) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling."; 47492c688b1f744dbded59f2df547f31db1638e316bYabin Cui#else 47592c688b1f744dbded59f2df547f31db1638e316bYabin Cui LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level 47692c688b1f744dbded59f2df547f31db1638e316bYabin Cui << ", " << GetLimitLevelDescription(limit_level) << "."; 47792c688b1f744dbded59f2df547f31db1638e316bYabin Cui#endif 47892c688b1f744dbded59f2df547f31db1638e316bYabin Cui return true; 47992c688b1f744dbded59f2df547f31db1638e316bYabin Cui} 480