• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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