The Pedigree Project 0.1
syscall-trace.h
1#ifndef POSIX_SYSCALL_TRACE_H
2#define POSIX_SYSCALL_TRACE_H
3
4#include "pedigree/kernel/Log.h"
5#include "pedigree/kernel/process/Process.h"
6#include "pedigree/kernel/process/Thread.h"
7#include "pedigree/kernel/processor/state.h"
8#include "pedigree/kernel/time/Time.h"
9
10#include "PosixSubsystem.h"
11#include "syscalls/translate.h"
12
13namespace {
14class SyscallTrace {
15 public:
16 SyscallTrace(SyscallState& state, Thread& thread) {
17 static uint64_t nextId = 0;
18 m_Id = __atomic_add_fetch(&nextId, static_cast<uint64_t>(1), __ATOMIC_RELAXED);
19
20 const bool linuxAbi = state.getSyscallService() == linuxCompat;
21 const uintptr_t number = state.getSyscallNumber();
22 const size_t base = linuxAbi ? 6 : 0;
23 uintptr_t arguments[6];
24 for (size_t i = 0; i < 6; ++i) {
25 arguments[i] = state.getSyscallParameter(base + i);
26 }
27
28 NOTICE("STRACE E id=" << Hex << m_Id << " pid=" << thread.getParent()->getId()
29 << " tid=" << thread.getId() << " abi=" << (linuxAbi ? "L" : "P")
30 << " nr=" << number);
31 for (size_t i = 0; i < 6; i += 3) {
32 NOTICE("STRACE A id=" << Hex << m_Id << " n=" << i << " x=" << arguments[i]
33 << " y=" << arguments[i + 1] << " z=" << arguments[i + 2]);
34 }
35
36 if (linuxAbi) {
37 const unsigned paths = pathArguments(number);
38 for (size_t i = 0; i < 6; ++i) {
39 if (paths & (1U << i)) {
40 path(i, reinterpret_cast<const char*>(arguments[i]));
41 }
42 }
43 }
44 }
45
46 void finish(uintptr_t result, int error, Time::Timestamp elapsed) const {
47 // Exec and exit return a deferred action here, not a userspace return value.
48 NOTICE("STRACE X id=" << Hex << m_Id << " raw=" << result
49 << " err=" << static_cast<unsigned>(error) << " ns=" << elapsed);
50 }
51
52 private:
53 static unsigned pathArguments(uintptr_t number) {
54 switch (number) {
55 case PedigreeLinuxAmd64Syscall_open:
56 case PedigreeLinuxAmd64Syscall_stat:
57 case PedigreeLinuxAmd64Syscall_lstat:
58 case PedigreeLinuxAmd64Syscall_access:
59 case PedigreeLinuxAmd64Syscall_execve:
60 case PedigreeLinuxAmd64Syscall_chdir:
61 case PedigreeLinuxAmd64Syscall_mkdir:
62 case PedigreeLinuxAmd64Syscall_rmdir:
63 case PedigreeLinuxAmd64Syscall_creat:
64 case PedigreeLinuxAmd64Syscall_unlink:
65 case PedigreeLinuxAmd64Syscall_readlink:
66 case PedigreeLinuxAmd64Syscall_chmod:
67 case PedigreeLinuxAmd64Syscall_chown:
68 case PedigreeLinuxAmd64Syscall_lchown:
69 case PedigreeLinuxAmd64Syscall_utime:
70 case PedigreeLinuxAmd64Syscall_utimes:
71 case PedigreeLinuxAmd64Syscall_statfs:
72 case PedigreeLinuxAmd64Syscall_chroot:
73 case PedigreeLinuxAmd64Syscall_truncate:
74 case PedigreeLinuxAmd64Syscall_mknod:
75 case PedigreeLinuxAmd64Syscall_umount2:
76 case PedigreeLinuxAmd64Syscall_swapon:
77 case PedigreeLinuxAmd64Syscall_swapoff:
78 case PedigreeLinuxAmd64Syscall_acct:
79 case PedigreeLinuxAmd64Syscall_setxattr:
80 case PedigreeLinuxAmd64Syscall_lsetxattr:
81 case PedigreeLinuxAmd64Syscall_getxattr:
82 case PedigreeLinuxAmd64Syscall_lgetxattr:
83 case PedigreeLinuxAmd64Syscall_listxattr:
84 case PedigreeLinuxAmd64Syscall_llistxattr:
85 case PedigreeLinuxAmd64Syscall_removexattr:
86 case PedigreeLinuxAmd64Syscall_lremovexattr:
87 return 1U;
88 case PedigreeLinuxAmd64Syscall_rename:
89 case PedigreeLinuxAmd64Syscall_link:
90 case PedigreeLinuxAmd64Syscall_symlink:
91 case PedigreeLinuxAmd64Syscall_pivot_root:
92 case PedigreeLinuxAmd64Syscall_mount:
93 return (1U << 0) | (1U << 1);
94 case PedigreeLinuxAmd64Syscall_openat:
95 case PedigreeLinuxAmd64Syscall_mkdirat:
96 case PedigreeLinuxAmd64Syscall_fchownat:
97 case PedigreeLinuxAmd64Syscall_futimesat:
98 case PedigreeLinuxAmd64Syscall_newfstatat:
99 case PedigreeLinuxAmd64Syscall_unlinkat:
100 case PedigreeLinuxAmd64Syscall_readlinkat:
101 case PedigreeLinuxAmd64Syscall_fchmodat:
102 case PedigreeLinuxAmd64Syscall_faccessat:
103 case PedigreeLinuxAmd64Syscall_faccessat2:
104 case PedigreeLinuxAmd64Syscall_execveat:
105 case PedigreeLinuxAmd64Syscall_utimensat:
106 case PedigreeLinuxAmd64Syscall_statx:
107 case PedigreeLinuxAmd64Syscall_fchmodat2:
108 case PedigreeLinuxAmd64Syscall_mknodat:
109 case PedigreeLinuxAmd64Syscall_name_to_handle_at:
110 case PedigreeLinuxAmd64Syscall_inotify_add_watch:
111 return 1U << 1;
112 case PedigreeLinuxAmd64Syscall_renameat:
113 case PedigreeLinuxAmd64Syscall_linkat:
114 case PedigreeLinuxAmd64Syscall_renameat2:
115 return (1U << 1) | (1U << 3);
116 case PedigreeLinuxAmd64Syscall_symlinkat:
117 return (1U << 0) | (1U << 2);
118 default:
119 return 0;
120 }
121 }
122
123 void path(size_t argument, const char* address) const {
124 String copy;
125 const auto result = PosixSubsystem::copyUserString(address, copy, 256);
126 const char* status = result == PosixSubsystem::UserStringSuccess ? "ok"
127 : result == PosixSubsystem::UserStringTooLong ? "truncated"
128 : "invalid";
129 constexpr char digits[] = "0123456789abcdef";
130 // Each chunk fits LOG_LENGTH even with a full-width record identifier.
131 for (size_t offset = 0; offset < copy.length(); offset += 32) {
132 const size_t remaining = copy.length() - offset;
133 const size_t count = remaining < 32 ? remaining : 32;
134 char data[65];
135 for (size_t i = 0; i < count; ++i) {
136 const uint8_t byte = static_cast<uint8_t>(copy[offset + i]);
137 data[i * 2] = digits[byte >> 4];
138 data[i * 2 + 1] = digits[byte & 15];
139 }
140 data[count * 2] = '\0';
141 NOTICE("STRACE P id=" << Hex << m_Id << " arg=" << argument << " off=" << offset
142 << " data=" << data);
143 }
144 NOTICE("STRACE S id=" << Hex << m_Id << " arg=" << argument << " status=" << status);
145 }
146
147 uint64_t m_Id;
148};
149} // namespace
150
151#endif
static UserStringResult copyUserString(const char *userString, String &copy, size_t maxLength)
size_t getId()
Definition Process.h:499
Process * getParent() const
Definition Thread.h:340
size_t getId()
Definition Thread.h:465
@ Hex
Definition Log.h:124