static void print_cap_data(struct tcb *tcp, unsigned long addr, const cap_user_header_t h) { struct user_cap_data_struct data[2]; unsigned int len; if (!addr || !h) { printaddr(addr); return; } if (_LINUX_CAPABILITY_VERSION_2 == h->version || _LINUX_CAPABILITY_VERSION_3 == h->version) len = 2; else len = 1; if (umoven_or_printaddr(tcp, addr, len * sizeof(data[0]), data)) return; tprints("{"); print_cap_bits(data[0].effective, len > 1 ? data[1].effective : 0); tprints(", "); print_cap_bits(data[0].permitted, len > 1 ? data[1].permitted : 0); tprints(", "); print_cap_bits(data[0].inheritable, len > 1 ? data[1].inheritable : 0); tprints("}"); }
bool decode_nla_linkinfo_xstats_can(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct strace_can_device_stats { uint32_t bus_error; uint32_t error_warning; uint32_t error_passive; uint32_t bus_off; uint32_t arbitration_lost; uint32_t restarts; } st; const unsigned int def_size = sizeof(st); const unsigned int size = (len >= def_size) ? def_size : 0; if (!size) return false; if (umoven_or_printaddr(tcp, addr, size, &st)) return true; PRINT_FIELD_U("{", st, bus_error); PRINT_FIELD_U(", ", st, error_warning); PRINT_FIELD_U(", ", st, error_passive); PRINT_FIELD_U(", ", st, bus_off); PRINT_FIELD_U(", ", st, arbitration_lost); PRINT_FIELD_U(", ", st, restarts); tprints("}"); return true; }
static void print_sched_attr(struct tcb *const tcp, const kernel_ulong_t addr, unsigned int size) { struct { uint32_t size; uint32_t sched_policy; uint64_t sched_flags; uint32_t sched_nice; uint32_t sched_priority; uint64_t sched_runtime; uint64_t sched_deadline; uint64_t sched_period; } attr = {}; if (size > sizeof(attr)) size = sizeof(attr); if (umoven_or_printaddr(tcp, addr, size, &attr)) return; tprintf("{size=%u, sched_policy=", attr.size); printxval(schedulers, attr.sched_policy, "SCHED_???"); tprints(", sched_flags="); printflags64(sched_flags, attr.sched_flags, "SCHED_FLAG_???"); tprintf(", sched_nice=%d", attr.sched_nice); tprintf(", sched_priority=%u", attr.sched_priority); tprintf(", sched_runtime=%" PRIu64, attr.sched_runtime); tprintf(", sched_deadline=%" PRIu64, attr.sched_deadline); tprintf(", sched_period=%" PRIu64 "}", attr.sched_period); }
static bool decode_tc_stats(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct tc_stats st; const unsigned int sizeof_tc_stats = offsetofend(struct tc_stats, backlog); if (len < sizeof_tc_stats) return false; else if (!umoven_or_printaddr(tcp, addr, sizeof_tc_stats, &st)) { PRINT_FIELD_U("{", st, bytes); PRINT_FIELD_U(", ", st, packets); PRINT_FIELD_U(", ", st, drops); PRINT_FIELD_U(", ", st, overlimits); PRINT_FIELD_U(", ", st, bps); PRINT_FIELD_U(", ", st, pps); PRINT_FIELD_U(", ", st, qlen); PRINT_FIELD_U(", ", st, backlog); tprints("}"); } return true; }
static void printargv(struct tcb *tcp, long addr) { union { unsigned int p32; unsigned long p64; char data[sizeof(long)]; } cp; const char *sep; unsigned int n = 0; const unsigned wordsize = current_wordsize; cp.p64 = 1; for (sep = ""; !abbrev(tcp) || n < max_strlen / 2; sep = ", ", ++n) { if (umoven_or_printaddr(tcp, addr, wordsize, cp.data)) return; if (wordsize == 4) cp.p64 = cp.p32; if (cp.p64 == 0) break; tprints(sep); printstr(tcp, cp.p64, -1); addr += wordsize; } if (cp.p64) tprintf("%s...", sep); }
static bool decode_rtnl_link_stats64(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_RTNL_LINK_STATS64 struct rtnl_link_stats64 st; const unsigned int min_size = offsetofend(struct rtnl_link_stats64, tx_compressed); const unsigned int def_size = sizeof(st); const unsigned int size = (len >= def_size) ? def_size : ((len == min_size) ? min_size : 0); if (!size) return false; if (!umoven_or_printaddr(tcp, addr, size, &st)) { PRINT_FIELD_U("{", st, rx_packets); PRINT_FIELD_U(", ", st, tx_packets); PRINT_FIELD_U(", ", st, rx_bytes); PRINT_FIELD_U(", ", st, tx_bytes); PRINT_FIELD_U(", ", st, rx_errors); PRINT_FIELD_U(", ", st, tx_errors); PRINT_FIELD_U(", ", st, rx_dropped); PRINT_FIELD_U(", ", st, tx_dropped); PRINT_FIELD_U(", ", st, multicast); PRINT_FIELD_U(", ", st, collisions); PRINT_FIELD_U(", ", st, rx_length_errors); PRINT_FIELD_U(", ", st, rx_over_errors); PRINT_FIELD_U(", ", st, rx_crc_errors); PRINT_FIELD_U(", ", st, rx_frame_errors); PRINT_FIELD_U(", ", st, rx_fifo_errors); PRINT_FIELD_U(", ", st, rx_missed_errors); PRINT_FIELD_U(", ", st, tx_aborted_errors); PRINT_FIELD_U(", ", st, tx_carrier_errors); PRINT_FIELD_U(", ", st, tx_fifo_errors); PRINT_FIELD_U(", ", st, tx_heartbeat_errors); PRINT_FIELD_U(", ", st, tx_window_errors); PRINT_FIELD_U(", ", st, rx_compressed); PRINT_FIELD_U(", ", st, tx_compressed); #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER if (len >= def_size) PRINT_FIELD_U(", ", st, rx_nohandler); #endif tprints("}"); } return true; #else return false; #endif }
static void print_sigset_addr_len_limit(struct tcb *tcp, long addr, long len, long min_len) { /* * Here len is usually equal to NSIG / 8 or current_wordsize. * But we code this defensively: */ if (len < min_len || len > NSIG / 8) { printaddr(addr); return; } int mask[NSIG / 8 / sizeof(int)] = {}; if (umoven_or_printaddr(tcp, addr, len, mask)) return; tprints(sprintsigmask_n("", mask, len)); }
static int fetch_msgrcv_args(struct tcb *tcp, const long addr, unsigned long *pair) { if (current_wordsize == sizeof(*pair)) { if (umoven_or_printaddr(tcp, addr, 2 * sizeof(*pair), pair)) return -1; } else { unsigned int tmp[2]; if (umove_or_printaddr(tcp, addr, &tmp)) return -1; pair[0] = tmp[0]; pair[1] = tmp[1]; } return 0; }
static void print_sigset_addr_len_limit(struct tcb *const tcp, const kernel_ulong_t addr, const kernel_ulong_t len, const unsigned int min_len) { /* * Here len is usually equal to NSIG_BYTES or current_wordsize. * But we code this defensively: */ if (len < min_len || len > NSIG_BYTES) { printaddr(addr); return; } int mask[NSIG_BYTES / sizeof(int)] = {}; if (umoven_or_printaddr(tcp, addr, len, mask)) return; tprints(sprintsigmask_n("", mask, len)); }
static void print_icmp_filter(struct tcb *tcp, const long addr, int len) { struct icmp_filter filter = {}; if (len > (int) sizeof(filter)) len = sizeof(filter); else if (len <= 0) { printaddr(addr); return; } if (umoven_or_printaddr(tcp, addr, len, &filter)) return; tprints("~("); printflags(icmpfilterflags, ~filter.data, "ICMP_???"); tprints(")"); }
static int umove_kulong_array_or_printaddr(struct tcb *const tcp, const kernel_ulong_t addr, kernel_ulong_t *const ptr, const size_t n) { #ifndef current_klongsize if (current_klongsize < sizeof(*ptr)) { uint32_t ptr32[n]; int r = umove_or_printaddr(tcp, addr, &ptr32); if (!r) { size_t i; for (i = 0; i < n; ++i) ptr[i] = ptr32[i]; } return r; } #endif /* !current_klongsize */ return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr); }
static void decode_inet_diag_req_compat(struct tcb *const tcp, const struct nlmsghdr *const nlmsghdr, const uint8_t family, const kernel_ulong_t addr, const unsigned int len) { struct inet_diag_req req = { .idiag_family = family }; size_t offset = sizeof(req.idiag_family); bool decode_nla = false; PRINT_FIELD_XVAL("{", req, idiag_family, addrfams, "AF_???"); tprints(", "); if (len >= sizeof(req)) { if (!umoven_or_printaddr(tcp, addr + offset, sizeof(req) - offset, (char *) &req + offset)) { PRINT_FIELD_U("", req, idiag_src_len); PRINT_FIELD_U(", ", req, idiag_dst_len); PRINT_FIELD_FLAGS(", ", req, idiag_ext, inet_diag_extended_flags, "1<<INET_DIAG_\?\?\?-1"); PRINT_FIELD_INET_DIAG_SOCKID(", ", req, id, req.idiag_family); PRINT_FIELD_FLAGS(", ", req, idiag_states, tcp_state_flags, "1<<TCP_???"); PRINT_FIELD_U(", ", req, idiag_dbs); decode_nla = true; } } else tprints("..."); tprints("}"); offset = NLMSG_ALIGN(sizeof(req)); if (decode_nla && len > offset) { tprints(", "); decode_nlattr(tcp, addr + offset, len - offset, inet_diag_req_attrs, "INET_DIAG_REQ_???", inet_diag_req_nla_decoders, ARRAY_SIZE(inet_diag_req_nla_decoders), NULL); } }
void printsock(struct tcb *tcp, long addr, int addrlen) { sockaddr_buf_t addrbuf; if (addrlen < 2) { printaddr(addr); return; } if (addrlen > (int) sizeof(addrbuf)) addrlen = sizeof(addrbuf); memset(&addrbuf, 0, sizeof(addrbuf)); if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad)) return; addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0'; print_sockaddr(tcp, &addrbuf, addrlen); }
static int umove_kulong_array_or_printaddr(struct tcb *tcp, const long addr, kernel_ulong_t *ptr, size_t n) { #if defined X86_64 || defined X32 if (current_personality == 1) { #else if (current_wordsize < sizeof(*ptr)) { #endif uint32_t ptr32[n]; int r = umove_or_printaddr(tcp, addr, &ptr32); if (!r) { size_t i; for (i = 0; i < n; ++i) ptr[i] = (kernel_ulong_t) ptr32[i]; } return r; } return umoven_or_printaddr(tcp, addr, n * sizeof(*ptr), ptr); } SYS_FUNC(pselect6) { int rc = decode_select(tcp, tcp->u_arg, print_timespec, sprint_timespec); if (entering(tcp)) { kernel_ulong_t data[2]; tprints(", "); if (!umove_kulong_array_or_printaddr(tcp, tcp->u_arg[5], data, ARRAY_SIZE(data))) { tprints("{"); /* NB: kernel requires data[1] == NSIG / 8 */ print_sigset_addr_len(tcp, (unsigned long) data[0], (unsigned long) data[1]); tprintf(", %llu}", (unsigned long long) data[1]); } } return rc; }
void print_sigset_addr_len(struct tcb *tcp, long addr, long len) { char mask[NSIG / 8]; /* Here len is usually equals NSIG / 8 or current_wordsize. * But we code this defensively: */ if (len < 0) { printaddr(addr); return; } if (len >= NSIG / 8) len = NSIG / 8; else len = (len + 3) & ~3; if (umoven_or_printaddr(tcp, addr, len, mask)) return; tprints(sprintsigmask_n("", mask, len)); }
static bool decode_gnet_stats_basic(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_GNET_STATS_BASIC struct gnet_stats_basic sb; const unsigned int sizeof_st_basic = offsetofend(struct gnet_stats_basic, packets); if (len < sizeof_st_basic) return false; else if (!umoven_or_printaddr(tcp, addr, sizeof_st_basic, &sb)) { PRINT_FIELD_U("{", sb, bytes); PRINT_FIELD_U(", ", sb, packets); tprints("}"); } return true; #else return false; #endif }
static bool decode_rtnl_link_ifmap(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct rtnl_link_ifmap map; const unsigned int sizeof_ifmap = offsetofend(struct rtnl_link_ifmap, port); if (len < sizeof_ifmap) return false; else if (!umoven_or_printaddr(tcp, addr, sizeof_ifmap, &map)) { PRINT_FIELD_X("{", map, mem_start); PRINT_FIELD_X(", ", map, mem_end); PRINT_FIELD_X(", ", map, base_addr); PRINT_FIELD_U(", ", map, irq); PRINT_FIELD_U(", ", map, dma); PRINT_FIELD_U(", ", map, port); tprints("}"); } return true; }
static void print_affinitylist(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len) { const unsigned int max_size = get_cpuset_size(); const unsigned int umove_size = len < max_size ? len : max_size; const unsigned int size = (umove_size + current_wordsize - 1) & -current_wordsize; const unsigned int ncpu = size * 8; void *cpu; if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)) || !addr || !len || !(cpu = calloc(size, 1))) { printaddr(addr); return; } if (!umoven_or_printaddr(tcp, addr, umove_size, cpu)) { int i = 0; const char *sep = ""; tprints("["); for (;; i++) { i = next_set_bit(cpu, i, ncpu); if (i < 0) break; tprintf("%s%d", sep, i); sep = ", "; } if (size < len) tprintf("%s...", sep); tprints("]"); } free(cpu); }
static bool decode_ifla_linkinfo(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { struct ifla_linkinfo_ctx ctx = { .kind = "", }; decode_nlattr(tcp, addr, len, rtnl_ifla_info_attrs, "IFLA_INFO_???", ARRSZ_PAIR(ifla_linkinfo_nla_decoders), &ctx); return true; } static bool decode_rtnl_link_stats64(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_RTNL_LINK_STATS64 struct rtnl_link_stats64 st; const unsigned int min_size = offsetofend(struct rtnl_link_stats64, tx_compressed); const unsigned int def_size = sizeof(st); const unsigned int size = (len >= def_size) ? def_size : ((len == min_size) ? min_size : 0); if (!size) return false; if (!umoven_or_printaddr(tcp, addr, size, &st)) { PRINT_FIELD_U("{", st, rx_packets); PRINT_FIELD_U(", ", st, tx_packets); PRINT_FIELD_U(", ", st, rx_bytes); PRINT_FIELD_U(", ", st, tx_bytes); PRINT_FIELD_U(", ", st, rx_errors); PRINT_FIELD_U(", ", st, tx_errors); PRINT_FIELD_U(", ", st, rx_dropped); PRINT_FIELD_U(", ", st, tx_dropped); PRINT_FIELD_U(", ", st, multicast); PRINT_FIELD_U(", ", st, collisions); PRINT_FIELD_U(", ", st, rx_length_errors); PRINT_FIELD_U(", ", st, rx_over_errors); PRINT_FIELD_U(", ", st, rx_crc_errors); PRINT_FIELD_U(", ", st, rx_frame_errors); PRINT_FIELD_U(", ", st, rx_fifo_errors); PRINT_FIELD_U(", ", st, rx_missed_errors); PRINT_FIELD_U(", ", st, tx_aborted_errors); PRINT_FIELD_U(", ", st, tx_carrier_errors); PRINT_FIELD_U(", ", st, tx_fifo_errors); PRINT_FIELD_U(", ", st, tx_heartbeat_errors); PRINT_FIELD_U(", ", st, tx_window_errors); PRINT_FIELD_U(", ", st, rx_compressed); PRINT_FIELD_U(", ", st, tx_compressed); #ifdef HAVE_STRUCT_RTNL_LINK_STATS64_RX_NOHANDLER if (len >= def_size) PRINT_FIELD_U(", ", st, rx_nohandler); #endif tprints("}"); } return true; #else return false; #endif } static bool decode_ifla_port_vsi(struct tcb *const tcp, const kernel_ulong_t addr, const unsigned int len, const void *const opaque_data) { #ifdef HAVE_STRUCT_IFLA_PORT_VSI struct ifla_port_vsi vsi; if (len < sizeof(vsi)) return false; else if (!umove_or_printaddr(tcp, addr, &vsi)) { PRINT_FIELD_U("{", vsi, vsi_mgr_id); PRINT_FIELD_STRING(", ", vsi, vsi_type_id, sizeof(vsi.vsi_type_id), QUOTE_FORCE_HEX); PRINT_FIELD_U(", ", vsi, vsi_type_version); tprints("}"); } return true; #else return false; #endif } static const nla_decoder_t ifla_port_nla_decoders[] = { [IFLA_PORT_VF] = decode_nla_u32, [IFLA_PORT_PROFILE] = decode_nla_str, [IFLA_PORT_VSI_TYPE] = decode_ifla_port_vsi, [IFLA_PORT_INSTANCE_UUID] = NULL, /* default parser */ [IFLA_PORT_HOST_UUID] = NULL, /* default parser */ [IFLA_PORT_REQUEST] = decode_nla_u8, [IFLA_PORT_RESPONSE] = decode_nla_u16 };
void printsock(struct tcb *tcp, long addr, int addrlen) { union { char pad[128]; struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_un sau; #ifdef HAVE_INET_NTOP struct sockaddr_in6 sa6; #endif #if defined(AF_IPX) struct sockaddr_ipx sipx; #endif #ifdef AF_PACKET struct sockaddr_ll ll; #endif #ifdef AF_NETLINK struct sockaddr_nl nl; #endif #ifdef HAVE_BLUETOOTH_BLUETOOTH_H struct sockaddr_hci hci; struct sockaddr_l2 l2; struct sockaddr_rc rc; struct sockaddr_sco sco; #endif } addrbuf; char string_addr[100]; if (addrlen < 2 || addrlen > (int) sizeof(addrbuf)) addrlen = sizeof(addrbuf); memset(&addrbuf, 0, sizeof(addrbuf)); if (umoven_or_printaddr(tcp, addr, addrlen, addrbuf.pad)) return; addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0'; tprints("{sa_family="); printxval(addrfams, addrbuf.sa.sa_family, "AF_???"); tprints(", "); switch (addrbuf.sa.sa_family) { case AF_UNIX: if (addrlen == 2) { tprints("NULL"); } else if (addrbuf.sau.sun_path[0]) { tprints("sun_path="); print_quoted_string(addrbuf.sau.sun_path, sizeof(addrbuf.sau.sun_path) + 1, QUOTE_0_TERMINATED); } else { tprints("sun_path=@"); print_quoted_string(addrbuf.sau.sun_path + 1, sizeof(addrbuf.sau.sun_path), QUOTE_0_TERMINATED); } break; case AF_INET: tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")", ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr)); break; #ifdef HAVE_INET_NTOP case AF_INET6: inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr)); tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u", ntohs(addrbuf.sa6.sin6_port), string_addr, addrbuf.sa6.sin6_flowinfo); #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID tprints(", sin6_scope_id="); #if defined IN6_IS_ADDR_LINKLOCAL && defined IN6_IS_ADDR_MC_LINKLOCAL if (IN6_IS_ADDR_LINKLOCAL(&addrbuf.sa6.sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&addrbuf.sa6.sin6_addr)) print_ifindex(addrbuf.sa6.sin6_scope_id); else #endif tprintf("%u", addrbuf.sa6.sin6_scope_id); #endif /* HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID */ break; #endif #if defined(AF_IPX) case AF_IPX: { int i; tprintf("sipx_port=htons(%u), ", ntohs(addrbuf.sipx.sipx_port)); /* Yes, I know, this does not look too * strace-ish, but otherwise the IPX * addresses just look monstrous... * Anyways, feel free if you don't like * this way.. :) */ tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network)); for (i = 0; i < IPX_NODE_LEN; i++) tprintf("%02x", addrbuf.sipx.sipx_node[i]); tprintf("/[%02x]", addrbuf.sipx.sipx_type); } break; #endif /* AF_IPX */ #ifdef AF_PACKET case AF_PACKET: { int i; tprintf("proto=%#04x, if%d, pkttype=", ntohs(addrbuf.ll.sll_protocol), addrbuf.ll.sll_ifindex); printxval(af_packet_types, addrbuf.ll.sll_pkttype, "PACKET_???"); tprintf(", addr(%d)={%d, ", addrbuf.ll.sll_halen, addrbuf.ll.sll_hatype); for (i = 0; i < addrbuf.ll.sll_halen; i++) tprintf("%02x", addrbuf.ll.sll_addr[i]); } break; #endif /* AF_PACKET */ #ifdef AF_NETLINK case AF_NETLINK: tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups); break; #endif /* AF_NETLINK */ #if defined(AF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H) case AF_BLUETOOTH: tprintf("{sco_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X} or " "{rc_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, rc_channel=%d} or " "{l2_psm=htobs(%d), l2_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, l2_cid=htobs(%d)} or " "{hci_dev=htobs(%d)}", addrbuf.sco.sco_bdaddr.b[0], addrbuf.sco.sco_bdaddr.b[1], addrbuf.sco.sco_bdaddr.b[2], addrbuf.sco.sco_bdaddr.b[3], addrbuf.sco.sco_bdaddr.b[4], addrbuf.sco.sco_bdaddr.b[5], addrbuf.rc.rc_bdaddr.b[0], addrbuf.rc.rc_bdaddr.b[1], addrbuf.rc.rc_bdaddr.b[2], addrbuf.rc.rc_bdaddr.b[3], addrbuf.rc.rc_bdaddr.b[4], addrbuf.rc.rc_bdaddr.b[5], addrbuf.rc.rc_channel, btohs(addrbuf.l2.l2_psm), addrbuf.l2.l2_bdaddr.b[0], addrbuf.l2.l2_bdaddr.b[1], addrbuf.l2.l2_bdaddr.b[2], addrbuf.l2.l2_bdaddr.b[3], addrbuf.l2.l2_bdaddr.b[4], addrbuf.l2.l2_bdaddr.b[5], btohs(addrbuf.l2.l2_cid), btohs(addrbuf.hci.hci_dev)); break; #endif /* AF_BLUETOOTH && HAVE_BLUETOOTH_BLUETOOTH_H */ /* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5 AF_X25 AF_ROSE etc. still need to be done */ default: tprints("sa_data="); print_quoted_string(addrbuf.sa.sa_data, sizeof(addrbuf.sa.sa_data), 0); break; } tprints("}"); }
static int decode_select(struct tcb *tcp, long *args, void (*print_tv_ts) (struct tcb *, const long), const char * (*sprint_tv_ts) (struct tcb *, const long)) { int i, j; int nfds, fdsize; fd_set *fds = NULL; const char *sep; long arg; /* Kernel truncates arg[0] to int, we do the same. */ nfds = (int) args[0]; /* Kernel rejects negative nfds, so we don't parse it either. */ if (nfds < 0) nfds = 0; /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ if (nfds > 1024*1024) nfds = 1024*1024; /* * We had bugs a-la "while (j < args[0])" and "umoven(args[0])" below. * Instead of args[0], use nfds for fd count, fdsize for array lengths. */ fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; if (entering(tcp)) { tprintf("%d", (int) args[0]); if (verbose(tcp) && fdsize > 0) fds = malloc(fdsize); for (i = 0; i < 3; i++) { arg = args[i+1]; tprints(", "); if (!fds) { printaddr(arg); continue; } if (umoven_or_printaddr(tcp, arg, fdsize, fds)) continue; tprints("["); for (j = 0, sep = "";; j++) { j = next_set_bit(fds, j, nfds); if (j < 0) break; tprints(sep); printfd(tcp, j); sep = " "; } tprints("]"); } free(fds); tprints(", "); print_tv_ts(tcp, args[4]); } else { static char outstr[1024]; char *outptr; #define end_outstr (outstr + sizeof(outstr)) int ready_fds; if (syserror(tcp)) return 0; ready_fds = tcp->u_rval; if (ready_fds == 0) { tcp->auxstr = "Timeout"; return RVAL_STR; } fds = malloc(fdsize); outptr = outstr; sep = ""; for (i = 0; i < 3 && ready_fds > 0; i++) { int first = 1; arg = args[i+1]; if (!arg || !fds || umoven(tcp, arg, fdsize, fds) < 0) continue; for (j = 0;; j++) { j = next_set_bit(fds, j, nfds); if (j < 0) break; /* +2 chars needed at the end: ']',NUL */ if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) { if (first) { outptr += sprintf(outptr, "%s%s [%u", sep, i == 0 ? "in" : i == 1 ? "out" : "except", j ); first = 0; sep = ", "; } else { outptr += sprintf(outptr, " %u", j); } } if (--ready_fds == 0) break; } if (outptr != outstr) *outptr++ = ']'; } free(fds); /* This contains no useful information on SunOS. */ if (args[4]) { const char *str = sprint_tv_ts(tcp, args[4]); if (outptr + sizeof("left ") + strlen(sep) + strlen(str) < end_outstr) { outptr += sprintf(outptr, "%sleft %s", sep, str); } } *outptr = '\0'; tcp->auxstr = outstr; return RVAL_STR; #undef end_outstr } return 0; }