2003-06-03 Roland McGrath <roland@redhat.com>

Linux/ARM improvements from Russell King <rmk@arm.linux.org.uk>:
	* defs.h [LINUX] (TCB_WAITEXECVE): Define for [ARM] too.
	* process.c (struct_user_offsets) [LINUX] [ARM]: Add ARM registers.
	* signal.c [LINUX] (sys_sigreturn) [ARM]: New case.
	* syscall.c (get_scno, syscall_fixup) [LINUX] [ARM]: Case rewritten.
	(get_error) [LINUX] [ARM]: Update.
	(syscall_enter) [LINUX] [ARM]: New case.
	* util.c (printcall) [LINUX] [ARM]: New case.
This commit is contained in:
Roland McGrath 2003-06-03 23:29:04 +00:00
parent ef38868961
commit 0f87c4972f
4 changed files with 181 additions and 82 deletions

2
defs.h
View File

@ -318,7 +318,7 @@ struct tcb {
#define TCB_FOLLOWFORK 00400 /* Process should have forks followed */
#define TCB_REPRINT 01000 /* We should reprint this syscall on exit */
#ifdef LINUX
# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SHMEDIA) || defined(S390) || defined(S390X)
# if defined(ALPHA) || defined(SPARC) || defined(POWERPC) || defined(IA64) || defined(HPPA) || defined(SH) || defined(SHMEDIA) || defined(S390) || defined(S390X) || defined(ARM)
# define TCB_WAITEXECVE 02000 /* ignore SIGTRAP after exceve */
# endif
# define TCB_CLONE_DETACHED 04000 /* CLONE_DETACHED set in creating syscall */

View File

@ -2626,6 +2626,25 @@ struct xlat struct_user_offsets[] = {
{ uoff(regs), "offsetof(struct user, regs)" },
{ uoff(fpu), "offsetof(struct user, fpu)" },
#endif
#ifdef ARM
{ uoff(regs.ARM_r0), "r0" },
{ uoff(regs.ARM_r1), "r1" },
{ uoff(regs.ARM_r2), "r2" },
{ uoff(regs.ARM_r3), "r3" },
{ uoff(regs.ARM_r4), "r4" },
{ uoff(regs.ARM_r5), "r5" },
{ uoff(regs.ARM_r6), "r6" },
{ uoff(regs.ARM_r7), "r7" },
{ uoff(regs.ARM_r8), "r8" },
{ uoff(regs.ARM_r9), "r9" },
{ uoff(regs.ARM_r10), "r10" },
{ uoff(regs.ARM_fp), "fp" },
{ uoff(regs.ARM_ip), "ip" },
{ uoff(regs.ARM_sp), "sp" },
{ uoff(regs.ARM_lr), "lr" },
{ uoff(regs.ARM_pc), "pc" },
{ uoff(regs.ARM_cpsr), "cpsr" },
#endif
#if !defined(S390) && !defined(S390X) && !defined(MIPS)
{ uoff(u_fpvalid), "offsetof(struct user, u_fpvalid)" },

153
signal.c
View File

@ -1183,26 +1183,51 @@ int
sys_sigreturn(tcp)
struct tcb *tcp;
{
#if defined(S390) || defined(S390X)
long usp;
struct sigcontext_struct sc;
#ifdef ARM
struct pt_regs regs;
struct sigcontext_struct sc;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (upeek(tcp->pid,PT_GPR15,&usp)<0)
return 0;
if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
memcpy(&tcp->u_arg[1],&sc.oldmask[0],sizeof(sigset_t));
} else {
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ",(sigset_t *)&tcp->u_arg[1],0);
return RVAL_NONE | RVAL_STR;
}
return 0;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
return 0;
if (umove(tcp, regs.ARM_sp, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.oldmask;
} else {
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
return 0;
#elif defined(S390) || defined(S390X)
long usp;
struct sigcontext_struct sc;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (upeek(tcp->pid,PT_GPR15,&usp)<0)
return 0;
if (umove(tcp, usp+__SIGNAL_FRAMESIZE, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
memcpy(&tcp->u_arg[1],&sc.oldmask[0],sizeof(sigset_t));
} else {
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ",(sigset_t *)&tcp->u_arg[1],0);
return RVAL_NONE | RVAL_STR;
}
return 0;
#else
#ifdef I386
long esp;
@ -1256,50 +1281,50 @@ struct tcb *tcp;
return 0;
#else /* !IA64 */
#ifdef POWERPC
long esp;
struct sigcontext_struct sc;
long esp;
struct sigcontext_struct sc;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (upeek(tcp->pid, sizeof(unsigned long)*PT_R1, &esp) < 0)
return 0;
if (umove(tcp, esp, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.oldmask;
}
else {
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
return 0;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (upeek(tcp->pid, sizeof(unsigned long)*PT_R1, &esp) < 0)
return 0;
if (umove(tcp, esp, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.oldmask;
}
else {
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
return 0;
#else /* !POWERPC */
#ifdef M68K
long usp;
struct sigcontext sc;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (upeek(tcp->pid, 4*PT_USP, &usp) < 0)
tcp->u_arg[0] = 0;
if (upeek(tcp->pid, 4*PT_USP, &usp) < 0)
return 0;
if (umove(tcp, usp, &sc) < 0)
if (umove(tcp, usp, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.sc_mask;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.sc_mask;
}
else {
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
return 0;
#else /* !M68K */
@ -1308,22 +1333,22 @@ struct tcb *tcp;
struct sigcontext_struct sc;
if (entering(tcp)) {
tcp->u_arg[0] = 0;
if (upeek(tcp->pid, REG_FP, &fp) < 0)
tcp->u_arg[0] = 0;
if (upeek(tcp->pid, REG_FP, &fp) < 0)
return 0;
if (umove(tcp, fp, &sc) < 0)
if (umove(tcp, fp, &sc) < 0)
return 0;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.sc_mask;
tcp->u_arg[0] = 1;
tcp->u_arg[1] = sc.sc_mask;
}
else {
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
sigset_t sigm;
long_to_sigset(tcp->u_arg[1], &sigm);
tcp->u_rval = tcp->u_error = 0;
if (tcp->u_arg[0] == 0)
return 0;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
tcp->auxstr = sprintsigmask("mask now ", &sigm, 0);
return RVAL_NONE | RVAL_STR;
}
return 0;
#else
@ -1333,8 +1358,8 @@ struct tcb *tcp;
m_siginfo_t si;
if(ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0) {
perror("sigreturn: PTRACE_GETREGS ");
return 0;
perror("sigreturn: PTRACE_GETREGS ");
return 0;
}
if(entering(tcp)) {
tcp->u_arg[0] = 0;

View File

@ -695,7 +695,7 @@ struct tcb *tcp;
#elif defined (M68K)
static int d0;
#elif defined (ARM)
static int r0;
static struct pt_regs regs;
#elif defined (ALPHA)
static long r0;
static long a3;
@ -714,7 +714,7 @@ struct tcb *tcp;
#elif defined(SH)
static long r0;
#elif defined(SHMEDIA)
static long r9;
static long r9;
#elif defined(X86_64)
static long rax;
#endif
@ -939,11 +939,59 @@ struct tcb *tcp;
return -1;
}
#elif defined (ARM)
{
long pc;
upeek(pid, 4*15, &pc);
umoven(tcp, pc-4, 4, (char *)&scno);
scno &= 0x000fffff;
/*
* Read complete register set in one go.
*/
if (ptrace(PTRACE_GETREGS, pid, NULL, (void *)&regs) == -1)
return -1;
/*
* We only need to grab the syscall number on syscall entry.
*/
if (regs.ARM_ip == 0) {
/*
* Note: we only deal with only 32-bit CPUs here.
*/
if (regs.ARM_cpsr & 0x20) {
/*
* Get the Thumb-mode system call number
*/
scno = regs.ARM_r7;
} else {
/*
* Get the ARM-mode system call number
*/
errno = 0;
scno = ptrace(PTRACE_PEEKTEXT, pid, (void *)(regs.ARM_pc - 4), NULL);
if (errno)
return -1;
if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
tcp->flags &= ~TCB_WAITEXECVE;
return 0;
}
if ((scno & 0x0ff00000) != 0x0f900000) {
fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
scno);
return -1;
}
/*
* Fixup the syscall number
*/
scno &= 0x000fffff;
}
if (tcp->flags & TCB_INSYSCALL) {
fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
tcp->flags &= ~TCB_INSYSCALL;
}
} else {
if (!(tcp->flags & TCB_INSYSCALL)) {
fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
tcp->flags |= TCB_INSYSCALL;
}
}
#elif defined (M68K)
if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
@ -1272,13 +1320,9 @@ struct tcb *tcp;
return 0;
}
#elif defined (ARM)
if (upeek(pid, 4*0, (long *)&r0) < 0)
return -1;
if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
if (debug)
fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0);
return 0;
}
/*
* Nothing required
*/
#elif defined (HPPA)
if (upeek(pid, PT_GR28, &r28) < 0)
return -1;
@ -1386,12 +1430,12 @@ struct tcb *tcp;
}
#else /* !M68K */
#ifdef ARM
if (r0 && (unsigned) -r0 < nerrnos) {
if (regs.ARM_r0 && (unsigned) -regs.ARM_r0 < nerrnos) {
tcp->u_rval = -1;
u_error = -r0;
u_error = -regs.ARM_r0;
}
else {
tcp->u_rval = r0;
tcp->u_rval = regs.ARM_r0;
u_error = 0;
}
#else /* !ARM */
@ -1864,6 +1908,17 @@ struct tcb *tcp;
return -1;
}
}
#elif defined(ARM)
{
int i;
if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
tcp->u_nargs = sysent[tcp->scno].nargs;
else
tcp->u_nargs = MAX_ARGS;
for (i = 0; i < tcp->u_nargs; i++)
tcp->u_arg[i] = regs.uregs[i];
}
#elif defined(SH)
{
int i;