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>
2009-02-10 19:03:20 +03:00
# include <sched.h>
1999-02-19 03:21:36 +03:00
# 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
2009-02-10 19:03:20 +03: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
2009-02-10 19:03:20 +03:00
# endif
# include <asm / reg.h>
# 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
2009-02-10 19:03:20 +03:00
# endif
1999-08-30 03:15:07 +04:00
# endif
1999-07-14 02:20:16 +04:00
# ifdef HAVE_SYS_REG_H
2009-02-10 19:03:20 +03:00
# include <sys / reg.h>
# ifndef PTRACE_PEEKUSR
# define PTRACE_PEEKUSR PTRACE_PEEKUSER
# endif
2000-02-20 02:59:03 +03:00
# elif defined(HAVE_LINUX_PTRACE_H)
2009-02-10 19:03:20 +03:00
# 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
2009-02-10 19:03:20 +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. */
2005-07-05 07:25:35 +04:00
# define TD TRACE_DESC
1999-02-19 03:21:36 +03:00
# 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 ] ;
2006-01-12 12:50:49 +03:00
int qual_flags0 [ MAX_QUALS ] ;
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 ] ;
2006-01-12 12:50:49 +03:00
int qual_flags1 [ MAX_QUALS ] ;
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 ] ;
2006-01-12 12:50:49 +03:00
int qual_flags2 [ MAX_QUALS ] ;
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 ;
2006-01-12 12:50:49 +03:00
int * qual_flags ;
1999-02-19 03:21:36 +03:00
int nsyscalls ;
/* Now undef them since short defines cause wicked namespace pollution. */
2005-07-05 07:25:35 +04:00
# undef TD
1999-02-19 03:21:36 +03:00
# 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 ;
2006-01-12 13:18:53 +03:00
# ifndef PERSONALITY0_WORDSIZE
# define PERSONALITY0_WORDSIZE sizeof(long)
# endif
const int personality_wordsize [ SUPPORTED_PERSONALITIES ] = {
PERSONALITY0_WORDSIZE ,
# if SUPPORTED_PERSONALITIES > 1
PERSONALITY1_WORDSIZE ,
# endif
# if SUPPORTED_PERSONALITIES > 2
PERSONALITY2_WORDSIZE ,
# endif
} ; ;
1999-02-19 03:21:36 +03:00
int
2006-12-21 01:37:21 +03:00
set_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 ;
2006-01-12 12:50:49 +03:00
qual_flags = qual_flags0 ;
1999-02-19 03:21:36 +03:00
break ;
# if SUPPORTED_PERSONALITIES >= 2
case 1 :
errnoent = errnoent1 ;
nerrnos = nerrnos1 ;
sysent = sysent1 ;
nsyscalls = nsyscalls1 ;
ioctlent = ioctlent1 ;
nioctlents = nioctlents1 ;
signalent = signalent1 ;
nsignals = nsignals1 ;
2006-01-12 12:50:49 +03:00
qual_flags = qual_flags1 ;
1999-02-19 03:21:36 +03:00
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 ;
2006-01-12 12:50:49 +03:00
qual_flags = qual_flags2 ;
1999-02-19 03:21:36 +03:00
break ;
# endif /* SUPPORTED_PERSONALITIES >= 3 */
default :
return - 1 ;
}
current_personality = personality ;
return 0 ;
}
2004-09-04 08:20:43 +04:00
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
2006-01-12 12:50:49 +03:00
qualify_one ( n , opt , not , pers )
2002-12-30 13:23:00 +03:00
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 ;
2006-01-12 12:50:49 +03:00
int pers ;
2002-12-30 13:23:00 +03:00
{
2006-01-12 12:50:49 +03:00
if ( pers = = 0 | | pers < 0 ) {
if ( not )
qual_flags0 [ n ] & = ~ opt - > bitflag ;
else
qual_flags0 [ n ] | = opt - > bitflag ;
}
# if SUPPORTED_PERSONALITIES >= 2
if ( pers = = 1 | | pers < 0 ) {
if ( not )
qual_flags1 [ n ] & = ~ opt - > bitflag ;
else
qual_flags1 [ n ] | = opt - > bitflag ;
}
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
if ( pers = = 2 | | pers < 0 ) {
if ( not )
qual_flags2 [ n ] & = ~ opt - > bitflag ;
else
qual_flags2 [ n ] | = opt - > bitflag ;
}
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2002-12-30 13:23:00 +03:00
}
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 ;
2005-02-02 07:40:11 +03:00
int rc = - 1 ;
1999-02-19 03:21:36 +03:00
2006-01-12 12:45:56 +03:00
if ( isdigit ( ( unsigned char ) * s ) ) {
int i = atoi ( s ) ;
2007-08-23 01:43:30 +04:00
if ( i < 0 | | i > = MAX_QUALS )
2006-01-12 12:45:56 +03:00
return - 1 ;
2006-01-12 12:50:49 +03:00
qualify_one ( i , opt , not , - 1 ) ;
2006-01-12 12:45:56 +03:00
return 0 ;
}
2007-08-23 01:43:30 +04:00
for ( i = 0 ; i < nsyscalls0 ; i + + )
2006-01-12 12:50:49 +03:00
if ( strcmp ( s , sysent0 [ i ] . sys_name ) = = 0 ) {
qualify_one ( i , opt , not , 0 ) ;
rc = 0 ;
}
# if SUPPORTED_PERSONALITIES >= 2
2007-08-23 01:43:30 +04:00
for ( i = 0 ; i < nsyscalls1 ; i + + )
2006-01-12 12:50:49 +03:00
if ( strcmp ( s , sysent1 [ i ] . sys_name ) = = 0 ) {
qualify_one ( i , opt , not , 1 ) ;
2005-02-02 07:40:11 +03:00
rc = 0 ;
2002-12-30 13:23:00 +03:00
}
2006-01-12 12:50:49 +03:00
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
2007-08-23 01:43:30 +04:00
for ( i = 0 ; i < nsyscalls2 ; i + + )
2006-01-12 12:50:49 +03:00
if ( strcmp ( s , sysent2 [ i ] . sys_name ) = = 0 ) {
qualify_one ( i , opt , not , 2 ) ;
rc = 0 ;
}
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2007-08-23 01:43:30 +04:00
2005-02-02 07:40:11 +03:00
return rc ;
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 ] ;
2006-01-12 12:45:56 +03:00
if ( isdigit ( ( unsigned char ) * s ) ) {
2005-02-02 07:40:11 +03:00
int signo = atoi ( s ) ;
if ( signo < 0 | | signo > = MAX_QUALS )
return - 1 ;
2006-01-12 12:50:49 +03:00
qualify_one ( signo , opt , not , - 1 ) ;
2005-02-02 07:40:11 +03:00
return 0 ;
2002-12-30 13:23:00 +03:00
}
2004-03-02 09:52:01 +03:00
if ( strlen ( s ) > = sizeof buf )
2005-02-02 07:40:11 +03:00
return - 1 ;
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 ) {
2006-01-12 12:50:49 +03:00
qualify_one ( i , opt , not , - 1 ) ;
2005-02-02 06:51:18 +03:00
return 0 ;
2002-12-30 13:23:00 +03:00
}
2005-02-02 06:51:18 +03:00
return - 1 ;
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
{
2006-01-12 12:45:56 +03:00
if ( isdigit ( ( unsigned char ) * s ) ) {
2005-02-02 07:40:11 +03:00
int desc = atoi ( s ) ;
if ( desc < 0 | | desc > = MAX_QUALS )
return - 1 ;
2006-01-12 12:50:49 +03:00
qualify_one ( desc , opt , not , - 1 ) ;
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 ;
2005-07-05 07:25:35 +04:00
if ( strcmp ( s , " desc " ) = = 0 )
return TRACE_DESC ;
1999-02-19 03:21:36 +03:00
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 + + ) {
2006-01-12 12:50:49 +03:00
qualify_one ( i , opt , not , - 1 ) ;
1999-02-19 03:21:36 +03:00
}
return ;
}
for ( i = 0 ; i < MAX_QUALS ; i + + ) {
2006-01-12 12:50:49 +03:00
qualify_one ( i , opt , ! not , - 1 ) ;
1999-02-19 03:21:36 +03:00
}
for ( p = strtok ( s , " , " ) ; p ; p = strtok ( NULL , " , " ) ) {
if ( opt - > bitflag = = QUAL_TRACE & & ( n = lookup_class ( p ) ) > 0 ) {
2007-08-23 01:43:30 +04:00
for ( i = 0 ; i < nsyscalls0 ; i + + )
2006-01-12 12:50:49 +03:00
if ( sysent0 [ i ] . sys_flags & n )
qualify_one ( i , opt , not , 0 ) ;
# if SUPPORTED_PERSONALITIES >= 2
2007-08-23 01:43:30 +04:00
for ( i = 0 ; i < nsyscalls1 ; i + + )
2006-01-12 12:50:49 +03:00
if ( sysent1 [ i ] . sys_flags & n )
qualify_one ( i , opt , not , 1 ) ;
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
2007-08-23 01:43:30 +04:00
for ( i = 0 ; i < nsyscalls2 ; i + + )
2006-01-12 12:50:49 +03:00
if ( sysent2 [ i ] . sys_flags & n )
qualify_one ( i , opt , not , 2 ) ;
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2007-08-23 01:43:30 +04:00
1999-02-19 03:21:36 +03:00
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 ;
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
switch ( known_scno ( tcp ) ) {
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 :
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
# elif defined SYS_sub_recv
case SYS_sub_recv :
1999-02-19 03:21:36 +03:00
# endif
# ifdef SYS_recvfrom
case SYS_recvfrom :
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
# elif defined SYS_sub_recvfrom
case SYS_sub_recvfrom :
1999-02-19 03:21:36 +03:00
# 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 :
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
# elif defined SYS_sub_send
case SYS_sub_send :
1999-02-19 03:21:36 +03:00
# endif
# ifdef SYS_sendto
case SYS_sendto :
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
# elif defined SYS_sub_sendto
case SYS_sub_sendto :
1999-02-19 03:21:36 +03:00
# 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
2008-12-30 21:47:55 +03:00
case SYS_readv :
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_READ )
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
break ;
2001-07-10 17:48:44 +04:00
# endif
# ifdef SYS_writev
2008-12-30 21:47:55 +03:00
case SYS_writev :
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_WRITE )
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
break ;
2001-07-10 17:48:44 +04:00
# 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 ] ;
} ;
2005-06-09 00:45:28 +04:00
static const struct subcall subcalls_table [ ] = {
2000-09-02 01:03:06 +04:00
{ 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
2008-12-30 20:50:46 +03:00
# if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__) ))
1999-02-19 03:21:36 +03:00
2005-06-09 00:45:28 +04:00
static 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 ;
{
2006-01-12 13:18:53 +03:00
unsigned long addr , mask ;
2002-10-07 18:31:00 +04:00
int i ;
2006-01-12 13:18:53 +03:00
int size = personality_wordsize [ current_personality ] ;
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 + + ) {
2006-01-12 13:18:53 +03:00
if ( size = = sizeof ( int ) ) {
unsigned int arg ;
if ( umove ( tcp , addr , & arg ) < 0 )
arg = 0 ;
tcp - > u_arg [ i ] = arg ;
}
else if ( size = = sizeof ( long ) ) {
unsigned long arg ;
if ( umove ( tcp , addr , & arg ) < 0 )
arg = 0 ;
tcp - > u_arg [ i ] = arg ;
}
else
abort ( ) ;
addr + = size ;
1999-02-19 03:21:36 +03:00
}
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
2006-12-21 14:44:28 +03:00
internal_syscall ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
/*
* We must always trace a few critical system calls in order to
* correctly support following forks in the presence of tracing
* qualifiers .
*/
2006-12-21 14:44:28 +03:00
int ( * func ) ( ) ;
1999-02-19 03:21:36 +03:00
2006-12-21 14:44:28 +03:00
if ( tcp - > scno < 0 | | tcp - > scno > = nsyscalls )
return 0 ;
func = sysent [ tcp - > scno ] . sys_func ;
if ( sys_exit = = func )
return internal_exit ( tcp ) ;
if ( sys_fork = = func
# if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
| | sys_vfork = = func
1999-02-19 03:21:36 +03:00
# endif
2006-12-21 14:44:28 +03:00
# if UNIXWARE > 2
| | sys_rfork = = func
2001-10-10 03:47:38 +04:00
# endif
2006-12-21 14:44:28 +03:00
)
return internal_fork ( tcp ) ;
# if defined(LINUX) && (defined SYS_clone || defined SYS_clone2)
if ( sys_clone = = func )
return internal_clone ( tcp ) ;
1999-02-19 03:21:36 +03:00
# endif
2006-12-21 14:44:28 +03:00
if ( sys_execve = = func
# if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
| | sys_execv = = func
1999-02-19 03:21:36 +03:00
# endif
2006-12-21 14:44:28 +03:00
# if UNIXWARE > 2
| | sys_rexecve = = func
2004-09-01 23:39:46 +04:00
# endif
2006-12-21 14:44:28 +03:00
)
return internal_exec ( tcp ) ;
1999-02-19 03:21:36 +03:00
2006-12-21 14:44:28 +03:00
if ( sys_waitpid = = func
| | sys_wait4 = = func
# if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
| | sys_wait = = func
2003-01-09 09:53:27 +03:00
# endif
2006-12-21 14:44:28 +03:00
# ifdef ALPHA
| | sys_osf_wait4 = = func
2004-02-21 01:56:43 +03:00
# endif
2006-12-21 14:44:28 +03:00
)
return internal_wait ( tcp , 2 ) ;
# if defined(LINUX) || defined(SVR4)
if ( sys_waitid = = func )
return internal_wait ( tcp , 3 ) ;
1999-02-19 03:21:36 +03:00
# endif
2006-12-21 14:44:28 +03:00
1999-02-19 03:21:36 +03:00
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 ;
2008-11-11 01:21:41 +03:00
# elif defined(BFIN)
static long r0 ;
2000-04-11 02:22:31 +04:00
# 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 ;
2008-05-20 05:11:56 +04:00
# elif defined(LINUX_MIPSN32)
static long long a3 ;
static long long r2 ;
2000-04-11 02:22:31 +04:00
# 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)
2008-12-30 21:47:55 +03:00
static long r0 ;
2003-06-27 02:40:42 +04:00
# elif defined(SH64)
2008-12-30 21:47:55 +03:00
static long r9 ;
2002-09-23 19:41:01 +04:00
# elif defined(X86_64)
2008-12-30 21:47:55 +03:00
static long rax ;
2009-02-25 20:08:40 +03:00
# elif defined(CRISV10) || defined(CRISV32)
static long r10 ;
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
2009-01-23 19:30:26 +03:00
get_scno ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
long scno = 0 ;
# ifdef LINUX
2009-02-25 20:08:40 +03: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
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_GPR2 , & syscall_mode ) < 0 )
2003-06-27 02:23:28 +04:00
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
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_PSWADDR , & pc ) < 0 )
2002-11-11 15:50:47 +03:00
return - 1 ;
2003-01-20 13:23:04 +03:00
errno = 0 ;
2009-01-23 19:30:26 +03:00
opcode = ptrace ( PTRACE_PEEKTEXT , tcp - > 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 ;
2008-12-16 21:18:40 +03:00
if ( offset_reg & & ( upeek ( tcp , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
2002-11-11 15:50:47 +03:00
return - 1 ;
svc_addr + = tmp ;
tmp = 0 ;
offset_reg = ( opcode & 0x0000f000 ) > > 12 ;
2008-12-16 21:18:40 +03:00
if ( offset_reg & & ( upeek ( tcp , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
2002-11-11 15:50:47 +03:00
return - 1 ;
svc_addr + = tmp ;
2009-01-23 19:30:26 +03:00
scno = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , svc_addr , 0 ) ;
2002-11-11 15:50:47 +03:00
if ( errno )
return - 1 ;
2009-02-25 20:08:40 +03:00
# if defined(S390X)
2002-11-11 15:50:47 +03:00
scno > > = 48 ;
2009-02-25 20:08:40 +03:00
# else
2002-11-11 15:50:47 +03:00
scno > > = 16 ;
2009-02-25 20:08:40 +03:00
# endif
2002-11-11 15:50:47 +03:00
tmp = 0 ;
offset_reg = ( opcode & 0x00f00000 ) > > 20 ;
2008-12-16 21:18:40 +03:00
if ( offset_reg & & ( upeek ( tcp , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
2002-11-11 15:50:47 +03:00
return - 1 ;
scno = ( scno | tmp ) & 0xff ;
}
}
2009-02-25 20:08:40 +03:00
# elif defined (POWERPC)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 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 ;
}
}
2009-02-25 20:08:40 +03:00
# elif defined(BFIN)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_ORIG_P0 , & scno ) )
2008-11-11 01:21:41 +03:00
return - 1 ;
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE & & tcp - > flags & TCB_INSYSCALL )
tcp - > flags & = ~ ( TCB_INSYSCALL | TCB_WAITEXECVE ) ;
2009-02-25 20:08:40 +03:00
# elif defined (I386)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 4 * ORIG_EAX , & scno ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined (X86_64)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 8 * ORIG_RAX , & scno ) < 0 )
2002-09-23 19:41:01 +04:00
return - 1 ;
2002-12-16 02:58:31 +03:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2009-01-02 21:10:08 +03:00
static int currpers = - 1 ;
2002-09-23 19:41:01 +04:00
long val ;
2009-01-23 19:30:26 +03:00
int pid = tcp - > pid ;
2002-09-23 19:41:01 +04:00
/* 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 .
*/
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 8 * CS , & val ) < 0 )
2002-09-23 19:41:01 +04:00
return - 1 ;
2009-01-02 21:10:08 +03:00
switch ( val ) {
2002-09-23 19:41:01 +04:00
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 ;
}
2009-02-25 20:08:40 +03:00
# if 0
2002-09-23 19:41:01 +04:00
/* 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 ;
2009-01-02 21:10:08 +03:00
if ( upeek ( tcp , 8 * RIP , & rip ) < 0 )
2002-09-23 19:41:01 +04:00
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 */
2009-01-02 21:10:08 +03:00
rip - = 2 ;
2002-09-23 19:41:01 +04:00
errno = 0 ;
2009-01-02 21:10:08 +03:00
call = ptrace ( PTRACE_PEEKTEXT , pid , ( char * ) rip , ( char * ) 0 ) ;
2002-12-16 02:58:31 +03:00
if ( errno )
printf ( " ptrace_peektext failed: %s \n " ,
2002-09-23 19:41:01 +04:00
strerror ( errno ) ) ;
2009-01-02 21:10:08 +03:00
switch ( call & 0xffff ) {
2002-09-23 19:41:01 +04:00
/* 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 ;
}
2009-02-25 20:08:40 +03:00
# endif
2009-01-02 21:10:08 +03:00
if ( currpers ! = current_personality ) {
static const char * const names [ ] = { " 64 bit " , " 32 bit " } ;
2002-09-23 19:41:01 +04:00
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
}
2009-02-25 20:08:40 +03:00
# elif defined(IA64)
2001-10-10 03:47:38 +04:00
# define IA64_PSR_IS ((long)1 << 34)
2009-01-17 04:06:18 +03:00
if ( upeek ( tcp , 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 ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_R1 , & scno ) < 0 ) /* orig eax */
2000-02-04 00:58:30 +03:00
return - 1 ;
} else {
2009-01-17 04:06:18 +03:00
if ( upeek ( tcp , PT_R15 , & scno ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
}
2003-03-05 09:29:06 +03:00
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
2009-02-25 20:08:40 +03:00
# if defined PTRACE_GETSIGINFO
2009-01-17 04:06:18 +03:00
siginfo_t si ;
tcp - > flags & = ~ TCB_WAITEXECVE ;
/* If SIGTRAP is masked, execve's magic SIGTRAP
* is not delivered . We end up here on a subsequent
* ptrace stop instead . Luckily , we can check
* for the type of this SIGTRAP . execve ' s magic one
* has 0 ( SI_USER ) in si . si_code , ptrace stop has 5.
* ( I don ' t know why 5 ) .
*/
si . si_code = SI_USER ;
/* If PTRACE_GETSIGINFO fails, we assume it's
* magic SIGTRAP . Moot anyway , PTRACE_GETSIGINFO
* doesn ' t fail .
*/
2009-01-23 19:30:26 +03:00
ptrace ( PTRACE_GETSIGINFO , tcp - > pid , ( void * ) 0 , ( void * ) & si ) ;
2009-01-17 04:06:18 +03:00
if ( si . si_code = = SI_USER )
return 0 ;
2009-02-25 20:08:40 +03:00
# else
2003-03-05 09:29:06 +03:00
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
2009-02-25 20:08:40 +03:00
# endif
2003-03-05 09:29:06 +03:00
}
2000-02-04 00:58:30 +03:00
} else {
/* syscall in progress */
2009-01-17 04:06:18 +03:00
if ( upeek ( tcp , PT_R8 , & r8 ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
2009-01-17 04:06:18 +03:00
if ( upeek ( tcp , PT_R10 , & r10 ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
}
2009-02-25 20:08:40 +03:00
# elif defined (ARM)
2003-06-04 03:29:04 +04:00
/*
* Read complete register set in one go .
*/
2009-01-23 19:30:26 +03:00
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , NULL , ( void * ) & regs ) = = - 1 )
2003-06-04 03:29:04 +04:00
return - 1 ;
/*
* We only need to grab the syscall number on syscall entry .
*/
if ( regs . ARM_ip = = 0 ) {
2007-11-02 00:42:18 +03:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2003-06-04 03:29:04 +04:00
/*
* 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 ;
2009-01-23 19:30:26 +03:00
scno = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( void * ) ( regs . ARM_pc - 4 ) , NULL ) ;
2003-06-04 03:29:04 +04:00
if ( errno )
return - 1 ;
if ( scno = = 0 & & ( tcp - > flags & TCB_WAITEXECVE ) ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
2006-04-25 11:34:41 +04:00
/* Handle the EABI syscall convention. We do not
bother converting structures between the two
ABIs , but basic functionality should work even
if strace and the traced program have different
ABIs . */
if ( scno = = 0xef000000 ) {
scno = regs . ARM_r7 ;
} else {
if ( ( scno & 0x0ff00000 ) ! = 0x0f900000 ) {
fprintf ( stderr , " syscall: unknown syscall trap 0x%08lx \n " ,
scno ) ;
return - 1 ;
}
/*
* Fixup the syscall number
*/
scno & = 0x000fffff ;
2003-06-04 03:29:04 +04:00
}
}
2008-05-20 05:35:55 +04:00
if ( scno & 0x0f0000 ) {
/*
* Handle ARM specific syscall
*/
set_personality ( 1 ) ;
scno & = 0x0000ffff ;
} else
set_personality ( 0 ) ;
2003-06-04 03:29:04 +04:00
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
}
2009-02-25 20:08:40 +03:00
# elif defined (M68K)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 4 * PT_ORIG_D0 , & scno ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined (LINUX_MIPSN32)
2008-05-20 05:11:56 +04:00
unsigned long long regs [ 38 ] ;
2009-02-24 18:17:53 +03:00
if ( do_ptrace ( PTRACE_GETREGS , tcp , NULL , ( long ) & regs ) < 0 )
2008-05-20 05:11:56 +04:00
return - 1 ;
a3 = regs [ REG_A3 ] ;
r2 = regs [ REG_V0 ] ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
scno = r2 ;
/* Check if we return from execve. */
if ( scno = = 0 & & tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
if ( scno < 0 | | scno > nsyscalls ) {
if ( a3 = = 0 | | a3 = = - 1 ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
return 0 ;
}
}
}
2009-02-25 20:08:40 +03:00
# elif defined (MIPS)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_A3 , & a3 ) < 0 )
1999-11-01 00:15:38 +03:00
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_V0 , & scno ) < 0 )
1999-11-01 00:15:38 +03:00
return - 1 ;
2008-05-20 05:11:56 +04:00
/* Check if we return from execve. */
if ( scno = = 0 & & tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
1999-11-01 00:15:38 +03:00
if ( scno < 0 | | scno > nsyscalls ) {
if ( a3 = = 0 | | a3 = = - 1 ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
return 0 ;
}
}
} else {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_V0 , & r2 ) < 0 )
1999-11-01 00:15:38 +03:00
return - 1 ;
}
2009-02-25 20:08:40 +03:00
# elif defined (ALPHA)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_A3 , & a3 ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_R0 , & scno ) < 0 )
1999-02-19 03:21:36 +03:00
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 {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_R0 , & r0 ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
}
2009-02-25 20:08:40 +03:00
# elif defined (SPARC) || defined (SPARC64)
1999-02-19 03:21:36 +03:00
/* Everything we need is in the current register set. */
2009-01-23 19:30:26 +03:00
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , ( char * ) & regs , 0 ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2008-12-30 21:47:55 +03:00
/* If we are entering, then disassemble the syscall trap. */
1999-02-19 03:21:36 +03:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Retrieve the syscall trap instruction. */
errno = 0 ;
2009-01-23 19:30:26 +03:00
trap = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) regs . r_pc , 0 ) ;
2009-02-25 20:08:40 +03:00
# if defined(SPARC64)
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
trap > > = 32 ;
2009-02-25 20:08:40 +03:00
# 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 ;
}
2009-02-25 20:08:40 +03:00
# if defined (SPARC64)
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
fprintf ( stderr , " syscall: unknown syscall trap %08lx %016lx \n " , trap , regs . r_tpc ) ;
2009-02-25 20:08:40 +03:00
# else
1999-08-30 03:15:07 +04:00
fprintf ( stderr , " syscall: unknown syscall trap %08x %08x \n " , trap , regs . r_pc ) ;
2009-02-25 20:08:40 +03: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
}
}
2009-02-25 20:08:40 +03:00
# elif defined(HPPA)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_GR20 , & scno ) < 0 )
2001-03-27 16:17:16 +04:00
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( ( tcp - > flags & TCB_WAITEXECVE ) ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2009-02-25 20:08:40 +03:00
# elif defined(SH)
2008-12-30 21:47:55 +03:00
/*
* In the new syscall ABI , the system call number is in R3 .
*/
if ( upeek ( tcp , 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 ,
" Detected glibc bug: bogus system call "
" number = %ld, correcting to %ld \n " ,
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 ;
}
}
2009-02-25 20:08:40 +03:00
# elif defined(SH64)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_SYSCALL , & scno ) < 0 )
2003-06-02 23:18:58 +04:00
return - 1 ;
2008-12-30 21:47:55 +03:00
scno & = 0xFFFF ;
2003-06-02 23:18:58 +04:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2009-02-25 20:08:40 +03:00
# elif defined(CRISV10) || defined(CRISV32)
if ( upeek ( tcp , 4 * PT_R9 , & scno ) < 0 )
return - 1 ;
# endif
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
2009-02-25 20:08:40 +03:00
1999-02-19 03:21:36 +03:00
# ifdef SUNOS4
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , uoff ( u_arg [ 7 ] ) , & scno ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2002-05-01 20:39:22 +04:00
# elif defined(SH)
2008-12-30 21:47:55 +03:00
/* new syscall ABI returns result in R0 */
if ( upeek ( tcp , 4 * REG_REG0 , ( long * ) & r0 ) < 0 )
return - 1 ;
2003-06-27 02:40:42 +04:00
# elif defined(SH64)
2008-12-30 21:47:55 +03:00
/* ABI defines result returned in r9 */
if ( upeek ( tcp , REG_GENERAL ( 9 ) , ( long * ) & r9 ) < 0 )
return - 1 ;
1999-02-19 03:21:36 +03:00
# endif
2009-02-25 20:08:40 +03:00
2000-09-02 01:03:06 +04:00
# ifdef USE_PROCFS
2009-02-25 20:08:40 +03:00
# ifdef HAVE_PR_SYSCALL
2001-03-06 13:10:06 +03:00
scno = tcp - > status . PR_SYSCALL ;
2009-02-25 20:08:40 +03:00
# else
# ifndef FREEBSD
1999-08-30 03:15:07 +04:00
scno = tcp - > status . PR_WHAT ;
2009-02-25 20:08:40 +03:00
# else
2000-09-02 01:03:06 +04:00
if ( pread ( tcp - > pfd_reg , & regs , sizeof ( regs ) , 0 ) < 0 ) {
2008-12-30 21:47:55 +03:00
perror ( " pread " ) ;
return - 1 ;
}
2000-09-02 01:03:06 +04:00
switch ( regs . r_eax ) {
case SYS_syscall :
case SYS___syscall :
2008-12-30 21:47:55 +03:00
pread ( tcp - > pfd , & scno , sizeof ( scno ) , regs . r_esp + sizeof ( int ) ) ;
break ;
2000-09-02 01:03:06 +04:00
default :
2008-12-30 21:47:55 +03:00
scno = regs . r_eax ;
break ;
2000-09-02 01:03:06 +04:00
}
2009-02-25 20:08:40 +03:00
# endif /* FREEBSD */
# endif /* !HAVE_PR_SYSCALL */
2000-09-02 01:03:06 +04:00
# endif /* USE_PROCFS */
2009-02-25 20:08:40 +03:00
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 ;
}
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
long
known_scno ( tcp )
struct tcb * tcp ;
{
long scno = tcp - > scno ;
if ( scno > = 0 & & scno < nsyscalls & & sysent [ scno ] . native_scno ! = 0 )
scno = sysent [ scno ] . native_scno ;
else
scno + = NR_SYSCALL_BASE ;
return scno ;
}
2009-02-24 18:17:53 +03:00
/* Called in trace_syscall at each syscall entry and exit.
2009-01-02 21:02:45 +03:00
* Returns :
2009-02-24 18:17:53 +03:00
* 0 : " ignore this syscall " , bail out of trace_syscall silently .
* 1 : ok , continue in trace_syscall .
* other : error , trace_syscall should print error indicator
2009-01-02 21:02:45 +03:00
* ( " ???? " etc ) and bail out .
*/
2005-06-09 00:45:28 +04:00
static int
2009-02-25 20:08:40 +03:00
syscall_fixup ( struct tcb * tcp )
2000-02-01 20:58:41 +03:00
{
2008-12-16 21:18:40 +03:00
# ifdef USE_PROCFS
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
int scno = known_scno ( tcp ) ;
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)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 4 * EAX , & eax ) < 0 )
1999-02-19 03:21:36 +03:00
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)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 8 * RAX , & rax ) < 0 )
2002-09-23 19:41:01 +04:00
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)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_GPR2 , & gpr2 ) < 0 )
2000-02-14 19:23:40 +03:00
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
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , sizeof ( unsigned long ) * PT_CCR , & flags ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 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)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 4 * PT_D0 , & d0 ) < 0 )
1999-02-19 03:21:36 +03:00
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
*/
2008-11-11 01:21:41 +03:00
# elif defined(BFIN)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_R0 , & r0 ) < 0 )
2008-11-11 01:21:41 +03:00
return - 1 ;
2001-03-27 16:17:16 +04:00
# elif defined (HPPA)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_GR28 , & r28 ) < 0 )
2001-03-27 16:17:16 +04:00
return - 1 ;
2001-10-10 03:47:38 +04:00
# elif defined(IA64)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_R10 , & r10 ) < 0 )
2001-10-10 03:47:38 +04:00
return - 1 ;
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_R8 , & r8 ) < 0 )
2001-10-10 03:47:38 +04:00
return - 1 ;
if ( ia32 & & r8 ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: r8 = %ld \n " , r8 ) ;
return 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(CRISV10) || defined(CRISV32)
if ( upeek ( tcp - > pid , 4 * PT_R10 , & r10 ) < 0 )
return - 1 ;
if ( r10 ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: r10 = %ld \n " , r10 ) ;
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
2008-05-28 03:18:29 +04:00
# ifdef LINUX
/*
* Check the syscall return value register value for whether it is
* a negated errno code indicating an error , or a success return value .
*/
static inline int
is_negated_errno ( unsigned long int val )
{
unsigned long int max = - ( long int ) nerrnos ;
if ( personality_wordsize [ current_personality ] < sizeof ( val ) ) {
val = ( unsigned int ) val ;
max = ( unsigned int ) max ;
}
return val > max ;
}
# endif
2005-06-09 00:45:28 +04:00
static int
2009-02-25 20:08:40 +03:00
get_error ( struct tcb * tcp )
2000-02-01 20:58:41 +03:00
{
int u_error = 0 ;
1999-02-19 03:21:36 +03:00
# ifdef LINUX
2009-02-25 20:08:40 +03:00
# if defined(S390) || defined(S390X)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( gpr2 ) ) {
tcp - > u_rval = - 1 ;
u_error = - gpr2 ;
}
else {
tcp - > u_rval = gpr2 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(I386)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( eax ) ) {
tcp - > u_rval = - 1 ;
u_error = - eax ;
}
else {
tcp - > u_rval = eax ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(X86_64)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( rax ) ) {
tcp - > u_rval = - 1 ;
u_error = - rax ;
}
else {
tcp - > u_rval = rax ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(IA64)
2008-05-28 03:18:29 +04:00
if ( ia32 ) {
int err ;
err = ( int ) r8 ;
if ( is_negated_errno ( err ) ) {
2002-09-23 19:41:01 +04:00
tcp - > u_rval = - 1 ;
2008-05-28 03:18:29 +04:00
u_error = - err ;
2002-09-23 19:41:01 +04:00
}
else {
2008-05-28 03:18:29 +04:00
tcp - > u_rval = err ;
2002-09-23 19:41:01 +04:00
u_error = 0 ;
}
2008-05-28 03:18:29 +04:00
} else {
if ( r10 ) {
tcp - > u_rval = - 1 ;
u_error = r8 ;
2000-02-04 00:58:30 +03:00
} else {
2008-05-28 03:18:29 +04:00
tcp - > u_rval = r8 ;
u_error = 0 ;
2000-02-04 00:58:30 +03:00
}
2008-05-28 03:18:29 +04:00
}
2009-02-25 20:08:40 +03:00
# elif defined(MIPS)
1999-11-01 00:15:38 +03:00
if ( a3 ) {
tcp - > u_rval = - 1 ;
u_error = r2 ;
} else {
tcp - > u_rval = r2 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(POWERPC)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( result ) ) {
1999-02-19 03:21:36 +03:00
tcp - > u_rval = - 1 ;
u_error = - result ;
}
else {
tcp - > u_rval = result ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(M68K)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( d0 ) ) {
1999-02-19 03:21:36 +03:00
tcp - > u_rval = - 1 ;
u_error = - d0 ;
}
else {
tcp - > u_rval = d0 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(ARM)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( regs . ARM_r0 ) ) {
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 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(BFIN)
2008-11-11 01:21:41 +03:00
if ( is_negated_errno ( r0 ) ) {
tcp - > u_rval = - 1 ;
u_error = - r0 ;
} else {
tcp - > u_rval = r0 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(ALPHA)
1999-02-19 03:21:36 +03:00
if ( a3 ) {
tcp - > u_rval = - 1 ;
u_error = r0 ;
}
else {
tcp - > u_rval = r0 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(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 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(SPARC64)
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 ( regs . r_tstate & 0x1100000000UL ) {
tcp - > u_rval = - 1 ;
u_error = regs . r_o0 ;
}
else {
tcp - > u_rval = regs . r_o0 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(HPPA)
2008-05-28 03:18:29 +04:00
if ( is_negated_errno ( r28 ) ) {
2001-03-27 16:17:16 +04:00
tcp - > u_rval = - 1 ;
u_error = - r28 ;
}
else {
tcp - > u_rval = r28 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(SH)
2008-05-28 03:18:29 +04:00
/* interpret R0 as return value or error number */
if ( is_negated_errno ( r0 ) ) {
tcp - > u_rval = - 1 ;
u_error = - r0 ;
}
else {
tcp - > u_rval = r0 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(SH64)
2008-12-30 21:47:55 +03:00
/* interpret result as return value or error number */
if ( is_negated_errno ( r9 ) ) {
tcp - > u_rval = - 1 ;
u_error = - r9 ;
}
else {
tcp - > u_rval = r9 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(CRISV10) || defined(CRISV32)
if ( r10 & & ( unsigned ) - r10 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - r10 ;
}
else {
tcp - > u_rval = r10 ;
u_error = 0 ;
}
# endif
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
/* get error code from user struct */
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , uoff ( u_error ) , & u_error ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
u_error > > = 24 ; /* u_error is a char */
/* get system call return value */
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , uoff ( u_rval1 ) , & tcp - > u_rval ) < 0 )
1999-02-19 03:21:36 +03:00
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
2009-02-25 20:08:40 +03:00
# if defined(S390) || defined(S390X)
2002-12-22 02:25:18 +03:00
gpr2 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) PT_GPR2 , gpr2 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(I386)
2002-12-22 02:25:18 +03:00
eax = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( EAX * 4 ) , eax ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(X86_64)
2002-12-22 02:25:18 +03:00
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 ;
2009-02-25 20:08:40 +03:00
# elif defined(IA64)
2002-12-22 02:25:18 +03:00
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 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(BFIN)
2008-11-11 01:21:41 +03:00
r0 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) PT_R0 , r0 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(MIPS)
2002-12-22 02:25:18 +03:00
if ( error ) {
r2 = error ;
a3 = - 1 ;
}
else {
r2 = rval ;
a3 = 0 ;
}
2008-05-20 05:11:56 +04:00
/* PTRACE_POKEUSER is OK even for n32 since rval is only a long. */
2002-12-22 02:25:18 +03:00
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( REG_A3 ) , a3 ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( REG_V0 ) , r2 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(POWERPC)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 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 ;
2009-02-25 20:08:40 +03:00
# elif defined(M68K)
2002-12-22 02:25:18 +03:00
d0 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( 4 * PT_D0 ) , d0 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(ARM)
2008-12-30 21:47:55 +03: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 ;
2009-02-25 20:08:40 +03:00
# elif defined(ALPHA)
2002-12-22 02:25:18 +03:00
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 ;
2009-02-25 20:08:40 +03:00
# elif defined(SPARC)
2002-12-22 02:25:18 +03:00
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 ;
2009-02-25 20:08:40 +03:00
# elif defined(SPARC64)
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 ( 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 ;
2009-02-25 20:08:40 +03:00
# elif defined(HPPA)
2002-12-22 02:25:18 +03:00
r28 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( PT_GR28 ) , r28 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(SH)
2002-12-22 02:25:18 +03:00
r0 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) ( 4 * REG_REG0 ) , r0 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# elif defined(SH64)
2008-12-30 21:47:55 +03:00
r9 = error ? - error : rval ;
2003-06-02 23:18:58 +04:00
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) REG_GENERAL ( 9 ) , r9 ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# endif
2002-12-22 02:25:18 +03:00
# endif /* LINUX */
2009-02-25 20:08:40 +03:00
2002-12-22 02:25:18 +03:00
# ifdef SUNOS4
2009-02-24 18:17:53 +03:00
if ( do_ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) uoff ( u_error ) , error < < 24 ) < 0
| | do_ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) uoff ( u_rval1 ) , rval ) < 0
) {
2002-12-22 02:25:18 +03:00
return - 1 ;
2009-02-24 18:17:53 +03:00
}
2002-12-22 02:25:18 +03:00
# endif /* SUNOS4 */
2009-02-25 20:08:40 +03:00
2002-12-22 02:25:18 +03:00
# ifdef SVR4
/* XXX no clue */
return - 1 ;
# endif /* SVR4 */
2009-02-25 20:08:40 +03:00
2002-12-22 02:25:18 +03:00
# ifdef FREEBSD
if ( pread ( tcp - > pfd_reg , & regs , sizeof ( regs ) , 0 ) < 0 ) {
2008-12-30 21:47:55 +03:00
perror ( " pread " ) ;
return - 1 ;
}
2002-12-22 02:25:18 +03:00
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 ) {
2008-12-30 21:47:55 +03:00
perror ( " pwrite " ) ;
return - 1 ;
}
2002-12-22 02:25:18 +03:00
# endif /* FREEBSD */
/* All branches reach here on success (only). */
tcp - > u_error = error ;
tcp - > u_rval = rval ;
return 0 ;
}
2005-06-09 00:45:28 +04:00
static int
2009-02-25 20:08:40 +03:00
syscall_enter ( struct tcb * tcp )
2000-02-01 20:58:41 +03:00
{
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 + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 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 !
*/
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
}
}
2000-02-04 00:58:30 +03:00
# elif defined (IA64)
{
2001-10-10 03:47:38 +04:00
if ( ! ia32 ) {
2008-08-07 01:38:52 +04:00
unsigned long * out0 , cfm , sof , sol , i ;
long rbs_end ;
2001-10-10 03:47:38 +04:00
/* be backwards compatible with kernel < 2.4.4... */
# ifndef PT_RBS_END
# define PT_RBS_END PT_AR_BSP
# endif
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_RBS_END , & rbs_end ) < 0 )
2001-10-10 03:47:38 +04:00
return - 1 ;
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_CFM , ( long * ) & cfm ) < 0 )
2001-10-10 03:47:38 +04:00
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 ;
2008-08-07 01:38:52 +04:00
out0 = ia64_rse_skip_regs ( ( unsigned long * ) 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 */
2008-12-16 21:18:40 +03:00
upeek ( tcp , PT_R11 , ( long * ) & tcp - > u_arg [ 0 ] ) < 0
2001-10-10 03:47:38 +04:00
/* ECX = out1 */
2008-12-16 21:18:40 +03:00
| | upeek ( tcp , PT_R9 , ( long * ) & tcp - > u_arg [ 1 ] ) < 0
2001-10-10 03:47:38 +04:00
/* EDX = out2 */
2008-12-16 21:18:40 +03:00
| | upeek ( tcp , PT_R10 , ( long * ) & tcp - > u_arg [ 2 ] ) < 0
2001-10-10 03:47:38 +04:00
/* ESI = out3 */
2008-12-16 21:18:40 +03:00
| | upeek ( tcp , PT_R14 , ( long * ) & tcp - > u_arg [ 3 ] ) < 0
2001-10-10 03:47:38 +04:00
/* EDI = out4 */
2008-12-16 21:18:40 +03:00
| | upeek ( tcp , PT_R15 , ( long * ) & tcp - > u_arg [ 4 ] ) < 0
2001-10-10 03:47:38 +04:00
/* EBP = out5 */
2008-12-16 21:18:40 +03:00
| | upeek ( tcp , 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
}
}
2008-05-20 05:11:56 +04:00
# elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
/* N32 and N64 both use up to six registers. */
{
unsigned long long regs [ 38 ] ;
int i , nargs ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
nargs = tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2008-05-28 03:18:29 +04:00
else
2008-05-20 05:11:56 +04:00
nargs = tcp - > u_nargs = MAX_ARGS ;
2009-02-24 18:17:53 +03:00
if ( do_ptrace ( PTRACE_GETREGS , tcp , NULL , ( long ) & regs ) < 0 )
2008-05-20 05:11:56 +04:00
return - 1 ;
2009-02-24 18:17:53 +03:00
for ( i = 0 ; i < nargs ; i + + ) {
2008-05-20 05:11:56 +04:00
tcp - > u_arg [ i ] = regs [ REG_A0 + i ] ;
# if defined (LINUX_MIPSN32)
tcp - > ext_arg [ i ] = regs [ REG_A0 + i ] ;
# endif
}
}
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 ;
2009-02-24 18:17:53 +03:00
if ( nargs > 4 ) {
if ( upeek ( tcp , REG_SP , & sp ) < 0 )
1999-11-01 00:15:38 +03:00
return - 1 ;
2009-02-24 18:17:53 +03:00
for ( i = 0 ; i < 4 ; i + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
1999-11-01 00:15:38 +03:00
return - 1 ;
}
umoven ( tcp , sp + 16 , ( nargs - 4 ) * sizeof ( tcp - > u_arg [ 0 ] ) ,
( char * ) ( tcp - > u_arg + 4 ) ) ;
} else {
2009-02-24 18:17:53 +03:00
for ( i = 0 ; i < nargs ; i + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
1999-11-01 00:15:38 +03:00
return - 1 ;
}
}
}
1999-02-19 03:21:36 +03:00
# elif defined (POWERPC)
2009-02-25 20:08:40 +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 + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , ( i = = 0 ) ?
2003-01-14 12:59:00 +03:00
( 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 + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_GR26 - 4 * i , & tcp - > u_arg [ i ] ) < 0 )
2001-03-27 16:17:16 +04:00
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 ] ;
}
2008-11-11 01:21:41 +03:00
# elif defined(BFIN)
{
int i ;
int argreg [ ] = { PT_R0 , PT_R1 , PT_R2 , PT_R3 , PT_R4 , PT_R5 } ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = sizeof ( argreg ) / sizeof ( argreg [ 0 ] ) ;
for ( i = 0 ; i < tcp - > u_nargs ; + + i )
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , argreg [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2008-11-11 01:21:41 +03:00
return - 1 ;
}
2002-05-01 20:39:22 +04:00
# elif defined(SH)
2008-12-30 21:47:55 +03:00
{
int i ;
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 ( tcp , 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 ;
2008-12-30 21:47:55 +03:00
/* Registers used by SH5 Linux system calls for parameters */
2003-06-02 23:18:58 +04:00
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 + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , REG_GENERAL ( syscall_regs [ i ] ) , & tcp - > u_arg [ i ] ) < 0 )
2003-06-02 23:18:58 +04:00
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 + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , argreg [ current_personality ] [ i ] * 8 , & tcp - > u_arg [ i ] ) < 0 )
2002-09-23 19:41:01 +04:00
return - 1 ;
}
}
2009-02-25 20:08:40 +03:00
# elif defined(CRISV10) || defined(CRISV32)
{
int i ;
static const int crisregs [ ] = {
4 * PT_ORIG_R10 , 4 * PT_R11 , 4 * PT_R12 ,
4 * PT_R13 , 4 * PT_MOF , 4 * PT_SRP
} ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls )
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
tcp - > u_nargs = 0 ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( tcp - > pid , crisregs [ i ] , & 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 + + ) {
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , i * 4 , & tcp - > u_arg [ i ] ) < 0 )
1999-02-19 03:21:36 +03:00
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 ;
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , uoff ( u_arg [ 0 ] ) +
1999-02-19 03:21:36 +03:00
( 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 ) ) ;
2008-12-30 21:47:55 +03:00
break ;
case SYS_syscall :
2000-09-02 01:03:06 +04:00
pread ( tcp - > pfd , & tcp - > u_arg , tcp - > u_nargs * sizeof ( unsigned long ) ,
regs . r_esp + 2 * sizeof ( int ) ) ;
2008-12-30 21:47:55 +03:00
break ;
default :
2000-09-02 01:03:06 +04:00
pread ( tcp - > pfd , & tcp - > u_arg , tcp - > u_nargs * sizeof ( unsigned long ) ,
regs . r_esp + sizeof ( int ) ) ;
2008-12-30 21:47:55 +03:00
break ;
2000-09-02 01:03:06 +04:00
}
# endif /* FREEBSD */
2000-02-01 20:58:41 +03:00
return 1 ;
}
int
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
trace_syscall ( struct tcb * tcp )
2000-02-01 20:58:41 +03:00
{
int sys_res ;
struct timeval tv ;
2008-12-17 22:21:59 +03:00
int res , scno_good ;
2000-02-01 20:58:41 +03:00
if ( tcp - > flags & TCB_INSYSCALL ) {
long u_error ;
2008-12-17 22:21:59 +03:00
/* Measure the exit time as early as possible to avoid errors. */
if ( dtime )
gettimeofday ( & tv , NULL ) ;
2009-02-24 18:17:53 +03:00
/* In code below,
* res = 1 : no error , continue
* res = 0 : return 0 at once ( not an error )
* any other value : error , complain and return the value
*
* BTW , why we don ' t just memorize syscall no . on entry
2009-01-07 00:45:06 +03:00
* in tcp - > something ?
*/
2008-12-17 22:21:59 +03:00
scno_good = res = get_scno ( tcp ) ;
if ( res = = 0 )
return res ;
if ( res = = 1 )
res = syscall_fixup ( tcp ) ;
if ( res = = 0 )
return res ;
if ( res = = 1 )
res = get_error ( tcp ) ;
if ( res = = 0 )
2000-02-01 20:58:41 +03:00
return res ;
2008-12-17 22:21:59 +03:00
if ( res = = 1 )
internal_syscall ( tcp ) ;
2000-02-01 20:58:41 +03:00
2008-12-17 22:21:59 +03:00
if ( res = = 1 & & tcp - > scno > = 0 & & tcp - > scno < nsyscalls & &
2000-09-02 01:03:06 +04:00
! ( 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 ) ;
2009-02-24 18:17:53 +03:00
if ( scno_good ! = 1 ) {
tprintf ( " <... syscall_?? resumed> " ) ;
} else {
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 )
tprintf ( " <... syscall_%lu resumed> " , tcp - > scno ) ;
else
tprintf ( " <... %s resumed> " , sysent [ tcp - > scno ] . sys_name ) ;
}
/* [do we need to clear TCB_REPRINT?...] */
2000-02-01 20:58:41 +03:00
}
2006-12-21 Dmitry V. Levin <ldv@altlinux.org>
Move counts code to separate file.
* count.c: New file.
* Makefile.am (strace_SOURCES): Add count.c.
* syscall.c (call_counts, countv, counts, shortest, time_cmp,
syscall_cmp, count_cmp, sortfun, overhead, set_sortby,
set_overhead, call_summary_pers, call_summary): Move to count.c
* count.c (count_syscall): New function.
* defs.h (count_syscall): Declare it.
* syscall.c (trace_syscall): Use it.
2006-12-22 00:15:04 +03:00
if ( cflag )
return count_syscall ( tcp , & tv ) ;
2000-02-01 20:58:41 +03:00
2008-12-17 22:21:59 +03:00
if ( res ! = 1 ) {
tprintf ( " ) " ) ;
tabto ( acolumn ) ;
2009-02-24 18:17:53 +03:00
tprintf ( " = ? " ) ;
/* line will be finished by error handling code */
2008-12-17 22:21:59 +03:00
tcp - > flags & = ~ TCB_INSYSCALL ;
return res ;
}
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 ;
}
2008-09-03 05:22:18 +04:00
if ( ( sys_res & RVAL_STR ) & & tcp - > auxstr )
tprintf ( " (%s) " , tcp - > auxstr ) ;
2000-02-01 20:58:41 +03:00
}
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 ) ;
}
2009-01-07 00:45:06 +03:00
printtrailer ( ) ;
2000-02-01 20:58:41 +03:00
dumpio ( tcp ) ;
if ( fflush ( tcp - > outf ) = = EOF )
return - 1 ;
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
/* Entering system call */
2008-12-17 22:21:59 +03:00
scno_good = res = get_scno ( tcp ) ;
if ( res = = 0 )
return res ;
if ( res = = 1 )
res = syscall_fixup ( tcp ) ;
if ( res = = 0 )
return res ;
if ( res = = 1 )
res = syscall_enter ( tcp ) ;
if ( res = = 0 )
return res ;
if ( res ! = 1 ) {
printleader ( tcp ) ;
2009-02-24 18:17:53 +03:00
tcp - > flags & = ~ TCB_REPRINT ; /* why? */
2008-12-17 22:21:59 +03:00
tcp_last = tcp ;
if ( scno_good ! = 1 )
2009-02-24 18:17:53 +03:00
tprintf ( " syscall_?? " /* anti-trigraph gap */ " ( " ) ;
2008-12-17 22:21:59 +03:00
else if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 )
tprintf ( " syscall_%lu( " , tcp - > scno ) ;
else
tprintf ( " %s( " , sysent [ tcp - > scno ] . sys_name ) ;
2009-02-24 18:17:53 +03:00
/* Line will be finished by error handling code. */
2008-12-17 22:21:59 +03:00
tcp - > flags | = TCB_INSYSCALL ;
2000-02-01 20:58:41 +03:00
return res ;
2008-12-17 22:21:59 +03:00
}
2000-02-01 20:58:41 +03:00
2005-06-06 Roland McGrath <roland@redhat.com>
* linux/syscall.h (SYS_socket, SYS_bind, SYS_connect, SYS_listen)
(SYS_accept, SYS_getsockname, SYS_getpeername, SYS_socketpair)
(SYS_send, SYS_recv, SYS_sendto, SYS_recvfrom, SYS_shutdown)
(SYS_setsockopt, SYS_getsockopt, SYS_sendmsg, SYS_recvmsg)
(SYS_getsockname, SYS_semop, SYS_semgsub_et, SYS_semget, SYS_semctl)
(SYS_semtimedop, SYS_msgsnd, SYS_msgrcv, SYS_msgget)
(SYS_msgctl, SYS_shmat, SYS_shmdt, SYS_shmget)
(SYS_shmctl): Macros renamed to SYS_sub_*.
* syscall.c (dumpio): Match SYS_sub_* if defined instead of SYS_*.
* defs.h (struct sysent): New member `native_scno'.
(known_scno): Declare new function.
* linux/syscallent.h: Add new final field to interesting syscalls.
* syscall.c (known_scno): New function.
(dumpio, internal_syscall, syscall_fixup, trace_syscall): Use it.
* process.c (internal_fork, internal_exit): Likewise.
[IA64] (ARG_STACKSIZE, ARG_PTID, ARG_CTID, ARG_TLS): Likewise.
* strace.c (proc_open): Likewise.
* util.c [LINUX] (setbpt): Likewise.
* linux/syscall.h: Remove [!defined(X86_64)] from conditional
for defining SYS_socket_subcall et al.
* linux/syscallent.h: Likewise for #error check.
* syscall.c (trace_syscall): Likewise for SYS_{socketcall,ipc} cases.
Fixes RH#158934.
2005-06-08 03:21:26 +04:00
switch ( known_scno ( tcp ) ) {
2008-08-25 07:16:26 +04:00
# ifdef SYS_socket_subcall
1999-02-19 03:21:36 +03:00
case SYS_socketcall :
decode_subcall ( tcp , SYS_socket_subcall ,
SYS_socket_nsubcalls , deref_style ) ;
break ;
2008-08-25 07:16:26 +04:00
# endif
# ifdef SYS_ipc_subcall
1999-02-19 03:21:36 +03:00
case SYS_ipc :
decode_subcall ( tcp , SYS_ipc_subcall ,
SYS_ipc_nsubcalls , shift_style ) ;
break ;
2008-08-25 07:16:26 +04:00
# endif
1999-02-19 03:21:36 +03:00
# 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 ;
2009-02-24 18:17:53 +03:00
if ( do_ptrace ( PTRACE_GETREGS , tcp , ( char * ) & regs , 0 ) < 0 )
1999-02-19 03:21:36 +03:00
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)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , 4 * ( REG_REG0 + 1 ) , & val ) < 0 )
2003-03-31 05:05:01 +04:00
return - 1 ;
2004-03-01 23:30:48 +03:00
# elif defined(IA64)
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , PT_R9 , & val ) < 0 )
2004-03-01 23:30:48 +03:00
return - 1 ;
2009-02-25 20:08:40 +03:00
# endif
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
2008-12-16 21:18:40 +03:00
if ( upeek ( tcp , uoff ( u_rval2 ) , & val ) < 0 )
1999-02-19 03:21:36 +03:00
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 */
2009-02-25 20:08:40 +03:00
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 ;
}
2006-12-13 19:59:44 +03:00
# ifdef SUNOS4
1999-02-19 03:21:36 +03:00
/*
* 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 ;
}
2006-12-13 19:59:44 +03:00
# endif /* SUNOS4 */
2008-09-03 05:02:46 +04:00
int
is_restart_error ( struct tcb * tcp )
{
# ifdef LINUX
if ( ! syserror ( tcp ) )
return 0 ;
switch ( tcp - > u_error ) {
case ERESTARTSYS :
case ERESTARTNOINTR :
case ERESTARTNOHAND :
case ERESTART_RESTARTBLOCK :
return 1 ;
default :
break ;
}
# endif /* LINUX */
return 0 ;
}