Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F168259493
D58094.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
39 KB
Referenced Files
None
Subscribers
None
D58094.diff
View Options
diff --git a/usr.bin/truss/extern.h b/usr.bin/truss/extern.h
--- a/usr.bin/truss/extern.h
+++ b/usr.bin/truss/extern.h
@@ -31,9 +31,18 @@
* SUCH DAMAGE.
*/
-extern int print_line_prefix(struct trussinfo *);
-extern void setup_and_wait(struct trussinfo *, char **);
-extern void start_tracing(struct trussinfo *, pid_t);
-extern void restore_proc(int);
-extern void decode_siginfo(FILE *, siginfo_t *);
-extern void eventloop(struct trussinfo *);
+#ifndef __TRUSS_EXTERN_H__
+#define __TRUSS_EXTERN_H__
+
+int print_line_prefix(struct trussinfo *);
+void setup_and_wait(struct trussinfo *, char **);
+void start_tracing(struct trussinfo *, pid_t);
+void restore_proc(int);
+void decode_siginfo(FILE *, siginfo_t *);
+void eventloop(struct trussinfo *);
+
+int truss_kill(struct trussinfo *info, struct procinfo *p, int sig);
+int truss_ptrace(struct trussinfo *info, int req, struct procinfo *p,
+ void *addr, int data);
+
+#endif
diff --git a/usr.bin/truss/main.c b/usr.bin/truss/main.c
--- a/usr.bin/truss/main.c
+++ b/usr.bin/truss/main.c
@@ -31,13 +31,14 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*
* The main module for truss. Surprisingly simple, but, then, the other
* files handle the bulk of the work. And, of course, the kernel has to
* do a lot of the work :).
*/
+#include <sys/capsicum.h>
+#include <sys/event.h>
#include <sys/ptrace.h>
#include <err.h>
@@ -57,8 +58,8 @@
usage(void)
{
fprintf(stderr, "%s\n%s\n",
- "usage: truss [-cfaedDHS] [-o file] [-s strsize] -p pid",
- " truss [-cfaedDHS] [-o file] [-s strsize] command [args]");
+ "usage: truss [-cfaedyYDHS] [-o file] [-s strsize] -p pid",
+ " truss [-cfaedyYDHS] [-o file] [-s strsize] command [args]");
exit(1);
}
@@ -67,6 +68,7 @@
{
struct sigaction sa;
struct trussinfo *trussinfo;
+ struct procinfo *np;
char *fname;
char **command;
const char *errstr;
@@ -85,7 +87,7 @@
trussinfo->strsize = 32;
trussinfo->curthread = NULL;
LIST_INIT(&trussinfo->proclist);
- while ((c = getopt(ac, av, "p:o:facedDs:SH")) != -1) {
+ while ((c = getopt(ac, av, "p:o:facedyYDs:SH")) != -1) {
switch (c) {
case 'p': /* specified pid */
pid = atoi(optarg);
@@ -121,6 +123,13 @@
if (errstr)
errx(1, "maximum string size is %s: %s", errstr, optarg);
break;
+ case 'y':
+ trussinfo->cap_mode = true;
+ break;
+ case 'Y':
+ trussinfo->cap_mode = true;
+ trussinfo->force_cap_mode = true;
+ break;
case 'S': /* Don't trace signals */
trussinfo->flags |= NOSIGS;
break;
@@ -146,6 +155,12 @@
err(1, "cannot open %s", fname);
}
+ if (trussinfo->cap_mode) {
+ trussinfo->pdkq = kqueue();
+ if (trussinfo->pdkq == -1)
+ err(1, "kqueue");
+ }
+
/*
* If truss starts the process itself, it will ignore some signals --
* they should be passed off to the process, which may or may not
@@ -173,7 +188,8 @@
* At this point, if we started the process, it is stopped waiting to
* be woken up, either in exit() or in execve().
*/
- if (LIST_FIRST(&trussinfo->proclist)->abi == NULL) {
+ np = LIST_FIRST(&trussinfo->proclist);
+ if (np->abi == NULL) {
/*
* If we are not able to handle this ABI, detach from the
* process and exit. If we just created a new process to
@@ -181,13 +197,11 @@
* it run untraced.
*/
if (pid == 0)
- kill(LIST_FIRST(&trussinfo->proclist)->pid, SIGKILL);
- ptrace(PT_DETACH, LIST_FIRST(&trussinfo->proclist)->pid, NULL,
- 0);
+ truss_kill(trussinfo, np, SIGKILL);
+ truss_ptrace(trussinfo, PT_DETACH, np, NULL, 0);
return (1);
}
- ptrace(PT_SYSCALL, LIST_FIRST(&trussinfo->proclist)->pid, (caddr_t)1,
- 0);
+ truss_ptrace(trussinfo, PT_SYSCALL, np, (caddr_t)1, 0);
/*
* At this point, it's a simple loop, waiting for the process to
diff --git a/usr.bin/truss/setup.c b/usr.bin/truss/setup.c
--- a/usr.bin/truss/setup.c
+++ b/usr.bin/truss/setup.c
@@ -31,13 +31,16 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
/*
* Various setup functions for truss. Not the cleanest-written code,
* I'm afraid.
*/
+#include <sys/capsicum.h>
+#include <sys/event.h>
#include <sys/ptrace.h>
+#include <sys/procdesc.h>
+#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <sys/wait.h>
@@ -59,6 +62,8 @@
#include "syscall.h"
#include "extern.h"
+#define WFLAGS (WTRAPPED | WEXITED | WCONTINUED | WUNTRACED)
+
struct procabi_table {
const char *name;
struct procabi *abi;
@@ -68,8 +73,9 @@
static void enter_syscall(struct trussinfo *, struct threadinfo *,
struct ptrace_lwpinfo *);
-static void new_proc(struct trussinfo *, pid_t, lwpid_t);
-
+static bool new_proc(struct trussinfo *, int, pid_t, lwpid_t, bool, bool);
+static void new_proc_register_kev(struct trussinfo *info, int pfd);
+static struct procinfo *find_proc(struct trussinfo *info, pid_t pid);
static struct procabi freebsd = {
.type = "FreeBSD",
@@ -138,6 +144,55 @@
#endif
};
+static int
+mypdptrace(int req, int pfd, int lwpid, void *addr, int data)
+{
+ return (syscall(SYS_pdptrace, req, pfd, lwpid, addr, data));
+}
+
+int
+truss_ptrace(struct trussinfo *info, int req, struct procinfo *p, void *addr,
+ int data)
+{
+ if (info->cap_mode)
+ return (mypdptrace(req, p->pfd, -1, addr, data));
+ return (ptrace(req, p->pid, addr, data));
+}
+
+static int
+truss_ptrace_lwp(struct trussinfo *info, int req, struct procinfo *p,
+ lwpid_t lwpid, void *addr, int data)
+{
+ if (info->cap_mode)
+ return (mypdptrace(req, p->pfd, lwpid, addr, data));
+ return (ptrace(req, lwpid, addr, data));
+}
+
+static int
+t_wait(struct trussinfo *info, int pid, int *status, int wflags)
+{
+ if (info->cap_mode)
+ return (pdwait(pid, status, wflags, NULL, NULL));
+ return (waitpid(pid, status, wflags));
+}
+
+static int
+truss_wait(struct trussinfo *info, struct procinfo *p, int *status,
+ int wflags)
+{
+ if (info->cap_mode)
+ return (pdwait(p->pfd, status, wflags, NULL, NULL));
+ return (waitpid(p->pid, status, wflags));
+}
+
+int
+truss_kill(struct trussinfo *info, struct procinfo *p, int sig)
+{
+ if (info->cap_mode)
+ return (pdkill(p->pfd, sig));
+ return (kill(p->pid, sig));
+}
+
/*
* setup_and_wait() is called to start a process. All it really does
* is fork(), enable tracing in the child, and then exec the given
@@ -148,21 +203,38 @@
setup_and_wait(struct trussinfo *info, char *command[])
{
pid_t pid;
+ int fd, res;
- pid = vfork();
- if (pid == -1)
- err(1, "fork failed");
+ if (info->cap_mode) {
+ pid = pdfork(&fd, PD_DAEMON | PD_CLOEXEC | PD_PTRACE_CAP);
+ if (pid == -1)
+ err(1, "fork failed");
+ } else {
+ pid = vfork();
+ fd = -1;
+ }
if (pid == 0) { /* Child */
ptrace(PT_TRACE_ME, 0, 0, 0);
execvp(command[0], command);
err(1, "execvp %s", command[0]);
}
+ if (info->cap_mode) {
+ if (cap_enter() == -1) {
+ if (info->force_cap_mode)
+ err(1, "cap_enter");
+ else
+ warn("cap_enter");
+ }
+ new_proc_register_kev(info, fd);
+ }
+
/* Only in the parent here */
- if (waitpid(pid, NULL, 0) < 0)
+ res = t_wait(info, info->cap_mode ? fd : pid, NULL, WFLAGS);
+ if (res < 0)
err(1, "unexpected stop in waitpid");
- new_proc(info, pid, 0);
+ new_proc(info, pid, 0, fd, false, false);
}
/*
@@ -171,20 +243,37 @@
void
start_tracing(struct trussinfo *info, pid_t pid)
{
- int ret, retry;
+ int fd, ret, retry;
+
+ if (info->cap_mode) {
+ fd = pdopenpid(pid, PD_DAEMON | PD_CLOEXEC | PD_PTRACE_CAP);
+ if (fd == -1)
+ err(1, "Cannot open the target process");
+ if (cap_enter() == -1) {
+ if (info->force_cap_mode)
+ err(1, "cap_enter");
+ else
+ warn("cap_enter");
+ }
+ new_proc_register_kev(info, fd);
+ } else {
+ fd = -1;
+ }
retry = 10;
do {
- ret = ptrace(PT_ATTACH, pid, NULL, 0);
+ ret = info->cap_mode ? mypdptrace(PT_ATTACH, fd, -1,
+ NULL, 0) : ptrace(PT_ATTACH, pid, NULL, 0);
usleep(200);
} while (ret && retry-- > 0);
if (ret)
err(1, "Cannot attach to target process");
- if (waitpid(pid, NULL, 0) < 0)
+ ret = t_wait(info, info->cap_mode ? fd : pid, NULL, WFLAGS);
+ if (ret < 0)
err(1, "Unexpected stop in waitpid");
- new_proc(info, pid, 0);
+ new_proc(info, pid, 0, fd, false, false);
}
/*
@@ -201,31 +290,32 @@
}
static void
-detach_proc(pid_t pid)
+detach_proc(struct trussinfo *info, struct procinfo *p)
{
- int sig, status;
+ int error, sig, status;
/*
* Stop the child so that we can detach. Filter out possible
* lingering SIGTRAP events buffered in the threads.
*/
- kill(pid, SIGSTOP);
+ truss_kill(info, p, SIGSTOP);
for (;;) {
- if (waitpid(pid, &status, 0) < 0)
+ error = truss_wait(info, p, &status, WFLAGS);
+ if (error < 0)
err(1, "Unexpected error in waitpid");
sig = WIFSTOPPED(status) ? WSTOPSIG(status) : 0;
if (sig == SIGSTOP)
break;
if (sig == SIGTRAP)
sig = 0;
- if (ptrace(PT_CONTINUE, pid, (caddr_t)1, sig) < 0)
+ if (truss_ptrace(info, PT_CONTINUE, p, (caddr_t)1, sig) < 0)
err(1, "Can not continue for detach");
}
- if (ptrace(PT_DETACH, pid, (caddr_t)1, 0) < 0)
+ if (truss_ptrace(info, PT_DETACH, p, (caddr_t)1, 0) < 0)
err(1, "Can not detach the process");
- kill(pid, SIGCONT);
+ truss_kill(info, p, SIGCONT);
}
/*
@@ -233,28 +323,22 @@
* a process is first monitored.
*/
static struct procabi *
-find_abi(pid_t pid)
+find_abi(struct trussinfo *info, struct procinfo *p)
{
- size_t len;
- unsigned int i;
- int error;
- int mib[4];
+ unsigned i;
char progt[32];
- len = sizeof(progt);
- mib[0] = CTL_KERN;
- mib[1] = KERN_PROC;
- mib[2] = KERN_PROC_SV_NAME;
- mib[3] = pid;
- error = sysctl(mib, 4, progt, &len, NULL, 0);
- if (error != 0)
- err(2, "can not get sysvec name");
+ if (truss_ptrace(info, PT_GET_ABI_NAME, p, progt,
+ sizeof(progt)) == -1) {
+ warn("cannot get ABI for proc %ld", (long)p->pid);
+ return (NULL);
+ }
for (i = 0; i < nitems(abis); i++) {
if (strcmp(abis[i].name, progt) == 0)
return (abis[i].abi);
}
- warnx("ABI %s for pid %ld is not supported", progt, (long)pid);
+ warnx("ABI %s for pid %ld is not supported", progt, (long)p->pid);
return (NULL);
}
@@ -297,17 +381,18 @@
lwpid_t *lwps;
int i, nlwps;
- nlwps = ptrace(PT_GETNUMLWPS, p->pid, NULL, 0);
+ nlwps = truss_ptrace(info, PT_GETNUMLWPS, p, NULL, 0);
if (nlwps == -1)
err(1, "Unable to fetch number of LWPs");
assert(nlwps > 0);
lwps = calloc(nlwps, sizeof(*lwps));
- nlwps = ptrace(PT_GETLWPLIST, p->pid, (caddr_t)lwps, nlwps);
+ nlwps = truss_ptrace(info, PT_GETLWPLIST, p, lwps, nlwps);
if (nlwps == -1)
err(1, "Unable to fetch LWP list");
for (i = 0; i < nlwps; i++) {
t = new_thread(p, lwps[i]);
- if (ptrace(PT_LWPINFO, lwps[i], (caddr_t)&pl, sizeof(pl)) == -1)
+ if (truss_ptrace_lwp(info, PT_LWPINFO, p, lwps[i], &pl,
+ sizeof(pl)) == -1)
err(1, "ptrace(PT_LWPINFO)");
if (pl.pl_flags & PL_FLAG_SCE) {
info->curthread = t;
@@ -318,27 +403,56 @@
}
static void
-new_proc(struct trussinfo *info, pid_t pid, lwpid_t lwpid)
+new_proc_register_kev(struct trussinfo *info, int pfd)
+{
+ struct kevent ev[1];
+ int error;
+
+ if (!info->cap_mode)
+ return;
+ EV_SET(&ev[0], pfd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT |
+ NOTE_PDSIGCHLD | NOTE_FORK, 0, 0);
+ error = kevent(info->pdkq, ev, nitems(ev), NULL, 0, NULL);
+ if (error == -1)
+ err(1, "Unable to register pfd %d for notifications", pfd);
+}
+
+static bool
+new_proc(struct trussinfo *info, pid_t pid, lwpid_t lwpid, int pfd,
+ bool allow_known, bool wait_for)
{
struct procinfo *np;
/*
- * If this happens it means there is a bug in truss. Unfortunately
- * this will kill any processes truss is attached to.
+ * If this happens it means there is a bug in truss.
+ * Unfortunately this will kill any processes truss is
+ * attached to.
*/
- LIST_FOREACH(np, &info->proclist, entries) {
- if (np->pid == pid)
+ if (find_proc(info, pid) != NULL) {
+ if (allow_known)
+ return (false);
+ else
errx(1, "Duplicate process for pid %ld", (long)pid);
}
+ if (pfd == -1 && info->cap_mode) {
+ pfd = pdopenpid(pid, PD_DAEMON | PD_CLOEXEC | PD_PTRACE_CAP);
+ if (pfd == -1)
+ err(1, "pdopenid %d", pid);
+ if (wait_for)
+ t_wait(info, pfd, NULL, WFLAGS);
+ new_proc_register_kev(info, pfd);
+ }
- if (info->flags & FOLLOWFORKS)
- if (ptrace(PT_FOLLOW_FORK, pid, NULL, 1) == -1)
- err(1, "Unable to follow forks for pid %ld", (long)pid);
- if (ptrace(PT_LWP_EVENTS, pid, NULL, 1) == -1)
- err(1, "Unable to enable LWP events for pid %ld", (long)pid);
np = calloc(1, sizeof(struct procinfo));
np->pid = pid;
- np->abi = find_abi(pid);
+ np->pfd = pfd;
+ np->abi = find_abi(info, np);
+ np->herald_printed = false;
+ if ((info->flags & FOLLOWFORKS) != 0 && truss_ptrace(info,
+ PT_FOLLOW_FORK, np, NULL, 1) == -1)
+ err(1, "Unable to follow forks for pid %ld", (long)pid);
+ if (truss_ptrace(info, PT_LWP_EVENTS, np, NULL, 1) == -1)
+ err(1, "Unable to enable LWP events for pid %ld", (long)pid);
LIST_INIT(&np->threadlist);
LIST_INIT(&np->fdlist);
LIST_INSERT_HEAD(&info->proclist, np, entries);
@@ -347,13 +461,21 @@
new_thread(np, lwpid);
else
add_threads(info, np);
+ return (true);
}
static void
-free_proc(struct procinfo *p)
+free_proc(struct trussinfo *info, struct procinfo *p)
{
struct threadinfo *t, *t2;
struct fd_domain *f, *f2;
+ struct kevent ev[1];
+
+ if (info->cap_mode) {
+ EV_SET(&ev[0], p->pfd, EVFILT_PROCDESC, EV_DELETE, 0, 0, 0);
+ (void)kevent(info->pdkq, ev, nitems(ev), NULL, 0, 0);
+ close(p->pfd);
+ }
LIST_FOREACH_SAFE(t, &p->threadlist, entries, t2) {
free(t);
@@ -373,8 +495,8 @@
struct procinfo *p, *p2;
LIST_FOREACH_SAFE(p, &info->proclist, entries, p2) {
- detach_proc(p->pid);
- free_proc(p);
+ detach_proc(info, p);
+ free_proc(info, p);
}
}
@@ -465,8 +587,8 @@
alloc_syscall(t, pl);
narg = MIN(pl->pl_syscall_narg, nitems(t->cs.args));
- if (narg != 0 && ptrace(PT_GET_SC_ARGS, t->tid, (caddr_t)t->cs.args,
- sizeof(t->cs.args)) != 0) {
+ if (narg != 0 && truss_ptrace_lwp(info, PT_GET_SC_ARGS, t->proc,
+ t->tid, (caddr_t)t->cs.args, sizeof(t->cs.args)) != 0) {
free_syscall(t);
return;
}
@@ -546,7 +668,8 @@
clock_gettime(CLOCK_REALTIME, &t->after);
p = t->proc;
- if (ptrace(PT_GET_SC_RET, t->tid, (caddr_t)&psr, sizeof(psr)) != 0) {
+ if (truss_ptrace_lwp(info, PT_GET_SC_RET, p, t->tid, &psr,
+ sizeof(psr)) != 0) {
free_syscall(t);
return;
}
@@ -614,11 +737,11 @@
*/
if (pl->pl_flags & PL_FLAG_EXEC) {
assert(LIST_NEXT(LIST_FIRST(&p->threadlist), entries) == NULL);
- p->abi = find_abi(p->pid);
+ p->abi = find_abi(info, p);
if (p->abi == NULL) {
- if (ptrace(PT_DETACH, p->pid, (caddr_t)1, 0) < 0)
+ if (truss_ptrace(info, PT_DETACH, p, (caddr_t)1, 0) < 0)
err(1, "Can not detach the process");
- free_proc(p);
+ free_proc(info, p);
}
}
}
@@ -701,6 +824,9 @@
struct threadinfo *t;
t = info->curthread;
+ if (t->proc->herald_printed)
+ return;
+ t->proc->herald_printed = true;
clock_gettime(CLOCK_REALTIME, &t->after);
t->before = t->after;
print_line_prefix(info);
@@ -780,6 +906,91 @@
}
+static void
+eventloop_handle_trapped(struct trussinfo *info, pid_t si_pid, int si_status,
+ siginfo_t *si)
+{
+ struct procinfo *np;
+ struct ptrace_lwpinfo pl;
+ int pending_signal;
+
+ np = find_proc(info, si_pid);
+ if (np == NULL)
+ new_proc(info, si_pid, -1, 0, true, false);
+ if (truss_ptrace(info, PT_LWPINFO, np, &pl, sizeof(pl)) == -1)
+ err(1, "ptrace(PT_LWPINFO)");
+
+ if ((pl.pl_flags & PL_FLAG_CHILD) != 0) {
+#if 0
+ new_proc(info, si_pid, pl.pl_lwpid, -1, true, false);
+#endif
+ assert(LIST_FIRST(&info->proclist)->abi != NULL);
+ } else if ((pl.pl_flags & PL_FLAG_BORN) != 0) {
+ new_thread(np, pl.pl_lwpid);
+ }
+ find_thread(info, si_pid, pl.pl_lwpid);
+
+ pending_signal = 0;
+ if (si_status == SIGTRAP && (pl.pl_flags & (PL_FLAG_BORN |
+ PL_FLAG_EXITED | PL_FLAG_SCE | PL_FLAG_SCX)) != 0) {
+ if ((pl.pl_flags & PL_FLAG_BORN) != 0) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_thread_birth(info);
+ } else if ((pl.pl_flags & PL_FLAG_EXITED) != 0) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_thread_death(info);
+ free_thread(info->curthread);
+ info->curthread = NULL;
+ } else if ((pl.pl_flags & PL_FLAG_SCE) != 0) {
+ enter_syscall(info, info->curthread, &pl);
+ } else if ((pl.pl_flags & PL_FLAG_SCX) != 0) {
+ exit_syscall(info, &pl);
+ }
+ } else if ((pl.pl_flags & PL_FLAG_CHILD) != 0) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_new_child(info);
+ } else if (si != NULL) {
+ if ((info->flags & NOSIGS) == 0)
+ report_signal(info, si, &pl);
+ pending_signal = si->si_status;
+ }
+ if (truss_ptrace(info, PT_SYSCALL, np, (caddr_t)1,
+ pending_signal) == -1)
+ err(1, "ptrace(PT_SYSCALL)");
+}
+
+static void
+eventloop_handle_note_fork(struct trussinfo *info)
+{
+ struct ptrace_child *ptcs;
+ int cnt, i;
+
+ cnt = ptrace(PT_GET_CHILDREN, getpid(), NULL, 0);
+ if (cnt == -1)
+ err(1, "Unexpected error from ptrace(PT_GET_CHILDREN) size");
+ if (cnt == 0)
+ return;
+ ptcs = calloc(cnt, sizeof(*ptcs));
+ if (ptcs == NULL)
+ err(1, "No memory");
+ cnt = ptrace(PT_GET_CHILDREN, getpid(), (caddr_t)ptcs,
+ cnt * sizeof(*ptcs));
+ if (cnt == -1)
+ err(1, "Unexpected error from ptrace(PT_GET_CHILDREN) data");
+ for (i = 0; i < cnt; i++) {
+ if ((ptcs[i].flags & (PTCHLD_TRACED | PTCHLD_TRACED_BY_ME |
+ PTCHLD_EXITED)) != (PTCHLD_TRACED | PTCHLD_TRACED_BY_ME))
+ continue;
+ if (new_proc(info, ptcs[i].pid, 0, -1, true, true)) {
+ if ((info->flags & COUNTONLY) == 0)
+ report_new_child(info);
+ eventloop_handle_trapped(info, ptcs[i].pid, SIGTRAP,
+ NULL);
+ }
+ }
+ free(ptcs);
+}
+
/*
* Wait for events until all the processes have exited or truss has been
* asked to stop.
@@ -787,9 +998,10 @@
void
eventloop(struct trussinfo *info)
{
- struct ptrace_lwpinfo pl;
siginfo_t si;
- int pending_signal;
+ struct kevent ev[1];
+ int cnt, error;
+ bool has_si;
while (!LIST_EMPTY(&info->proclist)) {
if (detaching) {
@@ -797,11 +1009,52 @@
return;
}
- if (waitid(P_ALL, 0, &si, WTRAPPED | WEXITED) == -1) {
- if (errno == EINTR)
+ has_si = false;
+ if (info->cap_mode) {
+ cnt = kevent(info->pdkq, NULL, 0, ev, nitems(ev),
+ NULL);
+ if (cnt == -1) {
+ if (errno == EINTR)
+ continue;
+ err(1, "Unexpected error from kevent");
+ }
+ if (cnt == 0) {
+ /* XXXKIB ? */
continue;
- err(1, "Unexpected error from waitid");
+ }
+ if ((ev[0].fflags & (NOTE_EXIT | NOTE_PDSIGCHLD)) !=
+ 0) {
+ error = pdwait(ev[0].ident, NULL,
+ WFLAGS | WNOHANG, NULL, &si);
+ if (error == -1) {
+ if (errno == EINTR ||
+ errno == EWOULDBLOCK)
+ continue;
+ err(1, "Unexpected error from pdwait");
+ }
+ has_si = true;
+
+ /*
+ * To get rid of zombie, we need to
+ * waitpid() on it in addition to the
+ * pdwait() above, because we are the
+ * debugger, and the child was
+ * reparented to us.
+ */
+ waitpid(si.si_pid, NULL, WEXITED | WNOHANG);
+ }
+ if ((ev[0].fflags & NOTE_FORK) != 0)
+ eventloop_handle_note_fork(info);
+ } else {
+ if (waitid(P_ALL, 0, &si, WTRAPPED | WEXITED) == -1) {
+ if (errno == EINTR)
+ continue;
+ err(1, "Unexpected error from waitid");
+ }
+ has_si = true;
}
+ if (!has_si)
+ continue;
assert(si.si_signo == SIGCHLD);
@@ -815,50 +1068,12 @@
thread_exit_syscall(info);
report_exit(info, &si);
}
- free_proc(info->curthread->proc);
+ free_proc(info, info->curthread->proc);
info->curthread = NULL;
break;
case CLD_TRAPPED:
- if (ptrace(PT_LWPINFO, si.si_pid, (caddr_t)&pl,
- sizeof(pl)) == -1)
- err(1, "ptrace(PT_LWPINFO)");
-
- if (pl.pl_flags & PL_FLAG_CHILD) {
- new_proc(info, si.si_pid, pl.pl_lwpid);
- assert(LIST_FIRST(&info->proclist)->abi !=
- NULL);
- } else if (pl.pl_flags & PL_FLAG_BORN)
- new_thread(find_proc(info, si.si_pid),
- pl.pl_lwpid);
- find_thread(info, si.si_pid, pl.pl_lwpid);
-
- if (si.si_status == SIGTRAP &&
- (pl.pl_flags & (PL_FLAG_BORN|PL_FLAG_EXITED|
- PL_FLAG_SCE|PL_FLAG_SCX)) != 0) {
- if (pl.pl_flags & PL_FLAG_BORN) {
- if ((info->flags & COUNTONLY) == 0)
- report_thread_birth(info);
- } else if (pl.pl_flags & PL_FLAG_EXITED) {
- if ((info->flags & COUNTONLY) == 0)
- report_thread_death(info);
- free_thread(info->curthread);
- info->curthread = NULL;
- } else if (pl.pl_flags & PL_FLAG_SCE)
- enter_syscall(info, info->curthread, &pl);
- else if (pl.pl_flags & PL_FLAG_SCX)
- exit_syscall(info, &pl);
- pending_signal = 0;
- } else if (pl.pl_flags & PL_FLAG_CHILD) {
- if ((info->flags & COUNTONLY) == 0)
- report_new_child(info);
- pending_signal = 0;
- } else {
- if ((info->flags & NOSIGS) == 0)
- report_signal(info, &si, &pl);
- pending_signal = si.si_status;
- }
- ptrace(PT_SYSCALL, si.si_pid, (caddr_t)1,
- pending_signal);
+ eventloop_handle_trapped(info, si.si_pid,
+ si.si_status, &si);
break;
case CLD_STOPPED:
errx(1, "waitid reported CLD_STOPPED");
diff --git a/usr.bin/truss/syscalls.c b/usr.bin/truss/syscalls.c
--- a/usr.bin/truss/syscalls.c
+++ b/usr.bin/truss/syscalls.c
@@ -948,7 +948,8 @@
* Copy a fixed amount of bytes from the process.
*/
static int
-get_struct(pid_t pid, psaddr_t offset, void *buf, size_t len)
+get_struct(struct trussinfo *info, struct procinfo *p, psaddr_t offset,
+ void *buf, size_t len)
{
struct ptrace_io_desc iorequest;
@@ -956,7 +957,7 @@
iorequest.piod_offs = (void *)(uintptr_t)offset;
iorequest.piod_addr = buf;
iorequest.piod_len = len;
- if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0)
+ if (truss_ptrace(info, PT_IO, p, (caddr_t)&iorequest, 0) < 0)
return (-1);
return (0);
}
@@ -969,7 +970,7 @@
* only get that much.
*/
static char *
-get_string(pid_t pid, psaddr_t addr, int max)
+get_string(struct trussinfo *info, struct procinfo *p, psaddr_t addr, int max)
{
struct ptrace_io_desc iorequest;
char *buf, *nbuf;
@@ -993,7 +994,7 @@
iorequest.piod_offs = (void *)((uintptr_t)addr + offset);
iorequest.piod_addr = buf + offset;
iorequest.piod_len = size;
- if (ptrace(PT_IO, pid, (caddr_t)&iorequest, 0) < 0) {
+ if (truss_ptrace(info, PT_IO, p, (caddr_t)&iorequest, 0) < 0) {
free(buf);
return (NULL);
}
@@ -1096,7 +1097,9 @@
struct sockaddr_un *sun;
struct sockaddr *sa;
u_char *q;
- pid_t pid = trussinfo->curthread->proc->pid;
+ struct procinfo *p;
+
+ p = trussinfo->curthread->proc;
if (arg == 0) {
fputs("NULL", fp);
@@ -1109,7 +1112,7 @@
}
sa = calloc(1, len);
- if (get_struct(pid, arg, sa, len) == -1) {
+ if (get_struct(trussinfo, p, arg, sa, len) == -1) {
free(sa);
print_pointer(fp, arg);
return;
@@ -1159,11 +1162,11 @@
static void
print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
{
+ struct procinfo *p;
struct iovec iov[IOV_LIMIT];
size_t max_string = trussinfo->strsize;
char tmp2[max_string + 1], *tmp3;
size_t len;
- pid_t pid = trussinfo->curthread->proc->pid;
int i;
bool buf_truncated, iov_truncated;
@@ -1177,7 +1180,9 @@
} else {
iov_truncated = false;
}
- if (get_struct(pid, arg, &iov, iovcnt * sizeof(struct iovec)) == -1) {
+ p = trussinfo->curthread->proc;
+ if (get_struct(trussinfo, p, arg, &iov, iovcnt *
+ sizeof(struct iovec)) == -1) {
print_pointer(fp, arg);
return;
}
@@ -1192,7 +1197,8 @@
buf_truncated = false;
}
fprintf(fp, "%s{", (i > 0) ? "," : "");
- if (len && get_struct(pid, (uintptr_t)iov[i].iov_base, &tmp2, len) != -1) {
+ if (len && get_struct(trussinfo, p, (uintptr_t)iov[i].iov_base,
+ &tmp2, len) != -1) {
tmp3 = malloc(len * 4 + 1);
while (len) {
if (strvisx(tmp3, tmp2, len,
@@ -1464,7 +1470,8 @@
}
static void
-print_cmsgs(FILE *fp, pid_t pid, bool receive, struct msghdr *msghdr)
+print_cmsgs(FILE *fp, struct trussinfo *info, struct procinfo *p,
+ bool receive, struct msghdr *msghdr)
{
struct cmsghdr *cmsghdr;
char *cmsgbuf;
@@ -1479,7 +1486,8 @@
return;
}
cmsgbuf = calloc(1, len);
- if (get_struct(pid, (uintptr_t)msghdr->msg_control, cmsgbuf, len) == -1) {
+ if (get_struct(info, p, (uintptr_t)msghdr->msg_control, cmsgbuf,
+ len) == -1) {
print_pointer(fp, (uintptr_t)msghdr->msg_control);
free(cmsgbuf);
return;
@@ -1597,7 +1605,7 @@
int protocol)
{
char *buf;
- pid_t pid = trussinfo->curthread->proc->pid;
+ struct procinfo *p;
bool success = false;
if (msg == NULL || len == 0)
@@ -1611,7 +1619,8 @@
if (buf == NULL)
return (false);
- if (get_struct(pid, (uintptr_t)msg, buf, read_len) == -1) {
+ p = trussinfo->curthread->proc;
+ if (get_struct(trussinfo, p, (uintptr_t)msg, buf, read_len) == -1) {
free(buf);
return (false);
}
@@ -1635,12 +1644,12 @@
struct trussinfo *trussinfo, struct syscall_decode *decode)
{
FILE *fp;
+ struct procinfo *p;
char *tmp;
size_t tmplen;
- pid_t pid;
fp = open_memstream(&tmp, &tmplen);
- pid = trussinfo->curthread->proc->pid;
+ p = trussinfo->curthread->proc;
switch (sc->type & ARG_MASK) {
case Hex:
fprintf(fp, "0x%x", (int)args[sc->offset]);
@@ -1657,7 +1666,7 @@
case PUInt: {
unsigned int val;
- if (get_struct(pid, args[sc->offset], &val,
+ if (get_struct(trussinfo, p, args[sc->offset], &val,
sizeof(val)) == 0)
fprintf(fp, "{ %u }", val);
else
@@ -1684,7 +1693,7 @@
/* NULL-terminated string. */
char *tmp2;
- tmp2 = get_string(pid, args[sc->offset], 0);
+ tmp2 = get_string(trussinfo, p, args[sc->offset], 0);
fprintf(fp, "\"%s\"", tmp2);
free(tmp2);
break;
@@ -1727,8 +1736,8 @@
len = max_string;
truncated = 1;
}
- if (len && get_struct(pid, args[sc->offset], &tmp2, len)
- != -1) {
+ if (len && get_struct(trussinfo, p, args[sc->offset], &tmp2,
+ len) != -1) {
tmp3 = malloc(len * 4 + 1);
while (len) {
if (strvisx(tmp3, tmp2, len,
@@ -1784,7 +1793,7 @@
}
len = PAGE_SIZE - (addr & PAGE_MASK);
- if (get_struct(pid, addr, u.buf, len) == -1) {
+ if (get_struct(trussinfo, p, addr, u.buf, len) == -1) {
print_pointer(fp, args[sc->offset]);
break;
}
@@ -1807,7 +1816,7 @@
/* Stop once we read the first NULL pointer. */
if (straddr == 0)
break;
- string = get_string(pid, straddr, 0);
+ string = get_string(trussinfo, p, straddr, 0);
fprintf(fp, "%s \"%s\"", first ? "" : ",", string);
free(string);
first = 0;
@@ -1816,7 +1825,8 @@
if (i == len / pointer_size) {
addr += len;
len = PAGE_SIZE;
- if (get_struct(pid, addr, u.buf, len) == -1) {
+ if (get_struct(trussinfo, p, addr, u.buf,
+ len) == -1) {
fprintf(fp, ", <inval>");
break;
}
@@ -1852,7 +1862,7 @@
case PQuadHex: {
uint64_t val;
- if (get_struct(pid, args[sc->offset], &val,
+ if (get_struct(trussinfo, p, args[sc->offset], &val,
sizeof(val)) == 0)
fprintf(fp, "{ 0x%jx }", (uintmax_t)val);
else
@@ -1867,7 +1877,7 @@
if (retval[0] == -1)
break;
- tmp2 = get_string(pid, args[sc->offset], retval[0]);
+ tmp2 = get_string(trussinfo, p, args[sc->offset], retval[0]);
fprintf(fp, "\"%s\"", tmp2);
free(tmp2);
break;
@@ -1892,7 +1902,8 @@
case Timespec: {
struct timespec ts;
- if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &ts, sizeof(ts))
+ != -1)
fprintf(fp, "{ %jd.%09ld }", (intmax_t)ts.tv_sec,
ts.tv_nsec);
else
@@ -1904,7 +1915,8 @@
const char *sep;
unsigned int i;
- if (get_struct(pid, args[sc->offset], &ts, sizeof(ts)) != -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], &ts, sizeof(ts))
+ != -1) {
fputs("{ ", fp);
sep = "";
for (i = 0; i < nitems(ts); i++) {
@@ -1932,7 +1944,8 @@
case Timeval: {
struct timeval tv;
- if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &tv, sizeof(tv))
+ != -1)
fprintf(fp, "{ %jd.%06ld }", (intmax_t)tv.tv_sec,
tv.tv_usec);
else
@@ -1942,7 +1955,8 @@
case Timeval2: {
struct timeval tv[2];
- if (get_struct(pid, args[sc->offset], &tv, sizeof(tv)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &tv, sizeof(tv))
+ != -1)
fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
(intmax_t)tv[0].tv_sec, tv[0].tv_usec,
(intmax_t)tv[1].tv_sec, tv[1].tv_usec);
@@ -1953,7 +1967,8 @@
case Itimerval: {
struct itimerval itv;
- if (get_struct(pid, args[sc->offset], &itv, sizeof(itv)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &itv, sizeof(itv))
+ != -1)
fprintf(fp, "{ %jd.%06ld, %jd.%06ld }",
(intmax_t)itv.it_interval.tv_sec,
itv.it_interval.tv_usec,
@@ -1967,7 +1982,7 @@
{
struct linux_socketcall_args largs;
- if (get_struct(pid, args[sc->offset], (void *)&largs,
+ if (get_struct(trussinfo, p, args[sc->offset], (void *)&largs,
sizeof(largs)) != -1)
fprintf(fp, "{ %s, 0x%lx }",
lookup(linux_socketcall_ops, largs.what, 10),
@@ -1990,7 +2005,8 @@
if ((pfd = malloc(bytes)) == NULL)
err(1, "Cannot malloc %zu bytes for pollfd array",
bytes);
- if (get_struct(pid, args[sc->offset], pfd, bytes) != -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], pfd, bytes)
+ != -1) {
fputs("{", fp);
for (i = 0; i < numfds; i++) {
fprintf(fp, " %d/%s", pfd[i].fd,
@@ -2017,7 +2033,8 @@
if ((fds = malloc(bytes)) == NULL)
err(1, "Cannot malloc %zu bytes for fd_set array",
bytes);
- if (get_struct(pid, args[sc->offset], fds, bytes) != -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], fds, bytes)
+ != -1) {
fputs("{", fp);
for (i = 0; i < numfds; i++) {
if (FD_ISSET(i, fds))
@@ -2036,7 +2053,7 @@
sigset_t ss;
int i, first;
- if (get_struct(pid, args[sc->offset], (void *)&ss,
+ if (get_struct(trussinfo, p, args[sc->offset], (void *)&ss,
sizeof(ss)) == -1) {
print_pointer(fp, args[sc->offset]);
break;
@@ -2122,8 +2139,8 @@
* the next argument contains a socklen_t by value.
*/
if (sc->type & OUT) {
- if (get_struct(pid, args[sc->offset + 1], &len,
- sizeof(len)) == -1) {
+ if (get_struct(trussinfo, p, args[sc->offset + 1],
+ &len, sizeof(len)) == -1) {
print_pointer(fp, args[sc->offset]);
break;
}
@@ -2136,7 +2153,8 @@
case Sigaction: {
struct sigaction sa;
- if (get_struct(pid, args[sc->offset], &sa, sizeof(sa)) != -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], &sa, sizeof(sa))
+ != -1) {
fputs("{ ", fp);
if (sa.sa_handler == SIG_DFL)
fputs("SIG_DFL", fp);
@@ -2153,7 +2171,8 @@
case Sigevent: {
struct sigevent se;
- if (get_struct(pid, args[sc->offset], &se, sizeof(se)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &se, sizeof(se))
+ != -1)
print_sigevent(fp, &se);
else
print_pointer(fp, args[sc->offset]);
@@ -2185,7 +2204,7 @@
bytes);
} else
ke = NULL;
- if (numevents >= 0 && get_struct(pid, args[sc->offset],
+ if (numevents >= 0 && get_struct(trussinfo, p, args[sc->offset],
ke, bytes) != -1) {
fputc('{', fp);
for (i = 0; i < numevents; i++) {
@@ -2220,7 +2239,7 @@
} else
ke11 = NULL;
memset(&ke, 0, sizeof(ke));
- if (numevents >= 0 && get_struct(pid, args[sc->offset],
+ if (numevents >= 0 && get_struct(trussinfo, p, args[sc->offset],
ke11, bytes) != -1) {
fputc('{', fp);
for (i = 0; i < numevents; i++) {
@@ -2243,7 +2262,7 @@
case Stat: {
struct stat st;
- if (get_struct(pid, args[sc->offset], &st, sizeof(st))
+ if (get_struct(trussinfo, p, args[sc->offset], &st, sizeof(st))
!= -1) {
char mode[12];
@@ -2260,7 +2279,7 @@
case Stat11: {
struct freebsd11_stat st;
- if (get_struct(pid, args[sc->offset], &st, sizeof(st))
+ if (get_struct(trussinfo, p, args[sc->offset], &st, sizeof(st))
!= -1) {
char mode[12];
@@ -2278,7 +2297,7 @@
unsigned int i;
struct statfs buf;
- if (get_struct(pid, args[sc->offset], &buf,
+ if (get_struct(trussinfo, p, args[sc->offset], &buf,
sizeof(buf)) != -1) {
char fsid[17];
@@ -2301,7 +2320,7 @@
case Rusage: {
struct rusage ru;
- if (get_struct(pid, args[sc->offset], &ru, sizeof(ru))
+ if (get_struct(trussinfo, p, args[sc->offset], &ru, sizeof(ru))
!= -1) {
fprintf(fp,
"{ u=%jd.%06ld,s=%jd.%06ld,in=%ld,out=%ld }",
@@ -2315,7 +2334,7 @@
case Rlimit: {
struct rlimit rl;
- if (get_struct(pid, args[sc->offset], &rl, sizeof(rl))
+ if (get_struct(trussinfo, p, args[sc->offset], &rl, sizeof(rl))
!= -1) {
fprintf(fp, "{ cur=%ju,max=%ju }",
rl.rlim_cur, rl.rlim_max);
@@ -2326,7 +2345,7 @@
case ExitStatus: {
int status;
- if (get_struct(pid, args[sc->offset], &status,
+ if (get_struct(trussinfo, p, args[sc->offset], &status,
sizeof(status)) != -1) {
fputs("{ ", fp);
if (WIFCONTINUED(status))
@@ -2384,7 +2403,7 @@
memset(name, 0, sizeof(name));
len = args[sc->offset + 1];
- if (get_struct(pid, args[sc->offset], oid,
+ if (get_struct(trussinfo, p, args[sc->offset], oid,
len * sizeof(oid[0])) != -1) {
fprintf(fp, "\"");
if (oid[0] == CTL_SYSCTL) {
@@ -2402,7 +2421,7 @@
break;
case CTL_SYSCTL_NAME2OID:
fprintf(fp, "name2oid %s",
- get_string(pid,
+ get_string(trussinfo, p,
args[sc->offset + 4],
args[sc->offset + 5]));
break;
@@ -2452,7 +2471,7 @@
len = args[sc->offset + 1];
utrace_addr = calloc(1, len);
- if (get_struct(pid, args[sc->offset],
+ if (get_struct(trussinfo, p, args[sc->offset],
(void *)utrace_addr, len) != -1)
print_utrace(fp, utrace_addr, len);
else
@@ -2471,7 +2490,7 @@
ndescriptors = nitems(descriptors);
truncated = true;
}
- if (get_struct(pid, args[sc->offset],
+ if (get_struct(trussinfo, p, args[sc->offset],
descriptors, ndescriptors * sizeof(descriptors[0])) != -1) {
fprintf(fp, "{");
for (i = 0; i < ndescriptors; i++)
@@ -2489,7 +2508,7 @@
uint32_t rights;
if (sc->type & OUT) {
- if (get_struct(pid, args[sc->offset], &rights,
+ if (get_struct(trussinfo, p, args[sc->offset], &rights,
sizeof(rights)) == -1) {
print_pointer(fp, args[sc->offset]);
break;
@@ -2585,7 +2604,7 @@
case CapRights: {
cap_rights_t rights;
- if (get_struct(pid, args[sc->offset], &rights,
+ if (get_struct(trussinfo, p, args[sc->offset], &rights,
sizeof(rights)) != -1) {
fputs("{ ", fp);
sysdecode_cap_rights(fp, &rights);
@@ -2627,8 +2646,8 @@
case Sendfilehdtr: {
struct sf_hdtr hdtr;
- if (get_struct(pid, args[sc->offset], &hdtr, sizeof(hdtr)) !=
- -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], &hdtr,
+ sizeof(hdtr)) != -1) {
fprintf(fp, "{");
print_iovec(fp, trussinfo, (uintptr_t)hdtr.headers,
hdtr.hdr_cnt);
@@ -2657,7 +2676,8 @@
case Schedparam: {
struct sched_param sp;
- if (get_struct(pid, args[sc->offset], &sp, sizeof(sp)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &sp,
+ sizeof(sp)) != -1)
fprintf(fp, "{ %d }", sp.sched_priority);
else
print_pointer(fp, args[sc->offset]);
@@ -2666,7 +2686,8 @@
case PSig: {
int sig;
- if (get_struct(pid, args[sc->offset], &sig, sizeof(sig)) == 0)
+ if (get_struct(trussinfo, p, args[sc->offset], &sig,
+ sizeof(sig)) == 0)
fprintf(fp, "{ %s }", strsig2(sig));
else
print_pointer(fp, args[sc->offset]);
@@ -2675,7 +2696,8 @@
case Siginfo: {
siginfo_t si;
- if (get_struct(pid, args[sc->offset], &si, sizeof(si)) != -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], &si,
+ sizeof(si)) != -1) {
fprintf(fp, "{ signo=%s", strsig2(si.si_signo));
decode_siginfo(fp, &si);
fprintf(fp, " }");
@@ -2695,7 +2717,8 @@
case Aiocb: {
struct aiocb cb;
- if (get_struct(pid, args[sc->offset], &cb, sizeof(cb)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &cb,
+ sizeof(cb)) != -1)
print_aiocb(fp, &cb);
else
print_pointer(fp, args[sc->offset]);
@@ -2717,14 +2740,16 @@
truncated = true;
}
- if (get_struct(pid, args[sc->offset], cbs, sizeof(uintptr_t) * nent) != -1) {
+ if (get_struct(trussinfo, p, args[sc->offset], cbs,
+ sizeof(uintptr_t) * nent) != -1) {
unsigned int i;
fputs("[", fp);
for (i = 0; i < nent; ++i) {
struct aiocb cb;
if (i > 0)
fputc(',', fp);
- if (get_struct(pid, cbs[i], &cb, sizeof(cb)) != -1)
+ if (get_struct(trussinfo, p, cbs[i], &cb,
+ sizeof(cb)) != -1)
print_aiocb(fp, &cb);
else
print_pointer(fp, cbs[i]);
@@ -2744,8 +2769,10 @@
uintptr_t cbp;
struct aiocb cb;
- if (get_struct(pid, args[sc->offset], &cbp, sizeof(cbp)) != -1) {
- if (get_struct(pid, cbp, &cb, sizeof(cb)) != -1)
+ if (get_struct(trussinfo, p, args[sc->offset], &cbp,
+ sizeof(cbp)) != -1) {
+ if (get_struct(trussinfo, p, cbp, &cb, sizeof(cb))
+ != -1)
print_aiocb(fp, &cb);
else
print_pointer(fp, cbp);
@@ -2756,7 +2783,7 @@
case Sctpsndrcvinfo: {
struct sctp_sndrcvinfo info;
- if (get_struct(pid, args[sc->offset],
+ if (get_struct(trussinfo, p, args[sc->offset],
&info, sizeof(struct sctp_sndrcvinfo)) == -1) {
print_pointer(fp, args[sc->offset]);
break;
@@ -2768,7 +2795,7 @@
struct msghdr msghdr;
struct iovec iov;
- if (get_struct(pid, args[sc->offset],
+ if (get_struct(trussinfo, p, args[sc->offset],
&msghdr, sizeof(struct msghdr)) == -1) {
print_pointer(fp, args[sc->offset]);
break;
@@ -2779,7 +2806,7 @@
/* Attempt Netlink decode; fallback to standard iovec if it fails. */
int protocol = get_netlink_protocol(trussinfo, (int)args[0]);
if ((protocol == -1) ||
- (get_struct(pid, (uintptr_t)msghdr.msg_iov,
+ (get_struct(trussinfo, p, (uintptr_t)msghdr.msg_iov,
&iov, sizeof(iov)) == -1) ||
(!print_netlink(fp, trussinfo, (void *)iov.iov_base,
(size_t)iov.iov_len, protocol))) {
@@ -2787,7 +2814,7 @@
msghdr.msg_iovlen);
}
fprintf(fp, ",%d,", msghdr.msg_iovlen);
- print_cmsgs(fp, pid, sc->type & OUT, &msghdr);
+ print_cmsgs(fp, trussinfo, p, sc->type & OUT, &msghdr);
fprintf(fp, ",%u,", msghdr.msg_controllen);
print_mask_arg(sysdecode_msg_flags, fp, msghdr.msg_flags);
fputs("}", fp);
diff --git a/usr.bin/truss/truss.h b/usr.bin/truss/truss.h
--- a/usr.bin/truss/truss.h
+++ b/usr.bin/truss/truss.h
@@ -25,6 +25,9 @@
* SUCH DAMAGE.
*/
+#ifndef __TRUSS_TRUSS_H__
+#define __TRUSS_TRUSS_H__
+
#include <sys/queue.h>
#define FOLLOWFORKS 0x00000001
@@ -106,7 +109,9 @@
struct procinfo {
LIST_ENTRY(procinfo) entries;
pid_t pid;
+ int pfd;
struct procabi *abi;
+ bool herald_printed;
LIST_HEAD(, threadinfo) threadlist;
LIST_HEAD(, fd_domain) fdlist;
@@ -117,6 +122,9 @@
int flags;
int strsize;
FILE *outfile;
+ int pdkq;
+ bool cap_mode;
+ bool force_cap_mode;
struct timespec start_time;
@@ -124,3 +132,5 @@
LIST_HEAD(, procinfo) proclist;
};
+
+#endif
diff --git a/usr.bin/truss/truss.1 b/usr.bin/truss/truss.1
--- a/usr.bin/truss/truss.1
+++ b/usr.bin/truss/truss.1
@@ -7,7 +7,7 @@
.Nd trace system calls
.Sh SYNOPSIS
.Nm
-.Op Fl facedDHS
+.Op Fl facedyDHSY
.Op Fl o Ar file
.Op Fl s Ar strsize
.Fl p Ar pid
@@ -62,6 +62,22 @@
(Normally,
.Nm
displays signal as well as system call events.)
+.It Fl y
+Enter the capability mode
+.Pq see Xr capsicum 4
+after opening the output file, and creating and
+attaching to the target process.
+The error to enter the mode is not fatal, but a warning is
+issued to the standard error.
+.It Fl Y
+Same as
+.Fl y ,
+but make the error to enter the capability mode fatal.
+Since the traced process is spawn and attached to
+before the entry into the mode, it is killed by
+the termination of the
+.Nm
+itself.
.It Fl o Ar file
Print the output to the specified
.Ar file
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 28, 5:50 AM (20 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37439153
Default Alt Text
D58094.diff (39 KB)
Attached To
Mode
D58094: Capsicumise truss(1)
Attached
Detach File
Event Timeline
Log In to Comment