diff options
author | Yabin Cui <yabinc@google.com> | 2020-10-19 14:50:54 -0700 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2020-10-19 15:00:35 -0700 |
commit | 68534b9e796819477b0cc985491c9624ae50c5dc (patch) | |
tree | 52861efb7b89b963b58ddabffb24b90623115123 | |
parent | bc8a4a3be6c779c01555858b641214eec80bad85 (diff) | |
download | extras-68534b9e796819477b0cc985491c9624ae50c5dc.tar.gz |
simpleperf: add shortcut for creating kprobe events.
When using a kprobe event without any arguments, a --kprobe option
isn't needed. For example, when "-e kprobes:do_sys_open" is used
without --kprobe, a default kprobe event is created at the entry
of do_sys_open().
Bug: 160630060
Test: run simpleperf_unit_test.
Change-Id: I62f5616c423ecb104d64a425fbd52e38e57e993e
-rw-r--r-- | simpleperf/ProbeEvents.cpp | 20 | ||||
-rw-r--r-- | simpleperf/ProbeEvents.h | 4 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 12 | ||||
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 3 | ||||
-rw-r--r-- | simpleperf/event_type.cpp | 9 | ||||
-rw-r--r-- | simpleperf/event_type.h | 2 |
6 files changed, 44 insertions, 6 deletions
diff --git a/simpleperf/ProbeEvents.cpp b/simpleperf/ProbeEvents.cpp index 5659b7e4..c09652a5 100644 --- a/simpleperf/ProbeEvents.cpp +++ b/simpleperf/ProbeEvents.cpp @@ -30,6 +30,7 @@ #include <android-base/unique_fd.h> #include "environment.h" +#include "event_type.h" #include "utils.h" using android::base::ParseInt; @@ -42,6 +43,8 @@ using namespace simpleperf; namespace simpleperf { +static const std::string kKprobeEventPrefix = "kprobes:"; + bool ProbeEvents::ParseKprobeEventName(const std::string& kprobe_cmd, ProbeEvent* event) { // kprobe_cmd is in formats described in <kernel>/Documentation/trace/kprobetrace.rst: // p[:[GRP/]EVENT] [MOD:]SYM[+offs]|MEMADDR [FETCHARGS] @@ -116,12 +119,26 @@ bool ProbeEvents::AddKprobe(const std::string& kprobe_cmd) { return true; } +bool ProbeEvents::IsProbeEvent(const std::string& event_name) { + return android::base::StartsWith(event_name, kKprobeEventPrefix); +} + +bool ProbeEvents::CreateProbeEventIfNotExist(const std::string& event_name) { + if (EventTypeManager::Instance().FindType(event_name) != nullptr) { + return true; + } + std::string function_name = event_name.substr(kKprobeEventPrefix.size()); + return AddKprobe(StringPrintf("p:%s %s", function_name.c_str(), function_name.c_str())); +} + void ProbeEvents::Clear() { for (const auto& kprobe_event : kprobe_events_) { if (!WriteKprobeCmd("-:" + kprobe_event.group_name + "/" + kprobe_event.event_name)) { LOG(WARNING) << "failed to delete kprobe event " << kprobe_event.group_name << ":" << kprobe_event.event_name; } + EventTypeManager::Instance().RemoveProbeType(kprobe_event.group_name + ":" + + kprobe_event.event_name); } kprobe_events_.clear(); } @@ -141,9 +158,6 @@ bool ProbeEvents::WriteKprobeCmd(const std::string& kprobe_cmd) { PLOG(ERROR) << "failed to write '" << kprobe_cmd << "' to " << path; return false; } - fd.reset(); - std::string data; - android::base::ReadFileToString(path, &data); return true; } diff --git a/simpleperf/ProbeEvents.h b/simpleperf/ProbeEvents.h index 1f47acd9..39fa65f2 100644 --- a/simpleperf/ProbeEvents.h +++ b/simpleperf/ProbeEvents.h @@ -38,7 +38,9 @@ class ProbeEvents { // Accept kprobe cmd as in <linux_kernel>/Documentation/trace/kprobetrace.rst. bool AddKprobe(const std::string& kprobe_cmd); - + bool IsProbeEvent(const std::string& event_name); + // If not exist, add a kprobe tracepoint at the function entry. + bool CreateProbeEventIfNotExist(const std::string& event_name); bool IsEmpty() const { return kprobe_events_.empty(); } void Clear(); diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 8935a971..1262fafc 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -989,6 +989,11 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args, } else if (name == "-e") { std::vector<std::string> event_types = android::base::Split(*value.str_value, ","); for (auto& event_type : event_types) { + if (probe_events->IsProbeEvent(event_type)) { + if (!probe_events->CreateProbeEventIfNotExist(event_type)) { + return false; + } + } size_t group_id; if (!event_selection_set_.AddEventType(event_type, &group_id)) { return false; @@ -1005,6 +1010,13 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args, dwarf_callchain_sampling_ = true; } else if (name == "--group") { std::vector<std::string> event_types = android::base::Split(*value.str_value, ","); + for (const auto& event_type : event_types) { + if (probe_events->IsProbeEvent(event_type)) { + if (!probe_events->CreateProbeEventIfNotExist(event_type)) { + return false; + } + } + } size_t group_id; if (!event_selection_set_.AddEventGroup(event_types, &group_id)) { return false; diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index 75a33ea5..bcb845f2 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -1137,4 +1137,7 @@ TEST(record_cmd, kprobe_option) { return; } ASSERT_TRUE(RunRecordCmd({"-e", "kprobes:myprobe", "--kprobe", "p:myprobe do_sys_open"})); + // A default kprobe event is created if not given an explicit --kprobe option. + ASSERT_TRUE(RunRecordCmd({"-e", "kprobes:do_sys_open"})); + ASSERT_TRUE(RunRecordCmd({"--group", "kprobes:do_sys_open"})); } diff --git a/simpleperf/event_type.cpp b/simpleperf/event_type.cpp index 97473aaf..44ed8163 100644 --- a/simpleperf/event_type.cpp +++ b/simpleperf/event_type.cpp @@ -142,13 +142,16 @@ class TracepointSystemFinder : public EventTypeFinder { std::string path = tracefs_dir + std::string("/events/") + strs[0] + "/" + strs[1] + "/id"; uint64_t id; if (!ReadEventId(path, &id)) { - LOG(ERROR) << "failed to read event id"; return nullptr; } auto res = types_.emplace(name, PERF_TYPE_TRACEPOINT, id, "", ""); return &*res.first; } + void RemoveType(const std::string& name) { + types_.erase(EventType(name, 0, 0, "", "")); + } + std::string ToString() { std::string result; for (auto& type : GetTypes()) { @@ -439,6 +442,10 @@ const EventType* EventTypeManager::AddRawType(const std::string& name) { return raw_finder.AddType(EventType(name, PERF_TYPE_RAW, config, "", "")); } +void EventTypeManager::RemoveProbeType(const std::string& name) { + GetTracepointSystemFinder().RemoveType(name); +} + void EventTypeManager::SetScopedFinder(std::unique_ptr<EventTypeFinder>&& finder) { scoped_finder_ = std::move(finder); } diff --git a/simpleperf/event_type.h b/simpleperf/event_type.h index cd16d45b..933b1c32 100644 --- a/simpleperf/event_type.h +++ b/simpleperf/event_type.h @@ -109,8 +109,8 @@ class EventTypeManager { // Iterate through all event types, and stop when callback returns false. bool ForEachType(const std::function<bool (const EventType&)>& callback); const EventType* FindType(const std::string& name); - const EventType* AddRawType(const std::string& name); + void RemoveProbeType(const std::string& name); const EventTypeFinder* GetScopedFinder() { return scoped_finder_.get(); } void SetScopedFinder(std::unique_ptr<EventTypeFinder>&& finder); |