1999-02-19 03:21:36 +03:00
/*
* Copyright ( c ) 1991 , 1992 Paul Kranenburg < pk @ cs . few . eur . nl >
* Copyright ( c ) 1993 Branko Lankester < branko @ hacktic . nl >
* Copyright ( c ) 1993 , 1994 , 1995 , 1996 Rick Sladkey < jrs @ world . std . com >
1999-12-23 17:20:14 +03:00
* Copyright ( c ) 1996 - 1999 Wichert Akkerman < wichert @ cistron . nl >
* Copyright ( c ) 1999 IBM Deutschland Entwicklung GmbH , IBM Corporation
* Linux for s390 port by D . J . Barrow
* < barrow_dj @ mail . yahoo . com , djbarrow @ de . ibm . com >
1999-02-19 03:21:36 +03:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ` ` AS IS ' ' AND ANY EXPRESS OR
* IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED .
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT
* NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE ,
* DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* $ Id $
*/
# include "defs.h"
# include <signal.h>
# include <time.h>
# include <errno.h>
# include <sys/user.h>
# include <sys/syscall.h>
# include <sys/param.h>
1999-06-24 17:55:29 +04:00
1999-07-14 02:20:16 +04:00
# ifdef HAVE_SYS_REG_H
2009-06-03 03:49:22 +04: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-06-03 03:49:22 +04: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-06-03 03:49:22 +04: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)
# 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
2011-08-18 14:48:56 +04:00
# warning: NSIG is not defined, using 32
1999-02-19 03:21:36 +03:00
# define NSIG 32
# endif
# ifdef ARM
2011-08-18 14:48:56 +04:00
/* Ugh. Is this really correct? ARM has no RT signals?! */
1999-02-19 03:21:36 +03:00
# 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
2011-01-18 20:36:20 +03:00
# define NF SYSCALL_NEVER_FAILS
1999-02-19 03:21:36 +03:00
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"
} ;
# 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"
} ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
# endif
1999-02-19 03:21:36 +03:00
# 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"
} ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
# endif
1999-02-19 03:21:36 +03:00
/* 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
2011-01-18 20:36:20 +03:00
# undef NF
1999-02-19 03:21:36 +03:00
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
/*
* ` ioctlent . h ' may be generated from ` ioctlent . raw ' by the auxiliary
* program ` ioctlsort ' , such that the list is sorted by the ` code ' field .
* This has the side - effect of resolving the _IO . . macros into
* plain integers , eliminating the need to include here everything
* in " /usr/include " .
*/
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"
} ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
static const char * const signalent0 [ ] = {
# include "signalent.h"
} ;
static const struct ioctlent ioctlent0 [ ] = {
# include "ioctlent.h"
} ;
enum { nsyscalls0 = ARRAY_SIZE ( sysent0 ) } ;
enum { nerrnos0 = ARRAY_SIZE ( errnoent0 ) } ;
enum { nsignals0 = ARRAY_SIZE ( signalent0 ) } ;
enum { nioctlents0 = ARRAY_SIZE ( ioctlent0 ) } ;
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 char * const errnoent1 [ ] = {
1999-02-19 03:21:36 +03:00
# include "errnoent1.h"
} ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
static const char * const signalent1 [ ] = {
# include "signalent1.h"
} ;
static const struct ioctlent ioctlent1 [ ] = {
# include "ioctlent1.h"
} ;
enum { nsyscalls1 = ARRAY_SIZE ( sysent1 ) } ;
enum { nerrnos1 = ARRAY_SIZE ( errnoent1 ) } ;
enum { nsignals1 = ARRAY_SIZE ( signalent1 ) } ;
enum { nioctlents1 = ARRAY_SIZE ( ioctlent1 ) } ;
int qual_flags1 [ MAX_QUALS ] ;
# endif
1999-02-19 03:21:36 +03:00
# 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"
} ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
static const char * const signalent2 [ ] = {
# include "signalent2.h"
} ;
static const struct ioctlent ioctlent2 [ ] = {
# include "ioctlent2.h"
} ;
enum { nsyscalls2 = ARRAY_SIZE ( sysent2 ) } ;
enum { nerrnos2 = ARRAY_SIZE ( errnoent2 ) } ;
enum { nsignals2 = ARRAY_SIZE ( signalent2 ) } ;
enum { nioctlents2 = ARRAY_SIZE ( ioctlent2 ) } ;
int qual_flags2 [ MAX_QUALS ] ;
# endif
1999-02-19 03:21:36 +03:00
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
const struct sysent * sysent ;
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 ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
const char * const * signalent ;
const struct ioctlent * ioctlent ;
int nsyscalls ;
1999-02-19 03:21:36 +03:00
int nerrnos ;
Small optimization in signal and ioctl tables
Trivial shuffling of data tables puts them all in one file,
allowing gcc to see their sizes and eliminate variables
which store these sizes.
Surprisingly, in C mode gcc does not optimize out static const int
variables. Help it by using enums instead.
* defs.h: Stop exporting ioctlent{0,1,2}, nioctlents{0,1,2},
signalent{0,1,2}, nsignals{0,1,2}.
* ioctl.c: Remove definitions of ioctlent{,0,1,2} and nioctlents{,0,1,2}.
* signal.c: Remove definitions of signalent{,0,1,2} and nsignals{,0,1,2}.
* syscall.c: Move above definitions to this file. Make them static const
or enums if suitable.
2011-08-20 04:12:33 +04:00
int nsignals ;
int nioctlents ;
int * qual_flags ;
1999-02-19 03:21:36 +03:00
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
2011-08-20 03:50:09 +04:00
} ;
2006-01-12 13:18:53 +03:00
2011-08-20 03:50:09 +04:00
void
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 ;
2011-08-20 03:50:09 +04:00
# endif
1999-02-19 03:21:36 +03:00
# 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 ;
2011-08-20 03:50:09 +04:00
# endif
1999-02-19 03:21:36 +03:00
}
current_personality = personality ;
}
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 ;
2010-09-07 02:08:24 +04:00
const char * option_name ;
2010-09-15 20:18:20 +04:00
int ( * qualify ) ( const char * , int , int ) ;
2010-09-07 02:08:24 +04:00
const char * argument_name ;
1999-02-19 03:21:36 +03:00
} 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
2010-09-15 20:18:20 +04:00
qualify_one ( int n , int bitflag , int not , 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 )
2010-09-15 20:18:20 +04:00
qual_flags0 [ n ] & = ~ bitflag ;
2006-01-12 12:50:49 +03:00
else
2010-09-15 20:18:20 +04:00
qual_flags0 [ n ] | = bitflag ;
2006-01-12 12:50:49 +03:00
}
# if SUPPORTED_PERSONALITIES >= 2
if ( pers = = 1 | | pers < 0 ) {
if ( not )
2010-09-15 20:18:20 +04:00
qual_flags1 [ n ] & = ~ bitflag ;
2006-01-12 12:50:49 +03:00
else
2010-09-15 20:18:20 +04:00
qual_flags1 [ n ] | = bitflag ;
2006-01-12 12:50:49 +03:00
}
# endif /* SUPPORTED_PERSONALITIES >= 2 */
# if SUPPORTED_PERSONALITIES >= 3
if ( pers = = 2 | | pers < 0 ) {
if ( not )
2010-09-15 20:18:20 +04:00
qual_flags2 [ n ] & = ~ bitflag ;
2006-01-12 12:50:49 +03:00
else
2010-09-15 20:18:20 +04:00
qual_flags2 [ n ] | = bitflag ;
2006-01-12 12:50:49 +03:00
}
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2002-12-30 13:23:00 +03:00
}
1999-02-19 03:21:36 +03:00
static int
2010-09-15 20:18:20 +04:00
qual_syscall ( const char * s , int bitflag , 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
2009-02-27 23:32:52 +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 )
2009-02-27 23:32:52 +03:00
return - 1 ;
2010-09-15 20:18:20 +04:00
qualify_one ( i , bitflag , not , - 1 ) ;
2009-02-27 23:32:52 +03:00
return 0 ;
2006-01-12 12:45:56 +03:00
}
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 ) {
2010-09-15 20:18:20 +04:00
qualify_one ( i , bitflag , not , 0 ) ;
2006-01-12 12:50:49 +03:00
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 ) {
2010-09-15 20:18:20 +04:00
qualify_one ( i , bitflag , 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 ) {
2010-09-15 20:18:20 +04:00
qualify_one ( i , bitflag , not , 2 ) ;
2006-01-12 12:50:49 +03:00
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
2010-09-15 20:18:20 +04:00
qual_signal ( const char * s , int bitflag , int not )
1999-02-19 03:21:36 +03:00
{
int i ;
char buf [ 32 ] ;
2009-02-27 23:32:52 +03:00
if ( isdigit ( ( unsigned char ) * s ) ) {
int signo = atoi ( s ) ;
if ( signo < 0 | | signo > = MAX_QUALS )
return - 1 ;
2010-09-15 20:18:20 +04:00
qualify_one ( signo , bitflag , not , - 1 ) ;
2009-02-27 23:32:52 +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 ;
2010-09-07 02:08:24 +04:00
if ( strncasecmp ( s , " SIG " , 3 ) = = 0 )
1999-02-19 03:21:36 +03:00
s + = 3 ;
2002-12-30 13:23:00 +03:00
for ( i = 0 ; i < = NSIG ; i + + )
2010-09-07 02:08:24 +04:00
if ( strcasecmp ( s , signame ( i ) + 3 ) = = 0 ) {
2010-09-15 20:18:20 +04:00
qualify_one ( i , bitflag , 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
2010-09-15 20:18:20 +04:00
qual_fault ( const char * s , int bitflag , int not )
1999-02-19 03:21:36 +03:00
{
return - 1 ;
}
static int
2010-09-15 20:18:20 +04:00
qual_desc ( const char * s , int bitflag , 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 ;
2010-09-15 20:18:20 +04:00
qualify_one ( desc , bitflag , 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
2010-09-07 02:08:24 +04:00
lookup_class ( const 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
2010-09-07 02:08:24 +04:00
qualify ( const char * s )
1999-02-19 03:21:36 +03:00
{
2004-09-04 08:20:43 +04:00
const struct qual_options * opt ;
1999-02-19 03:21:36 +03:00
int not ;
2010-09-07 02:08:24 +04:00
char * copy ;
const char * p ;
1999-02-19 03:21:36 +03:00
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 + + ) {
2010-09-15 20:18:20 +04:00
qualify_one ( i , opt - > bitflag , not , - 1 ) ;
1999-02-19 03:21:36 +03:00
}
return ;
}
for ( i = 0 ; i < MAX_QUALS ; i + + ) {
2010-09-15 20:18:20 +04:00
qualify_one ( i , opt - > bitflag , ! not , - 1 ) ;
1999-02-19 03:21:36 +03:00
}
2011-08-20 14:48:18 +04:00
copy = strdup ( s ) ;
if ( ! copy ) {
2010-09-07 02:08:24 +04:00
fprintf ( stderr , " out of memory \n " ) ;
exit ( 1 ) ;
}
for ( p = strtok ( copy , " , " ) ; p ; p = strtok ( NULL , " , " ) ) {
1999-02-19 03:21:36 +03:00
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 )
2010-09-15 20:18:20 +04:00
qualify_one ( i , opt - > bitflag , not , 0 ) ;
2006-01-12 12:50:49 +03:00
# 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 )
2010-09-15 20:18:20 +04:00
qualify_one ( i , opt - > bitflag , not , 1 ) ;
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 ( sysent2 [ i ] . sys_flags & n )
2010-09-15 20:18:20 +04:00
qualify_one ( i , opt - > bitflag , not , 2 ) ;
2006-01-12 12:50:49 +03:00
# endif /* SUPPORTED_PERSONALITIES >= 3 */
2007-08-23 01:43:30 +04:00
1999-02-19 03:21:36 +03:00
continue ;
}
2010-09-15 20:18:20 +04:00
if ( opt - > qualify ( p , opt - > bitflag , not ) ) {
1999-02-19 03:21:36 +03:00
fprintf ( stderr , " strace: invalid %s `%s' \n " ,
opt - > argument_name , p ) ;
exit ( 1 ) ;
}
}
2010-09-07 02:08:24 +04:00
free ( copy ) ;
1999-02-19 03:21:36 +03:00
return ;
}
static void
2011-02-09 03:39:47 +03:00
dumpio ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
if ( syserror ( tcp ) )
return ;
if ( tcp - > u_arg [ 0 ] < 0 | | tcp - > u_arg [ 0 ] > = MAX_QUALS )
return ;
2011-02-09 03:39:47 +03:00
if ( tcp - > scno < 0 | | tcp - > scno > = nsyscalls )
return ;
if ( sysent [ tcp - > scno ] . sys_func = = printargs )
return ;
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_READ ) {
if ( sysent [ tcp - > scno ] . sys_func = = sys_read | |
sysent [ tcp - > scno ] . sys_func = = sys_pread | |
sysent [ tcp - > scno ] . sys_func = = sys_pread64 | |
sysent [ tcp - > scno ] . sys_func = = sys_recv | |
sysent [ tcp - > scno ] . sys_func = = sys_recvfrom )
1999-02-19 03:21:36 +03:00
dumpstr ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_rval ) ;
2011-02-09 03:39:47 +03:00
else if ( sysent [ tcp - > scno ] . sys_func = = sys_readv )
2008-12-30 21:47:55 +03:00
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
2011-02-09 03:39:47 +03:00
return ;
}
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_WRITE ) {
if ( sysent [ tcp - > scno ] . sys_func = = sys_write | |
sysent [ tcp - > scno ] . sys_func = = sys_pwrite | |
sysent [ tcp - > scno ] . sys_func = = sys_pwrite64 | |
sysent [ tcp - > scno ] . sys_func = = sys_send | |
sysent [ tcp - > scno ] . sys_func = = sys_sendto )
dumpstr ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_arg [ 2 ] ) ;
else if ( sysent [ tcp - > scno ] . sys_func = = sys_writev )
2008-12-30 21:47:55 +03:00
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
2011-02-09 03:39:47 +03:00
return ;
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
2011-05-30 16:00:14 +04:00
decode_subcall ( struct tcb * tcp , int subcall , int nsubcalls , enum subcall_style style )
1999-02-19 03:21:36 +03:00
{
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 :
2011-06-14 01:58:43 +04:00
for ( i = 0 ; i < ARRAY_SIZE ( subcalls_table ) ; i + + )
2000-09-02 01:03:06 +04:00
if ( subcalls_table [ i ] . call = = tcp - > scno ) break ;
2011-06-14 01:58:43 +04:00
if ( i < ARRAY_SIZE ( subcalls_table ) & &
2000-09-02 01:03:06 +04:00
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 .
*/
2011-08-21 19:26:55 +04: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_fork = = func
# if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
| | sys_vfork = = func
1999-02-19 03:21:36 +03:00
# endif
2009-12-26 20:55:24 +03:00
# ifdef LINUX
| | sys_clone = = func
# 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 ) ;
2011-08-21 19:26:55 +04:00
# if defined SUNOS4 || (defined LINUX && defined TCB_WAITEXECVE)
2006-12-21 14:44:28 +03:00
if ( sys_execve = = func
2011-08-21 19:26:55 +04:00
# if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
2006-12-21 14:44:28 +03:00
| | sys_execv = = func
2011-08-21 19:26:55 +04:00
# endif
# if UNIXWARE > 2
2006-12-21 14:44:28 +03:00
| | sys_rexecve = = func
2011-08-21 19:26:55 +04:00
# endif
2006-12-21 14:44:28 +03:00
)
return internal_exec ( tcp ) ;
2011-08-21 19:26:55 +04:00
# endif
1999-02-19 03:21:36 +03:00
return 0 ;
}
2000-04-11 02:22:31 +04:00
# ifdef LINUX
2011-06-07 14:13:24 +04:00
# if defined (I386)
static long eax ;
# elif defined (IA64)
long r8 , r10 , psr ; /* TODO: make static? */
long ia32 = 0 ; /* not static */
# elif defined (POWERPC)
static long result , flags ;
# elif defined (M68K)
static long d0 ;
# elif defined(BFIN)
static long r0 ;
# elif defined (ARM)
static struct pt_regs regs ;
# elif defined (ALPHA)
static long r0 ;
static long a3 ;
# elif defined(AVR32)
static struct pt_regs regs ;
# elif defined (SPARC) || defined (SPARC64)
static struct pt_regs regs ;
static unsigned long trap ;
# elif defined(LINUX_MIPSN32)
static long long a3 ;
static long long r2 ;
# elif defined(MIPS)
static long a3 ;
static long r2 ;
# elif defined(S390) || defined(S390X)
static long gpr2 ;
static long pc ;
static long syscall_mode ;
# elif defined(HPPA)
static long r28 ;
# elif defined(SH)
static long r0 ;
# elif defined(SH64)
static long r9 ;
# elif defined(X86_64)
static long rax ;
# elif defined(CRISV10) || defined(CRISV32)
static long r10 ;
# elif defined(MICROBLAZE)
static long r3 ;
# endif
2000-04-11 02:22:31 +04:00
# endif /* LINUX */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
2011-06-07 14:13:24 +04:00
struct reg regs ; /* TODO: make static? */
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 )
2011-06-07 14:13:24 +04:00
return - 1 ;
2003-06-27 02:23:28 +04:00
if ( syscall_mode ! = - ENOSYS ) {
/*
2009-02-27 23:32:52 +03:00
* Since kernel version 2.5 .44 the scno gets passed in gpr2 .
2003-06-27 02:23:28 +04:00
*/
scno = syscall_mode ;
} else {
2009-02-27 23:32:52 +03:00
/*
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 ;
2011-08-19 21:46:32 +04:00
static const 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 ;
}
}
2010-07-12 23:39:57 +04:00
# ifdef POWERPC64
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2011-08-20 02:03:10 +04:00
/* TODO: speed up strace by not doing this at every syscall.
* We only need to do it after execve .
*/
int currpers ;
2010-07-12 23:39:57 +04:00
long val ;
int pid = tcp - > pid ;
/* Check for 64/32 bit mode. */
2011-06-07 14:13:24 +04:00
if ( upeek ( tcp , sizeof ( unsigned long ) * PT_MSR , & val ) < 0 )
2010-07-12 23:39:57 +04:00
return - 1 ;
/* SF is bit 0 of MSR */
if ( val < 0 )
currpers = 0 ;
else
currpers = 1 ;
if ( currpers ! = current_personality ) {
static const char * const names [ ] = { " 64 bit " , " 32 bit " } ;
set_personality ( currpers ) ;
2010-12-03 02:38:13 +03:00
fprintf ( stderr , " [ Process PID=%d runs in %s mode. ] \n " ,
2010-07-12 23:39:57 +04:00
pid , names [ current_personality ] ) ;
}
}
# endif
2009-02-27 23:32:52 +03:00
# elif defined(AVR32)
/*
* Read complete register set in one go .
*/
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , NULL , & regs ) < 0 )
return - 1 ;
/*
* We only need to grab the syscall number on syscall entry .
*/
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
scno = regs . r8 ;
/* 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(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 ;
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 ) ) {
2011-08-20 02:03:10 +04:00
/* TODO: speed up strace by not doing this at every syscall.
* We only need to do it after execve .
*/
int currpers ;
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:
2011-06-07 14:13:24 +04:00
* 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 )
2010-12-03 02:38:13 +03:00
fprintf ( stderr , " 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 ) ;
2010-12-03 02:38:13 +03:00
fprintf ( stderr , " [ 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)
2011-06-07 14:13:24 +04: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 {
2011-06-07 14:13:24 +04: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 ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
2000-02-04 00:58:30 +03:00
} else {
/* syscall in progress */
2011-06-07 14:13:24 +04:00
if ( upeek ( tcp , PT_R8 , & r8 ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
2011-06-07 14:13:24 +04: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 ] ;
2011-06-07 14:13:24 +04:00
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , NULL , ( long ) & regs ) < 0 )
2008-05-20 05:11:56 +04:00
return - 1 ;
a3 = regs [ REG_A3 ] ;
r2 = regs [ REG_V0 ] ;
2011-06-07 14:13:24 +04:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2008-05-20 05:11:56 +04:00
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 ) {
2011-06-07 14:13:24 +04:00
if ( a3 = = 0 | | a3 = = - 1 ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
2008-05-20 05:11:56 +04:00
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 )
2009-02-27 23:32:52 +03:00
return - 1 ;
2011-06-07 14:13:24 +04:00
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
2009-02-27 23:32:52 +03:00
if ( upeek ( tcp , REG_V0 , & scno ) < 0 )
return - 1 ;
1999-11-01 00:15:38 +03:00
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 ) {
2011-06-07 14:13:24 +04:00
if ( a3 = = 0 | | a3 = = - 1 ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
1999-11-01 00:15:38 +03:00
return 0 ;
}
}
} else {
2009-02-27 23:32:52 +03:00
if ( upeek ( tcp , REG_V0 , & r2 ) < 0 )
return - 1 ;
1999-11-01 00:15:38 +03:00
}
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 )
2011-06-07 14:13:24 +04:00
fprintf ( stderr , " stray syscall exit: r0 = %ld \n " , scno ) ;
1999-02-19 03:21:36 +03:00
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-02-25 20:08:40 +03:00
# if defined(SPARC64)
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
trap = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) regs . tpc , 0 ) ;
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
trap > > = 32 ;
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
# else
trap = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) regs . pc , 0 ) ;
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) */
2011-06-07 14:13:24 +04:00
fprintf ( stderr , " syscall: SunOS no support \n " ) ;
1999-02-19 03:21:36 +03:00
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. */
2011-06-07 14:13:24 +04:00
fprintf ( stderr , " syscall: NetBSD/FreeBSD not supported \n " ) ;
1999-02-19 03:21:36 +03:00
return - 1 ;
case 0x91d02027 :
/* Solaris 2.x gettimeofday */
set_personality ( 1 ) ;
break ;
default :
/* Unknown syscall trap. */
2011-06-07 14:13:24 +04:00
if ( tcp - > flags & TCB_WAITEXECVE ) {
1999-02-19 03:21:36 +03:00
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
2009-02-25 20:08:40 +03:00
# if defined (SPARC64)
2011-06-07 14:13:24 +04:00
fprintf ( stderr , " syscall: unknown syscall trap %08lx %016lx \n " , trap , regs . tpc ) ;
2009-02-25 20:08:40 +03:00
# else
2011-06-07 14:13:24 +04:00
fprintf ( stderr , " syscall: unknown syscall trap %08lx %08lx \n " , trap , regs . 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
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
scno = regs . u_regs [ U_REG_G1 ] ;
1999-02-19 03:21:36 +03:00
if ( scno = = 0 ) {
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
scno = regs . u_regs [ U_REG_O0 ] ;
2011-06-07 14:13:24 +04:00
memmove ( & regs . u_regs [ U_REG_O0 ] , & regs . u_regs [ U_REG_O1 ] , 7 * sizeof ( regs . u_regs [ 0 ] ) ) ;
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 )
2009-02-27 23:32:52 +03:00
fprintf ( stderr ,
2008-12-30 21:47:55 +03:00
" 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 ;
2009-12-28 18:00:15 +03:00
# elif defined(TILE)
if ( upeek ( tcp , PTREGS_OFFSET_REG ( 10 ) , & scno ) < 0 )
return - 1 ;
if ( ! ( tcp - > flags & TCB_INSYSCALL ) ) {
/* Check if we return from execve. */
if ( tcp - > flags & TCB_WAITEXECVE ) {
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
}
2010-07-06 16:21:07 +04:00
# elif defined(MICROBLAZE)
if ( upeek ( tcp , 0 , & scno ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
# 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
2011-02-19 02:19:47 +03:00
known_scno ( struct tcb * tcp )
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 scno = tcp - > scno ;
2011-02-19 02:19:47 +03:00
# if SUPPORTED_PERSONALITIES > 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
if ( scno > = 0 & & scno < nsyscalls & & sysent [ scno ] . native_scno ! = 0 )
scno = sysent [ scno ] . native_scno ;
else
2011-02-19 02:19:47 +03:00
# endif
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
scno + = NR_SYSCALL_BASE ;
return scno ;
}
2009-06-03 03:49:22 +04:00
/* Called in trace_syscall() at each syscall entry and exit.
2009-01-02 21:02:45 +03:00
* Returns :
2009-06-03 03:49:22 +04: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)
2009-10-05 18:41:02 +04:00
if ( upeek ( tcp , 4 * PT_R10 , & r10 ) < 0 )
2009-02-25 20:08:40 +03:00
return - 1 ;
if ( r10 ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: r10 = %ld \n " , r10 ) ;
return 0 ;
}
2010-07-06 16:21:07 +04:00
# elif defined(MICROBLAZE)
if ( upeek ( tcp , 3 * 4 , & r3 ) < 0 )
return - 1 ;
if ( r3 ! = - ENOSYS & & ! ( tcp - > flags & TCB_INSYSCALL ) ) {
if ( debug )
fprintf ( stderr , " stray syscall exit: r3 = %ld \n " , r3 ) ;
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 ;
2011-08-21 19:26:55 +04:00
# if SUPPORTED_PERSONALITIES > 1
2008-05-28 03:18:29 +04:00
if ( personality_wordsize [ current_personality ] < sizeof ( val ) ) {
val = ( unsigned int ) val ;
max = ( unsigned int ) max ;
}
2011-08-21 19:26:55 +04:00
# endif
2008-05-28 03:18:29 +04:00
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
2011-01-18 20:36:20 +03:00
int check_errno = 1 ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & &
sysent [ tcp - > scno ] . sys_flags & SYSCALL_NEVER_FAILS ) {
check_errno = 0 ;
}
2009-02-25 20:08:40 +03:00
# if defined(S390) || defined(S390X)
2011-01-18 20:36:20 +03:00
if ( check_errno & & is_negated_errno ( gpr2 ) ) {
2008-05-28 03:18:29 +04:00
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)
2011-01-18 20:36:20 +03:00
if ( check_errno & & is_negated_errno ( eax ) ) {
2008-05-28 03:18:29 +04:00
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)
2011-01-18 20:36:20 +03:00
if ( check_errno & & is_negated_errno ( rax ) ) {
2008-05-28 03:18:29 +04:00
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 ;
2011-01-18 20:36:20 +03:00
if ( check_errno & & 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 {
2011-01-18 20:36:20 +03:00
if ( check_errno & & r10 ) {
2008-05-28 03:18:29 +04:00
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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & 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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & is_negated_errno ( result ) ) {
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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & is_negated_errno ( d0 ) ) {
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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & is_negated_errno ( regs . ARM_r0 ) ) {
tcp - > u_rval = - 1 ;
u_error = - regs . ARM_r0 ;
}
else {
tcp - > u_rval = regs . ARM_r0 ;
u_error = 0 ;
}
2009-02-27 23:32:52 +03:00
# elif defined(AVR32)
2011-06-07 14:13:24 +04:00
if ( check_errno & & regs . r12 & & ( unsigned ) - regs . r12 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - regs . r12 ;
}
else {
tcp - > u_rval = regs . r12 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(BFIN)
2011-06-07 14:13:24 +04:00
if ( check_errno & & 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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & 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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & regs . psr & PSR_C ) {
tcp - > u_rval = - 1 ;
u_error = regs . u_regs [ U_REG_O0 ] ;
}
else {
tcp - > u_rval = regs . u_regs [ U_REG_O0 ] ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(SPARC64)
2011-06-07 14:13:24 +04:00
if ( check_errno & & regs . tstate & 0x1100000000UL ) {
tcp - > u_rval = - 1 ;
u_error = regs . u_regs [ U_REG_O0 ] ;
}
else {
tcp - > u_rval = regs . u_regs [ U_REG_O0 ] ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(HPPA)
2011-06-07 14:13:24 +04:00
if ( check_errno & & is_negated_errno ( r28 ) ) {
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)
2011-06-07 14:13:24 +04:00
/* interpret R0 as return value or error number */
if ( check_errno & & 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)
2011-06-07 14:13:24 +04:00
/* interpret result as return value or error number */
if ( check_errno & & 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)
2011-06-07 14:13:24 +04:00
if ( check_errno & & r10 & & ( unsigned ) - r10 < nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - r10 ;
}
else {
tcp - > u_rval = r10 ;
u_error = 0 ;
}
2009-12-28 18:00:15 +03:00
# elif defined(TILE)
2011-06-07 14:13:24 +04:00
long rval ;
/* interpret result as return value or error number */
if ( upeek ( tcp , PTREGS_OFFSET_REG ( 0 ) , & rval ) < 0 )
return - 1 ;
if ( check_errno & & rval < 0 & & rval > - nerrnos ) {
tcp - > u_rval = - 1 ;
u_error = - rval ;
}
else {
tcp - > u_rval = rval ;
u_error = 0 ;
}
2010-07-06 16:21:07 +04:00
# elif defined(MICROBLAZE)
2011-06-07 14:13:24 +04:00
/* interpret result as return value or error number */
if ( check_errno & & is_negated_errno ( r3 ) ) {
tcp - > u_rval = - 1 ;
u_error = - r3 ;
}
else {
tcp - > u_rval = r3 ;
u_error = 0 ;
}
2009-02-25 20:08:40 +03:00
# endif
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
2011-06-07 14:13:24 +04:00
/* get error code from user struct */
if ( upeek ( tcp , uoff ( u_error ) , & u_error ) < 0 )
return - 1 ;
u_error > > = 24 ; /* u_error is a char */
1999-02-19 03:21:36 +03:00
2011-06-07 14:13:24 +04:00
/* get system call return value */
if ( upeek ( tcp , uoff ( u_rval1 ) , & tcp - > u_rval ) < 0 )
return - 1 ;
1999-02-19 03:21:36 +03:00
# endif /* SUNOS4 */
# ifdef SVR4
2011-06-07 14:13:24 +04:00
# 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? */
if ( tcp - > status . PR_REG [ EFL ] & 0x1 ) {
tcp - > u_rval = - 1 ;
u_error = tcp - > status . PR_REG [ EAX ] ;
}
else {
tcp - > u_rval = tcp - > status . PR_REG [ EAX ] ;
# ifdef HAVE_LONG_LONG
tcp - > u_lrval =
( ( unsigned long long ) tcp - > status . PR_REG [ EDX ] < < 32 ) +
tcp - > status . PR_REG [ EAX ] ;
# endif
u_error = 0 ;
}
# endif /* I386 */
# 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 */
# 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 */
1999-02-19 03:21:36 +03:00
# endif /* SVR4 */
2000-09-02 01:03:06 +04:00
# ifdef FREEBSD
2011-06-07 14:13:24 +04:00
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
2011-05-30 16:00:14 +04:00
force_result ( struct tcb * tcp , int error , long rval )
2002-12-22 02:25:18 +03:00
{
# 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 )
2009-02-27 23:32:52 +03:00
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-27 23:32:52 +03:00
# elif defined(AVR32)
regs . r12 = error ? - error : rval ;
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) REG_R12 , regs . r12 ) < 0 )
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 ) {
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
regs . psr | = PSR_C ;
regs . u_regs [ U_REG_O0 ] = error ;
2002-12-22 02:25:18 +03:00
}
else {
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
regs . psr & = ~ PSR_C ;
regs . u_regs [ U_REG_O0 ] = rval ;
2002-12-22 02:25:18 +03:00
}
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 ) {
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
regs . tstate | = 0x1100000000UL ;
regs . u_regs [ U_REG_O0 ] = error ;
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
}
else {
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
regs . tstate & = ~ 0x1100000000UL ;
regs . u_regs [ U_REG_O0 ] = rval ;
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_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-06-03 03:49:22 +04:00
if ( ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) uoff ( u_error ) ,
error < < 24 ) < 0 | |
ptrace ( PTRACE_POKEUSER , tcp - > pid , ( char * ) uoff ( u_rval1 ) , rval ) < 0 )
2002-12-22 02:25:18 +03:00
return - 1 ;
# 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
2011-06-24 00:10:54 +04:00
# if defined(S390) || defined(S390X)
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 + + ) {
if ( upeek ( tcp , i = = 0 ? PT_ORIGGPR2 : PT_GPR2 + i * sizeof ( long ) , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
1999-12-23 17:20:14 +03:00
}
2011-06-24 00:10:54 +04:00
# elif defined(ALPHA)
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 + + ) {
/* WTA: if scno is out-of-bounds this will bomb. Add range-check
* for scno somewhere above here !
*/
if ( upeek ( tcp , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
}
# elif defined(IA64)
if ( ! ia32 ) {
unsigned long * out0 , cfm , sof , sol , i ;
long rbs_end ;
/* be backwards compatible with kernel < 2.4.4... */
# ifndef PT_RBS_END
# define PT_RBS_END PT_AR_BSP
# endif
if ( upeek ( tcp , PT_RBS_END , & rbs_end ) < 0 )
return - 1 ;
if ( upeek ( tcp , PT_CFM , ( long * ) & cfm ) < 0 )
return - 1 ;
sof = ( cfm > > 0 ) & 0x7f ;
sol = ( cfm > > 7 ) & 0x7f ;
out0 = ia64_rse_skip_regs ( ( unsigned long * ) rbs_end , - sof + sol ) ;
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls
& & sysent [ tcp - > scno ] . nargs ! = - 1 )
2000-09-02 01:03:06 +04:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
2002-12-16 02:58:31 +03:00
else
2009-02-27 23:32:52 +03:00
tcp - > u_nargs = MAX_ARGS ;
2011-06-24 00:10:54 +04:00
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 )
1999-02-19 03:21:36 +03:00
return - 1 ;
}
2011-06-24 00:10:54 +04:00
} else {
int i ;
2000-02-04 00:58:30 +03:00
2011-06-24 00:10:54 +04:00
if ( /* EBX = out0 */
upeek ( tcp , PT_R11 , ( long * ) & tcp - > u_arg [ 0 ] ) < 0
/* ECX = out1 */
| | upeek ( tcp , PT_R9 , ( long * ) & tcp - > u_arg [ 1 ] ) < 0
/* EDX = out2 */
| | upeek ( tcp , PT_R10 , ( long * ) & tcp - > u_arg [ 2 ] ) < 0
/* ESI = out3 */
| | upeek ( tcp , PT_R14 , ( long * ) & tcp - > u_arg [ 3 ] ) < 0
/* EDI = out4 */
| | upeek ( tcp , PT_R15 , ( long * ) & tcp - > u_arg [ 4 ] ) < 0
/* EBP = out5 */
| | upeek ( tcp , PT_R13 , ( long * ) & tcp - > u_arg [ 5 ] ) < 0 )
return - 1 ;
2001-10-10 03:47:38 +04:00
2011-06-24 00:10:54 +04:00
for ( i = 0 ; i < 6 ; + + i )
/* truncate away IVE sign-extension */
tcp - > u_arg [ i ] & = 0xffffffff ;
2001-10-10 03:47:38 +04:00
2011-06-24 00:10:54 +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 = 5 ;
2000-02-04 00:58:30 +03:00
}
2011-06-24 00:10:54 +04:00
# elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
2008-05-20 05:11:56 +04:00
/* N32 and N64 both use up to six registers. */
2011-06-24 00:10:54 +04:00
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 ;
else
nargs = tcp - > u_nargs = MAX_ARGS ;
2008-05-20 05:11:56 +04:00
2011-06-24 00:10:54 +04:00
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , NULL , ( long ) & regs ) < 0 )
return - 1 ;
2008-05-20 05:11:56 +04:00
2011-06-24 00:10:54 +04:00
for ( i = 0 ; i < nargs ; i + + ) {
tcp - > u_arg [ i ] = regs [ REG_A0 + i ] ;
# if defined(LINUX_MIPSN32)
tcp - > ext_arg [ i ] = regs [ REG_A0 + i ] ;
# endif
2008-05-20 05:11:56 +04:00
}
2011-06-24 00:10:54 +04:00
# elif defined(MIPS)
long sp ;
int i , nargs ;
1999-11-01 00:15:38 +03:00
2011-06-24 00:10:54 +04:00
if ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & & sysent [ tcp - > scno ] . nargs ! = - 1 )
nargs = tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
else
nargs = tcp - > u_nargs = MAX_ARGS ;
if ( nargs > 4 ) {
if ( upeek ( tcp , REG_SP , & sp ) < 0 )
return - 1 ;
for ( i = 0 ; i < 4 ; i + + ) {
if ( upeek ( tcp , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
2009-07-08 15:21:17 +04:00
return - 1 ;
1999-11-01 00:15:38 +03:00
}
2011-06-24 00:10:54 +04:00
umoven ( tcp , sp + 16 , ( nargs - 4 ) * sizeof ( tcp - > u_arg [ 0 ] ) ,
( char * ) ( tcp - > u_arg + 4 ) ) ;
} else {
for ( i = 0 ; i < nargs ; i + + ) {
if ( upeek ( tcp , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
}
}
2011-06-24 00:10:54 +04:00
# elif defined(POWERPC)
# ifndef PT_ORIG_R3
# define PT_ORIG_R3 34
# endif
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 + + ) {
if ( upeek ( tcp , ( i = = 0 ) ?
( sizeof ( unsigned long ) * PT_ORIG_R3 ) :
( ( i + PT_R3 ) * sizeof ( unsigned long ) ) ,
& tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2001-03-27 16:17:16 +04:00
}
2011-06-24 00:10:54 +04:00
# elif defined(SPARC) || defined(SPARC64)
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 . u_regs [ U_REG_O0 + i ] ;
# elif defined(HPPA)
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 + + ) {
if ( upeek ( tcp , PT_GR26 - 4 * i , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2009-02-27 23:32:52 +03:00
}
2011-06-24 00:10:54 +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 ] ;
# elif defined(AVR32)
2009-02-27 23:32:52 +03:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
tcp - > u_arg [ 0 ] = regs . r12 ;
tcp - > u_arg [ 1 ] = regs . r11 ;
tcp - > u_arg [ 2 ] = regs . r10 ;
tcp - > u_arg [ 3 ] = regs . r9 ;
tcp - > u_arg [ 4 ] = regs . r5 ;
tcp - > u_arg [ 5 ] = regs . r3 ;
2011-06-24 00:10:54 +04:00
# elif defined(BFIN)
int i ;
2011-06-24 00:22:34 +04:00
static const int argreg [ ] = { PT_R0 , PT_R1 , PT_R2 , PT_R3 , PT_R4 , PT_R5 } ;
2008-11-11 01:21:41 +03:00
2011-06-24 00:10:54 +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 = ARRAY_SIZE ( argreg ) ;
2008-11-11 01:21:41 +03:00
2011-06-24 00:10:54 +04:00
for ( i = 0 ; i < tcp - > u_nargs ; + + i )
if ( upeek ( tcp , argreg [ i ] , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
# elif defined(SH)
int i ;
2011-06-24 00:22:34 +04:00
static const int syscall_regs [ ] = {
4 * ( REG_REG0 + 4 ) , 4 * ( REG_REG0 + 5 ) , 4 * ( REG_REG0 + 6 ) , 4 * ( REG_REG0 + 7 ) ,
4 * ( REG_REG0 ) , 4 * ( REG_REG0 + 1 ) , 4 * ( REG_REG0 + 2 )
2011-06-24 00:10:54 +04:00
} ;
2008-12-30 21:47:55 +03:00
2011-06-24 00:10:54 +04:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
2011-06-24 00:22:34 +04:00
if ( upeek ( tcp , syscall_regs [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2011-06-24 00:10:54 +04:00
return - 1 ;
2008-12-30 21:47:55 +03:00
}
2011-06-24 00:10:54 +04:00
# elif defined(SH64)
int i ;
/* Registers used by SH5 Linux system calls for parameters */
2011-06-24 00:22:34 +04:00
static const int syscall_regs [ ] = { 2 , 3 , 4 , 5 , 6 , 7 } ;
2003-06-02 23:18:58 +04:00
2011-06-24 00:10:54 +04:00
/*
* TODO : should also check that the number of arguments encoded
* in the trap number matches the number strace expects .
*/
/*
assert ( sysent [ tcp - > scno ] . nargs < ARRAY_SIZE ( syscall_regs ) ) ;
*/
2003-06-02 23:18:58 +04:00
2011-06-24 00:10:54 +04:00
tcp - > u_nargs = sysent [ tcp - > scno ] . nargs ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + ) {
if ( upeek ( tcp , REG_GENERAL ( syscall_regs [ i ] ) , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2003-06-02 23:18:58 +04:00
}
2011-06-24 00:10:54 +04:00
# elif defined(X86_64)
int i ;
2011-06-24 00:22:34 +04:00
static const int argreg [ SUPPORTED_PERSONALITIES ] [ MAX_ARGS ] = {
{ 8 * RDI , 8 * RSI , 8 * RDX , 8 * R10 , 8 * R8 , 8 * R9 } , /* x86-64 ABI */
{ 8 * RBX , 8 * RCX , 8 * RDX , 8 * RSI , 8 * RDI , 8 * RBP } /* i386 ABI */
2011-06-24 00:10:54 +04:00
} ;
2003-06-02 23:18:58 +04:00
2011-06-24 00:10:54 +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 + + ) {
2011-06-24 00:22:34 +04:00
if ( upeek ( tcp , argreg [ current_personality ] [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2011-06-24 00:10:54 +04:00
return - 1 ;
2002-09-23 19:41:01 +04:00
}
2011-06-24 00:10:54 +04:00
# elif defined(MICROBLAZE)
int i ;
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 , ( 5 + i ) * 4 , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2010-07-06 16:21:07 +04:00
}
2011-06-24 00:10:54 +04:00
# elif defined(CRISV10) || defined(CRISV32)
int i ;
static const int crisregs [ ] = {
4 * PT_ORIG_R10 , 4 * PT_R11 , 4 * PT_R12 ,
2011-06-24 00:22:34 +04:00
4 * PT_R13 , 4 * PT_MOF , 4 * PT_SRP
2011-06-24 00:10:54 +04:00
} ;
2009-02-25 20:08:40 +03:00
2011-06-24 00:10:54 +04:00
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 , crisregs [ i ] , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2009-02-25 20:08:40 +03:00
}
2011-06-24 00:10:54 +04:00
# elif defined(TILE)
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 ) {
if ( upeek ( tcp , PTREGS_OFFSET_REG ( i ) , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2009-12-28 18:00:15 +03:00
}
2011-06-24 00:10:54 +04:00
# elif defined(M68K)
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 + + ) {
if ( upeek ( tcp , ( i < 5 ? i : i + 2 ) * 4 , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2010-06-05 23:50:30 +04:00
}
2011-06-24 00:10:54 +04:00
# else /* Other architecture (like i386) (32bits specific) */
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 + + ) {
if ( upeek ( tcp , i * 4 , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
1999-02-19 03:21:36 +03:00
}
2011-06-24 00:10:54 +04:00
# endif
1999-02-19 03:21:36 +03:00
# endif /* LINUX */
# ifdef SUNOS4
2011-06-24 00:10:54 +04:00
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 + + ) {
struct user * u ;
1999-02-19 03:21:36 +03:00
2011-06-24 00:10:54 +04:00
if ( upeek ( tcp , uoff ( u_arg [ 0 ] ) +
( i * sizeof ( u - > u_arg [ 0 ] ) ) , & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
1999-02-19 03:21:36 +03:00
}
# endif /* SUNOS4 */
# ifdef SVR4
2011-06-24 00:10:54 +04:00
# ifdef MIPS
1999-02-19 03:21:36 +03:00
/*
* 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 ] ,
2011-06-24 00:10:54 +04:00
4 * sizeof ( tcp - > u_arg [ 0 ] ) ) ;
1999-02-19 03:21:36 +03:00
umoven ( tcp , tcp - > status . pr_reg [ CTX_SP ] + 16 ,
2011-06-24 00:10:54 +04:00
( tcp - > u_nargs - 4 ) * sizeof ( tcp - > u_arg [ 0 ] ) , ( char * ) ( tcp - > u_arg + 4 ) ) ;
1999-02-19 03:21:36 +03:00
}
else {
memcpy ( tcp - > u_arg , & tcp - > status . pr_reg [ CTX_A0 ] ,
2011-06-24 00:10:54 +04:00
tcp - > u_nargs * sizeof ( tcp - > u_arg [ 0 ] ) ) ;
1999-02-19 03:21:36 +03:00
}
2011-06-24 00:10:54 +04:00
# elif UNIXWARE >= 2
2001-03-06 13:10:06 +03:00
/*
* 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 ,
2011-06-24 00:10:54 +04:00
tcp - > u_nargs * sizeof ( tcp - > u_arg [ 0 ] ) , ( char * ) tcp - > u_arg ) ;
# elif defined(HAVE_PR_SYSCALL)
int i ;
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 ;
2011-06-24 00:10:54 +04:00
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
tcp - > u_arg [ i ] = tcp - > status . pr_sysarg [ i ] ;
# 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 ;
2011-06-09 03:32:23 +04:00
if ( tcp - > u_nargs > 0 )
umoven ( tcp , tcp - > status . PR_REG [ UESP ] + 4 ,
2011-06-24 00:10:54 +04:00
tcp - > u_nargs * sizeof ( tcp - > u_arg [ 0 ] ) , ( char * ) tcp - > u_arg ) ;
# else
2001-03-06 13:10:06 +03:00
I DONT KNOW WHAT TO DO
2011-06-24 00:10:54 +04:00
# endif
1999-02-19 03:21:36 +03:00
# 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
2009-02-27 23:32:52 +03:00
tcp - > u_nargs = tcp - > status . val ;
2000-09-02 01:03:06 +04:00
if ( tcp - > u_nargs < 0 )
tcp - > u_nargs = 0 ;
if ( tcp - > u_nargs > MAX_ARGS )
tcp - > u_nargs = MAX_ARGS ;
2011-06-07 14:13:24 +04:00
switch ( regs . r_eax ) {
2000-09-02 01:03:06 +04:00
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 ;
}
2010-03-29 21:51:02 +04:00
static int
trace_syscall_exiting ( 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 ;
2010-03-29 21:51:02 +04:00
long u_error ;
2000-02-01 20:58:41 +03:00
2010-03-29 21:51:02 +04:00
/* Measure the exit time as early as possible to avoid errors. */
if ( dtime | | cflag )
gettimeofday ( & tv , NULL ) ;
2008-12-17 22:21:59 +03:00
2010-03-29 21:51:02 +04:00
/* BTW, why we don't just memorize syscall no. on entry
* in tcp - > something ?
*/
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 )
return res ;
if ( res = = 1 )
internal_syscall ( tcp ) ;
2000-02-01 20:58:41 +03:00
2011-04-08 00:25:40 +04:00
if ( res = = 1 & & filtered ( tcp ) ) {
2010-03-29 21:51:02 +04:00
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
2000-02-01 20:58:41 +03:00
2010-03-29 21:51:02 +04:00
if ( tcp - > flags & TCB_REPRINT ) {
printleader ( tcp ) ;
tprintf ( " <... " ) ;
if ( scno_good ! = 1 )
tprintf ( " ???? " ) ;
else if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 )
tprintf ( " syscall_%lu " , tcp - > scno ) ;
else
tprintf ( " %s " , sysent [ tcp - > scno ] . sys_name ) ;
tprintf ( " resumed> " ) ;
}
2000-02-01 20:58:41 +03:00
2010-03-29 21:51:02 +04:00
if ( cflag ) {
struct timeval t = tv ;
2011-08-21 19:47:40 +04:00
count_syscall ( tcp , & t ) ;
2011-06-22 16:32:43 +04:00
if ( cflag = = CFLAG_ONLY_STATS ) {
2008-12-17 22:21:59 +03:00
tcp - > flags & = ~ TCB_INSYSCALL ;
2011-08-21 19:47:40 +04:00
return 0 ;
2008-12-17 22:21:59 +03:00
}
2010-03-29 21:51:02 +04:00
}
2008-12-17 22:21:59 +03:00
2010-03-29 21:51:02 +04:00
if ( res ! = 1 ) {
2000-02-01 20:58:41 +03:00
tprintf ( " ) " ) ;
tabto ( acolumn ) ;
2010-03-29 21:51:02 +04:00
tprintf ( " = ? <unavailable> " ) ;
printtrailer ( ) ;
tcp - > flags & = ~ TCB_INSYSCALL ;
return res ;
}
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0
| | ( qual_flags [ tcp - > scno ] & QUAL_RAW ) )
sys_res = printargs ( tcp ) ;
else {
if ( not_failing_only & & tcp - > u_error )
return 0 ; /* ignore failed syscalls */
sys_res = ( * sysent [ tcp - > scno ] . sys_func ) ( tcp ) ;
}
u_error = tcp - > u_error ;
tprintf ( " ) " ) ;
tabto ( acolumn ) ;
if ( tcp - > scno > = nsyscalls | | tcp - > scno < 0 | |
qual_flags [ tcp - > scno ] & QUAL_RAW ) {
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 ;
case ERESTART_RESTARTBLOCK :
tprintf ( " = ? ERESTART_RESTARTBLOCK (To be restarted) " ) ;
break ;
# endif /* LINUX */
default :
if ( u_error < 0 )
2011-08-21 19:26:55 +04:00
tprintf ( " = -1 E??? (errno %ld) " , u_error ) ;
2010-03-29 21:51:02 +04:00
else if ( u_error < nerrnos )
2011-08-21 19:26:55 +04:00
tprintf ( " = -1 %s (%s) " , errnoent [ u_error ] ,
2010-03-29 21:51:02 +04:00
strerror ( u_error ) ) ;
2000-02-01 20:58:41 +03:00
else
2011-08-21 19:26:55 +04:00
tprintf ( " = -1 ERRNO_%ld (%s) " , u_error ,
2010-03-29 21:51:02 +04:00
strerror ( u_error ) ) ;
break ;
2000-02-01 20:58:41 +03:00
}
2010-03-29 21:51:02 +04:00
if ( ( sys_res & RVAL_STR ) & & tcp - > auxstr )
tprintf ( " (%s) " , tcp - > auxstr ) ;
}
else {
if ( sys_res & RVAL_NONE )
tprintf ( " = ? " ) ;
else {
switch ( sys_res & RVAL_MASK ) {
case RVAL_HEX :
tprintf ( " = %#lx " , tcp - > u_rval ) ;
2000-02-01 20:58:41 +03:00
break ;
2010-03-29 21:51:02 +04:00
case RVAL_OCTAL :
tprintf ( " = %#lo " , tcp - > u_rval ) ;
2000-02-01 20:58:41 +03:00
break ;
2010-03-29 21:51:02 +04:00
case RVAL_UDECIMAL :
tprintf ( " = %lu " , tcp - > u_rval ) ;
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
break ;
2010-03-29 21:51:02 +04:00
case RVAL_DECIMAL :
tprintf ( " = %ld " , tcp - > u_rval ) ;
2000-02-01 20:58:41 +03:00
break ;
2000-08-10 06:14:04 +04:00
# ifdef HAVE_LONG_LONG
2010-03-29 21:51:02 +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 ;
case RVAL_LDECIMAL :
tprintf ( " = %lld " , tcp - > u_lrval ) ;
break ;
2000-08-10 06:14:04 +04:00
# endif
2010-03-29 21:51:02 +04:00
default :
fprintf ( stderr ,
" invalid rval format \n " ) ;
break ;
2000-02-01 20:58:41 +03:00
}
}
2010-03-29 21:51:02 +04:00
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 ) ;
2000-02-01 20:58:41 +03:00
}
2010-03-29 21:51:02 +04:00
printtrailer ( ) ;
dumpio ( tcp ) ;
if ( fflush ( tcp - > outf ) = = EOF )
return - 1 ;
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
static int
trace_syscall_entering ( struct tcb * tcp )
{
int sys_res ;
int res , scno_good ;
2000-02-01 20:58:41 +03:00
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-06-03 03:49:22 +04:00
tcp - > flags & = ~ TCB_REPRINT ;
2008-12-17 22:21:59 +03:00
tcp_last = tcp ;
if ( scno_good ! = 1 )
2009-06-03 03:49:22 +04:00
tprintf ( " ???? " /* 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-06-03 03:49:22 +04:00
/*
* " <unavailable> " will be added later by the code which
* detects ptrace errors .
*/
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 ;
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 ) ;
2011-04-08 00:25:40 +04:00
if ( ( tcp - > scno > = 0 & & tcp - > scno < nsyscalls & &
! ( qual_flags [ tcp - > scno ] & QUAL_TRACE ) ) | |
( tracing_paths & & ! pathtrace_match ( tcp ) ) ) {
tcp - > flags | = TCB_INSYSCALL | TCB_FILTERED ;
1999-02-19 03:21:36 +03:00
return 0 ;
}
2011-04-08 00:25:40 +04:00
tcp - > flags & = ~ TCB_FILTERED ;
2010-03-28 23:24:54 +04:00
if ( cflag = = CFLAG_ONLY_STATS ) {
1999-02-19 03:21:36 +03:00
tcp - > flags | = TCB_INSYSCALL ;
2010-03-28 23:24:54 +04:00
gettimeofday ( & tcp - > etime , NULL ) ;
1999-02-19 03:21:36 +03:00
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 | |
2011-02-19 03:02:27 +03:00
( ( qual_flags [ tcp - > scno ] & QUAL_RAW ) & &
sysent [ tcp - > scno ] . sys_func ! = sys_exit ) )
1999-02-19 03:21:36 +03:00
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. */
2010-03-28 23:24:54 +04:00
if ( dtime | | cflag )
1999-02-19 03:21:36 +03:00
gettimeofday ( & tcp - > etime , NULL ) ;
return sys_res ;
}
2010-03-29 21:51:02 +04:00
int
trace_syscall ( struct tcb * tcp )
{
return exiting ( tcp ) ?
trace_syscall_exiting ( tcp ) : trace_syscall_entering ( tcp ) ;
}
1999-02-19 03:21:36 +03:00
int
2011-05-30 16:00:14 +04:00
printargs ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
if ( entering ( tcp ) ) {
int i ;
for ( i = 0 ; i < tcp - > u_nargs ; i + + )
tprintf ( " %s%#lx " , i ? " , " : " " , tcp - > u_arg [ i ] ) ;
}
return 0 ;
}
long
2011-05-30 16:00:14 +04:00
getrval2 ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
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)
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
struct pt_regs regs ;
2011-06-07 14:13:24 +04:00
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , ( char * ) & regs , 0 ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
sparc/linux: Rewrite to use asm/ptrace.h
The current sparc/linux code uses asm/reg.h, but recent Linux kernels
dropped that header completely. So switch over to the ptrace headers
as those should stick around indefinitely as part of the ABI.
* defs.h [LINUXSPARC] (U_REG_G1, U_REG_O0, U_REG_O1): Define.
* process.c: Drop asm/regs.h include.
[SPARC || SPARC64] (change_syscall): Change struct regs to struct pt_regs.
* signal.c: Drop asm/regs.h include.
(m_siginfo_t): Unify [SPARC || SPARC64] and [MIPS].
[SPARC || SPARC64] (sys_sigreturn): Change struct regs to struct pt_regs.
* syscall.c: Drop asm/regs.h include.
[SPARC || SPARC64] (internal_syscall, get_scno, get_error, force_result,
syscall_enter): Change struct regs to struct pt_regs.
* util.c: Drop asm/regs.h include.
(_hack_syscall5, _ptrace): Delete.
[SPARC || SPARC64] (getpc, printcall, arg_setup_state): Change
struct regs to struct pt_regs.
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
2009-10-12 19:05:14 +04:00
val = regs . u_regs [ U_REG_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
2011-05-30 16:00:14 +04:00
sys_indir ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
int i , scno , nargs ;
if ( entering ( tcp ) ) {
2011-08-20 14:48:18 +04:00
scno = tcp - > u_arg [ 0 ] ;
if ( scno > nsyscalls ) {
1999-02-19 03:21:36 +03:00
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 ;
}