Home | History | Annotate | Download | only in simpleperf
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "environment.h"
     18 
     19 #include <inttypes.h>
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 #include <sys/utsname.h>
     23 
     24 #include <limits>
     25 #include <set>
     26 #include <unordered_map>
     27 #include <vector>
     28 
     29 #include <android-base/file.h>
     30 #include <android-base/logging.h>
     31 #include <android-base/parseint.h>
     32 #include <android-base/strings.h>
     33 #include <android-base/stringprintf.h>
     34 #include <procinfo/process.h>
     35 
     36 #if defined(__ANDROID__)
     37 #include <sys/system_properties.h>
     38 #endif
     39 
     40 #include "read_elf.h"
     41 #include "thread_tree.h"
     42 #include "utils.h"
     43 
     44 class LineReader {
     45  public:
     46   explicit LineReader(FILE* fp) : fp_(fp), buf_(nullptr), bufsize_(0) {
     47   }
     48 
     49   ~LineReader() {
     50     free(buf_);
     51     fclose(fp_);
     52   }
     53 
     54   char* ReadLine() {
     55     if (getline(&buf_, &bufsize_, fp_) != -1) {
     56       return buf_;
     57     }
     58     return nullptr;
     59   }
     60 
     61   size_t MaxLineSize() {
     62     return bufsize_;
     63   }
     64 
     65  private:
     66   FILE* fp_;
     67   char* buf_;
     68   size_t bufsize_;
     69 };
     70 
     71 std::vector<int> GetOnlineCpus() {
     72   std::vector<int> result;
     73   FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
     74   if (fp == nullptr) {
     75     PLOG(ERROR) << "can't open online cpu information";
     76     return result;
     77   }
     78 
     79   LineReader reader(fp);
     80   char* line;
     81   if ((line = reader.ReadLine()) != nullptr) {
     82     result = GetCpusFromString(line);
     83   }
     84   CHECK(!result.empty()) << "can't get online cpu information";
     85   return result;
     86 }
     87 
     88 std::vector<int> GetCpusFromString(const std::string& s) {
     89   std::set<int> cpu_set;
     90   bool have_dash = false;
     91   const char* p = s.c_str();
     92   char* endp;
     93   int last_cpu;
     94   int cpu;
     95   // Parse line like: 0,1-3, 5, 7-8
     96   while ((cpu = static_cast<int>(strtol(p, &endp, 10))) != 0 || endp != p) {
     97     if (have_dash && !cpu_set.empty()) {
     98       for (int t = last_cpu + 1; t < cpu; ++t) {
     99         cpu_set.insert(t);
    100       }
    101     }
    102     have_dash = false;
    103     cpu_set.insert(cpu);
    104     last_cpu = cpu;
    105     p = endp;
    106     while (!isdigit(*p) && *p != '\0') {
    107       if (*p == '-') {
    108         have_dash = true;
    109       }
    110       ++p;
    111     }
    112   }
    113   return std::vector<int>(cpu_set.begin(), cpu_set.end());
    114 }
    115 
    116 static std::vector<KernelMmap> GetLoadedModules() {
    117   std::vector<KernelMmap> result;
    118   FILE* fp = fopen("/proc/modules", "re");
    119   if (fp == nullptr) {
    120     // There is no /proc/modules on Android devices, so we don't print error if failed to open it.
    121     PLOG(DEBUG) << "failed to open file /proc/modules";
    122     return result;
    123   }
    124   LineReader reader(fp);
    125   char* line;
    126   while ((line = reader.ReadLine()) != nullptr) {
    127     // Parse line like: nf_defrag_ipv6 34768 1 nf_conntrack_ipv6, Live 0xffffffffa0fe5000
    128     char name[reader.MaxLineSize()];
    129     uint64_t addr;
    130     if (sscanf(line, "%s%*lu%*u%*s%*s 0x%" PRIx64, name, &addr) == 2) {
    131       KernelMmap map;
    132       map.name = name;
    133       map.start_addr = addr;
    134       result.push_back(map);
    135     }
    136   }
    137   bool all_zero = true;
    138   for (const auto& map : result) {
    139     if (map.start_addr != 0) {
    140       all_zero = false;
    141     }
    142   }
    143   if (all_zero) {
    144     LOG(DEBUG) << "addresses in /proc/modules are all zero, so ignore kernel modules";
    145     return std::vector<KernelMmap>();
    146   }
    147   return result;
    148 }
    149 
    150 static void GetAllModuleFiles(const std::string& path,
    151                               std::unordered_map<std::string, std::string>* module_file_map) {
    152   for (const auto& name : GetEntriesInDir(path)) {
    153     std::string entry_path = path + "/" + name;
    154     if (IsRegularFile(entry_path) && android::base::EndsWith(name, ".ko")) {
    155       std::string module_name = name.substr(0, name.size() - 3);
    156       std::replace(module_name.begin(), module_name.end(), '-', '_');
    157       module_file_map->insert(std::make_pair(module_name, entry_path));
    158     } else if (IsDir(entry_path)) {
    159       GetAllModuleFiles(entry_path, module_file_map);
    160     }
    161   }
    162 }
    163 
    164 static std::vector<KernelMmap> GetModulesInUse() {
    165   utsname uname_buf;
    166   if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
    167     PLOG(ERROR) << "uname() failed";
    168     return std::vector<KernelMmap>();
    169   }
    170   std::string linux_version = uname_buf.release;
    171   std::string module_dirpath = "/lib/modules/" + linux_version + "/kernel";
    172   std::unordered_map<std::string, std::string> module_file_map;
    173   GetAllModuleFiles(module_dirpath, &module_file_map);
    174   // TODO: There is no /proc/modules or /lib/modules on Android, find methods work on it.
    175   std::vector<KernelMmap> module_mmaps = GetLoadedModules();
    176   for (auto& module : module_mmaps) {
    177     auto it = module_file_map.find(module.name);
    178     if (it != module_file_map.end()) {
    179       module.filepath = it->second;
    180     }
    181   }
    182   return module_mmaps;
    183 }
    184 
    185 void GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<KernelMmap>* module_mmaps) {
    186   kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME;
    187   kernel_mmap->start_addr = 0;
    188   kernel_mmap->filepath = kernel_mmap->name;
    189   *module_mmaps = GetModulesInUse();
    190   for (auto& map : *module_mmaps) {
    191     if (map.filepath.empty()) {
    192       map.filepath = "[" + map.name + "]";
    193     }
    194   }
    195 
    196   if (module_mmaps->size() == 0) {
    197     kernel_mmap->len = std::numeric_limits<uint64_t>::max() - kernel_mmap->start_addr;
    198   } else {
    199     std::sort(
    200         module_mmaps->begin(), module_mmaps->end(),
    201         [](const KernelMmap& m1, const KernelMmap& m2) { return m1.start_addr < m2.start_addr; });
    202     // When not having enough privilege, all addresses are read as 0.
    203     if (kernel_mmap->start_addr == (*module_mmaps)[0].start_addr) {
    204       kernel_mmap->len = 0;
    205     } else {
    206       kernel_mmap->len = (*module_mmaps)[0].start_addr - kernel_mmap->start_addr - 1;
    207     }
    208     for (size_t i = 0; i + 1 < module_mmaps->size(); ++i) {
    209       if ((*module_mmaps)[i].start_addr == (*module_mmaps)[i + 1].start_addr) {
    210         (*module_mmaps)[i].len = 0;
    211       } else {
    212         (*module_mmaps)[i].len =
    213             (*module_mmaps)[i + 1].start_addr - (*module_mmaps)[i].start_addr - 1;
    214       }
    215     }
    216     module_mmaps->back().len =
    217         std::numeric_limits<uint64_t>::max() - module_mmaps->back().start_addr;
    218   }
    219 }
    220 
    221 static bool ReadThreadNameAndPid(pid_t tid, std::string* comm, pid_t* pid) {
    222   android::procinfo::ProcessInfo procinfo;
    223   if (!android::procinfo::GetProcessInfo(tid, &procinfo)) {
    224     return false;
    225   }
    226   if (comm != nullptr) {
    227     *comm = procinfo.name;
    228   }
    229   if (pid != nullptr) {
    230     *pid = procinfo.pid;
    231   }
    232   return true;
    233 }
    234 
    235 std::vector<pid_t> GetThreadsInProcess(pid_t pid) {
    236   std::vector<pid_t> result;
    237   android::procinfo::GetProcessTids(pid, &result);
    238   return result;
    239 }
    240 
    241 bool IsThreadAlive(pid_t tid) {
    242   return IsDir(android::base::StringPrintf("/proc/%d", tid));
    243 }
    244 
    245 bool GetProcessForThread(pid_t tid, pid_t* pid) {
    246   return ReadThreadNameAndPid(tid, nullptr, pid);
    247 }
    248 
    249 bool GetThreadName(pid_t tid, std::string* name) {
    250   return ReadThreadNameAndPid(tid, name, nullptr);
    251 }
    252 
    253 std::vector<pid_t> GetAllProcesses() {
    254   std::vector<pid_t> result;
    255   std::vector<std::string> entries = GetEntriesInDir("/proc");
    256   for (const auto& entry : entries) {
    257     pid_t pid;
    258     if (!android::base::ParseInt(entry.c_str(), &pid, 0)) {
    259       continue;
    260     }
    261     result.push_back(pid);
    262   }
    263   return result;
    264 }
    265 
    266 bool GetThreadMmapsInProcess(pid_t pid, std::vector<ThreadMmap>* thread_mmaps) {
    267   std::string map_file = android::base::StringPrintf("/proc/%d/maps", pid);
    268   FILE* fp = fopen(map_file.c_str(), "re");
    269   if (fp == nullptr) {
    270     PLOG(DEBUG) << "can't open file " << map_file;
    271     return false;
    272   }
    273   thread_mmaps->clear();
    274   LineReader reader(fp);
    275   char* line;
    276   while ((line = reader.ReadLine()) != nullptr) {
    277     // Parse line like: 00400000-00409000 r-xp 00000000 fc:00 426998  /usr/lib/gvfs/gvfsd-http
    278     uint64_t start_addr, end_addr, pgoff;
    279     char type[reader.MaxLineSize()];
    280     char execname[reader.MaxLineSize()];
    281     strcpy(execname, "");
    282     if (sscanf(line, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %*x:%*x %*u %s\n", &start_addr,
    283                &end_addr, type, &pgoff, execname) < 4) {
    284       continue;
    285     }
    286     if (strcmp(execname, "") == 0) {
    287       strcpy(execname, DEFAULT_EXECNAME_FOR_THREAD_MMAP);
    288     }
    289     ThreadMmap thread;
    290     thread.start_addr = start_addr;
    291     thread.len = end_addr - start_addr;
    292     thread.pgoff = pgoff;
    293     thread.name = execname;
    294     thread.executable = (type[2] == 'x');
    295     thread_mmaps->push_back(thread);
    296   }
    297   return true;
    298 }
    299 
    300 bool GetKernelBuildId(BuildId* build_id) {
    301   ElfStatus result = GetBuildIdFromNoteFile("/sys/kernel/notes", build_id);
    302   if (result != ElfStatus::NO_ERROR) {
    303     LOG(DEBUG) << "failed to read /sys/kernel/notes: " << result;
    304   }
    305   return result == ElfStatus::NO_ERROR;
    306 }
    307 
    308 bool GetModuleBuildId(const std::string& module_name, BuildId* build_id) {
    309   std::string notefile = "/sys/module/" + module_name + "/notes/.note.gnu.build-id";
    310   return GetBuildIdFromNoteFile(notefile, build_id);
    311 }
    312 
    313 bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) {
    314   std::vector<std::string> strs = android::base::Split(tid_str, ",");
    315   for (const auto& s : strs) {
    316     int tid;
    317     if (!android::base::ParseInt(s.c_str(), &tid, 0)) {
    318       LOG(ERROR) << "Invalid tid '" << s << "'";
    319       return false;
    320     }
    321     if (!IsDir(android::base::StringPrintf("/proc/%d", tid))) {
    322       LOG(ERROR) << "Non existing thread '" << tid << "'";
    323       return false;
    324     }
    325     tid_set->insert(tid);
    326   }
    327   return true;
    328 }
    329 
    330 /*
    331  * perf event paranoia level:
    332  *  -1 - not paranoid at all
    333  *   0 - disallow raw tracepoint access for unpriv
    334  *   1 - disallow cpu events for unpriv
    335  *   2 - disallow kernel profiling for unpriv
    336  *   3 - disallow user profiling for unpriv
    337  */
    338 static bool ReadPerfEventParanoid(int* value) {
    339   std::string s;
    340   if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid", &s)) {
    341     PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_paranoid";
    342     return false;
    343   }
    344   s = android::base::Trim(s);
    345   if (!android::base::ParseInt(s.c_str(), value)) {
    346     PLOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_paranoid: " << s;
    347     return false;
    348   }
    349   return true;
    350 }
    351 
    352 static const char* GetLimitLevelDescription(int limit_level) {
    353   switch (limit_level) {
    354     case -1: return "unlimited";
    355     case 0: return "disallowing raw tracepoint access for unpriv";
    356     case 1: return "disallowing cpu events for unpriv";
    357     case 2: return "disallowing kernel profiling for unpriv";
    358     case 3: return "disallowing user profiling for unpriv";
    359     default: return "unknown level";
    360   }
    361 }
    362 
    363 bool CheckPerfEventLimit() {
    364   // root is not limited by /proc/sys/kernel/perf_event_paranoid.
    365   if (IsRoot()) {
    366     return true;
    367   }
    368   int limit_level;
    369   bool can_read_paranoid = ReadPerfEventParanoid(&limit_level);
    370   if (can_read_paranoid && limit_level <= 1) {
    371     return true;
    372   }
    373 #if defined(__ANDROID__)
    374   const char* prop_name = "security.perf_harden";
    375   char prop_value[PROP_VALUE_MAX];
    376   if (__system_property_get(prop_name, prop_value) <= 0) {
    377     // can't do anything if there is no such property.
    378     return true;
    379   }
    380   if (strcmp(prop_value, "0") == 0) {
    381     return true;
    382   }
    383   // Try to enable perf_event_paranoid by setprop security.perf_harden=0.
    384   if (__system_property_set(prop_name, "0") == 0) {
    385     sleep(1);
    386     if (can_read_paranoid && ReadPerfEventParanoid(&limit_level) && limit_level <= 1) {
    387       return true;
    388     }
    389     if (__system_property_get(prop_name, prop_value) > 0 && strcmp(prop_value, "0") == 0) {
    390       return true;
    391     }
    392   }
    393   if (can_read_paranoid) {
    394     LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level
    395         << ", " << GetLimitLevelDescription(limit_level) << ".";
    396   }
    397   LOG(WARNING) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling.";
    398   return false;
    399 #else
    400   if (can_read_paranoid) {
    401     LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level
    402         << ", " << GetLimitLevelDescription(limit_level) << ".";
    403     return false;
    404   }
    405 #endif
    406   return true;
    407 }
    408 
    409 bool GetMaxSampleFrequency(uint64_t* max_sample_freq) {
    410   std::string s;
    411   if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_max_sample_rate", &s)) {
    412     PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_max_sample_rate";
    413     return false;
    414   }
    415   s = android::base::Trim(s);
    416   if (!android::base::ParseUint(s.c_str(), max_sample_freq)) {
    417     LOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_max_sample_rate: " << s;
    418     return false;
    419   }
    420   return true;
    421 }
    422 
    423 bool CheckSampleFrequency(uint64_t sample_freq) {
    424   if (sample_freq == 0) {
    425     LOG(ERROR) << "Sample frequency can't be zero.";
    426     return false;
    427   }
    428   uint64_t max_sample_freq;
    429   if (!GetMaxSampleFrequency(&max_sample_freq)) {
    430     // Omit the check if can't read perf_event_max_sample_rate.
    431     return true;
    432   }
    433   if (sample_freq > max_sample_freq) {
    434     LOG(ERROR) << "Sample frequency " << sample_freq << " is out of range [1, "
    435         << max_sample_freq << "]";
    436     return false;
    437   }
    438   return true;
    439 }
    440 
    441 bool CheckKernelSymbolAddresses() {
    442   const std::string kptr_restrict_file = "/proc/sys/kernel/kptr_restrict";
    443   std::string s;
    444   if (!android::base::ReadFileToString(kptr_restrict_file, &s)) {
    445     PLOG(DEBUG) << "failed to read " << kptr_restrict_file;
    446     return false;
    447   }
    448   s = android::base::Trim(s);
    449   int value;
    450   if (!android::base::ParseInt(s.c_str(), &value)) {
    451     LOG(ERROR) << "failed to parse " << kptr_restrict_file << ": " << s;
    452     return false;
    453   }
    454   if (value == 0) {
    455     return true;
    456   }
    457   if (value == 1 && IsRoot()) {
    458     return true;
    459   }
    460   LOG(WARNING) << "Access to kernel symbol addresses is restricted. If "
    461       << "possible, please do `echo 0 >/proc/sys/kernel/kptr_restrict` "
    462       << "to fix this.";
    463   return false;
    464 }
    465 
    466 ArchType GetMachineArch() {
    467   utsname uname_buf;
    468   if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
    469     PLOG(WARNING) << "uname() failed";
    470     return GetBuildArch();
    471   }
    472   ArchType arch = GetArchType(uname_buf.machine);
    473   if (arch != ARCH_UNSUPPORTED) {
    474     return arch;
    475   }
    476   return GetBuildArch();
    477 }
    478