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 <string.h> 24 #include <sys/resource.h> 25 #include <sys/utsname.h> 26 27 #include <limits> 28 #include <set> 29 #include <unordered_map> 30 #include <vector> 31 32 #include <android-base/file.h> 33 #include <android-base/logging.h> 34 #include <android-base/parseint.h> 35 #include <android-base/strings.h> 36 #include <android-base/stringprintf.h> 37 #include <procinfo/process.h> 38 #include <procinfo/process_map.h> 39 40 #if defined(__ANDROID__) 41 #include <android-base/properties.h> 42 #endif 43 44 #include "command.h" 45 #include "event_type.h" 46 #include "IOEventLoop.h" 47 #include "read_elf.h" 48 #include "thread_tree.h" 49 #include "utils.h" 50 #include "workload.h" 51 52 using namespace simpleperf; 53 54 class LineReader { 55 public: 56 explicit LineReader(FILE* fp) : fp_(fp), buf_(nullptr), bufsize_(0) { 57 } 58 59 ~LineReader() { 60 free(buf_); 61 fclose(fp_); 62 } 63 64 char* ReadLine() { 65 if (getline(&buf_, &bufsize_, fp_) != -1) { 66 return buf_; 67 } 68 return nullptr; 69 } 70 71 size_t MaxLineSize() { 72 return bufsize_; 73 } 74 75 private: 76 FILE* fp_; 77 char* buf_; 78 size_t bufsize_; 79 }; 80 81 std::vector<int> GetOnlineCpus() { 82 std::vector<int> result; 83 FILE* fp = fopen("/sys/devices/system/cpu/online", "re"); 84 if (fp == nullptr) { 85 PLOG(ERROR) << "can't open online cpu information"; 86 return result; 87 } 88 89 LineReader reader(fp); 90 char* line; 91 if ((line = reader.ReadLine()) != nullptr) { 92 result = GetCpusFromString(line); 93 } 94 CHECK(!result.empty()) << "can't get online cpu information"; 95 return result; 96 } 97 98 static std::vector<KernelMmap> GetLoadedModules() { 99 std::vector<KernelMmap> result; 100 FILE* fp = fopen("/proc/modules", "re"); 101 if (fp == nullptr) { 102 // There is no /proc/modules on Android devices, so we don't print error if failed to open it. 103 PLOG(DEBUG) << "failed to open file /proc/modules"; 104 return result; 105 } 106 LineReader reader(fp); 107 char* line; 108 while ((line = reader.ReadLine()) != nullptr) { 109 // Parse line like: nf_defrag_ipv6 34768 1 nf_conntrack_ipv6, Live 0xffffffffa0fe5000 110 char name[reader.MaxLineSize()]; 111 uint64_t addr; 112 uint64_t len; 113 if (sscanf(line, "%s%" PRIu64 "%*u%*s%*s 0x%" PRIx64, name, &len, &addr) == 3) { 114 KernelMmap map; 115 map.name = name; 116 map.start_addr = addr; 117 map.len = len; 118 result.push_back(map); 119 } 120 } 121 bool all_zero = true; 122 for (const auto& map : result) { 123 if (map.start_addr != 0) { 124 all_zero = false; 125 } 126 } 127 if (all_zero) { 128 LOG(DEBUG) << "addresses in /proc/modules are all zero, so ignore kernel modules"; 129 return std::vector<KernelMmap>(); 130 } 131 return result; 132 } 133 134 static void GetAllModuleFiles(const std::string& path, 135 std::unordered_map<std::string, std::string>* module_file_map) { 136 for (const auto& name : GetEntriesInDir(path)) { 137 std::string entry_path = path + "/" + name; 138 if (IsRegularFile(entry_path) && android::base::EndsWith(name, ".ko")) { 139 std::string module_name = name.substr(0, name.size() - 3); 140 std::replace(module_name.begin(), module_name.end(), '-', '_'); 141 module_file_map->insert(std::make_pair(module_name, entry_path)); 142 } else if (IsDir(entry_path)) { 143 GetAllModuleFiles(entry_path, module_file_map); 144 } 145 } 146 } 147 148 static std::vector<KernelMmap> GetModulesInUse() { 149 std::vector<KernelMmap> module_mmaps = GetLoadedModules(); 150 if (module_mmaps.empty()) { 151 return std::vector<KernelMmap>(); 152 } 153 std::unordered_map<std::string, std::string> module_file_map; 154 #if defined(__ANDROID__) 155 // Search directories listed in "File locations" section in 156 // https://source.android.com/devices/architecture/kernel/modular-kernels. 157 for (const auto& path : {"/vendor/lib/modules", "/odm/lib/modules", "/lib/modules"}) { 158 GetAllModuleFiles(path, &module_file_map); 159 } 160 #else 161 utsname uname_buf; 162 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) { 163 PLOG(ERROR) << "uname() failed"; 164 return std::vector<KernelMmap>(); 165 } 166 std::string linux_version = uname_buf.release; 167 std::string module_dirpath = "/lib/modules/" + linux_version + "/kernel"; 168 GetAllModuleFiles(module_dirpath, &module_file_map); 169 #endif 170 for (auto& module : module_mmaps) { 171 auto it = module_file_map.find(module.name); 172 if (it != module_file_map.end()) { 173 module.filepath = it->second; 174 } 175 } 176 return module_mmaps; 177 } 178 179 void GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<KernelMmap>* module_mmaps) { 180 kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME; 181 kernel_mmap->start_addr = 0; 182 kernel_mmap->len = std::numeric_limits<uint64_t>::max(); 183 kernel_mmap->filepath = kernel_mmap->name; 184 *module_mmaps = GetModulesInUse(); 185 for (auto& map : *module_mmaps) { 186 if (map.filepath.empty()) { 187 map.filepath = "[" + map.name + "]"; 188 } 189 } 190 } 191 192 bool ReadThreadNameAndPid(pid_t tid, std::string* comm, pid_t* pid) { 193 android::procinfo::ProcessInfo procinfo; 194 if (!android::procinfo::GetProcessInfo(tid, &procinfo)) { 195 return false; 196 } 197 if (comm != nullptr) { 198 *comm = procinfo.name; 199 } 200 if (pid != nullptr) { 201 *pid = procinfo.pid; 202 } 203 return true; 204 } 205 206 std::vector<pid_t> GetThreadsInProcess(pid_t pid) { 207 std::vector<pid_t> result; 208 android::procinfo::GetProcessTids(pid, &result); 209 return result; 210 } 211 212 bool IsThreadAlive(pid_t tid) { 213 return IsDir(android::base::StringPrintf("/proc/%d", tid)); 214 } 215 216 bool GetProcessForThread(pid_t tid, pid_t* pid) { 217 return ReadThreadNameAndPid(tid, nullptr, pid); 218 } 219 220 bool GetThreadName(pid_t tid, std::string* name) { 221 return ReadThreadNameAndPid(tid, name, nullptr); 222 } 223 224 std::vector<pid_t> GetAllProcesses() { 225 std::vector<pid_t> result; 226 std::vector<std::string> entries = GetEntriesInDir("/proc"); 227 for (const auto& entry : entries) { 228 pid_t pid; 229 if (!android::base::ParseInt(entry.c_str(), &pid, 0)) { 230 continue; 231 } 232 result.push_back(pid); 233 } 234 return result; 235 } 236 237 bool GetThreadMmapsInProcess(pid_t pid, std::vector<ThreadMmap>* thread_mmaps) { 238 thread_mmaps->clear(); 239 return android::procinfo::ReadProcessMaps( 240 pid, [&](uint64_t start, uint64_t end, uint16_t flags, uint64_t pgoff, 241 ino_t, const char* name) { 242 thread_mmaps->emplace_back(start, end - start, pgoff, name, flags); 243 }); 244 } 245 246 bool GetKernelBuildId(BuildId* build_id) { 247 ElfStatus result = GetBuildIdFromNoteFile("/sys/kernel/notes", build_id); 248 if (result != ElfStatus::NO_ERROR) { 249 LOG(DEBUG) << "failed to read /sys/kernel/notes: " << result; 250 } 251 return result == ElfStatus::NO_ERROR; 252 } 253 254 bool GetModuleBuildId(const std::string& module_name, BuildId* build_id) { 255 std::string notefile = "/sys/module/" + module_name + "/notes/.note.gnu.build-id"; 256 return GetBuildIdFromNoteFile(notefile, build_id); 257 } 258 259 bool GetValidThreadsFromThreadString(const std::string& tid_str, std::set<pid_t>* tid_set) { 260 std::vector<std::string> strs = android::base::Split(tid_str, ","); 261 for (const auto& s : strs) { 262 int tid; 263 if (!android::base::ParseInt(s.c_str(), &tid, 0)) { 264 LOG(ERROR) << "Invalid tid '" << s << "'"; 265 return false; 266 } 267 if (!IsDir(android::base::StringPrintf("/proc/%d", tid))) { 268 LOG(ERROR) << "Non existing thread '" << tid << "'"; 269 return false; 270 } 271 tid_set->insert(tid); 272 } 273 return true; 274 } 275 276 /* 277 * perf event paranoia level: 278 * -1 - not paranoid at all 279 * 0 - disallow raw tracepoint access for unpriv 280 * 1 - disallow cpu events for unpriv 281 * 2 - disallow kernel profiling for unpriv 282 * 3 - disallow user profiling for unpriv 283 */ 284 static bool ReadPerfEventParanoid(int* value) { 285 std::string s; 286 if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid", &s)) { 287 PLOG(DEBUG) << "failed to read /proc/sys/kernel/perf_event_paranoid"; 288 return false; 289 } 290 s = android::base::Trim(s); 291 if (!android::base::ParseInt(s.c_str(), value)) { 292 PLOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_paranoid: " << s; 293 return false; 294 } 295 return true; 296 } 297 298 bool CanRecordRawData() { 299 if (IsRoot()) { 300 return true; 301 } 302 #if defined(__ANDROID__) 303 // Android R uses selinux to control perf_event_open. Whether raw data can be recorded is hard 304 // to check unless we really try it. And probably there is no need to record raw data in non-root 305 // users. 306 return false; 307 #else 308 int value; 309 return ReadPerfEventParanoid(&value) && value == -1; 310 #endif 311 } 312 313 static const char* GetLimitLevelDescription(int limit_level) { 314 switch (limit_level) { 315 case -1: return "unlimited"; 316 case 0: return "disallowing raw tracepoint access for unpriv"; 317 case 1: return "disallowing cpu events for unpriv"; 318 case 2: return "disallowing kernel profiling for unpriv"; 319 case 3: return "disallowing user profiling for unpriv"; 320 default: return "unknown level"; 321 } 322 } 323 324 bool CheckPerfEventLimit() { 325 // Root is not limited by /proc/sys/kernel/perf_event_paranoid. However, the monitored threads 326 // may create child processes not running as root. To make sure the child processes have 327 // enough permission to create inherited tracepoint events, write -1 to perf_event_paranoid. 328 // See http://b/62230699. 329 if (IsRoot()) { 330 return android::base::WriteStringToFile("-1", "/proc/sys/kernel/perf_event_paranoid"); 331 } 332 int limit_level; 333 bool can_read_paranoid = ReadPerfEventParanoid(&limit_level); 334 if (can_read_paranoid && limit_level <= 1) { 335 return true; 336 } 337 #if defined(__ANDROID__) 338 const std::string prop_name = "security.perf_harden"; 339 std::string prop_value = android::base::GetProperty(prop_name, ""); 340 if (prop_value.empty()) { 341 // can't do anything if there is no such property. 342 return true; 343 } 344 if (prop_value == "0") { 345 return true; 346 } 347 // Try to enable perf_event_paranoid by setprop security.perf_harden=0. 348 if (android::base::SetProperty(prop_name, "0")) { 349 sleep(1); 350 if (can_read_paranoid && ReadPerfEventParanoid(&limit_level) && limit_level <= 1) { 351 return true; 352 } 353 if (android::base::GetProperty(prop_name, "") == "0") { 354 return true; 355 } 356 } 357 if (can_read_paranoid) { 358 LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level 359 << ", " << GetLimitLevelDescription(limit_level) << "."; 360 } 361 LOG(WARNING) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling."; 362 return false; 363 #else 364 if (can_read_paranoid) { 365 LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level 366 << ", " << GetLimitLevelDescription(limit_level) << "."; 367 return false; 368 } 369 #endif 370 return true; 371 } 372 373 #if defined(__ANDROID__) 374 static bool SetProperty(const char* prop_name, uint64_t value) { 375 if (!android::base::SetProperty(prop_name, std::to_string(value))) { 376 LOG(ERROR) << "Failed to SetProperty " << prop_name << " to " << value; 377 return false; 378 } 379 return true; 380 } 381 382 bool SetPerfEventLimits(uint64_t sample_freq, size_t cpu_percent, uint64_t mlock_kb) { 383 if (!SetProperty("debug.perf_event_max_sample_rate", sample_freq) || 384 !SetProperty("debug.perf_cpu_time_max_percent", cpu_percent) || 385 !SetProperty("debug.perf_event_mlock_kb", mlock_kb) || 386 !SetProperty("security.perf_harden", 0)) { 387 return false; 388 } 389 // Wait for init process to change perf event limits based on properties. 390 const size_t max_wait_us = 3 * 1000000; 391 int finish_mask = 0; 392 for (size_t i = 0; i < max_wait_us && finish_mask != 7; ++i) { 393 usleep(1); // Wait 1us to avoid busy loop. 394 if ((finish_mask & 1) == 0) { 395 uint64_t freq; 396 if (!GetMaxSampleFrequency(&freq) || freq == sample_freq) { 397 finish_mask |= 1; 398 } 399 } 400 if ((finish_mask & 2) == 0) { 401 size_t percent; 402 if (!GetCpuTimeMaxPercent(&percent) || percent == cpu_percent) { 403 finish_mask |= 2; 404 } 405 } 406 if ((finish_mask & 4) == 0) { 407 uint64_t kb; 408 if (!GetPerfEventMlockKb(&kb) || kb == mlock_kb) { 409 finish_mask |= 4; 410 } 411 } 412 } 413 if (finish_mask != 7) { 414 LOG(WARNING) << "Wait setting perf event limits timeout"; 415 } 416 return true; 417 } 418 #else // !defined(__ANDROID__) 419 bool SetPerfEventLimits(uint64_t, size_t, uint64_t) { 420 return true; 421 } 422 #endif 423 424 template <typename T> 425 static bool ReadUintFromProcFile(const std::string& path, T* value) { 426 std::string s; 427 if (!android::base::ReadFileToString(path, &s)) { 428 PLOG(DEBUG) << "failed to read " << path; 429 return false; 430 } 431 s = android::base::Trim(s); 432 if (!android::base::ParseUint(s.c_str(), value)) { 433 LOG(ERROR) << "failed to parse " << path << ": " << s; 434 return false; 435 } 436 return true; 437 } 438 439 template <typename T> 440 static bool WriteUintToProcFile(const std::string& path, T value) { 441 if (IsRoot()) { 442 return android::base::WriteStringToFile(std::to_string(value), path); 443 } 444 return false; 445 } 446 447 bool GetMaxSampleFrequency(uint64_t* max_sample_freq) { 448 return ReadUintFromProcFile("/proc/sys/kernel/perf_event_max_sample_rate", max_sample_freq); 449 } 450 451 bool SetMaxSampleFrequency(uint64_t max_sample_freq) { 452 return WriteUintToProcFile("/proc/sys/kernel/perf_event_max_sample_rate", max_sample_freq); 453 } 454 455 bool GetCpuTimeMaxPercent(size_t* percent) { 456 return ReadUintFromProcFile("/proc/sys/kernel/perf_cpu_time_max_percent", percent); 457 } 458 459 bool SetCpuTimeMaxPercent(size_t percent) { 460 return WriteUintToProcFile("/proc/sys/kernel/perf_cpu_time_max_percent", percent); 461 } 462 463 bool GetPerfEventMlockKb(uint64_t* mlock_kb) { 464 return ReadUintFromProcFile("/proc/sys/kernel/perf_event_mlock_kb", mlock_kb); 465 } 466 467 bool SetPerfEventMlockKb(uint64_t mlock_kb) { 468 return WriteUintToProcFile("/proc/sys/kernel/perf_event_mlock_kb", mlock_kb); 469 } 470 471 bool CheckKernelSymbolAddresses() { 472 const std::string kptr_restrict_file = "/proc/sys/kernel/kptr_restrict"; 473 std::string s; 474 if (!android::base::ReadFileToString(kptr_restrict_file, &s)) { 475 PLOG(DEBUG) << "failed to read " << kptr_restrict_file; 476 return false; 477 } 478 s = android::base::Trim(s); 479 int value; 480 if (!android::base::ParseInt(s.c_str(), &value)) { 481 LOG(ERROR) << "failed to parse " << kptr_restrict_file << ": " << s; 482 return false; 483 } 484 // Accessible to everyone? 485 if (value == 0) { 486 return true; 487 } 488 // Accessible to root? 489 if (value == 1 && IsRoot()) { 490 return true; 491 } 492 // Can we make it accessible to us? 493 if (IsRoot() && android::base::WriteStringToFile("1", kptr_restrict_file)) { 494 return true; 495 } 496 LOG(WARNING) << "Access to kernel symbol addresses is restricted. If " 497 << "possible, please do `echo 0 >/proc/sys/kernel/kptr_restrict` " 498 << "to fix this."; 499 return false; 500 } 501 502 ArchType GetMachineArch() { 503 utsname uname_buf; 504 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) { 505 PLOG(WARNING) << "uname() failed"; 506 return GetBuildArch(); 507 } 508 ArchType arch = GetArchType(uname_buf.machine); 509 if (arch != ARCH_UNSUPPORTED) { 510 return arch; 511 } 512 return GetBuildArch(); 513 } 514 515 void PrepareVdsoFile() { 516 // vdso is an elf file in memory loaded in each process's user space by the kernel. To read 517 // symbols from it and unwind through it, we need to dump it into a file in storage. 518 // It doesn't affect much when failed to prepare vdso file, so there is no need to return values. 519 std::vector<ThreadMmap> thread_mmaps; 520 if (!GetThreadMmapsInProcess(getpid(), &thread_mmaps)) { 521 return; 522 } 523 const ThreadMmap* vdso_map = nullptr; 524 for (const auto& map : thread_mmaps) { 525 if (map.name == "[vdso]") { 526 vdso_map = ↦ 527 break; 528 } 529 } 530 if (vdso_map == nullptr) { 531 return; 532 } 533 std::string s(vdso_map->len, '\0'); 534 memcpy(&s[0], reinterpret_cast<void*>(static_cast<uintptr_t>(vdso_map->start_addr)), 535 vdso_map->len); 536 std::unique_ptr<TemporaryFile> tmpfile = ScopedTempFiles::CreateTempFile(); 537 if (!android::base::WriteStringToFd(s, tmpfile->fd)) { 538 return; 539 } 540 Dso::SetVdsoFile(tmpfile->path, sizeof(size_t) == sizeof(uint64_t)); 541 } 542 543 static bool HasOpenedAppApkFile(int pid) { 544 std::string fd_path = "/proc/" + std::to_string(pid) + "/fd/"; 545 std::vector<std::string> files = GetEntriesInDir(fd_path); 546 for (const auto& file : files) { 547 std::string real_path; 548 if (!android::base::Readlink(fd_path + file, &real_path)) { 549 continue; 550 } 551 if (real_path.find("app") != std::string::npos && real_path.find(".apk") != std::string::npos) { 552 return true; 553 } 554 } 555 return false; 556 } 557 558 std::set<pid_t> WaitForAppProcesses(const std::string& package_name) { 559 std::set<pid_t> result; 560 size_t loop_count = 0; 561 while (true) { 562 std::vector<pid_t> pids = GetAllProcesses(); 563 for (pid_t pid : pids) { 564 std::string cmdline; 565 if (!android::base::ReadFileToString("/proc/" + std::to_string(pid) + "/cmdline", &cmdline)) { 566 // Maybe we don't have permission to read it. 567 continue; 568 } 569 std::string process_name = android::base::Basename(cmdline); 570 // The app may have multiple processes, with process name like 571 // com.google.android.googlequicksearchbox:search. 572 size_t split_pos = process_name.find(':'); 573 if (split_pos != std::string::npos) { 574 process_name = process_name.substr(0, split_pos); 575 } 576 if (process_name != package_name) { 577 continue; 578 } 579 // If a debuggable app with wrap.sh runs on Android O, the app will be started with 580 // logwrapper as below: 581 // 1. Zygote forks a child process, rename it to package_name. 582 // 2. The child process execute sh, which starts a child process running 583 // /system/bin/logwrapper. 584 // 3. logwrapper starts a child process running sh, which interprets wrap.sh. 585 // 4. wrap.sh starts a child process running the app. 586 // The problem here is we want to profile the process started in step 4, but sometimes we 587 // run into the process started in step 1. To solve it, we can check if the process has 588 // opened an apk file in some app dirs. 589 if (!HasOpenedAppApkFile(pid)) { 590 continue; 591 } 592 if (loop_count > 0u) { 593 LOG(INFO) << "Got process " << pid << " for package " << package_name; 594 } 595 result.insert(pid); 596 } 597 if (!result.empty()) { 598 return result; 599 } 600 if (++loop_count == 1u) { 601 LOG(INFO) << "Waiting for process of app " << package_name; 602 } 603 usleep(1000); 604 } 605 } 606 607 bool IsAppDebuggable(const std::string& package_name) { 608 return Workload::RunCmd({"run-as", package_name, "echo", ">/dev/null", "2>/dev/null"}, false); 609 } 610 611 namespace { 612 613 class InAppRunner { 614 public: 615 InAppRunner(const std::string& package_name) : package_name_(package_name) {} 616 virtual ~InAppRunner() { 617 if (!tracepoint_file_.empty()) { 618 unlink(tracepoint_file_.c_str()); 619 } 620 } 621 virtual bool Prepare() = 0; 622 bool RunCmdInApp(const std::string& cmd, const std::vector<std::string>& args, 623 size_t workload_args_size, const std::string& output_filepath, 624 bool need_tracepoint_events); 625 protected: 626 virtual std::vector<std::string> GetPrefixArgs(const std::string& cmd) = 0; 627 628 const std::string package_name_; 629 std::string tracepoint_file_; 630 }; 631 632 bool InAppRunner::RunCmdInApp(const std::string& cmd, const std::vector<std::string>& cmd_args, 633 size_t workload_args_size, const std::string& output_filepath, 634 bool need_tracepoint_events) { 635 // 1. Build cmd args running in app's context. 636 std::vector<std::string> args = GetPrefixArgs(cmd); 637 args.insert(args.end(), {"--in-app", "--log", GetLogSeverityName()}); 638 if (log_to_android_buffer) { 639 args.emplace_back("--log-to-android-buffer"); 640 } 641 if (need_tracepoint_events) { 642 // Since we can't read tracepoint events from tracefs in app's context, we need to prepare 643 // them in tracepoint_file in shell's context, and pass the path of tracepoint_file to the 644 // child process using --tracepoint-events option. 645 const std::string tracepoint_file = "/data/local/tmp/tracepoint_events"; 646 if (!android::base::WriteStringToFile(GetTracepointEvents(), tracepoint_file)) { 647 PLOG(ERROR) << "Failed to store tracepoint events"; 648 return false; 649 } 650 tracepoint_file_ = tracepoint_file; 651 args.insert(args.end(), {"--tracepoint-events", tracepoint_file_}); 652 } 653 654 android::base::unique_fd out_fd; 655 if (!output_filepath.empty()) { 656 // A process running in app's context can't open a file outside it's data directory to write. 657 // So pass it a file descriptor to write. 658 out_fd = FileHelper::OpenWriteOnly(output_filepath); 659 if (out_fd == -1) { 660 PLOG(ERROR) << "Failed to open " << output_filepath; 661 return false; 662 } 663 args.insert(args.end(), {"--out-fd", std::to_string(int(out_fd))}); 664 } 665 666 // We can't send signal to a process running in app's context. So use a pipe file to send stop 667 // signal. 668 android::base::unique_fd stop_signal_rfd; 669 android::base::unique_fd stop_signal_wfd; 670 if (!android::base::Pipe(&stop_signal_rfd, &stop_signal_wfd, 0)) { 671 PLOG(ERROR) << "pipe"; 672 return false; 673 } 674 args.insert(args.end(), {"--stop-signal-fd", std::to_string(int(stop_signal_rfd))}); 675 676 for (size_t i = 0; i < cmd_args.size(); ++i) { 677 if (i < cmd_args.size() - workload_args_size) { 678 // Omit "-o output_file". It is replaced by "--out-fd fd". 679 if (cmd_args[i] == "-o" || cmd_args[i] == "--app") { 680 i++; 681 continue; 682 } 683 } 684 args.push_back(cmd_args[i]); 685 } 686 char* argv[args.size() + 1]; 687 for (size_t i = 0; i < args.size(); ++i) { 688 argv[i] = &args[i][0]; 689 } 690 argv[args.size()] = nullptr; 691 692 // 2. Run child process in app's context. 693 auto ChildProcFn = [&]() { 694 stop_signal_wfd.reset(); 695 execvp(argv[0], argv); 696 exit(1); 697 }; 698 std::unique_ptr<Workload> workload = Workload::CreateWorkload(ChildProcFn); 699 if (!workload) { 700 return false; 701 } 702 stop_signal_rfd.reset(); 703 704 // Wait on signals. 705 IOEventLoop loop; 706 bool need_to_stop_child = false; 707 std::vector<int> stop_signals = {SIGINT, SIGTERM}; 708 if (!SignalIsIgnored(SIGHUP)) { 709 stop_signals.push_back(SIGHUP); 710 } 711 if (!loop.AddSignalEvents(stop_signals, 712 [&]() { need_to_stop_child = true; return loop.ExitLoop(); })) { 713 return false; 714 } 715 if (!loop.AddSignalEvent(SIGCHLD, [&]() { return loop.ExitLoop(); })) { 716 return false; 717 } 718 719 if (!workload->Start()) { 720 return false; 721 } 722 if (!loop.RunLoop()) { 723 return false; 724 } 725 if (need_to_stop_child) { 726 stop_signal_wfd.reset(); 727 } 728 int exit_code; 729 if (!workload->WaitChildProcess(&exit_code) || exit_code != 0) { 730 return false; 731 } 732 return true; 733 } 734 735 class RunAs : public InAppRunner { 736 public: 737 RunAs(const std::string& package_name) : InAppRunner(package_name) {} 738 virtual ~RunAs() { 739 if (simpleperf_copied_in_app_) { 740 Workload::RunCmd({"run-as", package_name_, "rm", "-rf", "simpleperf"}); 741 } 742 } 743 bool Prepare() override; 744 745 protected: 746 std::vector<std::string> GetPrefixArgs(const std::string& cmd) { 747 return {"run-as", package_name_, 748 simpleperf_copied_in_app_ ? "./simpleperf" : simpleperf_path_, cmd, 749 "--app", package_name_}; 750 } 751 752 bool simpleperf_copied_in_app_ = false; 753 std::string simpleperf_path_; 754 }; 755 756 bool RunAs::Prepare() { 757 // Test if run-as can access the package. 758 if (!IsAppDebuggable(package_name_)) { 759 return false; 760 } 761 // run-as can't run /data/local/tmp/simpleperf directly. So copy simpleperf binary if needed. 762 if (!android::base::Readlink("/proc/self/exe", &simpleperf_path_)) { 763 PLOG(ERROR) << "ReadLink failed"; 764 return false; 765 } 766 if (simpleperf_path_.find("CtsSimpleperfTest") != std::string::npos) { 767 simpleperf_path_ = "/system/bin/simpleperf"; 768 return true; 769 } 770 if (android::base::StartsWith(simpleperf_path_, "/system")) { 771 return true; 772 } 773 if (!Workload::RunCmd({"run-as", package_name_, "cp", simpleperf_path_, "simpleperf"})) { 774 return false; 775 } 776 simpleperf_copied_in_app_ = true; 777 return true; 778 } 779 780 class SimpleperfAppRunner : public InAppRunner { 781 public: 782 SimpleperfAppRunner(const std::string& package_name) : InAppRunner(package_name) {} 783 bool Prepare() override { 784 return GetAndroidVersion() >= kAndroidVersionP + 1; 785 } 786 787 protected: 788 std::vector<std::string> GetPrefixArgs(const std::string& cmd) { 789 return {"simpleperf_app_runner", package_name_, cmd}; 790 } 791 }; 792 793 } // namespace 794 795 static bool allow_run_as = true; 796 static bool allow_simpleperf_app_runner = true; 797 798 void SetRunInAppToolForTesting(bool run_as, bool simpleperf_app_runner) { 799 allow_run_as = run_as; 800 allow_simpleperf_app_runner = simpleperf_app_runner; 801 } 802 803 bool RunInAppContext(const std::string& app_package_name, const std::string& cmd, 804 const std::vector<std::string>& args, size_t workload_args_size, 805 const std::string& output_filepath, bool need_tracepoint_events) { 806 std::unique_ptr<InAppRunner> in_app_runner; 807 if (allow_run_as) { 808 in_app_runner.reset(new RunAs(app_package_name)); 809 if (!in_app_runner->Prepare()) { 810 in_app_runner = nullptr; 811 } 812 } 813 if (!in_app_runner && allow_simpleperf_app_runner) { 814 in_app_runner.reset(new SimpleperfAppRunner(app_package_name)); 815 if (!in_app_runner->Prepare()) { 816 in_app_runner = nullptr; 817 } 818 } 819 if (!in_app_runner) { 820 LOG(ERROR) << "Package " << app_package_name 821 << " doesn't exist or isn't debuggable/profileable."; 822 return false; 823 } 824 return in_app_runner->RunCmdInApp(cmd, args, workload_args_size, output_filepath, 825 need_tracepoint_events); 826 } 827 828 void AllowMoreOpenedFiles() { 829 // On Android <= O, the hard limit is 4096, and the soft limit is 1024. 830 // On Android >= P, both the hard and soft limit are 32768. 831 rlimit limit; 832 if (getrlimit(RLIMIT_NOFILE, &limit) == 0) { 833 limit.rlim_cur = limit.rlim_max; 834 setrlimit(RLIMIT_NOFILE, &limit); 835 } 836 } 837 838 std::string ScopedTempFiles::tmp_dir_; 839 std::vector<std::string> ScopedTempFiles::files_to_delete_; 840 841 ScopedTempFiles::ScopedTempFiles(const std::string& tmp_dir) { 842 CHECK(tmp_dir_.empty()); // No other ScopedTempFiles. 843 tmp_dir_ = tmp_dir; 844 } 845 846 ScopedTempFiles::~ScopedTempFiles() { 847 tmp_dir_.clear(); 848 for (auto& file : files_to_delete_) { 849 unlink(file.c_str()); 850 } 851 files_to_delete_.clear(); 852 } 853 854 std::unique_ptr<TemporaryFile> ScopedTempFiles::CreateTempFile(bool delete_in_destructor) { 855 CHECK(!tmp_dir_.empty()); 856 std::unique_ptr<TemporaryFile> tmp_file(new TemporaryFile(tmp_dir_)); 857 CHECK_NE(tmp_file->fd, -1); 858 if (delete_in_destructor) { 859 tmp_file->DoNotRemove(); 860 files_to_delete_.push_back(tmp_file->path); 861 } 862 return tmp_file; 863 } 864 865 bool SignalIsIgnored(int signo) { 866 struct sigaction act; 867 if (sigaction(signo, nullptr, &act) != 0) { 868 PLOG(FATAL) << "failed to query signal handler for signal " << signo; 869 } 870 871 if ((act.sa_flags & SA_SIGINFO)) { 872 return false; 873 } 874 875 return act.sa_handler == SIG_IGN; 876 } 877 878 int GetAndroidVersion() { 879 #if defined(__ANDROID__) 880 static int android_version = -1; 881 if (android_version == -1) { 882 android_version = 0; 883 std::string s = android::base::GetProperty("ro.build.version.release", ""); 884 // The release string can be a list of numbers (like 8.1.0), a character (like Q) 885 // or many characters (like OMR1). 886 if (!s.empty()) { 887 // Each Android version has a version number: L is 5, M is 6, N is 7, O is 8, etc. 888 if (s[0] >= 'A' && s[0] <= 'Z') { 889 android_version = s[0] - 'P' + kAndroidVersionP; 890 } else if (isdigit(s[0])) { 891 sscanf(s.c_str(), "%d", &android_version); 892 } 893 } 894 } 895 return android_version; 896 #else // defined(__ANDROID__) 897 return 0; 898 #endif 899 } 900 901 std::string GetHardwareFromCpuInfo(const std::string& cpu_info) { 902 for (auto& line : android::base::Split(cpu_info, "\n")) { 903 size_t pos = line.find(':'); 904 if (pos != std::string::npos) { 905 std::string key = android::base::Trim(line.substr(0, pos)); 906 if (key == "Hardware") { 907 return android::base::Trim(line.substr(pos + 1)); 908 } 909 } 910 } 911 return ""; 912 } 913 914 bool MappedFileOnlyExistInMemory(const char* filename) { 915 // Mapped files only existing in memory: 916 // empty name 917 // [anon:???] 918 // [stack] 919 // /dev/* 920 // //anon: generated by kernel/events/core.c. 921 // /memfd: created by memfd_create. 922 return filename[0] == '\0' || 923 (filename[0] == '[' && strcmp(filename, "[vdso]") != 0) || 924 strncmp(filename, "//", 2) == 0 || 925 strncmp(filename, "/dev/", 5) == 0 || 926 strncmp(filename, "/memfd:", 7) == 0; 927 } 928 929 std::string GetCompleteProcessName(pid_t pid) { 930 std::string s; 931 if (!android::base::ReadFileToString(android::base::StringPrintf("/proc/%d/cmdline", pid), &s)) { 932 s.clear(); 933 } 934 for (size_t i = 0; i < s.size(); ++i) { 935 // /proc/pid/cmdline uses 0 to separate arguments. 936 if (isspace(s[i]) || s[i] == 0) { 937 s.resize(i); 938 break; 939 } 940 } 941 return s; 942 } 943 944 const char* GetTraceFsDir() { 945 static const char* tracefs_dirs[] = { 946 "/sys/kernel/debug/tracing", "/sys/kernel/tracing" 947 }; 948 for (const char* path : tracefs_dirs) { 949 if (IsDir(path)) { 950 return path; 951 } 952 } 953 return nullptr; 954 } 955