blob: ed50cd51365d4c70165d9ab16710717896ba35dd [file] [log] [blame]
Yabin Cui323e9452015-04-20 18:07:17 -07001/*
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
Yabin Cui7d59bb42015-05-04 20:27:57 -070019#include <inttypes.h>
Yabin Cuia80f8f72017-07-12 15:50:20 -070020#include <signal.h>
Yabin Cui7d59bb42015-05-04 20:27:57 -070021#include <stdio.h>
Yabin Cui323e9452015-04-20 18:07:17 -070022#include <stdlib.h>
Yabin Cui2db05b42018-07-16 14:04:49 -070023#include <string.h>
Yabin Cui7c5fe4e2017-12-05 17:44:05 -080024#include <sys/resource.h>
Yi Kongd5f247b2024-07-08 16:59:51 +090025#include <sys/sysinfo.h>
Yabin Cui0a7a06d2016-10-28 13:27:41 -070026#include <sys/utsname.h>
Yabin Cui554f3bb2021-05-05 13:34:59 -070027#include <unistd.h>
Yabin Cuic8485602015-08-20 15:04:39 -070028
29#include <limits>
Yabin Cui8974bb02023-10-16 10:42:16 -070030#include <optional>
Yabin Cuicb4c17e2015-10-26 16:15:29 -070031#include <set>
Yabin Cui7d59bb42015-05-04 20:27:57 -070032#include <unordered_map>
Yabin Cui323e9452015-04-20 18:07:17 -070033#include <vector>
34
Elliott Hughes66dd09e2015-12-04 14:00:57 -080035#include <android-base/file.h>
36#include <android-base/logging.h>
Yabin Cui569f64a2016-02-05 17:32:08 -080037#include <android-base/parseint.h>
Elliott Hughes66dd09e2015-12-04 14:00:57 -080038#include <android-base/stringprintf.h>
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020039#include <android-base/strings.h>
Yabin Cui7e5aa132016-11-16 22:47:53 +000040#include <procinfo/process.h>
Yabin Cui4f79dc82018-05-09 18:25:25 -070041#include <procinfo/process_map.h>
Yabin Cui323e9452015-04-20 18:07:17 -070042
Yabin Cuiebf79f32016-06-01 15:39:39 -070043#if defined(__ANDROID__)
Yabin Cui80a1e122017-08-11 14:52:51 -070044#include <android-base/properties.h>
Yabin Cui3485af92021-10-27 10:50:53 -070045#include <cutils/android_filesystem_config.h>
Yabin Cuiebf79f32016-06-01 15:39:39 -070046#endif
47
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +020048#include "IOEventLoop.h"
Yabin Cuia556c562020-02-14 16:50:10 -080049#include "command.h"
Yabin Cuif8974522017-07-17 14:36:37 -070050#include "event_type.h"
Thiébaud Weksteene7e750e2020-11-19 15:07:46 +010051#include "kallsyms.h"
Yabin Cui8f622512015-05-05 19:58:07 -070052#include "read_elf.h"
Yabin Cui003b2452016-09-29 15:32:45 -070053#include "thread_tree.h"
Yabin Cui323e9452015-04-20 18:07:17 -070054#include "utils.h"
Yabin Cuia80f8f72017-07-12 15:50:20 -070055#include "workload.h"
Yabin Cui323e9452015-04-20 18:07:17 -070056
Yabin Cuifaa7b922021-01-11 17:35:57 -080057namespace simpleperf {
Yabin Cuia556c562020-02-14 16:50:10 -080058
Yabin Cui323e9452015-04-20 18:07:17 -070059std::vector<int> GetOnlineCpus() {
60 std::vector<int> result;
Yabin Cui40eef9e2021-04-13 13:08:31 -070061 LineReader reader("/sys/devices/system/cpu/online");
62 if (!reader.Ok()) {
Yabin Cui323e9452015-04-20 18:07:17 -070063 PLOG(ERROR) << "can't open online cpu information";
64 return result;
65 }
66
Yabin Cui40eef9e2021-04-13 13:08:31 -070067 std::string* line;
Yabin Cui323e9452015-04-20 18:07:17 -070068 if ((line = reader.ReadLine()) != nullptr) {
Yabin Cui40eef9e2021-04-13 13:08:31 -070069 if (auto cpus = GetCpusFromString(*line); cpus) {
Yabin Cuie3ca9982020-10-16 13:16:26 -070070 result.assign(cpus->begin(), cpus->end());
71 }
Yabin Cui323e9452015-04-20 18:07:17 -070072 }
73 CHECK(!result.empty()) << "can't get online cpu information";
74 return result;
75}
76
Yabin Cui7d59bb42015-05-04 20:27:57 -070077static void GetAllModuleFiles(const std::string& path,
78 std::unordered_map<std::string, std::string>* module_file_map) {
Yabin Cui2c928d62024-04-03 13:46:08 -070079 if (!IsDir(path)) {
80 return;
81 }
Yabin Cui07865862016-08-22 13:39:19 -070082 for (const auto& name : GetEntriesInDir(path)) {
83 std::string entry_path = path + "/" + name;
84 if (IsRegularFile(entry_path) && android::base::EndsWith(name, ".ko")) {
Yabin Cui7d59bb42015-05-04 20:27:57 -070085 std::string module_name = name.substr(0, name.size() - 3);
86 std::replace(module_name.begin(), module_name.end(), '-', '_');
Yabin Cui07865862016-08-22 13:39:19 -070087 module_file_map->insert(std::make_pair(module_name, entry_path));
88 } else if (IsDir(entry_path)) {
89 GetAllModuleFiles(entry_path, module_file_map);
Yabin Cui7d59bb42015-05-04 20:27:57 -070090 }
91 }
Yabin Cui7d59bb42015-05-04 20:27:57 -070092}
93
Yabin Cui7134f382016-03-25 17:43:43 -070094static std::vector<KernelMmap> GetModulesInUse() {
Yabin Cuib068c102017-11-01 17:53:10 -070095 std::vector<KernelMmap> module_mmaps = GetLoadedModules();
96 if (module_mmaps.empty()) {
97 return std::vector<KernelMmap>();
98 }
99 std::unordered_map<std::string, std::string> module_file_map;
100#if defined(__ANDROID__)
Yabin Cui2c928d62024-04-03 13:46:08 -0700101 // On Android, kernel modules are stored in /system/lib/modules, /vendor/lib/modules,
102 // /odm/lib/modules.
103 // See https://source.android.com/docs/core/architecture/partitions/gki-partitions and
104 // https://source.android.com/docs/core/architecture/partitions/vendor-odm-dlkm-partition.
105 // They can also be stored in vendor_kernel_ramdisk.img, which isn't accessible from userspace.
106 // See https://source.android.com/docs/core/architecture/kernel/kernel-module-support.
107 for (const auto& path : {"/system/lib/modules", "/vendor/lib/modules", "/odm/lib/modules"}) {
Yabin Cuib068c102017-11-01 17:53:10 -0700108 GetAllModuleFiles(path, &module_file_map);
109 }
110#else
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700111 utsname uname_buf;
112 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
113 PLOG(ERROR) << "uname() failed";
114 return std::vector<KernelMmap>();
115 }
116 std::string linux_version = uname_buf.release;
Yabin Cui7d59bb42015-05-04 20:27:57 -0700117 std::string module_dirpath = "/lib/modules/" + linux_version + "/kernel";
Yabin Cui7d59bb42015-05-04 20:27:57 -0700118 GetAllModuleFiles(module_dirpath, &module_file_map);
Yabin Cuib068c102017-11-01 17:53:10 -0700119#endif
Yabin Cui7d59bb42015-05-04 20:27:57 -0700120 for (auto& module : module_mmaps) {
121 auto it = module_file_map.find(module.name);
122 if (it != module_file_map.end()) {
123 module.filepath = it->second;
124 }
125 }
126 return module_mmaps;
127}
128
Yabin Cui7134f382016-03-25 17:43:43 -0700129void GetKernelAndModuleMmaps(KernelMmap* kernel_mmap, std::vector<KernelMmap>* module_mmaps) {
Yabin Cui7d59bb42015-05-04 20:27:57 -0700130 kernel_mmap->name = DEFAULT_KERNEL_MMAP_NAME;
Yabin Cui7134f382016-03-25 17:43:43 -0700131 kernel_mmap->start_addr = 0;
Yabin Cuib068c102017-11-01 17:53:10 -0700132 kernel_mmap->len = std::numeric_limits<uint64_t>::max();
Yabin Cuic13ff892020-11-10 13:11:01 -0800133 if (uint64_t kstart_addr = GetKernelStartAddress(); kstart_addr != 0) {
134 kernel_mmap->name = std::string(DEFAULT_KERNEL_MMAP_NAME) + "_stext";
135 kernel_mmap->start_addr = kstart_addr;
136 kernel_mmap->len = std::numeric_limits<uint64_t>::max() - kstart_addr;
137 }
Yabin Cui7134f382016-03-25 17:43:43 -0700138 kernel_mmap->filepath = kernel_mmap->name;
Yabin Cui7d59bb42015-05-04 20:27:57 -0700139 *module_mmaps = GetModulesInUse();
Yabin Cui7134f382016-03-25 17:43:43 -0700140 for (auto& map : *module_mmaps) {
141 if (map.filepath.empty()) {
142 map.filepath = "[" + map.name + "]";
143 }
144 }
Yabin Cui7d59bb42015-05-04 20:27:57 -0700145}
146
Yabin Cuidc2708c2020-01-10 15:33:11 -0800147bool ReadThreadNameAndPid(pid_t tid, std::string* comm, pid_t* pid) {
Yabin Cui7e5aa132016-11-16 22:47:53 +0000148 android::procinfo::ProcessInfo procinfo;
149 if (!android::procinfo::GetProcessInfo(tid, &procinfo)) {
Yabin Cui7d59bb42015-05-04 20:27:57 -0700150 return false;
151 }
Yabin Cui7e5aa132016-11-16 22:47:53 +0000152 if (comm != nullptr) {
153 *comm = procinfo.name;
Yabin Cui7d59bb42015-05-04 20:27:57 -0700154 }
Yabin Cui7e5aa132016-11-16 22:47:53 +0000155 if (pid != nullptr) {
156 *pid = procinfo.pid;
157 }
158 return true;
Yabin Cui7d59bb42015-05-04 20:27:57 -0700159}
160
Yabin Cuibc2a1022016-08-29 12:33:17 -0700161std::vector<pid_t> GetThreadsInProcess(pid_t pid) {
Yabin Cuib032de72015-06-17 21:15:09 -0700162 std::vector<pid_t> result;
Yabin Cui7e5aa132016-11-16 22:47:53 +0000163 android::procinfo::GetProcessTids(pid, &result);
Yabin Cuib032de72015-06-17 21:15:09 -0700164 return result;
165}
166
Yabin Cui5f43fc42016-12-13 13:47:49 -0800167bool IsThreadAlive(pid_t tid) {
168 return IsDir(android::base::StringPrintf("/proc/%d", tid));
169}
170
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700171bool GetProcessForThread(pid_t tid, pid_t* pid) {
172 return ReadThreadNameAndPid(tid, nullptr, pid);
Yabin Cui7d59bb42015-05-04 20:27:57 -0700173}
174
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700175bool GetThreadName(pid_t tid, std::string* name) {
176 return ReadThreadNameAndPid(tid, name, nullptr);
177}
178
179std::vector<pid_t> GetAllProcesses() {
180 std::vector<pid_t> result;
181 std::vector<std::string> entries = GetEntriesInDir("/proc");
182 for (const auto& entry : entries) {
183 pid_t pid;
184 if (!android::base::ParseInt(entry.c_str(), &pid, 0)) {
Yabin Cui7d59bb42015-05-04 20:27:57 -0700185 continue;
186 }
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700187 result.push_back(pid);
Yabin Cui7d59bb42015-05-04 20:27:57 -0700188 }
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700189 return result;
Yabin Cui7d59bb42015-05-04 20:27:57 -0700190}
191
192bool GetThreadMmapsInProcess(pid_t pid, std::vector<ThreadMmap>* thread_mmaps) {
Yabin Cui7d59bb42015-05-04 20:27:57 -0700193 thread_mmaps->clear();
Yabin Cui58740ff2021-03-23 13:34:51 -0700194 return android::procinfo::ReadProcessMaps(pid, [&](const android::procinfo::MapInfo& mapinfo) {
195 thread_mmaps->emplace_back(mapinfo.start, mapinfo.end - mapinfo.start, mapinfo.pgoff,
196 mapinfo.name.c_str(), mapinfo.flags);
197 });
Yabin Cui7d59bb42015-05-04 20:27:57 -0700198}
Yabin Cui8f622512015-05-05 19:58:07 -0700199
200bool GetKernelBuildId(BuildId* build_id) {
Yabin Cuidec43c12016-07-29 16:40:40 -0700201 ElfStatus result = GetBuildIdFromNoteFile("/sys/kernel/notes", build_id);
202 if (result != ElfStatus::NO_ERROR) {
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700203 LOG(DEBUG) << "failed to read /sys/kernel/notes: " << result;
Yabin Cuidec43c12016-07-29 16:40:40 -0700204 }
205 return result == ElfStatus::NO_ERROR;
Yabin Cui8f622512015-05-05 19:58:07 -0700206}
207
Yabin Cuiea105c82020-07-22 13:01:31 -0700208bool GetModuleBuildId(const std::string& module_name, BuildId* build_id,
209 const std::string& sysfs_dir) {
210 std::string notefile = sysfs_dir + "/module/" + module_name + "/notes/.note.gnu.build-id";
211 return GetBuildIdFromNoteFile(notefile, build_id) == ElfStatus::NO_ERROR;
Yabin Cui8f622512015-05-05 19:58:07 -0700212}
Yabin Cuib032de72015-06-17 21:15:09 -0700213
Yabin Cuiebf79f32016-06-01 15:39:39 -0700214/*
Yabin Cui17cffbb2020-07-28 17:11:39 -0700215 * perf event allow level:
216 * -1 - everything allowed
Yabin Cuiebf79f32016-06-01 15:39:39 -0700217 * 0 - disallow raw tracepoint access for unpriv
218 * 1 - disallow cpu events for unpriv
219 * 2 - disallow kernel profiling for unpriv
220 * 3 - disallow user profiling for unpriv
221 */
Yabin Cui17cffbb2020-07-28 17:11:39 -0700222static const char* perf_event_allow_path = "/proc/sys/kernel/perf_event_paranoid";
223
Yabin Cui8974bb02023-10-16 10:42:16 -0700224static std::optional<int> ReadPerfEventAllowStatus() {
Yabin Cuiebf79f32016-06-01 15:39:39 -0700225 std::string s;
Yabin Cui17cffbb2020-07-28 17:11:39 -0700226 if (!android::base::ReadFileToString(perf_event_allow_path, &s)) {
227 PLOG(DEBUG) << "failed to read " << perf_event_allow_path;
Yabin Cui8974bb02023-10-16 10:42:16 -0700228 return std::nullopt;
Yabin Cuiebf79f32016-06-01 15:39:39 -0700229 }
230 s = android::base::Trim(s);
Yabin Cui8974bb02023-10-16 10:42:16 -0700231 int value;
232 if (!android::base::ParseInt(s.c_str(), &value)) {
Yabin Cui17cffbb2020-07-28 17:11:39 -0700233 PLOG(ERROR) << "failed to parse " << perf_event_allow_path << ": " << s;
Yabin Cui8974bb02023-10-16 10:42:16 -0700234 return std::nullopt;
Yabin Cuiebf79f32016-06-01 15:39:39 -0700235 }
Yabin Cui8974bb02023-10-16 10:42:16 -0700236 return value;
Yabin Cuiebf79f32016-06-01 15:39:39 -0700237}
238
Yabin Cuif8974522017-07-17 14:36:37 -0700239bool CanRecordRawData() {
Yabin Cuic3a9bf12020-02-27 16:55:38 -0800240 if (IsRoot()) {
241 return true;
Yabin Cuia5697762020-01-13 14:48:01 -0800242 }
Yabin Cuic3a9bf12020-02-27 16:55:38 -0800243#if defined(__ANDROID__)
Yabin Cuic98cb112020-04-06 16:26:41 -0700244 // Android R uses selinux to control perf_event_open. Whether raw data can be recorded is hard
245 // to check unless we really try it. And probably there is no need to record raw data in non-root
246 // users.
247 return false;
248#else
Yabin Cui8974bb02023-10-16 10:42:16 -0700249 return ReadPerfEventAllowStatus() == -1;
Yabin Cuic3a9bf12020-02-27 16:55:38 -0800250#endif
Yabin Cuif8974522017-07-17 14:36:37 -0700251}
252
Yi Kongd5f247b2024-07-08 16:59:51 +0900253uint64_t GetMemorySize() {
254 struct sysinfo info;
255 sysinfo(&info);
256 return info.totalram;
Yabin Cuicfdc7832023-03-02 15:35:01 -0800257}
258
Yabin Cuiebf79f32016-06-01 15:39:39 -0700259static const char* GetLimitLevelDescription(int limit_level) {
260 switch (limit_level) {
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200261 case -1:
262 return "unlimited";
263 case 0:
264 return "disallowing raw tracepoint access for unpriv";
265 case 1:
266 return "disallowing cpu events for unpriv";
267 case 2:
268 return "disallowing kernel profiling for unpriv";
269 case 3:
270 return "disallowing user profiling for unpriv";
271 default:
272 return "unknown level";
Yabin Cuiebf79f32016-06-01 15:39:39 -0700273 }
274}
275
276bool CheckPerfEventLimit() {
Yabin Cui8974bb02023-10-16 10:42:16 -0700277 std::optional<int> old_level = ReadPerfEventAllowStatus();
278
Yabin Cui17cffbb2020-07-28 17:11:39 -0700279 // Root is not limited by perf_event_allow_path. However, the monitored threads
Yabin Cui1137a8c2017-06-01 13:23:29 -0700280 // may create child processes not running as root. To make sure the child processes have
Yabin Cui17cffbb2020-07-28 17:11:39 -0700281 // enough permission to create inherited tracepoint events, write -1 to perf_event_allow_path.
Yabin Cui1137a8c2017-06-01 13:23:29 -0700282 // See http://b/62230699.
Yabin Cui5edb7fc2018-08-29 14:54:19 -0700283 if (IsRoot()) {
Yabin Cui8974bb02023-10-16 10:42:16 -0700284 if (old_level == -1) {
285 return true;
286 }
Yabin Cuic765ccb2021-02-23 15:53:09 -0800287 if (android::base::WriteStringToFile("-1", perf_event_allow_path)) {
288 return true;
289 }
290 // On host, we may not be able to write to perf_event_allow_path (like when running in docker).
291#if defined(__ANDROID__)
292 PLOG(ERROR) << "failed to write -1 to " << perf_event_allow_path;
293 return false;
294#endif
Yabin Cui4f41df62016-06-01 17:29:06 -0700295 }
Yabin Cui8974bb02023-10-16 10:42:16 -0700296 if (old_level.has_value() && old_level <= 1) {
Yabin Cuiebf79f32016-06-01 15:39:39 -0700297 return true;
298 }
299#if defined(__ANDROID__)
Yabin Cui80a1e122017-08-11 14:52:51 -0700300 const std::string prop_name = "security.perf_harden";
301 std::string prop_value = android::base::GetProperty(prop_name, "");
302 if (prop_value.empty()) {
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700303 // can't do anything if there is no such property.
304 return true;
305 }
Yabin Cui80a1e122017-08-11 14:52:51 -0700306 if (prop_value == "0") {
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700307 return true;
308 }
Yabin Cui17cffbb2020-07-28 17:11:39 -0700309 // Try to enable perf events by setprop security.perf_harden=0.
Yabin Cui80a1e122017-08-11 14:52:51 -0700310 if (android::base::SetProperty(prop_name, "0")) {
Yabin Cuiebf79f32016-06-01 15:39:39 -0700311 sleep(1);
Yabin Cui8974bb02023-10-16 10:42:16 -0700312 // Check the result of setprop, by reading allow status or the property value.
313 if (auto level = ReadPerfEventAllowStatus(); level.has_value() && level <= 1) {
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700314 return true;
315 }
Yabin Cui80a1e122017-08-11 14:52:51 -0700316 if (android::base::GetProperty(prop_name, "") == "0") {
Yabin Cuiebf79f32016-06-01 15:39:39 -0700317 return true;
318 }
319 }
Yabin Cui8974bb02023-10-16 10:42:16 -0700320 if (old_level.has_value()) {
321 LOG(ERROR) << perf_event_allow_path << " is " << old_level.value() << ", "
322 << GetLimitLevelDescription(old_level.value()) << ".";
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700323 }
Yabin Cuic95e3472022-09-22 09:55:31 -0700324 LOG(ERROR) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling.";
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700325 return false;
Yabin Cuiebf79f32016-06-01 15:39:39 -0700326#else
Yabin Cui8974bb02023-10-16 10:42:16 -0700327 if (old_level.has_value()) {
328 LOG(ERROR) << perf_event_allow_path << " is " << old_level.value() << ", "
329 << GetLimitLevelDescription(old_level.value()) << ". Try using `echo -1 >"
Yabin Cuic95e3472022-09-22 09:55:31 -0700330 << perf_event_allow_path << "` to enable profiling.";
Yabin Cui0a7a06d2016-10-28 13:27:41 -0700331 return false;
332 }
Yabin Cuiebf79f32016-06-01 15:39:39 -0700333#endif
334 return true;
335}
Yabin Cuib8915492016-06-22 12:43:09 -0700336
Yabin Cui6e173a42018-08-13 15:58:25 -0700337#if defined(__ANDROID__)
338static bool SetProperty(const char* prop_name, uint64_t value) {
339 if (!android::base::SetProperty(prop_name, std::to_string(value))) {
340 LOG(ERROR) << "Failed to SetProperty " << prop_name << " to " << value;
Yabin Cui0720d482017-03-06 17:05:50 -0800341 return false;
342 }
343 return true;
344}
345
Yabin Cui6e173a42018-08-13 15:58:25 -0700346bool SetPerfEventLimits(uint64_t sample_freq, size_t cpu_percent, uint64_t mlock_kb) {
347 if (!SetProperty("debug.perf_event_max_sample_rate", sample_freq) ||
348 !SetProperty("debug.perf_cpu_time_max_percent", cpu_percent) ||
349 !SetProperty("debug.perf_event_mlock_kb", mlock_kb) ||
350 !SetProperty("security.perf_harden", 0)) {
351 return false;
352 }
353 // Wait for init process to change perf event limits based on properties.
354 const size_t max_wait_us = 3 * 1000000;
Yury Khmelac7a26e2023-05-18 14:31:05 -0700355 const size_t interval_us = 10000;
Yabin Cui6e173a42018-08-13 15:58:25 -0700356 int finish_mask = 0;
Yury Khmelac7a26e2023-05-18 14:31:05 -0700357 for (size_t i = 0; i < max_wait_us && finish_mask != 7; i += interval_us) {
358 usleep(interval_us); // Wait 10ms to avoid busy loop.
Yabin Cui6e173a42018-08-13 15:58:25 -0700359 if ((finish_mask & 1) == 0) {
360 uint64_t freq;
361 if (!GetMaxSampleFrequency(&freq) || freq == sample_freq) {
362 finish_mask |= 1;
363 }
364 }
365 if ((finish_mask & 2) == 0) {
366 size_t percent;
367 if (!GetCpuTimeMaxPercent(&percent) || percent == cpu_percent) {
368 finish_mask |= 2;
369 }
370 }
371 if ((finish_mask & 4) == 0) {
372 uint64_t kb;
373 if (!GetPerfEventMlockKb(&kb) || kb == mlock_kb) {
374 finish_mask |= 4;
375 }
376 }
377 }
378 if (finish_mask != 7) {
379 LOG(WARNING) << "Wait setting perf event limits timeout";
380 }
381 return true;
382}
383#else // !defined(__ANDROID__)
384bool SetPerfEventLimits(uint64_t, size_t, uint64_t) {
385 return true;
386}
387#endif
388
389template <typename T>
390static bool ReadUintFromProcFile(const std::string& path, T* value) {
391 std::string s;
392 if (!android::base::ReadFileToString(path, &s)) {
393 PLOG(DEBUG) << "failed to read " << path;
394 return false;
395 }
396 s = android::base::Trim(s);
397 if (!android::base::ParseUint(s.c_str(), value)) {
398 LOG(ERROR) << "failed to parse " << path << ": " << s;
399 return false;
400 }
401 return true;
402}
403
404template <typename T>
405static bool WriteUintToProcFile(const std::string& path, T value) {
406 if (IsRoot()) {
407 return android::base::WriteStringToFile(std::to_string(value), path);
408 }
409 return false;
410}
411
412bool GetMaxSampleFrequency(uint64_t* max_sample_freq) {
413 return ReadUintFromProcFile("/proc/sys/kernel/perf_event_max_sample_rate", max_sample_freq);
414}
415
416bool SetMaxSampleFrequency(uint64_t max_sample_freq) {
417 return WriteUintToProcFile("/proc/sys/kernel/perf_event_max_sample_rate", max_sample_freq);
418}
419
420bool GetCpuTimeMaxPercent(size_t* percent) {
421 return ReadUintFromProcFile("/proc/sys/kernel/perf_cpu_time_max_percent", percent);
422}
423
424bool SetCpuTimeMaxPercent(size_t percent) {
425 return WriteUintToProcFile("/proc/sys/kernel/perf_cpu_time_max_percent", percent);
426}
427
428bool GetPerfEventMlockKb(uint64_t* mlock_kb) {
429 return ReadUintFromProcFile("/proc/sys/kernel/perf_event_mlock_kb", mlock_kb);
430}
431
432bool SetPerfEventMlockKb(uint64_t mlock_kb) {
433 return WriteUintToProcFile("/proc/sys/kernel/perf_event_mlock_kb", mlock_kb);
434}
435
Yabin Cui417df292016-11-16 12:26:13 -0800436ArchType GetMachineArch() {
Yabin Cuif227b6d2021-01-06 14:01:53 -0800437#if defined(__i386__)
438 // For 32 bit x86 build, we can't get machine arch by uname().
439 ArchType arch = ARCH_UNSUPPORTED;
440 std::unique_ptr<FILE, decltype(&pclose)> fp(popen("uname -m", "re"), pclose);
441 if (fp) {
442 char machine[40];
443 if (fgets(machine, sizeof(machine), fp.get()) == machine) {
444 arch = GetArchType(android::base::Trim(machine));
445 }
446 }
447#else
Yabin Cui417df292016-11-16 12:26:13 -0800448 utsname uname_buf;
449 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0) {
450 PLOG(WARNING) << "uname() failed";
Yabin Cui38076912021-08-16 16:59:09 -0700451 return GetTargetArch();
Yabin Cui417df292016-11-16 12:26:13 -0800452 }
453 ArchType arch = GetArchType(uname_buf.machine);
Yabin Cuif227b6d2021-01-06 14:01:53 -0800454#endif
Yabin Cui417df292016-11-16 12:26:13 -0800455 if (arch != ARCH_UNSUPPORTED) {
456 return arch;
457 }
Yabin Cui38076912021-08-16 16:59:09 -0700458 return GetTargetArch();
Yabin Cui417df292016-11-16 12:26:13 -0800459}
Yabin Cui63a1c3d2017-05-19 12:57:44 -0700460
461void PrepareVdsoFile() {
462 // vdso is an elf file in memory loaded in each process's user space by the kernel. To read
463 // symbols from it and unwind through it, we need to dump it into a file in storage.
464 // It doesn't affect much when failed to prepare vdso file, so there is no need to return values.
465 std::vector<ThreadMmap> thread_mmaps;
466 if (!GetThreadMmapsInProcess(getpid(), &thread_mmaps)) {
467 return;
468 }
469 const ThreadMmap* vdso_map = nullptr;
470 for (const auto& map : thread_mmaps) {
471 if (map.name == "[vdso]") {
472 vdso_map = &map;
473 break;
474 }
475 }
476 if (vdso_map == nullptr) {
477 return;
478 }
479 std::string s(vdso_map->len, '\0');
480 memcpy(&s[0], reinterpret_cast<void*>(static_cast<uintptr_t>(vdso_map->start_addr)),
481 vdso_map->len);
Yabin Cuic68e66d2018-03-07 15:47:15 -0800482 std::unique_ptr<TemporaryFile> tmpfile = ScopedTempFiles::CreateTempFile();
483 if (!android::base::WriteStringToFd(s, tmpfile->fd)) {
Yabin Cui63a1c3d2017-05-19 12:57:44 -0700484 return;
485 }
Yabin Cuic68e66d2018-03-07 15:47:15 -0800486 Dso::SetVdsoFile(tmpfile->path, sizeof(size_t) == sizeof(uint64_t));
Yabin Cui63a1c3d2017-05-19 12:57:44 -0700487}
Yabin Cuia80f8f72017-07-12 15:50:20 -0700488
Yabin Cui88387692017-08-28 15:49:33 -0700489static bool HasOpenedAppApkFile(int pid) {
490 std::string fd_path = "/proc/" + std::to_string(pid) + "/fd/";
491 std::vector<std::string> files = GetEntriesInDir(fd_path);
492 for (const auto& file : files) {
493 std::string real_path;
494 if (!android::base::Readlink(fd_path + file, &real_path)) {
495 continue;
496 }
497 if (real_path.find("app") != std::string::npos && real_path.find(".apk") != std::string::npos) {
498 return true;
499 }
500 }
501 return false;
502}
503
Yabin Cui7cb6f292017-08-28 14:49:04 -0700504std::set<pid_t> WaitForAppProcesses(const std::string& package_name) {
505 std::set<pid_t> result;
Yabin Cuia80f8f72017-07-12 15:50:20 -0700506 size_t loop_count = 0;
507 while (true) {
508 std::vector<pid_t> pids = GetAllProcesses();
509 for (pid_t pid : pids) {
Yabin Cui1c6be752023-02-28 11:46:37 -0800510 std::string process_name = GetCompleteProcessName(pid);
511 if (process_name.empty()) {
Yabin Cuia80f8f72017-07-12 15:50:20 -0700512 continue;
513 }
Yabin Cui7cb6f292017-08-28 14:49:04 -0700514 // The app may have multiple processes, with process name like
515 // com.google.android.googlequicksearchbox:search.
516 size_t split_pos = process_name.find(':');
517 if (split_pos != std::string::npos) {
518 process_name = process_name.substr(0, split_pos);
519 }
520 if (process_name != package_name) {
Yabin Cui88387692017-08-28 15:49:33 -0700521 continue;
Yabin Cuia80f8f72017-07-12 15:50:20 -0700522 }
Yabin Cui88387692017-08-28 15:49:33 -0700523 // If a debuggable app with wrap.sh runs on Android O, the app will be started with
524 // logwrapper as below:
525 // 1. Zygote forks a child process, rename it to package_name.
526 // 2. The child process execute sh, which starts a child process running
527 // /system/bin/logwrapper.
528 // 3. logwrapper starts a child process running sh, which interprets wrap.sh.
529 // 4. wrap.sh starts a child process running the app.
530 // The problem here is we want to profile the process started in step 4, but sometimes we
531 // run into the process started in step 1. To solve it, we can check if the process has
532 // opened an apk file in some app dirs.
533 if (!HasOpenedAppApkFile(pid)) {
534 continue;
535 }
536 if (loop_count > 0u) {
537 LOG(INFO) << "Got process " << pid << " for package " << package_name;
538 }
Yabin Cui7cb6f292017-08-28 14:49:04 -0700539 result.insert(pid);
540 }
541 if (!result.empty()) {
542 return result;
Yabin Cuia80f8f72017-07-12 15:50:20 -0700543 }
544 if (++loop_count == 1u) {
545 LOG(INFO) << "Waiting for process of app " << package_name;
546 }
547 usleep(1000);
548 }
549}
550
Yabin Cui1a30a582019-01-10 15:35:39 -0800551namespace {
Yabin Cuif8974522017-07-17 14:36:37 -0700552
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700553bool IsAppDebuggable(int user_id, const std::string& package_name) {
554 return Workload::RunCmd({"run-as", package_name, "--user", std::to_string(user_id), "echo",
555 ">/dev/null", "2>/dev/null"},
556 false);
Yabin Cui902f9082020-10-15 17:32:48 -0700557}
558
Yabin Cui1a30a582019-01-10 15:35:39 -0800559class InAppRunner {
560 public:
Yabin Cui902f9082020-10-15 17:32:48 -0700561 InAppRunner(int user_id, const std::string& package_name)
562 : user_id_(std::to_string(user_id)), package_name_(package_name) {}
Yabin Cui1a30a582019-01-10 15:35:39 -0800563 virtual ~InAppRunner() {
564 if (!tracepoint_file_.empty()) {
565 unlink(tracepoint_file_.c_str());
Yabin Cuif8974522017-07-17 14:36:37 -0700566 }
567 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800568 virtual bool Prepare() = 0;
569 bool RunCmdInApp(const std::string& cmd, const std::vector<std::string>& args,
570 size_t workload_args_size, const std::string& output_filepath,
571 bool need_tracepoint_events);
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200572
Yabin Cui1a30a582019-01-10 15:35:39 -0800573 protected:
574 virtual std::vector<std::string> GetPrefixArgs(const std::string& cmd) = 0;
Yabin Cuif8974522017-07-17 14:36:37 -0700575
Yabin Cui902f9082020-10-15 17:32:48 -0700576 const std::string user_id_;
Yabin Cui1a30a582019-01-10 15:35:39 -0800577 const std::string package_name_;
578 std::string tracepoint_file_;
Yabin Cuif8974522017-07-17 14:36:37 -0700579};
580
Yabin Cui1a30a582019-01-10 15:35:39 -0800581bool InAppRunner::RunCmdInApp(const std::string& cmd, const std::vector<std::string>& cmd_args,
582 size_t workload_args_size, const std::string& output_filepath,
583 bool need_tracepoint_events) {
584 // 1. Build cmd args running in app's context.
585 std::vector<std::string> args = GetPrefixArgs(cmd);
586 args.insert(args.end(), {"--in-app", "--log", GetLogSeverityName()});
Yabin Cuia556c562020-02-14 16:50:10 -0800587 if (log_to_android_buffer) {
588 args.emplace_back("--log-to-android-buffer");
589 }
Yabin Cuif8974522017-07-17 14:36:37 -0700590 if (need_tracepoint_events) {
591 // Since we can't read tracepoint events from tracefs in app's context, we need to prepare
592 // them in tracepoint_file in shell's context, and pass the path of tracepoint_file to the
593 // child process using --tracepoint-events option.
Yabin Cui1a30a582019-01-10 15:35:39 -0800594 const std::string tracepoint_file = "/data/local/tmp/tracepoint_events";
Yabin Cui16a6ace2020-10-01 14:56:32 -0700595 if (!EventTypeManager::Instance().WriteTracepointsToFile(tracepoint_file)) {
Yabin Cuif8974522017-07-17 14:36:37 -0700596 PLOG(ERROR) << "Failed to store tracepoint events";
597 return false;
598 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800599 tracepoint_file_ = tracepoint_file;
600 args.insert(args.end(), {"--tracepoint-events", tracepoint_file_});
Yabin Cuif8974522017-07-17 14:36:37 -0700601 }
Yabin Cuia80f8f72017-07-12 15:50:20 -0700602
Yabin Cui1a30a582019-01-10 15:35:39 -0800603 android::base::unique_fd out_fd;
604 if (!output_filepath.empty()) {
605 // A process running in app's context can't open a file outside it's data directory to write.
606 // So pass it a file descriptor to write.
607 out_fd = FileHelper::OpenWriteOnly(output_filepath);
608 if (out_fd == -1) {
609 PLOG(ERROR) << "Failed to open " << output_filepath;
610 return false;
Yabin Cuia80f8f72017-07-12 15:50:20 -0700611 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800612 args.insert(args.end(), {"--out-fd", std::to_string(int(out_fd))});
Yabin Cuia80f8f72017-07-12 15:50:20 -0700613 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800614
615 // We can't send signal to a process running in app's context. So use a pipe file to send stop
616 // signal.
617 android::base::unique_fd stop_signal_rfd;
618 android::base::unique_fd stop_signal_wfd;
619 if (!android::base::Pipe(&stop_signal_rfd, &stop_signal_wfd, 0)) {
620 PLOG(ERROR) << "pipe";
621 return false;
622 }
623 args.insert(args.end(), {"--stop-signal-fd", std::to_string(int(stop_signal_rfd))});
624
625 for (size_t i = 0; i < cmd_args.size(); ++i) {
626 if (i < cmd_args.size() - workload_args_size) {
627 // Omit "-o output_file". It is replaced by "--out-fd fd".
628 if (cmd_args[i] == "-o" || cmd_args[i] == "--app") {
629 i++;
630 continue;
631 }
632 }
633 args.push_back(cmd_args[i]);
634 }
635 char* argv[args.size() + 1];
636 for (size_t i = 0; i < args.size(); ++i) {
637 argv[i] = &args[i][0];
638 }
639 argv[args.size()] = nullptr;
640
641 // 2. Run child process in app's context.
642 auto ChildProcFn = [&]() {
643 stop_signal_wfd.reset();
644 execvp(argv[0], argv);
645 exit(1);
646 };
647 std::unique_ptr<Workload> workload = Workload::CreateWorkload(ChildProcFn);
Yabin Cuia80f8f72017-07-12 15:50:20 -0700648 if (!workload) {
649 return false;
650 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800651 stop_signal_rfd.reset();
Yabin Cuia80f8f72017-07-12 15:50:20 -0700652
Yabin Cui1a30a582019-01-10 15:35:39 -0800653 // Wait on signals.
Yabin Cuia80f8f72017-07-12 15:50:20 -0700654 IOEventLoop loop;
Yabin Cui1a30a582019-01-10 15:35:39 -0800655 bool need_to_stop_child = false;
Yabin Cuid5d9c422018-04-11 17:50:56 -0700656 std::vector<int> stop_signals = {SIGINT, SIGTERM};
657 if (!SignalIsIgnored(SIGHUP)) {
658 stop_signals.push_back(SIGHUP);
659 }
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200660 if (!loop.AddSignalEvents(stop_signals, [&]() {
661 need_to_stop_child = true;
662 return loop.ExitLoop();
663 })) {
Yabin Cuia80f8f72017-07-12 15:50:20 -0700664 return false;
665 }
666 if (!loop.AddSignalEvent(SIGCHLD, [&]() { return loop.ExitLoop(); })) {
667 return false;
668 }
669
Yabin Cuia80f8f72017-07-12 15:50:20 -0700670 if (!workload->Start()) {
671 return false;
672 }
673 if (!loop.RunLoop()) {
674 return false;
675 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800676 if (need_to_stop_child) {
677 stop_signal_wfd.reset();
Yabin Cuia80f8f72017-07-12 15:50:20 -0700678 }
679 int exit_code;
Yabin Cui248ef5e2021-12-16 14:09:39 -0800680 if (!workload->WaitChildProcess(true, &exit_code) || exit_code != 0) {
Yabin Cuia80f8f72017-07-12 15:50:20 -0700681 return false;
682 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800683 return true;
684}
Yabin Cuia80f8f72017-07-12 15:50:20 -0700685
Yabin Cui1a30a582019-01-10 15:35:39 -0800686class RunAs : public InAppRunner {
687 public:
Yabin Cui902f9082020-10-15 17:32:48 -0700688 RunAs(int user_id, const std::string& package_name) : InAppRunner(user_id, package_name) {}
Yabin Cui1a30a582019-01-10 15:35:39 -0800689 virtual ~RunAs() {
690 if (simpleperf_copied_in_app_) {
Yabin Cui902f9082020-10-15 17:32:48 -0700691 Workload::RunCmd({"run-as", package_name_, "--user", user_id_, "rm", "-rf", "simpleperf"});
Yabin Cuia80f8f72017-07-12 15:50:20 -0700692 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800693 }
694 bool Prepare() override;
695
696 protected:
697 std::vector<std::string> GetPrefixArgs(const std::string& cmd) {
Yabin Cui8729bc62021-05-11 11:29:38 -0700698 std::vector<std::string> args = {"run-as",
699 package_name_,
700 "--user",
701 user_id_,
702 simpleperf_copied_in_app_ ? "./simpleperf" : simpleperf_path_,
703 cmd,
704 "--app",
705 package_name_};
706 if (cmd == "record") {
707 if (simpleperf_copied_in_app_ || GetAndroidVersion() >= kAndroidVersionS) {
708 args.emplace_back("--add-meta-info");
709 args.emplace_back("app_type=debuggable");
710 }
711 }
712 return args;
Yabin Cui1a30a582019-01-10 15:35:39 -0800713 }
714
715 bool simpleperf_copied_in_app_ = false;
716 std::string simpleperf_path_;
717};
718
719bool RunAs::Prepare() {
Yabin Cui1a30a582019-01-10 15:35:39 -0800720 // run-as can't run /data/local/tmp/simpleperf directly. So copy simpleperf binary if needed.
721 if (!android::base::Readlink("/proc/self/exe", &simpleperf_path_)) {
722 PLOG(ERROR) << "ReadLink failed";
723 return false;
724 }
Yabin Cuia24cf962019-01-29 17:06:42 -0800725 if (simpleperf_path_.find("CtsSimpleperfTest") != std::string::npos) {
726 simpleperf_path_ = "/system/bin/simpleperf";
727 return true;
728 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800729 if (android::base::StartsWith(simpleperf_path_, "/system")) {
730 return true;
731 }
Yabin Cui902f9082020-10-15 17:32:48 -0700732 if (!Workload::RunCmd(
733 {"run-as", package_name_, "--user", user_id_, "cp", simpleperf_path_, "simpleperf"})) {
Yabin Cui1a30a582019-01-10 15:35:39 -0800734 return false;
735 }
736 simpleperf_copied_in_app_ = true;
737 return true;
738}
739
740class SimpleperfAppRunner : public InAppRunner {
741 public:
Greg Kaiserde124ee2021-05-17 12:54:14 -0700742 SimpleperfAppRunner(int user_id, const std::string& package_name, const std::string& app_type)
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700743 : InAppRunner(user_id, package_name) {
744 // On Android < S, the app type is unknown before running simpleperf_app_runner. Assume it's
745 // profileable.
746 app_type_ = app_type == "unknown" ? "profileable" : app_type;
747 }
Yabin Cui8729bc62021-05-11 11:29:38 -0700748 bool Prepare() override { return GetAndroidVersion() >= kAndroidVersionQ; }
Yabin Cui1a30a582019-01-10 15:35:39 -0800749
750 protected:
751 std::vector<std::string> GetPrefixArgs(const std::string& cmd) {
Yabin Cui92825be2020-12-02 17:06:54 -0800752 std::vector<std::string> args = {"simpleperf_app_runner", package_name_};
753 if (user_id_ != "0") {
754 args.emplace_back("--user");
755 args.emplace_back(user_id_);
756 }
757 args.emplace_back(cmd);
Yabin Cui8729bc62021-05-11 11:29:38 -0700758 if (cmd == "record" && GetAndroidVersion() >= kAndroidVersionS) {
759 args.emplace_back("--add-meta-info");
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700760 args.emplace_back("app_type=" + app_type_);
Yabin Cui8729bc62021-05-11 11:29:38 -0700761 }
Yabin Cui92825be2020-12-02 17:06:54 -0800762 return args;
Yabin Cui1a30a582019-01-10 15:35:39 -0800763 }
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700764
765 std::string app_type_;
Yabin Cui1a30a582019-01-10 15:35:39 -0800766};
767
768} // namespace
769
Yabin Cui94c148d2020-02-18 14:32:33 -0800770static bool allow_run_as = true;
771static bool allow_simpleperf_app_runner = true;
772
773void SetRunInAppToolForTesting(bool run_as, bool simpleperf_app_runner) {
774 allow_run_as = run_as;
775 allow_simpleperf_app_runner = simpleperf_app_runner;
776}
777
Yabin Cui902f9082020-10-15 17:32:48 -0700778static int GetCurrentUserId() {
779 std::unique_ptr<FILE, decltype(&pclose)> fd(popen("am get-current-user", "r"), pclose);
780 if (fd) {
781 char buf[128];
782 if (fgets(buf, sizeof(buf), fd.get()) != nullptr) {
783 int user_id;
784 if (android::base::ParseInt(android::base::Trim(buf), &user_id, 0)) {
785 return user_id;
786 }
787 }
788 }
789 return 0;
790}
791
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700792std::string GetAppType(const std::string& app_package_name) {
793 if (GetAndroidVersion() < kAndroidVersionS) {
794 return "unknown";
795 }
796 std::string cmd = "simpleperf_app_runner " + app_package_name + " --show-app-type";
797 std::unique_ptr<FILE, decltype(&pclose)> fp(popen(cmd.c_str(), "re"), pclose);
798 if (fp) {
799 char buf[128];
800 if (fgets(buf, sizeof(buf), fp.get()) != nullptr) {
801 return android::base::Trim(buf);
802 }
803 }
804 // Can't get app_type. It means the app doesn't exist.
805 return "not_exist";
806}
807
Yabin Cui1a30a582019-01-10 15:35:39 -0800808bool RunInAppContext(const std::string& app_package_name, const std::string& cmd,
809 const std::vector<std::string>& args, size_t workload_args_size,
810 const std::string& output_filepath, bool need_tracepoint_events) {
Yabin Cui902f9082020-10-15 17:32:48 -0700811 int user_id = GetCurrentUserId();
Yabin Cui94c148d2020-02-18 14:32:33 -0800812 std::unique_ptr<InAppRunner> in_app_runner;
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700813
814 std::string app_type = GetAppType(app_package_name);
815 if (app_type == "unknown" && IsAppDebuggable(user_id, app_package_name)) {
816 app_type = "debuggable";
817 }
818
819 if (allow_run_as && app_type == "debuggable") {
Yabin Cui902f9082020-10-15 17:32:48 -0700820 in_app_runner.reset(new RunAs(user_id, app_package_name));
Yabin Cui94c148d2020-02-18 14:32:33 -0800821 if (!in_app_runner->Prepare()) {
822 in_app_runner = nullptr;
823 }
824 }
825 if (!in_app_runner && allow_simpleperf_app_runner) {
Yabin Cuidb19d6d2021-05-12 17:36:02 -0700826 if (app_type == "debuggable" || app_type == "profileable" || app_type == "unknown") {
827 in_app_runner.reset(new SimpleperfAppRunner(user_id, app_package_name, app_type));
828 if (!in_app_runner->Prepare()) {
829 in_app_runner = nullptr;
830 }
Yabin Cuia80f8f72017-07-12 15:50:20 -0700831 }
832 }
Yabin Cui94c148d2020-02-18 14:32:33 -0800833 if (!in_app_runner) {
834 LOG(ERROR) << "Package " << app_package_name
835 << " doesn't exist or isn't debuggable/profileable.";
836 return false;
837 }
Yabin Cui1a30a582019-01-10 15:35:39 -0800838 return in_app_runner->RunCmdInApp(cmd, args, workload_args_size, output_filepath,
839 need_tracepoint_events);
Yabin Cuia80f8f72017-07-12 15:50:20 -0700840}
Yabin Cui616b3a02017-07-14 15:59:56 -0700841
Yabin Cui7c5fe4e2017-12-05 17:44:05 -0800842void AllowMoreOpenedFiles() {
843 // On Android <= O, the hard limit is 4096, and the soft limit is 1024.
844 // On Android >= P, both the hard and soft limit are 32768.
845 rlimit limit;
Yabin Cuic0e1f882023-02-15 10:43:16 -0800846 if (getrlimit(RLIMIT_NOFILE, &limit) != 0) {
847 return;
848 }
849 rlim_t new_limit = limit.rlim_max;
850 if (IsRoot()) {
851 rlim_t sysctl_nr_open = 0;
852 if (ReadUintFromProcFile("/proc/sys/fs/nr_open", &sysctl_nr_open) &&
853 sysctl_nr_open > new_limit) {
854 new_limit = sysctl_nr_open;
855 }
856 }
857 if (limit.rlim_cur < new_limit) {
858 limit.rlim_cur = limit.rlim_max = new_limit;
859 if (setrlimit(RLIMIT_NOFILE, &limit) == 0) {
860 LOG(DEBUG) << "increased open file limit to " << new_limit;
861 }
Yabin Cui7c5fe4e2017-12-05 17:44:05 -0800862 }
863}
Yabin Cui38b6a902017-12-06 14:15:48 -0800864
Yabin Cuic68e66d2018-03-07 15:47:15 -0800865std::string ScopedTempFiles::tmp_dir_;
866std::vector<std::string> ScopedTempFiles::files_to_delete_;
867
Yabin Cui554f3bb2021-05-05 13:34:59 -0700868std::unique_ptr<ScopedTempFiles> ScopedTempFiles::Create(const std::string& tmp_dir) {
869 if (access(tmp_dir.c_str(), W_OK | X_OK) != 0) {
870 return nullptr;
871 }
872 return std::unique_ptr<ScopedTempFiles>(new ScopedTempFiles(tmp_dir));
873}
874
Yabin Cuic68e66d2018-03-07 15:47:15 -0800875ScopedTempFiles::ScopedTempFiles(const std::string& tmp_dir) {
876 CHECK(tmp_dir_.empty()); // No other ScopedTempFiles.
877 tmp_dir_ = tmp_dir;
Yabin Cui38b6a902017-12-06 14:15:48 -0800878}
879
Yabin Cuic68e66d2018-03-07 15:47:15 -0800880ScopedTempFiles::~ScopedTempFiles() {
881 tmp_dir_.clear();
882 for (auto& file : files_to_delete_) {
883 unlink(file.c_str());
884 }
885 files_to_delete_.clear();
886}
887
888std::unique_ptr<TemporaryFile> ScopedTempFiles::CreateTempFile(bool delete_in_destructor) {
889 CHECK(!tmp_dir_.empty());
890 std::unique_ptr<TemporaryFile> tmp_file(new TemporaryFile(tmp_dir_));
Yabin Cuia9cfcde2020-06-29 14:04:44 -0700891 CHECK_NE(tmp_file->fd, -1) << "failed to create tmpfile under " << tmp_dir_;
Yabin Cuic68e66d2018-03-07 15:47:15 -0800892 if (delete_in_destructor) {
893 tmp_file->DoNotRemove();
894 files_to_delete_.push_back(tmp_file->path);
895 }
896 return tmp_file;
Yabin Cui38b6a902017-12-06 14:15:48 -0800897}
Josh Gao30535f22017-12-14 16:10:28 -0800898
Yabin Cuie32ed2b2020-07-23 15:30:14 -0700899void ScopedTempFiles::RegisterTempFile(const std::string& path) {
900 files_to_delete_.emplace_back(path);
901}
902
Josh Gao30535f22017-12-14 16:10:28 -0800903bool SignalIsIgnored(int signo) {
904 struct sigaction act;
905 if (sigaction(signo, nullptr, &act) != 0) {
906 PLOG(FATAL) << "failed to query signal handler for signal " << signo;
907 }
908
909 if ((act.sa_flags & SA_SIGINFO)) {
910 return false;
911 }
912
913 return act.sa_handler == SIG_IGN;
914}
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800915
916int GetAndroidVersion() {
917#if defined(__ANDROID__)
Yabin Cui6e173a42018-08-13 15:58:25 -0700918 static int android_version = -1;
919 if (android_version == -1) {
920 android_version = 0;
Yabin Cui58740ff2021-03-23 13:34:51 -0700921 std::string s = android::base::GetProperty("ro.build.version.codename", "REL");
922 if (s == "REL") {
923 s = android::base::GetProperty("ro.build.version.release", "");
924 }
Yabin Cui6e173a42018-08-13 15:58:25 -0700925 // The release string can be a list of numbers (like 8.1.0), a character (like Q)
926 // or many characters (like OMR1).
927 if (!s.empty()) {
928 // Each Android version has a version number: L is 5, M is 6, N is 7, O is 8, etc.
929 if (s[0] >= 'A' && s[0] <= 'Z') {
930 android_version = s[0] - 'P' + kAndroidVersionP;
931 } else if (isdigit(s[0])) {
932 sscanf(s.c_str(), "%d", &android_version);
933 }
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800934 }
935 }
Yabin Cui6e173a42018-08-13 15:58:25 -0700936 return android_version;
937#else // defined(__ANDROID__)
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800938 return 0;
Yabin Cui6e173a42018-08-13 15:58:25 -0700939#endif
Yabin Cui9e43e9f2018-03-09 15:57:13 -0800940}
Yabin Cui8faa6152018-06-07 15:52:57 -0700941
942std::string GetHardwareFromCpuInfo(const std::string& cpu_info) {
943 for (auto& line : android::base::Split(cpu_info, "\n")) {
944 size_t pos = line.find(':');
945 if (pos != std::string::npos) {
946 std::string key = android::base::Trim(line.substr(0, pos));
947 if (key == "Hardware") {
948 return android::base::Trim(line.substr(pos + 1));
949 }
950 }
951 }
952 return "";
953}
Yabin Cui2db05b42018-07-16 14:04:49 -0700954
955bool MappedFileOnlyExistInMemory(const char* filename) {
956 // Mapped files only existing in memory:
957 // empty name
958 // [anon:???]
959 // [stack]
960 // /dev/*
961 // //anon: generated by kernel/events/core.c.
Yabin Cui739b1542018-10-17 17:19:56 -0700962 // /memfd: created by memfd_create.
Thiébaud Weksteen4848ee02020-10-23 16:06:59 +0200963 return filename[0] == '\0' || (filename[0] == '[' && strcmp(filename, "[vdso]") != 0) ||
964 strncmp(filename, "//", 2) == 0 || strncmp(filename, "/dev/", 5) == 0 ||
965 strncmp(filename, "/memfd:", 7) == 0;
Yabin Cui2db05b42018-07-16 14:04:49 -0700966}
Yabin Cui38335f42018-07-17 16:06:21 -0700967
968std::string GetCompleteProcessName(pid_t pid) {
Yabin Cui1c6be752023-02-28 11:46:37 -0800969 std::string argv0;
970 if (!android::base::ReadFileToString("/proc/" + std::to_string(pid) + "/cmdline", &argv0)) {
971 // Maybe we don't have permission to read it.
972 return std::string();
Yabin Cui38335f42018-07-17 16:06:21 -0700973 }
Yabin Cui1c6be752023-02-28 11:46:37 -0800974 size_t pos = argv0.find('\0');
975 if (pos != std::string::npos) {
976 argv0.resize(pos);
Yabin Cui38335f42018-07-17 16:06:21 -0700977 }
Yabin Cui504119d2023-03-01 14:02:18 -0800978 // argv0 can be empty if the process is in zombie state. In that case, we don't want to pass argv0
979 // to Basename(), which returns ".".
980 return argv0.empty() ? std::string() : android::base::Basename(argv0);
Yabin Cui38335f42018-07-17 16:06:21 -0700981}
Yabin Cuia22efeb2020-01-29 13:27:33 -0800982
983const char* GetTraceFsDir() {
Yabin Cui142acc82020-10-14 10:24:38 -0700984 static const char* tracefs_dir = nullptr;
985 if (tracefs_dir == nullptr) {
986 for (const char* path : {"/sys/kernel/debug/tracing", "/sys/kernel/tracing"}) {
987 if (IsDir(path)) {
988 tracefs_dir = path;
989 break;
990 }
Yabin Cuia22efeb2020-01-29 13:27:33 -0800991 }
992 }
Yabin Cui142acc82020-10-14 10:24:38 -0700993 return tracefs_dir;
Yabin Cuia22efeb2020-01-29 13:27:33 -0800994}
Yabin Cui84c55ff2020-07-09 14:14:22 -0700995
Yabin Cuid703bb32021-01-05 16:45:52 -0800996std::optional<std::pair<int, int>> GetKernelVersion() {
Yabin Cui71aec162021-11-03 15:23:22 -0700997 static std::optional<std::pair<int, int>> kernel_version;
998 if (!kernel_version.has_value()) {
999 utsname uname_buf;
1000 int major;
1001 int minor;
1002 if (TEMP_FAILURE_RETRY(uname(&uname_buf)) != 0 ||
1003 sscanf(uname_buf.release, "%d.%d", &major, &minor) != 2) {
1004 return std::nullopt;
1005 }
1006 kernel_version = std::make_pair(major, minor);
Yabin Cui84c55ff2020-07-09 14:14:22 -07001007 }
Yabin Cui71aec162021-11-03 15:23:22 -07001008 return kernel_version;
Yabin Cui84c55ff2020-07-09 14:14:22 -07001009}
Yabin Cuifaa7b922021-01-11 17:35:57 -08001010
Yabin Cui3485af92021-10-27 10:50:53 -07001011#if defined(__ANDROID__)
1012bool IsInAppUid() {
1013 return getuid() % AID_USER_OFFSET >= AID_APP_START;
1014}
1015#endif
1016
Yabin Cuia89a3742021-02-11 13:14:54 -08001017std::optional<uid_t> GetProcessUid(pid_t pid) {
1018 std::string status_file = "/proc/" + std::to_string(pid) + "/status";
Yabin Cui40eef9e2021-04-13 13:08:31 -07001019 LineReader reader(status_file);
1020 if (!reader.Ok()) {
Yabin Cuia89a3742021-02-11 13:14:54 -08001021 return std::nullopt;
1022 }
1023
Yabin Cui40eef9e2021-04-13 13:08:31 -07001024 std::string* line;
Yabin Cuia89a3742021-02-11 13:14:54 -08001025 while ((line = reader.ReadLine()) != nullptr) {
Yabin Cui40eef9e2021-04-13 13:08:31 -07001026 if (android::base::StartsWith(*line, "Uid:")) {
Yabin Cuia89a3742021-02-11 13:14:54 -08001027 uid_t uid;
Yabin Cui40eef9e2021-04-13 13:08:31 -07001028 if (sscanf(line->data() + strlen("Uid:"), "%u", &uid) == 1) {
Yabin Cuia89a3742021-02-11 13:14:54 -08001029 return uid;
1030 }
1031 }
1032 }
1033 return std::nullopt;
1034}
1035
Yabin Cui433d6f52024-01-09 15:29:09 -08001036std::vector<ARMCpuModel> GetARMCpuModels() {
1037 std::vector<ARMCpuModel> cpu_models;
1038 LineReader reader("/proc/cpuinfo");
1039 if (!reader.Ok()) {
1040 return cpu_models;
1041 }
1042 auto add_cpu = [&](uint32_t processor, uint32_t implementer, uint32_t partnum) {
1043 for (auto& model : cpu_models) {
1044 if (model.implementer == implementer && model.partnum == partnum) {
1045 model.cpus.push_back(processor);
1046 return;
1047 }
1048 }
1049 cpu_models.resize(cpu_models.size() + 1);
1050 ARMCpuModel& model = cpu_models.back();
1051 model.implementer = implementer;
1052 model.partnum = partnum;
1053 model.cpus.push_back(processor);
1054 };
1055
1056 uint32_t processor = 0;
1057 uint32_t implementer = 0;
1058 uint32_t partnum = 0;
1059 int parsed = 0;
1060 std::string* line;
1061 while ((line = reader.ReadLine()) != nullptr) {
1062 std::vector<std::string> strs = android::base::Split(*line, ":");
1063 if (strs.size() != 2) {
1064 continue;
1065 }
1066 std::string name = android::base::Trim(strs[0]);
1067 std::string value = android::base::Trim(strs[1]);
1068 if (name == "processor") {
1069 if (android::base::ParseUint(value, &processor)) {
1070 parsed |= 1;
1071 }
1072 } else if (name == "CPU implementer") {
1073 if (android::base::ParseUint(value, &implementer)) {
1074 parsed |= 2;
1075 }
1076 } else if (name == "CPU part") {
1077 if (android::base::ParseUint(value, &partnum) && parsed == 0x3) {
1078 add_cpu(processor, implementer, partnum);
1079 }
1080 parsed = 0;
1081 }
1082 }
1083 return cpu_models;
1084}
1085
Yabin Cuifaa7b922021-01-11 17:35:57 -08001086} // namespace simpleperf