• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved.
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()), hmTraceDir_(GetHmTraceDir())
34 {
35     PROFILER_LOG_INFO(LOG_CORE, "FtraceFsOps create!");
36 }
37 
~FtraceFsOps()38 FtraceFsOps::~FtraceFsOps()
39 {
40     PROFILER_LOG_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 
GetHmTraceDir()57 std::string FtraceFsOps::GetHmTraceDir()
58 {
59     if (access((ftraceRoot_ + "/hongmeng").c_str(), F_OK) == 0) {
60         return "/hongmeng";
61     } else {
62         return "";
63     }
64 }
65 
WriteTraceFile(const std::string & path,const std::string & content)66 int FtraceFsOps::WriteTraceFile(const std::string& path, const std::string& content)
67 {
68     bool ret = false;
69     if (access((ftraceRoot_ + hmTraceDir_ + path).c_str(), W_OK) == 0) {
70         if (FileUtils::WriteFile(ftraceRoot_ + hmTraceDir_ + path, content) > 0) {
71             ret = true;
72         }
73     }
74     if (access((ftraceRoot_ + path).c_str(), W_OK) == 0) {
75         if (FileUtils::WriteFile(ftraceRoot_ + path, content) > 0) {
76             ret = true;
77         }
78     }
79 
80     return (int)ret;
81 }
82 
WriteTraceFile(const std::string & path,const std::string & content,int flags)83 int FtraceFsOps::WriteTraceFile(const std::string& path, const std::string& content, int flags)
84 {
85     bool ret = false;
86     if (access((ftraceRoot_ + hmTraceDir_ + path).c_str(), W_OK) == 0) {
87         if (FileUtils::WriteFile(ftraceRoot_ + hmTraceDir_ + path, content, flags) > 0) {
88             ret = true;
89         }
90     }
91     if (access((ftraceRoot_ + path).c_str(), W_OK) == 0) {
92         if (FileUtils::WriteFile(ftraceRoot_ + path, content, flags) > 0) {
93             ret = true;
94         }
95     }
96 
97     return (int)ret;
98 }
99 
ReadTraceFile(const std::string & path) const100 std::string FtraceFsOps::ReadTraceFile(const std::string& path) const
101 {
102     if (access((ftraceRoot_ + hmTraceDir_ + path).c_str(), R_OK) == 0) {
103         return FileUtils::ReadFile(ftraceRoot_ + hmTraceDir_ + path);
104     } else {
105         return FileUtils::ReadFile(ftraceRoot_ + path);
106     }
107 }
108 
GetPrintkFormats() const109 std::string FtraceFsOps::GetPrintkFormats() const
110 {
111     return ReadTraceFile("/printk_formats");
112 }
113 
GetKptrRestrict()114 std::string GetKptrRestrict()
115 {
116     return FileUtils::ReadFile("/proc/sys/kernel/kptr_restrict");
117 }
118 
SetKptrRestrict(const std::string & value)119 bool SetKptrRestrict(const std::string& value)
120 {
121     return FileUtils::WriteFile("/proc/sys/kernel/kptr_restrict", value) > 0;
122 }
123 
GetKernelSymbols() const124 std::string FtraceFsOps::GetKernelSymbols() const
125 {
126     std::string restrictValue = GetKptrRestrict();
127     CHECK_TRUE(restrictValue.size() > 0, "", "read kptr_restrict failed!");
128 
129     bool valueChanged = false;
130     if (std::stoi(restrictValue) == 0) {
131         SetKptrRestrict("1");
132         valueChanged = true;
133     }
134 
135     std::string result = FileUtils::ReadFile("/proc/kallsyms");
136     if (valueChanged) {
137         SetKptrRestrict(restrictValue);
138     }
139     return result;
140 }
141 
SetSavedCmdLinesSize(uint32_t size)142 bool FtraceFsOps::SetSavedCmdLinesSize(uint32_t size)
143 {
144     std::string path = "/saved_cmdlines_size";
145     return WriteTraceFile(path, std::to_string(static_cast<int>(size))) > 0;
146 }
147 
GetSavedCmdLines() const148 std::string FtraceFsOps::GetSavedCmdLines() const
149 {
150     return ReadTraceFile("/saved_cmdlines");
151 }
152 
GetSavedTgids() const153 std::string FtraceFsOps::GetSavedTgids() const
154 {
155     return ReadTraceFile("/saved_tgids");
156 }
157 
GetProcessComm(int pid)158 std::string FtraceFsOps::GetProcessComm(int pid)
159 {
160     std::string path = "/proc/" + std::to_string(pid) + "/comm";
161     if (access(path.c_str(), R_OK) != 0) {
162         return "";
163     }
164     return FileUtils::ReadFile(path);
165 }
166 
GetThreadComm(int pid,int tid)167 std::string FtraceFsOps::GetThreadComm(int pid, int tid)
168 {
169     std::string path = "/proc/" + std::to_string(pid) + "/task/" + std::to_string(tid) + "/comm";
170     if (access(path.c_str(), R_OK) != 0) {
171         return "";
172     }
173     return FileUtils::ReadFile(path);
174 }
175 
GetPerCpuStats(int cpu) const176 std::string FtraceFsOps::GetPerCpuStats(int cpu) const
177 {
178     return ReadTraceFile("/per_cpu/cpu" + std::to_string(cpu) + "/stats");
179 }
180 
GetRawTracePath(int cpu) const181 std::string FtraceFsOps::GetRawTracePath(int cpu) const
182 {
183     return ftraceRoot_ + "/per_cpu/cpu" + std::to_string(cpu) + "/trace_pipe_raw";
184 }
185 
GetHmRawTracePath() const186 std::string FtraceFsOps::GetHmRawTracePath() const
187 {
188     return ftraceRoot_ + hmTraceDir_ + "/trace_pipe_raw";
189 }
190 
GetPageHeaderFormat() const191 std::string FtraceFsOps::GetPageHeaderFormat() const
192 {
193     return ReadTraceFile("/events/header_page");
194 }
195 
GetEventDataFormat(const std::string & type,const std::string & name) const196 std::string FtraceFsOps::GetEventDataFormat(const std::string& type, const std::string& name) const
197 {
198     if (access((ftraceRoot_ + "/events/" + type + "/" + name + "/format").c_str(), R_OK) == 0) {
199         return FileUtils::ReadFile(ftraceRoot_ + "/events/" + type + "/" + name + "/format");
200     } else {
201         return "";
202     }
203 }
204 
HmGetEventDataFormat(const std::string & type,const std::string & name) const205 std::string FtraceFsOps::HmGetEventDataFormat(const std::string& type, const std::string& name) const
206 {
207     if (access((ftraceRoot_ + "/hongmeng/events/" + type + "/" + name + "/format").c_str(), R_OK) == 0) {
208         return FileUtils::ReadFile(ftraceRoot_ + "/hongmeng/events/" + type + "/" + name + "/format");
209     } else {
210         return "";
211     }
212 }
213 
ClearTraceBuffer()214 bool FtraceFsOps::ClearTraceBuffer()
215 {
216     char realPath[PATH_MAX + 1] = {0};
217 
218     std::string path;
219     if (access((ftraceRoot_ + hmTraceDir_ + "/trace").c_str(), F_OK) == 0) {
220         path = ftraceRoot_ + hmTraceDir_ + "/trace";
221     } else {
222         path = ftraceRoot_ + "/trace";
223     }
224 
225     CHECK_TRUE((path.length() < PATH_MAX) && (realpath(path.c_str(), realPath) != nullptr), false,
226                "%s:path is invalid: %s, errno=%d", __func__, path.c_str(), errno);
227     int fd = open(realPath, O_TRUNC | O_RDWR);
228     CHECK_TRUE(fd >= 0, false, "open %s failed!", realPath);
229     return close(fd) == 0;
230 }
231 
SetRecordCmdOption(bool enable)232 bool FtraceFsOps::SetRecordCmdOption(bool enable)
233 {
234     std::string path = "/options/record-cmd";
235     return WriteTraceFile(path, std::to_string(static_cast<int>(enable))) > 0;
236 }
237 
SetRecordTgidOption(bool enable)238 bool FtraceFsOps::SetRecordTgidOption(bool enable)
239 {
240     std::string path = "/options/record-tgid";
241     return WriteTraceFile(path, std::to_string(static_cast<int>(enable))) > 0;
242 }
243 
SetBufferSizeKb(int sizeKb)244 bool FtraceFsOps::SetBufferSizeKb(int sizeKb)
245 {
246     std::string path = "/buffer_size_kb";
247     return WriteTraceFile(path, std::to_string(sizeKb)) > 0;
248 }
249 
SetTraceClock(const std::string & clock)250 bool FtraceFsOps::SetTraceClock(const std::string& clock)
251 {
252     std::string path = "/trace_clock";
253     return WriteTraceFile(path, clock) > 0;
254 }
255 
GetTraceClock()256 std::string FtraceFsOps::GetTraceClock()
257 {
258     std::string path;
259     if (access((ftraceRoot_ + hmTraceDir_ + "/trace_clock").c_str(), F_OK) == 0) {
260         path = ftraceRoot_ + hmTraceDir_ + "/trace_clock";
261     } else {
262         path = ftraceRoot_ + "/trace_clock";
263     }
264 
265     std::string value = FileUtils::ReadFile(path);
266     auto pos = value.find('[');
267     CHECK_TRUE(pos != std::string::npos, "", "find [ in %s failed!", path.c_str());
268     pos++;
269 
270     auto rpos = value.find(']', pos);
271     CHECK_TRUE(rpos != std::string::npos, "", "find ] in %s failed!", path.c_str());
272     return value.substr(pos, rpos - pos);
273 }
274 
AddPlatformEvents(std::set<std::pair<std::string,std::string>> & eventSet,const std::string & eventsPath)275 static void AddPlatformEvents(std::set<std::pair<std::string, std::string>> &eventSet,
276     const std::string &eventsPath)
277 {
278     for (auto& type : FileUtils::ListDir(eventsPath)) {
279         struct stat st = {};
280         std::string typePath = eventsPath + "/" + type;
281         if (stat(typePath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
282             continue;
283         }
284         for (auto& name : FileUtils::ListDir(typePath)) {
285             struct stat st = {};
286             std::string namePath = typePath + "/" + name;
287             if (stat(namePath.c_str(), &st) != 0 || !S_ISDIR(st.st_mode)) {
288                 continue;
289             }
290             eventSet.insert(std::make_pair(type, name));
291         }
292     }
293 }
294 
GetPlatformEvents()295 std::vector<std::pair<std::string, std::string>> FtraceFsOps::GetPlatformEvents()
296 {
297     std::set<std::pair<std::string, std::string>> eventSet;
298     if (hmTraceDir_ != "") {
299         AddPlatformEvents(eventSet, ftraceRoot_ + hmTraceDir_ + "/events");
300     }
301     AddPlatformEvents(eventSet, ftraceRoot_ + "/events");
302     PROFILER_LOG_INFO(LOG_CORE, "get platform event formats done, types: %zu!", eventSet.size());
303     return {eventSet.begin(), eventSet.end()};
304 }
305 
AppendSetEvent(const std::string & type,const std::string & name)306 bool FtraceFsOps::AppendSetEvent(const std::string& type, const std::string& name)
307 {
308     std::string path = "/set_event";
309     return WriteTraceFile(path, type + ":" + name + "\n", O_WRONLY | O_APPEND) > 0;
310 }
311 
ClearSetEvent()312 bool FtraceFsOps::ClearSetEvent()
313 {
314     return WriteTraceFile("/set_event", "\n", O_WRONLY | O_TRUNC) > 0;
315 }
316 
EnableEvent(const std::string & type,const std::string & name)317 bool FtraceFsOps::EnableEvent(const std::string& type, const std::string& name)
318 {
319     std::string enablePath = "/events/" + type + "/" + name + "/enable";
320     return WriteTraceFile(enablePath, "1") > 0;
321 }
322 
DisableEvent(const std::string & type,const std::string & name)323 bool FtraceFsOps::DisableEvent(const std::string& type, const std::string& name)
324 {
325     std::string enablePath = "/events/" + type + "/" + name + "/enable";
326     return WriteTraceFile(enablePath, "0") > 0;
327 }
328 
DisableCategories(const std::string & categories)329 bool FtraceFsOps::DisableCategories(const std::string& categories)
330 {
331     std::string enablePath = "/events/" + categories + "/enable";
332     return WriteTraceFile(enablePath, "0") > 0;
333 }
334 
EnableTracing()335 bool FtraceFsOps::EnableTracing()
336 {
337     std::string tracingOn = "/tracing_on";
338     return WriteTraceFile(tracingOn, "1") > 0;
339 }
340 
DisableTracing()341 bool FtraceFsOps::DisableTracing()
342 {
343     std::string tracingOn = "/tracing_on";
344     return WriteTraceFile(tracingOn, "0") > 0;
345 }
346 FTRACE_NS_END
347