aio.c: use print_array function

* aio.c (print_iocbp): New function.
(SYS_FUNC(io_submit)): Use it via print_array.  Use widen_to_long
to process long int argument.
(print_io_event): Change to print struct io_event fetched elsewhere.
(SYS_FUNC(io_cancel)): Update use of print_io_event.
(SYS_FUNC(io_getevents)): Use print_io_event via print_array.
Use widen_to_long to print long int arguments.
* tests/aio.c (main): Check decoding of io_submit with negative "nr".
This commit is contained in:
Дмитрий Левин 2016-05-07 22:40:06 +00:00
parent 72e4f7af56
commit 2868e2b941
2 changed files with 51 additions and 54 deletions

101
aio.c
View File

@ -154,52 +154,54 @@ print_iocb(struct tcb *tcp, const struct iocb *cb)
}
}
static bool
print_iocbp(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
{
unsigned long addr;
struct iocb cb;
if (elem_size < sizeof(long)) {
addr = * (unsigned int *) elem_buf;
} else {
addr = * (unsigned long *) elem_buf;
}
tprints("{");
if (!umove_or_printaddr(tcp, addr, &cb))
print_iocb(tcp, &cb);
tprints("}");
return true;
}
SYS_FUNC(io_submit)
{
long nr = tcp->u_arg[1];
/* if nr <= 0, we end up printing just "[]" */
tprintf("%lu, %ld, [", tcp->u_arg[0], nr);
{
long i;
long iocbs = tcp->u_arg[2];
const long nr = widen_to_long(tcp->u_arg[1]);
const unsigned long addr = tcp->u_arg[2];
unsigned long iocbp;
for (i = 0; i < nr; ++i, iocbs += current_wordsize) {
unsigned long iocbp;
struct iocb cb;
tprintf("%lu, %ld, ", tcp->u_arg[0], nr);
if (i)
tprints(", ");
if (nr < 0)
printaddr(addr);
else
print_array(tcp, addr, nr, &iocbp, current_wordsize,
umoven_or_printaddr, print_iocbp, 0);
if (umove_ulong_or_printaddr(tcp, iocbs, &iocbp)) {
/*
* No point in trying to read the whole array
* because nr can be ridiculously large.
*/
break;
}
tprints("{");
if (!umove_or_printaddr(tcp, iocbp, &cb))
print_iocb(tcp, &cb);
tprints("}");
}
}
tprints("]");
return RVAL_DECODED;
}
static int
print_io_event(struct tcb *tcp, const long addr)
static bool
print_io_event(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
{
struct io_event event;
struct io_event *event = elem_buf;
if (umove_or_printaddr(tcp, addr, &event))
return -1;
tprintf("{data=%#" PRIx64 ", obj=%#" PRIx64
", res=%" PRId64 ", res2=%" PRId64 "}",
(uint64_t) event.data, (uint64_t) event.obj,
(int64_t) event.res, (int64_t) event.res2);
return 0;
(uint64_t) event->data, (uint64_t) event->obj,
(int64_t) event->res, (int64_t) event->res2);
return true;
}
SYS_FUNC(io_cancel)
@ -215,7 +217,10 @@ SYS_FUNC(io_cancel)
}
tprints(", ");
} else {
print_io_event(tcp, tcp->u_arg[2]);
struct io_event event;
if (!umove_or_printaddr(tcp, tcp->u_arg[2], &event))
print_io_event(tcp, &event, sizeof(event), 0);
}
return 0;
}
@ -224,26 +229,14 @@ SYS_FUNC(io_getevents)
{
if (entering(tcp)) {
tprintf("%lu, %ld, %ld, ",
tcp->u_arg[0], tcp->u_arg[1], tcp->u_arg[2]);
tcp->u_arg[0],
widen_to_long(tcp->u_arg[1]),
widen_to_long(tcp->u_arg[2]));
} else {
if (tcp->u_rval == 0) {
tprints("[]");
} else {
struct io_event *events = (void *)tcp->u_arg[3];
long i, nr = tcp->u_rval;
for (i = 0; i < nr; i++, events++) {
if (i == 0)
tprints("[");
else
tprints(", ");
if (print_io_event(tcp, (long)events))
break;
}
tprints("], ");
}
struct io_event buf;
print_array(tcp, tcp->u_arg[3], tcp->u_rval, &buf, sizeof(buf),
umoven_or_printaddr, print_io_event, 0);
tprints(", ");
/*
* Since the timeout parameter is read by the kernel
* on entering syscall, it has to be decoded the same way

View File

@ -146,6 +146,10 @@ main(void)
perror_msg_and_skip("io_setup");
printf("io_setup(%u, [%lu]) = 0\n", nr, *ctx);
assert(syscall(__NR_io_submit, *ctx, -1L, cbs) == -1);
printf("io_submit(%lu, -1, %p) = -1 %s (%m)\n",
*ctx, cbs, errno2name());
if (syscall(__NR_io_submit, *ctx, nr, cbs) != (long) nr)
perror_msg_and_skip("io_submit");
printf("io_submit(%lu, %u, ["