X-Git-Url: https://granicus.if.org/sourcecode?a=blobdiff_plain;f=syscall.c;h=50f3abee82cd23255ece5199f5ba0ccc745f1169;hb=ee36ce19e03e08f4b692570090ee58b72d2f0f50;hp=87f7a82920bef5da1fc8c09e0e0fb70b9bf76852;hpb=ce9f0740d3b6e9910f25712771961bdb4bb4eaa2;p=strace diff --git a/syscall.c b/syscall.c index 87f7a829..50f3abee 100644 --- a/syscall.c +++ b/syscall.c @@ -43,13 +43,13 @@ #include #if HAVE_ASM_REG_H -#ifdef SPARC +#if defined (SPARC) || defined (SPARC64) # define fpq kernel_fpq # define fq kernel_fq # define fpu kernel_fpu #endif #include -#ifdef SPARC +#if defined (SPARC) || defined (SPARC64) # undef fpq # undef fq # undef fpu @@ -74,6 +74,14 @@ # undef pt_all_user_regs #endif +#if defined (LINUX) && defined (SPARC64) +# define r_pc r_tpc +# undef PTRACE_GETREGS +# define PTRACE_GETREGS PTRACE_GETREGS64 +# undef PTRACE_SETREGS +# define PTRACE_SETREGS PTRACE_SETREGS64 +#endif /* LINUX && SPARC64 */ + #if defined(LINUX) && defined(IA64) # include # include @@ -116,26 +124,26 @@ #define TP TRACE_PROCESS #define TS TRACE_SIGNAL -struct sysent sysent0[] = { +static const struct sysent sysent0[] = { #include "syscallent.h" }; -int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0]; +static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0]; #if SUPPORTED_PERSONALITIES >= 2 -struct sysent sysent1[] = { +static const struct sysent sysent1[] = { #include "syscallent1.h" }; -int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0]; +static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0]; #endif /* SUPPORTED_PERSONALITIES >= 2 */ #if SUPPORTED_PERSONALITIES >= 3 -struct sysent sysent2[] = { +static const struct sysent sysent2[] = { #include "syscallent2.h" }; -int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0]; +static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0]; #endif /* SUPPORTED_PERSONALITIES >= 3 */ -struct sysent *sysent; +const struct sysent *sysent; int nsyscalls; /* Now undef them since short defines cause wicked namespace pollution. */ @@ -145,26 +153,26 @@ int nsyscalls; #undef TP #undef TS -char *errnoent0[] = { +static const char *const errnoent0[] = { #include "errnoent.h" }; -int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0]; +static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0]; #if SUPPORTED_PERSONALITIES >= 2 -char *errnoent1[] = { +static const char *const errnoent1[] = { #include "errnoent1.h" }; -int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0]; +static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0]; #endif /* SUPPORTED_PERSONALITIES >= 2 */ #if SUPPORTED_PERSONALITIES >= 3 -char *errnoent2[] = { +static const char *const errnoent2[] = { #include "errnoent2.h" }; -int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0]; +static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0]; #endif /* SUPPORTED_PERSONALITIES >= 3 */ -char **errnoent; +const char *const *errnoent; int nerrnos; int current_personality; @@ -302,6 +310,8 @@ qual_signal(s, opt, not) qualify_one(atoi(s), opt, not); return 1; } + if (strlen(s) >= sizeof buf) + return 0; strcpy(buf, s); s = buf; for (i = 0; s[i]; i++) @@ -428,6 +438,12 @@ struct tcb *tcp; return; switch (tcp->scno + NR_SYSCALL_BASE) { case SYS_read: +#ifdef SYS_pread64 + case SYS_pread64: +#endif +#if defined SYS_pread && SYS_pread64 != SYS_pread + case SYS_pread: +#endif #ifdef SYS_recv case SYS_recv: #endif @@ -438,6 +454,12 @@ struct tcb *tcp; dumpstr(tcp, tcp->u_arg[1], tcp->u_rval); break; case SYS_write: +#ifdef SYS_pwrite64 + case SYS_pwrite64: +#endif +#if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite + case SYS_pwrite: +#endif #ifdef SYS_send case SYS_send: #endif @@ -676,8 +698,13 @@ struct tcb *tcp; #ifdef SYS_waitsys case SYS_waitsys: #endif - internal_wait(tcp); + internal_wait(tcp, 2); + break; +#ifdef SYS_waitid + case SYS_waitid: + internal_wait(tcp, 3); break; +#endif #ifdef SYS_exit case SYS_exit: @@ -713,7 +740,7 @@ struct tcb *tcp; #elif defined (ALPHA) static long r0; static long a3; -#elif defined (SPARC) +#elif defined (SPARC) || defined (SPARC64) static struct regs regs; static unsigned long trap; #elif defined(MIPS) @@ -1060,7 +1087,7 @@ struct tcb *tcp; if (upeek(pid, REG_R0, &r0) < 0) return -1; } -#elif defined (SPARC) +#elif defined (SPARC) || defined (SPARC64) /* Everything we need is in the current register set. */ if (ptrace(PTRACE_GETREGS,pid,(char *)®s,0) < 0) return -1; @@ -1070,6 +1097,9 @@ struct tcb *tcp; /* Retrieve the syscall trap instruction. */ errno = 0; trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0); +#if defined(SPARC64) + trap >>= 32; +#endif if (errno) return -1; @@ -1081,8 +1111,8 @@ struct tcb *tcp; break; case 0x91d0206d: /* Linux/SPARC64 syscall trap. */ - fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n"); - return -1; + set_personality(2); + break; case 0x91d02000: /* SunOS syscall trap. (pers 1) */ fprintf(stderr,"syscall: SunOS no support\n"); @@ -1105,7 +1135,11 @@ struct tcb *tcp; tcp->flags &= ~TCB_WAITEXECVE; return 0; } +#if defined (SPARC64) + fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.r_tpc); +#else fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc); +#endif return -1; } @@ -1294,6 +1328,8 @@ struct tcb *tcp; #elif defined (X86_64) if (upeek(pid, 8*RAX, &rax) < 0) return -1; + if (current_personality == 1) + rax = (long int)(int)rax; /* sign extend from 32 bits */ if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) { if (debug) fprintf(stderr, "stray syscall exit: rax = %ld\n", rax); @@ -1474,6 +1510,16 @@ struct tcb *tcp; u_error = 0; } #else /* !SPARC */ +#ifdef SPARC64 + if (regs.r_tstate & 0x1100000000UL) { + tcp->u_rval = -1; + u_error = regs.r_o0; + } + else { + tcp->u_rval = regs.r_o0; + u_error = 0; + } +#else /* !SPARC64 */ #ifdef HPPA if (r28 && (unsigned) -r28 < nerrnos) { tcp->u_rval = -1; @@ -1509,6 +1555,7 @@ struct tcb *tcp; #endif /* SH */ #endif /* HPPA */ #endif /* SPARC */ +#endif /* SPARC64 */ #endif /* ALPHA */ #endif /* ARM */ #endif /* M68K */ @@ -1613,7 +1660,7 @@ force_result(tcp, error, rval) #else /* !I386 */ #ifdef X86_64 rax = error ? -error : rval; - if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 4), rax) < 0) + if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0) return -1; #else #ifdef IA64 @@ -1701,6 +1748,20 @@ force_result(tcp, error, rval) if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) return -1; #else /* !SPARC */ +#ifdef SPARC64 + if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) + return -1; + if (error) { + regs.r_tstate |= 0x1100000000UL; + regs.r_o0 = error; + } + else { + regs.r_tstate &= ~0x1100000000UL; + regs.r_o0 = rval; + } + if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) + return -1; +#else /* !SPARC64 */ #ifdef HPPA r28 = error ? -error : rval; if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0) @@ -1719,6 +1780,7 @@ force_result(tcp, error, rval) #endif /* SH */ #endif /* HPPA */ #endif /* SPARC */ +#endif /* SPARC64 */ #endif /* ALPHA */ #endif /* ARM */ #endif /* M68K */ @@ -1897,7 +1959,7 @@ struct tcb *tcp; return -1; } } -#elif defined (SPARC) +#elif defined (SPARC) || defined (SPARC64) { int i; @@ -2281,7 +2343,7 @@ struct tcb *tcp; switch (tcp->scno + NR_SYSCALL_BASE) { #ifdef LINUX -#if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64) +#if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64) case SYS_socketcall: decode_subcall(tcp, SYS_socket_subcall, SYS_socket_nsubcalls, deref_style); @@ -2290,8 +2352,8 @@ struct tcb *tcp; decode_subcall(tcp, SYS_ipc_subcall, SYS_ipc_nsubcalls, shift_style); break; -#endif /* !ALPHA && !MIPS && !SPARC && !HPPA && !X86_64 */ -#ifdef SPARC +#endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA && !X86_64 */ +#if defined (SPARC) || defined (SPARC64) case SYS_socketcall: sparc_socket_decode (tcp); break; @@ -2431,7 +2493,7 @@ struct tcb *tcp; long val = -1; #ifdef LINUX -#ifdef SPARC +#if defined (SPARC) || defined (SPARC64) struct regs regs; if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) return -1; @@ -2439,7 +2501,7 @@ struct tcb *tcp; #elif defined(SH) if (upeek(tcp->pid, 4*(REG_REG0+1), &val) < 0) return -1; -#endif /* SPARC */ +#endif /* SPARC || SPARC64 */ #elif defined(IA64) if (upeek(tcp->pid, PT_R9, &val) < 0) return -1;