1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 #include <csignal>
16 #include <mutex>
17 #include <array>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <sys/wait.h>
21 #include <parameters.h>
22
23 #include "common.h"
24 #include "hiebpf_plugin_config.pb.h"
25 #include "logging.h"
26 #include "plugin_module_api.h"
27 #include "trace_file_writer.h"
28
29 namespace {
30 constexpr uint32_t MAX_BUFFER_SIZE = 4 * 1024 * 1024;
31 std::mutex g_taskMutex;
32 constexpr int32_t RET_OK = 0;
33 constexpr int32_t RET_ERR = -1;
34 bool g_releaseResources = false;
35 HiebpfConfig g_config;
36 std::shared_ptr<TraceFileWriter> g_splitTraceWriter {nullptr};
37
RunCmd(std::string & cmd)38 void RunCmd(std::string& cmd)
39 {
40 std::string debugMode = "0";
41 debugMode = OHOS::system::GetParameter("const.debuggable", debugMode);
42 if (debugMode == "1") {
43 std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
44 if (pipe == nullptr) {
45 PROFILER_LOG_ERROR(LOG_CORE, "HiebpfPlugin::RunCmd: create popen FAILED!");
46 return;
47 }
48 constexpr uint32_t readBufferSize = 4096;
49 std::array<char, readBufferSize> buffer;
50 std::string result;
51 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
52 result += buffer.data();
53 }
54 PROFILER_LOG_INFO(LOG_CORE, "HiebpfPlugin::run command result: %s", result.c_str());
55 }
56 }
57 } // namespace
58
HiebpfSessionStart(const uint8_t * configData,uint32_t configSize)59 static int32_t HiebpfSessionStart(const uint8_t* configData, uint32_t configSize)
60 {
61 std::lock_guard<std::mutex> guard(g_taskMutex);
62 CHECK_TRUE(!g_releaseResources, 0, "%s: hiebpf released resources, return", __func__);
63 PROFILER_LOG_DEBUG(LOG_CORE, "enter");
64 if (configData == nullptr || configSize < 0) {
65 PROFILER_LOG_ERROR(LOG_CORE, "Parameter error");
66 return RET_ERR;
67 }
68
69 CHECK_TRUE(g_config.ParseFromArray(configData, configSize) > 0, RET_ERR, "Parameter parsing failed");
70
71 if (!g_config.split_outfile_name().empty()) {
72 g_splitTraceWriter = std::make_shared<TraceFileWriter>(g_config.split_outfile_name());
73 g_splitTraceWriter->WriteStandalonePluginData(
74 std::string(g_pluginModule.name) + "_config",
75 std::string(reinterpret_cast<const char *>(configData),
76 configSize));
77 g_splitTraceWriter->SetTimeSource();
78 }
79
80 size_t defaultSize = sizeof(g_pluginModule.outFileName);
81 CHECK_TRUE(sizeof(g_config.outfile_name().c_str()) <= defaultSize - 1, RET_ERR,
82 "The out file path more than %zu bytes", defaultSize);
83 int32_t ret = strncpy_s(g_pluginModule.outFileName, defaultSize, g_config.outfile_name().c_str(), defaultSize - 1);
84 CHECK_TRUE(ret == EOK, RET_ERR, "strncpy_s error! outfile is %s", g_config.outfile_name().c_str());
85 std::string cmd = g_config.cmd_line();
86 cmd += " --start true --output_file " + g_config.outfile_name();
87 RunCmd(cmd);
88 PROFILER_LOG_DEBUG(LOG_CORE, "leave");
89 return RET_OK;
90 }
91
HiebpfSessionStop()92 static int32_t HiebpfSessionStop()
93 {
94 std::lock_guard<std::mutex> guard(g_taskMutex);
95 CHECK_TRUE(!g_releaseResources, 0, "%s: hiebpf released resources, return", __func__);
96 PROFILER_LOG_DEBUG(LOG_CORE, "enter");
97
98 if (!g_config.split_outfile_name().empty()) {
99 CHECK_NOTNULL(g_splitTraceWriter, -1, "%s: writer is nullptr, SetDurationTime failed", __func__);
100 g_splitTraceWriter->SetDurationTime();
101 }
102
103 std::string stop = "hiebpf --stop true";
104 RunCmd(stop);
105
106 if (!g_config.split_outfile_name().empty()) { // write split file.
107 CHECK_NOTNULL(g_splitTraceWriter, -1, "%s: writer is nullptr, WriteStandaloneFile failed", __func__);
108 g_splitTraceWriter->WriteStandalonePluginFile(std::string(g_pluginModule.outFileName),
109 std::string(g_pluginModule.name), std::string(g_pluginModule.version), DataType::STANDALONE_DATA);
110 g_splitTraceWriter->Finish();
111 g_splitTraceWriter.reset();
112 g_splitTraceWriter = nullptr;
113 }
114 PROFILER_LOG_DEBUG(LOG_CORE, "leave");
115 return RET_OK;
116 }
117
118 static PluginModuleCallbacks g_callbacks = {
119 .onPluginSessionStart = HiebpfSessionStart,
120 .onPluginReportResult = nullptr,
121 .onPluginSessionStop = HiebpfSessionStop,
122 .onRegisterWriterStruct = nullptr,
123 };
124
125 EXPORT_API PluginModuleStruct g_pluginModule = {
126 .callbacks = &g_callbacks,
127 .name = "hiebpf-plugin",
128 .resultBufferSizeHint = MAX_BUFFER_SIZE,
129 .isStandaloneFileData = true,
130 .outFileName = "/data/local/tmp/hiebpf.data",
131 };
132