/*
 * PTRACE_GETREGS was added to the PowerPC kernel in v2.6.23,
 * we provide a slow fallback for old kernels.
 */
static int
getregs_old(pid_t pid)
{
	int i;
	long r;

	if (iflag) {
		r = upeek(pid, sizeof(long) * PT_NIP, (long *)&ppc_regs.nip);
		if (r)
			goto out;
	}
#ifdef POWERPC64 /* else we never use it */
	r = upeek(pid, sizeof(long) * PT_MSR, (long *)&ppc_regs.msr);
	if (r)
		goto out;
#endif
	r = upeek(pid, sizeof(long) * PT_CCR, (long *)&ppc_regs.ccr);
	if (r)
		goto out;
	r = upeek(pid, sizeof(long) * PT_ORIG_R3, (long *)&ppc_regs.orig_gpr3);
	if (r)
		goto out;
	for (i = 0; i <= 8; i++) {
		r = upeek(pid, sizeof(long) * (PT_R0 + i),
			  (long *)&ppc_regs.gpr[i]);
		if (r)
			goto out;
	}
 out:
	return r;
}
/* Return codes: 1 - ok, 0 - ignore, other - error. */
static int
arch_get_scno(struct tcb *tcp)
{
	long scno = 0;

	/*
	 * In the new syscall ABI, the system call number is in R3.
	 */
	if (upeek(tcp->pid, 4*(REG_REG0+3), &scno) < 0)
		return -1;

	if (scno < 0) {
		/* Odd as it may seem, a glibc bug has been known to cause
		   glibc to issue bogus negative syscall numbers.  So for
		   our purposes, make strace print what it *should* have been */
		long correct_scno = (scno & 0xff);
		if (debug_flag)
			error_msg("Detected glibc bug: bogus system call"
				  " number = %ld, correcting to %ld",
				  scno, correct_scno);
		scno = correct_scno;
	}

	tcp->scno = scno;
	return 1;
}
/* Return -1 on error or 1 on success (never 0!). */
static int
get_syscall_args(struct tcb *tcp)
{
	unsigned int i;

	for (i = 0; i < tcp->s_ent->nargs; ++i)
		if (upeek(tcp->pid, (5 + i) * 4, &tcp->u_arg[i]) < 0)
			return -1;
	return 1;
}
/* Return -1 on error or 1 on success (never 0!). */
static int
get_syscall_args(struct tcb *tcp)
{
	/* Registers used by SH5 Linux system calls for parameters */
	static const int syscall_regs[MAX_ARGS] = { 2, 3, 4, 5, 6, 7 };
	unsigned int i;

	for (i = 0; i < tcp->s_ent->nargs; ++i)
		if (upeek(tcp->pid, REG_GENERAL(syscall_regs[i]),
			  &tcp->u_arg[i]) < 0)
			return -1;
	return 1;
}
Esempio n. 5
0
/* Return -1 on error or 1 on success (never 0!). */
static int
get_syscall_args(struct tcb *tcp)
{
	static const int argreg[MAX_ARGS] = {
		PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5
	};
	unsigned int i;

	for (i = 0; i < tcp->s_ent->nargs; ++i)
		if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
			return -1;
	return 1;
}
/* Return -1 on error or 1 on success (never 0!). */
static int
get_syscall_args(struct tcb *tcp)
{
	static const int crisregs[MAX_ARGS] = {
		4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
		4*PT_R13     , 4*PT_MOF, 4*PT_SRP
	};
	unsigned int i;

	for (i = 0; i < tcp->s_ent->nargs; ++i)
		if (upeek(tcp->pid, crisregs[i], &tcp->u_arg[i]) < 0)
			return -1;
	return 1;
}
Esempio n. 7
0
static int
get_syscall_result_regs(struct tcb *tcp)
{
	return (upeek(tcp, REG_A3, &alpha_a3) < 0 ||
		upeek(tcp, REG_R0, &alpha_r0) < 0) ? -1 : 0;
}
Esempio n. 8
0
int
sys_sigreturn(struct tcb *tcp)
{
#if defined(ARM)
	if (entering(tcp)) {
		struct sigcontext_struct sc;
		sigset_t sigm;
		if (umove(tcp, arm_regs.ARM_sp, &sc) < 0)
			return 0;
		long_to_sigset(sc.oldmask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(S390) || defined(S390X)
	if (entering(tcp)) {
		long usp;
		struct sigcontext_struct sc;
		if (upeek(tcp, PT_GPR15, &usp) < 0)
			return 0;
		if (umove(tcp, usp + __SIGNAL_FRAMESIZE, &sc) < 0)
			return 0;
		tprints(sprintsigmask(") (mask ", (sigset_t *)&sc.oldmask[0], 0));
	}
#elif defined(I386)
	if (entering(tcp)) {
		struct sigcontext_struct sc;
		/* Note: on i386, sc is followed on stack by struct fpstate
		 * and after it an additional u32 extramask[1] which holds
		 * upper half of the mask. We can fetch it there
		 * if/when we'd want to display the full mask...
		 */
		sigset_t sigm;
		if (umove(tcp, i386_regs.esp, &sc) < 0)
			return 0;
		long_to_sigset(sc.oldmask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(IA64)
	if (entering(tcp)) {
		struct sigcontext sc;
		long sp;
		sigset_t sigm;
		/* offset of sigcontext in the kernel's sigframe structure: */
#		define SIGFRAME_SC_OFFSET	0x90
		if (upeek(tcp, PT_R12, &sp) < 0)
			return 0;
		if (umove(tcp, sp + 16 + SIGFRAME_SC_OFFSET, &sc) < 0)
			return 0;
		sigemptyset(&sigm);
		memcpy(&sigm, &sc.sc_mask, NSIG / 8);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(POWERPC)
	if (entering(tcp)) {
		long esp;
		struct sigcontext_struct sc;
		sigset_t sigm;
		if (upeek(tcp, sizeof(unsigned long) * PT_R1, &esp) < 0)
			return 0;
		/* Skip dummy stack frame. */
#ifdef POWERPC64
		if (current_personality == 0)
			esp += 128;
		else
			esp += 64;
#else
		esp += 64;
#endif
		if (umove(tcp, esp, &sc) < 0)
			return 0;
		long_to_sigset(sc.oldmask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(M68K)
	if (entering(tcp)) {
		long usp;
		struct sigcontext sc;
		sigset_t sigm;
		if (upeek(tcp, 4*PT_USP, &usp) < 0)
			return 0;
		if (umove(tcp, usp, &sc) < 0)
			return 0;
		long_to_sigset(sc.sc_mask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(ALPHA)
	if (entering(tcp)) {
		long fp;
		struct sigcontext_struct sc;
		sigset_t sigm;
		if (upeek(tcp, REG_FP, &fp) < 0)
			return 0;
		if (umove(tcp, fp, &sc) < 0)
			return 0;
		long_to_sigset(sc.sc_mask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(SPARC) || defined(SPARC64)
	if (entering(tcp)) {
		long i1;
		m_siginfo_t si;
		sigset_t sigm;
		i1 = sparc_regs.u_regs[U_REG_O1];
		if (umove(tcp, i1, &si) < 0) {
			perror_msg("%s", "sigreturn: umove");
			return 0;
		}
		long_to_sigset(si.si_mask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
	/* This decodes rt_sigreturn.  The 64-bit ABIs do not have
	   sigreturn.  */
	if (entering(tcp)) {
		long sp;
		struct ucontext uc;
		sigset_t sigm;
		if (upeek(tcp, REG_SP, &sp) < 0)
			return 0;
		/* There are six words followed by a 128-byte siginfo.  */
		sp = sp + 6 * 4 + 128;
		if (umove(tcp, sp, &uc) < 0)
			return 0;
		long_to_sigset(*(long *) &uc.uc_sigmask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(MIPS)
	if (entering(tcp)) {
		long sp;
		struct pt_regs regs;
		m_siginfo_t si;
		sigset_t sigm;
		if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
			perror_msg("%s", "sigreturn: PTRACE_GETREGS");
			return 0;
		}
		sp = regs.regs[29];
		if (umove(tcp, sp, &si) < 0)
			return 0;
		long_to_sigset(si.si_mask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(CRISV10) || defined(CRISV32)
	if (entering(tcp)) {
		struct sigcontext sc;
		long regs[PT_MAX+1];
		sigset_t sigm;
		if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) {
			perror_msg("%s", "sigreturn: PTRACE_GETREGS");
			return 0;
		}
		if (umove(tcp, regs[PT_USP], &sc) < 0)
			return 0;
		long_to_sigset(sc.oldmask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(TILE)
	if (entering(tcp)) {
		struct ucontext uc;
		sigset_t sigm;

		/* offset of ucontext in the kernel's sigframe structure */
#		define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(struct siginfo)
		if (umove(tcp, tile_regs.sp + SIGFRAME_UC_OFFSET, &uc) < 0)
			return 0;
		sigemptyset(&sigm);
		memcpy(&sigm, &uc.uc_sigmask, NSIG / 8);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(MICROBLAZE)
	/* TODO: Verify that this is correct...  */
	if (entering(tcp)) {
		struct sigcontext sc;
		long sp;
		sigset_t sigm;
		/* Read r1, the stack pointer.  */
		if (upeek(tcp, 1 * 4, &sp) < 0)
			return 0;
		if (umove(tcp, sp, &sc) < 0)
			return 0;
		long_to_sigset(sc.oldmask, &sigm);
		tprints(sprintsigmask(") (mask ", &sigm, 0));
	}
#elif defined(X86_64)
	/* no need to remind */
#else
# warning No sys_sigreturn() for this architecture
# warning         (no problem, just a reminder :-)
#endif
	return 0;
}
Esempio n. 9
0
int
sys_sigreturn(struct tcb *tcp)
{
#if defined(ARM)
	if (entering(tcp)) {
		struct arm_sigcontext {
			unsigned long trap_no;
			unsigned long error_code;
			unsigned long oldmask;
			unsigned long arm_r0;
			unsigned long arm_r1;
			unsigned long arm_r2;
			unsigned long arm_r3;
			unsigned long arm_r4;
			unsigned long arm_r5;
			unsigned long arm_r6;
			unsigned long arm_r7;
			unsigned long arm_r8;
			unsigned long arm_r9;
			unsigned long arm_r10;
			unsigned long arm_fp;
			unsigned long arm_ip;
			unsigned long arm_sp;
			unsigned long arm_lr;
			unsigned long arm_pc;
			unsigned long arm_cpsr;
			unsigned long fault_address;
		};
		struct arm_ucontext {
			unsigned long uc_flags;
			unsigned long uc_link;  /* struct ucontext* */
			/* The next three members comprise stack_t struct: */
			unsigned long ss_sp;    /* void*   */
			unsigned long ss_flags; /* int     */
			unsigned long ss_size;  /* size_t  */
			struct arm_sigcontext sc;
			/* These two members are sigset_t: */
			unsigned long uc_sigmask[2];
			/* more fields follow, which we aren't interested in */
		};
		struct arm_ucontext uc;
		if (umove(tcp, arm_regs.ARM_sp, &uc) < 0)
			return 0;
		/*
		 * Kernel fills out uc.sc.oldmask too when it sets up signal stack,
		 * but for sigmask restore, sigreturn syscall uses uc.uc_sigmask instead.
		 */
		tprintsigmask_addr(") (mask ", uc.uc_sigmask);
	}
#elif defined(S390) || defined(S390X)
	if (entering(tcp)) {
		long usp;
		struct sigcontext sc;
		if (upeek(tcp->pid, PT_GPR15, &usp) < 0)
			return 0;
		if (umove(tcp, usp + __SIGNAL_FRAMESIZE, &sc) < 0)
			return 0;
		tprintsigmask_addr(") (mask ", sc.oldmask);
	}
#elif defined(I386) || defined(X86_64)
# if defined(X86_64)
	if (current_personality == 0) /* 64-bit */
		return 0;
# endif
	if (entering(tcp)) {
		struct i386_sigcontext_struct {
			uint16_t gs, __gsh;
			uint16_t fs, __fsh;
			uint16_t es, __esh;
			uint16_t ds, __dsh;
			uint32_t edi;
			uint32_t esi;
			uint32_t ebp;
			uint32_t esp;
			uint32_t ebx;
			uint32_t edx;
			uint32_t ecx;
			uint32_t eax;
			uint32_t trapno;
			uint32_t err;
			uint32_t eip;
			uint16_t cs, __csh;
			uint32_t eflags;
			uint32_t esp_at_signal;
			uint16_t ss, __ssh;
			uint32_t i387;
			uint32_t oldmask;
			uint32_t cr2;
		};
		struct i386_fpstate {
			uint32_t cw;
			uint32_t sw;
			uint32_t tag;
			uint32_t ipoff;
			uint32_t cssel;
			uint32_t dataoff;
			uint32_t datasel;
			uint8_t  st[8][10]; /* 8*10 bytes: FP regs */
			uint16_t status;
			uint16_t magic;
			uint32_t fxsr_env[6];
			uint32_t mxcsr;
			uint32_t reserved;
			uint8_t  stx[8][16]; /* 8*16 bytes: FP regs, each padded to 16 bytes */
			uint8_t  xmm[8][16]; /* 8 XMM regs */
			uint32_t padding1[44];
			uint32_t padding2[12]; /* union with struct _fpx_sw_bytes */
		};
		struct {
			struct i386_sigcontext_struct sc;
			struct i386_fpstate fp;
			uint32_t extramask[1];
		} signal_stack;
		/* On i386, sc is followed on stack by struct fpstate
		 * and after it an additional u32 extramask[1] which holds
		 * upper half of the mask.
		 */
		uint32_t sigmask[2];
		if (umove(tcp, *i386_esp_ptr, &signal_stack) < 0)
			return 0;
		sigmask[0] = signal_stack.sc.oldmask;
		sigmask[1] = signal_stack.extramask[0];
		tprintsigmask_addr(") (mask ", sigmask);
	}
#elif defined(IA64)
	if (entering(tcp)) {
		struct sigcontext sc;
		long sp;
		/* offset of sigcontext in the kernel's sigframe structure: */
#		define SIGFRAME_SC_OFFSET	0x90
		if (upeek(tcp->pid, PT_R12, &sp) < 0)
			return 0;
		if (umove(tcp, sp + 16 + SIGFRAME_SC_OFFSET, &sc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", sc.sc_mask);
	}
#elif defined(POWERPC)
	if (entering(tcp)) {
		long esp;
		struct sigcontext sc;

		esp = ppc_regs.gpr[1];

		/* Skip dummy stack frame. */
#ifdef POWERPC64
		if (current_personality == 0)
			esp += 128;
		else
			esp += 64;
#else
		esp += 64;
#endif
		if (umove(tcp, esp, &sc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", sc.oldmask);
	}
#elif defined(M68K)
	if (entering(tcp)) {
		long usp;
		struct sigcontext sc;
		if (upeek(tcp->pid, 4*PT_USP, &usp) < 0)
			return 0;
		if (umove(tcp, usp, &sc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", sc.sc_mask);
	}
#elif defined(ALPHA)
	if (entering(tcp)) {
		long fp;
		struct sigcontext sc;
		if (upeek(tcp->pid, REG_FP, &fp) < 0)
			return 0;
		if (umove(tcp, fp, &sc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", sc.sc_mask);
	}
#elif defined(SPARC) || defined(SPARC64)
	if (entering(tcp)) {
		long i1;
		m_siginfo_t si;
		i1 = sparc_regs.u_regs[U_REG_O1];
		if (umove(tcp, i1, &si) < 0) {
			perror_msg("sigreturn: umove");
			return 0;
		}
		tprintsigmask_val(") (mask ", si.si_mask);
	}
#elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
	/* This decodes rt_sigreturn.  The 64-bit ABIs do not have
	   sigreturn.  */
	if (entering(tcp)) {
		long sp;
		struct ucontext uc;
		if (upeek(tcp->pid, REG_SP, &sp) < 0)
			return 0;
		/* There are six words followed by a 128-byte siginfo.  */
		sp = sp + 6 * 4 + 128;
		if (umove(tcp, sp, &uc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", uc.uc_sigmask);
	}
#elif defined(MIPS)
	if (entering(tcp)) {
		long sp;
		struct pt_regs regs;
		m_siginfo_t si;
		if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
			perror_msg("sigreturn: PTRACE_GETREGS");
			return 0;
		}
		sp = regs.regs[29];
		if (umove(tcp, sp, &si) < 0)
			return 0;
		tprintsigmask_val(") (mask ", si.si_mask);
	}
#elif defined(CRISV10) || defined(CRISV32)
	if (entering(tcp)) {
		struct sigcontext sc;
		long regs[PT_MAX+1];
		if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (long)regs) < 0) {
			perror_msg("sigreturn: PTRACE_GETREGS");
			return 0;
		}
		if (umove(tcp, regs[PT_USP], &sc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", sc.oldmask);
	}
#elif defined(TILE)
	if (entering(tcp)) {
		struct ucontext uc;

		/* offset of ucontext in the kernel's sigframe structure */
#		define SIGFRAME_UC_OFFSET C_ABI_SAVE_AREA_SIZE + sizeof(siginfo_t)
		if (umove(tcp, tile_regs.sp + SIGFRAME_UC_OFFSET, &uc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", uc.uc_sigmask);
	}
#elif defined(MICROBLAZE)
	/* TODO: Verify that this is correct...  */
	if (entering(tcp)) {
		struct sigcontext sc;
		long sp;
		/* Read r1, the stack pointer.  */
		if (upeek(tcp->pid, 1 * 4, &sp) < 0)
			return 0;
		if (umove(tcp, sp, &sc) < 0)
			return 0;
		tprintsigmask_val(") (mask ", sc.oldmask);
	}
#elif defined(XTENSA)
	/* Xtensa only has rt_sys_sigreturn */
#elif defined(ARC)
	/* ARC syscall ABI only supports rt_sys_sigreturn */
#else
# warning No sys_sigreturn() for this architecture
# warning         (no problem, just a reminder :-)
#endif
	return 0;
}
Esempio n. 10
0
static int
get_syscall_result_regs(struct tcb *tcp)
{
	/* ABI defines result returned in r9 */
	return upeek(tcp->pid, REG_GENERAL(9), &sh64_r9) < 0 ? -1 : 0;
}
static int
get_syscall_result_regs(struct tcb *tcp)
{
	return upeek(tcp->pid, PT_GR28, &hppa_r28) < 0 ? -1 : 0;
}
Esempio n. 12
0
/* Return codes: 1 - ok, 0 - ignore, other - error. */
static int
arch_get_scno(struct tcb *tcp)
{
	return upeek(tcp, 0, &tcp->scno) < 0 ? -1 : 1;
}