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}