Skip to content

Commit 2a65f0e

Browse files
committed
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. :^)
1 parent 25ddcd1 commit 2a65f0e

File tree

1 file changed

+40
-4
lines changed

1 file changed

+40
-4
lines changed

Userland/strace.cpp

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,58 @@
11
#include <stdio.h>
22
#include <unistd.h>
33
#include <stdlib.h>
4+
#include <string.h>
5+
#include <signal.h>
46
#include <AK/Assertions.h>
57
#include <AK/Types.h>
68
#include <Kernel/Syscall.h>
79

10+
static int usage()
11+
{
12+
printf("usage: strace [-p PID] [command...]\n");
13+
return 0;
14+
}
15+
816
int main(int argc, char** argv)
917
{
10-
if (argc < 2)
11-
return 1;
18+
if (argc == 1)
19+
return usage();
20+
21+
pid_t pid = -1;
22+
bool pid_is_child = false;
23+
24+
if (!strcmp(argv[1], "-p")) {
25+
if (argc != 3)
26+
return usage();
27+
pid = atoi(argv[2]);
28+
} else {
29+
pid_is_child = true;
30+
pid = fork();
31+
if (!pid) {
32+
kill(getpid(), SIGSTOP);
33+
int rc = execvp(argv[1], &argv[1]);
34+
if (rc < 0) {
35+
perror("execvp");
36+
exit(1);
37+
}
38+
ASSERT_NOT_REACHED();
39+
}
40+
}
1241

13-
int pid = atoi(argv[1]);
1442
int fd = systrace(pid);
1543
if (fd < 0) {
1644
perror("systrace");
1745
return 1;
1846
}
1947

48+
if (pid_is_child) {
49+
int rc = kill(pid, SIGCONT);
50+
if (rc < 0) {
51+
perror("kill(pid, SIGCONT)");
52+
return 1;
53+
}
54+
}
55+
2056
for (;;) {
2157
dword call[5];
2258
int nread = read(fd, &call, sizeof(call));
@@ -27,7 +63,7 @@ int main(int argc, char** argv)
2763
return 1;
2864
}
2965
ASSERT(nread == sizeof(call));
30-
printf("%s(%#x, %#x, %#x) = %#x\n", Syscall::to_string((Syscall::Function)call[0]), call[1], call[2], call[3], call[4]);
66+
fprintf(stderr, "%s(%#x, %#x, %#x) = %#x\n", Syscall::to_string((Syscall::Function)call[0]), call[1], call[2], call[3], call[4]);
3167
}
3268

3369
int rc = close(fd);

0 commit comments

Comments
 (0)