summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Boric <jblbeurope@gmail.com>2021-08-10 21:02:59 +0200
committerAndreas Kling <kling@serenityos.org>2021-08-10 21:55:48 +0200
commit0286160b62dd4871ddddd89276398739d7d737b0 (patch)
tree020c7d332ce12f51e92a9625584799a161660968
parent4c4b8ea443bceb14e041e6d4e6b6a56988aad0c7 (diff)
downloadserenity-0286160b62dd4871ddddd89276398739d7d737b0.zip
Kernel: Add syscall performance event type
This allows tracing the syscalls made by a thread through the kernel's performance event framework, which is similar in principle to strace. Currently, this merely logs a stack backtrace to the current thread's performance event buffer whenever a syscall is made, if profiling is enabled. Future improvements could include tracing the arguments and the return value, for example.
-rw-r--r--Kernel/PerformanceEventBuffer.cpp5
-rw-r--r--Kernel/PerformanceManager.h11
-rw-r--r--Kernel/Syscall.cpp3
-rw-r--r--Kernel/UnixTypes.h1
-rw-r--r--Userland/Libraries/LibC/serenity.h1
-rw-r--r--Userland/Utilities/profile.cpp4
6 files changed, 24 insertions, 1 deletions
diff --git a/Kernel/PerformanceEventBuffer.cpp b/Kernel/PerformanceEventBuffer.cpp
index 0e5e3cb3a4..f461ad8db9 100644
--- a/Kernel/PerformanceEventBuffer.cpp
+++ b/Kernel/PerformanceEventBuffer.cpp
@@ -135,6 +135,8 @@ KResult PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, ThreadID ti
break;
case PERF_EVENT_PAGE_FAULT:
break;
+ case PERF_EVENT_SYSCALL:
+ break;
default:
return EINVAL;
}
@@ -226,6 +228,9 @@ bool PerformanceEventBuffer::to_json_impl(Serializer& object) const
case PERF_EVENT_PAGE_FAULT:
event_object.add("type", "page_fault");
break;
+ case PERF_EVENT_SYSCALL:
+ event_object.add("type", "syscall");
+ break;
}
event_object.add("pid", event.pid);
event_object.add("tid", event.tid);
diff --git a/Kernel/PerformanceManager.h b/Kernel/PerformanceManager.h
index 7157d0e655..c05ad84d29 100644
--- a/Kernel/PerformanceManager.h
+++ b/Kernel/PerformanceManager.h
@@ -119,6 +119,17 @@ public:
}
}
+ inline static void add_syscall_event(Thread& thread, const RegisterState& regs)
+ {
+ if (thread.is_profiling_suppressed())
+ return;
+ if (auto* event_buffer = thread.process().current_perf_events_buffer()) {
+ [[maybe_unused]] auto rc = event_buffer->append_with_ip_and_bp(
+ thread.pid(), thread.tid(),
+ regs.ip(), regs.bp(), PERF_EVENT_SYSCALL, 0, 0, 0, nullptr);
+ }
+ }
+
inline static void timer_tick(RegisterState const& regs)
{
static Time last_wakeup;
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index 58f6e80f1a..6c71c0b94e 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -9,6 +9,7 @@
#include <Kernel/Arch/x86/TrapFrame.h>
#include <Kernel/Memory/MemoryManager.h>
#include <Kernel/Panic.h>
+#include <Kernel/PerformanceManager.h>
#include <Kernel/Process.h>
#include <Kernel/Sections.h>
#include <Kernel/ThreadTracer.h>
@@ -108,6 +109,8 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
auto& process = current_thread->process();
current_thread->did_syscall();
+ PerformanceManager::add_syscall_event(*current_thread, regs);
+
if (function >= Function::__Count) {
dbgln("Unknown syscall {} requested ({:p}, {:p}, {:p}, {:p})", function, arg1, arg2, arg3, arg4);
return ENOSYS;
diff --git a/Kernel/UnixTypes.h b/Kernel/UnixTypes.h
index 44a3351a8a..9ebc56bca8 100644
--- a/Kernel/UnixTypes.h
+++ b/Kernel/UnixTypes.h
@@ -62,6 +62,7 @@ enum {
PERF_EVENT_KMALLOC = 2048,
PERF_EVENT_KFREE = 4096,
PERF_EVENT_PAGE_FAULT = 8192,
+ PERF_EVENT_SYSCALL = 16384,
};
#define WNOHANG 1
diff --git a/Userland/Libraries/LibC/serenity.h b/Userland/Libraries/LibC/serenity.h
index 649c0914eb..a2533479d6 100644
--- a/Userland/Libraries/LibC/serenity.h
+++ b/Userland/Libraries/LibC/serenity.h
@@ -112,6 +112,7 @@ enum {
PERF_EVENT_KMALLOC = 2048,
PERF_EVENT_KFREE = 4096,
PERF_EVENT_PAGE_FAULT = 8192,
+ PERF_EVENT_SYSCALL = 16384,
};
#define PERF_EVENT_MASK_ALL (~0ull)
diff --git a/Userland/Utilities/profile.cpp b/Userland/Utilities/profile.cpp
index d1362ef8da..e11eac5d15 100644
--- a/Userland/Utilities/profile.cpp
+++ b/Userland/Utilities/profile.cpp
@@ -45,6 +45,8 @@ int main(int argc, char** argv)
event_mask |= PERF_EVENT_KFREE;
else if (event_type == "page_fault")
event_mask |= PERF_EVENT_PAGE_FAULT;
+ else if (event_type == "syscall")
+ event_mask |= PERF_EVENT_SYSCALL;
else {
warnln("Unknown event type '{}' specified.", event_type);
exit(1);
@@ -54,7 +56,7 @@ int main(int argc, char** argv)
auto print_types = [] {
outln();
- outln("Event type can be one of: sample, context_switch, page_fault, kmalloc and kfree.");
+ outln("Event type can be one of: sample, context_switch, page_fault, syscall, kmalloc and kfree.");
};
if (!args_parser.parse(argc, argv, Core::ArgsParser::FailureBehavior::PrintUsage)) {