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 <signal.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <sys/utsname.h>
     24 
     25 #include <limits>
     26 #include <set>
     27 #include <unordered_map>
     28 #include <vector>
     29 
     30 #include <android-base/file.h>
     31 #include <android-base/logging.h>
     32 #include <android-base/parseint.h>
     33 #include <android-base/strings.h>
     34 #include <android-base/stringprintf.h>
     35 #include <procinfo/process.h>
     36 
     37 #if defined(__ANDROID__)
     38 #include <sys/system_properties.h>
     39 #endif
     40 
     41 #include "event_type.h"
     42 #include "IOEventLoop.h"
     43 #include "read_elf.h"
     44 #include "thread_tree.h"
     45 #include "utils.h"
     46 #include "workload.h"
     47 
     48 class LineReader {
     49  public:
     50   explicit LineReader(FILE* fp) : fp_(fp), buf_(nullptr), bufsize_(0) {
     51   }
     52 
     53   ~LineReader() {
     54     free(buf_);
     55     fclose(fp_);
     56   }
     57 
     58   char* ReadLine() {
     59     if (getline(&buf_, &bufsize_, fp_) != -1) {
     60       return buf_;
     61     }
     62     return nullptr;
     63   }
     64 
     65   size_t MaxLineSize() {
     66     return bufsize_;
     67   }
     68 
     69  private:
     70   FILE* fp_;
     71   char* buf_;
     72   size_t bufsize_;
     73 };
     74 
     75 std::vector<int> GetOnlineCpus() {
     76   std::vector<int> result;
     77   FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
     78   if (fp == nullptr) {
     79     PLOG(ERROR) << "can't open online cpu information";
     80     return result;
     81   }
     82 
     83   LineReader reader(fp);
     84   char* line;
     85   if ((line = reader.ReadLine()) != nullptr) {
     86     result = GetCpusFromString(line);
     87   }
     88   CHECK(!result.empty()) << "can't get online cpu information";
     89   return result;
     90 }
     91 
     92 std::vector<int> GetCpusFromString(const std::string& s) {
     93   std::set<int> cpu_set;
     94   bool have_dash = false;
     95   const char* p = s.c_str();
     96   char* endp;
     97   int last_cpu;
     98   int cpu;
     99   // Parse line like: 0,1-3, 5, 7-8
    100   while ((cpu = static_cast<int>(strtol(p, &endp, 10))) != 0 || endp != p) {
    101     if (have_dash && !cpu_set.empty()) {
    102       for (int t = last_cpu + 1; t < cpu; ++t) {
    103         cpu_set.insert(t);
    104       }
    105     }
    106     have_dash = false;
    107     cpu_set.insert(cpu);
    108     last_cpu = cpu;
    109     p = endp;
    110     while (!isdigit(*p) && *p != '\0') {
    111       if (*p == '-') {
    112         have_dash = true;
    113       }
    114       ++p;
    115     }
    116   }
    117   return std::vector<int>(cpu_set.begin(), cpu_set.end());
    118 }
    119 
    120 static std::vector<KernelMmap> GetLoadedModules() {
    121   std::vector<KernelMmap> result;
    122   FILE* fp = fopen("/proc/modules", "re");
    123   if (fp == nullptr) {
    124     // There is no /proc/modules on Android devices, so we don't print error if failed to open it.
    125     PLOG(DEBUG) << "failed to open file /proc/modules";
    126     return result;
    127   }
    128   LineReader reader(fp);
    129   char* line;
    130   while ((line = reader.ReadLine()) != nullptr) {
    131     // Parse line like: nf_defrag_ipv6 34768 1 nf_conntrack_ipv6, Live 0xffffffffa0fe5000
    132     char name[reader.MaxLineSize()];
    133     uint64_t addr;
    134     if (sscanf(line, "%s%*lu%*u%*s%*s 0x%" PRIx64, name, &addr) == 2) {
    135       KernelMmap map;
    136       map.name = name;
    137       map.start_addr = addr;
    138       result.push_back(map);
    139     }
    140   }
    141   bool all_zero = true;
    142   for (const auto& map : result) {
    143     if (map.start_addr != 0) {
    144       all_zero = false;
    145     }
    146   }
    147   if (all_zero) {
    148     LOG(DEBUG) << "addresses in /proc/modules are all zero, so ignore kernel modules";
    149     return std::vector<KernelMmap>();
    150   }
    151   return result;
    152 }
    153 
    154 static void GetAllModuleFiles(const std::string& path,
    155                               std::unordered_map<std::string, std::string>* module_file_map) {
    156   for (const auto& name : GetEntriesInDir(path)) {
    157     std::string entry_path = path + "/" + name;
    158     if (IsRegularFile(entry_path) && android::base::EndsWith(name, ".ko")) {
    159       std::string module_name = name.substr(0, name.size() - 3);
    160       std::replace(module_name.begin(), module_name.end(), '-', '_');
    161       module_file_map->insert(std::make_pair(module_name, entry_path));
    162     } else if (IsDir(entry_path)) {
    163       GetAllModuleFiles(entry_path, module_file_map);
    164     }
    165   }
    166 }
    167 
    168 static std::vector<KernelMmap> GetModulesInUse() {
    169   utsname uname_buf;
    170   if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
    171     PLOG(ERROR) << "uname() failed";
    172     return std::vector<KernelMmap>();
    173   }
    174   std::string linux_version = uname_buf.release;
    175   std::string module_dirpath = "/lib/modules/" + linux_version + "/kernel";
    176   std::unordered_map<std::string, std::string> module_file_map;
    177   GetAllModuleFiles(module_dirpath, &module_file_map);
    178   // TODO: There is no /proc/modules or /lib/modules on Android, find methods work on it.
    179   std::vector<KernelMmap> module_mmaps = GetLoadedModules();
    180   for (auto& module : module_mmaps) {
    181     auto it = module_file_map.find(module.name);
    182     if (it != module_file_map.end()) {
    183       module.filepath = it->second;
    184     }
    185   }
    186   return module_mmaps;
    187 }
    188 
    189 void GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<KernelMmap>* module_mmaps) {
    190   kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME;
    191   kernel_mmap->start_addr = 0;
    192   kernel_mmap->filepath = kernel_mmap->name;
    193   *module_mmaps = GetModulesInUse();
    194   for (auto& map : *module_mmaps) {
    195     if (map.filepath.empty()) {
    196       map.filepath = "[" + map.name + "]";
    197     }
    198   }
    199 
    200   if (module_mmaps->size() == 0) {
    201     kernel_mmap->len = std::numeric_limits<uint64_t>::max() - kernel_mmap->start_addr;
    202   } else {
    203     std::sort(
    204         module_mmaps->begin(), module_mmaps->end(),
    205         [](const KernelMmap& m1, const KernelMmap& m2) { return m1.start_addr < m2.start_addr; });
    206     // When not having enough privilege, all addresses are read as 0.
    207     if (kernel_mmap->start_addr == (*module_mmaps)[0].start_addr) {
    208       kernel_mmap->len = 0;
    209     } else {
    210       kernel_mmap->len = (*module_mmaps)[0].start_addr - kernel_mmap->start_addr - 1;
    211     }
    212     for (size_t i = 0; i + 1 < module_mmaps->size(); ++i) {
    213       if ((*module_mmaps)[i].start_addr == (*module_mmaps)[i + 1].start_addr) {
    214         (*module_mmaps)[i].len = 0;
    215       } else {
    216         (*module_mmaps)[i].len =
    217             (*module_mmaps)[i + 1].start_addr - (*module_mmaps)[i].start_addr - 1;
    218       }
    219     }
    220     module_mmaps->back().len =
    221         std::numeric_limits<uint64_t>::max() - module_mmaps->back().start_addr;
    222   }
    223 }
    224 
    225 static bool ReadThreadNameAndPid(pid_t tid, std::string* comm, pid_t* pid) {
    226   android::procinfo::ProcessInfo procinfo;
    227   if (!android::procinfo::GetProcessInfo(tid, &procinfo)) {
    228     return false;
    229   }
    230   if (comm != nullptr) {
    231     *comm = procinfo.name;
    232   }
    233   if (pid != nullptr) {
    234     *pid = procinfo.pid;
    235   }
    236   return true;
    237 }
    238 
    239 std::vector<pid_t> GetThreadsInProcess(pid_t pid) {
    240   std::vector<pid_t> result;
    241   android::procinfo::GetProcessTids(pid, &result);
    242   return result;
    243 }
    244 
    245 bool IsThreadAlive(pid_t tid) {
    246   return IsDir(android::base::StringPrintf("/proc/%d", tid));
    247 }
    248 
    249 bool GetProcessForThread(pid_t tid, pid_t* pid) {
    250   return ReadThreadNameAndPid(tid, nullptr, pid);
    251 }
    252 
    253 bool GetThreadName(pid_t tid, std::string* name) {
    254   return ReadThreadNameAndPid(tid, name, nullptr);
    255 }
    256 
    257 std::vector<pid_t> GetAllProcesses() {
    258   std::vector<pid_t> result;
    259   std::vector<std::string> entries = GetEntriesInDir("/proc");
    260   for (const auto& entry : entries) {
    261     pid_t pid;
    262     if (!android::base::ParseInt(entry.c_str(), &pid, 0)) {
    263       continue;
    264     }
    265     result.push_back(pid);
    266   }
    267   return result;
    268 }
    269 
    270 bool GetThreadMmapsInProcess(pid_t pid, std::vector<ThreadMmap>* thread_mmaps) {
    271   std::string map_file = android::base::StringPrintf("/proc/%d/maps", pid);
    272   FILE* fp = fopen(map_file.c_str(), "re");
    273   if (fp == nullptr) {
    274     PLOG(DEBUG) << "can't open file " << map_file;
    275     return false;
    276   }
    277   thread_mmaps->clear();
    278   LineReader reader(fp);
    279   char* line;
    280   while ((line = reader.ReadLine()) != nullptr) {
    281     // Parse line like: 00400000-00409000 r-xp 00000000 fc:00 426998  /usr/lib/gvfs/gvfsd-http
    282     uint64_t start_addr, end_addr, pgoff;
    283     char type[reader.MaxLineSize()];
    284     char execname[reader.MaxLineSize()];
    285     strcpy(execname, "");
    286     if (sscanf(line, "%" PRIx64 "-%" PRIx64 " %s %" PRIx64 " %*x:%*x %*u %s\n", &start_addr,
    287                &end_addr, type, &pgoff, execname) < 4) {
    288       continue;
    289     }
    290     if (strcmp(execname, "") == 0) {
    291       strcpy(execname, DEFAULT_EXECNAME_FOR_THREAD_MMAP);
    292     }
    293     ThreadMmap thread;
    294     thread.start_addr = start_addr;
    295     thread.len = end_addr - start_addr;
    296     thread.pgoff = pgoff;
    297     thread.name = execname;
    298     thread.executable = (type[2] == 'x');
    299     thread_mmaps->push_back(thread);
    300   }
    301   return true;
    302 }
    303 
    304 bool GetKernelBuildId(BuildId* build_id) {
    305   ElfStatus result = GetBuildIdFromNoteFile("/sys/kernel/notes", build_id);
    306   if (result != ElfStatus::NO_ERROR) {
    307     LOG(DEBUG) << "failed to read /sys/kernel/notes: " << result;
    308   }
    309   return result == ElfStatus::NO_ERROR;
    310 }
    311 
    312 bool GetModuleBuildId(const std::string& module_name, BuildId* build_id) {
    313   std::string notefile = "/sys/module/" + module_name + "/notes/.note.gnu.build-id";
    314   return GetBuildIdFromNoteFile(notefile, build_id);
    315 }
    316 
    317 bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) {
    318   std::vector<std::string> strs = android::base::Split(tid_str, ",");
    319   for (const auto& s : strs) {
    320     int tid;
    321     if (!android::base::ParseInt(s.c_str(), &tid, 0)) {
    322       LOG(ERROR) << "Invalid tid '" << s << "'";
    323       return false;
    324     }
    325     if (!IsDir(android::base::StringPrintf("/proc/%d", tid))) {
    326       LOG(ERROR) << "Non existing thread '" << tid << "'";
    327       return false;
    328     }
    329     tid_set->insert(tid);
    330   }
    331   return true;
    332 }
    333 
    334 /*
    335  * perf event paranoia level:
    336  *  -1 - not paranoid at all
    337  *   0 - disallow raw tracepoint access for unpriv
    338  *   1 - disallow cpu events for unpriv
    339  *   2 - disallow kernel profiling for unpriv
    340  *   3 - disallow user profiling for unpriv
    341  */
    342 static bool ReadPerfEventParanoid(int* value) {
    343   std::string s;
    344   if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid", &s)) {
    345     PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_paranoid";
    346     return false;
    347   }
    348   s = android::base::Trim(s);
    349   if (!android::base::ParseInt(s.c_str(), value)) {
    350     PLOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_paranoid: " << s;
    351     return false;
    352   }
    353   return true;
    354 }
    355 
    356 bool CanRecordRawData() {
    357   int value;
    358   return IsRoot() || (ReadPerfEventParanoid(&value) && value == -1);
    359 }
    360 
    361 static const char* GetLimitLevelDescription(int limit_level) {
    362   switch (limit_level) {
    363     case -1: return "unlimited";
    364     case 0: return "disallowing raw tracepoint access for unpriv";
    365     case 1: return "disallowing cpu events for unpriv";
    366     case 2: return "disallowing kernel profiling for unpriv";
    367     case 3: return "disallowing user profiling for unpriv";
    368     default: return "unknown level";
    369   }
    370 }
    371 
    372 bool CheckPerfEventLimit() {
    373   // Root is not limited by /proc/sys/kernel/perf_event_paranoid. However, the monitored threads
    374   // may create child processes not running as root. To make sure the child processes have
    375   // enough permission to create inherited tracepoint events, write -1 to perf_event_paranoid.
    376   // See http://b/62230699.
    377   if (IsRoot() && android::base::WriteStringToFile("-1", "/proc/sys/kernel/perf_event_paranoid")) {
    378     return true;
    379   }
    380   int limit_level;
    381   bool can_read_paranoid = ReadPerfEventParanoid(&limit_level);
    382   if (can_read_paranoid && limit_level <= 1) {
    383     return true;
    384   }
    385 #if defined(__ANDROID__)
    386   const char* prop_name = "security.perf_harden";
    387   char prop_value[PROP_VALUE_MAX];
    388   if (__system_property_get(prop_name, prop_value) <= 0) {
    389     // can't do anything if there is no such property.
    390     return true;
    391   }
    392   if (strcmp(prop_value, "0") == 0) {
    393     return true;
    394   }
    395   // Try to enable perf_event_paranoid by setprop security.perf_harden=0.
    396   if (__system_property_set(prop_name, "0") == 0) {
    397     sleep(1);
    398     if (can_read_paranoid && ReadPerfEventParanoid(&limit_level) && limit_level <= 1) {
    399       return true;
    400     }
    401     if (__system_property_get(prop_name, prop_value) > 0 && strcmp(prop_value, "0") == 0) {
    402       return true;
    403     }
    404   }
    405   if (can_read_paranoid) {
    406     LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level
    407         << ", " << GetLimitLevelDescription(limit_level) << ".";
    408   }
    409   LOG(WARNING) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling.";
    410   return false;
    411 #else
    412   if (can_read_paranoid) {
    413     LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level
    414         << ", " << GetLimitLevelDescription(limit_level) << ".";
    415     return false;
    416   }
    417 #endif
    418   return true;
    419 }
    420 
    421 bool GetMaxSampleFrequency(uint64_t* max_sample_freq) {
    422   std::string s;
    423   if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_max_sample_rate", &s)) {
    424     PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_max_sample_rate";
    425     return false;
    426   }
    427   s = android::base::Trim(s);
    428   if (!android::base::ParseUint(s.c_str(), max_sample_freq)) {
    429     LOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_max_sample_rate: " << s;
    430     return false;
    431   }
    432   return true;
    433 }
    434 
    435 bool CheckSampleFrequency(uint64_t sample_freq) {
    436   if (sample_freq == 0) {
    437     LOG(ERROR) << "Sample frequency can't be zero.";
    438     return false;
    439   }
    440   uint64_t max_sample_freq;
    441   if (!GetMaxSampleFrequency(&max_sample_freq)) {
    442     // Omit the check if can't read perf_event_max_sample_rate.
    443     return true;
    444   }
    445   if (sample_freq > max_sample_freq) {
    446     LOG(ERROR) << "Sample frequency " << sample_freq << " is out of range [1, "
    447         << max_sample_freq << "]";
    448     return false;
    449   }
    450   return true;
    451 }
    452 
    453 bool CheckKernelSymbolAddresses() {
    454   const std::string kptr_restrict_file = "/proc/sys/kernel/kptr_restrict";
    455   std::string s;
    456   if (!android::base::ReadFileToString(kptr_restrict_file, &s)) {
    457     PLOG(DEBUG) << "failed to read " << kptr_restrict_file;
    458     return false;
    459   }
    460   s = android::base::Trim(s);
    461   int value;
    462   if (!android::base::ParseInt(s.c_str(), &value)) {
    463     LOG(ERROR) << "failed to parse " << kptr_restrict_file << ": " << s;
    464     return false;
    465   }
    466   // Accessible to everyone?
    467   if (value == 0) {
    468     return true;
    469   }
    470   // Accessible to root?
    471   if (value == 1 && IsRoot()) {
    472     return true;
    473   }
    474   // Can we make it accessible to us?
    475   if (IsRoot() && android::base::WriteStringToFile("1", kptr_restrict_file)) {
    476     return true;
    477   }
    478   LOG(WARNING) << "Access to kernel symbol addresses is restricted. If "
    479       << "possible, please do `echo 0 >/proc/sys/kernel/kptr_restrict` "
    480       << "to fix this.";
    481   return false;
    482 }
    483 
    484 ArchType GetMachineArch() {
    485   utsname uname_buf;
    486   if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
    487     PLOG(WARNING) << "uname() failed";
    488     return GetBuildArch();
    489   }
    490   ArchType arch = GetArchType(uname_buf.machine);
    491   if (arch != ARCH_UNSUPPORTED) {
    492     return arch;
    493   }
    494   return GetBuildArch();
    495 }
    496 
    497 void PrepareVdsoFile() {
    498   // vdso is an elf file in memory loaded in each process's user space by the kernel. To read
    499   // symbols from it and unwind through it, we need to dump it into a file in storage.
    500   // It doesn't affect much when failed to prepare vdso file, so there is no need to return values.
    501   std::vector<ThreadMmap> thread_mmaps;
    502   if (!GetThreadMmapsInProcess(getpid(), &thread_mmaps)) {
    503     return;
    504   }
    505   const ThreadMmap* vdso_map = nullptr;
    506   for (const auto& map : thread_mmaps) {
    507     if (map.name == "[vdso]") {
    508       vdso_map = &map;
    509       break;
    510     }
    511   }
    512   if (vdso_map == nullptr) {
    513     return;
    514   }
    515   std::string s(vdso_map->len, '\0');
    516   memcpy(&s[0], reinterpret_cast<void*>(static_cast<uintptr_t>(vdso_map->start_addr)),
    517          vdso_map->len);
    518   std::unique_ptr<TemporaryFile> tmpfile(new TemporaryFile);
    519   if (!android::base::WriteStringToFile(s, tmpfile->path)) {
    520     return;
    521   }
    522   Dso::SetVdsoFile(std::move(tmpfile), sizeof(size_t) == sizeof(uint64_t));
    523 }
    524 
    525 int WaitForAppProcess(const std::string& package_name) {
    526   size_t loop_count = 0;
    527   while (true) {
    528     std::vector<pid_t> pids = GetAllProcesses();
    529     for (pid_t pid : pids) {
    530       std::string cmdline;
    531       if (!android::base::ReadFileToString("/proc/" + std::to_string(pid) + "/cmdline", &cmdline)) {
    532         // Maybe we don't have permission to read it.
    533         continue;
    534       }
    535       cmdline = android::base::Basename(cmdline);
    536       if (cmdline == package_name) {
    537         if (loop_count > 0u) {
    538           LOG(INFO) << "Got process " << pid << " for package " << package_name;
    539         }
    540         return pid;
    541       }
    542     }
    543     if (++loop_count == 1u) {
    544       LOG(INFO) << "Waiting for process of app " << package_name;
    545     }
    546     usleep(1000);
    547   }
    548 }
    549 
    550 class ScopedFile {
    551  public:
    552   ScopedFile(const std::string& filepath, std::string app_package_name = "")
    553       : filepath_(filepath), app_package_name_(app_package_name) {}
    554 
    555   ~ScopedFile() {
    556     if (app_package_name_.empty()) {
    557       unlink(filepath_.c_str());
    558     } else {
    559       Workload::RunCmd({"run-as", app_package_name_, "rm", "-rf", filepath_});
    560     }
    561   }
    562 
    563  private:
    564   std::string filepath_;
    565   std::string app_package_name_;
    566 };
    567 
    568 bool RunInAppContext(const std::string& app_package_name, const std::string& cmd,
    569                      const std::vector<std::string>& args, size_t workload_args_size,
    570                      const std::string& output_filepath, bool need_tracepoint_events) {
    571   // 1. Test if the package exists.
    572   if (!Workload::RunCmd({"run-as", app_package_name, "echo", ">/dev/null"}, false)) {
    573     LOG(ERROR) << "Package " << app_package_name << "doesn't exist or isn't debuggable.";
    574     return false;
    575   }
    576 
    577   // 2. Copy simpleperf binary to the package. Create tracepoint_file if needed.
    578   std::string simpleperf_path;
    579   if (!android::base::Readlink("/proc/self/exe", &simpleperf_path)) {
    580     PLOG(ERROR) << "ReadLink failed";
    581     return false;
    582   }
    583   if (!Workload::RunCmd({"run-as", app_package_name, "cp", simpleperf_path, "simpleperf"})) {
    584     return false;
    585   }
    586   ScopedFile scoped_simpleperf("simpleperf", app_package_name);
    587   std::unique_ptr<ScopedFile> scoped_tracepoint_file;
    588   const std::string tracepoint_file = "/data/local/tmp/tracepoint_events";
    589   if (need_tracepoint_events) {
    590     // Since we can't read tracepoint events from tracefs in app's context, we need to prepare
    591     // them in tracepoint_file in shell's context, and pass the path of tracepoint_file to the
    592     // child process using --tracepoint-events option.
    593     if (!android::base::WriteStringToFile(GetTracepointEvents(), tracepoint_file)) {
    594       PLOG(ERROR) << "Failed to store tracepoint events";
    595       return false;
    596     }
    597     scoped_tracepoint_file.reset(new ScopedFile(tracepoint_file));
    598   }
    599 
    600   // 3. Prepare to start child process to profile.
    601   std::string output_basename = output_filepath.empty() ? "" :
    602                                     android::base::Basename(output_filepath);
    603   std::vector<std::string> new_args =
    604       {"run-as", app_package_name, "./simpleperf", cmd, "--in-app"};
    605   if (need_tracepoint_events) {
    606     new_args.push_back("--tracepoint-events");
    607     new_args.push_back(tracepoint_file);
    608   }
    609   for (size_t i = 0; i < args.size(); ++i) {
    610     if (i >= args.size() - workload_args_size || args[i] != "-o") {
    611       new_args.push_back(args[i]);
    612     } else {
    613       new_args.push_back(args[i++]);
    614       new_args.push_back(output_basename);
    615     }
    616   }
    617   std::unique_ptr<Workload> workload = Workload::CreateWorkload(new_args);
    618   if (!workload) {
    619     return false;
    620   }
    621 
    622   IOEventLoop loop;
    623   bool need_to_kill_child = false;
    624   if (!loop.AddSignalEvents({SIGINT, SIGTERM, SIGHUP},
    625                             [&]() { need_to_kill_child = true; return loop.ExitLoop(); })) {
    626     return false;
    627   }
    628   if (!loop.AddSignalEvent(SIGCHLD, [&]() { return loop.ExitLoop(); })) {
    629     return false;
    630   }
    631 
    632   // 4. Create child process to run run-as, and wait for the child process.
    633   if (!workload->Start()) {
    634     return false;
    635   }
    636   if (!loop.RunLoop()) {
    637     return false;
    638   }
    639   if (need_to_kill_child) {
    640     // The child process can exit before we kill it, so don't report kill errors.
    641     Workload::RunCmd({"run-as", app_package_name, "pkill", "simpleperf"}, false);
    642   }
    643   int exit_code;
    644   if (!workload->WaitChildProcess(&exit_code) || exit_code != 0) {
    645     return false;
    646   }
    647 
    648   // 5. If there is any output file, copy it from the app's directory.
    649   if (!output_filepath.empty()) {
    650     if (!Workload::RunCmd({"run-as", app_package_name, "cat", output_basename,
    651                            ">" + output_filepath})) {
    652       return false;
    653     }
    654     if (!Workload::RunCmd({"run-as", app_package_name, "rm", output_basename})) {
    655       return false;
    656     }
    657   }
    658   return true;
    659 }
    660 
    661 static std::string default_package_name;
    662 
    663 void SetDefaultAppPackageName(const std::string& package_name) {
    664   default_package_name = package_name;
    665 }
    666 
    667 const std::string& GetDefaultAppPackageName() {
    668   return default_package_name;
    669 }
    670