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