summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-05-02 15:51:39 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-05-02 15:51:39 +0200
commit2a65f0ee4fa7d4eebd57a955fbd8db016c0c6fdb (patch)
tree7033f029f0c300ed645183d0cc335ebd81721b63 /Userland
parent25ddcd1022032d5b0620cdd8fee5e336b6292742 (diff)
downloadserenity-2a65f0ee4fa7d4eebd57a955fbd8db016c0c6fdb.zip
strace: Allow "strace command" to trace a process from start to finish.
Tracing a specific pid is now done via "strace -p PID". To ensure we don't miss any syscalls, we fork and have the child immediately SIGSTOP itself. Then when the parent has set up the systrace() fd, we send SIGCONT to the child which then execs the command. :^)
Diffstat (limited to 'Userland')
-rw-r--r--Userland/strace.cpp44
1 files changed, 40 insertions, 4 deletions
diff --git a/Userland/strace.cpp b/Userland/strace.cpp
index 374ac1cf80..bd8b9cf61b 100644
--- a/Userland/strace.cpp
+++ b/Userland/strace.cpp
@@ -1,22 +1,58 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
#include <AK/Assertions.h>
#include <AK/Types.h>
#include <Kernel/Syscall.h>
+static int usage()
+{
+ printf("usage: strace [-p PID] [command...]\n");
+ return 0;
+}
+
int main(int argc, char** argv)
{
- if (argc < 2)
- return 1;
+ if (argc == 1)
+ return usage();
+
+ pid_t pid = -1;
+ bool pid_is_child = false;
+
+ if (!strcmp(argv[1], "-p")) {
+ if (argc != 3)
+ return usage();
+ pid = atoi(argv[2]);
+ } else {
+ pid_is_child = true;
+ pid = fork();
+ if (!pid) {
+ kill(getpid(), SIGSTOP);
+ int rc = execvp(argv[1], &argv[1]);
+ if (rc < 0) {
+ perror("execvp");
+ exit(1);
+ }
+ ASSERT_NOT_REACHED();
+ }
+ }
- int pid = atoi(argv[1]);
int fd = systrace(pid);
if (fd < 0) {
perror("systrace");
return 1;
}
+ if (pid_is_child) {
+ int rc = kill(pid, SIGCONT);
+ if (rc < 0) {
+ perror("kill(pid, SIGCONT)");
+ return 1;
+ }
+ }
+
for (;;) {
dword call[5];
int nread = read(fd, &call, sizeof(call));
@@ -27,7 +63,7 @@ int main(int argc, char** argv)
return 1;
}
ASSERT(nread == sizeof(call));
- printf("%s(%#x, %#x, %#x) = %#x\n", Syscall::to_string((Syscall::Function)call[0]), call[1], call[2], call[3], call[4]);
+ fprintf(stderr, "%s(%#x, %#x, %#x) = %#x\n", Syscall::to_string((Syscall::Function)call[0]), call[1], call[2], call[3], call[4]);
}
int rc = close(fd);