truss: Add AIO syscalls.
Display the arguments of aio_read(2), aio_write(2), aio_suspend(2), aio_error(2), aio_return(2), aio_cancel(2), aio_fsync(2), aio_mlock(2), aio_waitcomplete(2) and lio_listio(2) in human-readable form. Reviewed by: asomers Differential Revision: https://reviews.freebsd.org/D27518
This commit is contained in:
parent
4708d329f8
commit
bb24ee2b7e
@ -87,6 +87,7 @@ enum Argtype {
|
||||
/* Encoded scalar values. */
|
||||
Accessmode,
|
||||
Acltype,
|
||||
AiofsyncOp,
|
||||
Atfd,
|
||||
Atflags,
|
||||
CapFcntlRights,
|
||||
@ -101,6 +102,7 @@ enum Argtype {
|
||||
Ioctl,
|
||||
Kldsymcmd,
|
||||
Kldunloadflags,
|
||||
LioMode,
|
||||
Madvice,
|
||||
Minherit,
|
||||
Msgflags,
|
||||
@ -139,6 +141,8 @@ enum Argtype {
|
||||
|
||||
/* Pointers to non-structures. */
|
||||
Ptr,
|
||||
AiocbArray,
|
||||
AiocbPointer,
|
||||
BinString,
|
||||
CapRights,
|
||||
ExecArgs,
|
||||
@ -157,6 +161,7 @@ enum Argtype {
|
||||
StringArray,
|
||||
|
||||
/* Pointers to structures. */
|
||||
Aiocb,
|
||||
Itimerval,
|
||||
Kevent,
|
||||
Kevent11,
|
||||
@ -168,6 +173,7 @@ enum Argtype {
|
||||
Schedparam,
|
||||
Sctpsndrcvinfo,
|
||||
Sigaction,
|
||||
Sigevent,
|
||||
Siginfo,
|
||||
Sigset,
|
||||
Sockaddr,
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
* arguments.
|
||||
*/
|
||||
|
||||
#include <sys/aio.h>
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/types.h>
|
||||
#define _WANT_FREEBSD11_KEVENT
|
||||
@ -125,6 +126,24 @@ static struct syscall decoded_syscalls[] = {
|
||||
.args = { { Int, 0 }, { Sockaddr | OUT, 1 }, { Ptr | OUT, 2 } } },
|
||||
{ .name = "access", .ret_type = 1, .nargs = 2,
|
||||
.args = { { Name | IN, 0 }, { Accessmode, 1 } } },
|
||||
{ .name = "aio_cancel", .ret_type = 1, .nargs = 2,
|
||||
.args = { { Int, 0 }, { Aiocb, 1 } } },
|
||||
{ .name = "aio_error", .ret_type = 1, .nargs = 1,
|
||||
.args = { { Aiocb, 0 } } },
|
||||
{ .name = "aio_fsync", .ret_type = 1, .nargs = 2,
|
||||
.args = { { AiofsyncOp, 0 }, { Aiocb, 1 } } },
|
||||
{ .name = "aio_mlock", .ret_type = 1, .nargs = 1,
|
||||
.args = { { Aiocb, 0 } } },
|
||||
{ .name = "aio_read", .ret_type = 1, .nargs = 1,
|
||||
.args = { { Aiocb, 0 } } },
|
||||
{ .name = "aio_return", .ret_type = 1, .nargs = 1,
|
||||
.args = { { Aiocb, 0 } } },
|
||||
{ .name = "aio_suspend", .ret_type = 1, .nargs = 3,
|
||||
.args = { { AiocbArray, 0 }, { Int, 1 }, { Timespec, 2 } } },
|
||||
{ .name = "aio_waitcomplete", .ret_type = 1, .nargs = 2,
|
||||
.args = { { AiocbPointer | OUT, 0 }, { Timespec, 1 } } },
|
||||
{ .name = "aio_write", .ret_type = 1, .nargs = 1,
|
||||
.args = { { Aiocb, 0 } } },
|
||||
{ .name = "bind", .ret_type = 1, .nargs = 3,
|
||||
.args = { { Int, 0 }, { Sockaddr | IN, 1 }, { Socklent, 2 } } },
|
||||
{ .name = "bindat", .ret_type = 1, .nargs = 4,
|
||||
@ -324,6 +343,9 @@ static struct syscall decoded_syscalls[] = {
|
||||
{ .name = "linkat", .ret_type = 1, .nargs = 5,
|
||||
.args = { { Atfd, 0 }, { Name, 1 }, { Atfd, 2 }, { Name, 3 },
|
||||
{ Atflags, 4 } } },
|
||||
{ .name = "lio_listio", .ret_type = 1, .nargs = 4,
|
||||
.args = { { LioMode, 0 }, { AiocbArray, 1 }, { Int, 2 },
|
||||
{ Sigevent, 3 } } },
|
||||
{ .name = "listen", .ret_type = 1, .nargs = 2,
|
||||
.args = { { Int, 0 }, { Int, 1 } } },
|
||||
{ .name = "lseek", .ret_type = 2, .nargs = 3,
|
||||
@ -714,6 +736,21 @@ static struct xlat linux_socketcall_ops[] = {
|
||||
XEND
|
||||
};
|
||||
|
||||
static struct xlat lio_modes[] = {
|
||||
X(LIO_WAIT) X(LIO_NOWAIT)
|
||||
XEND
|
||||
};
|
||||
|
||||
static struct xlat lio_opcodes[] = {
|
||||
X(LIO_WRITE) X(LIO_READ) X(LIO_NOP)
|
||||
XEND
|
||||
};
|
||||
|
||||
static struct xlat aio_fsync_ops[] = {
|
||||
X(O_SYNC)
|
||||
XEND
|
||||
};
|
||||
|
||||
#undef X
|
||||
#define X(a) { CLOUDABI_##a, #a },
|
||||
|
||||
@ -1332,6 +1369,59 @@ print_iovec(FILE *fp, struct trussinfo *trussinfo, uintptr_t arg, int iovcnt)
|
||||
fprintf(fp, "%s%s", iov_truncated ? ",..." : "", "]");
|
||||
}
|
||||
|
||||
static void
|
||||
print_sigval(FILE *fp, union sigval *sv)
|
||||
{
|
||||
fprintf(fp, "{ %d, %p }", sv->sival_int, sv->sival_ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
print_sigevent(FILE *fp, struct sigevent *se)
|
||||
{
|
||||
fputs("{ sigev_notify=", fp);
|
||||
switch (se->sigev_notify) {
|
||||
case SIGEV_NONE:
|
||||
fputs("SIGEV_NONE", fp);
|
||||
break;
|
||||
case SIGEV_SIGNAL:
|
||||
fprintf(fp, "SIGEV_SIGNAL, sigev_signo=%s, sigev_value=",
|
||||
strsig2(se->sigev_signo));
|
||||
print_sigval(fp, &se->sigev_value);
|
||||
break;
|
||||
case SIGEV_THREAD:
|
||||
fputs("SIGEV_THREAD, sigev_value=", fp);
|
||||
print_sigval(fp, &se->sigev_value);
|
||||
break;
|
||||
case SIGEV_KEVENT:
|
||||
fprintf(fp, "SIGEV_KEVENT, sigev_notify_kqueue=%d, sigev_notify_kevent_flags=",
|
||||
se->sigev_notify_kqueue);
|
||||
print_mask_arg(sysdecode_kevent_flags, fp, se->sigev_notify_kevent_flags);
|
||||
break;
|
||||
case SIGEV_THREAD_ID:
|
||||
fprintf(fp, "SIGEV_THREAD_ID, sigev_notify_thread_id=%d, sigev_signo=%s, sigev_value=",
|
||||
se->sigev_notify_thread_id, strsig2(se->sigev_signo));
|
||||
print_sigval(fp, &se->sigev_value);
|
||||
break;
|
||||
default:
|
||||
fprintf(fp, "%d", se->sigev_notify);
|
||||
break;
|
||||
}
|
||||
fputs(" }", fp);
|
||||
}
|
||||
|
||||
static void
|
||||
print_aiocb(FILE *fp, struct aiocb *cb)
|
||||
{
|
||||
fprintf(fp, "{ %d,%jd,%p,%zu,%s,",
|
||||
cb->aio_fildes,
|
||||
cb->aio_offset,
|
||||
cb->aio_buf,
|
||||
cb->aio_nbytes,
|
||||
xlookup(lio_opcodes, cb->aio_lio_opcode));
|
||||
print_sigevent(fp, &cb->aio_sigevent);
|
||||
fputs(" }", fp);
|
||||
}
|
||||
|
||||
static void
|
||||
print_gen_cmsg(FILE *fp, struct cmsghdr *cmsghdr)
|
||||
{
|
||||
@ -2115,6 +2205,15 @@ print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
|
||||
print_pointer(fp, args[sc->offset]);
|
||||
break;
|
||||
}
|
||||
case Sigevent: {
|
||||
struct sigevent se;
|
||||
|
||||
if (get_struct(pid, args[sc->offset], &se, sizeof(se)) != -1)
|
||||
print_sigevent(fp, &se);
|
||||
else
|
||||
print_pointer(fp, args[sc->offset]);
|
||||
break;
|
||||
}
|
||||
case Kevent: {
|
||||
/*
|
||||
* XXX XXX: The size of the array is determined by either the
|
||||
@ -2481,6 +2580,12 @@ print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
|
||||
print_integer_arg(sysdecode_kldunload_flags, fp,
|
||||
args[sc->offset]);
|
||||
break;
|
||||
case AiofsyncOp:
|
||||
fputs(xlookup(aio_fsync_ops, args[sc->offset]), fp);
|
||||
break;
|
||||
case LioMode:
|
||||
fputs(xlookup(lio_modes, args[sc->offset]), fp);
|
||||
break;
|
||||
case Madvice:
|
||||
print_integer_arg(sysdecode_madvice, fp, args[sc->offset]);
|
||||
break;
|
||||
@ -2618,6 +2723,67 @@ print_arg(struct syscall_args *sc, unsigned long *args, register_t *retval,
|
||||
print_iovec(fp, trussinfo, args[sc->offset],
|
||||
(int)args[sc->offset + 1]);
|
||||
break;
|
||||
case Aiocb: {
|
||||
struct aiocb cb;
|
||||
|
||||
if (get_struct(pid, args[sc->offset], &cb, sizeof(cb)) != -1)
|
||||
print_aiocb(fp, &cb);
|
||||
else
|
||||
print_pointer(fp, args[sc->offset]);
|
||||
break;
|
||||
}
|
||||
case AiocbArray: {
|
||||
/*
|
||||
* Print argment as an array of pointers to struct aiocb, where
|
||||
* the next syscall argument is the number of elements.
|
||||
*/
|
||||
uintptr_t cbs[16];
|
||||
unsigned int nent;
|
||||
bool truncated;
|
||||
|
||||
nent = args[sc->offset + 1];
|
||||
truncated = false;
|
||||
if (nent > nitems(cbs)) {
|
||||
nent = nitems(cbs);
|
||||
truncated = true;
|
||||
}
|
||||
|
||||
if (get_struct(pid, 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)
|
||||
print_aiocb(fp, &cb);
|
||||
else
|
||||
print_pointer(fp, cbs[i]);
|
||||
}
|
||||
if (truncated)
|
||||
fputs(",...", fp);
|
||||
fputs("]", fp);
|
||||
} else
|
||||
print_pointer(fp, args[sc->offset]);
|
||||
break;
|
||||
}
|
||||
case AiocbPointer: {
|
||||
/*
|
||||
* aio_waitcomplete(2) assigns a pointer to a pointer to struct
|
||||
* aiocb, so we need to handle the extra layer of indirection.
|
||||
*/
|
||||
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)
|
||||
print_aiocb(fp, &cb);
|
||||
else
|
||||
print_pointer(fp, cbp);
|
||||
} else
|
||||
print_pointer(fp, args[sc->offset]);
|
||||
break;
|
||||
}
|
||||
case Sctpsndrcvinfo: {
|
||||
struct sctp_sndrcvinfo info;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user