4646#include " src/common/base/base.h"
4747#include " src/common/json/json.h"
4848#include " src/stirling/bpf_tools/probe_specs/probe_specs.h"
49+ #include " src/stirling/bpf_tools/rr/rr.h"
4950#include " src/stirling/bpf_tools/task_struct_resolver.h"
5051#include " src/stirling/obj_tools/elf_reader.h"
5152
@@ -89,7 +90,11 @@ class BCCWrapper {
8990 return task_struct_offsets_opt_;
9091 }
9192
92- virtual ebpf::BPF * BPF () = 0;
93+ virtual StatusOr<ebpf::BPF *> BPF () = 0;
94+ virtual StatusOr<BPFRecorder*> GetBPFRecorder () const = 0;
95+ virtual StatusOr<BPFReplayer*> GetBPFReplayer () const = 0;
96+ virtual bool IsRecording () const = 0;
97+ virtual bool IsReplaying () const = 0;
9398
9499 /* *
95100 * Compiles the BPF code.
@@ -271,7 +276,11 @@ class BCCWrapperImpl : public BCCWrapper {
271276 Close ();
272277 }
273278
274- ebpf::BPF * BPF () override { return &bpf_; }
279+ StatusOr<ebpf::BPF *> BPF () override { return &bpf_; }
280+ StatusOr<BPFRecorder*> GetBPFRecorder () const override { return error::Internal (" Wrong impl." ); }
281+ StatusOr<BPFReplayer*> GetBPFReplayer () const override { return error::Internal (" Wrong impl." ); }
282+ bool IsRecording () const override { return false ; }
283+ bool IsReplaying () const override { return false ; }
275284
276285 Status InitBPFProgram (std::string_view bpf_program, std::vector<std::string> cflags = {},
277286 bool requires_linux_headers = true ,
@@ -340,11 +349,111 @@ class BCCWrapperImpl : public BCCWrapper {
340349 // DEBUG_SOURCE = 0x8,
341350 // DEBUG_BPF_REGISTER_STATE = 0x10,
342351 // DEBUG_BTF = 0x20,
352+ protected:
343353 ebpf::BPF bpf_;
344354};
345355
356+ class RecordingBCCWrapperImpl : public BCCWrapperImpl {
357+ public:
358+ bool IsRecording () const override { return true ; }
359+ bool IsReplaying () const override { return false ; }
360+ StatusOr<BPFRecorder*> GetBPFRecorder () const override { return recorder_.get (); }
361+ StatusOr<BPFReplayer*> GetBPFReplayer () const override { return error::Internal (" Wrong impl." ); }
362+
363+ Status OpenPerfBuffer (const PerfBufferSpec& perf_buffer) override ;
364+
365+ RecordingBCCWrapperImpl () { recorder_ = std::make_unique<BPFRecorder>(); }
366+
367+ void WriteProto (const std::string& pb_file_path) { recorder_->WriteProto (pb_file_path); }
368+
369+ private:
370+ std::unique_ptr<BPFRecorder> recorder_;
371+ };
372+
373+ class ReplayingBCCWrapperImpl : public BCCWrapper {
374+ public:
375+ bool IsRecording () const override { return false ; }
376+ bool IsReplaying () const override { return true ; }
377+ StatusOr<BPFRecorder*> GetBPFRecorder () const override { return error::Internal (" Wrong impl." ); }
378+ StatusOr<BPFReplayer*> GetBPFReplayer () const override { return replayer_.get (); }
379+
380+ virtual ~ReplayingBCCWrapperImpl () {}
381+
382+ ReplayingBCCWrapperImpl () { replayer_ = std::make_unique<BPFReplayer>(); }
383+
384+ StatusOr<ebpf::BPF *> BPF () override { return error::Internal (" Wrong impl." ); }
385+
386+ Status InitBPFProgram (std::string_view, std::vector<std::string> cflags = {},
387+ bool requires_linux_headers = true ,
388+ bool always_infer_task_struct_offsets = false ) override {
389+ PX_UNUSED (cflags);
390+ PX_UNUSED (requires_linux_headers);
391+ PX_UNUSED (always_infer_task_struct_offsets);
392+ return Status::OK ();
393+ }
394+ Status AttachKProbe (const KProbeSpec&) override { return Status::OK (); }
395+ Status AttachUProbe (const UProbeSpec&) override { return Status::OK (); }
396+ Status AttachTracepoint (const TracepointSpec&) override { return Status::OK (); }
397+ Status AttachSamplingProbe (const SamplingProbeSpec&) override { return Status::OK (); }
398+ Status AttachPerfEvent (const PerfEventSpec&) override { return Status::OK (); }
399+ Status AttachKProbes (const ArrayView<KProbeSpec>&) override { return Status::OK (); }
400+ Status AttachTracepoints (const ArrayView<TracepointSpec>&) override { return Status::OK (); }
401+ Status AttachUProbes (const ArrayView<UProbeSpec>&) override { return Status::OK (); }
402+ Status AttachSamplingProbes (const ArrayView<SamplingProbeSpec>&) override { return Status::OK (); }
403+ Status AttachXDP (const std::string&, const std::string&) override { return Status::OK (); }
404+ Status AttachPerfEvents (const ArrayView<PerfEventSpec>&) override { return Status::OK (); }
405+ Status PopulateBPFPerfArray (const std::string&, const uint32_t , const uint64_t ) override {
406+ return Status::OK ();
407+ }
408+
409+ Status OpenPerfBuffer (const PerfBufferSpec& pbs) override {
410+ perf_buffer_specs_.push_back (std::make_unique<PerfBufferSpec>(pbs));
411+ return Status::OK ();
412+ }
413+
414+ Status OpenPerfBuffers (const ArrayView<PerfBufferSpec>& perf_buffer_specs) override {
415+ for (const auto & pbs : perf_buffer_specs) {
416+ PX_RETURN_IF_ERROR (OpenPerfBuffer (pbs));
417+ }
418+ return Status::OK ();
419+ }
420+
421+ Status PollPerfBuffer (const std::string& name, const int timeout_ms = 0 ) override {
422+ PX_UNUSED (timeout_ms);
423+ for (const auto & pbs : perf_buffer_specs_) {
424+ if (pbs->name == name) {
425+ replayer_->ReplayPerfBufferEvents (*pbs);
426+ return Status::OK ();
427+ }
428+ }
429+ return error::NotFound (absl::Substitute (" Perf buffer \" $0\" not found." , name));
430+ }
431+
432+ void PollPerfBuffers (const int timeout_ms = 0 ) override {
433+ PX_UNUSED (timeout_ms);
434+ for (const auto & pbs : perf_buffer_specs_) {
435+ replayer_->ReplayPerfBufferEvents (*pbs);
436+ }
437+ };
438+
439+ void Close () override {};
440+
441+ Status ClosePerfBuffer (const PerfBufferSpec&) override { return Status::OK (); }
442+
443+ Status OpenReplayProtobuf (const std::string& file_path) {
444+ return replayer_->OpenReplayProtobuf (file_path);
445+ }
446+
447+ private:
448+ std::unique_ptr<BPFReplayer> replayer_;
449+ std::vector<std::unique_ptr<PerfBufferSpec>> perf_buffer_specs_;
450+ };
451+
346452std::unique_ptr<BCCWrapper> CreateBCC ();
347453
454+ // //////////////////////////////////////////////////////////////////////////////////////////////////
455+ // //////////////////////////////////////////////////////////////////////////////////////////////////
456+ // Array Table.
348457template <typename T>
349458class WrappedBCCArrayTable {
350459 public:
@@ -378,7 +487,8 @@ class WrappedBCCArrayTableImpl : public WrappedBCCArrayTable<T> {
378487 }
379488
380489 WrappedBCCArrayTableImpl (bpf_tools::BCCWrapper* bcc, const std::string& name) : name_(name) {
381- underlying_ = std::make_unique<U>(bcc->BPF ()->get_array_table <T>(name_));
490+ ebpf::BPF * bpf = bcc->BPF ().ConsumeValueOrDie ();
491+ underlying_ = std::make_unique<U>(bpf->get_array_table <T>(name_));
382492 }
383493
384494 protected:
@@ -389,6 +499,9 @@ class WrappedBCCArrayTableImpl : public WrappedBCCArrayTable<T> {
389499 std::unique_ptr<U> underlying_;
390500};
391501
502+ // //////////////////////////////////////////////////////////////////////////////////////////////////
503+ // //////////////////////////////////////////////////////////////////////////////////////////////////
504+ // Map / BPF Hash Table
392505template <typename K, typename V, bool kUserSpaceManaged = false >
393506class WrappedBCCMap {
394507 public:
@@ -472,7 +585,8 @@ class WrappedBCCMapImpl : public WrappedBCCMap<K, V, kUserSpaceManaged> {
472585 }
473586
474587 WrappedBCCMapImpl (bpf_tools::BCCWrapper* bcc, const std::string& name) : name_(name) {
475- underlying_ = std::make_unique<U>(bcc->BPF ()->get_hash_table <K, V>(name_));
588+ ebpf::BPF * bpf = bcc->BPF ().ConsumeValueOrDie ();
589+ underlying_ = std::make_unique<U>(bpf->get_hash_table <K, V>(name_));
476590 }
477591
478592 protected:
@@ -484,6 +598,9 @@ class WrappedBCCMapImpl : public WrappedBCCMap<K, V, kUserSpaceManaged> {
484598 absl::flat_hash_set<K> shadow_keys_;
485599};
486600
601+ // //////////////////////////////////////////////////////////////////////////////////////////////////
602+ // //////////////////////////////////////////////////////////////////////////////////////////////////
603+ // Per CPU Array Table
487604template <typename T>
488605class WrappedBCCPerCPUArrayTable {
489606 public:
@@ -511,14 +628,18 @@ class WrappedBCCPerCPUArrayTableImpl : public WrappedBCCPerCPUArrayTable<T> {
511628
512629 WrappedBCCPerCPUArrayTableImpl (bpf_tools::BCCWrapper* bcc, const std::string& name)
513630 : name_(name) {
514- underlying_ = std::make_unique<U>(bcc->BPF ()->get_percpu_array_table <T>(name_));
631+ ebpf::BPF * bpf = bcc->BPF ().ConsumeValueOrDie ();
632+ underlying_ = std::make_unique<U>(bpf->get_percpu_array_table <T>(name_));
515633 }
516634
517635 private:
518636 const std::string name_;
519637 std::unique_ptr<U> underlying_;
520638};
521639
640+ // //////////////////////////////////////////////////////////////////////////////////////////////////
641+ // //////////////////////////////////////////////////////////////////////////////////////////////////
642+ // Stack Table
522643class WrappedBCCStackTable {
523644 public:
524645 static std::unique_ptr<WrappedBCCStackTable> Create (bpf_tools::BCCWrapper* bcc,
@@ -545,7 +666,8 @@ class WrappedBCCStackTableImpl : public WrappedBCCStackTable {
545666 void ClearStackID (const int stack_id) override { underlying_->clear_stack_id (stack_id); }
546667
547668 WrappedBCCStackTableImpl (bpf_tools::BCCWrapper* bcc, const std::string& name) : name_(name) {
548- underlying_ = std::make_unique<U>(bcc->BPF ()->get_stack_table (name_));
669+ ebpf::BPF * bpf = bcc->BPF ().ConsumeValueOrDie ();
670+ underlying_ = std::make_unique<U>(bpf->get_stack_table (name_));
549671 }
550672
551673 protected:
@@ -555,7 +677,16 @@ class WrappedBCCStackTableImpl : public WrappedBCCStackTable {
555677 std::unique_ptr<U> underlying_;
556678};
557679
680+ // //////////////////////////////////////////////////////////////////////////////////////////////////
681+ // //////////////////////////////////////////////////////////////////////////////////////////////////
558682// Creators fns for wrapped maps & arrays:
683+ // template <typename BaseT, typename ImplT>
684+ // std::unique_ptr<BaseT> CreateBCCWrappedMapOrArray(BCCWrapper* bcc, const std::string& name) {
685+ // // The decision logic for "normal" vs. "recording" vs. "replaying" impl. will be inserted
686+ // // here in a future PR.
687+ // return std::make_unique<ImplT>(bcc, name);
688+ // }
689+
559690template <typename BaseT, typename ImplT>
560691std::unique_ptr<BaseT> CreateBCCWrappedMapOrArray (BCCWrapper* bcc, const std::string& name) {
561692 return std::make_unique<ImplT>(bcc, name);
0 commit comments