1999-02-19 03:21:36 +03:00
/*
* Copyright ( c ) 1991 , 1992 Paul Kranenburg < pk @ cs . few . eur . nl >
* Copyright ( c ) 1993 Branko Lankester < branko @ hacktic . nl >
* Copyright ( c ) 1993 , 1994 , 1995 , 1996 Rick Sladkey < jrs @ world . std . com >
1999-12-23 17:20:14 +03:00
* Copyright ( c ) 1996 - 1999 Wichert Akkerman < wichert @ cistron . nl >
* Copyright ( c ) 1999 IBM Deutschland Entwicklung GmbH , IBM Corporation
* Linux for s390 port by D . J . Barrow
* < barrow_dj @ mail . yahoo . com , djbarrow @ de . ibm . com >
1999-02-19 03:21:36 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* $ Id $
*/
# include "defs.h"
# include <signal.h>
# include <time.h>
# include <errno.h>
# include <sys/user.h>
# include <sys/syscall.h>
# include <sys/param.h>
1999-06-24 17:55:29 +04:00
1999-10-06 17:06:34 +04:00
# if HAVE_ASM_REG_H
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# if defined (SPARC) || defined (SPARC64)
2001-03-29 00:29:17 +04:00
# define fpq kernel_fpq
# define fq kernel_fq
# define fpu kernel_fpu
# endif
1999-08-30 03:15:07 +04:00
# include <asm/reg.h>
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# if defined (SPARC) || defined (SPARC64)
2001-03-29 00:29:17 +04:00
# undef fpq
# undef fq
2002-12-16 02:58:31 +03:00
# undef fpu
2001-03-29 00:29:17 +04:00
# endif
1999-08-30 03:15:07 +04:00
# endif
1999-07-14 02:20:16 +04:00
# ifdef HAVE_SYS_REG_H
# include <sys/reg.h>
1999-10-06 17:06:34 +04:00
# ifndef PTRACE_PEEKUSR
1999-07-14 02:20:16 +04:00
# define PTRACE_PEEKUSR PTRACE_PEEKUSER
1999-02-19 03:21:36 +03:00
# endif
2000-02-20 02:59:03 +03:00
# elif defined(HAVE_LINUX_PTRACE_H)
# undef PTRACE_SYSCALL
2004-03-02 00:29:22 +03:00
# ifdef HAVE_STRUCT_IA64_FPREG
# define ia64_fpreg XXX_ia64_fpreg
# endif
# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
# define pt_all_user_regs XXX_pt_all_user_regs
# endif
2000-02-20 02:59:03 +03:00
# include <linux/ptrace.h>
2004-03-02 00:29:22 +03:00
# undef ia64_fpreg
# undef pt_all_user_regs
1999-10-06 17:06:34 +04:00
# endif
1999-07-14 02:20:16 +04:00
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# 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 */
2000-02-04 00:58:30 +03:00
# if defined(LINUX) && defined(IA64)
# include <asm / ptrace_offsets.h>
# include <asm / rse.h>
# endif
2000-02-01 20:17:25 +03:00
# define NR_SYSCALL_BASE 0
1999-02-19 03:21:36 +03:00
# ifdef LINUX
# ifndef ERESTARTSYS
# define ERESTARTSYS 512
# endif
# ifndef ERESTARTNOINTR
# define ERESTARTNOINTR 513
# endif
# ifndef ERESTARTNOHAND
# define ERESTARTNOHAND 514 /* restart if no handler.. */
# endif
# ifndef ENOIOCTLCMD
# define ENOIOCTLCMD 515 /* No ioctl command */
# endif
2003-07-05 Richard Henderson <rth@twiddle.net>
* process.c (sys_clone): Order arguments for alpha the same as x86_64.
* syscall.c (ERESTART_RESTARTBLOCK): New.
(trace_syscall): Print it.
* linux/alpha/syscallent.h (osf_syscall): Name properly.
(osf_set_program_attributes): Fix typo.
(osf_nfssvc): Likewise.
(osf_sigsendset): Likewise.
(getdents64, gettid, readahead, tkill, setxattr, lsetxattr, fsetxattr,
getxattr, lgetxattr, fgetxattr, listxattr, llistxattr, flistxattr,
removexattr, lremovexattr, fremovexattr, futex, sched_setaffinity,
sched_getaffinity, tuxcall, io_setup, io_destroy, io_getevents,
io_submit, io_cancel, exit_group, lookup_dcookie, epoll_create,
epoll_ctl, epoll_wait, remap_file_pages, set_tid_address,
restart_syscall, fadvise, timer_create, timer_settime, timer_gettime,
timer_getoverrun, timer_delete, clock_settime, clock_gettime,
clock_getres, clock_nanosleep, semtimedop): New.
2003-07-09 13:47:59 +04:00
# ifndef ERESTART_RESTARTBLOCK
# define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */
# endif
1999-02-19 03:21:36 +03:00
# ifndef NSIG
# define NSIG 32
# endif
# ifdef ARM
# undef NSIG
# define NSIG 32
2000-02-01 20:17:25 +03:00
# undef NR_SYSCALL_BASE
# define NR_SYSCALL_BASE __NR_SYSCALL_BASE
1999-02-19 03:21:36 +03:00
# endif
# endif /* LINUX */
# include "syscall.h"
/* Define these shorthand notations to simplify the syscallent files. */
# define TF TRACE_FILE
# define TI TRACE_IPC
# define TN TRACE_NETWORK
# define TP TRACE_PROCESS
# define TS TRACE_SIGNAL
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const struct sysent sysent0 [ ] = {
1999-02-19 03:21:36 +03:00
# include "syscallent.h"
} ;
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0 [ 0 ] ;
1999-02-19 03:21:36 +03:00
# if SUPPORTED_PERSONALITIES >= 2
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const struct sysent sysent1 [ ] = {
1999-02-19 03:21:36 +03:00
# include "syscallent1.h"
} ;
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1 [ 0 ] ;
1999-02-19 03:21:36 +03:00
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const struct sysent sysent2 [ ] = {
1999-02-19 03:21:36 +03:00
# include "syscallent2.h"
} ;
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2 [ 0 ] ;
1999-02-19 03:21:36 +03:00
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
const struct sysent * sysent ;
1999-02-19 03:21:36 +03:00
int nsyscalls ;
/* Now undef them since short defines cause wicked namespace pollution. */
# undef TF
# undef TI
# undef TN
# undef TP
# undef TS
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const char * const errnoent0 [ ] = {
1999-02-19 03:21:36 +03:00
# include "errnoent.h"
} ;
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0 [ 0 ] ;
1999-02-19 03:21:36 +03:00
# if SUPPORTED_PERSONALITIES >= 2
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const char * const errnoent1 [ ] = {
1999-02-19 03:21:36 +03:00
# include "errnoent1.h"
} ;
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1 [ 0 ] ;
1999-02-19 03:21:36 +03:00
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const char * const errnoent2 [ ] = {
1999-02-19 03:21:36 +03:00
# include "errnoent2.h"
} ;
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2 [ 0 ] ;
1999-02-19 03:21:36 +03:00
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2004-09-03 Roland McGrath <roland@redhat.com>
* syscall.c (sysent0, sysent1, sysent2, sysent): Add const to defn.
(nsyscalls0, nsyscalls1, nsyscalls2): Likewise.
(errnoent0, errnoent1, errnoent2, errnoent): Likewise.
(nerrnos0, nerrnos1, nerrnos2): Likewise.
* signal.c (signalent0, signalent1, signalent2): Likewise.
(nsignals0, nsignals1, nsignals2): Likewise.
(signame): LIkewise.
* ioctl.c (ioctlent0, ioctlent1, ioctlent2): Likewise.
(nioctlents0, nioctlents1, nioctlents2): Likewise.
(ioctl_lookup, ioctl_next_match): Likewise.
* defs.h: Update decls.
* io.c (sys_ioctl): Update users.
2004-09-04 07:53:10 +04:00
const char * const * errnoent ;
1999-02-19 03:21:36 +03:00
int nerrnos ;
int current_personality ;
int
1999-06-22 19:28:30 +04:00
set_personality ( personality )
int personality ;
1999-02-19 03:21:36 +03:00
{
switch ( personality ) {
case 0 :
errnoent = errnoent0 ;
nerrnos = nerrnos0 ;
sysent = sysent0 ;
nsyscalls = nsyscalls0 ;
ioctlent = ioctlent0 ;
nioctlents = nioctlents0 ;
signalent = signalent0 ;
nsignals = nsignals0 ;
break ;
# if SUPPORTED_PERSONALITIES >= 2
case 1 :
errnoent = errnoent1 ;
nerrnos = nerrnos1 ;
sysent = sysent1 ;
nsyscalls = nsyscalls1 ;
ioctlent = ioctlent1 ;
nioctlents = nioctlents1 ;
signalent = signalent1 ;
nsignals = nsignals1 ;
break ;
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
case 2 :
errnoent = errnoent2 ;
nerrnos = nerrnos2 ;
sysent = sysent2 ;
nsyscalls = nsyscalls2 ;
ioctlent = ioctlent2 ;
nioctlents = nioctlents2 ;
signalent = signalent2 ;
nsignals = nsignals2 ;
break ;
# endif /* SUPPORTED_PERSONALITIES >= 3 */
default :
return - 1 ;
}
current_personality = personality ;
return 0 ;
}
int qual_flags [ MAX_QUALS ] ;
2004-09-04 08:20:43 +04:00
struct call_counts {
struct timeval time ;
int calls , errors ;
} ;
static struct call_counts * counts ;
1999-02-19 03:21:36 +03:00
static struct timeval shortest = { 1000000 , 0 } ;
2002-12-30 13:23:00 +03:00
static int qual_syscall ( ) , qual_signal ( ) , qual_fault ( ) , qual_desc ( ) ;
1999-02-19 03:21:36 +03:00
2004-09-04 08:20:43 +04:00
static const struct qual_options {
1999-02-19 03:21:36 +03:00
int bitflag ;
char * option_name ;
2002-12-30 13:23:00 +03:00
int ( * qualify ) ( ) ;
1999-02-19 03:21:36 +03:00
char * argument_name ;
} qual_options [ ] = {
2002-12-30 13:23:00 +03:00
{ QUAL_TRACE , " trace " , qual_syscall , " system call " } ,
{ QUAL_TRACE , " t " , qual_syscall , " system call " } ,
{ QUAL_ABBREV , " abbrev " , qual_syscall , " system call " } ,
{ QUAL_ABBREV , " a " , qual_syscall , " system call " } ,
{ QUAL_VERBOSE , " verbose " , qual_syscall , " system call " } ,
{ QUAL_VERBOSE , " v " , qual_syscall , " system call " } ,
{ QUAL_RAW , " raw " , qual_syscall , " system call " } ,
{ QUAL_RAW , " x " , qual_syscall , " system call " } ,
{ QUAL_SIGNAL , " signal " , qual_signal , " signal " } ,
{ QUAL_SIGNAL , " signals " , qual_signal , " signal " } ,
{ QUAL_SIGNAL , " s " , qual_signal , " signal " } ,
{ QUAL_FAULT , " fault " , qual_fault , " fault " } ,
{ QUAL_FAULT , " faults " , qual_fault , " fault " } ,
{ QUAL_FAULT , " m " , qual_fault , " fault " } ,
{ QUAL_READ , " read " , qual_desc , " descriptor " } ,
{ QUAL_READ , " reads " , qual_desc , " descriptor " } ,
{ QUAL_READ , " r " , qual_desc , " descriptor " } ,
{ QUAL_WRITE , " write " , qual_desc , " descriptor " } ,
{ QUAL_WRITE , " writes " , qual_desc , " descriptor " } ,
{ QUAL_WRITE , " w " , qual_desc , " descriptor " } ,
1999-02-19 03:21:36 +03:00
{ 0 , NULL , NULL , NULL } ,
} ;
2002-12-30 13:23:00 +03:00
static void
qualify_one ( n , opt , not )
int n ;
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
2002-12-30 13:23:00 +03:00
int not ;
{
if ( not )
qual_flags [ n ] & = ~ opt - > bitflag ;
else
qual_flags [ n ] | = opt - > bitflag ;
}
1999-02-19 03:21:36 +03:00
static int
2002-12-30 13:23:00 +03:00
qual_syscall ( s , opt , not )
char * s ;
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
2002-12-30 13:23:00 +03:00
int not ;
1999-02-19 03:21:36 +03:00
{
int i ;
2002-12-30 13:23:00 +03:00
int any = 0 ;
1999-02-19 03:21:36 +03:00
for ( i = 0 ; i < nsyscalls ; i + + ) {
2002-12-30 13:23:00 +03:00
if ( strcmp ( s , sysent [ i ] . sys_name ) = = 0 ) {
qualify_one ( i , opt , not ) ;
any = 1 ;
}
1999-02-19 03:21:36 +03:00
}
2002-12-30 13:23:00 +03:00
return ! any ;
1999-02-19 03:21:36 +03:00
}
static int
2002-12-30 13:23:00 +03:00
qual_signal ( s , opt , not )
char * s ;
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
2002-12-30 13:23:00 +03:00
int not ;
1999-02-19 03:21:36 +03:00
{
int i ;
char buf [ 32 ] ;
2002-12-30 13:23:00 +03:00
if ( s & & * s & & isdigit ( ( unsigned char ) * s ) ) {
qualify_one ( atoi ( s ) , opt , not ) ;
return 1 ;
}
2004-03-02 09:52:01 +03:00
if ( strlen ( s ) > = sizeof buf )
return 0 ;
1999-02-19 03:21:36 +03:00
strcpy ( buf , s ) ;
s = buf ;
for ( i = 0 ; s [ i ] ; i + + )
2000-02-18 18:36:12 +03:00
s [ i ] = toupper ( ( unsigned char ) ( s [ i ] ) ) ;
1999-02-19 03:21:36 +03:00
if ( strncmp ( s , " SIG " , 3 ) = = 0 )
s + = 3 ;
2002-12-30 13:23:00 +03:00
for ( i = 0 ; i < = NSIG ; i + + )
if ( strcmp ( s , signame ( i ) + 3 ) = = 0 ) {
qualify_one ( atoi ( s ) , opt , not ) ;
return 1 ;
}
return 0 ;
1999-02-19 03:21:36 +03:00
}
static int
2002-12-30 13:23:00 +03:00
qual_fault ( s , opt , not )
char * s ;
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
2002-12-30 13:23:00 +03:00
int not ;
1999-02-19 03:21:36 +03:00
{
return - 1 ;
}
static int
2002-12-30 13:23:00 +03:00
qual_desc ( s , opt , not )
char * s ;
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
2002-12-30 13:23:00 +03:00
int not ;
1999-02-19 03:21:36 +03:00
{
2002-12-30 13:23:00 +03:00
if ( s & & * s & & isdigit ( ( unsigned char ) * s ) ) {
qualify_one ( atoi ( s ) , opt , not ) ;
2003-04-10 22:58:20 +04:00
return 0 ;
2002-12-30 13:23:00 +03:00
}
1999-02-19 03:21:36 +03:00
return - 1 ;
}
static int
lookup_class ( s )
2002-12-30 13:23:00 +03:00
char * s ;
1999-02-19 03:21:36 +03:00
{
if ( strcmp ( s , " file " ) = = 0 )
return TRACE_FILE ;
if ( strcmp ( s , " ipc " ) = = 0 )
return TRACE_IPC ;
if ( strcmp ( s , " network " ) = = 0 )
return TRACE_NETWORK ;
if ( strcmp ( s , " process " ) = = 0 )
return TRACE_PROCESS ;
if ( strcmp ( s , " signal " ) = = 0 )
return TRACE_SIGNAL ;
return - 1 ;
}
void
qualify ( s )
char * s ;
{
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
1999-02-19 03:21:36 +03:00
int not ;
char * p ;
int i , n ;
opt = & qual_options [ 0 ] ;
for ( i = 0 ; ( p = qual_options [ i ] . option_name ) ; i + + ) {
n = strlen ( p ) ;
if ( strncmp ( s , p , n ) = = 0 & & s [ n ] = = ' = ' ) {
opt = & qual_options [ i ] ;
s + = n + 1 ;
break ;
}
}
not = 0 ;
if ( * s = = ' ! ' ) {
not = 1 ;
s + + ;
}
if ( strcmp ( s , " none " ) = = 0 ) {
not = 1 - not ;
s = " all " ;
}
if ( strcmp ( s , " all " ) = = 0 ) {
for ( i = 0 ; i < MAX_QUALS ; i + + ) {
if ( not )
qual_flags [ i ] & = ~ opt - > bitflag ;
else
qual_flags [ i ] | = opt - > bitflag ;
}
return ;
}
for ( i = 0 ; i < MAX_QUALS ; i + + ) {
if ( not )
qual_flags [ i ] | = opt - > bitflag ;
else
qual_flags [ i ] & = ~ opt - > bitflag ;
}
for ( p = strtok ( s , " , " ) ; p ; p = strtok ( NULL , " , " ) ) {
if ( opt - > bitflag = = QUAL_TRACE & & ( n = lookup_class ( p ) ) > 0 ) {
for ( i = 0 ; i < MAX_QUALS ; i + + ) {
if ( sysent [ i ] . sys_flags & n ) {
if ( not )
qual_flags [ i ] & = ~ opt - > bitflag ;
else
qual_flags [ i ] | = opt - > bitflag ;
}
}
continue ;
}
2002-12-30 13:23:00 +03:00
if ( opt - > qualify ( p , opt , not ) ) {
1999-02-19 03:21:36 +03:00
fprintf ( stderr , " strace: invalid %s `%s' \n " ,
opt - > argument_name , p ) ;
exit ( 1 ) ;
}
}
return ;
}
static void
dumpio ( tcp )
struct tcb * tcp ;
{
if ( syserror ( tcp ) )
return ;
if ( tcp - > u_arg [ 0 ] < 0 | | tcp - > u_arg [ 0 ] > = MAX_QUALS )
return ;
2000-02-01 20:17:25 +03:00
switch ( tcp - > scno + NR_SYSCALL_BASE ) {
1999-02-19 03:21:36 +03:00
case SYS_read :
2004-08-31 11:47:45 +04:00
# ifdef SYS_pread64
case SYS_pread64 :
# endif
# if defined SYS_pread && SYS_pread64 != SYS_pread
case SYS_pread :
# endif
1999-02-19 03:21:36 +03:00
# ifdef SYS_recv
case SYS_recv :
# endif
# ifdef SYS_recvfrom
case SYS_recvfrom :
# endif
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_READ )
dumpstr ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_rval ) ;
break ;
case SYS_write :
2004-08-31 11:47:45 +04:00
# ifdef SYS_pwrite64
case SYS_pwrite64 :
# endif
# if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
case SYS_pwrite :
# endif
1999-02-19 03:21:36 +03:00
# ifdef SYS_send
case SYS_send :
# endif
# ifdef SYS_sendto
case SYS_sendto :
# endif
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_WRITE )
dumpstr ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_arg [ 2 ] ) ;
break ;
2001-07-10 17:48:44 +04:00
# ifdef SYS_readv
case SYS_readv :
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_READ )
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
break ;
# endif
# ifdef SYS_writev
case SYS_writev :
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_WRITE )
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
break ;
# endif
1999-02-19 03:21:36 +03:00
}
}
2000-09-02 01:03:06 +04:00
# ifndef FREEBSD
1999-06-11 17:18:40 +04:00
enum subcall_style { shift_style , deref_style , mask_style , door_style } ;
2000-09-02 01:03:06 +04:00
# else /* FREEBSD */
enum subcall_style { shift_style , deref_style , mask_style , door_style , table_style } ;
struct subcall {
int call ;
int nsubcalls ;
int subcalls [ 5 ] ;
} ;
const struct subcall subcalls_table [ ] = {
{ SYS_shmsys , 5 , { SYS_shmat , SYS_shmctl , SYS_shmdt , SYS_shmget , SYS_shmctl } } ,
2001-03-06 18:51:53 +03:00
# ifdef SYS_semconfig
2000-09-02 01:03:06 +04:00
{ SYS_semsys , 4 , { SYS___semctl , SYS_semget , SYS_semop , SYS_semconfig } } ,
2001-03-06 18:51:53 +03:00
# else
{ SYS_semsys , 3 , { SYS___semctl , SYS_semget , SYS_semop } } ,
# endif
2000-09-02 01:03:06 +04:00
{ SYS_msgsys , 4 , { SYS_msgctl , SYS_msgget , SYS_msgsnd , SYS_msgrcv } } ,
} ;
# endif /* FREEBSD */
1999-02-19 03:21:36 +03:00
2001-10-10 03:47:38 +04:00
# if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) ))
1999-02-19 03:21:36 +03:00
const int socket_map [ ] = {
/* SYS_SOCKET */ 97 ,
/* SYS_BIND */ 104 ,
/* SYS_CONNECT */ 98 ,
/* SYS_LISTEN */ 106 ,
/* SYS_ACCEPT */ 99 ,
/* SYS_GETSOCKNAME */ 150 ,
/* SYS_GETPEERNAME */ 141 ,
/* SYS_SOCKETPAIR */ 135 ,
/* SYS_SEND */ 101 ,
/* SYS_RECV */ 102 ,
/* SYS_SENDTO */ 133 ,
/* SYS_RECVFROM */ 125 ,
/* SYS_SHUTDOWN */ 134 ,
/* SYS_SETSOCKOPT */ 105 ,
/* SYS_GETSOCKOPT */ 118 ,
/* SYS_SENDMSG */ 114 ,
/* SYS_RECVMSG */ 113
} ;
void
1999-06-22 19:28:30 +04:00
sparc_socket_decode ( tcp )
struct tcb * tcp ;
1999-02-19 03:21:36 +03:00
{
volatile long addr ;
volatile int i , n ;
if ( tcp - > u_arg [ 0 ] < 1 | | tcp - > u_arg [ 0 ] > sizeof ( socket_map ) / sizeof ( int ) + 1 ) {
return ;
}
tcp - > scno = socket_map [ tcp - > u_arg [ 0 ] - 1 ] ;
n = tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
addr = tcp - > u_arg [ 1 ] ;
for ( i = 0 ; i < n ; i + + ) {
int arg ;
if ( umoven ( tcp , addr , sizeof ( arg ) , ( void * ) & arg ) < 0 )
arg = 0 ;
tcp - > u_arg [ i ] = arg ;
addr + = sizeof ( arg ) ;
}
}
2002-09-23 19:41:01 +04:00
void
1999-02-19 03:21:36 +03:00
decode_subcall ( tcp , subcall , nsubcalls , style )
struct tcb * tcp ;
int subcall ;
int nsubcalls ;
enum subcall_style style ;
{
2002-10-07 18:31:00 +04:00
long addr , mask , arg ;
int i ;
2000-09-02 01:03:06 +04:00
1999-02-19 03:21:36 +03:00
switch ( style ) {
case shift_style :
2000-08-10 06:14:04 +04:00
if ( tcp - > u_arg [ 0 ] < 0 | | tcp - > u_arg [ 0 ] > = nsubcalls )
return ;
1999-02-19 03:21:36 +03:00
tcp - > scno = subcall + tcp - > u_arg [ 0 ] ;
if ( sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs - - ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
tcp - > u_arg [ i ] = tcp - > u_arg [ i + 1 ] ;
break ;
case deref_style :
2000-08-10 06:14:04 +04:00
if ( tcp - > u_arg [ 0 ] < 0 | | tcp - > u_arg [ 0 ] > = nsubcalls )
return ;
1999-02-19 03:21:36 +03:00
tcp - > scno = subcall + tcp - > u_arg [ 0 ] ;
addr = tcp - > u_arg [ 1 ] ;
for ( i = 0 ; i < sysent [ tcp - > scno ] . nargs ; i + + ) {
if ( umove ( tcp , addr , & arg ) < 0 )
arg = 0 ;
tcp - > u_arg [ i ] = arg ;
addr + = sizeof ( arg ) ;
}
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
break ;
case mask_style :
mask = ( tcp - > u_arg [ 0 ] > > 8 ) & 0xff ;
for ( i = 0 ; mask ; i + + )
mask > > = 1 ;
2000-08-10 06:14:04 +04:00
if ( i > = nsubcalls )
return ;
tcp - > u_arg [ 0 ] & = 0xff ;
1999-02-19 03:21:36 +03:00
tcp - > scno = subcall + i ;
if ( sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
break ;
1999-06-11 17:18:40 +04:00
case door_style :
/*
* Oh , yuck . The call code is the * sixth * argument .
2000-08-10 06:14:04 +04:00
* ( don ' t you mean the * last * argument ? - JH )
1999-06-11 17:18:40 +04:00
*/
2000-08-10 06:14:04 +04:00
if ( tcp - > u_arg [ 5 ] < 0 | | tcp - > u_arg [ 5 ] > = nsubcalls )
return ;
1999-06-11 17:18:40 +04:00
tcp - > scno = subcall + tcp - > u_arg [ 5 ] ;
if ( sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs - - ;
break ;
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
case table_style :
for ( i = 0 ; i < sizeof ( subcalls_table ) / sizeof ( struct subcall ) ; i + + )
if ( subcalls_table [ i ] . call = = tcp - > scno ) break ;
if ( i < sizeof ( subcalls_table ) / sizeof ( struct subcall ) & &
tcp - > u_arg [ 0 ] > = 0 & & tcp - > u_arg [ 0 ] < subcalls_table [ i ] . nsubcalls ) {
tcp - > scno = subcalls_table [ i ] . subcalls [ tcp - > u_arg [ 0 ] ] ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
tcp - > u_arg [ i ] = tcp - > u_arg [ i + 1 ] ;
}
break ;
# endif /* FREEBSD */
1999-02-19 03:21:36 +03:00
}
}
# endif
struct tcb * tcp_last = NULL ;
static int
internal_syscall ( tcp )
struct tcb * tcp ;
{
/*
* We must always trace a few critical system calls in order to
* correctly support following forks in the presence of tracing
* qualifiers .
*/
2000-02-01 20:17:25 +03:00
switch ( tcp - > scno + NR_SYSCALL_BASE ) {
1999-02-19 03:21:36 +03:00
# ifdef SYS_fork
case SYS_fork :
# endif
# ifdef SYS_vfork
case SYS_vfork :
2001-04-18 19:11:51 +04:00
# endif
# ifdef SYS_fork1
case SYS_fork1 :
# endif
# ifdef SYS_forkall
case SYS_forkall :
# endif
# ifdef SYS_rfork1
case SYS_rfork1 :
# endif
# ifdef SYS_rforkall
case SYS_rforkall :
2003-02-20 05:45:22 +03:00
# endif
# ifdef SYS_rfork
case SYS_rfork :
1999-02-19 03:21:36 +03:00
# endif
1999-12-23 18:08:17 +03:00
internal_fork ( tcp ) ;
break ;
1999-02-19 03:21:36 +03:00
# ifdef SYS_clone
case SYS_clone :
1999-12-23 18:08:17 +03:00
internal_clone ( tcp ) ;
1999-02-19 03:21:36 +03:00
break ;
1999-12-23 18:08:17 +03:00
# endif
2001-10-10 03:47:38 +04:00
# ifdef SYS_clone2
case SYS_clone2 :
internal_clone ( tcp ) ;
break ;
# endif
1999-02-19 03:21:36 +03:00
# ifdef SYS_execv
case SYS_execv :
# endif
# ifdef SYS_execve
case SYS_execve :
2001-04-18 19:11:51 +04:00
# endif
# ifdef SYS_rexecve
case SYS_rexecve :
1999-02-19 03:21:36 +03:00
# endif
internal_exec ( tcp ) ;
break ;
# ifdef SYS_wait
case SYS_wait :
# endif
# ifdef SYS_wait4
case SYS_wait4 :
# endif
2001-10-10 03:47:38 +04:00
# ifdef SYS32_wait4
case SYS32_wait4 :
# endif
1999-02-19 03:21:36 +03:00
# ifdef SYS_waitpid
case SYS_waitpid :
# endif
# ifdef SYS_waitsys
case SYS_waitsys :
# endif
2004-09-01 23:39:46 +04:00
internal_wait ( tcp , 2 ) ;
1999-02-19 03:21:36 +03:00
break ;
2004-09-01 23:39:46 +04:00
# ifdef SYS_waitid
case SYS_waitid :
internal_wait ( tcp , 3 ) ;
break ;
# endif
1999-02-19 03:21:36 +03:00
# ifdef SYS_exit
case SYS_exit :
2001-10-10 03:47:38 +04:00
# endif
# ifdef SYS32_exit
case SYS32_exit :
2003-01-09 09:53:27 +03:00
# endif
# ifdef __NR_exit_group
case __NR_exit_group :
2004-02-21 01:56:43 +03:00
# endif
# ifdef IA64
case 252 : /* IA-32 __NR_exit_group */
1999-02-19 03:21:36 +03:00
# endif
internal_exit ( tcp ) ;
break ;
}
return 0 ;
}
2000-04-11 02:22:31 +04:00
# ifdef LINUX
# if defined (I386)
static long eax ;
# elif defined (IA64)
long r8 , r10 , psr ;
long ia32 = 0 ;
# elif defined (POWERPC)
static long result , flags ;
# elif defined (M68K)
static int d0 ;
# elif defined (ARM)
2003-06-04 03:29:04 +04:00
static struct pt_regs regs ;
2000-04-11 02:22:31 +04:00
# elif defined (ALPHA)
static long r0 ;
static long a3 ;
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# elif defined (SPARC) || defined (SPARC64)
2001-03-29 00:29:17 +04:00
static struct regs regs ;
2000-04-11 02:22:31 +04:00
static unsigned long trap ;
# elif defined(MIPS)
static long a3 ;
static long r2 ;
2002-10-07 18:31:00 +04:00
# elif defined(S390) || defined(S390X)
2000-04-11 02:22:31 +04:00
static long gpr2 ;
static long pc ;
2002-11-11 15:50:47 +03:00
static long syscall_mode ;
2001-03-27 16:17:16 +04:00
# elif defined(HPPA)
static long r28 ;
2002-05-01 20:39:22 +04:00
# elif defined(SH)
static long r0 ;
2003-06-27 02:40:42 +04:00
# elif defined(SH64)
2003-06-04 03:29:04 +04:00
static long r9 ;
2002-09-23 19:41:01 +04:00
# elif defined(X86_64)
static long rax ;
2002-12-16 02:58:31 +03:00
# endif
2000-04-11 02:22:31 +04:00
# endif /* LINUX */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
struct reg regs ;
2002-12-16 02:58:31 +03:00
# endif /* FREEBSD */
2000-04-11 02:22:31 +04:00
1999-02-19 03:21:36 +03:00
int
2000-02-01 20:58:41 +03:00
get_scno ( tcp )
1999-02-19 03:21:36 +03:00
struct tcb * tcp ;
{
long scno = 0 ;
2000-09-02 01:03:06 +04:00
# ifndef USE_PROCFS
1999-02-19 03:21:36 +03:00
int pid = tcp - > pid ;
2002-12-16 02:58:31 +03:00
# endif /* !PROCFS */
1999-02-19 03:21:36 +03:00
# ifdef LINUX
2002-10-07 18:31:00 +04:00
# if defined(S390) || defined(S390X)
2003-01-20 13:23:04 +03:00
if ( tcp - > flags & TCB_WAITEXECVE ) {
/*
* When the execve system call completes successfully , the
* new process still has - ENOSYS ( old style ) or __NR_execve
* ( new style ) in gpr2 . We cannot recover the scno again
* by disassembly , because the image that executed the
* syscall is gone now . Fortunately , we don ' t want it . We
* leave the flag set so that syscall_fixup can fake the
* result .
*/
if ( tcp - > flags & TCB_INSYSCALL )
return 1 ;
/*
* This is the SIGTRAP after execve . We cannot try to read
* the system call here either .
*/
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
2003-06-27 02:23:28 +04:00
if ( upeek ( pid , PT_GPR2 , & syscall_mode ) < 0 )
return - 1 ;
if ( syscall_mode ! = - ENOSYS ) {
/*
* Since kernel version 2.5 .44 the scno gets passed in gpr2 .
*/
scno = syscall_mode ;
} else {
2002-11-11 15:50:47 +03:00
/*
* Old style of " passing " the scno via the SVC instruction .
*/
long opcode , offset_reg , tmp ;
void * svc_addr ;
int gpr_offset [ 16 ] = { PT_GPR0 , PT_GPR1 , PT_ORIGGPR2 , PT_GPR3 ,
PT_GPR4 , PT_GPR5 , PT_GPR6 , PT_GPR7 ,
PT_GPR8 , PT_GPR9 , PT_GPR10 , PT_GPR11 ,
PT_GPR12 , PT_GPR13 , PT_GPR14 , PT_GPR15 } ;
2002-12-16 02:58:31 +03:00
2002-11-11 15:50:47 +03:00
if ( upeek ( pid , PT_PSWADDR , & pc ) < 0 )
return - 1 ;
2003-01-20 13:23:04 +03:00
errno = 0 ;
2002-11-11 15:50:47 +03:00
opcode = ptrace ( PTRACE_PEEKTEXT , pid , ( char * ) ( pc - sizeof ( long ) ) , 0 ) ;
2003-01-20 13:23:04 +03:00
if ( errno ) {
perror ( " peektext(pc-oneword) " ) ;
2002-11-11 15:50:47 +03:00
return - 1 ;
2003-01-20 13:23:04 +03:00
}
2002-11-11 15:50:47 +03:00
/*
* We have to check if the SVC got executed directly or via an
* EXECUTE instruction . In case of EXECUTE it is necessary to do
* instruction decoding to derive the system call number .
* Unfortunately the opcode sizes of EXECUTE and SVC are differently ,
* so that this doesn ' t work if a SVC opcode is part of an EXECUTE
* opcode . Since there is no way to find out the opcode size this
* is the best we can do . . .
*/
if ( ( opcode & 0xff00 ) = = 0x0a00 ) {
/* SVC opcode */
scno = opcode & 0xff ;
2002-12-16 02:58:31 +03:00
}
2002-11-11 15:50:47 +03:00
else {
/* SVC got executed by EXECUTE instruction */
/*
* Do instruction decoding of EXECUTE . If you really want to
* understand this , read the Principles of Operations .
*/
svc_addr = ( void * ) ( opcode & 0xfff ) ;
tmp = 0 ;
offset_reg = ( opcode & 0x000f0000 ) > > 16 ;
if ( offset_reg & & ( upeek ( pid , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
return - 1 ;
svc_addr + = tmp ;
tmp = 0 ;
offset_reg = ( opcode & 0x0000f000 ) > > 12 ;
if ( offset_reg & & ( upeek ( pid , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
return - 1 ;
svc_addr + = tmp ;
scno = ptrace ( PTRACE_PEEKTEXT , pid , svc_addr , 0 ) ;
if ( errno )
return - 1 ;
# if defined(S390X)
scno > > = 48 ;
# else
scno > > = 16 ;
# endif
tmp = 0 ;
offset_reg = ( opcode & 0x00f00000 ) > > 20 ;
if ( offset_reg & & ( upeek ( pid , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
return - 1 ;
scno = ( scno | tmp ) & 0xff ;
}
}
1999-12-23 17:20:14 +03:00
# elif defined (POWERPC)
2003-01-14 12:59:00 +03:00
if ( upeek ( pid , sizeof ( unsigned long ) * PT_R0 , & scno ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( scno = = 0 & & ( tcp - > flags & TCB_WAITEXECVE ) ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
# elif defined (I386)
if ( upeek ( pid , 4 * ORIG_EAX , & scno ) < 0 )
return - 1 ;
2002-09-23 19:41:01 +04:00
# elif defined (X86_64)
if ( upeek ( pid , 8 * ORIG_RAX , & scno ) < 0 )
return - 1 ;
2002-12-16 02:58:31 +03:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
static int currpers = - 1 ;
2002-09-23 19:41:01 +04:00
long val ;
/* Check CS register value. On x86-64 linux it is:
* 0x33 for long mode ( 64 bit )
* 0x23 for compatibility mode ( 32 bit )
2002-12-16 02:58:31 +03:00
* It takes only one ptrace and thus doesn ' t need
2002-09-23 19:41:01 +04:00
* to be cached .
*/
if ( upeek ( pid , 8 * CS , & val ) < 0 )
return - 1 ;
switch ( val )
{
case 0x23 : currpers = 1 ; break ;
case 0x33 : currpers = 0 ; break ;
default :
fprintf ( stderr , " Unknown value CS=0x%02X while "
" detecting personality of process "
" PID=%d \n " , ( int ) val , pid ) ;
currpers = current_personality ;
break ;
}
#if 0
/* This version analyzes the opcode of a syscall instruction.
* ( int 0x80 on i386 vs . syscall on x86 - 64 )
* It works , but is too complicated .
*/
unsigned long val , rip , i ;
if ( upeek ( pid , 8 * RIP , & rip ) < 0 )
perror ( " upeek(RIP) " ) ;
2002-12-16 02:58:31 +03:00
2002-09-23 19:41:01 +04:00
/* sizeof(syscall) == sizeof(int 0x80) == 2 */
rip - = 2 ;
errno = 0 ;
2002-12-16 02:58:31 +03:00
call = ptrace ( PTRACE_PEEKTEXT , pid , ( char * ) rip , 0 ) ;
if ( errno )
printf ( " ptrace_peektext failed: %s \n " ,
2002-09-23 19:41:01 +04:00
strerror ( errno ) ) ;
switch ( call & 0xffff )
{
/* x86-64: syscall = 0x0f 0x05 */
case 0x050f : currpers = 0 ; break ;
/* i386: int 0x80 = 0xcd 0x80 */
case 0x80cd : currpers = 1 ; break ;
default :
currpers = current_personality ;
2002-12-16 02:58:31 +03:00
fprintf ( stderr ,
2002-09-23 19:41:01 +04:00
" Unknown syscall opcode (0x%04X) while "
" detecting personality of process "
" PID=%d \n " , ( int ) call , pid ) ;
break ;
}
# endif
if ( currpers ! = current_personality )
{
char * names [ ] = { " 64 bit " , " 32 bit " } ;
set_personality ( currpers ) ;
2002-12-16 02:58:31 +03:00
printf ( " [ Process PID=%d runs in %s mode. ] \n " ,
2002-09-23 19:41:01 +04:00
pid , names [ current_personality ] ) ;
}
2002-12-16 02:58:31 +03:00
}
2000-02-04 00:58:30 +03:00
# elif defined(IA64)
2001-10-10 03:47:38 +04:00
# define IA64_PSR_IS ((long)1 << 34)
2000-02-04 00:58:30 +03:00
if ( upeek ( pid , PT_CR_IPSR , & psr ) > = 0 )
2001-10-10 03:47:38 +04:00
ia32 = ( psr & IA64_PSR_IS ) ! = 0 ;
2000-02-04 00:58:30 +03:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( ia32 ) {
2001-10-10 03:47:38 +04:00
if ( upeek ( pid , PT_R1 , & scno ) < 0 ) /* orig eax */
2000-02-04 00:58:30 +03:00
return - 1 ;
} else {
if ( upeek ( pid , PT_R15 , & scno ) < 0 )
return - 1 ;
}
2003-03-05 09:29:06 +03:00
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
2000-02-04 00:58:30 +03:00
} else {
/* syscall in progress */
if ( upeek ( pid , PT_R8 , & r8 ) < 0 )
return - 1 ;
if ( upeek ( pid , PT_R10 , & r10 ) < 0 )
return - 1 ;
}
1999-02-19 03:21:36 +03:00
# elif defined (ARM)
2003-06-04 03:29:04 +04:00
/*
* 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 ;
}
1999-02-19 03:21:36 +03:00
}
# elif defined (M68K)
if ( upeek ( pid , 4 * PT_ORIG_D0 , & scno ) < 0 )
return - 1 ;
1999-11-01 00:15:38 +03:00
# elif defined (MIPS)
if ( upeek ( pid , REG_A3 , & a3 ) < 0 )
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( upeek ( pid , REG_V0 , & scno ) < 0 )
return - 1 ;
if ( scno < 0 | | scno > nsyscalls ) {
if ( a3 = = 0 | | a3 = = - 1 ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
return 0 ;
}
}
} else {
if ( upeek ( pid , REG_V0 , & r2 ) < 0 )
return - 1 ;
}
1999-02-19 03:21:36 +03:00
# elif defined (ALPHA)
if ( upeek ( pid , REG_A3 , & a3 ) < 0 )
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( upeek ( pid , REG_R0 , & scno ) < 0 )
return - 1 ;
/* Check if we return from execve. */
if ( scno = = 0 & & tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
/*
* Do some sanity checks to figure out if it ' s
* really a syscall entry
*/
if ( scno < 0 | | scno > nsyscalls ) {
if ( a3 = = 0 | | a3 = = - 1 ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: r0 = %ld \n " , scno ) ;
return 0 ;
}
}
}
else {
if ( upeek ( pid , REG_R0 , & r0 ) < 0 )
return - 1 ;
}
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# elif defined (SPARC) || defined (SPARC64)
1999-02-19 03:21:36 +03:00
/* Everything we need is in the current register set. */
if ( ptrace ( PTRACE_GETREGS , pid , ( char * ) & regs , 0 ) < 0 )
return - 1 ;
/* If we are entering, then disassemble the syscall trap. */
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Retrieve the syscall trap instruction. */
errno = 0 ;
1999-08-30 03:15:07 +04:00
trap = ptrace ( PTRACE_PEEKTEXT , pid , ( char * ) regs . r_pc , 0 ) ;
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# if defined(SPARC64)
trap > > = 32 ;
# endif
1999-02-19 03:21:36 +03:00
if ( errno )
return - 1 ;
/* Disassemble the trap to see what personality to use. */
switch ( trap ) {
case 0x91d02010 :
/* Linux/SPARC syscall trap. */
set_personality ( 0 ) ;
break ;
1999-06-03 18:21:07 +04:00
case 0x91d0206d :
/* Linux/SPARC64 syscall trap. */
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
set_personality ( 2 ) ;
break ;
1999-02-19 03:21:36 +03:00
case 0x91d02000 :
/* SunOS syscall trap. (pers 1) */
fprintf ( stderr , " syscall: SunOS no support \n " ) ;
return - 1 ;
case 0x91d02008 :
/* Solaris 2.x syscall trap. (per 2) */
set_personality ( 1 ) ;
2002-12-16 02:58:31 +03:00
break ;
1999-02-19 03:21:36 +03:00
case 0x91d02009 :
/* NetBSD/FreeBSD syscall trap. */
fprintf ( stderr , " syscall: NetBSD/FreeBSD not supported \n " ) ;
return - 1 ;
case 0x91d02027 :
/* Solaris 2.x gettimeofday */
set_personality ( 1 ) ;
break ;
default :
/* Unknown syscall trap. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# if defined (SPARC64)
fprintf ( stderr , " syscall: unknown syscall trap %08lx %016lx \n " , trap , regs . r_tpc ) ;
# else
1999-08-30 03:15:07 +04:00
fprintf ( stderr , " syscall: unknown syscall trap %08x %08x \n " , trap , regs . r_pc ) ;
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# endif
1999-02-19 03:21:36 +03:00
return - 1 ;
}
/* Extract the system call number from the registers. */
if ( trap = = 0x91d02027 )
scno = 156 ;
else
1999-08-30 03:15:07 +04:00
scno = regs . r_g1 ;
1999-02-19 03:21:36 +03:00
if ( scno = = 0 ) {
1999-08-30 03:15:07 +04:00
scno = regs . r_o0 ;
memmove ( & regs . r_o0 , & regs . r_o1 , 7 * sizeof ( regs . r_o0 ) ) ;
1999-02-19 03:21:36 +03:00
}
}
2001-03-27 16:17:16 +04:00
# elif defined(HPPA)
if ( upeek ( pid , PT_GR20 , & scno ) < 0 )
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( ( tcp - > flags & TCB_WAITEXECVE ) ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2002-05-01 20:39:22 +04:00
# elif defined(SH)
/*
* In the new syscall ABI , the system call number is in R3 .
*/
if ( upeek ( 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 )
fprintf ( stderr ,
2002-09-23 17:30:09 +04:00
" Detected glibc bug: bogus system call number = %ld, "
" correcting to %ld \n " ,
2002-05-01 20:39:22 +04:00
scno ,
correct_scno ) ;
scno = correct_scno ;
}
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( scno = = 0 & & tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2003-06-27 02:40:42 +04:00
# elif defined(SH64)
2003-06-02 23:18:58 +04:00
if ( upeek ( pid , REG_SYSCALL , & scno ) < 0 )
return - 1 ;
scno & = 0xFFFF ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2003-06-27 02:40:42 +04:00
# endif /* SH64 */
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
if ( upeek ( pid , uoff ( u_arg [ 7 ] ) , & scno ) < 0 )
return - 1 ;
2002-05-01 20:39:22 +04:00
# elif defined(SH)
2003-06-02 23:18:58 +04:00
/* new syscall ABI returns result in R0 */
if ( upeek ( pid , 4 * REG_REG0 , ( long * ) & r0 ) < 0 )
return - 1 ;
2003-06-27 02:40:42 +04:00
# elif defined(SH64)
2003-06-02 23:18:58 +04:00
/* ABI defines result returned in r9 */
if ( upeek ( pid , REG_GENERAL ( 9 ) , ( long * ) & r9 ) < 0 )
return - 1 ;
1999-02-19 03:21:36 +03:00
# endif
2000-09-02 01:03:06 +04:00
# ifdef USE_PROCFS
1999-02-19 03:21:36 +03:00
# ifdef HAVE_PR_SYSCALL
2001-03-06 13:10:06 +03:00
scno = tcp - > status . PR_SYSCALL ;
1999-02-19 03:21:36 +03:00
# else /* !HAVE_PR_SYSCALL */
2000-09-02 01:03:06 +04:00
# ifndef FREEBSD
1999-08-30 03:15:07 +04:00
scno = tcp - > status . PR_WHAT ;
2000-09-02 01:03:06 +04:00
# else /* FREEBSD */
if ( pread ( tcp - > pfd_reg , & regs , sizeof ( regs ) , 0 ) < 0 ) {
perror ( " pread " ) ;
return - 1 ;
}
switch ( regs . r_eax ) {
case SYS_syscall :
case SYS___syscall :
pread ( tcp - > pfd , & scno , sizeof ( scno ) , regs . r_esp + sizeof ( int ) ) ;
break ;
default :
scno = regs . r_eax ;
break ;
}
# endif /* FREEBSD */
1999-02-19 03:21:36 +03:00
# endif /* !HAVE_PR_SYSCALL */
2000-09-02 01:03:06 +04:00
# endif /* USE_PROCFS */
2000-05-01 05:53:59 +04:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) )
tcp - > scno = scno ;
2000-02-01 20:58:41 +03:00
return 1 ;
}
int
syscall_fixup ( tcp )
struct tcb * tcp ;
{
2000-09-02 01:03:06 +04:00
# ifndef USE_PROCFS
2000-02-01 20:58:41 +03:00
int pid = tcp - > pid ;
2002-12-16 02:58:31 +03:00
# else /* USE_PROCFS */
2000-09-02 01:03:06 +04:00
int scno = tcp - > scno ;
2000-02-01 20:58:41 +03:00
1999-02-19 03:21:36 +03:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
1999-08-30 03:15:07 +04:00
if ( tcp - > status . PR_WHY ! = PR_SYSENTRY ) {
1999-02-19 03:21:36 +03:00
if (
scno = = SYS_fork
# ifdef SYS_vfork
| | scno = = SYS_vfork
# endif /* SYS_vfork */
2001-04-18 19:11:51 +04:00
# ifdef SYS_fork1
| | scno = = SYS_fork1
# endif /* SYS_fork1 */
# ifdef SYS_forkall
| | scno = = SYS_forkall
# endif /* SYS_forkall */
# ifdef SYS_rfork1
| | scno = = SYS_rfork1
# endif /* SYS_fork1 */
# ifdef SYS_rforkall
| | scno = = SYS_rforkall
# endif /* SYS_rforkall */
1999-02-19 03:21:36 +03:00
) {
/* We are returning in the child, fake it. */
1999-08-30 03:15:07 +04:00
tcp - > status . PR_WHY = PR_SYSENTRY ;
1999-02-19 03:21:36 +03:00
trace_syscall ( tcp ) ;
1999-08-30 03:15:07 +04:00
tcp - > status . PR_WHY = PR_SYSEXIT ;
1999-02-19 03:21:36 +03:00
}
else {
fprintf ( stderr , " syscall: missing entry \n " ) ;
tcp - > flags | = TCB_INSYSCALL ;
}
}
}
else {
1999-08-30 03:15:07 +04:00
if ( tcp - > status . PR_WHY ! = PR_SYSEXIT ) {
1999-02-19 03:21:36 +03:00
fprintf ( stderr , " syscall: missing exit \n " ) ;
tcp - > flags & = ~ TCB_INSYSCALL ;
}
}
2000-09-02 01:03:06 +04:00
# endif /* USE_PROCFS */
1999-02-19 03:21:36 +03:00
# ifdef SUNOS4
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( scno = = 0 ) {
fprintf ( stderr , " syscall: missing entry \n " ) ;
tcp - > flags | = TCB_INSYSCALL ;
}
}
else {
if ( scno ! = 0 ) {
if ( debug ) {
/*
* This happens when a signal handler
* for a signal which interrupted a
* a system call makes another system call .
*/
fprintf ( stderr , " syscall: missing exit \n " ) ;
}
tcp - > flags & = ~ TCB_INSYSCALL ;
}
}
# endif /* SUNOS4 */
# ifdef LINUX
# if defined (I386)
if ( upeek ( pid , 4 * EAX , & eax ) < 0 )
return - 1 ;
if ( eax ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: eax = %ld \n " , eax ) ;
return 0 ;
}
2002-09-23 19:41:01 +04:00
# elif defined (X86_64)
if ( upeek ( pid , 8 * RAX , & rax ) < 0 )
return - 1 ;
2004-06-23 05:40:45 +04:00
if ( current_personality = = 1 )
rax = ( long int ) ( int ) rax ; /* sign extend from 32 bits */
2002-09-23 19:41:01 +04:00
if ( rax ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: rax = %ld \n " , rax ) ;
return 0 ;
}
2002-10-07 18:31:00 +04:00
# elif defined (S390) || defined (S390X)
2000-02-14 19:23:40 +03:00
if ( upeek ( pid , PT_GPR2 , & gpr2 ) < 0 )
return - 1 ;
2002-11-11 15:50:47 +03:00
if ( syscall_mode ! = - ENOSYS )
syscall_mode = tcp - > scno ;
if ( gpr2 ! = syscall_mode & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2000-02-14 19:23:40 +03:00
if ( debug )
fprintf ( stderr , " stray syscall exit: gpr2 = %ld \n " , gpr2 ) ;
return 0 ;
}
2003-01-20 13:23:04 +03:00
else if ( ( ( tcp - > flags & ( TCB_INSYSCALL | TCB_WAITEXECVE ) )
= = ( TCB_INSYSCALL | TCB_WAITEXECVE ) )
& & ( gpr2 = = - ENOSYS | | gpr2 = = tcp - > scno ) ) {
/*
* Fake a return value of zero . We leave the TCB_WAITEXECVE
* flag set for the post - execve SIGTRAP to see and reset .
*/
gpr2 = 0 ;
}
1999-02-19 03:21:36 +03:00
# elif defined (POWERPC)
# define SO_MASK 0x10000000
2003-01-14 12:59:00 +03:00
if ( upeek ( pid , sizeof ( unsigned long ) * PT_CCR , & flags ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2003-01-14 12:59:00 +03:00
if ( upeek ( pid , sizeof ( unsigned long ) * PT_R3 , & result ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
if ( flags & SO_MASK )
result = - result ;
# elif defined (M68K)
if ( upeek ( pid , 4 * PT_D0 , & d0 ) < 0 )
return - 1 ;
if ( d0 ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: d0 = %ld \n " , d0 ) ;
return 0 ;
}
# elif defined (ARM)
2003-06-04 03:29:04 +04:00
/*
* Nothing required
*/
2001-03-27 16:17:16 +04:00
# elif defined (HPPA)
if ( upeek ( pid , PT_GR28 , & r28 ) < 0 )
return - 1 ;
2001-10-10 03:47:38 +04:00
# elif defined(IA64)
if ( upeek ( pid , PT_R10 , & r10 ) < 0 )
return - 1 ;
if ( upeek ( pid , PT_R8 , & r8 ) < 0 )
return - 1 ;
if ( ia32 & & r8 ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: r8 = %ld \n " , r8 ) ;
return 0 ;
}
1999-02-19 03:21:36 +03:00
# endif
# endif /* LINUX */
2000-02-01 20:58:41 +03:00
return 1 ;
}
1999-02-19 03:21:36 +03:00
2000-02-01 20:58:41 +03:00
int
get_error ( tcp )
struct tcb * tcp ;
{
int u_error = 0 ;
1999-02-19 03:21:36 +03:00
# ifdef LINUX
2002-10-07 18:31:00 +04:00
# if defined(S390) || defined(S390X)
2000-02-14 19:23:40 +03:00
if ( gpr2 & & ( unsigned ) - gpr2 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - gpr2 ;
}
else {
tcp - > u_rval = gpr2 ;
u_error = 0 ;
}
2002-10-07 18:31:00 +04:00
# else /* !S390 && !S390X */
1999-02-19 03:21:36 +03:00
# ifdef I386
if ( eax < 0 & & - eax < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - eax ;
}
else {
tcp - > u_rval = eax ;
u_error = 0 ;
}
# else /* !I386 */
2002-09-23 19:41:01 +04:00
# ifdef X86_64
if ( rax < 0 & & - rax < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - rax ;
}
else {
tcp - > u_rval = rax ;
u_error = 0 ;
}
# else
2000-02-04 00:58:30 +03:00
# ifdef IA64
if ( ia32 ) {
int err ;
err = ( int ) r8 ;
if ( err < 0 & & - err < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - err ;
}
else {
tcp - > u_rval = err ;
u_error = 0 ;
}
} else {
if ( r10 ) {
tcp - > u_rval = - 1 ;
u_error = r8 ;
} else {
tcp - > u_rval = r8 ;
u_error = 0 ;
}
}
# else /* !IA64 */
1999-11-01 00:15:38 +03:00
# ifdef MIPS
if ( a3 ) {
tcp - > u_rval = - 1 ;
u_error = r2 ;
} else {
tcp - > u_rval = r2 ;
u_error = 0 ;
}
# else
1999-02-19 03:21:36 +03:00
# ifdef POWERPC
2004-01-13 13:13:44 +03:00
if ( result & & ( unsigned long ) - result < nerrnos ) {
1999-02-19 03:21:36 +03:00
tcp - > u_rval = - 1 ;
u_error = - result ;
}
else {
tcp - > u_rval = result ;
u_error = 0 ;
}
# else /* !POWERPC */
# ifdef M68K
if ( d0 & & ( unsigned ) - d0 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - d0 ;
}
else {
tcp - > u_rval = d0 ;
u_error = 0 ;
}
# else /* !M68K */
# ifdef ARM
2003-06-04 03:29:04 +04:00
if ( regs . ARM_r0 & & ( unsigned ) - regs . ARM_r0 < nerrnos ) {
1999-02-19 03:21:36 +03:00
tcp - > u_rval = - 1 ;
2003-06-04 03:29:04 +04:00
u_error = - regs . ARM_r0 ;
1999-02-19 03:21:36 +03:00
}
else {
2003-06-04 03:29:04 +04:00
tcp - > u_rval = regs . ARM_r0 ;
1999-02-19 03:21:36 +03:00
u_error = 0 ;
}
# else /* !ARM */
# ifdef ALPHA
if ( a3 ) {
tcp - > u_rval = - 1 ;
u_error = r0 ;
}
else {
tcp - > u_rval = r0 ;
u_error = 0 ;
}
# else /* !ALPHA */
# ifdef SPARC
1999-08-30 03:15:07 +04:00
if ( regs . r_psr & PSR_C ) {
1999-02-19 03:21:36 +03:00
tcp - > u_rval = - 1 ;
1999-08-30 03:15:07 +04:00
u_error = regs . r_o0 ;
1999-02-19 03:21:36 +03:00
}
else {
1999-08-30 03:15:07 +04:00
tcp - > u_rval = regs . r_o0 ;
1999-02-19 03:21:36 +03:00
u_error = 0 ;
}
2001-03-27 16:17:16 +04:00
# else /* !SPARC */
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# 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 */
2001-03-27 16:17:16 +04:00
# ifdef HPPA
if ( r28 & & ( unsigned ) - r28 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - r28 ;
}
else {
tcp - > u_rval = r28 ;
u_error = 0 ;
}
2002-05-01 20:39:22 +04:00
# else
# ifdef SH
/* interpret R0 as return value or error number */
if ( r0 & & ( unsigned ) - r0 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - r0 ;
}
else {
tcp - > u_rval = r0 ;
u_error = 0 ;
}
2003-06-02 23:18:58 +04:00
# else
2003-06-27 02:40:42 +04:00
# ifdef SH64
2003-06-02 23:18:58 +04:00
/* interpret result as return value or error number */
if ( r9 & & ( unsigned ) - r9 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - r9 ;
}
else {
tcp - > u_rval = r9 ;
u_error = 0 ;
}
2003-06-27 02:40:42 +04:00
# endif /* SH64 */
2002-05-01 20:39:22 +04:00
# endif /* SH */
2001-03-27 16:17:16 +04:00
# endif /* HPPA */
1999-02-19 03:21:36 +03:00
# endif /* SPARC */
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# endif /* SPARC64 */
1999-02-19 03:21:36 +03:00
# endif /* ALPHA */
# endif /* ARM */
# endif /* M68K */
# endif /* POWERPC */
1999-11-01 00:15:38 +03:00
# endif /* MIPS */
2000-02-04 00:58:30 +03:00
# endif /* IA64 */
2002-09-23 19:41:01 +04:00
# endif /* X86_64 */
1999-02-19 03:21:36 +03:00
# endif /* I386 */
2002-10-07 18:31:00 +04:00
# endif /* S390 || S390X */
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
/* get error code from user struct */
if ( upeek ( pid , uoff ( u_error ) , & u_error ) < 0 )
return - 1 ;
u_error > > = 24 ; /* u_error is a char */
/* get system call return value */
if ( upeek ( pid , uoff ( u_rval1 ) , & tcp - > u_rval ) < 0 )
return - 1 ;
# endif /* SUNOS4 */
# ifdef SVR4
# ifdef SPARC
/* Judicious guessing goes a long way. */
if ( tcp - > status . pr_reg [ R_PSR ] & 0x100000 ) {
tcp - > u_rval = - 1 ;
u_error = tcp - > status . pr_reg [ R_O0 ] ;
}
else {
tcp - > u_rval = tcp - > status . pr_reg [ R_O0 ] ;
u_error = 0 ;
}
# endif /* SPARC */
# ifdef I386
/* Wanna know how to kill an hour single-stepping? */
1999-08-30 03:15:07 +04:00
if ( tcp - > status . PR_REG [ EFL ] & 0x1 ) {
1999-02-19 03:21:36 +03:00
tcp - > u_rval = - 1 ;
1999-08-30 03:15:07 +04:00
u_error = tcp - > status . PR_REG [ EAX ] ;
1999-02-19 03:21:36 +03:00
}
else {
1999-08-30 03:15:07 +04:00
tcp - > u_rval = tcp - > status . PR_REG [ EAX ] ;
2000-08-10 06:14:04 +04:00
# ifdef HAVE_LONG_LONG
tcp - > u_lrval =
( ( unsigned long long ) tcp - > status . PR_REG [ EDX ] < < 32 ) +
tcp - > status . PR_REG [ EAX ] ;
# endif
1999-02-19 03:21:36 +03:00
u_error = 0 ;
}
# endif /* I386 */
2002-09-23 19:41:01 +04:00
# ifdef X86_64
/* Wanna know how to kill an hour single-stepping? */
if ( tcp - > status . PR_REG [ EFLAGS ] & 0x1 ) {
tcp - > u_rval = - 1 ;
u_error = tcp - > status . PR_REG [ RAX ] ;
}
else {
tcp - > u_rval = tcp - > status . PR_REG [ RAX ] ;
u_error = 0 ;
}
# endif /* X86_64 */
1999-02-19 03:21:36 +03:00
# ifdef MIPS
if ( tcp - > status . pr_reg [ CTX_A3 ] ) {
tcp - > u_rval = - 1 ;
u_error = tcp - > status . pr_reg [ CTX_V0 ] ;
}
else {
tcp - > u_rval = tcp - > status . pr_reg [ CTX_V0 ] ;
u_error = 0 ;
}
# endif /* MIPS */
# endif /* SVR4 */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
if ( regs . r_eflags & PSL_C ) {
tcp - > u_rval = - 1 ;
u_error = regs . r_eax ;
} else {
tcp - > u_rval = regs . r_eax ;
tcp - > u_lrval =
( ( unsigned long long ) regs . r_edx < < 32 ) + regs . r_eax ;
u_error = 0 ;
}
2002-12-16 02:58:31 +03:00
# endif /* FREEBSD */
2000-02-01 20:58:41 +03:00
tcp - > u_error = u_error ;
return 1 ;
}
1999-02-19 03:21:36 +03:00
2002-12-22 02:25:18 +03:00
int
force_result ( tcp , error , rval )
struct tcb * tcp ;
int error ;
long rval ;
{
# ifdef LINUX
# if defined(S390) || defined(S390X)
gpr2 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) PT_GPR2 , gpr2 ) < 0 )
return - 1 ;
# else /* !S390 && !S390X */
# ifdef I386
eax = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( EAX * 4 ) , eax ) < 0 )
return - 1 ;
# else /* !I386 */
# ifdef X86_64
rax = error ? - error : rval ;
2004-06-23 05:40:45 +04:00
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( RAX * 8 ) , rax ) < 0 )
2002-12-22 02:25:18 +03:00
return - 1 ;
# else
# ifdef IA64
if ( ia32 ) {
r8 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( PT_R8 ) , r8 ) < 0 )
return - 1 ;
}
else {
if ( error ) {
r8 = error ;
r10 = - 1 ;
}
else {
r8 = rval ;
r10 = 0 ;
}
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( PT_R8 ) , r8 ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( PT_R10 ) , r10 ) < 0 )
return - 1 ;
}
# else /* !IA64 */
# ifdef MIPS
if ( error ) {
r2 = error ;
a3 = - 1 ;
}
else {
r2 = rval ;
a3 = 0 ;
}
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( REG_A3 ) , a3 ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( REG_V0 ) , r2 ) < 0 )
return - 1 ;
# else
# ifdef POWERPC
2003-01-14 12:59:00 +03:00
if ( upeek ( tcp - > pid , sizeof ( unsigned long ) * PT_CCR , & flags ) < 0 )
2002-12-22 02:25:18 +03:00
return - 1 ;
if ( error ) {
flags | = SO_MASK ;
result = error ;
}
else {
flags & = ~ SO_MASK ;
result = rval ;
}
2003-01-14 12:59:00 +03:00
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( sizeof ( unsigned long ) * PT_CCR ) , flags ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( sizeof ( unsigned long ) * PT_R3 ) , result ) < 0 )
2002-12-22 02:25:18 +03:00
return - 1 ;
# else /* !POWERPC */
# ifdef M68K
d0 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( 4 * PT_D0 ) , d0 ) < 0 )
return - 1 ;
# else /* !M68K */
# ifdef ARM
2003-06-27 02:29:32 +04:00
regs . ARM_r0 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( 4 * 0 ) , regs . ARM_r0 ) < 0 )
2002-12-22 02:25:18 +03:00
return - 1 ;
# else /* !ARM */
# ifdef ALPHA
if ( error ) {
a3 = - 1 ;
r0 = error ;
}
else {
a3 = 0 ;
r0 = rval ;
}
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( REG_A3 ) , a3 ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( REG_R0 ) , r0 ) < 0 )
return - 1 ;
# else /* !ALPHA */
# ifdef SPARC
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , ( char * ) & regs , 0 ) < 0 )
return - 1 ;
if ( error ) {
regs . r_psr | = PSR_C ;
regs . r_o0 = error ;
}
else {
regs . r_psr & = ~ PSR_C ;
regs . r_o0 = rval ;
}
if ( ptrace ( PTRACE_SETREGS , tcp - > pid , ( char * ) & regs , 0 ) < 0 )
return - 1 ;
# else /* !SPARC */
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# ifdef SPARC64
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , ( char * ) & regs , 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 * ) & regs , 0 ) < 0 )
return - 1 ;
# else /* !SPARC64 */
2002-12-22 02:25:18 +03:00
# ifdef HPPA
r28 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( PT_GR28 ) , r28 ) < 0 )
return - 1 ;
# else
# ifdef SH
r0 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( 4 * REG_REG0 ) , r0 ) < 0 )
return - 1 ;
2003-06-02 23:18:58 +04:00
# else
2003-06-27 02:40:42 +04:00
# ifdef SH64
2003-06-02 23:18:58 +04:00
r9 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) REG_GENERAL ( 9 ) , r9 ) < 0 )
return - 1 ;
2003-06-27 02:40:42 +04:00
# endif /* SH64 */
2002-12-22 02:25:18 +03:00
# endif /* SH */
# endif /* HPPA */
# endif /* SPARC */
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# endif /* SPARC64 */
2002-12-22 02:25:18 +03:00
# endif /* ALPHA */
# endif /* ARM */
# endif /* M68K */
# endif /* POWERPC */
# endif /* MIPS */
# endif /* IA64 */
# endif /* X86_64 */
# endif /* I386 */
# endif /* S390 || S390X */
# endif /* LINUX */
# ifdef SUNOS4
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) uoff ( u_error ) ,
error < < 24 ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) uoff ( u_rval1 ) , rval ) < 0 )
return - 1 ;
# endif /* SUNOS4 */
# ifdef SVR4
/* XXX no clue */
return - 1 ;
# endif /* SVR4 */
# ifdef FREEBSD
if ( pread ( tcp - > pfd_reg , & regs , sizeof ( regs ) , 0 ) < 0 ) {
perror ( " pread " ) ;
return - 1 ;
}
if ( error ) {
regs . r_eflags | = PSL_C ;
regs . r_eax = error ;
}
else {
regs . r_eflags & = ~ PSL_C ;
regs . r_eax = rval ;
}
if ( pwrite ( tcp - > pfd_reg , & regs , sizeof ( regs ) , 0 ) < 0 ) {
perror ( " pwrite " ) ;
return - 1 ;
}
# endif /* FREEBSD */
/* All branches reach here on success (only). */
tcp - > u_error = error ;
tcp - > u_rval = rval ;
return 0 ;
}
2000-02-01 20:58:41 +03:00
int syscall_enter ( tcp )
struct tcb * tcp ;
{
2000-09-02 01:03:06 +04:00
# ifndef USE_PROCFS
2000-02-01 20:58:41 +03:00
int pid = tcp - > pid ;
2002-12-16 02:58:31 +03:00
# endif /* !USE_PROCFS */
1999-02-19 03:21:36 +03:00
# ifdef LINUX
2002-10-07 18:31:00 +04:00
# if defined(S390) || defined(S390X)
1999-12-23 17:20:14 +03:00
{
int i ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = MAX_ARGS ;
1999-12-23 17:20:14 +03:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
2002-10-07 18:31:00 +04:00
if ( upeek ( pid , i = = 0 ? PT_ORIGGPR2 : PT_GPR2 + i * sizeof ( long ) , & tcp - > u_arg [ i ] ) < 0 )
1999-12-23 17:20:14 +03:00
return - 1 ;
}
}
# elif defined (ALPHA)
1999-02-19 03:21:36 +03:00
{
int i ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = MAX_ARGS ;
1999-02-19 03:21:36 +03:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
1999-04-19 02:50:50 +04:00
/* WTA: if scno is out-of-bounds this will bomb. Add range-check
* for scno somewhere above here !
*/
1999-02-19 03:21:36 +03:00
if ( upeek ( pid , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
2000-02-04 00:58:30 +03:00
# elif defined (IA64)
{
2001-10-10 03:47:38 +04:00
if ( ! ia32 ) {
unsigned long * out0 , * rbs_end , cfm , sof , sol , i ;
/* be backwards compatible with kernel < 2.4.4... */
# ifndef PT_RBS_END
# define PT_RBS_END PT_AR_BSP
# endif
if ( upeek ( pid , PT_RBS_END , ( long * ) & rbs_end ) < 0 )
return - 1 ;
if ( upeek ( pid , PT_CFM , ( long * ) & cfm ) < 0 )
return - 1 ;
2000-05-01 05:53:59 +04:00
2001-10-10 03:47:38 +04:00
sof = ( cfm > > 0 ) & 0x7f ;
sol = ( cfm > > 7 ) & 0x7f ;
out0 = ia64_rse_skip_regs ( rbs_end , - sof + sol ) ;
2000-02-04 00:58:30 +03:00
2001-10-10 03:47:38 +04:00
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 ) {
if ( umoven ( tcp , ( unsigned long ) ia64_rse_skip_regs ( out0 , i ) ,
sizeof ( long ) , ( char * ) & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
} else {
int i ;
if ( /* EBX = out0 */
upeek ( pid , PT_R11 , ( long * ) & tcp - > u_arg [ 0 ] ) < 0
/* ECX = out1 */
| | upeek ( pid , PT_R9 , ( long * ) & tcp - > u_arg [ 1 ] ) < 0
/* EDX = out2 */
| | upeek ( pid , PT_R10 , ( long * ) & tcp - > u_arg [ 2 ] ) < 0
/* ESI = out3 */
| | upeek ( pid , PT_R14 , ( long * ) & tcp - > u_arg [ 3 ] ) < 0
/* EDI = out4 */
| | upeek ( pid , PT_R15 , ( long * ) & tcp - > u_arg [ 4 ] ) < 0
/* EBP = out5 */
| | upeek ( pid , PT_R13 , ( long * ) & tcp - > u_arg [ 5 ] ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
2001-10-10 03:47:38 +04:00
for ( i = 0 ; i < 6 ; + + i )
/* truncate away IVE sign-extension */
tcp - > u_arg [ i ] & = 0xffffffff ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls
& & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = 5 ;
2000-02-04 00:58:30 +03:00
}
}
1999-11-01 00:15:38 +03:00
# elif defined (MIPS)
{
long sp ;
int i , nargs ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
nargs = tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
nargs = tcp - > u_nargs = MAX_ARGS ;
1999-11-01 00:15:38 +03:00
if ( nargs > 4 ) {
if ( upeek ( pid , REG_SP , & sp ) < 0 )
return - 1 ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( upeek ( pid , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
umoven ( tcp , sp + 16 , ( nargs - 4 ) * sizeof ( tcp - > u_arg [ 0 ] ) ,
( char * ) ( tcp - > u_arg + 4 ) ) ;
} else {
for ( i = 0 ; i < nargs ; i + + ) {
if ( upeek ( pid , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
}
1999-02-19 03:21:36 +03:00
# elif defined (POWERPC)
2002-12-16 02:58:31 +03:00
# ifndef PT_ORIG_R3
# define PT_ORIG_R3 34
# endif
1999-02-19 03:21:36 +03:00
{
int i ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = MAX_ARGS ;
1999-02-19 03:21:36 +03:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
2003-01-14 12:59:00 +03:00
if ( upeek ( pid , ( i = = 0 ) ?
( sizeof ( unsigned long ) * PT_ORIG_R3 ) :
( ( i + PT_R3 ) * sizeof ( unsigned long ) ) ,
& tcp - > u_arg [ i ] ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
}
}
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# elif defined (SPARC) || defined (SPARC64)
1999-02-19 03:21:36 +03:00
{
1999-08-30 03:15:07 +04:00
int i ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = MAX_ARGS ;
1999-02-19 03:21:36 +03:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
1999-08-30 03:15:07 +04:00
tcp - > u_arg [ i ] = * ( ( & regs . r_o0 ) + i ) ;
1999-02-19 03:21:36 +03:00
}
2001-03-27 16:17:16 +04:00
# elif defined (HPPA)
{
int i ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2001-03-27 16:17:16 +04:00
tcp - > u_nargs = MAX_ARGS ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( pid , PT_GR26 - 4 * i , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
2003-06-04 03:29:04 +04:00
# 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 ] ;
}
2002-05-01 20:39:22 +04:00
# elif defined(SH)
{
2002-12-16 02:58:31 +03:00
int i ;
2002-05-01 20:39:22 +04:00
static int syscall_regs [ ] = {
REG_REG0 + 4 , REG_REG0 + 5 , REG_REG0 + 6 , REG_REG0 + 7 ,
REG_REG0 , REG_REG0 + 1 , REG_REG0 + 2
} ;
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( pid , 4 * syscall_regs [ i ] , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
2003-06-27 02:40:42 +04:00
# elif defined(SH64)
2003-06-02 23:18:58 +04:00
{
int i ;
/* Registers used by SH5 Linux system calls for parameters */
static int syscall_regs [ ] = { 2 , 3 , 4 , 5 , 6 , 7 } ;
/*
* TODO : should also check that the number of arguments encoded
* in the trap number matches the number strace expects .
*/
/*
assert ( sysent [ tcp - > scno ] . nargs <
sizeof ( syscall_regs ) / sizeof ( syscall_regs [ 0 ] ) ) ;
*/
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( pid , REG_GENERAL ( syscall_regs [ i ] ) , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
2002-09-23 19:41:01 +04:00
# elif defined(X86_64)
{
int i ;
static int argreg [ SUPPORTED_PERSONALITIES ] [ MAX_ARGS ] = {
{ RDI , RSI , RDX , R10 , R8 , R9 } , /* x86-64 ABI */
2005-02-02 06:06:52 +03:00
{ RBX , RCX , RDX , RSI , RDI , RBP } /* i386 ABI */
2002-09-23 19:41:01 +04:00
} ;
2002-12-16 02:58:31 +03:00
2002-09-23 19:41:01 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2002-09-23 19:41:01 +04:00
tcp - > u_nargs = MAX_ARGS ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( pid , argreg [ current_personality ] [ i ] * 8 , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
2000-02-20 02:59:03 +03:00
# else /* Other architecture (like i386) (32bits specific) */
1999-02-19 03:21:36 +03:00
{
int i ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = MAX_ARGS ;
1999-02-19 03:21:36 +03:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( pid , i * 4 , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
2002-12-16 02:58:31 +03:00
# endif
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
{
int i ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = MAX_ARGS ;
1999-02-19 03:21:36 +03:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
struct user * u ;
if ( upeek ( pid , uoff ( u_arg [ 0 ] ) +
( i * sizeof ( u - > u_arg [ 0 ] ) ) , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
}
# endif /* SUNOS4 */
# ifdef SVR4
# ifdef MIPS
/*
* SGI is broken : even though it has pr_sysarg , it doesn ' t
* set them on system call entry . Get a clue .
*/
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
1999-02-19 03:21:36 +03:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = tcp - > status . pr_nsysarg ;
if ( tcp - > u_nargs > 4 ) {
memcpy ( tcp - > u_arg , & tcp - > status . pr_reg [ CTX_A0 ] ,
4 * sizeof ( tcp - > u_arg [ 0 ] ) ) ;
umoven ( tcp , tcp - > status . pr_reg [ CTX_SP ] + 16 ,
( tcp - > u_nargs - 4 ) * sizeof ( tcp - > u_arg [ 0 ] ) , ( char * ) ( tcp - > u_arg + 4 ) ) ;
}
else {
memcpy ( tcp - > u_arg , & tcp - > status . pr_reg [ CTX_A0 ] ,
tcp - > u_nargs * sizeof ( tcp - > u_arg [ 0 ] ) ) ;
}
2001-03-06 13:10:06 +03:00
# elif UNIXWARE >= 2
/*
* Like SGI , UnixWare doesn ' t set pr_sysarg until system call exit
*/
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = tcp - > status . pr_lwp . pr_nsysarg ;
umoven ( tcp , tcp - > status . PR_REG [ UESP ] + 4 ,
tcp - > u_nargs * sizeof ( tcp - > u_arg [ 0 ] ) , ( char * ) tcp - > u_arg ) ;
# elif defined (HAVE_PR_SYSCALL)
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
1999-02-19 03:21:36 +03:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = tcp - > status . pr_nsysarg ;
{
int i ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
tcp - > u_arg [ i ] = tcp - > status . pr_sysarg [ i ] ;
}
2001-03-06 13:10:06 +03:00
# elif defined (I386)
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
1999-02-19 03:21:36 +03:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = 5 ;
1999-08-30 03:15:07 +04:00
umoven ( tcp , tcp - > status . PR_REG [ UESP ] + 4 ,
1999-02-19 03:21:36 +03:00
tcp - > u_nargs * sizeof ( tcp - > u_arg [ 0 ] ) , ( char * ) tcp - > u_arg ) ;
2001-03-06 13:10:06 +03:00
# else
I DONT KNOW WHAT TO DO
1999-02-19 03:21:36 +03:00
# endif /* !HAVE_PR_SYSCALL */
# endif /* SVR4 */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & &
sysent [ tcp - > scno ] . nargs > tcp - > status . val )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = tcp - > status . val ;
if ( tcp - > u_nargs < 0 )
tcp - > u_nargs = 0 ;
if ( tcp - > u_nargs > MAX_ARGS )
tcp - > u_nargs = MAX_ARGS ;
switch ( regs . r_eax ) {
case SYS___syscall :
pread ( tcp - > pfd , & tcp - > u_arg , tcp - > u_nargs * sizeof ( unsigned long ) ,
regs . r_esp + sizeof ( int ) + sizeof ( quad_t ) ) ;
break ;
case SYS_syscall :
pread ( tcp - > pfd , & tcp - > u_arg , tcp - > u_nargs * sizeof ( unsigned long ) ,
regs . r_esp + 2 * sizeof ( int ) ) ;
break ;
default :
pread ( tcp - > pfd , & tcp - > u_arg , tcp - > u_nargs * sizeof ( unsigned long ) ,
regs . r_esp + sizeof ( int ) ) ;
break ;
}
# endif /* FREEBSD */
2000-02-01 20:58:41 +03:00
return 1 ;
}
int
trace_syscall ( tcp )
struct tcb * tcp ;
{
int sys_res ;
struct timeval tv ;
int res ;
/* Measure the exit time as early as possible to avoid errors. */
if ( dtime & & ( tcp - > flags & TCB_INSYSCALL ) )
gettimeofday ( & tv , NULL ) ;
res = get_scno ( tcp ) ;
if ( res ! = 1 )
return res ;
res = syscall_fixup ( tcp ) ;
if ( res ! = 1 )
return res ;
if ( tcp - > flags & TCB_INSYSCALL ) {
long u_error ;
res = get_error ( tcp ) ;
if ( res ! = 1 )
return res ;
internal_syscall ( tcp ) ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & &
! ( qual_flags [ tcp - > scno ] & QUAL_TRACE ) ) {
2000-02-01 20:58:41 +03:00
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
if ( tcp - > flags & TCB_REPRINT ) {
printleader ( tcp ) ;
tprintf ( " <... " ) ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 )
2000-02-01 20:58:41 +03:00
tprintf ( " syscall_%lu " , tcp - > scno ) ;
else
tprintf ( " %s " , sysent [ tcp - > scno ] . sys_name ) ;
tprintf ( " resumed> " ) ;
}
2000-09-02 01:03:06 +04:00
if ( cflag & & tcp - > scno < nsyscalls & & tcp - > scno > = 0 ) {
2004-09-04 08:20:43 +04:00
if ( counts = = NULL ) {
counts = calloc ( sizeof * counts , nsyscalls ) ;
if ( counts = = NULL ) {
fprintf ( stderr , " \
strace : out of memory for call counts \ n " );
exit ( 1 ) ;
}
}
counts [ tcp - > scno ] . calls + + ;
2000-02-01 20:58:41 +03:00
if ( tcp - > u_error )
2004-09-04 08:20:43 +04:00
counts [ tcp - > scno ] . errors + + ;
2000-02-01 20:58:41 +03:00
tv_sub ( & tv , & tv , & tcp - > etime ) ;
# ifdef LINUX
if ( tv_cmp ( & tv , & tcp - > dtime ) > 0 ) {
2003-11-02 01:11:22 +03:00
static struct timeval one_tick ;
if ( one_tick . tv_usec = = 0 ) {
/* Initialize it. */
struct itimerval it ;
memset ( & it , 0 , sizeof it ) ;
it . it_interval . tv_usec = 1 ;
setitimer ( ITIMER_REAL , & it , NULL ) ;
getitimer ( ITIMER_REAL , & it ) ;
one_tick = it . it_interval ;
}
2000-02-01 20:58:41 +03:00
if ( tv_nz ( & tcp - > dtime ) )
tv = tcp - > dtime ;
else if ( tv_cmp ( & tv , & one_tick ) > 0 ) {
if ( tv_cmp ( & shortest , & one_tick ) < 0 )
tv = shortest ;
else
tv = one_tick ;
}
}
# endif /* LINUX */
if ( tv_cmp ( & tv , & shortest ) < 0 )
shortest = tv ;
2004-09-04 08:20:43 +04:00
tv_add ( & counts [ tcp - > scno ] . time ,
& counts [ tcp - > scno ] . time , & tv ) ;
2000-02-01 20:58:41 +03:00
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0
2000-02-01 20:58:41 +03:00
| | ( qual_flags [ tcp - > scno ] & QUAL_RAW ) )
sys_res = printargs ( tcp ) ;
2002-11-06 16:17:21 +03:00
else {
if ( not_failing_only & & tcp - > u_error )
2002-12-16 02:58:31 +03:00
return 0 ; /* ignore failed syscalls */
2000-02-01 20:58:41 +03:00
sys_res = ( * sysent [ tcp - > scno ] . sys_func ) ( tcp ) ;
2002-12-16 02:58:31 +03:00
}
2000-02-01 20:58:41 +03:00
u_error = tcp - > u_error ;
tprintf ( " ) " ) ;
tabto ( acolumn ) ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 | |
qual_flags [ tcp - > scno ] & QUAL_RAW ) {
2000-02-01 20:58:41 +03:00
if ( u_error )
tprintf ( " = -1 (errno %ld) " , u_error ) ;
else
tprintf ( " = %#lx " , tcp - > u_rval ) ;
}
else if ( ! ( sys_res & RVAL_NONE ) & & u_error ) {
switch ( u_error ) {
# ifdef LINUX
case ERESTARTSYS :
tprintf ( " = ? ERESTARTSYS (To be restarted) " ) ;
break ;
case ERESTARTNOINTR :
tprintf ( " = ? ERESTARTNOINTR (To be restarted) " ) ;
break ;
case ERESTARTNOHAND :
tprintf ( " = ? ERESTARTNOHAND (To be restarted) " ) ;
break ;
2003-07-05 Richard Henderson <rth@twiddle.net>
* process.c (sys_clone): Order arguments for alpha the same as x86_64.
* syscall.c (ERESTART_RESTARTBLOCK): New.
(trace_syscall): Print it.
* linux/alpha/syscallent.h (osf_syscall): Name properly.
(osf_set_program_attributes): Fix typo.
(osf_nfssvc): Likewise.
(osf_sigsendset): Likewise.
(getdents64, gettid, readahead, tkill, setxattr, lsetxattr, fsetxattr,
getxattr, lgetxattr, fgetxattr, listxattr, llistxattr, flistxattr,
removexattr, lremovexattr, fremovexattr, futex, sched_setaffinity,
sched_getaffinity, tuxcall, io_setup, io_destroy, io_getevents,
io_submit, io_cancel, exit_group, lookup_dcookie, epoll_create,
epoll_ctl, epoll_wait, remap_file_pages, set_tid_address,
restart_syscall, fadvise, timer_create, timer_settime, timer_gettime,
timer_getoverrun, timer_delete, clock_settime, clock_gettime,
clock_getres, clock_nanosleep, semtimedop): New.
2003-07-09 13:47:59 +04:00
case ERESTART_RESTARTBLOCK :
tprintf ( " = ? ERESTART_RESTARTBLOCK (To be restarted) " ) ;
break ;
2000-02-01 20:58:41 +03:00
# endif /* LINUX */
default :
tprintf ( " = -1 " ) ;
2002-03-31 23:03:29 +04:00
if ( u_error < 0 )
tprintf ( " E??? (errno %ld) " , u_error ) ;
2000-02-01 20:58:41 +03:00
else if ( u_error < nerrnos )
2002-12-16 02:58:31 +03:00
tprintf ( " %s (%s) " , errnoent [ u_error ] ,
strerror ( u_error ) ) ;
2000-02-01 20:58:41 +03:00
else
2002-12-16 02:58:31 +03:00
tprintf ( " ERRNO_%ld (%s) " , u_error ,
strerror ( u_error ) ) ;
2000-02-01 20:58:41 +03:00
break ;
}
}
else {
if ( sys_res & RVAL_NONE )
tprintf ( " = ? " ) ;
else {
switch ( sys_res & RVAL_MASK ) {
case RVAL_HEX :
tprintf ( " = %#lx " , tcp - > u_rval ) ;
break ;
case RVAL_OCTAL :
tprintf ( " = %#lo " , tcp - > u_rval ) ;
break ;
case RVAL_UDECIMAL :
tprintf ( " = %lu " , tcp - > u_rval ) ;
break ;
case RVAL_DECIMAL :
tprintf ( " = %ld " , tcp - > u_rval ) ;
break ;
2000-08-10 06:14:04 +04:00
# ifdef HAVE_LONG_LONG
2000-09-02 01:03:06 +04:00
case RVAL_LHEX :
tprintf ( " = %#llx " , tcp - > u_lrval ) ;
break ;
case RVAL_LOCTAL :
tprintf ( " = %#llo " , tcp - > u_lrval ) ;
break ;
case RVAL_LUDECIMAL :
tprintf ( " = %llu " , tcp - > u_lrval ) ;
break ;
2000-08-10 06:14:04 +04:00
case RVAL_LDECIMAL :
2000-09-02 01:03:06 +04:00
tprintf ( " = %lld " , tcp - > u_lrval ) ;
2000-08-10 06:14:04 +04:00
break ;
# endif
2000-02-01 20:58:41 +03:00
default :
fprintf ( stderr ,
" invalid rval format \n " ) ;
break ;
}
}
if ( ( sys_res & RVAL_STR ) & & tcp - > auxstr )
tprintf ( " (%s) " , tcp - > auxstr ) ;
}
if ( dtime ) {
tv_sub ( & tv , & tv , & tcp - > etime ) ;
tprintf ( " <%ld.%06ld> " ,
( long ) tv . tv_sec , ( long ) tv . tv_usec ) ;
}
printtrailer ( tcp ) ;
dumpio ( tcp ) ;
if ( fflush ( tcp - > outf ) = = EOF )
return - 1 ;
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
/* Entering system call */
res = syscall_enter ( tcp ) ;
if ( res ! = 1 )
return res ;
2000-02-01 20:17:25 +03:00
switch ( tcp - > scno + NR_SYSCALL_BASE ) {
1999-02-19 03:21:36 +03:00
# ifdef LINUX
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# if !defined (ALPHA) && !defined(SPARC) && !defined(SPARC64) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64)
1999-02-19 03:21:36 +03:00
case SYS_socketcall :
decode_subcall ( tcp , SYS_socket_subcall ,
SYS_socket_nsubcalls , deref_style ) ;
break ;
case SYS_ipc :
decode_subcall ( tcp , SYS_ipc_subcall ,
SYS_ipc_nsubcalls , shift_style ) ;
break ;
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# endif /* !ALPHA && !MIPS && !SPARC && !SPARC64 && !HPPA && !X86_64 */
# if defined (SPARC) || defined (SPARC64)
1999-02-19 03:21:36 +03:00
case SYS_socketcall :
sparc_socket_decode ( tcp ) ;
break ;
# endif
# endif /* LINUX */
# ifdef SVR4
# ifdef SYS_pgrpsys_subcall
case SYS_pgrpsys :
decode_subcall ( tcp , SYS_pgrpsys_subcall ,
SYS_pgrpsys_nsubcalls , shift_style ) ;
break ;
# endif /* SYS_pgrpsys_subcall */
# ifdef SYS_sigcall_subcall
case SYS_sigcall :
decode_subcall ( tcp , SYS_sigcall_subcall ,
SYS_sigcall_nsubcalls , mask_style ) ;
break ;
# endif /* SYS_sigcall_subcall */
case SYS_msgsys :
decode_subcall ( tcp , SYS_msgsys_subcall ,
SYS_msgsys_nsubcalls , shift_style ) ;
break ;
case SYS_shmsys :
decode_subcall ( tcp , SYS_shmsys_subcall ,
SYS_shmsys_nsubcalls , shift_style ) ;
break ;
case SYS_semsys :
decode_subcall ( tcp , SYS_semsys_subcall ,
SYS_semsys_nsubcalls , shift_style ) ;
break ;
#if 0 /* broken */
case SYS_utssys :
decode_subcall ( tcp , SYS_utssys_subcall ,
SYS_utssys_nsubcalls , shift_style ) ;
break ;
# endif
case SYS_sysfs :
decode_subcall ( tcp , SYS_sysfs_subcall ,
SYS_sysfs_nsubcalls , shift_style ) ;
break ;
case SYS_spcall :
decode_subcall ( tcp , SYS_spcall_subcall ,
SYS_spcall_nsubcalls , shift_style ) ;
break ;
# ifdef SYS_context_subcall
case SYS_context :
decode_subcall ( tcp , SYS_context_subcall ,
SYS_context_nsubcalls , shift_style ) ;
break ;
# endif /* SYS_context_subcall */
1999-06-11 17:18:40 +04:00
# ifdef SYS_door_subcall
case SYS_door :
decode_subcall ( tcp , SYS_door_subcall ,
SYS_door_nsubcalls , door_style ) ;
break ;
# endif /* SYS_door_subcall */
2001-03-06 18:08:09 +03:00
# ifdef SYS_kaio_subcall
case SYS_kaio :
decode_subcall ( tcp , SYS_kaio_subcall ,
SYS_kaio_nsubcalls , shift_style ) ;
break ;
2001-10-10 03:47:38 +04:00
# endif
1999-02-19 03:21:36 +03:00
# endif /* SVR4 */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
case SYS_msgsys :
case SYS_shmsys :
case SYS_semsys :
decode_subcall ( tcp , 0 , 0 , table_style ) ;
break ;
2001-10-10 03:47:38 +04:00
# endif
1999-02-19 03:21:36 +03:00
# ifdef SUNOS4
case SYS_semsys :
decode_subcall ( tcp , SYS_semsys_subcall ,
SYS_semsys_nsubcalls , shift_style ) ;
break ;
case SYS_msgsys :
decode_subcall ( tcp , SYS_msgsys_subcall ,
SYS_msgsys_nsubcalls , shift_style ) ;
break ;
case SYS_shmsys :
decode_subcall ( tcp , SYS_shmsys_subcall ,
SYS_shmsys_nsubcalls , shift_style ) ;
break ;
# endif
}
internal_syscall ( tcp ) ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & ! ( qual_flags [ tcp - > scno ] & QUAL_TRACE ) ) {
1999-02-19 03:21:36 +03:00
tcp - > flags | = TCB_INSYSCALL ;
return 0 ;
}
if ( cflag ) {
gettimeofday ( & tcp - > etime , NULL ) ;
tcp - > flags | = TCB_INSYSCALL ;
return 0 ;
}
printleader ( tcp ) ;
tcp - > flags & = ~ TCB_REPRINT ;
tcp_last = tcp ;
2000-09-02 01:03:06 +04:00
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 )
1999-02-19 03:21:36 +03:00
tprintf ( " syscall_%lu( " , tcp - > scno ) ;
else
tprintf ( " %s( " , sysent [ tcp - > scno ] . sys_name ) ;
2002-12-16 02:58:31 +03:00
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 | |
1999-02-19 03:21:36 +03:00
( ( qual_flags [ tcp - > scno ] & QUAL_RAW ) & & tcp - > scno ! = SYS_exit ) )
sys_res = printargs ( tcp ) ;
else
sys_res = ( * sysent [ tcp - > scno ] . sys_func ) ( tcp ) ;
if ( fflush ( tcp - > outf ) = = EOF )
return - 1 ;
tcp - > flags | = TCB_INSYSCALL ;
/* Measure the entrance time as late as possible to avoid errors. */
if ( dtime )
gettimeofday ( & tcp - > etime , NULL ) ;
return sys_res ;
}
int
printargs ( tcp )
struct tcb * tcp ;
{
if ( entering ( tcp ) ) {
int i ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
tprintf ( " %s%#lx " , i ? " , " : " " , tcp - > u_arg [ i ] ) ;
}
return 0 ;
}
long
getrval2 ( tcp )
struct tcb * tcp ;
{
long val = - 1 ;
# ifdef LINUX
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# if defined (SPARC) || defined (SPARC64)
1999-08-30 03:15:07 +04:00
struct regs regs ;
1999-02-19 03:21:36 +03:00
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , ( char * ) & regs , 0 ) < 0 )
return - 1 ;
1999-08-30 03:15:07 +04:00
val = regs . r_o1 ;
2003-03-31 05:05:01 +04:00
# elif defined(SH)
if ( upeek ( tcp - > pid , 4 * ( REG_REG0 + 1 ) , & val ) < 0 )
return - 1 ;
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# endif /* SPARC || SPARC64 */
2004-03-01 23:30:48 +03:00
# elif defined(IA64)
if ( upeek ( tcp - > pid , PT_R9 , & val ) < 0 )
return - 1 ;
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
if ( upeek ( tcp - > pid , uoff ( u_rval2 ) , & val ) < 0 )
return - 1 ;
# endif /* SUNOS4 */
# ifdef SVR4
# ifdef SPARC
1999-08-30 03:15:07 +04:00
val = tcp - > status . PR_REG [ R_O1 ] ;
1999-02-19 03:21:36 +03:00
# endif /* SPARC */
# ifdef I386
1999-08-30 03:15:07 +04:00
val = tcp - > status . PR_REG [ EDX ] ;
1999-02-19 03:21:36 +03:00
# endif /* I386 */
2002-09-23 19:41:01 +04:00
# ifdef X86_64
val = tcp - > status . PR_REG [ RDX ] ;
# endif /* X86_64 */
1999-02-19 03:21:36 +03:00
# ifdef MIPS
1999-08-30 03:15:07 +04:00
val = tcp - > status . PR_REG [ CTX_V1 ] ;
1999-02-19 03:21:36 +03:00
# endif /* MIPS */
# endif /* SVR4 */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
struct reg regs ;
pread ( tcp - > pfd_reg , & regs , sizeof ( regs ) , 0 ) ;
val = regs . r_edx ;
2002-12-16 02:58:31 +03:00
# endif
1999-02-19 03:21:36 +03:00
return val ;
}
/*
* Apparently , indirect system calls have already be converted by ptrace ( 2 ) ,
* so if you see " indir " this program has gone astray .
*/
int
sys_indir ( tcp )
struct tcb * tcp ;
{
int i , scno , nargs ;
if ( entering ( tcp ) ) {
if ( ( scno = tcp - > u_arg [ 0 ] ) > nsyscalls ) {
fprintf ( stderr , " Bogus syscall: %u \n " , scno ) ;
return 0 ;
}
nargs = sysent [ scno ] . nargs ;
tprintf ( " %s " , sysent [ scno ] . sys_name ) ;
for ( i = 0 ; i < nargs ; i + + )
tprintf ( " , %#lx " , tcp - > u_arg [ i + 1 ] ) ;
}
return 0 ;
}
static int
time_cmp ( a , b )
void * a ;
void * b ;
{
2004-09-04 08:20:43 +04:00
return - tv_cmp ( & counts [ * ( ( int * ) a ) ] . time , & counts [ * ( ( int * ) b ) ] . time ) ;
1999-02-19 03:21:36 +03:00
}
static int
syscall_cmp ( a , b )
void * a ;
void * b ;
{
return strcmp ( sysent [ * ( ( int * ) a ) ] . sys_name ,
sysent [ * ( ( int * ) b ) ] . sys_name ) ;
}
static int
count_cmp ( a , b )
void * a ;
void * b ;
{
2004-09-04 08:20:43 +04:00
int m = counts [ * ( ( int * ) a ) ] . calls , n = counts [ * ( ( int * ) b ) ] . calls ;
1999-02-19 03:21:36 +03:00
return ( m < n ) ? 1 : ( m > n ) ? - 1 : 0 ;
}
static int ( * sortfun ) ( ) ;
static struct timeval overhead = { - 1 , - 1 } ;
void
set_sortby ( sortby )
char * sortby ;
{
if ( strcmp ( sortby , " time " ) = = 0 )
sortfun = time_cmp ;
else if ( strcmp ( sortby , " calls " ) = = 0 )
sortfun = count_cmp ;
else if ( strcmp ( sortby , " name " ) = = 0 )
sortfun = syscall_cmp ;
else if ( strcmp ( sortby , " nothing " ) = = 0 )
sortfun = NULL ;
else {
fprintf ( stderr , " invalid sortby: `%s' \n " , sortby ) ;
exit ( 1 ) ;
}
}
void set_overhead ( n )
int n ;
{
overhead . tv_sec = n / 1000000 ;
overhead . tv_usec = n % 1000000 ;
}
void
call_summary ( outf )
FILE * outf ;
{
int i , j ;
int call_cum , error_cum ;
struct timeval tv_cum , dtv ;
double percent ;
char * dashes = " ------------------------- " ;
char error_str [ 16 ] ;
2004-09-04 08:20:43 +04:00
int * sorted_count = malloc ( nsyscalls * sizeof ( int ) ) ;
1999-02-19 03:21:36 +03:00
call_cum = error_cum = tv_cum . tv_sec = tv_cum . tv_usec = 0 ;
if ( overhead . tv_sec = = - 1 ) {
tv_mul ( & overhead , & shortest , 8 ) ;
tv_div ( & overhead , & overhead , 10 ) ;
}
for ( i = 0 ; i < nsyscalls ; i + + ) {
sorted_count [ i ] = i ;
2004-09-04 08:20:43 +04:00
if ( counts = = NULL | | counts [ i ] . calls = = 0 )
1999-02-19 03:21:36 +03:00
continue ;
2004-09-04 08:20:43 +04:00
tv_mul ( & dtv , & overhead , counts [ i ] . calls ) ;
tv_sub ( & counts [ i ] . time , & counts [ i ] . time , & dtv ) ;
call_cum + = counts [ i ] . calls ;
error_cum + = counts [ i ] . errors ;
tv_add ( & tv_cum , & tv_cum , & counts [ i ] . time ) ;
1999-02-19 03:21:36 +03:00
}
if ( sortfun )
qsort ( ( void * ) sorted_count , nsyscalls , sizeof ( int ) , sortfun ) ;
fprintf ( outf , " %6.6s %11.11s %11.11s %9.9s %9.9s %s \n " ,
" % time " , " seconds " , " usecs/call " ,
" calls " , " errors " , " syscall " ) ;
fprintf ( outf , " %6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s \n " ,
dashes , dashes , dashes , dashes , dashes , dashes ) ;
2004-09-04 08:20:43 +04:00
if ( counts ) {
for ( i = 0 ; i < nsyscalls ; i + + ) {
j = sorted_count [ i ] ;
if ( counts [ j ] . calls = = 0 )
continue ;
tv_div ( & dtv , & counts [ j ] . time , counts [ j ] . calls ) ;
if ( counts [ j ] . errors )
sprintf ( error_str , " %d " , counts [ j ] . errors ) ;
else
error_str [ 0 ] = ' \0 ' ;
percent = ( 100.0 * tv_float ( & counts [ j ] . time )
/ tv_float ( & tv_cum ) ) ;
fprintf ( outf , " %6.2f %4ld.%06ld %11ld %9d %9.9s %s \n " ,
percent , ( long ) counts [ j ] . time . tv_sec ,
( long ) counts [ j ] . time . tv_usec ,
( long ) 1000000 * dtv . tv_sec + dtv . tv_usec ,
counts [ j ] . calls ,
error_str , sysent [ j ] . sys_name ) ;
}
1999-02-19 03:21:36 +03:00
}
2004-09-04 08:20:43 +04:00
free ( sorted_count ) ;
1999-02-19 03:21:36 +03:00
fprintf ( outf , " %6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s \n " ,
dashes , dashes , dashes , dashes , dashes , dashes ) ;
if ( error_cum )
sprintf ( error_str , " %d " , error_cum ) ;
else
error_str [ 0 ] = ' \0 ' ;
fprintf ( outf , " %6.6s %4ld.%06ld %11.11s %9d %9.9s %s \n " ,
" 100.00 " , ( long ) tv_cum . tv_sec , ( long ) tv_cum . tv_usec , " " ,
call_cum , error_str , " total " ) ;
2004-09-04 08:20:43 +04:00
1999-02-19 03:21:36 +03:00
}