xref: /aosp_15_r20/external/toybox/toys/pending/strace.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1*cf5a6c84SAndroid Build Coastguard Worker /* strace.c - Trace system calls.
2*cf5a6c84SAndroid Build Coastguard Worker  *
3*cf5a6c84SAndroid Build Coastguard Worker  * Copyright 2020 The Android Open Source Project
4*cf5a6c84SAndroid Build Coastguard Worker  *
5*cf5a6c84SAndroid Build Coastguard Worker  * See https://man7.org/linux/man-pages/man2/syscall.2.html
6*cf5a6c84SAndroid Build Coastguard Worker 
7*cf5a6c84SAndroid Build Coastguard Worker USE_STRACE(NEWTOY(strace, "^p#s#v", TOYFLAG_USR|TOYFLAG_SBIN))
8*cf5a6c84SAndroid Build Coastguard Worker 
9*cf5a6c84SAndroid Build Coastguard Worker config STRACE
10*cf5a6c84SAndroid Build Coastguard Worker   bool "strace"
11*cf5a6c84SAndroid Build Coastguard Worker   default n
12*cf5a6c84SAndroid Build Coastguard Worker   help
13*cf5a6c84SAndroid Build Coastguard Worker     usage: strace [-fv] [-p PID] [-s NUM] COMMAND [ARGS...]
14*cf5a6c84SAndroid Build Coastguard Worker 
15*cf5a6c84SAndroid Build Coastguard Worker     Trace systems calls made by a process.
16*cf5a6c84SAndroid Build Coastguard Worker 
17*cf5a6c84SAndroid Build Coastguard Worker     -s	String length limit.
18*cf5a6c84SAndroid Build Coastguard Worker     -v	Dump all of large structs/arrays.
19*cf5a6c84SAndroid Build Coastguard Worker */
20*cf5a6c84SAndroid Build Coastguard Worker 
21*cf5a6c84SAndroid Build Coastguard Worker #include <sys/ptrace.h>
22*cf5a6c84SAndroid Build Coastguard Worker #include <sys/user.h>
23*cf5a6c84SAndroid Build Coastguard Worker 
24*cf5a6c84SAndroid Build Coastguard Worker #define FOR_strace
25*cf5a6c84SAndroid Build Coastguard Worker #include "toys.h"
26*cf5a6c84SAndroid Build Coastguard Worker 
27*cf5a6c84SAndroid Build Coastguard Worker GLOBALS(
28*cf5a6c84SAndroid Build Coastguard Worker   long s, p;
29*cf5a6c84SAndroid Build Coastguard Worker 
30*cf5a6c84SAndroid Build Coastguard Worker   char ioctl[32], *fmt;
31*cf5a6c84SAndroid Build Coastguard Worker   long regs[256/sizeof(long)], syscall;
32*cf5a6c84SAndroid Build Coastguard Worker   pid_t pid;
33*cf5a6c84SAndroid Build Coastguard Worker   int arg;
34*cf5a6c84SAndroid Build Coastguard Worker )
35*cf5a6c84SAndroid Build Coastguard Worker 
36*cf5a6c84SAndroid Build Coastguard Worker // Syscall args from https://man7.org/linux/man-pages/man2/syscall.2.html
37*cf5a6c84SAndroid Build Coastguard Worker // REG_ORDER is args 0-6, SYSCALL, RESULT
38*cf5a6c84SAndroid Build Coastguard Worker #if defined(__arm__)
39*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {0,1,2,3,4,5,7,0};
40*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__aarch64__)
41*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {0,1,2,3,4,5,8,0};
42*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__i386__)
43*cf5a6c84SAndroid Build Coastguard Worker // ebx,ecx,edx,esi,edi,ebp,orig_eax,eax
44*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {0,1,2,3,4,5,11,6};
45*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__m68k__)
46*cf5a6c84SAndroid Build Coastguard Worker // d1,d2,d3,d4,d5,a0,orig_d0,d0
47*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {0,1,2,3,4,7,16,14};
48*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__PPC__) || defined(__PPC64__)
49*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {3,4,5,6,7,8,0,3};
50*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__riscv)
51*cf5a6c84SAndroid Build Coastguard Worker // a0,a1,a2,a3,a4,a5,a7,a0
52*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {10,11,12,13,14,15,17,10};
53*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__s390__) // also covers s390x
54*cf5a6c84SAndroid Build Coastguard Worker // r2,r3,r4,r5,r6,r7,r1,r2 but mask+addr before r0 so +2
55*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {4,5,6,7,8,9,3,4};
56*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__sh__)
57*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {4,5,6,7,0,1,3,0};
58*cf5a6c84SAndroid Build Coastguard Worker #elif defined(__x86_64__)
59*cf5a6c84SAndroid Build Coastguard Worker // rdi,rsi,rdx,r10,r8,r9,orig_rax,rax
60*cf5a6c84SAndroid Build Coastguard Worker static const char REG_ORDER[] = {14,13,12,7,9,8,15,10};
61*cf5a6c84SAndroid Build Coastguard Worker #else
62*cf5a6c84SAndroid Build Coastguard Worker #error unsupported architecture
63*cf5a6c84SAndroid Build Coastguard Worker #endif
64*cf5a6c84SAndroid Build Coastguard Worker 
65*cf5a6c84SAndroid Build Coastguard Worker #define C(x) case x: return #x
66*cf5a6c84SAndroid Build Coastguard Worker 
67*cf5a6c84SAndroid Build Coastguard Worker #define FS_IOC_FSGETXATTR 0x801c581f
68*cf5a6c84SAndroid Build Coastguard Worker #define FS_IOC_FSSETXATTR 0x401c5820
69*cf5a6c84SAndroid Build Coastguard Worker #define FS_IOC_GETFLAGS 0x80086601
70*cf5a6c84SAndroid Build Coastguard Worker #define FS_IOC_SETFLAGS 0x40086602
71*cf5a6c84SAndroid Build Coastguard Worker #define FS_IOC_GETVERSION 0x80087601
72*cf5a6c84SAndroid Build Coastguard Worker #define FS_IOC_SETVERSION 0x40047602
73*cf5a6c84SAndroid Build Coastguard Worker struct fsxattr {
74*cf5a6c84SAndroid Build Coastguard Worker   unsigned fsx_xflags;
75*cf5a6c84SAndroid Build Coastguard Worker   unsigned fsx_extsize;
76*cf5a6c84SAndroid Build Coastguard Worker   unsigned fsx_nextents;
77*cf5a6c84SAndroid Build Coastguard Worker   unsigned fsx_projid;
78*cf5a6c84SAndroid Build Coastguard Worker   unsigned fsx_cowextsize;
79*cf5a6c84SAndroid Build Coastguard Worker   char fsx_pad[8];
80*cf5a6c84SAndroid Build Coastguard Worker };
81*cf5a6c84SAndroid Build Coastguard Worker 
strioctl(int i)82*cf5a6c84SAndroid Build Coastguard Worker static char *strioctl(int i)
83*cf5a6c84SAndroid Build Coastguard Worker {
84*cf5a6c84SAndroid Build Coastguard Worker   switch (i) {
85*cf5a6c84SAndroid Build Coastguard Worker     C(FS_IOC_FSGETXATTR);
86*cf5a6c84SAndroid Build Coastguard Worker     C(FS_IOC_FSSETXATTR);
87*cf5a6c84SAndroid Build Coastguard Worker     C(FS_IOC_GETFLAGS);
88*cf5a6c84SAndroid Build Coastguard Worker     C(FS_IOC_GETVERSION);
89*cf5a6c84SAndroid Build Coastguard Worker     C(FS_IOC_SETFLAGS);
90*cf5a6c84SAndroid Build Coastguard Worker     C(FS_IOC_SETVERSION);
91*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFADDR);
92*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFBRDADDR);
93*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFCONF);
94*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFDSTADDR);
95*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFFLAGS);
96*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFHWADDR);
97*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFMAP);
98*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFMTU);
99*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFNETMASK);
100*cf5a6c84SAndroid Build Coastguard Worker     C(SIOCGIFTXQLEN);
101*cf5a6c84SAndroid Build Coastguard Worker     C(TCGETS);
102*cf5a6c84SAndroid Build Coastguard Worker     C(TCSETS);
103*cf5a6c84SAndroid Build Coastguard Worker     C(TIOCGWINSZ);
104*cf5a6c84SAndroid Build Coastguard Worker     C(TIOCSWINSZ);
105*cf5a6c84SAndroid Build Coastguard Worker   }
106*cf5a6c84SAndroid Build Coastguard Worker   sprintf(toybuf, "%#x", i);
107*cf5a6c84SAndroid Build Coastguard Worker   return toybuf;
108*cf5a6c84SAndroid Build Coastguard Worker }
109*cf5a6c84SAndroid Build Coastguard Worker 
110*cf5a6c84SAndroid Build Coastguard Worker // TODO: move to lib, implement errno(1)?
strerrno(int e)111*cf5a6c84SAndroid Build Coastguard Worker static char *strerrno(int e)
112*cf5a6c84SAndroid Build Coastguard Worker {
113*cf5a6c84SAndroid Build Coastguard Worker   switch (e) {
114*cf5a6c84SAndroid Build Coastguard Worker     // uapi errno-base.h
115*cf5a6c84SAndroid Build Coastguard Worker     C(EPERM);
116*cf5a6c84SAndroid Build Coastguard Worker     C(ENOENT);
117*cf5a6c84SAndroid Build Coastguard Worker     C(ESRCH);
118*cf5a6c84SAndroid Build Coastguard Worker     C(EINTR);
119*cf5a6c84SAndroid Build Coastguard Worker     C(EIO);
120*cf5a6c84SAndroid Build Coastguard Worker     C(ENXIO);
121*cf5a6c84SAndroid Build Coastguard Worker     C(E2BIG);
122*cf5a6c84SAndroid Build Coastguard Worker     C(ENOEXEC);
123*cf5a6c84SAndroid Build Coastguard Worker     C(EBADF);
124*cf5a6c84SAndroid Build Coastguard Worker     C(ECHILD);
125*cf5a6c84SAndroid Build Coastguard Worker     C(EAGAIN);
126*cf5a6c84SAndroid Build Coastguard Worker     C(ENOMEM);
127*cf5a6c84SAndroid Build Coastguard Worker     C(EACCES);
128*cf5a6c84SAndroid Build Coastguard Worker     C(EFAULT);
129*cf5a6c84SAndroid Build Coastguard Worker     C(ENOTBLK);
130*cf5a6c84SAndroid Build Coastguard Worker     C(EBUSY);
131*cf5a6c84SAndroid Build Coastguard Worker     C(EEXIST);
132*cf5a6c84SAndroid Build Coastguard Worker     C(EXDEV);
133*cf5a6c84SAndroid Build Coastguard Worker     C(ENODEV);
134*cf5a6c84SAndroid Build Coastguard Worker     C(ENOTDIR);
135*cf5a6c84SAndroid Build Coastguard Worker     C(EISDIR);
136*cf5a6c84SAndroid Build Coastguard Worker     C(EINVAL);
137*cf5a6c84SAndroid Build Coastguard Worker     C(ENFILE);
138*cf5a6c84SAndroid Build Coastguard Worker     C(EMFILE);
139*cf5a6c84SAndroid Build Coastguard Worker     C(ENOTTY);
140*cf5a6c84SAndroid Build Coastguard Worker     C(ETXTBSY);
141*cf5a6c84SAndroid Build Coastguard Worker     C(EFBIG);
142*cf5a6c84SAndroid Build Coastguard Worker     C(ENOSPC);
143*cf5a6c84SAndroid Build Coastguard Worker     C(ESPIPE);
144*cf5a6c84SAndroid Build Coastguard Worker     C(EROFS);
145*cf5a6c84SAndroid Build Coastguard Worker     C(EMLINK);
146*cf5a6c84SAndroid Build Coastguard Worker     C(EPIPE);
147*cf5a6c84SAndroid Build Coastguard Worker     C(EDOM);
148*cf5a6c84SAndroid Build Coastguard Worker     C(ERANGE);
149*cf5a6c84SAndroid Build Coastguard Worker     // uapi errno.h
150*cf5a6c84SAndroid Build Coastguard Worker     C(EDEADLK);
151*cf5a6c84SAndroid Build Coastguard Worker     C(ENAMETOOLONG);
152*cf5a6c84SAndroid Build Coastguard Worker     C(ENOLCK);
153*cf5a6c84SAndroid Build Coastguard Worker     C(ENOSYS);
154*cf5a6c84SAndroid Build Coastguard Worker     C(ENOTEMPTY);
155*cf5a6c84SAndroid Build Coastguard Worker     C(ELOOP);
156*cf5a6c84SAndroid Build Coastguard Worker     C(ENOMSG);
157*cf5a6c84SAndroid Build Coastguard Worker     // ...etc; fill in as we see them in practice?
158*cf5a6c84SAndroid Build Coastguard Worker   }
159*cf5a6c84SAndroid Build Coastguard Worker   sprintf(toybuf, "%d", e);
160*cf5a6c84SAndroid Build Coastguard Worker   return toybuf;
161*cf5a6c84SAndroid Build Coastguard Worker }
162*cf5a6c84SAndroid Build Coastguard Worker 
163*cf5a6c84SAndroid Build Coastguard Worker #undef C
164*cf5a6c84SAndroid Build Coastguard Worker 
xptrace(int req,pid_t pid,void * addr,void * data)165*cf5a6c84SAndroid Build Coastguard Worker static void xptrace(int req, pid_t pid, void *addr, void *data)
166*cf5a6c84SAndroid Build Coastguard Worker {
167*cf5a6c84SAndroid Build Coastguard Worker   if (ptrace(req, pid, addr, data)) perror_exit("ptrace %d pid %d", req, pid);
168*cf5a6c84SAndroid Build Coastguard Worker }
169*cf5a6c84SAndroid Build Coastguard Worker 
ptrace_struct(long addr,void * dst,size_t bytes)170*cf5a6c84SAndroid Build Coastguard Worker static void ptrace_struct(long addr, void *dst, size_t bytes)
171*cf5a6c84SAndroid Build Coastguard Worker {
172*cf5a6c84SAndroid Build Coastguard Worker   int offset = 0, i;
173*cf5a6c84SAndroid Build Coastguard Worker   long v;
174*cf5a6c84SAndroid Build Coastguard Worker 
175*cf5a6c84SAndroid Build Coastguard Worker   for (i=0; i<bytes; i+=sizeof(long)) {
176*cf5a6c84SAndroid Build Coastguard Worker     errno = 0;
177*cf5a6c84SAndroid Build Coastguard Worker     v = ptrace(PTRACE_PEEKDATA, TT.pid, addr + offset);
178*cf5a6c84SAndroid Build Coastguard Worker     if (errno) perror_exit("PTRACE_PEEKDATA failed");
179*cf5a6c84SAndroid Build Coastguard Worker     memcpy(dst + offset, &v, sizeof(v));
180*cf5a6c84SAndroid Build Coastguard Worker     offset += sizeof(long);
181*cf5a6c84SAndroid Build Coastguard Worker   }
182*cf5a6c84SAndroid Build Coastguard Worker }
183*cf5a6c84SAndroid Build Coastguard Worker 
184*cf5a6c84SAndroid Build Coastguard Worker #define C(n) n, #n
185*cf5a6c84SAndroid Build Coastguard Worker 
print_bits(int bitmask,long v,char * zero,...)186*cf5a6c84SAndroid Build Coastguard Worker static void print_bits(int bitmask, long v, char *zero, ...)
187*cf5a6c84SAndroid Build Coastguard Worker {
188*cf5a6c84SAndroid Build Coastguard Worker   va_list ap;
189*cf5a6c84SAndroid Build Coastguard Worker   int first = 1;
190*cf5a6c84SAndroid Build Coastguard Worker 
191*cf5a6c84SAndroid Build Coastguard Worker   if (!v && zero) {
192*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "%s", zero);
193*cf5a6c84SAndroid Build Coastguard Worker     return;
194*cf5a6c84SAndroid Build Coastguard Worker   }
195*cf5a6c84SAndroid Build Coastguard Worker   va_start(ap, zero);
196*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
197*cf5a6c84SAndroid Build Coastguard Worker     int this = va_arg(ap, int);
198*cf5a6c84SAndroid Build Coastguard Worker     char *name;
199*cf5a6c84SAndroid Build Coastguard Worker 
200*cf5a6c84SAndroid Build Coastguard Worker     if (!this) break;
201*cf5a6c84SAndroid Build Coastguard Worker     name = va_arg(ap, char*);
202*cf5a6c84SAndroid Build Coastguard Worker     if (bitmask) {
203*cf5a6c84SAndroid Build Coastguard Worker       if (v & this) {
204*cf5a6c84SAndroid Build Coastguard Worker         fprintf(stderr, "%s%s", first?"":"|", name);
205*cf5a6c84SAndroid Build Coastguard Worker         first = 0;
206*cf5a6c84SAndroid Build Coastguard Worker         v &= ~this;
207*cf5a6c84SAndroid Build Coastguard Worker       }
208*cf5a6c84SAndroid Build Coastguard Worker     } else {
209*cf5a6c84SAndroid Build Coastguard Worker       if (v == this) {
210*cf5a6c84SAndroid Build Coastguard Worker         fprintf(stderr, "%s", name);
211*cf5a6c84SAndroid Build Coastguard Worker         v = 0;
212*cf5a6c84SAndroid Build Coastguard Worker         break;
213*cf5a6c84SAndroid Build Coastguard Worker       }
214*cf5a6c84SAndroid Build Coastguard Worker     }
215*cf5a6c84SAndroid Build Coastguard Worker   }
216*cf5a6c84SAndroid Build Coastguard Worker   va_end(ap);
217*cf5a6c84SAndroid Build Coastguard Worker   if (v) fprintf(stderr, "%s%#lx", first?"":"|", v);
218*cf5a6c84SAndroid Build Coastguard Worker }
219*cf5a6c84SAndroid Build Coastguard Worker 
print_mode(unsigned m)220*cf5a6c84SAndroid Build Coastguard Worker static void print_mode(unsigned m)
221*cf5a6c84SAndroid Build Coastguard Worker {
222*cf5a6c84SAndroid Build Coastguard Worker   if (m & S_IFMT) {
223*cf5a6c84SAndroid Build Coastguard Worker     print_bits(0, m & S_IFMT, "", C(S_IFREG), C(S_IFDIR), C(S_IFLNK),
224*cf5a6c84SAndroid Build Coastguard Worker       C(S_IFBLK), C(S_IFCHR), C(S_IFIFO), C(S_IFSOCK), 0);
225*cf5a6c84SAndroid Build Coastguard Worker     fputc('|', stderr);
226*cf5a6c84SAndroid Build Coastguard Worker     m &= ~S_IFMT;
227*cf5a6c84SAndroid Build Coastguard Worker   }
228*cf5a6c84SAndroid Build Coastguard Worker   fprintf(stderr, "%#o", m);
229*cf5a6c84SAndroid Build Coastguard Worker }
230*cf5a6c84SAndroid Build Coastguard Worker 
231*cf5a6c84SAndroid Build Coastguard Worker // TODO: this all relies on having the libc structs match the kernel structs,
232*cf5a6c84SAndroid Build Coastguard Worker // which isn't always true for glibc...
print_struct(long addr)233*cf5a6c84SAndroid Build Coastguard Worker static void print_struct(long addr)
234*cf5a6c84SAndroid Build Coastguard Worker {
235*cf5a6c84SAndroid Build Coastguard Worker   if (!addr) { // All NULLs look the same...
236*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "NULL");
237*cf5a6c84SAndroid Build Coastguard Worker     while (*TT.fmt != '}') ++TT.fmt;
238*cf5a6c84SAndroid Build Coastguard Worker     ++TT.fmt;
239*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "ifreq}")) {
240*cf5a6c84SAndroid Build Coastguard Worker     struct ifreq ir;
241*cf5a6c84SAndroid Build Coastguard Worker 
242*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &ir, sizeof(ir));
243*cf5a6c84SAndroid Build Coastguard Worker     // TODO: is this always an ioctl? use TT.regs[REG_ORDER[1]] to work out what to show.
244*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "{...}");
245*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "fsxattr}")) {
246*cf5a6c84SAndroid Build Coastguard Worker     struct fsxattr fx;
247*cf5a6c84SAndroid Build Coastguard Worker 
248*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &fx, sizeof(fx));
249*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "{fsx_xflags=%#x, fsx_extsize=%d, fsx_nextents=%d, "
250*cf5a6c84SAndroid Build Coastguard Worker         "fsx_projid=%d, fsx_cowextsize=%d}", fx.fsx_xflags, fx.fsx_extsize,
251*cf5a6c84SAndroid Build Coastguard Worker         fx.fsx_nextents, fx.fsx_projid, fx.fsx_cowextsize);
252*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "long}")) {
253*cf5a6c84SAndroid Build Coastguard Worker     long l;
254*cf5a6c84SAndroid Build Coastguard Worker 
255*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &l, sizeof(l));
256*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "%ld", l);
257*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "longx}")) {
258*cf5a6c84SAndroid Build Coastguard Worker     long l;
259*cf5a6c84SAndroid Build Coastguard Worker 
260*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &l, sizeof(l));
261*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "%#lx", l);
262*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "rlimit}")) {
263*cf5a6c84SAndroid Build Coastguard Worker     struct rlimit rl;
264*cf5a6c84SAndroid Build Coastguard Worker 
265*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &rl, sizeof(rl));
266*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "{rlim_cur=%lld, rlim_max=%lld}",
267*cf5a6c84SAndroid Build Coastguard Worker         (long long)rl.rlim_cur, (long long)rl.rlim_max);
268*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "sigset}")) {
269*cf5a6c84SAndroid Build Coastguard Worker     long long ss;
270*cf5a6c84SAndroid Build Coastguard Worker     int i;
271*cf5a6c84SAndroid Build Coastguard Worker 
272*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &ss, sizeof(ss));
273*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "[");
274*cf5a6c84SAndroid Build Coastguard Worker     for (i=0; i<64;++i) {
275*cf5a6c84SAndroid Build Coastguard Worker       // TODO: use signal names, fix spacing
276*cf5a6c84SAndroid Build Coastguard Worker       if (ss & (1ULL<<i)) fprintf(stderr, "%d ", i);
277*cf5a6c84SAndroid Build Coastguard Worker     }
278*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "]");
279*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "stat}")) {
280*cf5a6c84SAndroid Build Coastguard Worker     struct stat sb;
281*cf5a6c84SAndroid Build Coastguard Worker 
282*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &sb, sizeof(sb));
283*cf5a6c84SAndroid Build Coastguard Worker     if (FLAG(v)) {
284*cf5a6c84SAndroid Build Coastguard Worker       // TODO: full atime/mtime/ctime dump.
285*cf5a6c84SAndroid Build Coastguard Worker       fprintf(stderr, "{st_dev=makedev(%#x, %#x), st_ino=%ld, st_mode=",
286*cf5a6c84SAndroid Build Coastguard Worker           dev_major(sb.st_dev), dev_minor(sb.st_dev), sb.st_ino);
287*cf5a6c84SAndroid Build Coastguard Worker       print_mode(sb.st_mode);
288*cf5a6c84SAndroid Build Coastguard Worker       fprintf(stderr, ", st_nlink=%ld, st_uid=%d, st_gid=%d, "
289*cf5a6c84SAndroid Build Coastguard Worker         "st_blksize=%ld, st_blocks=%ld, st_size=%lld, st_atime=%ld, "
290*cf5a6c84SAndroid Build Coastguard Worker         "st_mtime=%ld, st_ctime=%ld}", (long) sb.st_nlink, sb.st_uid,
291*cf5a6c84SAndroid Build Coastguard Worker         sb.st_gid, (long) sb.st_blksize, sb.st_blocks, (long long)sb.st_size,
292*cf5a6c84SAndroid Build Coastguard Worker         sb.st_atime, sb.st_mtime, sb.st_ctime);
293*cf5a6c84SAndroid Build Coastguard Worker     } else {
294*cf5a6c84SAndroid Build Coastguard Worker       fprintf(stderr, "{st_mode=");
295*cf5a6c84SAndroid Build Coastguard Worker       print_mode(sb.st_mode);
296*cf5a6c84SAndroid Build Coastguard Worker       fprintf(stderr, ", st_size=%lld, ...}", (long long)sb.st_size);
297*cf5a6c84SAndroid Build Coastguard Worker     }
298*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "termios}")) {
299*cf5a6c84SAndroid Build Coastguard Worker     struct termios to;
300*cf5a6c84SAndroid Build Coastguard Worker 
301*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &to, sizeof(to));
302*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "{c_iflag=%#lx, c_oflag=%#lx, c_cflag=%#lx, c_lflag=%#lx}",
303*cf5a6c84SAndroid Build Coastguard Worker         (long)to.c_iflag, (long)to.c_oflag, (long)to.c_cflag, (long)to.c_lflag);
304*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "timespec}")) {
305*cf5a6c84SAndroid Build Coastguard Worker     struct timespec ts;
306*cf5a6c84SAndroid Build Coastguard Worker 
307*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &ts, sizeof(ts));
308*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "{tv_sec=%lld, tv_nsec=%lld}",
309*cf5a6c84SAndroid Build Coastguard Worker         (long long)ts.tv_sec, (long long)ts.tv_nsec);
310*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "winsize}")) {
311*cf5a6c84SAndroid Build Coastguard Worker     struct winsize ws;
312*cf5a6c84SAndroid Build Coastguard Worker 
313*cf5a6c84SAndroid Build Coastguard Worker     ptrace_struct(addr, &ws, sizeof(ws));
314*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "{ws_row=%hu, ws_col=%hu, ws_xpixel=%hu, ws_ypixel=%hu}",
315*cf5a6c84SAndroid Build Coastguard Worker         ws.ws_row, ws.ws_col, ws.ws_xpixel, ws.ws_ypixel);
316*cf5a6c84SAndroid Build Coastguard Worker   } else abort();
317*cf5a6c84SAndroid Build Coastguard Worker }
318*cf5a6c84SAndroid Build Coastguard Worker 
print_ptr(long addr)319*cf5a6c84SAndroid Build Coastguard Worker static void print_ptr(long addr)
320*cf5a6c84SAndroid Build Coastguard Worker {
321*cf5a6c84SAndroid Build Coastguard Worker   if (!addr) fprintf(stderr, "NULL");
322*cf5a6c84SAndroid Build Coastguard Worker   else fprintf(stderr, "0x%lx", addr);
323*cf5a6c84SAndroid Build Coastguard Worker }
324*cf5a6c84SAndroid Build Coastguard Worker 
print_string(long addr,long limit)325*cf5a6c84SAndroid Build Coastguard Worker static void print_string(long addr, long limit)
326*cf5a6c84SAndroid Build Coastguard Worker {
327*cf5a6c84SAndroid Build Coastguard Worker   long offset = 0, total = 0;
328*cf5a6c84SAndroid Build Coastguard Worker   int i;
329*cf5a6c84SAndroid Build Coastguard Worker 
330*cf5a6c84SAndroid Build Coastguard Worker   fputc('"', stderr);
331*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
332*cf5a6c84SAndroid Build Coastguard Worker     errno = 0;
333*cf5a6c84SAndroid Build Coastguard Worker     long v = ptrace(PTRACE_PEEKDATA, TT.pid, addr + offset);
334*cf5a6c84SAndroid Build Coastguard Worker     if (errno) return;
335*cf5a6c84SAndroid Build Coastguard Worker     memcpy(toybuf, &v, sizeof(v));
336*cf5a6c84SAndroid Build Coastguard Worker     for (i=0; i<sizeof(v); ++i) {
337*cf5a6c84SAndroid Build Coastguard Worker       if (!toybuf[i]) {
338*cf5a6c84SAndroid Build Coastguard Worker         // TODO: handle the case of dumping n bytes (e.g. read()/write()), not
339*cf5a6c84SAndroid Build Coastguard Worker         // just NUL-terminated strings.
340*cf5a6c84SAndroid Build Coastguard Worker         fputc('"', stderr);
341*cf5a6c84SAndroid Build Coastguard Worker         return;
342*cf5a6c84SAndroid Build Coastguard Worker       }
343*cf5a6c84SAndroid Build Coastguard Worker       if (isprint(toybuf[i])) fputc(toybuf[i], stderr);
344*cf5a6c84SAndroid Build Coastguard Worker       else {
345*cf5a6c84SAndroid Build Coastguard Worker         // TODO: reuse an existing escape function.
346*cf5a6c84SAndroid Build Coastguard Worker         fputc('\\', stderr);
347*cf5a6c84SAndroid Build Coastguard Worker         if (toybuf[i] == '\n') fputc('n', stderr);
348*cf5a6c84SAndroid Build Coastguard Worker         else if (toybuf[i] == '\r') fputc('r', stderr);
349*cf5a6c84SAndroid Build Coastguard Worker         else if (toybuf[i] == '\t') fputc('t', stderr);
350*cf5a6c84SAndroid Build Coastguard Worker         else fprintf(stderr, "x%2.2x", toybuf[i]);
351*cf5a6c84SAndroid Build Coastguard Worker       }
352*cf5a6c84SAndroid Build Coastguard Worker       if (++total >= limit) {
353*cf5a6c84SAndroid Build Coastguard Worker         fprintf(stderr, "\"...");
354*cf5a6c84SAndroid Build Coastguard Worker         return;
355*cf5a6c84SAndroid Build Coastguard Worker       }
356*cf5a6c84SAndroid Build Coastguard Worker     }
357*cf5a6c84SAndroid Build Coastguard Worker     offset += sizeof(v);
358*cf5a6c84SAndroid Build Coastguard Worker   }
359*cf5a6c84SAndroid Build Coastguard Worker }
360*cf5a6c84SAndroid Build Coastguard Worker 
print_flags(long v)361*cf5a6c84SAndroid Build Coastguard Worker static void print_flags(long v)
362*cf5a6c84SAndroid Build Coastguard Worker {
363*cf5a6c84SAndroid Build Coastguard Worker   if (strstart(&TT.fmt, "access|")) {
364*cf5a6c84SAndroid Build Coastguard Worker     print_bits(1, v, "F_OK", C(R_OK), C(W_OK), C(X_OK), 0);
365*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "mmap|")) {
366*cf5a6c84SAndroid Build Coastguard Worker     print_bits(1, v, 0, C(MAP_SHARED), C(MAP_PRIVATE),
367*cf5a6c84SAndroid Build Coastguard Worker #if defined(MAP_32BIT)
368*cf5a6c84SAndroid Build Coastguard Worker         C(MAP_32BIT),
369*cf5a6c84SAndroid Build Coastguard Worker #endif
370*cf5a6c84SAndroid Build Coastguard Worker         C(MAP_ANONYMOUS), C(MAP_FIXED), C(MAP_GROWSDOWN), C(MAP_HUGETLB),
371*cf5a6c84SAndroid Build Coastguard Worker         C(MAP_DENYWRITE), 0);
372*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "open|")) {
373*cf5a6c84SAndroid Build Coastguard Worker     print_bits(1, v, "O_RDONLY", C(O_WRONLY), C(O_RDWR), C(O_CLOEXEC),
374*cf5a6c84SAndroid Build Coastguard Worker         C(O_CREAT), C(O_DIRECTORY), C(O_EXCL), C(O_NOCTTY), C(O_NOFOLLOW),
375*cf5a6c84SAndroid Build Coastguard Worker         C(O_TRUNC), C(O_ASYNC), C(O_APPEND), C(O_DSYNC), C(O_EXCL),
376*cf5a6c84SAndroid Build Coastguard Worker         C(O_NOATIME), C(O_NONBLOCK), C(O_PATH), C(O_SYNC),
377*cf5a6c84SAndroid Build Coastguard Worker         0x4000, "O_DIRECT", 0x8000, "O_LARGEFILE", 0x410000, "O_TMPFILE", 0);
378*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "prot|")) {
379*cf5a6c84SAndroid Build Coastguard Worker     print_bits(1,v,"PROT_NONE",C(PROT_READ),C(PROT_WRITE),C(PROT_EXEC),
380*cf5a6c84SAndroid Build Coastguard Worker #if defined(PROT_BTI)
381*cf5a6c84SAndroid Build Coastguard Worker         C(PROT_BTI),
382*cf5a6c84SAndroid Build Coastguard Worker #endif
383*cf5a6c84SAndroid Build Coastguard Worker #if defined(PROT_MTE)
384*cf5a6c84SAndroid Build Coastguard Worker         C(PROT_MTE),
385*cf5a6c84SAndroid Build Coastguard Worker #endif
386*cf5a6c84SAndroid Build Coastguard Worker         0);
387*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "grnd|")) {
388*cf5a6c84SAndroid Build Coastguard Worker     print_bits(1,v,"0",C(GRND_RANDOM),C(GRND_NONBLOCK),0);
389*cf5a6c84SAndroid Build Coastguard Worker   } else abort();
390*cf5a6c84SAndroid Build Coastguard Worker }
391*cf5a6c84SAndroid Build Coastguard Worker 
print_alternatives(long v)392*cf5a6c84SAndroid Build Coastguard Worker static void print_alternatives(long v)
393*cf5a6c84SAndroid Build Coastguard Worker {
394*cf5a6c84SAndroid Build Coastguard Worker   if (strstart(&TT.fmt, "clockid^")) {
395*cf5a6c84SAndroid Build Coastguard Worker     print_bits(0, v, "CLOCK_REALTIME", C(CLOCK_MONOTONIC),
396*cf5a6c84SAndroid Build Coastguard Worker         C(CLOCK_PROCESS_CPUTIME_ID), C(CLOCK_THREAD_CPUTIME_ID),
397*cf5a6c84SAndroid Build Coastguard Worker         C(CLOCK_MONOTONIC_RAW), C(CLOCK_REALTIME_COARSE),
398*cf5a6c84SAndroid Build Coastguard Worker         C(CLOCK_MONOTONIC_COARSE), C(CLOCK_BOOTTIME),
399*cf5a6c84SAndroid Build Coastguard Worker         C(CLOCK_REALTIME_ALARM), C(CLOCK_BOOTTIME_ALARM), 0);
400*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "rlimit^")) {
401*cf5a6c84SAndroid Build Coastguard Worker     print_bits(0, v, "RLIMIT_CPU", C(RLIMIT_FSIZE), C(RLIMIT_DATA),
402*cf5a6c84SAndroid Build Coastguard Worker         C(RLIMIT_STACK), C(RLIMIT_CORE), C(RLIMIT_RSS), C(RLIMIT_NPROC),
403*cf5a6c84SAndroid Build Coastguard Worker         C(RLIMIT_NOFILE), C(RLIMIT_MEMLOCK), C(RLIMIT_AS), C(RLIMIT_LOCKS),
404*cf5a6c84SAndroid Build Coastguard Worker         C(RLIMIT_SIGPENDING), C(RLIMIT_MSGQUEUE), C(RLIMIT_NICE),
405*cf5a6c84SAndroid Build Coastguard Worker         C(RLIMIT_RTPRIO), C(RLIMIT_RTTIME), 0);
406*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "seek^")) {
407*cf5a6c84SAndroid Build Coastguard Worker     print_bits(0, v, "SEEK_SET", C(SEEK_CUR), C(SEEK_END), C(SEEK_DATA),
408*cf5a6c84SAndroid Build Coastguard Worker         C(SEEK_HOLE), 0);
409*cf5a6c84SAndroid Build Coastguard Worker   } else if (strstart(&TT.fmt, "sig^")) {
410*cf5a6c84SAndroid Build Coastguard Worker     print_bits(0, v, "SIG_BLOCK", C(SIG_UNBLOCK), C(SIG_SETMASK), 0);
411*cf5a6c84SAndroid Build Coastguard Worker   } else abort();
412*cf5a6c84SAndroid Build Coastguard Worker }
413*cf5a6c84SAndroid Build Coastguard Worker 
print_args()414*cf5a6c84SAndroid Build Coastguard Worker static void print_args()
415*cf5a6c84SAndroid Build Coastguard Worker {
416*cf5a6c84SAndroid Build Coastguard Worker   int i;
417*cf5a6c84SAndroid Build Coastguard Worker 
418*cf5a6c84SAndroid Build Coastguard Worker   // Loop through arguments and print according to format string
419*cf5a6c84SAndroid Build Coastguard Worker   for (i = 0; *TT.fmt; i++, TT.arg++) {
420*cf5a6c84SAndroid Build Coastguard Worker     long v = TT.regs[REG_ORDER[TT.arg]];
421*cf5a6c84SAndroid Build Coastguard Worker     char *s, ch;
422*cf5a6c84SAndroid Build Coastguard Worker 
423*cf5a6c84SAndroid Build Coastguard Worker     if (i) fprintf(stderr, ", ");
424*cf5a6c84SAndroid Build Coastguard Worker     switch (ch = *TT.fmt++) {
425*cf5a6c84SAndroid Build Coastguard Worker       case 'd': fprintf(stderr, "%ld", v); break; // decimal
426*cf5a6c84SAndroid Build Coastguard Worker       case 'f': if ((int) v == AT_FDCWD) fprintf(stderr, "AT_FDCWD"); // fd
427*cf5a6c84SAndroid Build Coastguard Worker                 else fprintf(stderr, "%ld", v);
428*cf5a6c84SAndroid Build Coastguard Worker                 break;
429*cf5a6c84SAndroid Build Coastguard Worker       case 'F': print_string(v, LONG_MAX); break;
430*cf5a6c84SAndroid Build Coastguard Worker       case 'i': fprintf(stderr, "%s", strioctl(v)); break; // ioctl name
431*cf5a6c84SAndroid Build Coastguard Worker       case 'm': print_mode(v); break;
432*cf5a6c84SAndroid Build Coastguard Worker       case 'o': fprintf(stderr, "%ld", v); break; // off_t
433*cf5a6c84SAndroid Build Coastguard Worker       case 'p': print_ptr(v); break;
434*cf5a6c84SAndroid Build Coastguard Worker       case 's': print_string(v, TT.s); break;
435*cf5a6c84SAndroid Build Coastguard Worker       case 'S': // The libc-reserved signals aren't known to num_to_sig().
436*cf5a6c84SAndroid Build Coastguard Worker                 // TODO: use an strace-only routine for >= 32?
437*cf5a6c84SAndroid Build Coastguard Worker                 if (!(s = num_to_sig(v))) fprintf(stderr, "%ld", v);
438*cf5a6c84SAndroid Build Coastguard Worker                 else fprintf(stderr, "SIG%s", s);
439*cf5a6c84SAndroid Build Coastguard Worker                 break;
440*cf5a6c84SAndroid Build Coastguard Worker       case 'z': fprintf(stderr, "%lu", (unsigned long) v); break; // size_t
441*cf5a6c84SAndroid Build Coastguard Worker       case 'x': fprintf(stderr, "%#lx", v); break; // hex
442*cf5a6c84SAndroid Build Coastguard Worker 
443*cf5a6c84SAndroid Build Coastguard Worker       case '{': print_struct(v); break;
444*cf5a6c84SAndroid Build Coastguard Worker       case '|': print_flags(v); break;
445*cf5a6c84SAndroid Build Coastguard Worker       case '^': print_alternatives(v); break;
446*cf5a6c84SAndroid Build Coastguard Worker 
447*cf5a6c84SAndroid Build Coastguard Worker       case '/': return; // Separates "enter" and "exit" arguments.
448*cf5a6c84SAndroid Build Coastguard Worker 
449*cf5a6c84SAndroid Build Coastguard Worker       default: fprintf(stderr, "?%c<%#lx>", ch, v); break;
450*cf5a6c84SAndroid Build Coastguard Worker     }
451*cf5a6c84SAndroid Build Coastguard Worker   }
452*cf5a6c84SAndroid Build Coastguard Worker }
453*cf5a6c84SAndroid Build Coastguard Worker 
print_enter(void)454*cf5a6c84SAndroid Build Coastguard Worker static void print_enter(void)
455*cf5a6c84SAndroid Build Coastguard Worker {
456*cf5a6c84SAndroid Build Coastguard Worker   struct iovec v = {.iov_base=&TT.regs, .iov_len=sizeof(TT.regs)};
457*cf5a6c84SAndroid Build Coastguard Worker   char *name;
458*cf5a6c84SAndroid Build Coastguard Worker 
459*cf5a6c84SAndroid Build Coastguard Worker   xptrace(PTRACE_GETREGSET, TT.pid, (void *)1, &v); // NT_PRSTATUS
460*cf5a6c84SAndroid Build Coastguard Worker   TT.syscall = TT.regs[REG_ORDER[6]];
461*cf5a6c84SAndroid Build Coastguard Worker   if (TT.syscall == __NR_ioctl) {
462*cf5a6c84SAndroid Build Coastguard Worker     name = "ioctl";
463*cf5a6c84SAndroid Build Coastguard Worker     switch (TT.regs[REG_ORDER[1]]) {
464*cf5a6c84SAndroid Build Coastguard Worker       case FS_IOC_FSGETXATTR: TT.fmt = "fi/{fsxattr}"; break;
465*cf5a6c84SAndroid Build Coastguard Worker       case FS_IOC_FSSETXATTR: TT.fmt = "fi{fsxattr}"; break;
466*cf5a6c84SAndroid Build Coastguard Worker       case FS_IOC_GETFLAGS: TT.fmt = "fi/{longx}"; break;
467*cf5a6c84SAndroid Build Coastguard Worker       case FS_IOC_GETVERSION: TT.fmt = "fi/{long}"; break;
468*cf5a6c84SAndroid Build Coastguard Worker       case FS_IOC_SETFLAGS: TT.fmt = "fi{long}"; break;
469*cf5a6c84SAndroid Build Coastguard Worker       case FS_IOC_SETVERSION: TT.fmt = "fi{long}"; break;
470*cf5a6c84SAndroid Build Coastguard Worker       //case SIOCGIFCONF: struct ifconf
471*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFADDR:
472*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFBRDADDR:
473*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFDSTADDR:
474*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFFLAGS:
475*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFHWADDR:
476*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFMAP:
477*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFMTU:
478*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFNETMASK:
479*cf5a6c84SAndroid Build Coastguard Worker       case SIOCGIFTXQLEN: TT.fmt = "fi/{ifreq}"; break;
480*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFADDR:
481*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFBRDADDR:
482*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFDSTADDR:
483*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFFLAGS:
484*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFHWADDR:
485*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFMAP:
486*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFMTU:
487*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFNETMASK:
488*cf5a6c84SAndroid Build Coastguard Worker       case SIOCSIFTXQLEN: TT.fmt = "fi{ifreq}"; break;
489*cf5a6c84SAndroid Build Coastguard Worker       case TCGETS: TT.fmt = "fi/{termios}"; break;
490*cf5a6c84SAndroid Build Coastguard Worker       case TCSETS: TT.fmt = "fi{termios}"; break;
491*cf5a6c84SAndroid Build Coastguard Worker       case TIOCGWINSZ: TT.fmt = "fi/{winsize}"; break;
492*cf5a6c84SAndroid Build Coastguard Worker       case TIOCSWINSZ: TT.fmt = "fi{winsize}"; break;
493*cf5a6c84SAndroid Build Coastguard Worker       default:
494*cf5a6c84SAndroid Build Coastguard Worker         TT.fmt = (TT.regs[REG_ORDER[0]]&1) ? "fip" : "fi/p";
495*cf5a6c84SAndroid Build Coastguard Worker         break;
496*cf5a6c84SAndroid Build Coastguard Worker     }
497*cf5a6c84SAndroid Build Coastguard Worker   } else switch (TT.syscall) {
498*cf5a6c84SAndroid Build Coastguard Worker #define SC(n,f) case __NR_ ## n: name = #n; TT.fmt = f; break
499*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_access)
500*cf5a6c84SAndroid Build Coastguard Worker     SC(access, "F|access|");
501*cf5a6c84SAndroid Build Coastguard Worker #endif
502*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_arch_prctl)
503*cf5a6c84SAndroid Build Coastguard Worker     SC(arch_prctl, "dp");
504*cf5a6c84SAndroid Build Coastguard Worker #endif
505*cf5a6c84SAndroid Build Coastguard Worker     SC(brk, "p");
506*cf5a6c84SAndroid Build Coastguard Worker     SC(clock_nanosleep, "^clockid^d{timespec}/{timespec}");
507*cf5a6c84SAndroid Build Coastguard Worker     SC(close, "d");
508*cf5a6c84SAndroid Build Coastguard Worker     SC(connect, "fpd"); // TODO: sockaddr
509*cf5a6c84SAndroid Build Coastguard Worker     SC(dup, "f");
510*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_dup2)
511*cf5a6c84SAndroid Build Coastguard Worker     SC(dup2, "ff");
512*cf5a6c84SAndroid Build Coastguard Worker #endif
513*cf5a6c84SAndroid Build Coastguard Worker     SC(dup3, "ff|open|");
514*cf5a6c84SAndroid Build Coastguard Worker     SC(execve, "Fpp");
515*cf5a6c84SAndroid Build Coastguard Worker     SC(exit_group, "d");
516*cf5a6c84SAndroid Build Coastguard Worker     SC(faccessat, "fF|access|");
517*cf5a6c84SAndroid Build Coastguard Worker     SC(fcntl, "fdp"); // TODO: probably needs special case
518*cf5a6c84SAndroid Build Coastguard Worker     SC(fstat, "f/{stat}");
519*cf5a6c84SAndroid Build Coastguard Worker     SC(futex, "pdxppx");
520*cf5a6c84SAndroid Build Coastguard Worker     SC(getcwd, "/Fz");
521*cf5a6c84SAndroid Build Coastguard Worker     SC(getdents64, "dpz");
522*cf5a6c84SAndroid Build Coastguard Worker     SC(getegid, "");
523*cf5a6c84SAndroid Build Coastguard Worker     SC(geteuid, "");
524*cf5a6c84SAndroid Build Coastguard Worker     SC(getrandom, "pz|grnd|");
525*cf5a6c84SAndroid Build Coastguard Worker     SC(getgid, "");
526*cf5a6c84SAndroid Build Coastguard Worker     SC(getuid, "");
527*cf5a6c84SAndroid Build Coastguard Worker 
528*cf5a6c84SAndroid Build Coastguard Worker     SC(getxattr, "Fspz");
529*cf5a6c84SAndroid Build Coastguard Worker     SC(lgetxattr, "Fspz");
530*cf5a6c84SAndroid Build Coastguard Worker     SC(fgetxattr, "fspz");
531*cf5a6c84SAndroid Build Coastguard Worker 
532*cf5a6c84SAndroid Build Coastguard Worker     SC(lseek, "fo^seek^");
533*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_lstat)
534*cf5a6c84SAndroid Build Coastguard Worker     SC(lstat, "s/{stat}");
535*cf5a6c84SAndroid Build Coastguard Worker #endif
536*cf5a6c84SAndroid Build Coastguard Worker     SC(mmap, "pz|prot||mmap|fx");
537*cf5a6c84SAndroid Build Coastguard Worker     SC(mprotect, "pz|prot|");
538*cf5a6c84SAndroid Build Coastguard Worker     SC(mremap, "pzzdp"); // TODO: flags
539*cf5a6c84SAndroid Build Coastguard Worker     SC(munmap, "pz");
540*cf5a6c84SAndroid Build Coastguard Worker     SC(nanosleep, "{timespec}/{timespec}");
541*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_newfstatat)
542*cf5a6c84SAndroid Build Coastguard Worker     SC(newfstatat, "fF/{stat}d");
543*cf5a6c84SAndroid Build Coastguard Worker #endif
544*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_open)
545*cf5a6c84SAndroid Build Coastguard Worker     SC(open, "Fd|open|m");
546*cf5a6c84SAndroid Build Coastguard Worker #endif
547*cf5a6c84SAndroid Build Coastguard Worker     SC(openat, "fF|open|m");
548*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_poll)
549*cf5a6c84SAndroid Build Coastguard Worker     SC(poll, "pdd");
550*cf5a6c84SAndroid Build Coastguard Worker #endif
551*cf5a6c84SAndroid Build Coastguard Worker     SC(prlimit64, "d^rlimit^{rlimit}/{rlimit}");
552*cf5a6c84SAndroid Build Coastguard Worker     SC(read, "d/sz");
553*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_readlink)
554*cf5a6c84SAndroid Build Coastguard Worker     SC(readlink, "F/sz");
555*cf5a6c84SAndroid Build Coastguard Worker #endif
556*cf5a6c84SAndroid Build Coastguard Worker     SC(readlinkat, "fF/sz");
557*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_rseq)
558*cf5a6c84SAndroid Build Coastguard Worker     SC(rseq, "pzxx");
559*cf5a6c84SAndroid Build Coastguard Worker #endif
560*cf5a6c84SAndroid Build Coastguard Worker     SC(rt_sigaction, "Sppz");
561*cf5a6c84SAndroid Build Coastguard Worker     SC(rt_sigprocmask, "^sig^{sigset}/{sigset}z");
562*cf5a6c84SAndroid Build Coastguard Worker     SC(set_robust_list, "pd");
563*cf5a6c84SAndroid Build Coastguard Worker     SC(set_tid_address, "p");
564*cf5a6c84SAndroid Build Coastguard Worker     SC(socket, "ddd"); // TODO: flags
565*cf5a6c84SAndroid Build Coastguard Worker #if defined(__NR_stat)
566*cf5a6c84SAndroid Build Coastguard Worker     SC(stat, "F/{stat}");
567*cf5a6c84SAndroid Build Coastguard Worker #endif
568*cf5a6c84SAndroid Build Coastguard Worker     SC(statfs, "Fp");
569*cf5a6c84SAndroid Build Coastguard Worker     SC(sysinfo, "p");
570*cf5a6c84SAndroid Build Coastguard Worker     SC(umask, "m");
571*cf5a6c84SAndroid Build Coastguard Worker     SC(uname, "p");
572*cf5a6c84SAndroid Build Coastguard Worker     SC(write, "dsz");
573*cf5a6c84SAndroid Build Coastguard Worker     default:
574*cf5a6c84SAndroid Build Coastguard Worker       sprintf(name = toybuf, "SYS_%ld", TT.syscall);
575*cf5a6c84SAndroid Build Coastguard Worker       TT.fmt = "pppppp";
576*cf5a6c84SAndroid Build Coastguard Worker       break;
577*cf5a6c84SAndroid Build Coastguard Worker   }
578*cf5a6c84SAndroid Build Coastguard Worker 
579*cf5a6c84SAndroid Build Coastguard Worker   fprintf(stderr, "%s(", name);
580*cf5a6c84SAndroid Build Coastguard Worker   TT.arg = 0;
581*cf5a6c84SAndroid Build Coastguard Worker   print_args();
582*cf5a6c84SAndroid Build Coastguard Worker }
583*cf5a6c84SAndroid Build Coastguard Worker 
print_exit(void)584*cf5a6c84SAndroid Build Coastguard Worker static void print_exit(void)
585*cf5a6c84SAndroid Build Coastguard Worker {
586*cf5a6c84SAndroid Build Coastguard Worker   long regs[256/sizeof(long)];
587*cf5a6c84SAndroid Build Coastguard Worker   struct iovec v = {.iov_base=&regs, .iov_len=sizeof(regs)};
588*cf5a6c84SAndroid Build Coastguard Worker   long result;
589*cf5a6c84SAndroid Build Coastguard Worker 
590*cf5a6c84SAndroid Build Coastguard Worker   // We read the registers into a local because we only want the result,
591*cf5a6c84SAndroid Build Coastguard Worker   // and don't want to clobber the argument that was in the same register
592*cf5a6c84SAndroid Build Coastguard Worker   // earlier (the first argument of getcwd(2), for example, gets printed
593*cf5a6c84SAndroid Build Coastguard Worker   // on exit rather than entry, and arm/riscv both reuse that register for
594*cf5a6c84SAndroid Build Coastguard Worker   // the result).
595*cf5a6c84SAndroid Build Coastguard Worker   xptrace(PTRACE_GETREGSET, TT.pid, (void *)1, &v); // NT_PRSTATUS
596*cf5a6c84SAndroid Build Coastguard Worker   if (*TT.fmt) print_args();
597*cf5a6c84SAndroid Build Coastguard Worker   fprintf(stderr, ") = ");
598*cf5a6c84SAndroid Build Coastguard Worker   result = regs[REG_ORDER[7]];
599*cf5a6c84SAndroid Build Coastguard Worker   if (result >= -4095UL)
600*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "-1 %s (%s)", strerrno(-result), strerror(-result));
601*cf5a6c84SAndroid Build Coastguard Worker   else if (TT.syscall==__NR_mmap || TT.syscall==__NR_brk) print_ptr(result);
602*cf5a6c84SAndroid Build Coastguard Worker   else fprintf(stderr, "%ld", result);
603*cf5a6c84SAndroid Build Coastguard Worker   fputc('\n', stderr);
604*cf5a6c84SAndroid Build Coastguard Worker }
605*cf5a6c84SAndroid Build Coastguard Worker 
next(void)606*cf5a6c84SAndroid Build Coastguard Worker static int next(void)
607*cf5a6c84SAndroid Build Coastguard Worker {
608*cf5a6c84SAndroid Build Coastguard Worker   int status;
609*cf5a6c84SAndroid Build Coastguard Worker 
610*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
611*cf5a6c84SAndroid Build Coastguard Worker     ptrace(PTRACE_SYSCALL, TT.pid, 0, 0);
612*cf5a6c84SAndroid Build Coastguard Worker     waitpid(TT.pid, &status, 0);
613*cf5a6c84SAndroid Build Coastguard Worker     // PTRACE_O_TRACESYSGOOD sets bit 7 to indicate a syscall.
614*cf5a6c84SAndroid Build Coastguard Worker     if (WIFSTOPPED(status) && WSTOPSIG(status) & 0x80) return 1;
615*cf5a6c84SAndroid Build Coastguard Worker     if (WIFEXITED(status)) return 0;
616*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "[stopped %d (%x)]\n", status, WSTOPSIG(status));
617*cf5a6c84SAndroid Build Coastguard Worker   }
618*cf5a6c84SAndroid Build Coastguard Worker }
619*cf5a6c84SAndroid Build Coastguard Worker 
strace_detach(int s)620*cf5a6c84SAndroid Build Coastguard Worker static void strace_detach(int s)
621*cf5a6c84SAndroid Build Coastguard Worker {
622*cf5a6c84SAndroid Build Coastguard Worker   xptrace(PTRACE_DETACH, TT.pid, 0, 0);
623*cf5a6c84SAndroid Build Coastguard Worker   exit(1);
624*cf5a6c84SAndroid Build Coastguard Worker }
625*cf5a6c84SAndroid Build Coastguard Worker 
strace_main(void)626*cf5a6c84SAndroid Build Coastguard Worker void strace_main(void)
627*cf5a6c84SAndroid Build Coastguard Worker {
628*cf5a6c84SAndroid Build Coastguard Worker   int status;
629*cf5a6c84SAndroid Build Coastguard Worker 
630*cf5a6c84SAndroid Build Coastguard Worker   if (!FLAG(s)) TT.s = 32;
631*cf5a6c84SAndroid Build Coastguard Worker 
632*cf5a6c84SAndroid Build Coastguard Worker   if (FLAG(p)) {
633*cf5a6c84SAndroid Build Coastguard Worker     if (*toys.optargs) help_exit("No arguments with -p");
634*cf5a6c84SAndroid Build Coastguard Worker     TT.pid = TT.p;
635*cf5a6c84SAndroid Build Coastguard Worker     signal(SIGINT, strace_detach);
636*cf5a6c84SAndroid Build Coastguard Worker     // TODO: PTRACE_SEIZE instead?
637*cf5a6c84SAndroid Build Coastguard Worker     xptrace(PTRACE_ATTACH, TT.pid, 0, 0);
638*cf5a6c84SAndroid Build Coastguard Worker   } else {
639*cf5a6c84SAndroid Build Coastguard Worker     if (!*toys.optargs) help_exit("Needs 1 argument");
640*cf5a6c84SAndroid Build Coastguard Worker     TT.pid = xfork();
641*cf5a6c84SAndroid Build Coastguard Worker     if (!TT.pid) {
642*cf5a6c84SAndroid Build Coastguard Worker       errno = 0;
643*cf5a6c84SAndroid Build Coastguard Worker       ptrace(PTRACE_TRACEME);
644*cf5a6c84SAndroid Build Coastguard Worker       if (errno) perror_exit("PTRACE_TRACEME failed");
645*cf5a6c84SAndroid Build Coastguard Worker       raise(SIGSTOP);
646*cf5a6c84SAndroid Build Coastguard Worker       toys.stacktop = 0;
647*cf5a6c84SAndroid Build Coastguard Worker       xexec(toys.optargs);
648*cf5a6c84SAndroid Build Coastguard Worker     }
649*cf5a6c84SAndroid Build Coastguard Worker   }
650*cf5a6c84SAndroid Build Coastguard Worker 
651*cf5a6c84SAndroid Build Coastguard Worker   do {
652*cf5a6c84SAndroid Build Coastguard Worker     waitpid(TT.pid, &status, 0);
653*cf5a6c84SAndroid Build Coastguard Worker   } while (!WIFSTOPPED(status));
654*cf5a6c84SAndroid Build Coastguard Worker 
655*cf5a6c84SAndroid Build Coastguard Worker   // TODO: PTRACE_O_TRACEEXIT
656*cf5a6c84SAndroid Build Coastguard Worker   // TODO: PTRACE_O_TRACEFORK/PTRACE_O_TRACEVFORK/PTRACE_O_TRACECLONE for -f.
657*cf5a6c84SAndroid Build Coastguard Worker   errno = 0;
658*cf5a6c84SAndroid Build Coastguard Worker   ptrace(PTRACE_SETOPTIONS, TT.pid, 0, PTRACE_O_TRACESYSGOOD);
659*cf5a6c84SAndroid Build Coastguard Worker   if (errno) perror_exit("PTRACE_SETOPTIONS PTRACE_O_TRACESYSGOOD failed");
660*cf5a6c84SAndroid Build Coastguard Worker 
661*cf5a6c84SAndroid Build Coastguard Worker   // TODO: real strace swallows the failed execve()s if it started the child
662*cf5a6c84SAndroid Build Coastguard Worker 
663*cf5a6c84SAndroid Build Coastguard Worker   for (;;) {
664*cf5a6c84SAndroid Build Coastguard Worker     if (!next()) break;
665*cf5a6c84SAndroid Build Coastguard Worker     print_enter();
666*cf5a6c84SAndroid Build Coastguard Worker     if (!next()) break;
667*cf5a6c84SAndroid Build Coastguard Worker     print_exit();
668*cf5a6c84SAndroid Build Coastguard Worker   }
669*cf5a6c84SAndroid Build Coastguard Worker 
670*cf5a6c84SAndroid Build Coastguard Worker   // TODO: support -f and keep track of children.
671*cf5a6c84SAndroid Build Coastguard Worker   waitpid(TT.pid, &status, 0);
672*cf5a6c84SAndroid Build Coastguard Worker   if (WIFEXITED(status))
673*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "+++ exited with %d +++\n", WEXITSTATUS(status));
674*cf5a6c84SAndroid Build Coastguard Worker   if (WIFSTOPPED(status))
675*cf5a6c84SAndroid Build Coastguard Worker     fprintf(stderr, "+++ stopped with %d +++\n", WSTOPSIG(status));
676*cf5a6c84SAndroid Build Coastguard Worker }
677