Skip to content

Commit

Permalink
Ksymbol support: convert ksymbol events into mmap
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 634592878
  • Loading branch information
ghanzouri authored and gmarin13 committed Jun 13, 2024
1 parent 3a24d89 commit 590f10c
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 1 deletion.
47 changes: 46 additions & 1 deletion src/perf_data_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

#include "src/perf_data_handler.h"

#include <sys/mman.h>

#include <cstdint>
#include <cstdio>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <memory>
#include <regex>
#include <sstream>
Expand Down Expand Up @@ -196,6 +201,10 @@ class Normalizer {
// finds the build ID according to the filename from the mmap.
BuildId GetBuildId(const quipper::PerfDataProto_MMapEvent* mmap);

void ConvertMmapFromKsymbol(
const quipper::PerfDataProto_KsymbolEvent& ksymbol_event, uint32_t prot,
quipper::PerfDataProto_MMapEvent* mmap);

// Copy the parent's mmaps/comm if they exist. Otherwise, items
// will be lazily populated.
void UpdateMapsWithMMapEvent(const quipper::PerfDataProto_MMapEvent* mmap);
Expand All @@ -214,6 +223,9 @@ class Normalizer {
// records to parse potential samples.
void HandleSpeAuxtrace(const quipper::PerfDataProto::PerfEvent& event_proto);

// Handles the ksymbol event in event_proto.
void HandleKsymbol(const quipper::PerfDataProto::PerfEvent& event_proto);

// Handles the perf LOST event or LOST_SAMPLE event.
void HandleLost(const quipper::PerfDataProto::PerfEvent& event_proto);

Expand Down Expand Up @@ -449,6 +461,8 @@ void Normalizer::Normalize() {
} else if (event_proto.has_auxtrace_error_event()) {
LOG(WARNING) << "auxtrace_error event: "
<< event_proto.auxtrace_error_event().msg();
} else if (event_proto.has_ksymbol_event()) {
HandleKsymbol(event_proto);
}
}

Expand Down Expand Up @@ -535,7 +549,7 @@ void Normalizer::HandleSample(
context.branch_stack.resize(sample.branch_stack_size());
for (int i = 0; i < sample.branch_stack_size(); ++i) {
stat_.branch_stack_ips += 2;
auto entry = sample.branch_stack(i);
const auto& entry = sample.branch_stack(i);
// from
context.branch_stack[i].from.ip = entry.from_ip();
context.branch_stack[i].from.mapping =
Expand Down Expand Up @@ -714,6 +728,25 @@ static bool IsVirtualMapping(const std::string& map_name) {
HasPrefixString(map_name, "[anon:");
}

void Normalizer::ConvertMmapFromKsymbol(
const quipper::PerfDataProto_KsymbolEvent& ksymbol_event, uint32_t prot,
quipper::PerfDataProto_MMapEvent* mmap) {
uint32_t pid = 1;
uint32_t tid = 1;
uint32_t flags = 0;
uint64_t pgoff = 0;
mmap->set_pid(pid);
mmap->set_tid(tid);
mmap->set_flags(flags);
mmap->set_pgoff(pgoff);
mmap->set_prot(prot);
mmap->set_start(ksymbol_event.addr());
mmap->set_len(ksymbol_event.len());
// TODO(go/gwp-bpf-name-breakdown): Need to do post-processing on `filename`.
mmap->set_filename(ksymbol_event.name());
*mmap->mutable_sample_info() = ksymbol_event.sample_info();
}

void Normalizer::UpdateMapsWithMMapEvent(
const quipper::PerfDataProto_MMapEvent* mmap) {
if (mmap->len() == 0) {
Expand Down Expand Up @@ -920,6 +953,18 @@ void Normalizer::HandleSpeAuxtrace(
}
}

void Normalizer::HandleKsymbol(
const quipper::PerfDataProto::PerfEvent& event_proto) {
quipper::PerfDataProto_MMapEvent mmap;
if (event_proto.ksymbol_event().ksym_type() ==
quipper::PERF_RECORD_KSYMBOL_TYPE_BPF &&
event_proto.ksymbol_event().flags() == 0) {
uint32_t prot = PROT_EXEC | PROT_READ;
ConvertMmapFromKsymbol(event_proto.ksymbol_event(), prot, &mmap);
UpdateMapsWithMMapEvent(&mmap);
}
}

} // namespace

// Finds needle in haystack starting at cursor. It then returns the index
Expand Down
33 changes: 33 additions & 0 deletions src/perf_data_handler_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ class TestPerfDataHandler : public PerfDataHandler {
}
}

void CheckNotEmptyFilenames() {
EXPECT_EQ(1, seen_filenames_.size());
for (auto const& filename : seen_filenames_) {
EXPECT_TRUE(expected_filename_to_build_id_.find(filename) !=
expected_filename_to_build_id_.end());
}
}

const std::vector<std::unique_ptr<Mapping>>& SeenAddrMappings() const {
return seen_addr_mappings_;
}
Expand Down Expand Up @@ -550,6 +558,31 @@ TEST(PerfDataHandlerTest, SpeAuxtraceIntoSamples) {
EXPECT_EQ(sample_events[1].pid(), 2);
}

TEST(PerfDataHandlerTest, KsymbolIntoMappings) {
quipper::PerfDataProto proto;
std::string mock_filename = "bpf_prog_bec4c5629f7c7e2d_netcg_bind4";

// File attrs are required for sample event processing.
uint64_t file_attr_id = 0;
auto* file_attr = proto.add_file_attrs();
file_attr->add_ids(file_attr_id);

// Add a ksymbol event.
auto* ksymbol_event = proto.add_events()->mutable_ksymbol_event();
ksymbol_event->set_addr(0x1000);
ksymbol_event->set_len(0x500);
ksymbol_event->set_ksym_type(quipper::PERF_RECORD_KSYMBOL_TYPE_BPF);
ksymbol_event->set_flags(0);
ksymbol_event->set_name(mock_filename);

std::unordered_map<std::string, std::string> expected_filename_to_build_id;
expected_filename_to_build_id[mock_filename] = "";
TestPerfDataHandler handler(std::vector<BranchStackEntry>{},
expected_filename_to_build_id);
PerfDataHandler::Process(proto, &handler);
handler.CheckSeenFilenames();
}

} // namespace perftools

int main(int argc, char** argv) {
Expand Down

0 comments on commit 590f10c

Please sign in to comment.