1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "ftrace_fs_ops.h"
16
17 #include <fcntl.h>
18 #include <set>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <unistd.h>
22
23 #include "file_utils.h"
24 #include "logging.h"
25
26 FTRACE_NS_BEGIN
GetInstance()27 FtraceFsOps& FtraceFsOps::GetInstance()
28 {
29 static FtraceFsOps instance;
30 return instance;
31 }
32
FtraceFsOps()33 FtraceFsOps::FtraceFsOps() : ftraceRoot_(GetFtraceRoot())
34 {
35 HILOG_INFO(LOG_CORE, "FtraceFsOps create!");
36 }
37
~FtraceFsOps()38 FtraceFsOps::~FtraceFsOps()
39 {
40 HILOG_INFO(LOG_CORE, "FtraceFsOps destroy!");
41 }
42
GetFtraceRoot()43 std::string FtraceFsOps::GetFtraceRoot()
44 {
45 std::vector<std::string> testRootPath = {"/sys/kernel/tracing", "/sys/kernel/debug/tracing"};
46 for (auto iter = testRootPath.begin(); iter != testRootPath.end(); ++iter) {
47 auto path = *iter + "/events";
48 struct stat s;
49 lstat(path.c_str(), &s);
50 if (S_ISDIR(s.st_mode)) {
51 return *iter;
52 }
53 }
54 return "";
55 }
56
GetPrintkFormats() const57 std::string FtraceFsOps::GetPrintkFormats() const
58 {
59 return FileUtils::ReadFile(ftraceRoot_ + "/printk_formats");
60 }
61
GetKptrRestrict()62 std::string GetKptrRestrict()
63 {
64 return FileUtils::ReadFile("/proc/sys/kernel/kptr_restrict");
65 }
66
SetKptrRestrict(const std::string & value)67 bool SetKptrRestrict(const std::string& value)
68 {
69 return FileUtils::WriteFile("/proc/sys/kernel/kptr_restrict", value) > 0;
70 }
71
GetKernelSymbols() const72 std::string FtraceFsOps::GetKernelSymbols() const
73 {
74 std::string restrictValue = GetKptrRestrict();
75 CHECK_TRUE(restrictValue.size() > 0, "", "read kptr_restrict failed!");
76
77 bool valueChanged = false;
78 if (std::stoi(restrictValue) == 0) {
79 SetKptrRestrict("1");
80 valueChanged = true;
81 }
82
83 std::string result = FileUtils::ReadFile("/proc/kallsyms");
84 if (valueChanged) {
85 SetKptrRestrict(restrictValue);
86 }
87 return result;
88 }
89
GetSavedCmdLines() const90 std::string FtraceFsOps::GetSavedCmdLines() const
91 {
92 return FileUtils::ReadFile(ftraceRoot_ + "/saved_cmdlines");
93 }
94
GetSavedTgids() const95 std::string FtraceFsOps::GetSavedTgids() const
96 {
97 return FileUtils::ReadFile(ftraceRoot_ + "/saved_tgids");
98 }
99
GetProcessComm(int pid)100 std::string FtraceFsOps::GetProcessComm(int pid)
101 {
102 std::string path = "/proc/" + std::to_string(pid) + "/comm";
103 if (access(path.c_str(), R_OK) != 0) {
104 return "";
105 }
106 return FileUtils::ReadFile(path);
107 }
108
GetThreadComm(int pid,int tid)109 std::string FtraceFsOps::GetThreadComm(int pid, int tid)
110 {
111 std::string path = "/proc/" + std::to_string(pid) + "/task/" + std::to_string(tid) + "/comm";
112 if (access(path.c_str(), R_OK) != 0) {
113 return "";
114 }
115 return FileUtils::ReadFile(path);
116 }
117
GetPerCpuStats(int cpu) const118 std::string FtraceFsOps::GetPerCpuStats(int cpu) const
119 {
120 return FileUtils::ReadFile(ftraceRoot_ + "/per_cpu/cpu" + std::to_string(cpu) + "/stats");
121 }
122
GetRawTracePath(int cpu) const123 std::string FtraceFsOps::GetRawTracePath(int cpu) const
124 {
125 return ftraceRoot_ + "/per_cpu/cpu" + std::to_string(cpu) + "/trace_pipe_raw";
126 }
127
GetPageHeaderFormat() const128 std::string FtraceFsOps::GetPageHeaderFormat() const
129 {
130 return FileUtils::ReadFile(ftraceRoot_ + "/events/header_page");
131 }
132
GetEventDataFormat(const std::string & type,const std::string & name) const133 std::string FtraceFsOps::GetEventDataFormat(const std::string& type, const std::string& name) const
134 {
135 return FileUtils::ReadFile(ftraceRoot_ + "/events/" + type + "/" + name + "/format");
136 }
137
ClearTraceBuffer()138 bool FtraceFsOps::ClearTraceBuffer()
139 {
140 char realPath[PATH_MAX + 1] = {0};
141
142 std::string path = ftraceRoot_ + "/trace";
143 if ((path.length() >= PATH_MAX) || (realpath(path.c_str(), realPath) == nullptr)) {
144 HILOG_ERROR(LOG_CORE, "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
145 return false;
146 }
147 int fd = open(realPath, O_TRUNC);
148 CHECK_TRUE(fd >= 0, false, "open %s failed!", realPath);
149 return close(fd) == 0;
150 }
151
SetRecordCmdOption(bool enable)152 bool FtraceFsOps::SetRecordCmdOption(bool enable)
153 {
154 std::string path = ftraceRoot_ + "/options/record-cmd";
155 return FileUtils::WriteFile(path, std::to_string(static_cast<int>(enable))) > 0;
156 }
157
SetRecordTgidOption(bool enable)158 bool FtraceFsOps::SetRecordTgidOption(bool enable)
159 {
160 std::string path = ftraceRoot_ + "/options/record-tgid";
161 return FileUtils::WriteFile(path, std::to_string(static_cast<int>(enable))) > 0;
162 }
163
SetBufferSizeKb(int sizeKb)164 bool FtraceFsOps::SetBufferSizeKb(int sizeKb)
165 {
166 std::string path = ftraceRoot_ + "/buffer_size_kb";
167 return FileUtils::WriteFile(path, std::to_string(sizeKb)) > 0;
168 }
169
SetTraceClock(const std::string & clock)170 bool FtraceFsOps::SetTraceClock(const std::string& clock)
171 {
172 std::string path = ftraceRoot_ + "/trace_clock";
173 return FileUtils::WriteFile(path, clock) > 0;
174 }
175
GetTraceClock()176 std::string FtraceFsOps::GetTraceClock()
177 {
178 std::string path = ftraceRoot_ + "/trace_clock";
179 std::string value = FileUtils::ReadFile(path);
180 auto pos = value.find('[');
181 CHECK_TRUE(pos != std::string::npos, "", "find [ in %s failed!", path.c_str());
182 pos++;
183
184 auto rpos = value.find(']', pos);
185 CHECK_TRUE(rpos != std::string::npos, "", "find ] in %s failed!", path.c_str());
186 return value.substr(pos, rpos - pos);
187 }
188
GetPlatformEvents()189 std::vector<std::pair<std::string, std::string>> FtraceFsOps::GetPlatformEvents()
190 {
191 std::set<std::pair<std::string, std::string>> eventSet;
192 std::string eventsPath = ftraceRoot_ + "/events";
193 for (auto& type : FileUtils::ListDir(eventsPath)) {
194 struct stat st = {};
195 std::string typePath = eventsPath + "/" + type;
196 if (stat(typePath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
197 continue;
198 }
199 for (auto& name : FileUtils::ListDir(typePath)) {
200 struct stat st = {};
201 std::string namePath = typePath + "/" + name;
202 if (stat(namePath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
203 continue;
204 }
205 eventSet.insert(std::make_pair(type, name));
206 }
207 }
208 HILOG_INFO(LOG_CORE, "get platform event formats done, types: %zu!", eventSet.size());
209 return {eventSet.begin(), eventSet.end()};
210 }
211
AppendSetEvent(const std::string & type,const std::string & name)212 bool FtraceFsOps::AppendSetEvent(const std::string& type, const std::string& name)
213 {
214 std::string path = ftraceRoot_ + "/set_event";
215 return FileUtils::WriteFile(path, type + ":" + name + "\n", O_WRONLY | O_APPEND) > 0;
216 }
217
ClearSetEvent()218 bool FtraceFsOps::ClearSetEvent()
219 {
220 return FileUtils::WriteFile(ftraceRoot_ + "/set_event", "\n", O_WRONLY | O_TRUNC) > 0;
221 }
222
EnableEvent(const std::string & type,const std::string & name)223 bool FtraceFsOps::EnableEvent(const std::string& type, const std::string& name)
224 {
225 std::string enablePath = ftraceRoot_ + "/events/" + type + "/" + name + "/enable";
226 return FileUtils::WriteFile(enablePath, "1") > 0;
227 }
228
DisableEvent(const std::string & type,const std::string & name)229 bool FtraceFsOps::DisableEvent(const std::string& type, const std::string& name)
230 {
231 std::string enablePath = ftraceRoot_ + "/events/" + type + "/" + name + "/enable";
232 return FileUtils::WriteFile(enablePath, "0") > 0;
233 }
234
DisableCategories(const std::string & categories)235 bool FtraceFsOps::DisableCategories(const std::string& categories)
236 {
237 std::string enablePath = ftraceRoot_ + "/events/" + categories + "/enable";
238 return FileUtils::WriteFile(enablePath, "0") > 0;
239 }
240
EnableTracing()241 bool FtraceFsOps::EnableTracing()
242 {
243 std::string tracingOn = ftraceRoot_ + "/tracing_on";
244 return FileUtils::WriteFile(tracingOn, "1") > 0;
245 }
246
DisableTracing()247 bool FtraceFsOps::DisableTracing()
248 {
249 std::string tracingOn = ftraceRoot_ + "/tracing_on";
250 return FileUtils::WriteFile(tracingOn, "0") > 0;
251 }
252 FTRACE_NS_END
253