summaryrefslogtreecommitdiff
path: root/simpleperf
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2020-10-19 14:50:54 -0700
committerYabin Cui <yabinc@google.com>2020-10-19 15:00:35 -0700
commit68534b9e796819477b0cc985491c9624ae50c5dc (patch)
tree52861efb7b89b963b58ddabffb24b90623115123 /simpleperf
parentbc8a4a3be6c779c01555858b641214eec80bad85 (diff)
downloadextras-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
Diffstat (limited to 'simpleperf')
-rw-r--r--simpleperf/ProbeEvents.cpp20
-rw-r--r--simpleperf/ProbeEvents.h4
-rw-r--r--simpleperf/cmd_record.cpp12
-rw-r--r--simpleperf/cmd_record_test.cpp3
-rw-r--r--simpleperf/event_type.cpp9
-rw-r--r--simpleperf/event_type.h2
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);