Page MenuHomeFreeBSD

D58094.diff
No OneTemporary

D58094.diff

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

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)

Event Timeline