Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[record & replay] Introduce a virtual base class for BCCWrapper. #1660

Merged
merged 11 commits into from
Aug 9, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/stirling/benchmarks/bpf_map_ops_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include "src/stirling/utils/proc_path_tools.h"

using ::px::stirling::GetSelfPath;
using ::px::stirling::bpf_tools::BCCWrapper;
using ::px::stirling::bpf_tools::BCCWrapperImpl;
using ::px::stirling::bpf_tools::BPFProbeAttachType;
using ::px::stirling::bpf_tools::UProbeSpec;
using ::px::stirling::bpf_tools::WrappedBCCMap;
Expand All @@ -50,7 +50,7 @@ NO_OPT_ATTR void BPFMapPopulateTrigger(int n) {
}
}

void SetupCleanupProbe(BCCWrapper* bcc) {
void SetupCleanupProbe(BCCWrapperImpl* bcc) {
std::filesystem::path self_path = GetSelfPath().ValueOrDie();
auto elf_reader_or_s = px::stirling::obj_tools::ElfReader::Create(self_path.string());
PX_CHECK_OK(elf_reader_or_s.status());
Expand All @@ -75,7 +75,7 @@ void SetupCleanupProbe(BCCWrapper* bcc) {
PX_CHECK_OK(bcc->AttachUProbe(uprobe));
}

void SetupPopulateProbe(BCCWrapper* bcc) {
void SetupPopulateProbe(BCCWrapperImpl* bcc) {
std::filesystem::path self_path = GetSelfPath().ValueOrDie();
auto elf_reader_or_s = px::stirling::obj_tools::ElfReader::Create(self_path.string());
PX_CHECK_OK(elf_reader_or_s.status());
Expand All @@ -102,7 +102,7 @@ void SetupPopulateProbe(BCCWrapper* bcc) {

// NOLINTNEXTLINE : runtime/references.
static void BM_userspace_update_remove(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
std::string_view kProgram = "BPF_HASH(map, int, int);";
PX_CHECK_OK(bcc_wrapper.InitBPFProgram(kProgram));
auto bpf_map = WrappedBCCMap<int, int>::Create(&bcc_wrapper, "map");
Expand All @@ -124,7 +124,7 @@ static void BM_userspace_update_remove(benchmark::State& state) {

// NOLINTNEXTLINE : runtime/references.
static void BM_bpf_triggered_update_remove(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
std::string_view kProgram = R"(
#include <linux/ptrace.h>

Expand Down Expand Up @@ -192,7 +192,7 @@ int map_populate_uprobe(struct pt_regs* ctx) {

// NOLINTNEXTLINE : runtime/references.
static void BM_userspace_update_get_remove(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
std::string_view kProgram = "BPF_HASH(map, int, int);";
PX_CHECK_OK(bcc_wrapper.InitBPFProgram(kProgram));
auto bpf_map = WrappedBCCMap<int, int>::Create(&bcc_wrapper, "map");
Expand All @@ -217,7 +217,7 @@ static void BM_userspace_update_get_remove(benchmark::State& state) {

// NOLINTNEXTLINE : runtime/references.
static void BM_bpf_triggered_update_get_remove(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
std::string_view kProgram = R"(
#include <linux/ptrace.h>

Expand Down
10 changes: 5 additions & 5 deletions src/stirling/benchmarks/symbolization_benchmark.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include "src/stirling/obj_tools/address_converter.h"
#include "src/stirling/obj_tools/elf_reader.h"

using ::px::stirling::bpf_tools::BCCWrapper;
using ::px::stirling::bpf_tools::BCCWrapperImpl;
using ::px::stirling::bpf_tools::WrappedBCCArrayTable;
using ::px::stirling::bpf_tools::WrappedBCCStackTable;
using ::px::stirling::obj_tools::ElfReader;
Expand Down Expand Up @@ -64,7 +64,7 @@ const std::string_view kProgram = R"(
}
)";

std::vector<uintptr_t> CollectStackTrace(BCCWrapper* bcc_wrapper,
std::vector<uintptr_t> CollectStackTrace(BCCWrapperImpl* bcc_wrapper,
const std::filesystem::path& self_path) {
::px::stirling::bpf_tools::UProbeSpec spec = {
.binary_path = self_path.string(),
Expand All @@ -90,7 +90,7 @@ std::vector<uintptr_t> CollectStackTrace(BCCWrapper* bcc_wrapper,

// NOLINTNEXTLINE : runtime/references.
static void BM_elf_reader_symbolization(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
PX_ASSIGN_OR_EXIT(std::filesystem::path self_path, ::px::fs::ReadSymlink("/proc/self/exe"));
std::vector<uintptr_t> addrs = CollectStackTrace(&bcc_wrapper, self_path);
PX_ASSIGN_OR_EXIT(auto elf_reader,
Expand All @@ -112,7 +112,7 @@ static void BM_elf_reader_symbolization(benchmark::State& state) {

// NOLINTNEXTLINE : runtime/references.
static void BM_elf_reader_symbolization_indexed(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
PX_ASSIGN_OR_EXIT(std::filesystem::path self_path, ::px::fs::ReadSymlink("/proc/self/exe"));
std::vector<uintptr_t> addrs = CollectStackTrace(&bcc_wrapper, self_path);
PX_ASSIGN_OR_EXIT(auto elf_reader, ElfReader::Create(self_path.string()));
Expand All @@ -134,7 +134,7 @@ static void BM_elf_reader_symbolization_indexed(benchmark::State& state) {

// NOLINTNEXTLINE : runtime/references.
static void BM_bcc_symbolization(benchmark::State& state) {
BCCWrapper bcc_wrapper;
BCCWrapperImpl bcc_wrapper;
PX_ASSIGN_OR_EXIT(std::filesystem::path self_path, ::px::fs::ReadSymlink("/proc/self/exe"));
std::vector<uintptr_t> addrs = CollectStackTrace(&bcc_wrapper, self_path);
auto bcc_symbolizer = WrappedBCCStackTable::Create(&bcc_wrapper, "stack_traces");
Expand Down
62 changes: 32 additions & 30 deletions src/stirling/bpf_tools/bcc_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ StatusOr<utils::TaskStructOffsets> BCCWrapper::ComputeTaskStructOffsets() {
return task_struct_offsets_opt_.value();
}

Status BCCWrapper::InitBPFProgram(std::string_view bpf_program, std::vector<std::string> cflags,
bool requires_linux_headers,
bool always_infer_task_struct_offsets) {
Status BCCWrapperImpl::InitBPFProgram(std::string_view bpf_program, std::vector<std::string> cflags,
bool requires_linux_headers,
bool always_infer_task_struct_offsets) {
using utils::TaskStructOffsets;

if (!IsRoot()) {
Expand Down Expand Up @@ -177,7 +177,7 @@ Status BCCWrapper::InitBPFProgram(std::string_view bpf_program, std::vector<std:
return Status::OK();
}

Status BCCWrapper::AttachKProbe(const KProbeSpec& probe) {
Status BCCWrapperImpl::AttachKProbe(const KProbeSpec& probe) {
VLOG(1) << "Deploying kprobe: " << probe.ToString();
DCHECK(probe.attach_type != BPFProbeAttachType::kReturnInsts);

Expand All @@ -197,7 +197,7 @@ Status BCCWrapper::AttachKProbe(const KProbeSpec& probe) {
return Status::OK();
}

Status BCCWrapper::AttachTracepoint(const TracepointSpec& probe) {
Status BCCWrapperImpl::AttachTracepoint(const TracepointSpec& probe) {
VLOG(1) << "Deploying tracepoint: " << probe.ToString();

PX_RETURN_IF_ERROR(bpf_.attach_tracepoint(probe.tracepoint, probe.probe_fn));
Expand All @@ -206,7 +206,7 @@ Status BCCWrapper::AttachTracepoint(const TracepointSpec& probe) {
return Status::OK();
}

Status BCCWrapper::AttachUProbe(const UProbeSpec& probe) {
Status BCCWrapperImpl::AttachUProbe(const UProbeSpec& probe) {
VLOG(1) << "Deploying uprobe: " << probe.ToString();
// TODO(oazizi): Natively support this attach type in BCCWrapper.
DCHECK(probe.attach_type != BPFProbeAttachType::kReturnInsts);
Expand All @@ -227,7 +227,7 @@ Status BCCWrapper::AttachUProbe(const UProbeSpec& probe) {
return Status::OK();
}

Status BCCWrapper::AttachSamplingProbe(const SamplingProbeSpec& probe) {
Status BCCWrapperImpl::AttachSamplingProbe(const SamplingProbeSpec& probe) {
constexpr uint64_t kNanosPerMilli = 1000 * 1000;
const uint64_t sample_period = probe.period_millis * kNanosPerMilli;
// A sampling probe is just a PerfEventProbe, where the perf event is a clock counter.
Expand All @@ -242,28 +242,28 @@ Status BCCWrapper::AttachSamplingProbe(const SamplingProbeSpec& probe) {
return AttachPerfEvent(perf_event_spec);
}

Status BCCWrapper::AttachKProbes(const ArrayView<KProbeSpec>& probes) {
Status BCCWrapperImpl::AttachKProbes(const ArrayView<KProbeSpec>& probes) {
for (const KProbeSpec& p : probes) {
PX_RETURN_IF_ERROR(AttachKProbe(p));
}
return Status::OK();
}

Status BCCWrapper::AttachTracepoints(const ArrayView<TracepointSpec>& probes) {
Status BCCWrapperImpl::AttachTracepoints(const ArrayView<TracepointSpec>& probes) {
for (const TracepointSpec& spec : probes) {
PX_RETURN_IF_ERROR(AttachTracepoint(spec));
}
return Status::OK();
}

Status BCCWrapper::AttachUProbes(const ArrayView<UProbeSpec>& probes) {
Status BCCWrapperImpl::AttachUProbes(const ArrayView<UProbeSpec>& probes) {
for (const UProbeSpec& p : probes) {
PX_RETURN_IF_ERROR(AttachUProbe(p));
}
return Status::OK();
}

Status BCCWrapper::AttachSamplingProbes(const ArrayView<SamplingProbeSpec>& probes) {
Status BCCWrapperImpl::AttachSamplingProbes(const ArrayView<SamplingProbeSpec>& probes) {
for (const SamplingProbeSpec& p : probes) {
PX_RETURN_IF_ERROR(AttachSamplingProbe(p));
}
Expand All @@ -273,7 +273,7 @@ Status BCCWrapper::AttachSamplingProbes(const ArrayView<SamplingProbeSpec>& prob
// This will replace the XDP program previously-attached on the the same device.
// Newer kernel allows attaching multiple XDP programs on the same device:
// https://lwn.net/Articles/801478/
Status BCCWrapper::AttachXDP(const std::string& dev_name, const std::string& fn_name) {
Status BCCWrapperImpl::AttachXDP(const std::string& dev_name, const std::string& fn_name) {
int fn_fd = -1;
ebpf::StatusTuple load_status = bpf_.load_func(fn_name, BPF_PROG_TYPE_XDP, fn_fd);

Expand All @@ -293,15 +293,15 @@ Status BCCWrapper::AttachXDP(const std::string& dev_name, const std::string& fn_
}

// TODO(PL-1294): This can fail in rare cases. See the cited issue. Find the root cause.
Status BCCWrapper::DetachKProbe(const KProbeSpec& probe) {
Status BCCWrapperImpl::DetachKProbe(const KProbeSpec& probe) {
VLOG(1) << "Detaching kprobe: " << probe.ToString();
PX_RETURN_IF_ERROR(bpf_.detach_kprobe(GetKProbeTargetName(probe),
static_cast<bpf_probe_attach_type>(probe.attach_type)));
--num_attached_kprobes_;
return Status::OK();
}

Status BCCWrapper::DetachUProbe(const UProbeSpec& probe) {
Status BCCWrapperImpl::DetachUProbe(const UProbeSpec& probe) {
VLOG(1) << "Detaching uprobe " << probe.ToString();

if (fs::Exists(probe.binary_path)) {
Expand All @@ -313,7 +313,7 @@ Status BCCWrapper::DetachUProbe(const UProbeSpec& probe) {
return Status::OK();
}

Status BCCWrapper::DetachTracepoint(const TracepointSpec& probe) {
Status BCCWrapperImpl::DetachTracepoint(const TracepointSpec& probe) {
VLOG(1) << "Detaching tracepoint " << probe.ToString();

PX_RETURN_IF_ERROR(bpf_.detach_tracepoint(probe.tracepoint));
Expand All @@ -322,31 +322,31 @@ Status BCCWrapper::DetachTracepoint(const TracepointSpec& probe) {
return Status::OK();
}

void BCCWrapper::DetachKProbes() {
void BCCWrapperImpl::DetachKProbes() {
for (const auto& p : kprobes_) {
auto res = DetachKProbe(p);
LOG_IF(ERROR, !res.ok()) << res.msg();
}
kprobes_.clear();
}

void BCCWrapper::DetachUProbes() {
void BCCWrapperImpl::DetachUProbes() {
for (const auto& p : uprobes_) {
auto res = DetachUProbe(p);
LOG_IF(ERROR, !res.ok()) << res.msg();
}
uprobes_.clear();
}

void BCCWrapper::DetachTracepoints() {
void BCCWrapperImpl::DetachTracepoints() {
for (const auto& t : tracepoints_) {
auto res = DetachTracepoint(t);
LOG_IF(ERROR, !res.ok()) << res.msg();
}
tracepoints_.clear();
}

Status BCCWrapper::OpenPerfBuffer(const PerfBufferSpec& perf_buffer) {
Status BCCWrapperImpl::OpenPerfBuffer(const PerfBufferSpec& perf_buffer) {
const int kPageSizeBytes = system::Config::GetInstance().PageSizeBytes();
int num_pages = IntRoundUpDivide(perf_buffer.size_bytes, kPageSizeBytes);

Expand All @@ -364,29 +364,29 @@ Status BCCWrapper::OpenPerfBuffer(const PerfBufferSpec& perf_buffer) {
return Status::OK();
}

Status BCCWrapper::OpenPerfBuffers(const ArrayView<PerfBufferSpec>& perf_buffers) {
Status BCCWrapperImpl::OpenPerfBuffers(const ArrayView<PerfBufferSpec>& perf_buffers) {
for (const PerfBufferSpec& p : perf_buffers) {
PX_RETURN_IF_ERROR(OpenPerfBuffer(p));
}
return Status::OK();
}

Status BCCWrapper::ClosePerfBuffer(const PerfBufferSpec& perf_buffer) {
Status BCCWrapperImpl::ClosePerfBuffer(const PerfBufferSpec& perf_buffer) {
VLOG(1) << "Closing perf buffer: " << perf_buffer.name;
PX_RETURN_IF_ERROR(bpf_.close_perf_buffer(std::string(perf_buffer.name)));
--num_open_perf_buffers_;
return Status::OK();
}

void BCCWrapper::ClosePerfBuffers() {
void BCCWrapperImpl::ClosePerfBuffers() {
for (const PerfBufferSpec& p : perf_buffers_) {
auto res = ClosePerfBuffer(p);
LOG_IF(ERROR, !res.ok()) << res.msg();
}
perf_buffers_.clear();
}

Status BCCWrapper::AttachPerfEvent(const PerfEventSpec& perf_event) {
Status BCCWrapperImpl::AttachPerfEvent(const PerfEventSpec& perf_event) {
VLOG(1) << absl::Substitute("Attaching perf event:\n type=$0\n probe_fn=$1",
magic_enum::enum_name(perf_event.type), perf_event.probe_fn);
PX_RETURN_IF_ERROR(bpf_.attach_perf_event(perf_event.type, perf_event.config,
Expand All @@ -397,58 +397,60 @@ Status BCCWrapper::AttachPerfEvent(const PerfEventSpec& perf_event) {
return Status::OK();
}

Status BCCWrapper::AttachPerfEvents(const ArrayView<PerfEventSpec>& perf_events) {
Status BCCWrapperImpl::AttachPerfEvents(const ArrayView<PerfEventSpec>& perf_events) {
for (const PerfEventSpec& p : perf_events) {
PX_RETURN_IF_ERROR(AttachPerfEvent(p));
}
return Status::OK();
}

Status BCCWrapper::DetachPerfEvent(const PerfEventSpec& perf_event) {
Status BCCWrapperImpl::DetachPerfEvent(const PerfEventSpec& perf_event) {
VLOG(1) << absl::Substitute("Detaching perf event:\n type=$0\n probe_fn=$1",
magic_enum::enum_name(perf_event.type), perf_event.probe_fn);
PX_RETURN_IF_ERROR(bpf_.detach_perf_event(perf_event.type, perf_event.config));
--num_attached_perf_events_;
return Status::OK();
}

void BCCWrapper::DetachPerfEvents() {
void BCCWrapperImpl::DetachPerfEvents() {
for (const PerfEventSpec& p : perf_events_) {
auto res = DetachPerfEvent(p);
LOG_IF(ERROR, !res.ok()) << res.msg();
}
perf_events_.clear();
}

std::string BCCWrapper::GetKProbeTargetName(const KProbeSpec& probe) {
std::string BCCWrapperImpl::GetKProbeTargetName(const KProbeSpec& probe) {
auto target = std::string(probe.kernel_fn);
if (probe.is_syscall) {
target = bpf_.get_syscall_fnname(target);
}
return target;
}

void BCCWrapper::PollPerfBuffer(std::string_view perf_buffer_name, int timeout_ms) {
void BCCWrapperImpl::PollPerfBuffer(std::string_view perf_buffer_name, int timeout_ms) {
auto perf_buffer = bpf_.get_perf_buffer(std::string(perf_buffer_name));
if (perf_buffer != nullptr) {
perf_buffer->poll(timeout_ms);
}
}

void BCCWrapper::PollPerfBuffers(int timeout_ms) {
void BCCWrapperImpl::PollPerfBuffers(int timeout_ms) {
for (const auto& spec : perf_buffers_) {
PollPerfBuffer(spec.name, timeout_ms);
}
}

void BCCWrapper::Close() {
void BCCWrapperImpl::Close() {
DetachPerfEvents();
ClosePerfBuffers();
DetachKProbes();
DetachUProbes();
DetachTracepoints();
}

std::unique_ptr<BCCWrapper> CreateBCC() { return std::make_unique<BCCWrapperImpl>(); }

} // namespace bpf_tools
} // namespace stirling
} // namespace px
Loading
Loading