106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. 306f6ba60Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 406f6ba60Sopenharmony_ci * you may not use this file except in compliance with the License. 506f6ba60Sopenharmony_ci * You may obtain a copy of the License at 606f6ba60Sopenharmony_ci * 706f6ba60Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 806f6ba60Sopenharmony_ci * 906f6ba60Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1006f6ba60Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1106f6ba60Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1206f6ba60Sopenharmony_ci * See the License for the specific language governing permissions and 1306f6ba60Sopenharmony_ci * limitations under the License. 1406f6ba60Sopenharmony_ci */ 1506f6ba60Sopenharmony_ci#include "ftrace_fs_ops.h" 1606f6ba60Sopenharmony_ci 1706f6ba60Sopenharmony_ci#include <fcntl.h> 1806f6ba60Sopenharmony_ci#include <set> 1906f6ba60Sopenharmony_ci#include <sys/stat.h> 2006f6ba60Sopenharmony_ci#include <sys/types.h> 2106f6ba60Sopenharmony_ci#include <sys/utsname.h> 2206f6ba60Sopenharmony_ci#include <unistd.h> 2306f6ba60Sopenharmony_ci#include "common.h" 2406f6ba60Sopenharmony_ci#include "file_utils.h" 2506f6ba60Sopenharmony_ci#include "logging.h" 2606f6ba60Sopenharmony_ci 2706f6ba60Sopenharmony_ciFTRACE_NS_BEGIN 2806f6ba60Sopenharmony_ciFtraceFsOps& FtraceFsOps::GetInstance() 2906f6ba60Sopenharmony_ci{ 3006f6ba60Sopenharmony_ci static FtraceFsOps instance; 3106f6ba60Sopenharmony_ci return instance; 3206f6ba60Sopenharmony_ci} 3306f6ba60Sopenharmony_ci 3406f6ba60Sopenharmony_ciFtraceFsOps::FtraceFsOps() : ftraceRoot_(GetFtraceRoot()) 3506f6ba60Sopenharmony_ci{ 3606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "FtraceFsOps create!"); 3706f6ba60Sopenharmony_ci} 3806f6ba60Sopenharmony_ci 3906f6ba60Sopenharmony_ciFtraceFsOps::~FtraceFsOps() 4006f6ba60Sopenharmony_ci{ 4106f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "FtraceFsOps destroy!"); 4206f6ba60Sopenharmony_ci} 4306f6ba60Sopenharmony_ci 4406f6ba60Sopenharmony_cistd::string FtraceFsOps::GetFtraceRoot() 4506f6ba60Sopenharmony_ci{ 4606f6ba60Sopenharmony_ci std::vector<std::string> testRootPath = {"/sys/kernel/tracing", "/sys/kernel/debug/tracing"}; 4706f6ba60Sopenharmony_ci for (auto iter = testRootPath.begin(); iter != testRootPath.end(); ++iter) { 4806f6ba60Sopenharmony_ci auto path = *iter + "/events"; 4906f6ba60Sopenharmony_ci struct stat s; 5006f6ba60Sopenharmony_ci lstat(path.c_str(), &s); 5106f6ba60Sopenharmony_ci if (S_ISDIR(s.st_mode)) { 5206f6ba60Sopenharmony_ci return *iter; 5306f6ba60Sopenharmony_ci } 5406f6ba60Sopenharmony_ci } 5506f6ba60Sopenharmony_ci return ""; 5606f6ba60Sopenharmony_ci} 5706f6ba60Sopenharmony_ci 5806f6ba60Sopenharmony_cibool FtraceFsOps::IsHmKernel() 5906f6ba60Sopenharmony_ci{ 6006f6ba60Sopenharmony_ci bool isHM = false; 6106f6ba60Sopenharmony_ci utsname unameBuf; 6206f6ba60Sopenharmony_ci if ((uname(&unameBuf)) == 0) { 6306f6ba60Sopenharmony_ci std::string osRelease = unameBuf.release; 6406f6ba60Sopenharmony_ci isHM = osRelease.find("HongMeng") != std::string::npos; 6506f6ba60Sopenharmony_ci } 6606f6ba60Sopenharmony_ci return isHM; 6706f6ba60Sopenharmony_ci} 6806f6ba60Sopenharmony_ci 6906f6ba60Sopenharmony_ciint FtraceFsOps::WriteTraceFile(const std::string& path, const std::string& content) 7006f6ba60Sopenharmony_ci{ 7106f6ba60Sopenharmony_ci bool ret = false; 7206f6ba60Sopenharmony_ci if (access((ftraceRoot_ + path).c_str(), W_OK) == 0) { 7306f6ba60Sopenharmony_ci if (FileUtils::WriteFile(ftraceRoot_ + path, content) > 0) { 7406f6ba60Sopenharmony_ci ret = true; 7506f6ba60Sopenharmony_ci } 7606f6ba60Sopenharmony_ci } 7706f6ba60Sopenharmony_ci 7806f6ba60Sopenharmony_ci return (int)ret; 7906f6ba60Sopenharmony_ci} 8006f6ba60Sopenharmony_ci 8106f6ba60Sopenharmony_ciint FtraceFsOps::WriteTraceFile(const std::string& path, const std::string& content, int flags) 8206f6ba60Sopenharmony_ci{ 8306f6ba60Sopenharmony_ci bool ret = false; 8406f6ba60Sopenharmony_ci if (access((ftraceRoot_ + path).c_str(), W_OK) == 0) { 8506f6ba60Sopenharmony_ci if (FileUtils::WriteFile(ftraceRoot_ + path, content, flags) > 0) { 8606f6ba60Sopenharmony_ci ret = true; 8706f6ba60Sopenharmony_ci } 8806f6ba60Sopenharmony_ci } 8906f6ba60Sopenharmony_ci 9006f6ba60Sopenharmony_ci return (int)ret; 9106f6ba60Sopenharmony_ci} 9206f6ba60Sopenharmony_ci 9306f6ba60Sopenharmony_cistd::string FtraceFsOps::ReadTraceFile(const std::string& path) const 9406f6ba60Sopenharmony_ci{ 9506f6ba60Sopenharmony_ci return FileUtils::ReadFile(ftraceRoot_ + path); 9606f6ba60Sopenharmony_ci} 9706f6ba60Sopenharmony_ci 9806f6ba60Sopenharmony_cistd::string FtraceFsOps::GetPrintkFormats() const 9906f6ba60Sopenharmony_ci{ 10006f6ba60Sopenharmony_ci return ReadTraceFile("/printk_formats"); 10106f6ba60Sopenharmony_ci} 10206f6ba60Sopenharmony_ci 10306f6ba60Sopenharmony_cistd::string GetKptrRestrict() 10406f6ba60Sopenharmony_ci{ 10506f6ba60Sopenharmony_ci return FileUtils::ReadFile("/proc/sys/kernel/kptr_restrict"); 10606f6ba60Sopenharmony_ci} 10706f6ba60Sopenharmony_ci 10806f6ba60Sopenharmony_cibool SetKptrRestrict(const std::string& value) 10906f6ba60Sopenharmony_ci{ 11006f6ba60Sopenharmony_ci return FileUtils::WriteFile("/proc/sys/kernel/kptr_restrict", value) > 0; 11106f6ba60Sopenharmony_ci} 11206f6ba60Sopenharmony_ci 11306f6ba60Sopenharmony_cistd::string FtraceFsOps::GetKernelSymbols() const 11406f6ba60Sopenharmony_ci{ 11506f6ba60Sopenharmony_ci if (COMMON::IsUserMode()) { 11606f6ba60Sopenharmony_ci PROFILER_LOG_ERROR(LOG_CORE, "GetKernelSymbols failed, only root mode can access kernel symbols"); 11706f6ba60Sopenharmony_ci return ""; 11806f6ba60Sopenharmony_ci } 11906f6ba60Sopenharmony_ci std::string restrictValue = GetKptrRestrict(); 12006f6ba60Sopenharmony_ci CHECK_TRUE(restrictValue.size() > 0, "", "read kptr_restrict failed!"); 12106f6ba60Sopenharmony_ci 12206f6ba60Sopenharmony_ci bool valueChanged = false; 12306f6ba60Sopenharmony_ci if (std::stoi(restrictValue) == 0) { 12406f6ba60Sopenharmony_ci SetKptrRestrict("1"); 12506f6ba60Sopenharmony_ci valueChanged = true; 12606f6ba60Sopenharmony_ci } 12706f6ba60Sopenharmony_ci 12806f6ba60Sopenharmony_ci std::string result = FileUtils::ReadFile("/proc/kallsyms"); 12906f6ba60Sopenharmony_ci if (valueChanged) { 13006f6ba60Sopenharmony_ci SetKptrRestrict(restrictValue); 13106f6ba60Sopenharmony_ci } 13206f6ba60Sopenharmony_ci return result; 13306f6ba60Sopenharmony_ci} 13406f6ba60Sopenharmony_ci 13506f6ba60Sopenharmony_cibool FtraceFsOps::SetSavedCmdLinesSize(uint32_t size) 13606f6ba60Sopenharmony_ci{ 13706f6ba60Sopenharmony_ci std::string path = "/saved_cmdlines_size"; 13806f6ba60Sopenharmony_ci return WriteTraceFile(path, std::to_string(static_cast<int>(size))) > 0; 13906f6ba60Sopenharmony_ci} 14006f6ba60Sopenharmony_ci 14106f6ba60Sopenharmony_cistd::string FtraceFsOps::GetSavedCmdLines() const 14206f6ba60Sopenharmony_ci{ 14306f6ba60Sopenharmony_ci return ReadTraceFile("/saved_cmdlines"); 14406f6ba60Sopenharmony_ci} 14506f6ba60Sopenharmony_ci 14606f6ba60Sopenharmony_cistd::string FtraceFsOps::GetSavedTgids() const 14706f6ba60Sopenharmony_ci{ 14806f6ba60Sopenharmony_ci return ReadTraceFile("/saved_tgids"); 14906f6ba60Sopenharmony_ci} 15006f6ba60Sopenharmony_ci 15106f6ba60Sopenharmony_cistd::string FtraceFsOps::GetProcessComm(int pid) 15206f6ba60Sopenharmony_ci{ 15306f6ba60Sopenharmony_ci std::string path = "/proc/" + std::to_string(pid) + "/comm"; 15406f6ba60Sopenharmony_ci if (access(path.c_str(), R_OK) != 0) { 15506f6ba60Sopenharmony_ci return ""; 15606f6ba60Sopenharmony_ci } 15706f6ba60Sopenharmony_ci return FileUtils::ReadFile(path); 15806f6ba60Sopenharmony_ci} 15906f6ba60Sopenharmony_ci 16006f6ba60Sopenharmony_cistd::string FtraceFsOps::GetThreadComm(int pid, int tid) 16106f6ba60Sopenharmony_ci{ 16206f6ba60Sopenharmony_ci std::string path = "/proc/" + std::to_string(pid) + "/task/" + std::to_string(tid) + "/comm"; 16306f6ba60Sopenharmony_ci if (access(path.c_str(), R_OK) != 0) { 16406f6ba60Sopenharmony_ci return ""; 16506f6ba60Sopenharmony_ci } 16606f6ba60Sopenharmony_ci return FileUtils::ReadFile(path); 16706f6ba60Sopenharmony_ci} 16806f6ba60Sopenharmony_ci 16906f6ba60Sopenharmony_cistd::string FtraceFsOps::GetPerCpuStats(int cpu) const 17006f6ba60Sopenharmony_ci{ 17106f6ba60Sopenharmony_ci return ReadTraceFile("/per_cpu/cpu" + std::to_string(cpu) + "/stats"); 17206f6ba60Sopenharmony_ci} 17306f6ba60Sopenharmony_ci 17406f6ba60Sopenharmony_cistd::string FtraceFsOps::GetRawTracePath(int cpu) const 17506f6ba60Sopenharmony_ci{ 17606f6ba60Sopenharmony_ci return ftraceRoot_ + "/per_cpu/cpu" + std::to_string(cpu) + "/trace_pipe_raw"; 17706f6ba60Sopenharmony_ci} 17806f6ba60Sopenharmony_ci 17906f6ba60Sopenharmony_cistd::string FtraceFsOps::GetHmRawTracePath() const 18006f6ba60Sopenharmony_ci{ 18106f6ba60Sopenharmony_ci return ftraceRoot_ + "/trace_pipe_raw"; 18206f6ba60Sopenharmony_ci} 18306f6ba60Sopenharmony_ci 18406f6ba60Sopenharmony_cistd::string FtraceFsOps::GetPageHeaderFormat() const 18506f6ba60Sopenharmony_ci{ 18606f6ba60Sopenharmony_ci return ReadTraceFile("/events/header_page"); 18706f6ba60Sopenharmony_ci} 18806f6ba60Sopenharmony_ci 18906f6ba60Sopenharmony_cistd::string FtraceFsOps::GetEventDataFormat(const std::string& type, const std::string& name) const 19006f6ba60Sopenharmony_ci{ 19106f6ba60Sopenharmony_ci if (access((ftraceRoot_ + "/events/" + type + "/" + name + "/format").c_str(), R_OK) == 0) { 19206f6ba60Sopenharmony_ci return FileUtils::ReadFile(ftraceRoot_ + "/events/" + type + "/" + name + "/format"); 19306f6ba60Sopenharmony_ci } else { 19406f6ba60Sopenharmony_ci return ""; 19506f6ba60Sopenharmony_ci } 19606f6ba60Sopenharmony_ci} 19706f6ba60Sopenharmony_ci 19806f6ba60Sopenharmony_cibool FtraceFsOps::ClearTraceBuffer() 19906f6ba60Sopenharmony_ci{ 20006f6ba60Sopenharmony_ci char realPath[PATH_MAX + 1] = {0}; 20106f6ba60Sopenharmony_ci 20206f6ba60Sopenharmony_ci std::string path = ftraceRoot_ + "/trace"; 20306f6ba60Sopenharmony_ci 20406f6ba60Sopenharmony_ci CHECK_TRUE((path.length() < PATH_MAX) && (realpath(path.c_str(), realPath) != nullptr), false, 20506f6ba60Sopenharmony_ci "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno); 20606f6ba60Sopenharmony_ci int fd = open(realPath, O_TRUNC | O_RDWR); 20706f6ba60Sopenharmony_ci CHECK_TRUE(fd >= 0, false, "open %s failed!", realPath); 20806f6ba60Sopenharmony_ci return close(fd) == 0; 20906f6ba60Sopenharmony_ci} 21006f6ba60Sopenharmony_ci 21106f6ba60Sopenharmony_cibool FtraceFsOps::SetRecordCmdOption(bool enable) 21206f6ba60Sopenharmony_ci{ 21306f6ba60Sopenharmony_ci std::string path = "/options/record-cmd"; 21406f6ba60Sopenharmony_ci return WriteTraceFile(path, std::to_string(static_cast<int>(enable))) > 0; 21506f6ba60Sopenharmony_ci} 21606f6ba60Sopenharmony_ci 21706f6ba60Sopenharmony_cibool FtraceFsOps::SetRecordTgidOption(bool enable) 21806f6ba60Sopenharmony_ci{ 21906f6ba60Sopenharmony_ci std::string path = "/options/record-tgid"; 22006f6ba60Sopenharmony_ci return WriteTraceFile(path, std::to_string(static_cast<int>(enable))) > 0; 22106f6ba60Sopenharmony_ci} 22206f6ba60Sopenharmony_ci 22306f6ba60Sopenharmony_cibool FtraceFsOps::SetBufferSizeKb(int sizeKb) 22406f6ba60Sopenharmony_ci{ 22506f6ba60Sopenharmony_ci std::string path = "/buffer_size_kb"; 22606f6ba60Sopenharmony_ci return WriteTraceFile(path, std::to_string(sizeKb)) > 0; 22706f6ba60Sopenharmony_ci} 22806f6ba60Sopenharmony_ci 22906f6ba60Sopenharmony_cibool FtraceFsOps::SetTraceClock(const std::string& clock) 23006f6ba60Sopenharmony_ci{ 23106f6ba60Sopenharmony_ci std::string path = "/trace_clock"; 23206f6ba60Sopenharmony_ci return WriteTraceFile(path, clock) > 0; 23306f6ba60Sopenharmony_ci} 23406f6ba60Sopenharmony_ci 23506f6ba60Sopenharmony_cistd::string FtraceFsOps::GetTraceClock() 23606f6ba60Sopenharmony_ci{ 23706f6ba60Sopenharmony_ci std::string path = ftraceRoot_ + "/trace_clock"; 23806f6ba60Sopenharmony_ci 23906f6ba60Sopenharmony_ci std::string value = FileUtils::ReadFile(path); 24006f6ba60Sopenharmony_ci auto pos = value.find('['); 24106f6ba60Sopenharmony_ci CHECK_TRUE(pos != std::string::npos, "", "find [ in %s failed!", path.c_str()); 24206f6ba60Sopenharmony_ci pos++; 24306f6ba60Sopenharmony_ci 24406f6ba60Sopenharmony_ci auto rpos = value.find(']', pos); 24506f6ba60Sopenharmony_ci CHECK_TRUE(rpos != std::string::npos, "", "find ] in %s failed!", path.c_str()); 24606f6ba60Sopenharmony_ci return value.substr(pos, rpos - pos); 24706f6ba60Sopenharmony_ci} 24806f6ba60Sopenharmony_ci 24906f6ba60Sopenharmony_cistatic void AddPlatformEvents(std::set<std::pair<std::string, std::string>> &eventSet, 25006f6ba60Sopenharmony_ci const std::string &eventsPath) 25106f6ba60Sopenharmony_ci{ 25206f6ba60Sopenharmony_ci for (auto& type : FileUtils::ListDir(eventsPath)) { 25306f6ba60Sopenharmony_ci struct stat st = {}; 25406f6ba60Sopenharmony_ci std::string typePath = eventsPath + "/" + type; 25506f6ba60Sopenharmony_ci if (stat(typePath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) { 25606f6ba60Sopenharmony_ci continue; 25706f6ba60Sopenharmony_ci } 25806f6ba60Sopenharmony_ci for (auto& name : FileUtils::ListDir(typePath)) { 25906f6ba60Sopenharmony_ci struct stat st = {}; 26006f6ba60Sopenharmony_ci std::string namePath = typePath + "/" + name; 26106f6ba60Sopenharmony_ci if (stat(namePath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) { 26206f6ba60Sopenharmony_ci continue; 26306f6ba60Sopenharmony_ci } 26406f6ba60Sopenharmony_ci eventSet.insert(std::make_pair(type, name)); 26506f6ba60Sopenharmony_ci } 26606f6ba60Sopenharmony_ci } 26706f6ba60Sopenharmony_ci} 26806f6ba60Sopenharmony_ci 26906f6ba60Sopenharmony_cistd::vector<std::pair<std::string, std::string>> FtraceFsOps::GetPlatformEvents() 27006f6ba60Sopenharmony_ci{ 27106f6ba60Sopenharmony_ci std::set<std::pair<std::string, std::string>> eventSet; 27206f6ba60Sopenharmony_ci if (IsHmKernel()) { 27306f6ba60Sopenharmony_ci AddPlatformEvents(eventSet, ftraceRoot_ + "/events"); 27406f6ba60Sopenharmony_ci } 27506f6ba60Sopenharmony_ci AddPlatformEvents(eventSet, ftraceRoot_ + "/events"); 27606f6ba60Sopenharmony_ci PROFILER_LOG_INFO(LOG_CORE, "get platform event formats done, types: %zu!", eventSet.size()); 27706f6ba60Sopenharmony_ci return {eventSet.begin(), eventSet.end()}; 27806f6ba60Sopenharmony_ci} 27906f6ba60Sopenharmony_ci 28006f6ba60Sopenharmony_cibool FtraceFsOps::AppendSetEvent(const std::string& type, const std::string& name) 28106f6ba60Sopenharmony_ci{ 28206f6ba60Sopenharmony_ci std::string path = "/set_event"; 28306f6ba60Sopenharmony_ci return WriteTraceFile(path, type + ":" + name + "\n", O_WRONLY | O_APPEND) > 0; 28406f6ba60Sopenharmony_ci} 28506f6ba60Sopenharmony_ci 28606f6ba60Sopenharmony_cibool FtraceFsOps::ClearSetEvent() 28706f6ba60Sopenharmony_ci{ 28806f6ba60Sopenharmony_ci return WriteTraceFile("/set_event", "\n", O_WRONLY | O_TRUNC) > 0; 28906f6ba60Sopenharmony_ci} 29006f6ba60Sopenharmony_ci 29106f6ba60Sopenharmony_cibool FtraceFsOps::EnableEvent(const std::string& type, const std::string& name) 29206f6ba60Sopenharmony_ci{ 29306f6ba60Sopenharmony_ci std::string enablePath = "/events/" + type + "/" + name + "/enable"; 29406f6ba60Sopenharmony_ci return WriteTraceFile(enablePath, "1") > 0; 29506f6ba60Sopenharmony_ci} 29606f6ba60Sopenharmony_ci 29706f6ba60Sopenharmony_cibool FtraceFsOps::DisableEvent(const std::string& type, const std::string& name) 29806f6ba60Sopenharmony_ci{ 29906f6ba60Sopenharmony_ci std::string enablePath = "/events/" + type + "/" + name + "/enable"; 30006f6ba60Sopenharmony_ci return WriteTraceFile(enablePath, "0") > 0; 30106f6ba60Sopenharmony_ci} 30206f6ba60Sopenharmony_ci 30306f6ba60Sopenharmony_cibool FtraceFsOps::DisableCategories(const std::string& categories) 30406f6ba60Sopenharmony_ci{ 30506f6ba60Sopenharmony_ci std::string enablePath = "/events/" + categories + "/enable"; 30606f6ba60Sopenharmony_ci return WriteTraceFile(enablePath, "0") > 0; 30706f6ba60Sopenharmony_ci} 30806f6ba60Sopenharmony_ci 30906f6ba60Sopenharmony_cibool FtraceFsOps::EnableTracing() 31006f6ba60Sopenharmony_ci{ 31106f6ba60Sopenharmony_ci std::string tracingOn = "/tracing_on"; 31206f6ba60Sopenharmony_ci return WriteTraceFile(tracingOn, "1") > 0; 31306f6ba60Sopenharmony_ci} 31406f6ba60Sopenharmony_ci 31506f6ba60Sopenharmony_cibool FtraceFsOps::DisableTracing() 31606f6ba60Sopenharmony_ci{ 31706f6ba60Sopenharmony_ci std::string tracingOn = "/tracing_on"; 31806f6ba60Sopenharmony_ci return WriteTraceFile(tracingOn, "0") > 0; 31906f6ba60Sopenharmony_ci} 32006f6ba60Sopenharmony_ciFTRACE_NS_END 321