Beispiel #1
0
/*
 * Fetch 64bit argument at position arg_no and
 * return the index of the next argument.
 */
int
getllval(struct tcb *tcp, unsigned long long *val, int arg_no)
{
#if SIZEOF_KERNEL_LONG_T > 4
# ifndef current_klongsize
	if (current_klongsize < SIZEOF_KERNEL_LONG_T) {
#  if defined(AARCH64) || defined(POWERPC64)
		/* Align arg_no to the next even number. */
		arg_no = (arg_no + 1) & 0xe;
#  endif /* AARCH64 || POWERPC64 */
		*val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
		arg_no += 2;
	} else
# endif /* !current_klongsize */
	{
		*val = tcp->u_arg[arg_no];
		arg_no++;
	}
#else /* SIZEOF_KERNEL_LONG_T == 4 */
# if defined __ARM_EABI__	\
  || defined LINUX_MIPSO32	\
  || defined POWERPC		\
  || defined XTENSA
	/* Align arg_no to the next even number. */
	arg_no = (arg_no + 1) & 0xe;
# elif defined SH
	/*
	 * The SH4 ABI does allow long longs in odd-numbered registers, but
	 * does not allow them to be split between registers and memory - and
	 * there are only four argument registers for normal functions.  As a
	 * result, pread, for example, takes an extra padding argument before
	 * the offset.  This was changed late in the 2.4 series (around 2.4.20).
	 */
	if (arg_no == 3)
		arg_no++;
# endif /* __ARM_EABI__ || LINUX_MIPSO32 || POWERPC || XTENSA || SH */
	*val = ULONG_LONG(tcp->u_arg[arg_no], tcp->u_arg[arg_no + 1]);
	arg_no += 2;
#endif

	return arg_no;
}
Beispiel #2
0
static void
decode_new_sigaction(struct tcb *const tcp, const kernel_ulong_t addr)
{
	struct new_sigaction sa;

#ifndef current_wordsize
	if (current_wordsize < sizeof(sa.sa_handler__)) {
		struct new_sigaction32 sa32;

		if (umove_or_printaddr(tcp, addr, &sa32))
			return;

		memset(&sa, 0, sizeof(sa));
		sa.sa_handler__ = sa32.sa_handler__;
		sa.sa_flags     = sa32.sa_flags;
#if HAVE_SA_RESTORER && defined SA_RESTORER
		sa.sa_restorer  = sa32.sa_restorer;
#endif
		/* Kernel treats sa_mask as an array of longs.
		 * For 32-bit process, "long" is uint32_t, thus, for example,
		 * 32th bit in sa_mask will end up as bit 0 in sa_mask[1].
		 * But for (64-bit) kernel, 32th bit in sa_mask is
		 * 32th bit in 0th (64-bit) long!
		 * For little-endian, it's the same.
		 * For big-endian, we swap 32-bit words.
		 */
		sa.sa_mask[0] = ULONG_LONG(sa32.sa_mask[0], sa32.sa_mask[1]);
	} else
#endif
	if (umove_or_printaddr(tcp, addr, &sa))
		return;

	tprints("{sa_handler=");
	print_sa_handler(sa.sa_handler__);
	tprints(", sa_mask=");
	/*
	 * Sigset size is in tcp->u_arg[4] (SPARC)
	 * or in tcp->u_arg[3] (all other),
	 * but kernel won't handle sys_rt_sigaction
	 * with wrong sigset size (just returns EINVAL instead).
	 * We just fetch the right size, which is NSIG_BYTES.
	 */
	tprintsigmask_val("", sa.sa_mask);
	tprints(", sa_flags=");

	printflags(sigact_flags, sa.sa_flags, "SA_???");
#if HAVE_SA_RESTORER && defined SA_RESTORER
	if (sa.sa_flags & SA_RESTORER) {
		tprints(", sa_restorer=");
		printaddr(sa.sa_restorer);
	}
#endif
	tprints("}");
}