scsi_ioctl(struct tcb *const tcp, const unsigned int code,
const kernel_ulong_t arg)
{
- uint32_t iid;
-
if (SG_IO != code)
return RVAL_DECODED;
if (entering(tcp)) {
+ uint32_t iid;
+
tprints(", ");
if (umove_or_printaddr(tcp, arg, &iid)) {
return RVAL_DECODED | 1;
} else {
- set_tcb_priv_ulong(tcp, iid);
return decode_sg_io(tcp, iid, arg);
}
} else {
- if (!syserror(tcp)) {
- iid = get_tcb_priv_ulong(tcp);
- decode_sg_io(tcp, iid, arg);
- }
+ uint32_t *piid = get_tcb_priv_data(tcp);
+ if (piid)
+ decode_sg_io(tcp, *piid, arg);
tprints("}");
return RVAL_DECODED | 1;
}
print_sg_io_buffer(tcp, ptr_to_kulong(sg_io.dxferp),
sg_io.dxfer_len);
}
+
+ struct_sg_io_hdr *entering_sg_io = malloc(sizeof(*entering_sg_io));
+ if (entering_sg_io) {
+ memcpy(entering_sg_io, &sg_io, sizeof(sg_io));
+ entering_sg_io->interface_id = (unsigned char) 'S';
+ set_tcb_priv_data(tcp, entering_sg_io, free);
+ }
+
return 1;
}
static int
decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
{
+ struct_sg_io_hdr *entering_sg_io = get_tcb_priv_data(tcp);
struct_sg_io_hdr sg_io;
if (umove(tcp, arg, &sg_io) < 0) {
- tprints(", ???");
+ /* print i/o fields fetched on entering syscall */
+ if (entering_sg_io->dxfer_direction == SG_DXFER_FROM_DEV) {
+ tprints(", dxferp=");
+ printaddr(ptr_to_kulong(entering_sg_io->dxferp));
+ }
+ tprints(", sbp=");
+ printaddr(ptr_to_kulong(entering_sg_io->sbp));
return RVAL_DECODED | 1;
}
- if (sg_io.interface_id != (unsigned char) 'S') {
+ if (sg_io.interface_id != entering_sg_io->interface_id) {
tprintf(" => interface_id=%u", sg_io.interface_id);
return RVAL_DECODED | 1;
}
sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
uint32_t din_len = sg_io.dxfer_len;
- if (sg_io.resid > 0)
+ if (sg_io.resid > 0 && (unsigned int) sg_io.resid <= din_len)
din_len -= sg_io.resid;
- tprints(", dxferp=");
- if (sg_io.iovec_count)
- tprint_iov_upto(tcp, sg_io.iovec_count,
- ptr_to_kulong(sg_io.dxferp),
- syserror(tcp) ? IOV_DECODE_ADDR :
- IOV_DECODE_STR, din_len);
- else
- print_sg_io_buffer(tcp, ptr_to_kulong(sg_io.dxferp),
- din_len);
+ if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV) {
+ tprints(", dxferp=");
+ } else if (din_len) {
+ tprints(" => dxferp=");
+ }
+ if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV || din_len) {
+ if (sg_io.iovec_count)
+ tprint_iov_upto(tcp, sg_io.iovec_count,
+ ptr_to_kulong(sg_io.dxferp),
+ IOV_DECODE_STR, din_len);
+ else
+ print_sg_io_buffer(tcp, ptr_to_kulong(sg_io.dxferp),
+ din_len);
+ }
}
tprintf(", status=%#x", sg_io.status);
tprintf(", masked_status=%#x", sg_io.masked_status);
tprints(", flags=");
printflags(bsg_flags, sg_io.flags, "BSG_FLAG_???");
tprintf(", usr_ptr=%#" PRI__x64, sg_io.usr_ptr);
+
+ struct sg_io_v4 *entering_sg_io = malloc(sizeof(*entering_sg_io));
+ if (entering_sg_io) {
+ memcpy(entering_sg_io, &sg_io, sizeof(sg_io));
+ entering_sg_io->guard = (unsigned char) 'Q';
+ set_tcb_priv_data(tcp, entering_sg_io, free);
+ }
+
return 1;
}
static int
decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
{
+ struct sg_io_v4 *entering_sg_io = get_tcb_priv_data(tcp);
struct sg_io_v4 sg_io;
uint32_t din_len;
if (umove(tcp, arg, &sg_io) < 0) {
- tprints(", ???");
+ /* print i/o fields fetched on entering syscall */
+ tprints(", response=");
+ printaddr(entering_sg_io->response);
+ tprints(", din_xferp=");
+ printaddr(entering_sg_io->din_xferp);
return RVAL_DECODED | 1;
}
- if (sg_io.guard != (unsigned char) 'Q') {
+ if (sg_io.guard != entering_sg_io->guard) {
tprintf(" => guard=%u", sg_io.guard);
return RVAL_DECODED | 1;
}
tprintf(", response_len=%u, response=", sg_io.response_len);
print_sg_io_buffer(tcp, sg_io.response, sg_io.response_len);
din_len = sg_io.din_xfer_len;
- if (sg_io.din_resid > 0)
+ if (sg_io.din_resid > 0 && (unsigned int) sg_io.din_resid <= din_len)
din_len -= sg_io.din_resid;
tprints(", din_xferp=");
if (sg_io.din_iovec_count)
tprint_iov_upto(tcp, sg_io.din_iovec_count, sg_io.din_xferp,
- syserror(tcp) ? IOV_DECODE_ADDR :
IOV_DECODE_STR, din_len);
else
print_sg_io_buffer(tcp, sg_io.din_xferp, din_len);