106f6ba60Sopenharmony_ci/* 206f6ba60Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 1606f6ba60Sopenharmony_ci#include <cerrno> 1706f6ba60Sopenharmony_ci#include <chrono> 1806f6ba60Sopenharmony_ci#include <csignal> 1906f6ba60Sopenharmony_ci#include <cstdio> 2006f6ba60Sopenharmony_ci#include <cstdlib> 2106f6ba60Sopenharmony_ci#include <cstring> 2206f6ba60Sopenharmony_ci#include <ctime> 2306f6ba60Sopenharmony_ci#include <iomanip> 2406f6ba60Sopenharmony_ci#include <iostream> 2506f6ba60Sopenharmony_ci#include <memory> 2606f6ba60Sopenharmony_ci#include <mutex> 2706f6ba60Sopenharmony_ci 2806f6ba60Sopenharmony_ci#include <fcntl.h> 2906f6ba60Sopenharmony_ci#include <unistd.h> 3006f6ba60Sopenharmony_ci#include <linux/bpf.h> 3106f6ba60Sopenharmony_ci#include <linux/perf_event.h> 3206f6ba60Sopenharmony_ci#include <sys/resource.h> 3306f6ba60Sopenharmony_ci 3406f6ba60Sopenharmony_ci#include "bpf.h" 3506f6ba60Sopenharmony_ci#include "elf_file.h" 3606f6ba60Sopenharmony_ci#include "libbpf_logger.h" 3706f6ba60Sopenharmony_ci#include "bpf_controller.h" 3806f6ba60Sopenharmony_ci 3906f6ba60Sopenharmony_cinamespace { 4006f6ba60Sopenharmony_cistd::unique_ptr<LIBBPFLogger> libbpfLogger {nullptr}; 4106f6ba60Sopenharmony_ciconst std::string THIRD_PARTY_MUSL_ADDR = "/system/lib/ld-musl-aarch64.so.1"; 4206f6ba60Sopenharmony_ciconstexpr int32_t SYM_32_VALUE_OFFSET = 4; 4306f6ba60Sopenharmony_ciconstexpr int32_t SYM_64_VALUE_OFFSET = 8; 4406f6ba60Sopenharmony_ciconstexpr int32_t WIDE_SIXTEEN = 16; 4506f6ba60Sopenharmony_ciconstexpr uint32_t MAX_SIZE = INT_MAX; 4606f6ba60Sopenharmony_ci} // namespace 4706f6ba60Sopenharmony_ci 4806f6ba60Sopenharmony_ciint BPFController::LIBBPFPrintFunc(enum libbpf_print_level level, const char *format, va_list args) 4906f6ba60Sopenharmony_ci{ 5006f6ba60Sopenharmony_ci if (libbpfLogger) { 5106f6ba60Sopenharmony_ci return libbpfLogger->Printf(level, format, args); 5206f6ba60Sopenharmony_ci } 5306f6ba60Sopenharmony_ci return 0; 5406f6ba60Sopenharmony_ci} 5506f6ba60Sopenharmony_ci 5606f6ba60Sopenharmony_ciBPFController::~BPFController() 5706f6ba60Sopenharmony_ci{ 5806f6ba60Sopenharmony_ci Stop(); 5906f6ba60Sopenharmony_ci if (rb_) { 6006f6ba60Sopenharmony_ci // release bpf ringbuffer 6106f6ba60Sopenharmony_ci ring_buffer__free(rb_); 6206f6ba60Sopenharmony_ci rb_ = nullptr; 6306f6ba60Sopenharmony_ci } 6406f6ba60Sopenharmony_ci if (ips_) { 6506f6ba60Sopenharmony_ci delete[] ips_; 6606f6ba60Sopenharmony_ci ips_ = nullptr; 6706f6ba60Sopenharmony_ci } 6806f6ba60Sopenharmony_ci if (skel_) { 6906f6ba60Sopenharmony_ci hiebpf_bpf__destroy(skel_); 7006f6ba60Sopenharmony_ci skel_ = nullptr; 7106f6ba60Sopenharmony_ci } 7206f6ba60Sopenharmony_ci 7306f6ba60Sopenharmony_ci for (size_t k = 0; k < receivers_.size(); ++k) { 7406f6ba60Sopenharmony_ci receivers_[k]->Stop(); 7506f6ba60Sopenharmony_ci } 7606f6ba60Sopenharmony_ci if (bpfLogReader_) { 7706f6ba60Sopenharmony_ci bpfLogReader_->Stop(); 7806f6ba60Sopenharmony_ci } 7906f6ba60Sopenharmony_ci} 8006f6ba60Sopenharmony_ci 8106f6ba60Sopenharmony_cistd::unique_ptr<BPFController> BPFController::MakeUnique(const BPFConfig& config) 8206f6ba60Sopenharmony_ci{ 8306f6ba60Sopenharmony_ci std::unique_ptr<BPFController> bpfctlr {new(std::nothrow) BPFController {config}}; 8406f6ba60Sopenharmony_ci CHECK_NOTNULL(bpfctlr, nullptr, "failed to instantiate BPFController"); 8506f6ba60Sopenharmony_ci HHLOGI(true, "BPFController instantiated"); 8606f6ba60Sopenharmony_ci 8706f6ba60Sopenharmony_ci CHECK_TRUE(bpfctlr->VerifyConfigurations() == 0, nullptr, "failed to verify config"); 8806f6ba60Sopenharmony_ci HHLOGI(true, "BPFConfig verified"); 8906f6ba60Sopenharmony_ci 9006f6ba60Sopenharmony_ci CHECK_TRUE(bpfctlr->SetUpBPF() == 0, nullptr, "failed to set up BPF"); 9106f6ba60Sopenharmony_ci HHLOGI(true, "BPF setup done"); 9206f6ba60Sopenharmony_ci 9306f6ba60Sopenharmony_ci return bpfctlr; 9406f6ba60Sopenharmony_ci} 9506f6ba60Sopenharmony_ci 9606f6ba60Sopenharmony_cistatic inline int VerifyDumpEvents(const __u32 nr) 9706f6ba60Sopenharmony_ci{ 9806f6ba60Sopenharmony_ci CHECK_TRUE(nr <= BPFController::DUMP_EVENTS_LIMIT, -1, "dump events exceeds limit"); 9906f6ba60Sopenharmony_ci return 0; 10006f6ba60Sopenharmony_ci} 10106f6ba60Sopenharmony_ci 10206f6ba60Sopenharmony_cistatic inline int VerifyTraceDuration(const __u32 duration) 10306f6ba60Sopenharmony_ci{ 10406f6ba60Sopenharmony_ci CHECK_TRUE(duration <= BPFController::TRACE_DURATION_LIMIT, -1, "trace duration exceeds limit"); 10506f6ba60Sopenharmony_ci return 0; 10606f6ba60Sopenharmony_ci} 10706f6ba60Sopenharmony_ci 10806f6ba60Sopenharmony_cistatic inline int VerifyMaxStackDepth(const __u32 depth) 10906f6ba60Sopenharmony_ci{ 11006f6ba60Sopenharmony_ci CHECK_TRUE(depth <= MAX_STACK_LIMIT, -1, "max stack depth exceeds limit"); 11106f6ba60Sopenharmony_ci return 0; 11206f6ba60Sopenharmony_ci} 11306f6ba60Sopenharmony_ci 11406f6ba60Sopenharmony_ciint BPFController::VerifySelectEventGroups(const std::set<HiebpfEventGroup> &selectEventGroups) 11506f6ba60Sopenharmony_ci{ 11606f6ba60Sopenharmony_ci CHECK_TRUE(!selectEventGroups.empty(), -1, "VerifySelectEventGroups() failed: event group list is empty"); 11706f6ba60Sopenharmony_ci selectEventGroups_ = selectEventGroups; 11806f6ba60Sopenharmony_ci return 0; 11906f6ba60Sopenharmony_ci} 12006f6ba60Sopenharmony_ci 12106f6ba60Sopenharmony_ciint BPFController::VerifyConfigurations() 12206f6ba60Sopenharmony_ci{ 12306f6ba60Sopenharmony_ci CHECK_TRUE(VerifySelectEventGroups(config_.selectEventGroups_) == 0, -1, "VerifySelectEventGroups fail"); 12406f6ba60Sopenharmony_ci HHLOGI(true, "VerifySelectEventGroups() done"); 12506f6ba60Sopenharmony_ci CHECK_TRUE(VerifyDumpEvents(config_.dumpEvents_) == 0, -1, 12606f6ba60Sopenharmony_ci "VerifyDumpEvents() failed: dump events = %u", config_.dumpEvents_); 12706f6ba60Sopenharmony_ci HHLOGI(true, "VerifyDumpEents() done"); 12806f6ba60Sopenharmony_ci CHECK_TRUE(VerifyTraceDuration(config_.traceDuration_) == 0, -1, 12906f6ba60Sopenharmony_ci "VerifyTraceDuration() failed: duration = %u", config_.traceDuration_); 13006f6ba60Sopenharmony_ci HHLOGI(true, "VerifyTraceDuration() done"); 13106f6ba60Sopenharmony_ci CHECK_TRUE(VerifyMaxStackDepth(config_.maxStackDepth_) == 0, -1, 13206f6ba60Sopenharmony_ci "VerifyMaxStackDepth() failed: max stack depth = %u", config_.maxStackDepth_); 13306f6ba60Sopenharmony_ci HHLOGI(true, "VerifyMaxStackDepth() done"); 13406f6ba60Sopenharmony_ci return 0; 13506f6ba60Sopenharmony_ci} 13606f6ba60Sopenharmony_ci 13706f6ba60Sopenharmony_ciint BPFController::SetUpBPF() 13806f6ba60Sopenharmony_ci{ 13906f6ba60Sopenharmony_ci CHECK_TRUE(ConfigLIBBPFLogger() == 0, -1, "failed to configure LIBBPF logger"); 14006f6ba60Sopenharmony_ci HHLOGI(true, "ConfigLIBBPFLogger() done"); 14106f6ba60Sopenharmony_ci 14206f6ba60Sopenharmony_ci // set up libbpf deubug level 14306f6ba60Sopenharmony_ci libbpf_set_strict_mode(LIBBPF_STRICT_ALL); 14406f6ba60Sopenharmony_ci // set RLIMIT_MEMLOCK 14506f6ba60Sopenharmony_ci struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY}; 14606f6ba60Sopenharmony_ci setrlimit(RLIMIT_MEMLOCK, &r); 14706f6ba60Sopenharmony_ci 14806f6ba60Sopenharmony_ci skel_ = hiebpf_bpf__open(); 14906f6ba60Sopenharmony_ci int err = libbpf_get_error(skel_); 15006f6ba60Sopenharmony_ci CHECK_TRUE(!err, err, "failed to open BPF skeleton: %s", strerror(-err)); 15106f6ba60Sopenharmony_ci HHLOGI(true, "BPF skeleton opened"); 15206f6ba60Sopenharmony_ci if (config_.maxStackDepth_ > MAX_SIZE) { 15306f6ba60Sopenharmony_ci HHLOGE(true, "SetUpBPF maxStackDepth exceeds max size"); 15406f6ba60Sopenharmony_ci return -1; 15506f6ba60Sopenharmony_ci } 15606f6ba60Sopenharmony_ci if (config_.unwindStack_) { 15706f6ba60Sopenharmony_ci ips_ = new(std::nothrow) __u64[config_.maxStackDepth_]; 15806f6ba60Sopenharmony_ci CHECK_NOTNULL(ips_, -1, "failed to allocate memory for ips"); 15906f6ba60Sopenharmony_ci } 16006f6ba60Sopenharmony_ci HHLOGI(true, "allocate ips buffer done"); 16106f6ba60Sopenharmony_ci dataFile_ = HiebpfDataFile::MakeShared(config_.cmd_, config_.outputFile_); 16206f6ba60Sopenharmony_ci CHECK_NOTNULL(dataFile_, -1, "failed to make hiebpf data file"); 16306f6ba60Sopenharmony_ci CHECK_TRUE(FilterProgByEvents() == 0, -1, "failed to load BPF objects"); 16406f6ba60Sopenharmony_ci HHLOGI(true, "make HiebpfDataFile done"); 16506f6ba60Sopenharmony_ci skel_->rodata->g_stack_limit = config_.maxStackDepth_; 16606f6ba60Sopenharmony_ci err = hiebpf_bpf__load(skel_); 16706f6ba60Sopenharmony_ci CHECK_TRUE(!err, err, "failed to load BPF skeleton: %s", strerror(-err)); 16806f6ba60Sopenharmony_ci CHECK_TRUE(ConfigureBPF() == 0, -1, "failed to configure BPF"); 16906f6ba60Sopenharmony_ci HHLOGI(true, "BPF configuration done"); 17006f6ba60Sopenharmony_ci 17106f6ba60Sopenharmony_ci return 0; 17206f6ba60Sopenharmony_ci} 17306f6ba60Sopenharmony_ci 17406f6ba60Sopenharmony_ciint BPFController::FilterProgByEvents() 17506f6ba60Sopenharmony_ci{ 17606f6ba60Sopenharmony_ci // check each one hiebpf_bpf.progs in hiebpf.skel.h 17706f6ba60Sopenharmony_ci // hiebpf_bpf.progs is autoload by default 17806f6ba60Sopenharmony_ci FilterFsGroup(); 17906f6ba60Sopenharmony_ci 18006f6ba60Sopenharmony_ci if (selectEventGroups_.find(MEM_GROUP_ALL) == selectEventGroups_.end()) { 18106f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__do_fault_entry, false); 18206f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__do_fault_exit, false); 18306f6ba60Sopenharmony_ci 18406f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_swap_page_entry, false); 18506f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_swap_page_exit, false); 18606f6ba60Sopenharmony_ci 18706f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_wp_page_entry, false); 18806f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_wp_page_exit, false); 18906f6ba60Sopenharmony_ci } 19006f6ba60Sopenharmony_ci if (selectEventGroups_.find(BIO_GROUP_ALL) == selectEventGroups_.end()) { 19106f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.block_issue, false); 19206f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.blk_update_request, false); 19306f6ba60Sopenharmony_ci } else { 19406f6ba60Sopenharmony_ci dataFile_->WriteKernelSymbol(); 19506f6ba60Sopenharmony_ci } 19606f6ba60Sopenharmony_ci return 0; 19706f6ba60Sopenharmony_ci} 19806f6ba60Sopenharmony_ci 19906f6ba60Sopenharmony_civoid BPFController::FilterFsGroup() 20006f6ba60Sopenharmony_ci{ 20106f6ba60Sopenharmony_ci if (selectEventGroups_.find(FS_GROUP_ALL) != selectEventGroups_.end()) { 20206f6ba60Sopenharmony_ci return; 20306f6ba60Sopenharmony_ci } 20406f6ba60Sopenharmony_ci if (skel_ == nullptr) { 20506f6ba60Sopenharmony_ci return; 20606f6ba60Sopenharmony_ci } 20706f6ba60Sopenharmony_ci if (selectEventGroups_.find(FS_GROUP_OPEN) == selectEventGroups_.end()) { 20806f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_sys_openat2_entry, false); 20906f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_sys_openat2_exit, false); 21006f6ba60Sopenharmony_ci } 21106f6ba60Sopenharmony_ci if (selectEventGroups_.find(FS_GROUP_READ) == selectEventGroups_.end()) { 21206f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_readv_entry, false); 21306f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_readv_exit, false); 21406f6ba60Sopenharmony_ci 21506f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_preadv_entry, false); 21606f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_preadv_exit, false); 21706f6ba60Sopenharmony_ci 21806f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_read_entry, false); 21906f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_read_exit, false); 22006f6ba60Sopenharmony_ci 22106f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_pread64_entry, false); 22206f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_pread64_exit, false); 22306f6ba60Sopenharmony_ci } 22406f6ba60Sopenharmony_ci if (selectEventGroups_.find(FS_GROUP_WRITE) == selectEventGroups_.end()) { 22506f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_writev_entry, false); 22606f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.do_writev_exit, false); 22706f6ba60Sopenharmony_ci 22806f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_sys_pwritev_entry, false); 22906f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_sys_pwritev_exit, false); 23006f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_sys_pwritev2_entry, false); 23106f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_sys_pwritev2_exit, false); 23206f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_compat_sys_pwritev_entry, false); 23306f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_compat_sys_pwritev_exit, false); 23406f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_compat_sys_pwritev2_entry, false); 23506f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__arm64_compat_sys_pwritev2_exit, false); 23606f6ba60Sopenharmony_ci 23706f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_write_entry, false); 23806f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_write_exit, false); 23906f6ba60Sopenharmony_ci 24006f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_pwrite64_entry, false); 24106f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.ksys_pwrite64_exit, false); 24206f6ba60Sopenharmony_ci } 24306f6ba60Sopenharmony_ci if (selectEventGroups_.find(FS_GROUP_CLOSE) == selectEventGroups_.end()) { 24406f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__close_fd_entry, false); 24506f6ba60Sopenharmony_ci bpf_program__set_autoload(skel_->progs.__close_fd_exit, false); 24606f6ba60Sopenharmony_ci } 24706f6ba60Sopenharmony_ci} 24806f6ba60Sopenharmony_ci 24906f6ba60Sopenharmony_cistatic int InitTracerPid(const int fd, bool excludeTracer) 25006f6ba60Sopenharmony_ci{ 25106f6ba60Sopenharmony_ci int32_t pid = -1; 25206f6ba60Sopenharmony_ci if (excludeTracer) { 25306f6ba60Sopenharmony_ci /* we write the tracer pid into BPF map to notify BPF progs 25406f6ba60Sopenharmony_ci * to exclude the tracer itself 25506f6ba60Sopenharmony_ci */ 25606f6ba60Sopenharmony_ci pid = static_cast<int32_t>(getpid()); 25706f6ba60Sopenharmony_ci CHECK_TRUE(pid >= 0, -1, "failed to get current pid"); 25806f6ba60Sopenharmony_ci } 25906f6ba60Sopenharmony_ci constexpr __u32 pididx {TRACER_PID_INDEX}; 26006f6ba60Sopenharmony_ci int err = bpf_map_update_elem(fd, &pididx, &pid, BPF_ANY); 26106f6ba60Sopenharmony_ci CHECK_TRUE(!err, -1, "failed to update tracer pid %d in config_var_map", pid); 26206f6ba60Sopenharmony_ci return 0; 26306f6ba60Sopenharmony_ci} 26406f6ba60Sopenharmony_ci 26506f6ba60Sopenharmony_cistatic inline int InitBPFLogLevel(const int fd, const __u32 level) 26606f6ba60Sopenharmony_ci{ 26706f6ba60Sopenharmony_ci if (level == BPF_LOG_NONE) { 26806f6ba60Sopenharmony_ci HHLOGD(true, "bpf log level is NONE!"); 26906f6ba60Sopenharmony_ci return 0; 27006f6ba60Sopenharmony_ci } 27106f6ba60Sopenharmony_ci constexpr __u32 levelidx {BPF_LOG_LEVEL_INDEX}; 27206f6ba60Sopenharmony_ci int err = bpf_map_update_elem(fd, &levelidx, &level, BPF_ANY); 27306f6ba60Sopenharmony_ci CHECK_TRUE(!err, -1, "failed to set bpf log level in config_var_map"); 27406f6ba60Sopenharmony_ci return 0; 27506f6ba60Sopenharmony_ci} 27606f6ba60Sopenharmony_ci 27706f6ba60Sopenharmony_cistatic inline int InitUnwindFlag(const int fd, bool unwind) 27806f6ba60Sopenharmony_ci{ 27906f6ba60Sopenharmony_ci constexpr __u32 uflagidx {UNWIND_FLAG_INDEX}; 28006f6ba60Sopenharmony_ci __u32 uflag {0}; 28106f6ba60Sopenharmony_ci if (unwind) { 28206f6ba60Sopenharmony_ci uflag = 1; 28306f6ba60Sopenharmony_ci } 28406f6ba60Sopenharmony_ci int err = bpf_map_update_elem(fd, &uflagidx, &uflag, BPF_ANY); 28506f6ba60Sopenharmony_ci CHECK_TRUE(!err, -1, "failed to set unwind stack flag in config_var_map"); 28606f6ba60Sopenharmony_ci return 0; 28706f6ba60Sopenharmony_ci} 28806f6ba60Sopenharmony_ci 28906f6ba60Sopenharmony_ciint BPFController::InitBPFVariables() const 29006f6ba60Sopenharmony_ci{ 29106f6ba60Sopenharmony_ci int fd = bpf_map__fd(skel_->maps.config_var_map); 29206f6ba60Sopenharmony_ci CHECK_TRUE(fd >= 0, -1, "failed to get fd of config_var_map"); 29306f6ba60Sopenharmony_ci HHLOGI(true, "InitBPFVariables() done"); 29406f6ba60Sopenharmony_ci CHECK_TRUE(InitTracerPid(fd, config_.excludeTracer_) == 0, -1, 29506f6ba60Sopenharmony_ci "failed to init tracer pid in config_var_map"); 29606f6ba60Sopenharmony_ci HHLOGI(true, "InitTracerPid() done"); 29706f6ba60Sopenharmony_ci CHECK_TRUE(InitBPFLogLevel(fd, config_.BPFLogLevel_) == 0, -1, 29806f6ba60Sopenharmony_ci "failed to init BPF log level in config_var_map"); 29906f6ba60Sopenharmony_ci HHLOGI(true, "InitBPFLogLevel() done"); 30006f6ba60Sopenharmony_ci CHECK_TRUE(InitUnwindFlag(fd, config_.unwindStack_) == 0, -1, 30106f6ba60Sopenharmony_ci "failed to init unwind stack flag in config_var_map"); 30206f6ba60Sopenharmony_ci HHLOGI(true, "InitUnwindFlag() done"); 30306f6ba60Sopenharmony_ci return 0; 30406f6ba60Sopenharmony_ci} 30506f6ba60Sopenharmony_ci 30606f6ba60Sopenharmony_ciint BPFController::FillTargetPidMap() const 30706f6ba60Sopenharmony_ci{ 30806f6ba60Sopenharmony_ci int fd = bpf_map__fd(skel_->maps.target_pid_map); 30906f6ba60Sopenharmony_ci CHECK_TRUE(fd >= 0, -1, "failed to get fd of target_pid_map"); 31006f6ba60Sopenharmony_ci int index {0}; 31106f6ba60Sopenharmony_ci uint32_t val {1}; // target_pid_Map[0] = 1 means tracing all processes 31206f6ba60Sopenharmony_ci int err {0}; 31306f6ba60Sopenharmony_ci int numPids {config_.targetPids_.size()}; 31406f6ba60Sopenharmony_ci HHLOGD(true, "target pid num = %d", numPids); 31506f6ba60Sopenharmony_ci if (numPids == 0) { 31606f6ba60Sopenharmony_ci // no target pid specified, trace all processes 31706f6ba60Sopenharmony_ci err = bpf_map_update_elem(fd, &index, &val, BPF_ANY); 31806f6ba60Sopenharmony_ci CHECK_TRUE(!err, -1, "failed to set target pid = %u", val); 31906f6ba60Sopenharmony_ci return 0; 32006f6ba60Sopenharmony_ci } 32106f6ba60Sopenharmony_ci if (numPids > MAX_TARGET_PIDS) { 32206f6ba60Sopenharmony_ci HHLOGW(true, "BPFController WARN: number of target pids exceeds the maximum limit"); 32306f6ba60Sopenharmony_ci numPids = MAX_TARGET_PIDS; 32406f6ba60Sopenharmony_ci } 32506f6ba60Sopenharmony_ci for (index = 1; index <= numPids; ++index) { 32606f6ba60Sopenharmony_ci val = static_cast<uint32_t>(config_.targetPids_[index - 1]); 32706f6ba60Sopenharmony_ci HHLOGD(true, "target pid = %u", val); 32806f6ba60Sopenharmony_ci std::cout << "target pid = " << val << std::endl; 32906f6ba60Sopenharmony_ci err = bpf_map_update_elem(fd, &index, &val, BPF_ANY); 33006f6ba60Sopenharmony_ci CHECK_TRUE(!err, -1, "failed to set target pid = %d", val); 33106f6ba60Sopenharmony_ci } 33206f6ba60Sopenharmony_ci return 0; 33306f6ba60Sopenharmony_ci} 33406f6ba60Sopenharmony_ci 33506f6ba60Sopenharmony_ciinline int BPFController::ConfigBPFLogger() 33606f6ba60Sopenharmony_ci{ 33706f6ba60Sopenharmony_ci if (config_.BPFLogLevel_ == BPF_LOG_NONE) { 33806f6ba60Sopenharmony_ci HHLOGD(true, "bpf log level is NONE!"); 33906f6ba60Sopenharmony_ci return 0; 34006f6ba60Sopenharmony_ci } 34106f6ba60Sopenharmony_ci#if defined(BPF_LOGGER_DEBUG) || defined(BPF_LOGGER_INFO) || defined(BPF_LOGGER_WARN) || \ 34206f6ba60Sopenharmony_ci defined(BPF_LOGGER_ERROR) || defined(BPF_LOGGER_FATAL) 34306f6ba60Sopenharmony_ci bpfLogReader_ = BPFLogReader::MakeUnique(config_.BPFLogFile_); 34406f6ba60Sopenharmony_ci CHECK_NOTNULL(bpfLogReader_, -1, "failed to initialize BPFLogReader"); 34506f6ba60Sopenharmony_ci#endif 34606f6ba60Sopenharmony_ci return 0; 34706f6ba60Sopenharmony_ci} 34806f6ba60Sopenharmony_ci 34906f6ba60Sopenharmony_ciinline int BPFController::ConfigLIBBPFLogger() const 35006f6ba60Sopenharmony_ci{ 35106f6ba60Sopenharmony_ci // set up libbpf print callback 35206f6ba60Sopenharmony_ci HHLOGI(true, "libbpf logger: file = %s, level = %d", config_.LIBBPFLogFile_.c_str(), config_.LIBBPFLogLevel_); 35306f6ba60Sopenharmony_ci libbpf_set_print(BPFController::LIBBPFPrintFunc); 35406f6ba60Sopenharmony_ci if (config_.LIBBPFLogLevel_ == LIBBPF_NONE) { 35506f6ba60Sopenharmony_ci HHLOGD(true, "libbpf log level is NONE!"); 35606f6ba60Sopenharmony_ci return 0; 35706f6ba60Sopenharmony_ci } 35806f6ba60Sopenharmony_ci libbpfLogger = LIBBPFLogger::MakeUnique(config_.LIBBPFLogFile_, config_.LIBBPFLogLevel_); 35906f6ba60Sopenharmony_ci CHECK_NOTNULL(libbpfLogger, -1, "libbpfLogger is nullptr"); 36006f6ba60Sopenharmony_ci return 0; 36106f6ba60Sopenharmony_ci} 36206f6ba60Sopenharmony_ci 36306f6ba60Sopenharmony_ciint BPFController::ConfigReceivers() 36406f6ba60Sopenharmony_ci{ 36506f6ba60Sopenharmony_ci if (config_.dumpEvents_ == 0) { 36606f6ba60Sopenharmony_ci rb_ = ring_buffer__new( 36706f6ba60Sopenharmony_ci bpf_map__fd(skel_->maps.bpf_ringbuf_map), 36806f6ba60Sopenharmony_ci BPFController::HandleEvent, 36906f6ba60Sopenharmony_ci this, nullptr); 37006f6ba60Sopenharmony_ci int err = libbpf_get_error(rb_); 37106f6ba60Sopenharmony_ci CHECK_TRUE(!err, err, "failed to make BPF ring buffer: %s", strerror(-err)); 37206f6ba60Sopenharmony_ci if (config_.pipelines_ == 0) { 37306f6ba60Sopenharmony_ci config_.pipelines_ = MIN_PIPELINES_LIMIT; 37406f6ba60Sopenharmony_ci } 37506f6ba60Sopenharmony_ci for (__u32 cnt = config_.pipelines_; cnt != 0; --cnt) { 37606f6ba60Sopenharmony_ci receivers_.push_back(BPFEventReceiver::MakeShared(dataFile_)); 37706f6ba60Sopenharmony_ci } 37806f6ba60Sopenharmony_ci CHECK_TRUE(receivers_.size() == config_.pipelines_, -1, "failed to make BPF event receivers"); 37906f6ba60Sopenharmony_ci last_ = 0; 38006f6ba60Sopenharmony_ci } else { 38106f6ba60Sopenharmony_ci rb_ = ring_buffer__new( 38206f6ba60Sopenharmony_ci bpf_map__fd(skel_->maps.bpf_ringbuf_map), 38306f6ba60Sopenharmony_ci BPFController::DumpEvent, 38406f6ba60Sopenharmony_ci this, nullptr); 38506f6ba60Sopenharmony_ci int err = libbpf_get_error(rb_); 38606f6ba60Sopenharmony_ci CHECK_TRUE(!err, err, "failed to make BPF ring buffer: %s", strerror(-err)); 38706f6ba60Sopenharmony_ci } 38806f6ba60Sopenharmony_ci return 0; 38906f6ba60Sopenharmony_ci} 39006f6ba60Sopenharmony_ci 39106f6ba60Sopenharmony_ciuint64_t BPFController::GetSymOffset(const std::string &path, const std::string &symbol) 39206f6ba60Sopenharmony_ci{ 39306f6ba60Sopenharmony_ci CHECK_TRUE(access(path.c_str(), F_OK) == 0, 0, "the file does not exist"); 39406f6ba60Sopenharmony_ci using namespace OHOS::Developtools::Hiebpf; 39506f6ba60Sopenharmony_ci std::unique_ptr<ElfFile> elfFile = ElfFile::MakeUnique(path); 39606f6ba60Sopenharmony_ci CHECK_NOTNULL(elfFile, 0, "ELF file open failed"); 39706f6ba60Sopenharmony_ci const std::string dynsym {".dynsym"}; 39806f6ba60Sopenharmony_ci CHECK_TRUE(elfFile->shdrs_.find(dynsym) != elfFile->shdrs_.end(), 0, "section dynsym failed to obtain data"); 39906f6ba60Sopenharmony_ci const auto &sym = elfFile->shdrs_[dynsym]; 40006f6ba60Sopenharmony_ci const uint8_t *symData = elfFile->GetSectionData(sym->secIndex_); 40106f6ba60Sopenharmony_ci CHECK_NOTNULL(symData, 0, "symData is NULL!"); 40206f6ba60Sopenharmony_ci 40306f6ba60Sopenharmony_ci const std::string dynstr {".dynstr"}; 40406f6ba60Sopenharmony_ci CHECK_TRUE(elfFile->shdrs_.find(dynstr) != elfFile->shdrs_.end(), 0, "section dynstr failed to obtain data"); 40506f6ba60Sopenharmony_ci const auto &str = elfFile->shdrs_[dynstr]; 40606f6ba60Sopenharmony_ci const uint8_t *strData = elfFile->GetSectionData(str->secIndex_); 40706f6ba60Sopenharmony_ci CHECK_NOTNULL(strData, 0, "strData is NULL!"); 40806f6ba60Sopenharmony_ci 40906f6ba60Sopenharmony_ci uint32_t st_name = 0; 41006f6ba60Sopenharmony_ci uint64_t stepLength = 0; 41106f6ba60Sopenharmony_ci uint64_t vaddr = 0; 41206f6ba60Sopenharmony_ci while (stepLength < sym->secSize_) { 41306f6ba60Sopenharmony_ci int ret = memcpy_s(&st_name, sizeof(uint32_t), symData + stepLength, sizeof(uint32_t)); 41406f6ba60Sopenharmony_ci CHECK_TRUE(ret == EOK, 0, "failed to memcpy symData"); 41506f6ba60Sopenharmony_ci auto name = const_cast<uint8_t*>(strData + st_name); 41606f6ba60Sopenharmony_ci if (name != nullptr && std::string(reinterpret_cast<char*>(name)).compare(symbol) == 0) { 41706f6ba60Sopenharmony_ci int32_t valueOffset = sym->secEntrySize_ == sizeof(Elf64_Sym) ? SYM_64_VALUE_OFFSET : SYM_32_VALUE_OFFSET; 41806f6ba60Sopenharmony_ci int32_t valueSize = valueOffset == SYM_64_VALUE_OFFSET ? sizeof(uint64_t) : sizeof(uint32_t); 41906f6ba60Sopenharmony_ci CHECK_TRUE(stepLength + static_cast<uint64_t>(valueOffset) < sym->secSize_, 0, "invalid symbol offset"); 42006f6ba60Sopenharmony_ci ret = memcpy_s(&vaddr, sizeof(uint64_t), symData + stepLength + valueOffset, valueSize); 42106f6ba60Sopenharmony_ci CHECK_TRUE(ret == EOK, 0, "failed to memcpy symData"); 42206f6ba60Sopenharmony_ci break; 42306f6ba60Sopenharmony_ci } 42406f6ba60Sopenharmony_ci stepLength += sym->secEntrySize_; 42506f6ba60Sopenharmony_ci } 42606f6ba60Sopenharmony_ci CHECK_TRUE(vaddr != 0, 0, "get vaddr failed"); 42706f6ba60Sopenharmony_ci 42806f6ba60Sopenharmony_ci const std::string text {".text"}; 42906f6ba60Sopenharmony_ci CHECK_TRUE(elfFile->shdrs_.find(text) != elfFile->shdrs_.end(), 0, "section text failed to obtain data"); 43006f6ba60Sopenharmony_ci const auto &textPtr = elfFile->shdrs_[text]; 43106f6ba60Sopenharmony_ci return vaddr - textPtr->secVaddr_ + textPtr->fileOffset_; 43206f6ba60Sopenharmony_ci} 43306f6ba60Sopenharmony_ci 43406f6ba60Sopenharmony_ciint32_t BPFController::ConfigDlopenBPFProg() 43506f6ba60Sopenharmony_ci{ 43606f6ba60Sopenharmony_ci uint64_t symOffset = GetSymOffset(THIRD_PARTY_MUSL_ADDR, "dlopen"); 43706f6ba60Sopenharmony_ci CHECK_TRUE(symOffset != 0, -1, "get symOffset failed"); 43806f6ba60Sopenharmony_ci skel_->links.uretprobe_dlopen = bpf_program__attach_uprobe(skel_->progs.uretprobe_dlopen, 43906f6ba60Sopenharmony_ci true, 44006f6ba60Sopenharmony_ci -1, 44106f6ba60Sopenharmony_ci THIRD_PARTY_MUSL_ADDR.c_str(), 44206f6ba60Sopenharmony_ci symOffset); 44306f6ba60Sopenharmony_ci CHECK_TRUE(skel_->links.uretprobe_dlopen, -1, "failed to attach uretprobe_dlopen"); 44406f6ba60Sopenharmony_ci return 0; 44506f6ba60Sopenharmony_ci} 44606f6ba60Sopenharmony_ci 44706f6ba60Sopenharmony_ciint BPFController::ConfigureBPF() 44806f6ba60Sopenharmony_ci{ 44906f6ba60Sopenharmony_ci CHECK_TRUE(InitBPFVariables() == 0, -1, "failed to fill config_var_map"); 45006f6ba60Sopenharmony_ci HHLOGI(true, "InitBPFVariables() done"); 45106f6ba60Sopenharmony_ci CHECK_TRUE(FillTargetPidMap() == 0, -1, "failed to fill target_pid_map"); 45206f6ba60Sopenharmony_ci HHLOGI(true, "FillTargetPidMap() done"); 45306f6ba60Sopenharmony_ci CHECK_TRUE(ConfigBPFLogger() == 0, -1, "failed to configure BPF logger"); 45406f6ba60Sopenharmony_ci HHLOGI(true, "ConfigBPFLogger() done"); 45506f6ba60Sopenharmony_ci CHECK_TRUE(ConfigReceivers() == 0, -1, "failed to configure BPF ringbuffer"); 45606f6ba60Sopenharmony_ci HHLOGI(true, "ConfigReceivers() done"); 45706f6ba60Sopenharmony_ci CHECK_TRUE(ConfigDlopenBPFProg() == 0, -1, "failed to configure user BPF prog"); 45806f6ba60Sopenharmony_ci return 0; 45906f6ba60Sopenharmony_ci} 46006f6ba60Sopenharmony_ci 46106f6ba60Sopenharmony_ciint BPFController::Start() 46206f6ba60Sopenharmony_ci{ 46306f6ba60Sopenharmony_ci#if defined(BPF_LOGGER_DEBUG) || defined(BPF_LOGGER_INFO) || defined(BPF_LOGGER_WARN) || \ 46406f6ba60Sopenharmony_ci defined(BPF_LOGGER_ERROR) || defined(BPF_LOGGER_FATAL) 46506f6ba60Sopenharmony_ci CHECK_TRUE(StartBPFLogReader() == 0, -1, "failed to start BPF log reader"); 46606f6ba60Sopenharmony_ci#endif 46706f6ba60Sopenharmony_ci HHLOGI(true, "BPF log reader started"); 46806f6ba60Sopenharmony_ci CHECK_TRUE(StartReceivers() == 0, -1, "failed to start receivers"); 46906f6ba60Sopenharmony_ci HHLOGI(true, "receivers started"); 47006f6ba60Sopenharmony_ci // activate events 47106f6ba60Sopenharmony_ci int err = hiebpf_bpf__attach(skel_); 47206f6ba60Sopenharmony_ci CHECK_TRUE(!err, -1, "failed to attach bpf object: %s", strerror(-err)); 47306f6ba60Sopenharmony_ci HHLOGI(true, "BPF events activated"); 47406f6ba60Sopenharmony_ci 47506f6ba60Sopenharmony_ci const auto endTime = std::chrono::steady_clock::now() + std::chrono::seconds(config_.traceDuration_); 47606f6ba60Sopenharmony_ci while (!loopStop_) { 47706f6ba60Sopenharmony_ci if (BPFEventLoopOnce() != 0) { 47806f6ba60Sopenharmony_ci printf("libbpf error occured, hiebpf exit\n"); 47906f6ba60Sopenharmony_ci err = -1; 48006f6ba60Sopenharmony_ci break; 48106f6ba60Sopenharmony_ci } 48206f6ba60Sopenharmony_ci if (std::chrono::steady_clock::now() >= endTime) { 48306f6ba60Sopenharmony_ci printf("timeout(%us), hiebpf exit\n", config_.traceDuration_); 48406f6ba60Sopenharmony_ci break; 48506f6ba60Sopenharmony_ci } 48606f6ba60Sopenharmony_ci } 48706f6ba60Sopenharmony_ci // receivers_ must stop after BPFEventLoopOnce(); 48806f6ba60Sopenharmony_ci for (size_t k = 0; k < receivers_.size(); ++k) { 48906f6ba60Sopenharmony_ci receivers_[k]->Stop(); 49006f6ba60Sopenharmony_ci } 49106f6ba60Sopenharmony_ci if (bpfLogReader_) { 49206f6ba60Sopenharmony_ci bpfLogReader_->Stop(); 49306f6ba60Sopenharmony_ci } 49406f6ba60Sopenharmony_ci 49506f6ba60Sopenharmony_ci HHLOGI(true, "hiebpf stopped"); 49606f6ba60Sopenharmony_ci 49706f6ba60Sopenharmony_ci return err; 49806f6ba60Sopenharmony_ci} 49906f6ba60Sopenharmony_ci 50006f6ba60Sopenharmony_civoid BPFController::Stop() 50106f6ba60Sopenharmony_ci{ 50206f6ba60Sopenharmony_ci loopStop_ = true; 50306f6ba60Sopenharmony_ci} 50406f6ba60Sopenharmony_ci 50506f6ba60Sopenharmony_ciint BPFController::HandleEvent(void *ctx, void *data, size_t dataSize) 50606f6ba60Sopenharmony_ci{ 50706f6ba60Sopenharmony_ci // get the next running receiver 50806f6ba60Sopenharmony_ci BPFController *bpfctlr = static_cast<BPFController *>(ctx); 50906f6ba60Sopenharmony_ci auto wrecv = bpfctlr->NextActiveReceiver(); 51006f6ba60Sopenharmony_ci auto receiver = wrecv.lock(); 51106f6ba60Sopenharmony_ci if (receiver == nullptr) { 51206f6ba60Sopenharmony_ci HHLOGF(true, "all receivers have stopped, will stop BPF event loop"); 51306f6ba60Sopenharmony_ci bpfctlr->Stop(); 51406f6ba60Sopenharmony_ci return -1; 51506f6ba60Sopenharmony_ci } 51606f6ba60Sopenharmony_ci 51706f6ba60Sopenharmony_ci // move data and notify receiver 51806f6ba60Sopenharmony_ci int ret = receiver->Put(data, dataSize); 51906f6ba60Sopenharmony_ci HHLOGE((ret < 0), "event lost: failed to move data to receiver"); // try other receivers ? 52006f6ba60Sopenharmony_ci HHLOGF( 52106f6ba60Sopenharmony_ci (0 <= ret and ret < static_cast<int>(dataSize)), 52206f6ba60Sopenharmony_ci "incomplete data movement: this should never happen"); 52306f6ba60Sopenharmony_ci return ret; 52406f6ba60Sopenharmony_ci} 52506f6ba60Sopenharmony_ci 52606f6ba60Sopenharmony_cistatic int DumpOpenat2Args(const struct fstrace_cmplt_event_t &cmpltEvent) 52706f6ba60Sopenharmony_ci{ 52806f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 52906f6ba60Sopenharmony_ci std::cout << "\n dfd = " << cmpltEvent.start_event.openat2_args.dfd; 53006f6ba60Sopenharmony_ci std::cout << "\n filename = " << cmpltEvent.start_event.openat2_args.filename; 53106f6ba60Sopenharmony_ci std::cout << "\n how = " << cmpltEvent.start_event.openat2_args.how; 53206f6ba60Sopenharmony_ci return 0; 53306f6ba60Sopenharmony_ci} 53406f6ba60Sopenharmony_ci 53506f6ba60Sopenharmony_cistatic int DumpReadvArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 53606f6ba60Sopenharmony_ci{ 53706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 53806f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.readv_args.fd; 53906f6ba60Sopenharmony_ci std::cout << "\n vec = " << cmpltEvent.start_event.readv_args.vec; 54006f6ba60Sopenharmony_ci std::cout << "\n vlen = " << cmpltEvent.start_event.readv_args.vlen; 54106f6ba60Sopenharmony_ci std::cout << "\n flags = " << cmpltEvent.start_event.readv_args.flags; 54206f6ba60Sopenharmony_ci return 0; 54306f6ba60Sopenharmony_ci} 54406f6ba60Sopenharmony_ci 54506f6ba60Sopenharmony_cistatic int DumpPreadvArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 54606f6ba60Sopenharmony_ci{ 54706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 54806f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.preadv_args.fd; 54906f6ba60Sopenharmony_ci std::cout << "\n vec = " << cmpltEvent.start_event.preadv_args.vec; 55006f6ba60Sopenharmony_ci std::cout << "\n vlen = " << cmpltEvent.start_event.preadv_args.vlen; 55106f6ba60Sopenharmony_ci std::cout << "\n pos = " << cmpltEvent.start_event.preadv_args.pos; 55206f6ba60Sopenharmony_ci std::cout << "\n flags = " << cmpltEvent.start_event.preadv_args.flags; 55306f6ba60Sopenharmony_ci return 0; 55406f6ba60Sopenharmony_ci} 55506f6ba60Sopenharmony_ci 55606f6ba60Sopenharmony_cistatic int DumpReadArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 55706f6ba60Sopenharmony_ci{ 55806f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 55906f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.read_args.fd; 56006f6ba60Sopenharmony_ci std::cout << "\n buf = " << cmpltEvent.start_event.read_args.buf; 56106f6ba60Sopenharmony_ci std::cout << "\n count = " << cmpltEvent.start_event.read_args.count; 56206f6ba60Sopenharmony_ci return 0; 56306f6ba60Sopenharmony_ci} 56406f6ba60Sopenharmony_ci 56506f6ba60Sopenharmony_cistatic int DumpPread64Args(const struct fstrace_cmplt_event_t &cmpltEvent) 56606f6ba60Sopenharmony_ci{ 56706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 56806f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.pread64_args.fd; 56906f6ba60Sopenharmony_ci std::cout << "\n buf = " << cmpltEvent.start_event.pread64_args.buf; 57006f6ba60Sopenharmony_ci std::cout << "\n count = " << cmpltEvent.start_event.pread64_args.count; 57106f6ba60Sopenharmony_ci std::cout << "\n pos = " << cmpltEvent.start_event.pread64_args.pos; 57206f6ba60Sopenharmony_ci return 0; 57306f6ba60Sopenharmony_ci} 57406f6ba60Sopenharmony_ci 57506f6ba60Sopenharmony_cistatic int DumpWritevArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 57606f6ba60Sopenharmony_ci{ 57706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 57806f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.writev_args.fd; 57906f6ba60Sopenharmony_ci std::cout << "\n vec = " << cmpltEvent.start_event.writev_args.vec; 58006f6ba60Sopenharmony_ci std::cout << "\n vlen = " << cmpltEvent.start_event.writev_args.vlen; 58106f6ba60Sopenharmony_ci std::cout << "\n flags = " << cmpltEvent.start_event.writev_args.flags; 58206f6ba60Sopenharmony_ci return 0; 58306f6ba60Sopenharmony_ci} 58406f6ba60Sopenharmony_ci 58506f6ba60Sopenharmony_cistatic int DumpPwritevArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 58606f6ba60Sopenharmony_ci{ 58706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 58806f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.pwritev_args.fd; 58906f6ba60Sopenharmony_ci std::cout << "\n vec = " << cmpltEvent.start_event.pwritev_args.vec; 59006f6ba60Sopenharmony_ci std::cout << "\n vlen = " << cmpltEvent.start_event.pwritev_args.vlen; 59106f6ba60Sopenharmony_ci std::cout << "\n pos = " << cmpltEvent.start_event.pwritev_args.pos; 59206f6ba60Sopenharmony_ci std::cout << "\n flags = " << cmpltEvent.start_event.pwritev_args.flags; 59306f6ba60Sopenharmony_ci return 0; 59406f6ba60Sopenharmony_ci} 59506f6ba60Sopenharmony_ci 59606f6ba60Sopenharmony_cistatic int DumpWriteArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 59706f6ba60Sopenharmony_ci{ 59806f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 59906f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.write_args.fd; 60006f6ba60Sopenharmony_ci std::cout << "\n buf = " << cmpltEvent.start_event.write_args.buf; 60106f6ba60Sopenharmony_ci std::cout << "\n count = " << cmpltEvent.start_event.write_args.count; 60206f6ba60Sopenharmony_ci return 0; 60306f6ba60Sopenharmony_ci} 60406f6ba60Sopenharmony_ci 60506f6ba60Sopenharmony_cistatic int DumpPwrite64Args(const struct fstrace_cmplt_event_t &cmpltEvent) 60606f6ba60Sopenharmony_ci{ 60706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 60806f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.pwrite64_args.fd; 60906f6ba60Sopenharmony_ci std::cout << "\n buf = " << cmpltEvent.start_event.pwrite64_args.buf; 61006f6ba60Sopenharmony_ci std::cout << "\n count = " << cmpltEvent.start_event.pwrite64_args.count; 61106f6ba60Sopenharmony_ci std::cout << "\n pos = " << cmpltEvent.start_event.pwrite64_args.pos; 61206f6ba60Sopenharmony_ci return 0; 61306f6ba60Sopenharmony_ci} 61406f6ba60Sopenharmony_ci 61506f6ba60Sopenharmony_cistatic int DumpCloseArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 61606f6ba60Sopenharmony_ci{ 61706f6ba60Sopenharmony_ci std::cout << "\nArgs:"; 61806f6ba60Sopenharmony_ci std::cout << "\n files = " << cmpltEvent.start_event.close_args.files; 61906f6ba60Sopenharmony_ci std::cout << "\n fd = " << cmpltEvent.start_event.close_args.fd; 62006f6ba60Sopenharmony_ci return 0; 62106f6ba60Sopenharmony_ci} 62206f6ba60Sopenharmony_ci 62306f6ba60Sopenharmony_cistatic int DumpTypeAndArgs(const struct fstrace_cmplt_event_t &cmpltEvent) 62406f6ba60Sopenharmony_ci{ 62506f6ba60Sopenharmony_ci std::cout << "\nevent type: "; 62606f6ba60Sopenharmony_ci switch (cmpltEvent.start_event.type) { 62706f6ba60Sopenharmony_ci case SYS_OPENAT2: std::cout << "openat2"; return DumpOpenat2Args(cmpltEvent); 62806f6ba60Sopenharmony_ci 62906f6ba60Sopenharmony_ci case SYS_READV: std::cout << "readv"; return DumpReadvArgs(cmpltEvent); 63006f6ba60Sopenharmony_ci case SYS_PREADV: std::cout << "preadv"; return DumpPreadvArgs(cmpltEvent); 63106f6ba60Sopenharmony_ci case SYS_READ: std::cout << "read"; return DumpReadArgs(cmpltEvent); 63206f6ba60Sopenharmony_ci case SYS_PREAD64: std::cout << "pread64"; return DumpPread64Args(cmpltEvent); 63306f6ba60Sopenharmony_ci 63406f6ba60Sopenharmony_ci case SYS_WRITEV: std::cout << "writev"; return DumpWritevArgs(cmpltEvent); 63506f6ba60Sopenharmony_ci case SYS_PWRITEV: std::cout << "pwritev"; return DumpPwritevArgs(cmpltEvent); 63606f6ba60Sopenharmony_ci case SYS_WRITE: std::cout << "write"; return DumpWriteArgs(cmpltEvent); 63706f6ba60Sopenharmony_ci case SYS_PWRITE64: std::cout << "pwrite64"; return DumpPwrite64Args(cmpltEvent); 63806f6ba60Sopenharmony_ci 63906f6ba60Sopenharmony_ci case SYS_CLOSE: std::cout << "close"; return DumpCloseArgs(cmpltEvent); 64006f6ba60Sopenharmony_ci } 64106f6ba60Sopenharmony_ci HHLOGE(true, "unreognized fstrace event type = %d", cmpltEvent.start_event.type); 64206f6ba60Sopenharmony_ci return -1; 64306f6ba60Sopenharmony_ci} 64406f6ba60Sopenharmony_ci 64506f6ba60Sopenharmony_ciint BPFController::DumpFSTraceEvent(BPFController *bpfctlr, void *data, size_t dataSize) 64606f6ba60Sopenharmony_ci{ 64706f6ba60Sopenharmony_ci if (dataSize != sizeof(fstrace_cmplt_event_t)) { 64806f6ba60Sopenharmony_ci std::cout << "DumpFSTraceEvent ERROR: size dismatch:" 64906f6ba60Sopenharmony_ci << " data size = " << dataSize 65006f6ba60Sopenharmony_ci << " fstrace event size = " << sizeof(fstrace_cmplt_event_t) 65106f6ba60Sopenharmony_ci << std::endl; 65206f6ba60Sopenharmony_ci return -1; 65306f6ba60Sopenharmony_ci } 65406f6ba60Sopenharmony_ci struct fstrace_cmplt_event_t cmpltEvent {}; 65506f6ba60Sopenharmony_ci if (memcpy_s(&cmpltEvent, sizeof(fstrace_cmplt_event_t), data, dataSize) != EOK) { 65606f6ba60Sopenharmony_ci std::cout << "failed to copy data to fstrace_cmplt_event_t" << std::endl; 65706f6ba60Sopenharmony_ci return -1; 65806f6ba60Sopenharmony_ci } 65906f6ba60Sopenharmony_ci std::cout << "\nFSTrace Event:" 66006f6ba60Sopenharmony_ci << "\ndata size: " << dataSize; 66106f6ba60Sopenharmony_ci DumpTypeAndArgs(cmpltEvent); 66206f6ba60Sopenharmony_ci std::cout << "\nretval: " << cmpltEvent.retval 66306f6ba60Sopenharmony_ci << "\nstart time: " << cmpltEvent.start_event.stime 66406f6ba60Sopenharmony_ci << "\nexit time: " << cmpltEvent.ctime 66506f6ba60Sopenharmony_ci << "\npid: " << cmpltEvent.pid 66606f6ba60Sopenharmony_ci << "\ntgid: " << cmpltEvent.tgid 66706f6ba60Sopenharmony_ci << "\ncomm: " << cmpltEvent.comm 66806f6ba60Sopenharmony_ci << "\nips: " << cmpltEvent.nips 66906f6ba60Sopenharmony_ci << "\nips:" 67006f6ba60Sopenharmony_ci << std::setw(WIDE_SIXTEEN) << std::hex; 67106f6ba60Sopenharmony_ci for (uint32_t i = 0; i < cmpltEvent.nips; ++i) { 67206f6ba60Sopenharmony_ci std::cout << "\n " << cmpltEvent.ips[i]; 67306f6ba60Sopenharmony_ci } 67406f6ba60Sopenharmony_ci std::cout << std::dec << std::endl; 67506f6ba60Sopenharmony_ci return 0; 67606f6ba60Sopenharmony_ci} 67706f6ba60Sopenharmony_ci 67806f6ba60Sopenharmony_ciint BPFController::DumpPFTraceEvent(BPFController *bpfctlr, void *data, size_t dataSize) 67906f6ba60Sopenharmony_ci{ 68006f6ba60Sopenharmony_ci if (dataSize != sizeof(pftrace_cmplt_event_t)) { 68106f6ba60Sopenharmony_ci std::cout << "DumpPFTraceEvent ERROR: size dismatch:" 68206f6ba60Sopenharmony_ci << " data size = " << dataSize 68306f6ba60Sopenharmony_ci << " pftrace event size = " << sizeof(pftrace_cmplt_event_t) 68406f6ba60Sopenharmony_ci << std::endl; 68506f6ba60Sopenharmony_ci return -1; 68606f6ba60Sopenharmony_ci } 68706f6ba60Sopenharmony_ci struct pftrace_cmplt_event_t cmpltEvent {}; 68806f6ba60Sopenharmony_ci if (memcpy_s(&cmpltEvent, sizeof(pftrace_cmplt_event_t), data, dataSize) != EOK) { 68906f6ba60Sopenharmony_ci std::cout << "failed to copy data to pftrace_cmplt_event_t" << std::endl; 69006f6ba60Sopenharmony_ci return -1; 69106f6ba60Sopenharmony_ci } 69206f6ba60Sopenharmony_ci std::cout << "PFTrace Event:" 69306f6ba60Sopenharmony_ci << "\ndata size: " << dataSize 69406f6ba60Sopenharmony_ci << "\nevent type: "; 69506f6ba60Sopenharmony_ci switch (cmpltEvent.start_event.type) { 69606f6ba60Sopenharmony_ci case PF_COPY_ON_WRITE: std::cout << "Copy On Write"; break; 69706f6ba60Sopenharmony_ci case PF_FAKE_ZERO_PAGE: std::cout << "Zero FAKE Page"; break; 69806f6ba60Sopenharmony_ci case PF_FILE_BACKED_IN: std::cout << "File Backed In"; break; 69906f6ba60Sopenharmony_ci case PF_PAGE_CACHE_HIT: std::cout << "Page Cache Hit"; break; 70006f6ba60Sopenharmony_ci case PF_SWAP_FROM_DISK: std::cout << "Swap From Disk"; break; 70106f6ba60Sopenharmony_ci case PF_SWAP_FROM_ZRAM: std::cout << "Swap From Zram"; break; 70206f6ba60Sopenharmony_ci case PF_ZERO_FILL_PAGE: std::cout << "Zero Fill Page"; break; 70306f6ba60Sopenharmony_ci default: std::cout << cmpltEvent.start_event.type; 70406f6ba60Sopenharmony_ci } 70506f6ba60Sopenharmony_ci std::cout << "\naddress: " << cmpltEvent.start_event.addr 70606f6ba60Sopenharmony_ci << "\nsize: " << cmpltEvent.size 70706f6ba60Sopenharmony_ci << "\nstart time: " << cmpltEvent.start_event.stime 70806f6ba60Sopenharmony_ci << "\nexit time: " << cmpltEvent.ctime 70906f6ba60Sopenharmony_ci << "\npid: " << cmpltEvent.pid 71006f6ba60Sopenharmony_ci << "\ntgid: " << cmpltEvent.tgid 71106f6ba60Sopenharmony_ci << "\ncomm: " << cmpltEvent.comm 71206f6ba60Sopenharmony_ci << "\nips: " << cmpltEvent.nips 71306f6ba60Sopenharmony_ci << std::setw(WIDE_SIXTEEN) << std::hex; 71406f6ba60Sopenharmony_ci for (uint32_t i = 0; i < cmpltEvent.nips; ++i) { 71506f6ba60Sopenharmony_ci std::cout << "\n " << cmpltEvent.ips[i]; 71606f6ba60Sopenharmony_ci } 71706f6ba60Sopenharmony_ci std::cout << std::dec << std::endl; 71806f6ba60Sopenharmony_ci return 0; 71906f6ba60Sopenharmony_ci} 72006f6ba60Sopenharmony_ci 72106f6ba60Sopenharmony_ciint BPFController::DumpBIOTraceEvent(BPFController *bpfctlr, void *data, size_t dataSize) 72206f6ba60Sopenharmony_ci{ 72306f6ba60Sopenharmony_ci if (dataSize != sizeof(biotrace_cmplt_event_t)) { 72406f6ba60Sopenharmony_ci std::cout << "DumpBIOTraceEvent ERROR: size dismatch:" 72506f6ba60Sopenharmony_ci << " data size = " << dataSize 72606f6ba60Sopenharmony_ci << " biotrace event size = " << sizeof(biotrace_cmplt_event_t) 72706f6ba60Sopenharmony_ci << std::endl; 72806f6ba60Sopenharmony_ci return -1; 72906f6ba60Sopenharmony_ci } 73006f6ba60Sopenharmony_ci struct biotrace_cmplt_event_t cmpltEvent {}; 73106f6ba60Sopenharmony_ci if (memcpy_s(&cmpltEvent, sizeof(biotrace_cmplt_event_t), data, dataSize) != EOK) { 73206f6ba60Sopenharmony_ci std::cout << "failed to copy data to biotrace_cmplt_event_t" << std::endl; 73306f6ba60Sopenharmony_ci return -1; 73406f6ba60Sopenharmony_ci } 73506f6ba60Sopenharmony_ci std::cout << "BIOTrace Event:" 73606f6ba60Sopenharmony_ci << "\ndata size: " << dataSize 73706f6ba60Sopenharmony_ci << "\nevent type: "; 73806f6ba60Sopenharmony_ci switch (cmpltEvent.start_event.type) { 73906f6ba60Sopenharmony_ci case BIO_DATA_READ: std::cout << "DATA_READ"; break; 74006f6ba60Sopenharmony_ci case BIO_DATA_WRITE: std::cout << "DATA_WRITE"; break; 74106f6ba60Sopenharmony_ci case BIO_METADATA_READ: std::cout << "METADATA_READ"; break; 74206f6ba60Sopenharmony_ci case BIO_METADATA_WRITE: std::cout << "METADATA_WRITE"; break; 74306f6ba60Sopenharmony_ci case BIO_PAGE_IN: std::cout << "PAGE_IN"; break; 74406f6ba60Sopenharmony_ci case BIO_PAGE_OUT: std::cout << "PAGE_OUT"; break; 74506f6ba60Sopenharmony_ci default: std::cout << cmpltEvent.start_event.type; 74606f6ba60Sopenharmony_ci } 74706f6ba60Sopenharmony_ci 74806f6ba60Sopenharmony_ci std::cout << "\nstart time: " << cmpltEvent.start_event.stime 74906f6ba60Sopenharmony_ci << "\nexit time: " << cmpltEvent.ctime 75006f6ba60Sopenharmony_ci << "\npid: " << cmpltEvent.start_event.pid 75106f6ba60Sopenharmony_ci << "\ntgid: " << cmpltEvent.start_event.tgid 75206f6ba60Sopenharmony_ci << "\ncomm: " << cmpltEvent.start_event.comm 75306f6ba60Sopenharmony_ci << "\nprio: " << cmpltEvent.prio 75406f6ba60Sopenharmony_ci << "\nsize: " << cmpltEvent.start_event.size 75506f6ba60Sopenharmony_ci << "\nblkcnt: " << cmpltEvent.blkcnt 75606f6ba60Sopenharmony_ci << "\nips: " << cmpltEvent.nips 75706f6ba60Sopenharmony_ci << std::setw(WIDE_SIXTEEN) << std::hex; 75806f6ba60Sopenharmony_ci for (uint32_t i = 0; i < cmpltEvent.nips; ++i) { 75906f6ba60Sopenharmony_ci std::cout << "\n " << cmpltEvent.ips[i]; 76006f6ba60Sopenharmony_ci } 76106f6ba60Sopenharmony_ci std::cout << std::dec << std::endl; 76206f6ba60Sopenharmony_ci return 0; 76306f6ba60Sopenharmony_ci} 76406f6ba60Sopenharmony_ci 76506f6ba60Sopenharmony_ciint BPFController::DumpSTRTraceEvent(void *data, size_t dataSize) 76606f6ba60Sopenharmony_ci{ 76706f6ba60Sopenharmony_ci if (dataSize != sizeof(strtrace_cmplt_event_t)) { 76806f6ba60Sopenharmony_ci std::cout << "DumpSTRTraceEvent ERROR: size dismatch:" 76906f6ba60Sopenharmony_ci << " data size = " << dataSize 77006f6ba60Sopenharmony_ci << " strtrace event size = " << sizeof(strtrace_cmplt_event_t) 77106f6ba60Sopenharmony_ci << std::endl; 77206f6ba60Sopenharmony_ci return -1; 77306f6ba60Sopenharmony_ci } 77406f6ba60Sopenharmony_ci struct strtrace_cmplt_event_t cmpltEvent {}; 77506f6ba60Sopenharmony_ci if (memcpy_s(&cmpltEvent, sizeof(strtrace_cmplt_event_t), data, dataSize) != EOK) { 77606f6ba60Sopenharmony_ci std::cout << "failed to copy data to strtrace_cmplt_event_t" << std::endl; 77706f6ba60Sopenharmony_ci return -1; 77806f6ba60Sopenharmony_ci } 77906f6ba60Sopenharmony_ci std::cout << "STRTrace Event:" 78006f6ba60Sopenharmony_ci << "\ndata size: " << dataSize 78106f6ba60Sopenharmony_ci << "\ntracer: " << cmpltEvent.start_event.stracer 78206f6ba60Sopenharmony_ci << "\ntype: " << cmpltEvent.start_event.type 78306f6ba60Sopenharmony_ci << "\naddress: " << cmpltEvent.start_event.addr 78406f6ba60Sopenharmony_ci << "\nstart time: " << cmpltEvent.start_event.stime 78506f6ba60Sopenharmony_ci << "\npid: " << cmpltEvent.pid 78606f6ba60Sopenharmony_ci << "\ntgid: " << cmpltEvent.tgid 78706f6ba60Sopenharmony_ci << "\nfilename len: " << cmpltEvent.len 78806f6ba60Sopenharmony_ci << "\nfilename: " << cmpltEvent.filename 78906f6ba60Sopenharmony_ci << std::endl; 79006f6ba60Sopenharmony_ci return 0; 79106f6ba60Sopenharmony_ci} 79206f6ba60Sopenharmony_ci 79306f6ba60Sopenharmony_ciint BPFController::DumpEvent(void *ctx, void *data, size_t dataSize) 79406f6ba60Sopenharmony_ci{ 79506f6ba60Sopenharmony_ci const __u32 *tracer = static_cast<const __u32 *>(data); 79606f6ba60Sopenharmony_ci BPFController *bpfctlr = static_cast<BPFController *>(ctx); 79706f6ba60Sopenharmony_ci if (bpfctlr->config_.dumpEvents_) { 79806f6ba60Sopenharmony_ci --bpfctlr->config_.dumpEvents_; 79906f6ba60Sopenharmony_ci static __u32 counter {0}; 80006f6ba60Sopenharmony_ci std::cout << "\ncounter = " << ++counter; 80106f6ba60Sopenharmony_ci switch (*tracer) { 80206f6ba60Sopenharmony_ci case FSTRACE: return DumpFSTraceEvent(bpfctlr, data, dataSize); 80306f6ba60Sopenharmony_ci case PFTRACE: return DumpPFTraceEvent(bpfctlr, data, dataSize); 80406f6ba60Sopenharmony_ci case BIOTRACE: return DumpBIOTraceEvent(bpfctlr, data, dataSize); 80506f6ba60Sopenharmony_ci case STRTRACE: return DumpSTRTraceEvent(data, dataSize); 80606f6ba60Sopenharmony_ci } 80706f6ba60Sopenharmony_ci std::cout << "DumpEvent ERROR: bad tracer type = " << (*tracer) << std::endl; 80806f6ba60Sopenharmony_ci } 80906f6ba60Sopenharmony_ci return 0; 81006f6ba60Sopenharmony_ci} 81106f6ba60Sopenharmony_ci 81206f6ba60Sopenharmony_cistd::weak_ptr<BPFEventReceiver> BPFController::NextActiveReceiver() 81306f6ba60Sopenharmony_ci{ 81406f6ba60Sopenharmony_ci __u32 next = last_ + 1; 81506f6ba60Sopenharmony_ci __u32 total = receivers_.size(); 81606f6ba60Sopenharmony_ci for (;;) { 81706f6ba60Sopenharmony_ci if (next >= total) { 81806f6ba60Sopenharmony_ci next -= total; 81906f6ba60Sopenharmony_ci } 82006f6ba60Sopenharmony_ci if (receivers_[next]->Running() or next == last_) { 82106f6ba60Sopenharmony_ci break; 82206f6ba60Sopenharmony_ci } 82306f6ba60Sopenharmony_ci ++next; 82406f6ba60Sopenharmony_ci } 82506f6ba60Sopenharmony_ci if (receivers_[next]->Running()) { 82606f6ba60Sopenharmony_ci last_ = next; 82706f6ba60Sopenharmony_ci return receivers_[last_]; 82806f6ba60Sopenharmony_ci } 82906f6ba60Sopenharmony_ci return std::weak_ptr<BPFEventReceiver>(); 83006f6ba60Sopenharmony_ci}