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 .
*/
# include "defs.h"
# include <sys/user.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
2012-02-25 05:44:25 +04:00
# include <sys / reg.h>
2014-10-20 03:02:48 +04:00
# endif
# ifdef HAVE_LINUX_PTRACE_H
2012-02-25 05:44:25 +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
2013-09-24 21:04:32 +04:00
# ifdef HAVE_STRUCT_PTRACE_PEEKSIGINFO_ARGS
# define ptrace_peeksiginfo_args XXX_ptrace_peeksiginfo_args
# endif
2012-02-25 05:44:25 +04:00
# include <linux / ptrace.h>
2013-09-24 21:04:32 +04:00
# undef ptrace_peeksiginfo_args
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
2012-02-25 05:38:52 +04:00
# if defined(SPARC64)
2004-07-07 David S. Miller <davem@nuts.davemloft.net>
* linux/sparc/syscallent.h: Sync with reality.
* linux/sparc/syscall.h (sys_sendfile64, sys_futex, sys_gettid,
sys_sched_setaffinity, sys_sched_getaffinity, sys_setxattr,
sys_lsetxattr, sys_fsetxattr, sys_getxattr, sys_lgetxattr,
sys_fgetxattr, sys_listxattr, sys_llistxattr, sys_flistxattr,
sys_removexattr, sys_lremovexattr, sys_fremovexattr,
sys_remap_file_pages, sys_readahead, sys_tgkill, sys_statfs64,
sys_fstatfs64, sys_clock_settime, sys_clock_gettime,
sys_clock_getres, sys_clock_nanosleep, sys_timer_create,
sys_timer_settime, sys_timer_gettime): New declarations.
* linux/sparc64/dummy2.h, linux/sparc64/syscallent2.h,
linux/sparc64/syscall.h, linux/sparc64/errnoent.h,
linux/sparc64/errnoent1.h, linux/sparc64/errnoent2.h,
linux/sparc64/ioctlent.h, linux/sparc64/ioctlent1.h,
linux/sparc64/ioctlent2.h, linux/sparc64/signalent.h,
linux/sparc64/signalent.h, linux/sparc64/signalent.h,
linux/sparc64/signalent1.h, linux/sparc64/signalent2.h,
linux/sparc64/syscall1.h, linux/sparc64/syscallent.h,
linux/sparc64/syscallent1.h: New files.
* defs.h (LINUXSPARC): Define also when SPARC64.
(LINUX && SPARC64): Set SUPPORTED_PERSONALITIES to 3.
Ignore SIGTRAP after execve by defining TCB_WAITEXECVE.
Define possibly missing __NR_exit_group. Declare getrval2.
* configure.ac (sparc64): New architecture case.
* config.h.in (SPARC64): New define.
* file.c (stat_sparc64): New structure.
(printstat_sparc64): New output routine for that.
(printstat): Call it, if personality is 2.
(printstat64): Likewise.
* util.c: Conditionalize ptrace defines on LINUXSPARC
not LINUX && SPARC.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(_hack_syscall5): Correct trap number when SPARC64.
(PTRACE_WRITE{TEXT,DATA}): Add SPARC64 to ifdef guard.
(getpc): Handle SPARC64 && LINUX.
(printcall): Likewise.
(arg fetching/setting): Use same code for SPARC64 LINUX
as for SPARC.
(setbpt): Handle SPARC64 && LINUX.
(clearbpt): Likewise.
* signal.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(m_siginfo): Use same definition on SPARC64 as SPARC.
(sys_sigreturn): Handle LINUX && SPARC64.
* syscall.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(getscno): Use same static state on SPARC64 as SPARC,
and add SPARC64 handling.
(get_error): Handle LINUX && SPARC64.
(force_result): Likewise.
(syscall_enter): Likewise.
(trace_syscall): Handle sys_socketcall and sys_ipc on SPARC64
just like SPARC.
(getrval2): Handle LINUX && SPARC64.
* process.c: Conditionalize ptrace defines on SPARC and
SPARC64.
(SPARC64 && LINUX): Define r_pc to r_tpc, and PTRACE_FOOREGS
to PTRACE_FOOREGS64 so that more sparc code can be shared
between 64-bit and 32-bit.
(change_syscall): Handle LINUX && SPARC64.
(struct_user_offsets): Ifdef out those which do not exist
on SPARC64.
* net.c (sys_pipe): Handle LINUX && SPARC64.
* ioctl.c: Fix initializer typo for nioctlents2, was
nioctlents1 by accident.
2004-07-12 11:44:08 +04:00
# undef PTRACE_GETREGS
# define PTRACE_GETREGS PTRACE_GETREGS64
# undef PTRACE_SETREGS
# define PTRACE_SETREGS PTRACE_SETREGS64
2012-02-25 05:38:52 +04:00
# endif
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
2012-02-25 05:38:52 +04:00
# if defined(IA64)
2000-02-04 00:58:30 +03:00
# include <asm / ptrace_offsets.h>
# include <asm / rse.h>
# endif
2013-03-18 04:59:27 +04:00
/* for struct iovec */
# include <sys/uio.h>
/* for NT_PRSTATUS */
# ifdef HAVE_ELF_H
2013-02-14 06:29:48 +04:00
# include <elf.h>
# endif
2012-10-24 20:58:16 +04:00
# if defined(AARCH64)
# include <asm / ptrace.h>
2013-02-22 18:44:10 +04:00
# endif
2013-03-25 21:22:07 +04:00
# if defined(XTENSA)
# include <asm / ptrace.h>
# endif
1999-02-19 03:21:36 +03:00
# ifndef NSIG
2012-02-25 05:44:25 +04:00
# warning: NSIG is not defined, using 32
# define NSIG 32
1999-02-19 03:21:36 +03:00
# endif
# 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
Add -e trace=memory option
Add a new 'memory' category for tracing memory mapping related syscalls.
Affected syscalls are: break, brk, get_mempolicy, madvise, mbind,
migrate_pages, mincore, mlock, mlockall, mmap, move_pages, mprotect,
mremap, msync, munlock, munlockall, munmap, remap_file_pages, and
set_mempolicy.
* defs.h (TRACE_MEMORY): New macro.
* syscall.c (lookup_class): Handle trace=memory option.
* strace.1: Document it.
* linux/alpha/syscallent.h: Add TM flag to memory mapping related syscalls.
* linux/arm/syscallent.h: Likewise.
* linux/avr32/syscallent.h: Likewise.
* linux/bfin/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/i386/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/microblaze/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/tile/syscallent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Signed-off-by: Namhyung Kim <namhyung.kim@lge.com>
2012-10-24 06:41:57 +04:00
# define TM TRACE_MEMORY
2011-01-18 20:36:20 +03:00
# define NF SYSCALL_NEVER_FAILS
2011-08-23 15:24:17 +04:00
# define MA MAX_ARGS
2014-04-16 10:33:11 +04:00
# define SI STACKTRACE_INVALIDATE_CACHE
# define SE STACKTRACE_CAPTURE_ON_ENTER
1999-02-19 03:21:36 +03:00
2013-02-22 16:37:36 +04:00
const struct_sysent sysent0 [ ] = {
1999-02-19 03:21:36 +03:00
# include "syscallent.h"
} ;
2013-02-22 16:26:10 +04:00
# if SUPPORTED_PERSONALITIES > 1
static const struct_sysent sysent1 [ ] = {
2012-02-25 05:44:25 +04:00
# include "syscallent1.h"
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
# endif
1999-02-19 03:21:36 +03:00
2013-02-22 16:26:10 +04:00
# if SUPPORTED_PERSONALITIES > 2
static const struct_sysent sysent2 [ ] = {
2012-02-25 05:44:25 +04:00
# include "syscallent2.h"
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
# 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
Add -e trace=memory option
Add a new 'memory' category for tracing memory mapping related syscalls.
Affected syscalls are: break, brk, get_mempolicy, madvise, mbind,
migrate_pages, mincore, mlock, mlockall, mmap, move_pages, mprotect,
mremap, msync, munlock, munlockall, munmap, remap_file_pages, and
set_mempolicy.
* defs.h (TRACE_MEMORY): New macro.
* syscall.c (lookup_class): Handle trace=memory option.
* strace.1: Document it.
* linux/alpha/syscallent.h: Add TM flag to memory mapping related syscalls.
* linux/arm/syscallent.h: Likewise.
* linux/avr32/syscallent.h: Likewise.
* linux/bfin/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/i386/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/microblaze/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/tile/syscallent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Signed-off-by: Namhyung Kim <namhyung.kim@lge.com>
2012-10-24 06:41:57 +04:00
# undef TM
2011-01-18 20:36:20 +03:00
# undef NF
2011-08-23 15:24:17 +04:00
# undef MA
2014-04-16 10:33:11 +04:00
# undef SI
# undef SE
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
/*
ioctl: take all 32 bits of ioctl commands into account
Historically, only 16 bits (8-bit number and 8-bit type) of 32-bit ioctl
commands were used for decoding, which was the source for numerous
annoying collisions like this:
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, MGSL_IOCGPARAMS or MMTIMER_GETRES or MTIOCTOP or SNDCTL_MIDI_MPUMODE, 0x7fffd47f7338) = -1 ENOTTY (Inappropriate ioctl for device)
The solution is to use all 32 bits for decoding, not just "number" and
"type", but also "size" and "direction".
As some architectures override defaults that come from asm-generic/ and
provide alternative definitions for some ioctl commands, we support
per-architecture ioctl definitions and merge them with common
definitions at build time. During the merge, we used to keep both
generic and architecture-specific definitions, now architecture-specific
definitions have precedence over generic ones -- ioctlsort omits
definitions from asm-generic/ for those ioctl names that have different
definitions in asm/.
Additional bits of "direction" are architecture specific -- the number
of bits and their values differ between architectures. To reduce
architecture differences in the source code, we keep "direction" in
symbolic form and compile it in ioctlsort.
Additional bits of "size" are also architecture specific -- not only the
number of bits differ between architectures, but sizes of many types
depend on sizeof(long). To reduce architecture differences in the
source code, we keep 32-bit and 64-bit versions of common ioctl
definitions, and use the appropriate version for each architecture and
personality.
To implement this, the tools for generating ioctl definitions from
kernel headers have been rewritten, and the source format of ioctl
definitions has been extended. The final ioctlent*.h files that are
included by syscall.c are now generated from source ioctls_inc*.h and
ioctls_arch*.h files at build time with ioctlsort.
* ioctl.c (ioctl_lookup): Use all 32 bits of ioctl command code.
* ioctlsort.c: Rewritten.
* linux/32/ioctls_inc.h: New file.
* linux/64/ioctls_inc.h: New file.
* linux/aarch64/ioctls_arch0.h: New file.
* linux/aarch64/ioctls_arch1.h: New file.
* linux/aarch64/ioctls_inc0.h: New file.
* linux/aarch64/ioctls_inc1.h: New file.
* linux/alpha/ioctls_arch0.h: New file.
* linux/alpha/ioctls_inc0.h: New file.
* linux/arc/ioctls_arch0.h: New file.
* linux/arc/ioctls_inc0.h: New file.
* linux/arm/ioctls_arch0.h: New file.
* linux/arm/ioctls_inc0.h: New file.
* linux/avr32/ioctls_arch0.h: New file.
* linux/avr32/ioctls_inc0.h: New file.
* linux/bfin/ioctls_arch0.h: New file.
* linux/bfin/ioctls_inc0.h: New file.
* linux/hppa/ioctls_arch0.h: New file.
* linux/hppa/ioctls_inc0.h: New file.
* linux/i386/ioctls_arch0.h: New file.
* linux/i386/ioctls_inc0.h: New file.
* linux/ia64/ioctls_arch0.h: New file.
* linux/ia64/ioctls_inc0.h: New file.
* linux/m68k/ioctls_arch0.h: New file.
* linux/m68k/ioctls_inc0.h: New file.
* linux/metag/ioctls_arch0.h: New file.
* linux/metag/ioctls_inc0.h: New file.
* linux/microblaze/ioctls_arch0.h: New file.
* linux/microblaze/ioctls_inc0.h: New file.
* linux/mips/ioctls_arch0.h: New file.
* linux/mips/ioctls_inc0.h: New file.
* linux/or1k/ioctls_arch0.h: New file.
* linux/or1k/ioctls_inc0.h: New file.
* linux/powerpc/ioctls_arch0.h: New file.
* linux/powerpc/ioctls_inc0.h: New file.
* linux/powerpc64/ioctls_arch0.h: New file.
* linux/powerpc64/ioctls_arch1.h: New file.
* linux/powerpc64/ioctls_inc0.h: New file.
* linux/powerpc64/ioctls_inc1.h: New file.
* linux/s390/ioctls_arch0.h: New file.
* linux/s390/ioctls_inc0.h: New file.
* linux/s390x/ioctls_arch0.h: New file.
* linux/s390x/ioctls_inc0.h: New file.
* linux/sh/ioctls_arch0.h: New file.
* linux/sh/ioctls_inc0.h: New file.
* linux/sh64/ioctls_arch0.h: New file.
* linux/sh64/ioctls_inc0.h: New file.
* linux/sparc/ioctls_arch0.h: New file.
* linux/sparc/ioctls_inc0.h: New file.
* linux/sparc64/ioctls_arch0.h: New file.
* linux/sparc64/ioctls_arch2.h: New file.
* linux/sparc64/ioctls_inc0.h: New file.
* linux/sparc64/ioctls_inc2.h: New file.
* linux/tile/ioctls_arch0.h: New file.
* linux/tile/ioctls_arch1.h: New file.
* linux/tile/ioctls_inc0.h: New file.
* linux/tile/ioctls_inc1.h: New file.
* linux/x32/ioctls_arch0.h: New file.
* linux/x32/ioctls_arch1.h: New file.
* linux/x32/ioctls_inc0.h: New file.
* linux/x32/ioctls_inc1.h: New file.
* linux/x86_64/ioctls_arch0.h: New file.
* linux/x86_64/ioctls_arch1.h: New file.
* linux/x86_64/ioctls_inc0.h: New file.
* linux/x86_64/ioctls_inc1.h: New file.
* linux/xtensa/ioctls_arch0.h: New file.
* linux/xtensa/ioctls_inc0.h: New file.
* linux/aarch64/ioctlent.h.in: Remove.
* linux/aarch64/ioctlent1.h: Remove.
* linux/alpha/ioctlent.h.in: Remove.
* linux/arc/ioctlent.h.in: Remove.
* linux/arm/ioctlent.h.in: Remove.
* linux/avr32/ioctlent.h.in: Remove.
* linux/bfin/ioctlent.h.in: Remove.
* linux/hppa/ioctlent.h.in: Remove.
* linux/i386/ioctlent.h.in: Remove.
* linux/ia64/ioctlent.h.in: Remove.
* linux/ioctlent.h.in: Remove.
* linux/ioctlent.sh: Remove.
* linux/m68k/ioctlent.h.in: Remove.
* linux/metag/ioctlent.h.in: Remove.
* linux/microblaze/ioctlent.h.in: Remove.
* linux/mips/ioctlent.h.in: Remove.
* linux/mips/ioctlent.sh: Remove.
* linux/or1k/ioctlent.h.in: Remove.
* linux/powerpc/ioctlent.h.in: Remove.
* linux/powerpc64/ioctlent.h: Remove.
* linux/powerpc64/ioctlent1.h: Remove.
* linux/s390/ioctlent.h.in: Remove.
* linux/s390x/ioctlent.h.in: Remove.
* linux/sh/ioctlent.h.in: Remove.
* linux/sh64/ioctlent.h.in: Remove.
* linux/sparc/ioctlent.h.in: Remove.
* linux/sparc64/ioctlent.h.in: Remove.
* linux/sparc64/ioctlent2.h: Remove.
* linux/tile/ioctlent.h.in: Remove.
* linux/tile/ioctlent1.h: Remove.
* linux/x32/ioctlent.h.in: Remove.
* linux/x32/ioctlent1.h: Remove.
* linux/x86_64/ioctlent.h.in: Remove.
* linux/x86_64/ioctlent1.h: Remove.
* linux/xtensa/ioctlent.h.in: Remove.
* linux/x86_64/ioctlent2.h: Include ioctlent0.h instead of ioctlent.h.
* syscall.c (struct_ioctlent ioctlent0): Likewise.
* Makefile.am: Remove all ioctlent-related definitions.
Define the list of ioctlent*.h files that have to be generated by
presence of $(srcdir)/$(OS)/$(ARCH)/ioctls_inc*.h files.
Add rules for ioctlent*.h files generation.
(EXTRA_DIST): Update.
* maint/ioctls_gen.sh: New file.
* maint/ioctls_hex.sh: New file.
* maint/ioctls_sym.sh: New file.
* maint/print_ioctlent.c: New file.
* HACKING-scripts: Update for ioctlent.sh -> ioctls_gen.sh migration.
* .gitignore: Add ioctlent[012].h and ioctls_all[012].h.
* configure.ac (AC_CHECK_HEADERS): Add linux/hiddev.h
and linux/mmtimer.h for tests.
* tests/ioctl.c: New file.
* tests/ioctl.test: New test.
* tests/Makefile.am (check_PROGRAMS): Add ioctl.
(TESTS): Add ioctl.test.
* tests/.gitignore: Add ioctl.
2015-01-19 20:02:16 +03:00
* ` ioctlent [ 012 ] . h ' files are automatically generated by the auxiliary
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
* 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 " .
*/
2013-02-22 16:37:36 +04:00
const char * const errnoent0 [ ] = {
1999-02-19 03:21:36 +03:00
# include "errnoent.h"
} ;
2013-02-22 16:37:36 +04:00
const char * const signalent0 [ ] = {
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
# include "signalent.h"
} ;
2013-02-22 16:37:36 +04:00
const struct_ioctlent ioctlent0 [ ] = {
ioctl: take all 32 bits of ioctl commands into account
Historically, only 16 bits (8-bit number and 8-bit type) of 32-bit ioctl
commands were used for decoding, which was the source for numerous
annoying collisions like this:
ioctl(0, SNDCTL_TMR_TIMEBASE or SNDRV_TIMER_IOCTL_NEXT_DEVICE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(0, MGSL_IOCGPARAMS or MMTIMER_GETRES or MTIOCTOP or SNDCTL_MIDI_MPUMODE, 0x7fffd47f7338) = -1 ENOTTY (Inappropriate ioctl for device)
The solution is to use all 32 bits for decoding, not just "number" and
"type", but also "size" and "direction".
As some architectures override defaults that come from asm-generic/ and
provide alternative definitions for some ioctl commands, we support
per-architecture ioctl definitions and merge them with common
definitions at build time. During the merge, we used to keep both
generic and architecture-specific definitions, now architecture-specific
definitions have precedence over generic ones -- ioctlsort omits
definitions from asm-generic/ for those ioctl names that have different
definitions in asm/.
Additional bits of "direction" are architecture specific -- the number
of bits and their values differ between architectures. To reduce
architecture differences in the source code, we keep "direction" in
symbolic form and compile it in ioctlsort.
Additional bits of "size" are also architecture specific -- not only the
number of bits differ between architectures, but sizes of many types
depend on sizeof(long). To reduce architecture differences in the
source code, we keep 32-bit and 64-bit versions of common ioctl
definitions, and use the appropriate version for each architecture and
personality.
To implement this, the tools for generating ioctl definitions from
kernel headers have been rewritten, and the source format of ioctl
definitions has been extended. The final ioctlent*.h files that are
included by syscall.c are now generated from source ioctls_inc*.h and
ioctls_arch*.h files at build time with ioctlsort.
* ioctl.c (ioctl_lookup): Use all 32 bits of ioctl command code.
* ioctlsort.c: Rewritten.
* linux/32/ioctls_inc.h: New file.
* linux/64/ioctls_inc.h: New file.
* linux/aarch64/ioctls_arch0.h: New file.
* linux/aarch64/ioctls_arch1.h: New file.
* linux/aarch64/ioctls_inc0.h: New file.
* linux/aarch64/ioctls_inc1.h: New file.
* linux/alpha/ioctls_arch0.h: New file.
* linux/alpha/ioctls_inc0.h: New file.
* linux/arc/ioctls_arch0.h: New file.
* linux/arc/ioctls_inc0.h: New file.
* linux/arm/ioctls_arch0.h: New file.
* linux/arm/ioctls_inc0.h: New file.
* linux/avr32/ioctls_arch0.h: New file.
* linux/avr32/ioctls_inc0.h: New file.
* linux/bfin/ioctls_arch0.h: New file.
* linux/bfin/ioctls_inc0.h: New file.
* linux/hppa/ioctls_arch0.h: New file.
* linux/hppa/ioctls_inc0.h: New file.
* linux/i386/ioctls_arch0.h: New file.
* linux/i386/ioctls_inc0.h: New file.
* linux/ia64/ioctls_arch0.h: New file.
* linux/ia64/ioctls_inc0.h: New file.
* linux/m68k/ioctls_arch0.h: New file.
* linux/m68k/ioctls_inc0.h: New file.
* linux/metag/ioctls_arch0.h: New file.
* linux/metag/ioctls_inc0.h: New file.
* linux/microblaze/ioctls_arch0.h: New file.
* linux/microblaze/ioctls_inc0.h: New file.
* linux/mips/ioctls_arch0.h: New file.
* linux/mips/ioctls_inc0.h: New file.
* linux/or1k/ioctls_arch0.h: New file.
* linux/or1k/ioctls_inc0.h: New file.
* linux/powerpc/ioctls_arch0.h: New file.
* linux/powerpc/ioctls_inc0.h: New file.
* linux/powerpc64/ioctls_arch0.h: New file.
* linux/powerpc64/ioctls_arch1.h: New file.
* linux/powerpc64/ioctls_inc0.h: New file.
* linux/powerpc64/ioctls_inc1.h: New file.
* linux/s390/ioctls_arch0.h: New file.
* linux/s390/ioctls_inc0.h: New file.
* linux/s390x/ioctls_arch0.h: New file.
* linux/s390x/ioctls_inc0.h: New file.
* linux/sh/ioctls_arch0.h: New file.
* linux/sh/ioctls_inc0.h: New file.
* linux/sh64/ioctls_arch0.h: New file.
* linux/sh64/ioctls_inc0.h: New file.
* linux/sparc/ioctls_arch0.h: New file.
* linux/sparc/ioctls_inc0.h: New file.
* linux/sparc64/ioctls_arch0.h: New file.
* linux/sparc64/ioctls_arch2.h: New file.
* linux/sparc64/ioctls_inc0.h: New file.
* linux/sparc64/ioctls_inc2.h: New file.
* linux/tile/ioctls_arch0.h: New file.
* linux/tile/ioctls_arch1.h: New file.
* linux/tile/ioctls_inc0.h: New file.
* linux/tile/ioctls_inc1.h: New file.
* linux/x32/ioctls_arch0.h: New file.
* linux/x32/ioctls_arch1.h: New file.
* linux/x32/ioctls_inc0.h: New file.
* linux/x32/ioctls_inc1.h: New file.
* linux/x86_64/ioctls_arch0.h: New file.
* linux/x86_64/ioctls_arch1.h: New file.
* linux/x86_64/ioctls_inc0.h: New file.
* linux/x86_64/ioctls_inc1.h: New file.
* linux/xtensa/ioctls_arch0.h: New file.
* linux/xtensa/ioctls_inc0.h: New file.
* linux/aarch64/ioctlent.h.in: Remove.
* linux/aarch64/ioctlent1.h: Remove.
* linux/alpha/ioctlent.h.in: Remove.
* linux/arc/ioctlent.h.in: Remove.
* linux/arm/ioctlent.h.in: Remove.
* linux/avr32/ioctlent.h.in: Remove.
* linux/bfin/ioctlent.h.in: Remove.
* linux/hppa/ioctlent.h.in: Remove.
* linux/i386/ioctlent.h.in: Remove.
* linux/ia64/ioctlent.h.in: Remove.
* linux/ioctlent.h.in: Remove.
* linux/ioctlent.sh: Remove.
* linux/m68k/ioctlent.h.in: Remove.
* linux/metag/ioctlent.h.in: Remove.
* linux/microblaze/ioctlent.h.in: Remove.
* linux/mips/ioctlent.h.in: Remove.
* linux/mips/ioctlent.sh: Remove.
* linux/or1k/ioctlent.h.in: Remove.
* linux/powerpc/ioctlent.h.in: Remove.
* linux/powerpc64/ioctlent.h: Remove.
* linux/powerpc64/ioctlent1.h: Remove.
* linux/s390/ioctlent.h.in: Remove.
* linux/s390x/ioctlent.h.in: Remove.
* linux/sh/ioctlent.h.in: Remove.
* linux/sh64/ioctlent.h.in: Remove.
* linux/sparc/ioctlent.h.in: Remove.
* linux/sparc64/ioctlent.h.in: Remove.
* linux/sparc64/ioctlent2.h: Remove.
* linux/tile/ioctlent.h.in: Remove.
* linux/tile/ioctlent1.h: Remove.
* linux/x32/ioctlent.h.in: Remove.
* linux/x32/ioctlent1.h: Remove.
* linux/x86_64/ioctlent.h.in: Remove.
* linux/x86_64/ioctlent1.h: Remove.
* linux/xtensa/ioctlent.h.in: Remove.
* linux/x86_64/ioctlent2.h: Include ioctlent0.h instead of ioctlent.h.
* syscall.c (struct_ioctlent ioctlent0): Likewise.
* Makefile.am: Remove all ioctlent-related definitions.
Define the list of ioctlent*.h files that have to be generated by
presence of $(srcdir)/$(OS)/$(ARCH)/ioctls_inc*.h files.
Add rules for ioctlent*.h files generation.
(EXTRA_DIST): Update.
* maint/ioctls_gen.sh: New file.
* maint/ioctls_hex.sh: New file.
* maint/ioctls_sym.sh: New file.
* maint/print_ioctlent.c: New file.
* HACKING-scripts: Update for ioctlent.sh -> ioctls_gen.sh migration.
* .gitignore: Add ioctlent[012].h and ioctls_all[012].h.
* configure.ac (AC_CHECK_HEADERS): Add linux/hiddev.h
and linux/mmtimer.h for tests.
* tests/ioctl.c: New file.
* tests/ioctl.test: New test.
* tests/Makefile.am (check_PROGRAMS): Add ioctl.
(TESTS): Add ioctl.test.
* tests/.gitignore: Add ioctl.
2015-01-19 20:02:16 +03:00
# include "ioctlent0.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
} ;
1999-02-19 03:21:36 +03:00
2013-02-22 16:26:10 +04:00
# if SUPPORTED_PERSONALITIES > 1
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 [ ] = {
2012-02-25 05:44:25 +04:00
# include "errnoent1.h"
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
static const char * const signalent1 [ ] = {
2012-02-25 05:44:25 +04:00
# include "signalent1.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
} ;
2013-02-22 16:26:10 +04:00
static const struct_ioctlent ioctlent1 [ ] = {
2012-02-25 05:44:25 +04:00
# include "ioctlent1.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
2013-02-22 16:26:10 +04: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 errnoent2 [ ] = {
2012-02-25 05:44:25 +04:00
# include "errnoent2.h"
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
static const char * const signalent2 [ ] = {
2012-02-25 05:44:25 +04:00
# include "signalent2.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
} ;
2013-02-22 16:26:10 +04:00
static const struct_ioctlent ioctlent2 [ ] = {
2012-02-25 05:44:25 +04:00
# include "ioctlent2.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
2013-02-27 02:02:30 +04:00
enum {
nsyscalls0 = ARRAY_SIZE ( sysent0 )
# if SUPPORTED_PERSONALITIES > 1
, nsyscalls1 = ARRAY_SIZE ( sysent1 )
# if SUPPORTED_PERSONALITIES > 2
, nsyscalls2 = ARRAY_SIZE ( sysent2 )
# endif
# endif
} ;
enum {
nerrnos0 = ARRAY_SIZE ( errnoent0 )
# if SUPPORTED_PERSONALITIES > 1
, nerrnos1 = ARRAY_SIZE ( errnoent1 )
# if SUPPORTED_PERSONALITIES > 2
, nerrnos2 = ARRAY_SIZE ( errnoent2 )
# endif
# endif
} ;
enum {
nsignals0 = ARRAY_SIZE ( signalent0 )
# if SUPPORTED_PERSONALITIES > 1
, nsignals1 = ARRAY_SIZE ( signalent1 )
# if SUPPORTED_PERSONALITIES > 2
, nsignals2 = ARRAY_SIZE ( signalent2 )
# endif
# endif
} ;
enum {
nioctlents0 = ARRAY_SIZE ( ioctlent0 )
# if SUPPORTED_PERSONALITIES > 1
, nioctlents1 = ARRAY_SIZE ( ioctlent1 )
# if SUPPORTED_PERSONALITIES > 2
, nioctlents2 = ARRAY_SIZE ( ioctlent2 )
# endif
# endif
} ;
2013-02-22 16:37:36 +04:00
# if SUPPORTED_PERSONALITIES > 1
2013-02-22 16:26:10 +04:00
const struct_sysent * sysent = sysent0 ;
2012-03-19 12:36:42 +04:00
const char * const * errnoent = errnoent0 ;
const char * const * signalent = signalent0 ;
2013-02-22 16:26:10 +04:00
const struct_ioctlent * ioctlent = ioctlent0 ;
2013-02-22 16:37:36 +04:00
# endif
2012-03-19 12:36:42 +04:00
unsigned nsyscalls = nsyscalls0 ;
unsigned nerrnos = nerrnos0 ;
unsigned nsignals = nsignals0 ;
unsigned nioctlents = nioctlents0 ;
2013-02-22 16:37:36 +04:00
unsigned num_quals ;
qualbits_t * qual_vec [ SUPPORTED_PERSONALITIES ] ;
static const unsigned nsyscall_vec [ SUPPORTED_PERSONALITIES ] = {
nsyscalls0 ,
# if SUPPORTED_PERSONALITIES > 1
nsyscalls1 ,
# endif
# if SUPPORTED_PERSONALITIES > 2
nsyscalls2 ,
# endif
} ;
static const struct_sysent * const sysent_vec [ SUPPORTED_PERSONALITIES ] = {
sysent0 ,
# if SUPPORTED_PERSONALITIES > 1
sysent1 ,
# endif
# if SUPPORTED_PERSONALITIES > 2
sysent2 ,
# endif
} ;
enum {
MAX_NSYSCALLS1 = ( nsyscalls0
# if SUPPORTED_PERSONALITIES > 1
> nsyscalls1 ? nsyscalls0 : nsyscalls1
# endif
) ,
MAX_NSYSCALLS2 = ( MAX_NSYSCALLS1
# if SUPPORTED_PERSONALITIES > 2
> nsyscalls2 ? MAX_NSYSCALLS1 : nsyscalls2
# endif
) ,
MAX_NSYSCALLS = MAX_NSYSCALLS2 ,
/* We are ready for arches with up to 255 signals,
* even though the largest known signo is on MIPS and it is 128.
* The number of existing syscalls on all arches is
* larger that 255 anyway , so it is just a pedantic matter .
*/
MIN_QUALS = MAX_NSYSCALLS > 255 ? MAX_NSYSCALLS : 255
} ;
1999-02-19 03:21:36 +03:00
2012-03-19 12:36:42 +04:00
# if SUPPORTED_PERSONALITIES > 1
2013-02-15 17:55:14 +04:00
unsigned current_personality ;
1999-02-19 03:21:36 +03:00
2013-02-15 17:55:14 +04:00
# ifndef current_wordsize
unsigned current_wordsize ;
static const int personality_wordsize [ SUPPORTED_PERSONALITIES ] = {
2006-01-12 13:18:53 +03:00
PERSONALITY0_WORDSIZE ,
PERSONALITY1_WORDSIZE ,
2012-03-19 12:36:42 +04:00
# if SUPPORTED_PERSONALITIES > 2
2006-01-12 13:18:53 +03:00
PERSONALITY2_WORDSIZE ,
2012-03-19 12:36:42 +04:00
# endif
2011-08-20 03:50:09 +04:00
} ;
2013-02-15 17:55:14 +04:00
# endif
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
{
2013-02-22 16:37:36 +04:00
nsyscalls = nsyscall_vec [ personality ] ;
sysent = sysent_vec [ personality ] ;
1999-02-19 03:21:36 +03:00
switch ( personality ) {
case 0 :
errnoent = errnoent0 ;
nerrnos = nerrnos0 ;
ioctlent = ioctlent0 ;
nioctlents = nioctlents0 ;
signalent = signalent0 ;
nsignals = nsignals0 ;
break ;
case 1 :
errnoent = errnoent1 ;
nerrnos = nerrnos1 ;
ioctlent = ioctlent1 ;
nioctlents = nioctlents1 ;
signalent = signalent1 ;
nsignals = nsignals1 ;
break ;
2013-02-22 16:26:10 +04:00
# if SUPPORTED_PERSONALITIES > 2
1999-02-19 03:21:36 +03:00
case 2 :
errnoent = errnoent2 ;
nerrnos = nerrnos2 ;
ioctlent = ioctlent2 ;
nioctlents = nioctlents2 ;
signalent = signalent2 ;
nsignals = nsignals2 ;
break ;
2012-03-19 12:36:42 +04:00
# endif
1999-02-19 03:21:36 +03:00
}
current_personality = personality ;
2013-02-15 17:55:14 +04:00
# ifndef current_wordsize
current_wordsize = personality_wordsize [ personality ] ;
# endif
1999-02-19 03:21:36 +03:00
}
2011-12-23 04:50:49 +04:00
static void
2014-09-10 17:46:04 +04:00
update_personality ( struct tcb * tcp , unsigned int personality )
2011-12-23 04:50:49 +04:00
{
if ( personality = = current_personality )
return ;
set_personality ( personality ) ;
if ( personality = = tcp - > currpers )
return ;
tcp - > currpers = personality ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# if defined(POWERPC64)
2011-12-23 04:50:49 +04:00
if ( ! qflag ) {
static const char * const names [ ] = { " 64 bit " , " 32 bit " } ;
fprintf ( stderr , " [ Process PID=%d runs in %s mode. ] \n " ,
tcp - > pid , names [ personality ] ) ;
}
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# elif defined(X86_64)
if ( ! qflag ) {
static const char * const names [ ] = { " 64 bit " , " 32 bit " , " x32 " } ;
fprintf ( stderr , " [ Process PID=%d runs in %s mode. ] \n " ,
tcp - > pid , names [ personality ] ) ;
}
2012-04-17 22:05:04 +04:00
# elif defined(X32)
if ( ! qflag ) {
static const char * const names [ ] = { " x32 " , " 32 bit " } ;
fprintf ( stderr , " [ Process PID=%d runs in %s mode. ] \n " ,
tcp - > pid , names [ personality ] ) ;
}
2012-11-10 15:24:48 +04:00
# elif defined(AARCH64)
if ( ! qflag ) {
2013-02-08 15:38:51 +04:00
static const char * const names [ ] = { " 32-bit " , " AArch64 " } ;
2012-11-10 15:24:48 +04:00
fprintf ( stderr , " [ Process PID=%d runs in %s mode. ] \n " ,
tcp - > pid , names [ personality ] ) ;
}
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
# elif defined(TILE)
if ( ! qflag ) {
static const char * const names [ ] = { " 64-bit " , " 32-bit " } ;
fprintf ( stderr , " [ Process PID=%d runs in %s mode. ] \n " ,
tcp - > pid , names [ personality ] ) ;
}
2012-02-25 05:44:25 +04:00
# endif
2011-12-23 04:50:49 +04:00
}
# endif
2004-09-04 08:20:43 +04:00
2013-02-21 19:17:08 +04:00
static int qual_syscall ( ) , qual_signal ( ) , qual_desc ( ) ;
1999-02-19 03:21:36 +03:00
2004-09-04 08:20:43 +04:00
static const struct qual_options {
2014-09-10 17:46:04 +04:00
unsigned 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_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 } ,
} ;
2013-02-22 16:37:36 +04:00
static void
2014-09-10 17:46:04 +04:00
reallocate_qual ( const unsigned int n )
2013-02-22 16:37:36 +04:00
{
unsigned p ;
qualbits_t * qp ;
for ( p = 0 ; p < SUPPORTED_PERSONALITIES ; p + + ) {
qp = qual_vec [ p ] = realloc ( qual_vec [ p ] , n * sizeof ( qualbits_t ) ) ;
if ( ! qp )
die_out_of_memory ( ) ;
memset ( & qp [ num_quals ] , 0 , ( n - num_quals ) * sizeof ( qualbits_t ) ) ;
}
num_quals = n ;
}
2002-12-30 13:23:00 +03:00
static void
2014-09-10 17:46:04 +04:00
qualify_one ( const unsigned int n , unsigned int bitflag , const int not , const int pers )
2002-12-30 13:23:00 +03:00
{
2014-09-10 17:46:04 +04:00
int p ;
2006-01-12 12:50:49 +03:00
2013-02-22 16:37:36 +04:00
if ( num_quals < = n )
reallocate_qual ( n + 1 ) ;
2006-01-12 12:50:49 +03:00
2013-02-22 16:37:36 +04:00
for ( p = 0 ; p < SUPPORTED_PERSONALITIES ; p + + ) {
if ( pers = = p | | pers < 0 ) {
if ( not )
qual_vec [ p ] [ n ] & = ~ bitflag ;
else
qual_vec [ p ] [ n ] | = bitflag ;
}
2006-01-12 12:50:49 +03:00
}
2002-12-30 13:23:00 +03:00
}
1999-02-19 03:21:36 +03:00
static int
2014-09-10 17:46:04 +04:00
qual_syscall ( const char * s , const unsigned int bitflag , const int not )
1999-02-19 03:21:36 +03:00
{
2014-09-10 17:46:04 +04:00
int p ;
unsigned int i ;
2005-02-02 07:40:11 +03:00
int rc = - 1 ;
1999-02-19 03:21:36 +03:00
2012-03-23 14:29:01 +04:00
if ( * s > = ' 0 ' & & * s < = ' 9 ' ) {
2013-02-22 16:37:36 +04:00
i = string_to_uint ( s ) ;
2013-02-23 21:19:28 +04:00
if ( i > = MAX_NSYSCALLS )
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
}
2006-01-12 12:50:49 +03:00
2013-02-22 16:37:36 +04:00
for ( p = 0 ; p < SUPPORTED_PERSONALITIES ; p + + ) {
for ( i = 0 ; i < nsyscall_vec [ p ] ; i + + ) {
if ( sysent_vec [ p ] [ i ] . sys_name
& & strcmp ( s , sysent_vec [ p ] [ i ] . sys_name ) = = 0
) {
2013-03-01 19:50:22 +04:00
qualify_one ( i , bitflag , not , p ) ;
2013-02-22 16:37:36 +04:00
rc = 0 ;
}
2006-01-12 12:50:49 +03:00
}
2013-02-22 16:37:36 +04:00
}
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
2014-09-10 17:46:04 +04:00
qual_signal ( const char * s , const unsigned int bitflag , const int not )
1999-02-19 03:21:36 +03:00
{
2014-09-10 17:46:04 +04:00
unsigned int i ;
1999-02-19 03:21:36 +03:00
2012-03-23 14:29:01 +04:00
if ( * s > = ' 0 ' & & * s < = ' 9 ' ) {
2012-03-26 01:49:48 +04:00
int signo = string_to_uint ( s ) ;
2013-02-22 16:37:36 +04:00
if ( signo < 0 | | signo > 255 )
2009-02-27 23:32:52 +03:00
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
}
2010-09-07 02:08:24 +04:00
if ( strncasecmp ( s , " SIG " , 3 ) = = 0 )
1999-02-19 03:21:36 +03:00
s + = 3 ;
2012-03-23 14:29:01 +04: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
}
2012-03-23 14:29:01 +04:00
}
2005-02-02 06:51:18 +03:00
return - 1 ;
1999-02-19 03:21:36 +03:00
}
static int
2014-09-10 17:46:04 +04:00
qual_desc ( const char * s , const unsigned int bitflag , const int not )
1999-02-19 03:21:36 +03:00
{
2012-03-23 14:29:01 +04:00
if ( * s > = ' 0 ' & & * s < = ' 9 ' ) {
2012-03-26 01:49:48 +04:00
int desc = string_to_uint ( s ) ;
2013-02-22 16:37:36 +04:00
if ( desc < 0 | | desc > 0x7fff ) /* paranoia */
2005-02-02 07:40:11 +03:00
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 ;
Add -e trace=memory option
Add a new 'memory' category for tracing memory mapping related syscalls.
Affected syscalls are: break, brk, get_mempolicy, madvise, mbind,
migrate_pages, mincore, mlock, mlockall, mmap, move_pages, mprotect,
mremap, msync, munlock, munlockall, munmap, remap_file_pages, and
set_mempolicy.
* defs.h (TRACE_MEMORY): New macro.
* syscall.c (lookup_class): Handle trace=memory option.
* strace.1: Document it.
* linux/alpha/syscallent.h: Add TM flag to memory mapping related syscalls.
* linux/arm/syscallent.h: Likewise.
* linux/avr32/syscallent.h: Likewise.
* linux/bfin/syscallent.h: Likewise.
* linux/hppa/syscallent.h: Likewise.
* linux/i386/syscallent.h: Likewise.
* linux/ia64/syscallent.h: Likewise.
* linux/m68k/syscallent.h: Likewise.
* linux/microblaze/syscallent.h: Likewise.
* linux/mips/syscallent.h: Likewise.
* linux/powerpc/syscallent.h: Likewise.
* linux/s390/syscallent.h: Likewise.
* linux/s390x/syscallent.h: Likewise.
* linux/sh/syscallent.h: Likewise.
* linux/sh64/syscallent.h: Likewise.
* linux/sparc/syscallent.h: Likewise.
* linux/tile/syscallent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/syscallent.h: Likewise.
Signed-off-by: Namhyung Kim <namhyung.kim@lge.com>
2012-10-24 06:41:57 +04:00
if ( strcmp ( s , " memory " ) = = 0 )
return TRACE_MEMORY ;
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 ;
2010-09-07 02:08:24 +04:00
char * copy ;
const char * p ;
2014-09-10 17:46:04 +04:00
int not ;
unsigned int i ;
1999-02-19 03:21:36 +03:00
2013-02-22 16:37:36 +04:00
if ( num_quals = = 0 )
reallocate_qual ( MIN_QUALS ) ;
1999-02-19 03:21:36 +03:00
opt = & qual_options [ 0 ] ;
for ( i = 0 ; ( p = qual_options [ i ] . option_name ) ; i + + ) {
2014-09-10 17:46:04 +04:00
unsigned int len = strlen ( p ) ;
if ( strncmp ( s , p , len ) = = 0 & & s [ len ] = = ' = ' ) {
1999-02-19 03:21:36 +03:00
opt = & qual_options [ i ] ;
2014-09-10 17:46:04 +04:00
s + = len + 1 ;
1999-02-19 03:21:36 +03:00
break ;
}
}
not = 0 ;
if ( * s = = ' ! ' ) {
not = 1 ;
s + + ;
}
if ( strcmp ( s , " none " ) = = 0 ) {
not = 1 - not ;
s = " all " ;
}
if ( strcmp ( s , " all " ) = = 0 ) {
2013-02-22 16:37:36 +04:00
for ( i = 0 ; i < num_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 ;
}
2013-02-22 16:37:36 +04:00
for ( i = 0 ; i < num_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 ) ;
2011-08-31 16:00:02 +04:00
if ( ! copy )
die_out_of_memory ( ) ;
2010-09-07 02:08:24 +04:00
for ( p = strtok ( copy , " , " ) ; p ; p = strtok ( NULL , " , " ) ) {
2014-09-10 17:46:04 +04:00
int n ;
1999-02-19 03:21:36 +03:00
if ( opt - > bitflag = = QUAL_TRACE & & ( n = lookup_class ( p ) ) > 0 ) {
2013-02-22 16:37:36 +04:00
unsigned pers ;
for ( pers = 0 ; pers < SUPPORTED_PERSONALITIES ; pers + + ) {
for ( i = 0 ; i < nsyscall_vec [ pers ] ; i + + )
if ( sysent_vec [ pers ] [ i ] . sys_flags & n )
2013-03-01 19:50:22 +04:00
qualify_one ( i , opt - > bitflag , not , pers ) ;
2013-02-22 16:37:36 +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 ) ) {
2012-03-08 14:54:10 +04:00
error_msg_and_die ( " invalid %s '%s' " ,
1999-02-19 03:21:36 +03:00
opt - > argument_name , p ) ;
}
}
2010-09-07 02:08:24 +04:00
free ( copy ) ;
1999-02-19 03:21:36 +03:00
return ;
}
2012-03-16 02:08:55 +04:00
# ifdef SYS_socket_subcall
2005-06-09 00:45:28 +04:00
static void
2012-03-16 02:08:55 +04:00
decode_socket_subcall ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
2012-03-16 02:08:55 +04:00
unsigned long addr ;
2013-02-21 19:13:47 +04:00
unsigned int i , n , size ;
2012-03-16 02:08:55 +04:00
if ( tcp - > u_arg [ 0 ] < 0 | | tcp - > u_arg [ 0 ] > = SYS_socket_nsubcalls )
return ;
tcp - > scno = SYS_socket_subcall + tcp - > u_arg [ 0 ] ;
2013-02-21 19:13:47 +04:00
tcp - > qual_flg = qual_flags [ tcp - > scno ] ;
tcp - > s_ent = & sysent [ tcp - > scno ] ;
2012-03-16 02:08:55 +04:00
addr = tcp - > u_arg [ 1 ] ;
2012-03-19 12:36:42 +04:00
size = current_wordsize ;
2013-02-21 19:13:47 +04:00
n = tcp - > s_ent - > nargs ;
for ( i = 0 ; i < n ; + + i ) {
2012-03-16 02:08:55 +04:00
if ( size = = sizeof ( int ) ) {
unsigned int arg ;
if ( umove ( tcp , addr , & arg ) < 0 )
arg = 0 ;
tcp - > u_arg [ i ] = arg ;
1999-02-19 03:21:36 +03:00
}
2012-03-16 02:08:55 +04:00
else {
unsigned long arg ;
if ( umove ( tcp , addr , & arg ) < 0 )
arg = 0 ;
tcp - > u_arg [ i ] = arg ;
}
addr + = size ;
1999-02-19 03:21:36 +03:00
}
}
2012-03-16 02:08:55 +04:00
# endif
# ifdef SYS_ipc_subcall
static void
decode_ipc_subcall ( struct tcb * tcp )
{
2013-02-21 19:13:47 +04:00
unsigned int i , n ;
2012-03-16 02:08:55 +04:00
if ( tcp - > u_arg [ 0 ] < 0 | | tcp - > u_arg [ 0 ] > = SYS_ipc_nsubcalls )
return ;
2012-03-15 09:09:19 +04:00
2012-03-16 02:08:55 +04:00
tcp - > scno = SYS_ipc_subcall + tcp - > u_arg [ 0 ] ;
2013-02-21 19:13:47 +04:00
tcp - > qual_flg = qual_flags [ tcp - > scno ] ;
tcp - > s_ent = & sysent [ tcp - > scno ] ;
n = tcp - > s_ent - > nargs ;
for ( i = 0 ; i < n ; i + + )
2012-03-16 02:08:55 +04:00
tcp - > u_arg [ i ] = tcp - > u_arg [ i + 1 ] ;
}
# endif
1999-02-19 03:21:36 +03:00
2011-08-24 20:07:22 +04:00
int
printargs ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
2011-08-24 20:07:22 +04:00
if ( entering ( tcp ) ) {
int i ;
2013-02-21 19:13:47 +04:00
int n = tcp - > s_ent - > nargs ;
for ( i = 0 ; i < n ; i + + )
2011-08-24 20:07:22 +04:00
tprintf ( " %s%#lx " , i ? " , " : " " , tcp - > u_arg [ i ] ) ;
}
return 0 ;
}
2006-12-21 14:44:28 +03:00
2012-02-27 17:18:02 +04:00
int
printargs_lu ( struct tcb * tcp )
{
if ( entering ( tcp ) ) {
int i ;
2013-02-21 19:13:47 +04:00
int n = tcp - > s_ent - > nargs ;
for ( i = 0 ; i < n ; i + + )
2012-02-27 17:18:02 +04:00
tprintf ( " %s%lu " , i ? " , " : " " , tcp - > u_arg [ i ] ) ;
}
return 0 ;
}
int
printargs_ld ( struct tcb * tcp )
{
if ( entering ( tcp ) ) {
int i ;
2013-02-21 19:13:47 +04:00
int n = tcp - > s_ent - > nargs ;
for ( i = 0 ; i < n ; i + + )
2012-02-27 17:18:02 +04:00
tprintf ( " %s%ld " , i ? " , " : " " , tcp - > u_arg [ i ] ) ;
}
return 0 ;
}
2013-02-05 19:55:23 +04:00
# if defined(SPARC) || defined(SPARC64) || defined(IA64) || defined(SH)
2011-08-24 20:07:22 +04:00
long
getrval2 ( struct tcb * tcp )
{
2013-02-05 19:55:23 +04:00
long val ;
2006-12-21 14:44:28 +03:00
2013-02-05 19:55:23 +04:00
# if defined(SPARC) || defined(SPARC64)
2013-02-16 11:23:40 +04:00
val = sparc_regs . u_regs [ U_REG_O1 ] ;
2013-02-05 19:55:23 +04:00
# elif defined(SH)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * ( REG_REG0 + 1 ) , & val ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-02-05 19:55:23 +04:00
# elif defined(IA64)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R9 , & val ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-02-05 19:55:23 +04:00
# endif
2006-12-21 14:44:28 +03:00
2012-02-25 05:24:03 +04:00
return val ;
2011-08-24 20:07:22 +04:00
}
2013-02-05 19:55:23 +04:00
# endif
2012-02-25 05:24:03 +04:00
2012-02-25 05:44:25 +04:00
# if defined(I386)
2013-07-16 14:06:25 +04:00
static struct user_regs_struct i386_regs ;
2013-07-18 19:40:45 +04:00
/* Cast suppresses signedness warning (.esp is long, not unsigned long) */
uint32_t * const i386_esp_ptr = ( uint32_t * ) & i386_regs . esp ;
2013-03-18 14:17:14 +04:00
# define ARCH_REGS_FOR_GETREGSET i386_regs
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# elif defined(X86_64) || defined(X32)
2012-01-18 14:07:24 +04:00
/*
2013-02-14 06:29:48 +04:00
* On i386 , pt_regs and user_regs_struct are the same ,
* but on 64 bit x86 , user_regs_struct has six more fields :
2012-01-18 14:07:24 +04:00
* fs_base , gs_base , ds , es , fs , gs .
* PTRACE_GETREGS fills them too , so struct pt_regs would overflow .
*/
2013-02-14 06:29:48 +04:00
struct i386_user_regs_struct {
uint32_t ebx ;
uint32_t ecx ;
uint32_t edx ;
uint32_t esi ;
uint32_t edi ;
uint32_t ebp ;
uint32_t eax ;
uint32_t xds ;
uint32_t xes ;
uint32_t xfs ;
uint32_t xgs ;
uint32_t orig_eax ;
uint32_t eip ;
uint32_t xcs ;
uint32_t eflags ;
uint32_t esp ;
uint32_t xss ;
} ;
static union {
struct user_regs_struct x86_64_r ;
struct i386_user_regs_struct i386_r ;
} x86_regs_union ;
# define x86_64_regs x86_regs_union.x86_64_r
# define i386_regs x86_regs_union.i386_r
2013-07-16 14:06:25 +04:00
uint32_t * const i386_esp_ptr = & i386_regs . esp ;
2013-02-14 06:29:48 +04:00
static struct iovec x86_io = {
. iov_base = & x86_regs_union
} ;
2012-02-25 05:44:25 +04:00
# elif defined(IA64)
2013-07-01 14:28:17 +04:00
bool ia64_ia32mode = 0 ; /* not static */
2013-02-07 16:14:48 +04:00
static long ia64_r8 , ia64_r10 ;
2012-02-25 05:44:25 +04:00
# elif defined(POWERPC)
2013-06-26 17:53:33 +04:00
struct pt_regs ppc_regs ;
2012-02-25 05:44:25 +04:00
# elif defined(M68K)
2013-02-07 16:14:48 +04:00
static long m68k_d0 ;
2012-02-25 05:44:25 +04:00
# elif defined(BFIN)
2013-02-13 20:52:31 +04:00
static long bfin_r0 ;
2012-02-25 05:44:25 +04:00
# elif defined(ARM)
2013-02-06 21:24:39 +04:00
struct pt_regs arm_regs ; /* not static */
2013-03-18 14:17:14 +04:00
# define ARCH_REGS_FOR_GETREGSET arm_regs
2012-10-24 20:58:16 +04:00
# elif defined(AARCH64)
2013-02-08 15:38:51 +04:00
static union {
2013-02-11 15:29:36 +04:00
struct user_pt_regs aarch64_r ;
struct arm_pt_regs arm_r ;
2013-02-08 15:38:51 +04:00
} arm_regs_union ;
2013-02-11 15:29:36 +04:00
# define aarch64_regs arm_regs_union.aarch64_r
# define arm_regs arm_regs_union.arm_r
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
static struct iovec aarch64_io = {
2013-02-11 15:29:36 +04:00
. iov_base = & arm_regs_union
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
} ;
2012-02-25 05:44:25 +04:00
# elif defined(ALPHA)
2013-02-13 20:52:31 +04:00
static long alpha_r0 ;
2013-02-07 16:14:48 +04:00
static long alpha_a3 ;
2012-02-25 05:44:25 +04:00
# elif defined(AVR32)
2013-02-16 11:23:40 +04:00
static struct pt_regs avr32_regs ;
2012-02-25 05:44:25 +04:00
# elif defined(SPARC) || defined(SPARC64)
2013-02-16 11:23:40 +04:00
struct pt_regs sparc_regs ; /* not static */
2012-02-25 05:44:25 +04:00
# elif defined(LINUX_MIPSN32)
2013-02-13 20:52:31 +04:00
static long long mips_a3 ;
static long long mips_r2 ;
2012-02-25 05:44:25 +04:00
# elif defined(MIPS)
2013-02-13 20:52:31 +04:00
static long mips_a3 ;
static long mips_r2 ;
2012-02-25 05:44:25 +04:00
# elif defined(S390) || defined(S390X)
2013-07-07 14:47:39 +04:00
static long s390_gpr2 ;
2012-02-25 05:44:25 +04:00
# elif defined(HPPA)
2013-02-07 16:14:48 +04:00
static long hppa_r28 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH)
2013-02-13 20:52:31 +04:00
static long sh_r0 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH64)
2013-02-07 16:14:48 +04:00
static long sh64_r9 ;
2012-02-25 05:44:25 +04:00
# elif defined(CRISV10) || defined(CRISV32)
2013-02-07 16:14:48 +04:00
static long cris_r10 ;
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
# elif defined(TILE)
struct pt_regs tile_regs ;
2012-02-25 05:44:25 +04:00
# elif defined(MICROBLAZE)
2013-02-07 16:14:48 +04:00
static long microblaze_r3 ;
2013-02-14 16:26:27 +04:00
# elif defined(OR1K)
static struct user_regs_struct or1k_regs ;
2013-03-18 14:17:14 +04:00
# define ARCH_REGS_FOR_GETREGSET or1k_regs
2013-02-22 18:44:10 +04:00
# elif defined(METAG)
static struct user_gp_regs metag_regs ;
2013-03-18 14:17:14 +04:00
# define ARCH_REGS_FOR_GETREGSET metag_regs
2013-03-25 21:22:07 +04:00
# elif defined(XTENSA)
static long xtensa_a2 ;
2013-08-16 11:17:06 +04:00
# elif defined(ARC)
static struct user_regs_struct arc_regs ;
# define ARCH_REGS_FOR_GETREGSET arc_regs
2012-02-25 05:44:25 +04:00
# endif
2000-04-11 02:22:31 +04:00
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
void
2013-07-01 14:49:14 +04:00
print_pc ( struct tcb * tcp )
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
{
# define PRINTBADPC tprintf(sizeof(long) == 4 ? "[????????] " : \
sizeof ( long ) = = 8 ? " [????????????????] " : \
NULL /* crash */ )
if ( get_regs_error ) {
PRINTBADPC ;
return ;
}
# if defined(I386)
tprintf ( " [%08lx] " , i386_regs . eip ) ;
# elif defined(S390) || defined(S390X)
long psw ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_PSWADDR , & psw ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
PRINTBADPC ;
return ;
}
# ifdef S390
tprintf ( " [%08lx] " , psw ) ;
# elif S390X
2013-02-05 23:01:58 +04:00
tprintf ( " [%016lx] " , psw ) ;
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# endif
# elif defined(X86_64) || defined(X32)
2013-02-14 06:29:48 +04:00
if ( x86_io . iov_len = = sizeof ( i386_regs ) ) {
tprintf ( " [%08x] " , ( unsigned ) i386_regs . eip ) ;
} else {
# if defined(X86_64)
tprintf ( " [%016lx] " , ( unsigned long ) x86_64_regs . rip ) ;
# elif defined(X32)
/* Note: this truncates 64-bit rip to 32 bits */
tprintf ( " [%08lx] " , ( unsigned long ) x86_64_regs . rip ) ;
# endif
}
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# elif defined(IA64)
long ip ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_B0 , & ip ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
PRINTBADPC ;
return ;
}
tprintf ( " [%08lx] " , ip ) ;
# elif defined(POWERPC)
2013-06-26 17:53:33 +04:00
long pc = ppc_regs . nip ;
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# ifdef POWERPC64
tprintf ( " [%016lx] " , pc ) ;
# else
tprintf ( " [%08lx] " , pc ) ;
# endif
# elif defined(M68K)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_PC , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
tprints ( " [????????] " ) ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(ALPHA)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_PC , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
tprints ( " [????????????????] " ) ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(SPARC)
2013-02-16 11:23:40 +04:00
tprintf ( " [%08lx] " , sparc_regs . pc ) ;
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# elif defined(SPARC64)
2013-02-16 11:23:40 +04:00
tprintf ( " [%08lx] " , sparc_regs . tpc ) ;
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# elif defined(HPPA)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_IAOQ0 , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
tprints ( " [????????] " ) ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(MIPS)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_EPC , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
tprints ( " [????????] " ) ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(SH)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * REG_PC , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
tprints ( " [????????] " ) ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(SH64)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_PC , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
tprints ( " [????????????????] " ) ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(ARM)
2013-02-06 21:24:39 +04:00
tprintf ( " [%08lx] " , arm_regs . ARM_pc ) ;
2013-02-08 15:38:51 +04:00
# elif defined(AARCH64)
/* tprintf("[%016lx] ", aarch64_regs.regs[???]); */
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# elif defined(AVR32)
2013-02-16 11:23:40 +04:00
tprintf ( " [%08lx] " , avr32_regs . pc ) ;
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# elif defined(BFIN)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_PC , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
PRINTBADPC ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(CRISV10)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_IRP , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
PRINTBADPC ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
# elif defined(CRISV32)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_ERP , & pc ) < 0 ) {
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
PRINTBADPC ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
# elif defined(TILE)
# ifdef _LP64
2013-02-05 22:02:42 +04:00
tprintf ( " [%016lx] " , ( unsigned long ) tile_regs . pc ) ;
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
# else
2013-02-05 22:02:42 +04:00
tprintf ( " [%08lx] " , ( unsigned long ) tile_regs . pc ) ;
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
# endif
2013-02-14 16:26:27 +04:00
# elif defined(OR1K)
tprintf ( " [%08lx] " , or1k_regs . pc ) ;
2013-02-22 18:44:10 +04:00
# elif defined(METAG)
tprintf ( " [%08lx] " , metag_regs . pc ) ;
2013-03-25 21:22:07 +04:00
# elif defined(XTENSA)
long pc ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_PC , & pc ) < 0 ) {
2013-03-25 21:22:07 +04:00
PRINTBADPC ;
return ;
}
tprintf ( " [%08lx] " , pc ) ;
2013-08-16 11:17:06 +04:00
# elif defined(ARC)
tprintf ( " [%08lx] " , arc_regs . efa ) ;
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# endif /* architecture */
}
2015-01-11 20:26:29 +03:00
/*
* Shuffle syscall numbers so that we don ' t have huge gaps in syscall table .
* The shuffling should be an involution : shuffle_scno ( shuffle_scno ( n ) ) = = n .
2013-02-21 18:46:34 +04:00
*/
2014-03-04 03:45:26 +04:00
# if defined(ARM) || defined(AARCH64) /* So far only 32-bit ARM needs this */
2013-02-21 18:46:34 +04:00
static long
shuffle_scno ( unsigned long scno )
{
2015-01-11 20:26:29 +03:00
if ( scno < ARM_FIRST_SHUFFLED_SYSCALL )
2013-02-21 18:46:34 +04:00
return scno ;
/* __ARM_NR_cmpxchg? Swap with LAST_ORDINARY+1 */
2015-01-11 20:26:29 +03:00
if ( scno = = ARM_FIRST_SHUFFLED_SYSCALL )
2013-02-21 18:46:34 +04:00
return 0x000ffff0 ;
2015-01-11 20:26:29 +03:00
if ( scno = = 0x000ffff0 )
return ARM_FIRST_SHUFFLED_SYSCALL ;
2013-02-21 18:46:34 +04:00
2015-01-11 20:26:29 +03:00
# define ARM_SECOND_SHUFFLED_SYSCALL (ARM_FIRST_SHUFFLED_SYSCALL + 1)
/*
* Is it ARM specific syscall ?
* Swap [ 0x000f0000 , 0x000f0000 + LAST_SPECIAL ] range
* with [ SECOND_SHUFFLED , SECOND_SHUFFLED + LAST_SPECIAL ] range .
2013-02-21 18:46:34 +04:00
*/
2015-01-11 20:26:29 +03:00
if ( scno > = 0x000f0000 & &
scno < = 0x000f0000 + ARM_LAST_SPECIAL_SYSCALL ) {
return scno - 0x000f0000 + ARM_SECOND_SHUFFLED_SYSCALL ;
}
if ( scno < = ARM_SECOND_SHUFFLED_SYSCALL + ARM_LAST_SPECIAL_SYSCALL ) {
return scno + 0x000f0000 - ARM_SECOND_SHUFFLED_SYSCALL ;
2013-02-21 18:46:34 +04:00
}
return scno ;
}
# else
# define shuffle_scno(scno) ((long)(scno))
# endif
static char *
undefined_scno_name ( struct tcb * tcp )
{
static char buf [ sizeof ( " syscall_%lu " ) + sizeof ( long ) * 3 ] ;
sprintf ( buf , " syscall_%lu " , shuffle_scno ( tcp - > scno ) ) ;
return buf ;
}
2013-06-26 08:42:37 +04:00
# ifdef POWERPC
/*
2013-06-28 16:36:39 +04:00
* PTRACE_GETREGS was added to the PowerPC kernel in v2 .6 .23 ,
* we provide a slow fallback for old kernels .
2013-06-26 08:42:37 +04:00
*/
2013-06-28 16:36:39 +04:00
static int powerpc_getregs_old ( pid_t pid )
2013-06-26 08:42:37 +04:00
{
int i ;
long r ;
2013-06-28 16:51:50 +04:00
if ( iflag ) {
2013-07-12 14:24:02 +04:00
r = upeek ( pid , sizeof ( long ) * PT_NIP , ( long * ) & ppc_regs . nip ) ;
2013-06-28 16:51:50 +04:00
if ( r )
goto out ;
}
# ifdef POWERPC64 /* else we never use it */
2013-07-12 14:24:02 +04:00
r = upeek ( pid , sizeof ( long ) * PT_MSR , ( long * ) & ppc_regs . msr ) ;
2013-06-26 08:42:37 +04:00
if ( r )
goto out ;
2013-06-28 16:51:50 +04:00
# endif
2013-07-12 14:24:02 +04:00
r = upeek ( pid , sizeof ( long ) * PT_CCR , ( long * ) & ppc_regs . ccr ) ;
2013-06-26 08:42:37 +04:00
if ( r )
goto out ;
2013-07-12 14:24:02 +04:00
r = upeek ( pid , sizeof ( long ) * PT_ORIG_R3 , ( long * ) & ppc_regs . orig_gpr3 ) ;
2013-06-26 08:42:37 +04:00
if ( r )
goto out ;
for ( i = 0 ; i < = 8 ; i + + ) {
2013-07-12 14:24:02 +04:00
r = upeek ( pid , sizeof ( long ) * ( PT_R0 + i ) ,
( long * ) & ppc_regs . gpr [ i ] ) ;
2013-06-26 08:42:37 +04:00
if ( r )
goto out ;
}
2013-06-28 16:36:39 +04:00
out :
2013-06-26 08:42:37 +04:00
return r ;
}
# endif
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# ifndef get_regs
long get_regs_error ;
2013-03-18 03:48:45 +04:00
# if defined(PTRACE_GETREGSET) && defined(NT_PRSTATUS)
static void get_regset ( pid_t pid )
{
2013-03-18 14:17:14 +04:00
/* constant iovec */
# if defined(ARM) \
| | defined ( I386 ) \
| | defined ( METAG ) \
2013-08-16 11:17:06 +04:00
| | defined ( OR1K ) \
| | defined ( ARC )
2013-03-18 14:17:14 +04:00
static struct iovec io = {
. iov_base = & ARCH_REGS_FOR_GETREGSET ,
. iov_len = sizeof ( ARCH_REGS_FOR_GETREGSET )
2013-03-18 03:48:45 +04:00
} ;
2013-03-18 14:17:14 +04:00
get_regs_error = ptrace ( PTRACE_GETREGSET , pid , NT_PRSTATUS , & io ) ;
/* variable iovec */
# elif defined(X86_64) || defined(X32)
2013-03-18 03:48:45 +04:00
/* x86_io.iov_base = &x86_regs_union; - already is */
x86_io . iov_len = sizeof ( x86_regs_union ) ;
2013-03-18 14:17:14 +04:00
get_regs_error = ptrace ( PTRACE_GETREGSET , pid , NT_PRSTATUS , & x86_io ) ;
# elif defined(AARCH64)
/* aarch64_io.iov_base = &arm_regs_union; - already is */
aarch64_io . iov_len = sizeof ( arm_regs_union ) ;
get_regs_error = ptrace ( PTRACE_GETREGSET , pid , NT_PRSTATUS , & aarch64_io ) ;
# else
# warning both PTRACE_GETREGSET and NT_PRSTATUS are available but not yet used
2013-03-18 03:48:45 +04:00
# endif
2013-03-18 14:17:14 +04:00
}
2013-03-18 03:48:45 +04:00
# endif /* PTRACE_GETREGSET && NT_PRSTATUS */
2013-03-18 14:17:14 +04:00
2013-02-16 11:23:40 +04:00
void
get_regs ( pid_t pid )
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
{
2013-03-18 14:17:14 +04:00
/* PTRACE_GETREGSET only */
2013-08-16 11:17:06 +04:00
# if defined(METAG) || defined(OR1K) || defined(X32) || defined(AARCH64) || defined(ARC)
2013-03-18 14:17:14 +04:00
get_regset ( pid ) ;
/* PTRACE_GETREGS only */
# elif defined(AVR32)
2013-02-16 11:23:40 +04:00
get_regs_error = ptrace ( PTRACE_GETREGS , pid , NULL , & avr32_regs ) ;
2013-03-18 14:17:14 +04:00
# elif defined(TILE)
get_regs_error = ptrace ( PTRACE_GETREGS , pid , NULL , & tile_regs ) ;
# elif defined(SPARC) || defined(SPARC64)
get_regs_error = ptrace ( PTRACE_GETREGS , pid , ( char * ) & sparc_regs , 0 ) ;
2013-06-26 17:53:33 +04:00
# elif defined(POWERPC)
2013-06-28 16:41:30 +04:00
static bool old_kernel = 0 ;
if ( old_kernel )
goto old ;
2013-06-26 17:53:33 +04:00
get_regs_error = ptrace ( PTRACE_GETREGS , pid , NULL , ( long ) & ppc_regs ) ;
2013-06-28 16:41:30 +04:00
if ( get_regs_error & & errno = = EIO ) {
old_kernel = 1 ;
old :
2013-06-26 08:42:37 +04:00
get_regs_error = powerpc_getregs_old ( pid ) ;
2013-06-28 16:41:30 +04:00
}
2013-03-18 14:17:14 +04:00
/* try PTRACE_GETREGSET first, fallback to PTRACE_GETREGS */
# else
2013-03-18 03:18:35 +04:00
# if defined(PTRACE_GETREGSET) && defined(NT_PRSTATUS)
static int getregset_support ;
if ( getregset_support > = 0 ) {
2013-03-18 03:48:45 +04:00
get_regset ( pid ) ;
2013-03-18 03:18:35 +04:00
if ( getregset_support > 0 )
return ;
if ( get_regs_error > = 0 ) {
getregset_support = 1 ;
return ;
2013-02-14 06:29:48 +04:00
}
2013-03-18 03:18:35 +04:00
if ( errno = = EPERM | | errno = = ESRCH )
return ;
getregset_support = - 1 ;
}
# endif /* PTRACE_GETREGSET && NT_PRSTATUS */
2013-03-18 03:48:45 +04:00
# if defined(ARM)
2013-03-18 14:17:14 +04:00
get_regs_error = ptrace ( PTRACE_GETREGS , pid , NULL , & arm_regs ) ;
2013-03-18 03:48:45 +04:00
# elif defined(I386)
2013-03-18 14:17:14 +04:00
get_regs_error = ptrace ( PTRACE_GETREGS , pid , NULL , & i386_regs ) ;
2013-03-18 03:48:45 +04:00
# elif defined(X86_64)
2013-03-18 03:18:35 +04:00
/* Use old method, with unreliable heuristical detection of 32-bitness. */
x86_io . iov_len = sizeof ( x86_64_regs ) ;
2013-03-18 14:17:14 +04:00
get_regs_error = ptrace ( PTRACE_GETREGS , pid , NULL , & x86_64_regs ) ;
2013-03-18 03:18:35 +04:00
if ( ! get_regs_error & & x86_64_regs . cs = = 0x23 ) {
x86_io . iov_len = sizeof ( i386_regs ) ;
/*
* The order is important : i386_regs and x86_64_regs
* are overlaid in memory !
*/
i386_regs . ebx = x86_64_regs . rbx ;
i386_regs . ecx = x86_64_regs . rcx ;
i386_regs . edx = x86_64_regs . rdx ;
i386_regs . esi = x86_64_regs . rsi ;
i386_regs . edi = x86_64_regs . rdi ;
i386_regs . ebp = x86_64_regs . rbp ;
i386_regs . eax = x86_64_regs . rax ;
/* i386_regs.xds = x86_64_regs.ds; unused by strace */
/* i386_regs.xes = x86_64_regs.es; ditto... */
/* i386_regs.xfs = x86_64_regs.fs; */
/* i386_regs.xgs = x86_64_regs.gs; */
i386_regs . orig_eax = x86_64_regs . orig_rax ;
i386_regs . eip = x86_64_regs . rip ;
/* i386_regs.xcs = x86_64_regs.cs; */
/* i386_regs.eflags = x86_64_regs.eflags; */
i386_regs . esp = x86_64_regs . rsp ;
/* i386_regs.xss = x86_64_regs.ss; */
2013-02-14 06:29:48 +04:00
}
2013-03-18 03:48:45 +04:00
# else
2013-03-18 14:17:14 +04:00
# error unhandled architecture
2013-03-18 03:48:45 +04:00
# endif /* ARM || I386 || X86_64 */
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
# endif
}
2013-03-18 14:17:14 +04:00
# endif /* !get_regs */
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
2011-08-21 20:03:23 +04:00
/* Returns:
2012-03-21 03:23:16 +04:00
* 0 : " ignore this ptrace stop " , bail out of trace_syscall_entering ( ) silently .
* 1 : ok , continue in trace_syscall_entering ( ) .
* other : error , trace_syscall_entering ( ) should print error indicator
2011-08-21 20:03:23 +04:00
* ( " ???? " etc ) and bail out .
*/
2012-03-19 12:36:42 +04:00
static int
2011-08-24 19:53:52 +04:00
get_scno ( struct tcb * tcp )
1999-02-19 03:21:36 +03:00
{
long scno = 0 ;
2012-02-25 05:44:25 +04:00
# if defined(S390) || defined(S390X)
2013-07-07 14:47:39 +04:00
if ( upeek ( tcp - > pid , PT_GPR2 , & s390_gpr2 ) < 0 )
2011-06-07 14:13:24 +04:00
return - 1 ;
2003-06-27 02:23:28 +04:00
2013-07-07 14:47:39 +04:00
if ( s390_gpr2 ! = - ENOSYS ) {
2003-06-27 02:23:28 +04:00
/*
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
*/
2013-07-07 14:47:39 +04:00
scno = s390_gpr2 ;
2003-06-27 02:23:28 +04:00
} 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 .
*/
2013-02-08 18:50:05 +04:00
long psw ;
2002-11-11 15:50:47 +03:00
long opcode , offset_reg , tmp ;
2011-08-24 18:52:57 +04:00
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
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_PSWADDR , & psw ) < 0 )
2002-11-11 15:50:47 +03:00
return - 1 ;
2003-01-20 13:23:04 +03:00
errno = 0 ;
2013-02-08 18:50:05 +04:00
opcode = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) ( psw - sizeof ( long ) ) , 0 ) ;
2003-01-20 13:23:04 +03:00
if ( errno ) {
2013-02-26 15:30:09 +04:00
perror_msg ( " peektext(psw-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 ;
2013-06-28 16:35:47 +04:00
if ( offset_reg & & ( upeek ( tcp - > pid , 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 ;
2013-06-28 16:35:47 +04:00
if ( offset_reg & & ( upeek ( tcp - > pid , 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 ;
2012-02-25 05:44:25 +04:00
# if defined(S390X)
2002-11-11 15:50:47 +03:00
scno > > = 48 ;
2012-02-25 05:44:25 +04:00
# else
2002-11-11 15:50:47 +03:00
scno > > = 16 ;
2012-02-25 05:44:25 +04:00
# endif
2002-11-11 15:50:47 +03:00
tmp = 0 ;
offset_reg = ( opcode & 0x00f00000 ) > > 20 ;
2013-06-28 16:35:47 +04:00
if ( offset_reg & & ( upeek ( tcp - > pid , gpr_offset [ offset_reg ] , & tmp ) < 0 ) )
2002-11-11 15:50:47 +03:00
return - 1 ;
scno = ( scno | tmp ) & 0xff ;
}
}
2012-02-25 05:44:25 +04:00
# elif defined(POWERPC)
2013-06-26 17:53:33 +04:00
scno = ppc_regs . gpr [ 0 ] ;
2012-02-25 05:44:25 +04:00
# ifdef POWERPC64
2014-09-10 17:46:04 +04:00
unsigned int currpers ;
2010-07-12 23:39:57 +04:00
2014-02-19 01:32:43 +04:00
/*
* Check for 64 / 32 bit mode .
* Embedded implementations covered by Book E extension of PPC use
* bit 0 ( CM ) of 32 - bit Machine state register ( MSR ) .
* Other implementations use bit 0 ( SF ) of 64 - bit MSR .
*/
currpers = ( ppc_regs . msr & 0x8000000080000000 ) ? 0 : 1 ;
2011-12-23 04:50:49 +04:00
update_personality ( tcp , currpers ) ;
2012-02-25 05:44:25 +04:00
# endif
# elif defined(AVR32)
2013-02-16 11:23:40 +04:00
scno = avr32_regs . r8 ;
2012-02-25 05:44:25 +04:00
# elif defined(BFIN)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_ORIG_P0 , & scno ) )
2008-11-11 01:21:41 +03:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(I386)
2011-08-30 20:53:49 +04:00
scno = i386_regs . orig_eax ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# elif defined(X86_64) || defined(X32)
# ifndef __X32_SYSCALL_BIT
# define __X32_SYSCALL_BIT 0x40000000
# endif
2014-09-10 17:46:04 +04:00
unsigned int currpers ;
2013-02-14 06:29:48 +04:00
# if 1
/* GETREGSET of NT_PRSTATUS tells us regset size,
* which unambiguously detects i386 .
*
* Linux kernel distinguishes x86 - 64 and x32 processes
* solely by looking at __X32_SYSCALL_BIT :
* arch / x86 / include / asm / compat . h : : is_x32_task ( ) :
* if ( task_pt_regs ( current ) - > orig_ax & __X32_SYSCALL_BIT )
* return true ;
*/
if ( x86_io . iov_len = = sizeof ( i386_regs ) ) {
scno = i386_regs . orig_eax ;
currpers = 1 ;
} else {
scno = x86_64_regs . orig_rax ;
currpers = 0 ;
if ( scno & __X32_SYSCALL_BIT ) {
2015-02-05 19:15:46 +03:00
/*
* Syscall number - 1 requires special treatment :
* it might be a side effect of SECCOMP_RET_ERRNO
* filtering that sets orig_rax to - 1
* in some versions of linux kernel .
* If that is the case , then
* __X32_SYSCALL_BIT logic does not apply .
*/
if ( ( long long ) x86_64_regs . orig_rax ! = - 1 ) {
scno - = __X32_SYSCALL_BIT ;
currpers = 2 ;
} else {
# ifdef X32
currpers = 2 ;
# endif
}
2013-02-14 06:29:48 +04:00
}
}
# elif 0
/* cs = 0x33 for long mode (native 64 bit and x32)
* cs = 0x23 for compatibility mode ( 32 bit )
* ds = 0x2b for x32 mode ( x86 - 64 in 32 bit )
2011-08-24 18:52:57 +04:00
*/
2013-02-14 06:29:48 +04:00
scno = x86_64_regs . orig_rax ;
2011-08-30 20:53:49 +04:00
switch ( x86_64_regs . cs ) {
2011-08-24 18:52:57 +04:00
case 0x23 : currpers = 1 ; break ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
case 0x33 :
if ( x86_64_regs . ds = = 0x2b ) {
currpers = 2 ;
2013-02-11 15:29:36 +04:00
scno & = ~ __X32_SYSCALL_BIT ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
} else
currpers = 0 ;
break ;
2011-08-24 18:52:57 +04:00
default :
2011-08-30 20:53:49 +04:00
fprintf ( stderr , " Unknown value CS=0x%08X while "
2011-08-24 18:52:57 +04:00
" detecting personality of process "
2011-08-30 20:53:49 +04:00
" PID=%d \n " , ( int ) x86_64_regs . cs , tcp - > pid ) ;
2011-08-24 18:52:57 +04:00
currpers = current_personality ;
break ;
}
2013-02-14 06:29:48 +04:00
# elif 0
2011-08-24 18:52:57 +04:00
/* This version analyzes the opcode of a syscall instruction.
* ( int 0x80 on i386 vs . syscall on x86 - 64 )
2013-02-14 06:29:48 +04:00
* It works , but is too complicated , and strictly speaking , unreliable .
2011-08-24 18:52:57 +04:00
*/
2013-02-14 06:29:48 +04:00
unsigned long call , rip = x86_64_regs . rip ;
2011-08-24 18:52:57 +04:00
/* sizeof(syscall) == sizeof(int 0x80) == 2 */
rip - = 2 ;
errno = 0 ;
2011-08-30 20:53:49 +04:00
call = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) rip , ( char * ) 0 ) ;
2011-08-24 18:52:57 +04:00
if ( errno )
fprintf ( stderr , " ptrace_peektext failed: %s \n " ,
strerror ( errno ) ) ;
switch ( call & 0xffff ) {
/* x86-64: syscall = 0x0f 0x05 */
case 0x050f : currpers = 0 ; break ;
/* i386: int 0x80 = 0xcd 0x80 */
case 0x80cd : currpers = 1 ; break ;
default :
currpers = current_personality ;
fprintf ( stderr ,
" Unknown syscall opcode (0x%04X) while "
" detecting personality of process "
2011-08-30 20:53:49 +04:00
" PID=%d \n " , ( int ) call , tcp - > pid ) ;
2011-08-24 18:52:57 +04:00
break ;
}
2012-02-25 05:44:25 +04:00
# endif
2013-02-11 15:29:36 +04:00
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# ifdef X32
2013-02-11 15:29:36 +04:00
/* If we are built for a x32 system, then personality 0 is x32
* ( not x86_64 ) , and stracing of x86_64 apps is not supported .
* Stracing of i386 apps is still supported .
2012-04-17 22:05:04 +04:00
*/
2013-02-11 15:29:36 +04:00
if ( currpers = = 0 ) {
fprintf ( stderr , " syscall_%lu(...) in unsupported "
" 64-bit mode of process PID=%d \n " ,
scno , tcp - > pid ) ;
return 0 ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
}
2013-02-11 15:29:36 +04:00
currpers & = ~ 2 ; /* map 2,1 to 0,1 */
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# endif
2012-04-17 22:05:04 +04:00
update_personality ( tcp , currpers ) ;
2012-02-25 05:44:25 +04:00
# elif defined(IA64)
2001-10-10 03:47:38 +04:00
# define IA64_PSR_IS ((long)1 << 34)
2013-02-06 21:09:31 +04:00
long psr ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_CR_IPSR , & psr ) > = 0 )
2013-07-01 14:28:17 +04:00
ia64_ia32mode = ( ( psr & IA64_PSR_IS ) ! = 0 ) ;
if ( ia64_ia32mode ) {
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R1 , & scno ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
2011-08-24 18:52:57 +04:00
} else {
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R15 , & scno ) < 0 )
2000-02-04 00:58:30 +03:00
return - 1 ;
}
2012-11-10 15:24:48 +04:00
# elif defined(AARCH64)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
switch ( aarch64_io . iov_len ) {
2012-11-10 15:24:48 +04:00
case sizeof ( aarch64_regs ) :
/* We are in 64-bit mode */
scno = aarch64_regs . regs [ 8 ] ;
update_personality ( tcp , 1 ) ;
break ;
2013-02-08 15:38:51 +04:00
case sizeof ( arm_regs ) :
2012-11-10 15:24:48 +04:00
/* We are in 32-bit mode */
2013-07-04 11:54:19 +04:00
/* Note: we don't support OABI, unlike 32-bit ARM build */
2013-02-08 15:38:51 +04:00
scno = arm_regs . ARM_r7 ;
2014-03-04 03:45:26 +04:00
scno = shuffle_scno ( scno ) ;
2012-11-10 15:24:48 +04:00
update_personality ( tcp , 0 ) ;
break ;
}
2012-02-25 05:44:25 +04:00
# elif defined(ARM)
2013-02-20 21:08:25 +04:00
if ( arm_regs . ARM_ip ! = 0 ) {
/* It is not a syscall entry */
fprintf ( stderr , " pid %d stray syscall exit \n " , tcp - > pid ) ;
tcp - > flags | = TCB_INSYSCALL ;
return 0 ;
}
/* Note: we support only 32-bit CPUs, not 26-bit */
2014-03-19 03:37:43 +04:00
# if !defined(__ARM_EABI__) || ENABLE_ARM_OABI
2013-07-04 11:54:19 +04:00
if ( arm_regs . ARM_cpsr & 0x20 )
2013-02-20 21:08:25 +04:00
/* Thumb mode */
2013-07-04 11:54:19 +04:00
goto scno_in_r7 ;
/* ARM mode */
/* Check EABI/OABI by examining SVC insn's low 24 bits */
errno = 0 ;
scno = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( void * ) ( arm_regs . ARM_pc - 4 ) , NULL ) ;
if ( errno )
return - 1 ;
/* EABI syscall convention? */
2015-01-14 10:21:36 +03:00
if ( ( unsigned long ) scno ! = 0xef000000 ) {
2013-07-04 11:54:19 +04:00
/* No, it's OABI */
if ( ( scno & 0x0ff00000 ) ! = 0x0f900000 ) {
fprintf ( stderr , " pid %d unknown syscall trap 0x%08lx \n " ,
tcp - > pid , scno ) ;
2013-02-20 21:08:25 +04:00
return - 1 ;
2003-06-04 03:29:04 +04:00
}
2013-07-04 11:54:19 +04:00
/* Fixup the syscall number */
scno & = 0x000fffff ;
} else {
scno_in_r7 :
scno = arm_regs . ARM_r7 ;
2013-02-20 21:08:25 +04:00
}
2014-03-19 03:37:43 +04:00
# else /* __ARM_EABI__ || !ENABLE_ARM_OABI */
2013-07-04 11:54:19 +04:00
scno = arm_regs . ARM_r7 ;
# endif
2013-02-21 18:46:34 +04:00
scno = shuffle_scno ( scno ) ;
2012-02-25 05:44:25 +04:00
# elif defined(M68K)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_ORIG_D0 , & scno ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2012-02-25 05:44:25 +04: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 ;
2013-02-13 20:52:31 +04:00
mips_a3 = regs [ REG_A3 ] ;
mips_r2 = regs [ REG_V0 ] ;
2008-05-20 05:11:56 +04:00
2013-02-13 20:52:31 +04:00
scno = mips_r2 ;
2013-02-21 19:13:47 +04:00
if ( ! SCNO_IN_RANGE ( scno ) ) {
2013-02-13 20:52:31 +04:00
if ( mips_a3 = = 0 | | mips_a3 = = - 1 ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2011-08-24 18:52:57 +04:00
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
return 0 ;
2008-05-20 05:11:56 +04:00
}
}
2012-02-25 05:44:25 +04:00
# elif defined(MIPS)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A3 , & mips_a3 ) < 0 )
2009-02-27 23:32:52 +03:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_V0 , & scno ) < 0 )
2011-08-24 18:52:57 +04:00
return - 1 ;
1999-11-01 00:15:38 +03:00
2013-02-21 19:13:47 +04:00
if ( ! SCNO_IN_RANGE ( scno ) ) {
2013-02-13 20:52:31 +04:00
if ( mips_a3 = = 0 | | mips_a3 = = - 1 ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2011-08-24 18:52:57 +04:00
fprintf ( stderr , " stray syscall exit: v0 = %ld \n " , scno ) ;
return 0 ;
1999-11-01 00:15:38 +03:00
}
}
2012-02-25 05:44:25 +04:00
# elif defined(ALPHA)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A3 , & alpha_a3 ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_R0 , & scno ) < 0 )
2011-08-24 18:52:57 +04:00
return - 1 ;
1999-02-19 03:21:36 +03:00
2011-08-24 18:52:57 +04:00
/*
* Do some sanity checks to figure out if it ' s
* really a syscall entry
*/
2013-02-21 19:13:47 +04:00
if ( ! SCNO_IN_RANGE ( scno ) ) {
2013-02-07 16:14:48 +04:00
if ( alpha_a3 = = 0 | | alpha_a3 = = - 1 ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2011-08-24 18:52:57 +04:00
fprintf ( stderr , " stray syscall exit: r0 = %ld \n " , scno ) ;
return 0 ;
1999-02-19 03:21:36 +03:00
}
}
2012-02-25 05:44:25 +04:00
# elif defined(SPARC) || defined(SPARC64)
2011-08-24 18:52:57 +04:00
/* Disassemble the syscall trap. */
/* Retrieve the syscall trap instruction. */
2013-02-05 20:02:59 +04:00
unsigned long trap ;
2011-08-24 18:52:57 +04:00
errno = 0 ;
2012-02-25 05:44:25 +04:00
# if defined(SPARC64)
2013-02-16 11:23:40 +04:00
trap = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) sparc_regs . tpc , 0 ) ;
2011-08-24 18:52:57 +04:00
trap > > = 32 ;
2012-02-25 05:44:25 +04:00
# else
2013-02-16 11:23:40 +04:00
trap = ptrace ( PTRACE_PEEKTEXT , tcp - > pid , ( char * ) sparc_regs . pc , 0 ) ;
2012-02-25 05:44:25 +04:00
# endif
2011-08-24 18:52:57 +04:00
if ( errno )
return - 1 ;
1999-02-19 03:21:36 +03:00
2011-08-24 18:52:57 +04:00
/* Disassemble the trap to see what personality to use. */
switch ( trap ) {
case 0x91d02010 :
/* Linux/SPARC syscall trap. */
2011-12-23 04:50:49 +04:00
update_personality ( tcp , 0 ) ;
2011-08-24 18:52:57 +04:00
break ;
case 0x91d0206d :
/* Linux/SPARC64 syscall trap. */
2011-12-23 04:50:49 +04:00
update_personality ( tcp , 2 ) ;
2011-08-24 18:52:57 +04:00
break ;
case 0x91d02000 :
/* SunOS syscall trap. (pers 1) */
fprintf ( stderr , " syscall: SunOS no support \n " ) ;
return - 1 ;
case 0x91d02008 :
/* Solaris 2.x syscall trap. (per 2) */
2011-12-23 04:50:49 +04:00
update_personality ( tcp , 1 ) ;
2011-08-24 18:52:57 +04:00
break ;
case 0x91d02009 :
/* NetBSD/FreeBSD syscall trap. */
fprintf ( stderr , " syscall: NetBSD/FreeBSD not supported \n " ) ;
return - 1 ;
case 0x91d02027 :
/* Solaris 2.x gettimeofday */
2011-12-23 04:50:49 +04:00
update_personality ( tcp , 1 ) ;
2011-08-24 18:52:57 +04:00
break ;
default :
2012-02-25 05:44:25 +04:00
# if defined(SPARC64)
2013-02-16 11:23:40 +04:00
fprintf ( stderr , " syscall: unknown syscall trap %08lx %016lx \n " , trap , sparc_regs . tpc ) ;
2012-02-25 05:44:25 +04:00
# else
2013-02-16 11:23:40 +04:00
fprintf ( stderr , " syscall: unknown syscall trap %08lx %08lx \n " , trap , sparc_regs . pc ) ;
2012-02-25 05:44:25 +04:00
# endif
2011-08-24 18:52:57 +04:00
return - 1 ;
}
1999-02-19 03:21:36 +03:00
2011-08-24 18:52:57 +04:00
/* Extract the system call number from the registers. */
if ( trap = = 0x91d02027 )
scno = 156 ;
else
2013-02-16 11:23:40 +04:00
scno = sparc_regs . u_regs [ U_REG_G1 ] ;
2011-08-24 18:52:57 +04:00
if ( scno = = 0 ) {
2013-02-16 11:23:40 +04:00
scno = sparc_regs . u_regs [ U_REG_O0 ] ;
memmove ( & sparc_regs . u_regs [ U_REG_O0 ] , & sparc_regs . u_regs [ U_REG_O1 ] , 7 * sizeof ( sparc_regs . u_regs [ 0 ] ) ) ;
1999-02-19 03:21:36 +03:00
}
2012-02-25 05:44:25 +04:00
# elif defined(HPPA)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_GR20 , & scno ) < 0 )
2001-03-27 16:17:16 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH)
2008-12-30 21:47:55 +03:00
/*
* In the new syscall ABI , the system call number is in R3 .
*/
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * ( REG_REG0 + 3 ) , & scno ) < 0 )
2008-12-30 21:47:55 +03:00
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 ) ;
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
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 ;
}
2012-02-25 05:44:25 +04:00
# elif defined(SH64)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_SYSCALL , & scno ) < 0 )
2003-06-02 23:18:58 +04:00
return - 1 ;
2008-12-30 21:47:55 +03:00
scno & = 0xFFFF ;
2012-02-25 05:44:25 +04:00
# elif defined(CRISV10) || defined(CRISV32)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_R9 , & scno ) < 0 )
2009-02-25 20:08:40 +03:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(TILE)
2014-09-10 17:46:04 +04:00
unsigned int currpers ;
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
scno = tile_regs . regs [ 10 ] ;
# ifdef __tilepro__
currpers = 1 ;
# else
2013-02-11 15:29:36 +04:00
# ifndef PT_FLAGS_COMPAT
# define PT_FLAGS_COMPAT 0x10000 /* from Linux 3.8 on */
# endif
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
if ( tile_regs . flags & PT_FLAGS_COMPAT )
currpers = 1 ;
else
currpers = 0 ;
# endif
update_personality ( tcp , currpers ) ;
2012-02-25 05:44:25 +04:00
# elif defined(MICROBLAZE)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 0 , & scno ) < 0 )
2010-07-06 16:21:07 +04:00
return - 1 ;
2013-02-14 16:26:27 +04:00
# elif defined(OR1K)
scno = or1k_regs . gpr [ 11 ] ;
2013-02-22 18:44:10 +04:00
# elif defined(METAG)
scno = metag_regs . dx [ 0 ] [ 1 ] ; /* syscall number in D1Re0 (D1.0) */
2013-03-25 21:22:07 +04:00
# elif defined(XTENSA)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , SYSCALL_NR , & scno ) < 0 )
2013-03-25 21:22:07 +04:00
return - 1 ;
2013-08-16 11:17:06 +04:00
# elif defined(ARC)
scno = arc_regs . scratch . r8 ;
2012-02-25 05:44:25 +04:00
# endif
2009-02-25 20:08:40 +03:00
2011-08-24 18:52:57 +04:00
tcp - > scno = scno ;
2013-02-21 19:13:47 +04:00
if ( SCNO_IS_VALID ( tcp - > scno ) ) {
tcp - > s_ent = & sysent [ scno ] ;
tcp - > qual_flg = qual_flags [ scno ] ;
} else {
2013-02-22 16:26:10 +04:00
static const struct_sysent unknown = {
2013-02-21 19:13:47 +04:00
. nargs = MAX_ARGS ,
. sys_flags = 0 ,
. sys_func = printargs ,
. sys_name = " unknown " , /* not used */
} ;
tcp - > s_ent = & unknown ;
tcp - > qual_flg = UNDEFINED_SCNO | QUAL_RAW | DEFAULT_QUAL_FLAGS ;
}
2000-02-01 20:58:41 +03:00
return 1 ;
}
2011-08-25 12:23:00 +04:00
/* Called at each syscall entry.
2009-01-02 21:02:45 +03:00
* Returns :
2012-03-21 03:23:16 +04:00
* 0 : " ignore this ptrace stop " , bail out of trace_syscall_entering ( ) silently .
* 1 : ok , continue in trace_syscall_entering ( ) .
* other : error , trace_syscall_entering ( ) 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
2011-08-25 12:40:14 +04:00
syscall_fixup_on_sysenter ( struct tcb * tcp )
2000-02-01 20:58:41 +03:00
{
2011-08-21 20:03:23 +04:00
/* A common case of "not a syscall entry" is post-execve SIGTRAP */
2012-02-25 05:44:25 +04:00
# if defined(I386)
2015-02-05 22:31:13 +03:00
/*
* Syscall number - 1 requires special treatment .
* On X86 , it might be a side effect of SECCOMP_RET_ERRNO filtering
* that sets orig_eax to - 1 in some versions of linux kernel .
*/
if ( i386_regs . orig_eax ! = - 1 & &
i386_regs . eax ! = - ENOSYS ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2015-02-05 22:31:13 +03:00
fprintf ( stderr ,
" not a syscall entry (eax = %ld, orig_eax = %ld) \n " ,
i386_regs . eax , i386_regs . orig_eax ) ;
2011-08-30 20:53:49 +04:00
return 0 ;
1999-02-19 03:21:36 +03:00
}
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# elif defined(X86_64) || defined(X32)
2015-02-05 22:31:13 +03:00
/*
* Syscall number - 1 requires special treatment .
* On X86_64 / X32 , it might be a side effect of SECCOMP_RET_ERRNO
* filtering that sets orig_rax to - 1 in some versions of linux kernel .
*/
if ( x86_io . iov_len = = sizeof ( i386_regs ) ) {
if ( ( int ) i386_regs . orig_eax ! = - 1 & &
( int ) i386_regs . eax ! = - ENOSYS ) {
if ( debug_flag )
fprintf ( stderr ,
" not a syscall entry (eax = %d, orig_eax = %d) \n " ,
( int ) i386_regs . eax ,
( int ) i386_regs . orig_eax ) ;
return 0 ;
2013-02-14 06:29:48 +04:00
}
2015-02-05 22:31:13 +03:00
} else {
if ( ( long long ) x86_64_regs . orig_rax ! = - 1 & &
( long long ) x86_64_regs . rax ! = - ENOSYS ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2015-02-05 22:31:13 +03:00
fprintf ( stderr ,
" not a syscall entry (rax = %lld, orig_rax = %lld) \n " ,
( long long ) x86_64_regs . rax ,
( long long ) x86_64_regs . orig_rax ) ;
2011-08-24 18:59:23 +04:00
return 0 ;
}
2002-09-23 19:41:01 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(M68K)
2011-08-25 12:31:24 +04:00
/* TODO? Eliminate upeek's in arches below like we did in x86 */
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_D0 , & m68k_d0 ) < 0 )
1999-02-19 03:21:36 +03:00
return - 1 ;
2013-02-07 16:14:48 +04:00
if ( m68k_d0 ! = - ENOSYS ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2013-02-07 16:14:48 +04:00
fprintf ( stderr , " not a syscall entry (d0 = %ld) \n " , m68k_d0 ) ;
1999-02-19 03:21:36 +03:00
return 0 ;
}
2001-10-10 03:47:38 +04:00
# elif defined(IA64)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R10 , & ia64_r10 ) < 0 )
2001-10-10 03:47:38 +04:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R8 , & ia64_r8 ) < 0 )
2001-10-10 03:47:38 +04:00
return - 1 ;
2013-07-01 14:28:17 +04:00
if ( ia64_ia32mode & & ia64_r8 ! = - ENOSYS ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2013-02-07 16:14:48 +04:00
fprintf ( stderr , " not a syscall entry (r8 = %ld) \n " , ia64_r8 ) ;
2001-10-10 03:47:38 +04:00
return 0 ;
}
2009-02-25 20:08:40 +03:00
# elif defined(CRISV10) || defined(CRISV32)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_R10 , & cris_r10 ) < 0 )
2009-02-25 20:08:40 +03:00
return - 1 ;
2013-02-07 16:14:48 +04:00
if ( cris_r10 ! = - ENOSYS ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2013-02-07 16:14:48 +04:00
fprintf ( stderr , " not a syscall entry (r10 = %ld) \n " , cris_r10 ) ;
2009-02-25 20:08:40 +03:00
return 0 ;
}
2010-07-06 16:21:07 +04:00
# elif defined(MICROBLAZE)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 3 * 4 , & microblaze_r3 ) < 0 )
2010-07-06 16:21:07 +04:00
return - 1 ;
2013-02-07 16:14:48 +04:00
if ( microblaze_r3 ! = - ENOSYS ) {
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( debug_flag )
2013-02-07 16:14:48 +04:00
fprintf ( stderr , " not a syscall entry (r3 = %ld) \n " , microblaze_r3 ) ;
2010-07-06 16:21:07 +04:00
return 0 ;
}
1999-02-19 03:21:36 +03:00
# endif
2000-02-01 20:58:41 +03:00
return 1 ;
}
1999-02-19 03:21:36 +03:00
2012-03-19 01:10:48 +04:00
static void
internal_fork ( struct tcb * tcp )
{
# if defined S390 || defined S390X || defined CRISV10 || defined CRISV32
# define ARG_FLAGS 1
# else
# define ARG_FLAGS 0
# endif
# ifndef CLONE_UNTRACED
# define CLONE_UNTRACED 0x00800000
# endif
if ( ( ptrace_setoptions
& ( PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK ) )
= = ( PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK ) )
return ;
if ( ! followfork )
return ;
if ( entering ( tcp ) ) {
/*
* We won ' t see the new child if clone is called with
* CLONE_UNTRACED , so we keep the same logic with that option
* and don ' t trace it .
*/
2013-02-21 19:13:47 +04:00
if ( ( tcp - > s_ent - > sys_func = = sys_clone )
& & ( tcp - > u_arg [ ARG_FLAGS ] & CLONE_UNTRACED )
)
2012-03-19 01:10:48 +04:00
return ;
setbpt ( tcp ) ;
} else {
if ( tcp - > flags & TCB_BPTSET )
clearbpt ( tcp ) ;
}
}
# if defined(TCB_WAITEXECVE)
static void
internal_exec ( struct tcb * tcp )
{
/* Maybe we have post-execve SIGTRAP suppressed? */
if ( ptrace_setoptions & PTRACE_O_TRACEEXEC )
return ; /* yes, no need to do anything */
if ( exiting ( tcp ) & & syserror ( tcp ) )
/* Error in execve, no post-execve SIGTRAP expected */
tcp - > flags & = ~ TCB_WAITEXECVE ;
else
tcp - > flags | = TCB_WAITEXECVE ;
}
# endif
static void
2013-02-06 16:18:42 +04:00
syscall_fixup_for_fork_exec ( struct tcb * tcp )
2008-05-28 03:18:29 +04:00
{
2011-08-24 20:07:22 +04:00
/*
* We must always trace a few critical system calls in order to
* correctly support following forks in the presence of tracing
* qualifiers .
*/
int ( * func ) ( ) ;
2013-02-21 19:13:47 +04:00
func = tcp - > s_ent - > sys_func ;
2011-08-24 20:07:22 +04:00
if ( sys_fork = = func
| | sys_clone = = func
2012-03-19 01:10:48 +04:00
) {
internal_fork ( tcp ) ;
return ;
}
2011-08-24 20:07:22 +04:00
2012-02-25 05:38:52 +04:00
# if defined(TCB_WAITEXECVE)
2011-08-24 20:07:22 +04:00
if ( sys_execve = = func
2012-02-25 05:38:52 +04:00
# if defined(SPARC) || defined(SPARC64)
2011-08-24 20:07:22 +04:00
| | sys_execv = = func
# endif
2012-03-19 01:10:48 +04:00
) {
internal_exec ( tcp ) ;
return ;
}
2008-05-28 03:18:29 +04:00
# endif
2011-08-24 20:07:22 +04:00
}
2012-03-20 20:10:35 +04:00
/* Return -1 on error or 1 on success (never 0!) */
2005-06-09 00:45:28 +04:00
static int
2012-03-20 20:10:35 +04:00
get_syscall_args ( struct tcb * tcp )
2000-02-01 20:58:41 +03:00
{
2011-08-24 20:07:22 +04:00
int i , nargs ;
2013-02-21 19:13:47 +04:00
nargs = tcp - > s_ent - > nargs ;
2011-08-24 20:07:22 +04:00
2012-02-25 05:44:25 +04:00
# if defined(S390) || defined(S390X)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , i = = 0 ? PT_ORIGGPR2 : PT_GPR2 + i * sizeof ( long ) , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(ALPHA)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(IA64)
2013-07-01 14:28:17 +04:00
if ( ! ia64_ia32mode ) {
2011-08-24 20:07:22 +04:00
unsigned long * out0 , cfm , sof , sol ;
long rbs_end ;
/* be backwards compatible with kernel < 2.4.4... */
# ifndef PT_RBS_END
# define PT_RBS_END PT_AR_BSP
# endif
2008-05-28 03:18:29 +04:00
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_RBS_END , & rbs_end ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_CFM , ( long * ) & cfm ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
sof = ( cfm > > 0 ) & 0x7f ;
sol = ( cfm > > 7 ) & 0x7f ;
out0 = ia64_rse_skip_regs ( ( unsigned long * ) rbs_end , - sof + sol ) ;
for ( i = 0 ; i < nargs ; + + i ) {
if ( umoven ( tcp , ( unsigned long ) ia64_rse_skip_regs ( out0 , i ) ,
sizeof ( long ) , ( char * ) & tcp - > u_arg [ i ] ) < 0 )
return - 1 ;
2002-09-23 19:41:01 +04:00
}
2008-05-28 03:18:29 +04:00
} else {
2011-08-24 20:07:22 +04:00
static const int argreg [ MAX_ARGS ] = { PT_R11 /* EBX = out0 */ ,
PT_R9 /* ECX = out1 */ ,
PT_R10 /* EDX = out2 */ ,
PT_R14 /* ESI = out3 */ ,
PT_R15 /* EDI = out4 */ ,
PT_R13 /* EBP = out5 */ } ;
for ( i = 0 ; i < nargs ; + + i ) {
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , argreg [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
/* truncate away IVE sign-extension */
tcp - > u_arg [ i ] & = 0xffffffff ;
2000-02-04 00:58:30 +03:00
}
2008-05-28 03:18:29 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(LINUX_MIPSN32) || defined(LINUX_MIPSN64)
2011-08-24 20:07:22 +04:00
/* N32 and N64 both use up to six registers. */
unsigned long long regs [ 38 ] ;
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , NULL , ( long ) & regs ) < 0 )
return - 1 ;
for ( i = 0 ; i < nargs ; + + i ) {
tcp - > u_arg [ i ] = regs [ REG_A0 + i ] ;
2012-02-25 05:44:25 +04:00
# if defined(LINUX_MIPSN32)
2011-08-24 20:07:22 +04:00
tcp - > ext_arg [ i ] = regs [ REG_A0 + i ] ;
2012-02-25 05:44:25 +04:00
# endif
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(MIPS)
2011-08-24 20:07:22 +04:00
if ( nargs > 4 ) {
long sp ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_SP , & sp ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
for ( i = 0 ; i < 4 ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
umoven ( tcp , sp + 16 , ( nargs - 4 ) * sizeof ( tcp - > u_arg [ 0 ] ) ,
( char * ) ( tcp - > u_arg + 4 ) ) ;
2011-06-07 14:13:24 +04:00
} else {
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A0 + i , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2011-06-07 14:13:24 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(POWERPC)
2013-06-26 17:53:33 +04:00
( void ) i ;
( void ) nargs ;
tcp - > u_arg [ 0 ] = ppc_regs . orig_gpr3 ;
tcp - > u_arg [ 1 ] = ppc_regs . gpr [ 4 ] ;
tcp - > u_arg [ 2 ] = ppc_regs . gpr [ 5 ] ;
tcp - > u_arg [ 3 ] = ppc_regs . gpr [ 6 ] ;
tcp - > u_arg [ 4 ] = ppc_regs . gpr [ 7 ] ;
tcp - > u_arg [ 5 ] = ppc_regs . gpr [ 8 ] ;
2012-02-25 05:44:25 +04:00
# elif defined(SPARC) || defined(SPARC64)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-02-16 11:23:40 +04:00
tcp - > u_arg [ i ] = sparc_regs . u_regs [ U_REG_O0 + i ] ;
2012-02-25 05:44:25 +04:00
# elif defined(HPPA)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_GR26 - 4 * i , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-11-10 15:24:48 +04:00
# elif defined(ARM) || defined(AARCH64)
# if defined(AARCH64)
if ( tcp - > currpers = = 1 )
for ( i = 0 ; i < nargs ; + + i )
tcp - > u_arg [ i ] = aarch64_regs . regs [ i ] ;
else
2013-02-08 15:38:51 +04:00
# endif
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-02-06 21:24:39 +04:00
tcp - > u_arg [ i ] = arm_regs . uregs [ i ] ;
2012-02-25 05:44:25 +04:00
# elif defined(AVR32)
2011-08-30 21:04:54 +04:00
( void ) i ;
( void ) nargs ;
2013-02-16 11:23:40 +04:00
tcp - > u_arg [ 0 ] = avr32_regs . r12 ;
tcp - > u_arg [ 1 ] = avr32_regs . r11 ;
tcp - > u_arg [ 2 ] = avr32_regs . r10 ;
tcp - > u_arg [ 3 ] = avr32_regs . r9 ;
tcp - > u_arg [ 4 ] = avr32_regs . r5 ;
tcp - > u_arg [ 5 ] = avr32_regs . r3 ;
2012-02-25 05:44:25 +04:00
# elif defined(BFIN)
2011-08-24 20:07:22 +04:00
static const int argreg [ MAX_ARGS ] = { PT_R0 , PT_R1 , PT_R2 , PT_R3 , PT_R4 , PT_R5 } ;
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , argreg [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH)
2011-08-24 20:07:22 +04:00
static const int syscall_regs [ MAX_ARGS ] = {
4 * ( REG_REG0 + 4 ) , 4 * ( REG_REG0 + 5 ) , 4 * ( REG_REG0 + 6 ) ,
4 * ( REG_REG0 + 7 ) , 4 * ( REG_REG0 ) , 4 * ( REG_REG0 + 1 )
} ;
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , syscall_regs [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH64)
2011-08-24 20:07:22 +04:00
int i ;
/* Registers used by SH5 Linux system calls for parameters */
static const int syscall_regs [ MAX_ARGS ] = { 2 , 3 , 4 , 5 , 6 , 7 } ;
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_GENERAL ( syscall_regs [ i ] ) , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-02-15 18:01:38 +04:00
# elif defined(I386)
( void ) i ;
( void ) nargs ;
tcp - > u_arg [ 0 ] = i386_regs . ebx ;
tcp - > u_arg [ 1 ] = i386_regs . ecx ;
tcp - > u_arg [ 2 ] = i386_regs . edx ;
tcp - > u_arg [ 3 ] = i386_regs . esi ;
tcp - > u_arg [ 4 ] = i386_regs . edi ;
tcp - > u_arg [ 5 ] = i386_regs . ebp ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# elif defined(X86_64) || defined(X32)
2011-08-30 20:53:49 +04:00
( void ) i ;
( void ) nargs ;
2013-02-14 06:29:48 +04:00
if ( x86_io . iov_len ! = sizeof ( i386_regs ) ) {
/* x86-64 or x32 ABI */
2011-08-30 20:53:49 +04:00
tcp - > u_arg [ 0 ] = x86_64_regs . rdi ;
tcp - > u_arg [ 1 ] = x86_64_regs . rsi ;
tcp - > u_arg [ 2 ] = x86_64_regs . rdx ;
tcp - > u_arg [ 3 ] = x86_64_regs . r10 ;
tcp - > u_arg [ 4 ] = x86_64_regs . r8 ;
tcp - > u_arg [ 5 ] = x86_64_regs . r9 ;
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# ifdef X32
tcp - > ext_arg [ 0 ] = x86_64_regs . rdi ;
tcp - > ext_arg [ 1 ] = x86_64_regs . rsi ;
tcp - > ext_arg [ 2 ] = x86_64_regs . rdx ;
tcp - > ext_arg [ 3 ] = x86_64_regs . r10 ;
tcp - > ext_arg [ 4 ] = x86_64_regs . r8 ;
tcp - > ext_arg [ 5 ] = x86_64_regs . r9 ;
# endif
2013-02-14 06:29:48 +04:00
} else {
/* i386 ABI */
2013-02-15 18:01:38 +04:00
/* Zero-extend from 32 bits */
/* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
* if you need to use * sign - extended * parameter .
*/
tcp - > u_arg [ 0 ] = ( long ) ( uint32_t ) i386_regs . ebx ;
tcp - > u_arg [ 1 ] = ( long ) ( uint32_t ) i386_regs . ecx ;
tcp - > u_arg [ 2 ] = ( long ) ( uint32_t ) i386_regs . edx ;
tcp - > u_arg [ 3 ] = ( long ) ( uint32_t ) i386_regs . esi ;
tcp - > u_arg [ 4 ] = ( long ) ( uint32_t ) i386_regs . edi ;
tcp - > u_arg [ 5 ] = ( long ) ( uint32_t ) i386_regs . ebp ;
2011-08-30 20:53:49 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(MICROBLAZE)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , ( 5 + i ) * 4 , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(CRISV10) || defined(CRISV32)
2011-08-24 20:07:22 +04:00
static const int crisregs [ MAX_ARGS ] = {
4 * PT_ORIG_R10 , 4 * PT_R11 , 4 * PT_R12 ,
4 * PT_R13 , 4 * PT_MOF , 4 * PT_SRP
} ;
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , crisregs [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(TILE)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
tcp - > u_arg [ i ] = tile_regs . regs [ i ] ;
2012-02-25 05:44:25 +04:00
# elif defined(M68K)
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , ( i < 5 ? i : i + 2 ) * 4 , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-02-14 16:26:27 +04:00
# elif defined(OR1K)
( void ) nargs ;
for ( i = 0 ; i < 6 ; + + i )
tcp - > u_arg [ i ] = or1k_regs . gpr [ 3 + i ] ;
2013-02-22 18:44:10 +04:00
# elif defined(METAG)
for ( i = 0 ; i < nargs ; i + + )
/* arguments go backwards from D1Ar1 (D1.3) */
tcp - > u_arg [ i ] = ( ( unsigned long * ) & metag_regs . dx [ 3 ] [ 1 ] ) [ - i ] ;
2013-03-25 21:22:07 +04:00
# elif defined(XTENSA)
/* arg0: a6, arg1: a3, arg2: a4, arg3: a5, arg4: a8, arg5: a9 */
static const int xtensaregs [ MAX_ARGS ] = { 6 , 3 , 4 , 5 , 8 , 9 } ;
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A_BASE + xtensaregs [ i ] , & tcp - > u_arg [ i ] ) < 0 )
2013-03-25 21:22:07 +04:00
return - 1 ;
2013-08-16 11:17:06 +04:00
# elif defined(ARC)
long * arc_args = & arc_regs . scratch . r0 ;
for ( i = 0 ; i < nargs ; + + i )
tcp - > u_arg [ i ] = * arc_args - - ;
2012-02-25 05:44:25 +04:00
# else /* Other architecture (32bits specific) */
2011-08-24 20:07:22 +04:00
for ( i = 0 ; i < nargs ; + + i )
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , i * 4 , & tcp - > u_arg [ i ] ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# endif
2000-02-01 20:58:41 +03:00
return 1 ;
}
2011-08-22 13:54:06 +04:00
static int
trace_syscall_entering ( struct tcb * tcp )
{
int res , scno_good ;
2011-08-24 19:25:32 +04:00
# if defined TCB_WAITEXECVE
if ( tcp - > flags & TCB_WAITEXECVE ) {
/* This is the post-execve SIGTRAP. */
tcp - > flags & = ~ TCB_WAITEXECVE ;
return 0 ;
}
# endif
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
scno_good = res = ( get_regs_error ? - 1 : get_scno ( tcp ) ) ;
2011-08-22 13:54:06 +04:00
if ( res = = 0 )
return res ;
2012-03-21 03:23:16 +04:00
if ( res = = 1 ) {
2011-08-25 12:40:14 +04:00
res = syscall_fixup_on_sysenter ( tcp ) ;
2012-03-21 03:23:16 +04:00
if ( res = = 0 )
return res ;
if ( res = = 1 )
res = get_syscall_args ( tcp ) ;
}
2011-08-22 13:54:06 +04:00
if ( res ! = 1 ) {
printleader ( tcp ) ;
if ( scno_good ! = 1 )
2012-03-20 19:48:35 +04:00
tprints ( " ???? " /* anti-trigraph gap */ " ( " ) ;
2013-02-21 19:13:47 +04:00
else if ( tcp - > qual_flg & UNDEFINED_SCNO )
2013-02-21 18:46:34 +04:00
tprintf ( " %s( " , undefined_scno_name ( tcp ) ) ;
2011-08-22 13:54:06 +04:00
else
2013-02-21 19:13:47 +04:00
tprintf ( " %s( " , tcp - > s_ent - > sys_name ) ;
2011-08-22 13:54:06 +04:00
/*
* " <unavailable> " will be added later by the code which
* detects ptrace errors .
*/
goto ret ;
}
2013-05-14 18:07:46 +04:00
if ( sys_execve = = tcp - > s_ent - > sys_func
# if defined(SPARC) || defined(SPARC64)
| | sys_execv = = tcp - > s_ent - > sys_func
# endif
) {
hide_log_until_execve = 0 ;
}
2012-02-20 21:02:38 +04:00
# if defined(SYS_socket_subcall) || defined(SYS_ipc_subcall)
2013-02-21 19:13:47 +04:00
while ( 1 ) {
2012-02-25 05:44:25 +04:00
# ifdef SYS_socket_subcall
2013-02-21 19:13:47 +04:00
if ( tcp - > s_ent - > sys_func = = sys_socketcall ) {
2012-03-16 02:08:55 +04:00
decode_socket_subcall ( tcp ) ;
2012-02-20 21:02:38 +04:00
break ;
}
2012-02-25 05:44:25 +04:00
# endif
# ifdef SYS_ipc_subcall
2013-02-21 19:13:47 +04:00
if ( tcp - > s_ent - > sys_func = = sys_ipc ) {
2012-03-16 02:08:55 +04:00
decode_ipc_subcall ( tcp ) ;
2012-02-20 21:02:38 +04:00
break ;
}
2012-02-25 05:44:25 +04:00
# endif
2012-02-20 21:02:38 +04:00
break ;
}
2013-02-21 19:13:47 +04:00
# endif
2012-02-20 21:02:38 +04:00
2013-02-06 16:18:42 +04:00
if ( need_fork_exec_workarounds )
syscall_fixup_for_fork_exec ( tcp ) ;
2011-08-24 20:07:22 +04:00
2013-02-21 19:13:47 +04:00
if ( ! ( tcp - > qual_flg & QUAL_TRACE )
| | ( tracing_paths & & ! pathtrace_match ( tcp ) )
) {
2011-08-24 20:07:22 +04:00
tcp - > flags | = TCB_INSYSCALL | TCB_FILTERED ;
return 0 ;
}
tcp - > flags & = ~ TCB_FILTERED ;
2013-05-14 18:07:46 +04:00
if ( cflag = = CFLAG_ONLY_STATS | | hide_log_until_execve ) {
2011-08-24 20:07:22 +04:00
res = 0 ;
goto ret ;
}
2014-04-16 10:33:35 +04:00
# ifdef USE_LIBUNWIND
if ( stack_trace_enabled ) {
if ( tcp - > s_ent - > sys_flags & STACKTRACE_CAPTURE_ON_ENTER )
unwind_capture_stacktrace ( tcp ) ;
}
# endif
2011-08-24 20:07:22 +04:00
printleader ( tcp ) ;
2013-02-21 19:13:47 +04:00
if ( tcp - > qual_flg & UNDEFINED_SCNO )
2013-02-21 18:46:34 +04:00
tprintf ( " %s( " , undefined_scno_name ( tcp ) ) ;
2011-08-24 20:07:22 +04:00
else
2013-02-21 19:13:47 +04:00
tprintf ( " %s( " , tcp - > s_ent - > sys_name ) ;
if ( ( tcp - > qual_flg & QUAL_RAW ) & & tcp - > s_ent - > sys_func ! = sys_exit )
2011-08-24 20:07:22 +04:00
res = printargs ( tcp ) ;
else
2013-02-21 19:13:47 +04:00
res = tcp - > s_ent - > sys_func ( tcp ) ;
2011-08-24 20:07:22 +04:00
2012-09-18 02:40:12 +04:00
fflush ( tcp - > outf ) ;
2011-08-24 20:07:22 +04:00
ret :
tcp - > flags | = TCB_INSYSCALL ;
/* Measure the entrance time as late as possible to avoid errors. */
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( Tflag | | cflag )
2011-08-24 20:07:22 +04:00
gettimeofday ( & tcp - > etime , NULL ) ;
return res ;
}
/* Returns:
2012-03-21 03:23:16 +04:00
* 1 : ok , continue in trace_syscall_exiting ( ) .
* - 1 : error , trace_syscall_exiting ( ) should print error indicator
2011-08-24 20:07:22 +04:00
* ( " ???? " etc ) and bail out .
*/
static int
get_syscall_result ( struct tcb * tcp )
{
2012-02-25 05:44:25 +04:00
# if defined(S390) || defined(S390X)
2013-07-07 14:47:39 +04:00
if ( upeek ( tcp - > pid , PT_GPR2 , & s390_gpr2 ) < 0 )
2011-08-25 12:31:24 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(POWERPC)
2013-06-28 18:47:38 +04:00
/* already done by get_regs */
2012-02-25 05:44:25 +04:00
# elif defined(AVR32)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* already done by get_regs */
2012-02-25 05:44:25 +04:00
# elif defined(BFIN)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R0 , & bfin_r0 ) < 0 )
2011-08-25 12:31:24 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(I386)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* already done by get_regs */
Add x32 support to strace
X32 support is added to Linux kernel 3.4. In a nutshell, x32 is x86-64 with
32bit pointers. At system call level, x32 is also identical to x86-64,
as shown by many changes like "defined(X86_64) || defined(X32)". The
main differerence bewteen x32 and x86-64 is off_t in x32 is long long
instead of long.
This patch adds x32 support to strace. Tested on Linux/x32.
* configure.ac: Support X32.
* defs.h: Set SUPPORTED_PERSONALITIES to 3 for X86_64,
Set PERSONALITY2_WORDSIZE to 4 for X86_64.
Add tcb::ext_arg for X32.
* file.c (stat): New for X32.
(sys_lseek): Use 64-bit version for X32.
(printstat64): Check current_personality != 1 for X86_64.
* ipc.c (indirect_ipccall): Check current_personality == 1
for X86_64.
* mem.c (sys_mmap64): Also use tcp->u_arg for X32. Print NULL
for zero address. Call printllval for offset for X32.
* pathtrace.c (pathtrace_match): Don't check sys_old_mmap for
X32.
* process.c (ARG_FLAGS): Defined for X32.
(ARG_STACK): Likewise.
(ARG_PTID): Likewise.
(change_syscall): Handle X32.
(struct_user_offsets): Support X32.
(sys_arch_prctl): Likewise.
* signal.c: Include <asm/sigcontext.h> for X32.
(SA_RESTORER): Also define for X32.
* syscall.c (update_personality): Support X32 for X86_64.
(is_restart_error): Likewise.
(syscall_fixup_on_sysenter): Likewise.
(get_syscall_args): Likewise.
(get_syscall_result): Likewise.
(get_error): Likewise.
(__X32_SYSCALL_BIT): Define if not defined.
(__X32_SYSCALL_MASK): Likewise.
(get_scno): Check DS register value for X32. Use
__X32_SYSCALL_MASK on X32 system calls.
* util.c (printllval): Use ext_arg for X32.
(printcall): Support X32.
(change_syscall): Likewise.
(arg0_offset): Likewise.
(arg1_offset): Likewise.
* Makefile.am (EXTRA_DIST): Add linux/x32/errnoent.h,
linux/x32/ioctlent.h.in, linux/x32/signalent.h,
linux/x32/syscallent.h, linux/x86_64/errnoent2.h,
linux/x86_64/ioctlent2.h, linux/x86_64/signalent2.h and
linux/x86_64/syscallent2.h.
* linux/x32/errnoent.h: New.
* linux/x32/ioctlent.h.in: Likewise.
* linux/x32/signalent.h: Likewise.
* linux/x32/syscallent.h: Likewise.
* linux/x86_64/errnoent2.h: Likewise.
* linux/x86_64/ioctlent2.h: Likewise.
* linux/x86_64/signalent2.h: Likewise.
* linux/x86_64/syscallent2.h: Likewise.
Signed-off-by: H.J. Lu <hongjiu.lu@intel.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-04-16 15:00:01 +04:00
# elif defined(X86_64) || defined(X32)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* already done by get_regs */
2012-02-25 05:44:25 +04:00
# elif defined(IA64)
2011-08-24 20:07:22 +04:00
# define IA64_PSR_IS ((long)1 << 34)
2013-02-06 21:09:31 +04:00
long psr ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_CR_IPSR , & psr ) > = 0 )
2013-07-01 14:28:17 +04:00
ia64_ia32mode = ( ( psr & IA64_PSR_IS ) ! = 0 ) ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R8 , & ia64_r8 ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_R10 , & ia64_r10 ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-02-08 15:38:51 +04:00
# elif defined(ARM)
/* already done by get_regs */
2012-10-24 20:58:16 +04:00
# elif defined(AARCH64)
2013-02-08 15:38:51 +04:00
/* register reading already done by get_regs */
/* Used to do this, but we did it on syscall entry already: */
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* We are in 64-bit mode (personality 1) if register struct is aarch64_regs,
* else it ' s personality 0.
*/
2013-02-08 15:38:51 +04:00
/*update_personality(tcp, aarch64_io.iov_len == sizeof(aarch64_regs));*/
2012-02-25 05:44:25 +04:00
# elif defined(M68K)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_D0 , & m68k_d0 ) < 0 )
2011-08-25 12:31:24 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(LINUX_MIPSN32)
2011-08-24 20:07:22 +04:00
unsigned long long regs [ 38 ] ;
if ( ptrace ( PTRACE_GETREGS , tcp - > pid , NULL , ( long ) & regs ) < 0 )
return - 1 ;
2013-02-13 20:52:31 +04:00
mips_a3 = regs [ REG_A3 ] ;
mips_r2 = regs [ REG_V0 ] ;
2012-02-25 05:44:25 +04:00
# elif defined(MIPS)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A3 , & mips_a3 ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_V0 , & mips_r2 ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(ALPHA)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A3 , & alpha_a3 ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_R0 , & alpha_r0 ) < 0 )
2011-08-24 20:07:22 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(SPARC) || defined(SPARC64)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* already done by get_regs */
2012-02-25 05:44:25 +04:00
# elif defined(HPPA)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , PT_GR28 , & hppa_r28 ) < 0 )
2011-08-25 12:31:24 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* new syscall ABI returns result in R0 */
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * REG_REG0 , ( long * ) & sh_r0 ) < 0 )
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(SH64)
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
/* ABI defines result returned in r9 */
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_GENERAL ( 9 ) , ( long * ) & sh64_r9 ) < 0 )
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(CRISV10) || defined(CRISV32)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 4 * PT_R10 , & cris_r10 ) < 0 )
2011-08-25 12:31:24 +04:00
return - 1 ;
2012-02-25 05:44:25 +04:00
# elif defined(TILE)
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
/* already done by get_regs */
2012-02-25 05:44:25 +04:00
# elif defined(MICROBLAZE)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , 3 * 4 , & microblaze_r3 ) < 0 )
2011-08-25 12:31:24 +04:00
return - 1 ;
2013-02-14 16:26:27 +04:00
# elif defined(OR1K)
/* already done by get_regs */
2013-02-22 18:44:10 +04:00
# elif defined(METAG)
/* already done by get_regs */
2013-03-25 21:22:07 +04:00
# elif defined(XTENSA)
2013-06-28 16:35:47 +04:00
if ( upeek ( tcp - > pid , REG_A_BASE + 2 , & xtensa_a2 ) < 0 )
2013-03-25 21:22:07 +04:00
return - 1 ;
2013-08-16 11:17:06 +04:00
# elif defined(ARC)
/* already done by get_regs */
2012-02-25 05:44:25 +04:00
# endif
2011-08-24 20:07:22 +04:00
return 1 ;
}
2012-03-20 20:10:35 +04:00
/* Called at each syscall exit */
static void
2011-08-25 12:23:00 +04:00
syscall_fixup_on_sysexit ( struct tcb * tcp )
{
2012-02-25 05:44:25 +04:00
# if defined(S390) || defined(S390X)
2011-08-25 12:25:35 +04:00
if ( ( tcp - > flags & TCB_WAITEXECVE )
2013-07-07 14:47:39 +04:00
& & ( s390_gpr2 = = - ENOSYS | | s390_gpr2 = = tcp - > scno ) ) {
2011-08-25 12:23:00 +04:00
/*
* Return from execve .
* Fake a return value of zero . We leave the TCB_WAITEXECVE
* flag set for the post - execve SIGTRAP to see and reset .
*/
2013-07-07 14:47:39 +04:00
s390_gpr2 = 0 ;
2011-08-25 12:23:00 +04:00
}
2012-02-25 05:44:25 +04:00
# endif
2011-08-25 12:23:00 +04:00
}
2011-08-24 20:07:22 +04:00
/*
* Check the syscall return value register value for whether it is
* a negated errno code indicating an error , or a success return value .
*/
2015-02-05 21:04:36 +03:00
# ifndef X32
2011-08-24 20:07:22 +04:00
static inline int
is_negated_errno ( unsigned long int val )
{
unsigned long int max = - ( long int ) nerrnos ;
2013-02-19 20:39:56 +04:00
# if SUPPORTED_PERSONALITIES > 1 && SIZEOF_LONG > 4
2012-03-19 12:36:42 +04:00
if ( current_wordsize < sizeof ( val ) ) {
2011-08-24 20:07:22 +04:00
val = ( unsigned int ) val ;
max = ( unsigned int ) max ;
}
2012-02-25 05:44:25 +04:00
# endif
2011-08-24 20:07:22 +04:00
return val > max ;
}
2015-02-05 21:04:36 +03:00
# else /* X32 */
2013-02-12 14:52:35 +04:00
static inline int
2015-02-05 21:04:36 +03:00
is_negated_errno ( unsigned long long val )
2013-02-12 14:52:35 +04:00
{
unsigned long long max = - ( long long ) nerrnos ;
/*
* current_wordsize is 4 even in personality 0 ( native X32 )
* but truncation _must not_ be done in it .
* can ' t check current_wordsize here !
*/
if ( current_personality ! = 0 ) {
val = ( uint32_t ) val ;
max = ( uint32_t ) max ;
}
return val > max ;
}
2015-02-05 21:04:36 +03:00
# endif /* X32 */
2013-02-12 14:52:35 +04:00
2012-03-21 03:23:16 +04:00
/* Returns:
* 1 : ok , continue in trace_syscall_exiting ( ) .
* - 1 : error , trace_syscall_exiting ( ) should print error indicator
* ( " ???? " etc ) and bail out .
*/
2013-02-16 17:25:56 +04:00
static void
2011-08-24 20:07:22 +04:00
get_error ( struct tcb * tcp )
{
int u_error = 0 ;
int check_errno = 1 ;
2013-02-21 19:13:47 +04:00
if ( tcp - > s_ent - > sys_flags & SYSCALL_NEVER_FAILS ) {
2011-08-24 20:07:22 +04:00
check_errno = 0 ;
}
2012-02-25 05:44:25 +04:00
# if defined(S390) || defined(S390X)
2013-07-07 14:47:39 +04:00
if ( check_errno & & is_negated_errno ( s390_gpr2 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-07-07 14:47:39 +04:00
u_error = - s390_gpr2 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-07-07 14:47:39 +04:00
tcp - > u_rval = s390_gpr2 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(I386)
2011-08-30 20:53:49 +04:00
if ( check_errno & & is_negated_errno ( i386_regs . eax ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2011-08-30 20:53:49 +04:00
u_error = - i386_regs . eax ;
2011-08-24 20:07:22 +04:00
}
else {
2011-08-30 20:53:49 +04:00
tcp - > u_rval = i386_regs . eax ;
2011-08-24 20:07:22 +04:00
}
2013-02-12 14:52:35 +04:00
# elif defined(X86_64)
2013-02-14 06:29:48 +04:00
long rax ;
if ( x86_io . iov_len = = sizeof ( i386_regs ) ) {
/* Sign extend from 32 bits */
rax = ( int32_t ) i386_regs . eax ;
} else {
rax = x86_64_regs . rax ;
}
if ( check_errno & & is_negated_errno ( rax ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-14 06:29:48 +04:00
u_error = - rax ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-14 06:29:48 +04:00
tcp - > u_rval = rax ;
2013-02-12 14:52:35 +04:00
}
# elif defined(X32)
2013-02-14 06:29:48 +04:00
/* In X32, return value is 64-bit (llseek uses one).
* Using merely " long rax " would not work .
*/
long long rax ;
if ( x86_io . iov_len = = sizeof ( i386_regs ) ) {
/* Sign extend from 32 bits */
rax = ( int32_t ) i386_regs . eax ;
} else {
rax = x86_64_regs . rax ;
}
2015-02-05 21:04:36 +03:00
if ( check_errno & & is_negated_errno ( rax ) ) {
2013-02-12 14:52:35 +04:00
tcp - > u_rval = - 1 ;
2013-02-14 06:29:48 +04:00
u_error = - rax ;
2013-02-12 14:52:35 +04:00
}
else {
2013-02-14 06:29:48 +04:00
tcp - > u_rval = rax ; /* truncating */
tcp - > u_lrval = rax ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(IA64)
2013-07-01 14:28:17 +04:00
if ( ia64_ia32mode ) {
2011-08-24 20:07:22 +04:00
int err ;
2013-02-07 16:14:48 +04:00
err = ( int ) ia64_r8 ;
2011-08-24 20:07:22 +04:00
if ( check_errno & & is_negated_errno ( err ) ) {
tcp - > u_rval = - 1 ;
u_error = - err ;
}
else {
tcp - > u_rval = err ;
}
} else {
2013-02-07 16:14:48 +04:00
if ( check_errno & & ia64_r10 ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-07 16:14:48 +04:00
u_error = ia64_r8 ;
2011-08-24 20:07:22 +04:00
} else {
2013-02-07 16:14:48 +04:00
tcp - > u_rval = ia64_r8 ;
2011-08-24 20:07:22 +04:00
}
}
2012-02-25 05:44:25 +04:00
# elif defined(MIPS)
2013-02-13 20:52:31 +04:00
if ( check_errno & & mips_a3 ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-13 20:52:31 +04:00
u_error = mips_r2 ;
2011-08-24 20:07:22 +04:00
} else {
2013-02-13 20:52:31 +04:00
tcp - > u_rval = mips_r2 ;
2012-04-16 14:16:45 +04:00
# if defined(LINUX_MIPSN32)
2013-02-13 20:52:31 +04:00
tcp - > u_lrval = mips_r2 ;
2012-04-16 14:16:45 +04:00
# endif
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(POWERPC)
2013-06-28 18:47:38 +04:00
if ( check_errno & & ( ppc_regs . ccr & 0x10000000 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-06-28 18:47:38 +04:00
u_error = ppc_regs . gpr [ 3 ] ;
2011-08-24 20:07:22 +04:00
}
else {
2013-06-28 18:47:38 +04:00
tcp - > u_rval = ppc_regs . gpr [ 3 ] ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(M68K)
2013-02-07 16:14:48 +04:00
if ( check_errno & & is_negated_errno ( m68k_d0 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-07 16:14:48 +04:00
u_error = - m68k_d0 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-07 16:14:48 +04:00
tcp - > u_rval = m68k_d0 ;
2011-08-24 20:07:22 +04:00
}
2012-11-10 15:24:48 +04:00
# elif defined(ARM) || defined(AARCH64)
# if defined(AARCH64)
if ( tcp - > currpers = = 1 ) {
if ( check_errno & & is_negated_errno ( aarch64_regs . regs [ 0 ] ) ) {
tcp - > u_rval = - 1 ;
u_error = - aarch64_regs . regs [ 0 ] ;
}
else {
tcp - > u_rval = aarch64_regs . regs [ 0 ] ;
}
2012-10-24 20:58:16 +04:00
}
2012-11-10 15:24:48 +04:00
else
2013-02-08 15:38:51 +04:00
# endif
2012-11-10 15:24:48 +04:00
{
2013-02-06 21:24:39 +04:00
if ( check_errno & & is_negated_errno ( arm_regs . ARM_r0 ) ) {
2012-11-10 15:24:48 +04:00
tcp - > u_rval = - 1 ;
2013-02-06 21:24:39 +04:00
u_error = - arm_regs . ARM_r0 ;
2012-11-10 15:24:48 +04:00
}
else {
2013-02-06 21:24:39 +04:00
tcp - > u_rval = arm_regs . ARM_r0 ;
2012-11-10 15:24:48 +04:00
}
2012-10-24 20:58:16 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(AVR32)
2013-02-16 11:23:40 +04:00
if ( check_errno & & avr32_regs . r12 & & ( unsigned ) - avr32_regs . r12 < nerrnos ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-16 11:23:40 +04:00
u_error = - avr32_regs . r12 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-16 11:23:40 +04:00
tcp - > u_rval = avr32_regs . r12 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(BFIN)
2013-02-13 20:52:31 +04:00
if ( check_errno & & is_negated_errno ( bfin_r0 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-13 20:52:31 +04:00
u_error = - bfin_r0 ;
2011-08-24 20:07:22 +04:00
} else {
2013-02-13 20:52:31 +04:00
tcp - > u_rval = bfin_r0 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(ALPHA)
2013-02-07 16:14:48 +04:00
if ( check_errno & & alpha_a3 ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-13 20:52:31 +04:00
u_error = alpha_r0 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-13 20:52:31 +04:00
tcp - > u_rval = alpha_r0 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(SPARC)
2013-02-16 11:23:40 +04:00
if ( check_errno & & sparc_regs . psr & PSR_C ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-16 11:23:40 +04:00
u_error = sparc_regs . u_regs [ U_REG_O0 ] ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-16 11:23:40 +04:00
tcp - > u_rval = sparc_regs . u_regs [ U_REG_O0 ] ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(SPARC64)
2013-02-16 11:23:40 +04:00
if ( check_errno & & sparc_regs . tstate & 0x1100000000UL ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-16 11:23:40 +04:00
u_error = sparc_regs . u_regs [ U_REG_O0 ] ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-16 11:23:40 +04:00
tcp - > u_rval = sparc_regs . u_regs [ U_REG_O0 ] ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(HPPA)
2013-02-07 16:14:48 +04:00
if ( check_errno & & is_negated_errno ( hppa_r28 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-07 16:14:48 +04:00
u_error = - hppa_r28 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-07 16:14:48 +04:00
tcp - > u_rval = hppa_r28 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(SH)
2013-02-13 20:52:31 +04:00
if ( check_errno & & is_negated_errno ( sh_r0 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-13 20:52:31 +04:00
u_error = - sh_r0 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-13 20:52:31 +04:00
tcp - > u_rval = sh_r0 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(SH64)
2013-02-07 16:14:48 +04:00
if ( check_errno & & is_negated_errno ( sh64_r9 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-07 16:14:48 +04:00
u_error = - sh64_r9 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-07 16:14:48 +04:00
tcp - > u_rval = sh64_r9 ;
2011-08-24 20:07:22 +04:00
}
2013-02-22 18:44:10 +04:00
# elif defined(METAG)
/* result pointer in D0Re0 (D0.0) */
if ( check_errno & & is_negated_errno ( metag_regs . dx [ 0 ] [ 0 ] ) ) {
tcp - > u_rval = - 1 ;
u_error = - metag_regs . dx [ 0 ] [ 0 ] ;
}
else {
tcp - > u_rval = metag_regs . dx [ 0 ] [ 0 ] ;
}
2012-02-25 05:44:25 +04:00
# elif defined(CRISV10) || defined(CRISV32)
2013-02-07 16:14:48 +04:00
if ( check_errno & & cris_r10 & & ( unsigned ) - cris_r10 < nerrnos ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-07 16:14:48 +04:00
u_error = - cris_r10 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-07 16:14:48 +04:00
tcp - > u_rval = cris_r10 ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(TILE)
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
/*
* The standard tile calling convention returns the value ( or negative
* errno ) in r0 , and zero ( or positive errno ) in r1 .
* Until at least kernel 3.8 , however , the r1 value is not reflected
* in ptregs at this point , so we use r0 here .
*/
if ( check_errno & & is_negated_errno ( tile_regs . regs [ 0 ] ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
Add tilegx support to strace
tilegx support has been in the kernel since 3.0.
In addition, fix some issues with the tilepro support already
present in strace, primarily the decision to use the
<asm/unistd.h> numbering space for system calls.
* defs.h [TILE]: Include <asm/ptrace.h> and provide an extern
struct pt_regs tile_regs for efficiency. Provide compat 32-bit
personality via SUPPORTED_PERSONALITIES, PERSONALITY0_WORDSIZE,
PERSONALITY1_WORDSIZE, and DEFAULT_PERSONALITY.
* linux/tile/errnoent1.h: New file, includes linux/errnoent.h.
* linux/tile/ioctlent1.h: New file, includes linux/ioctlent.h.
* linux/tile/signalent1.h: New file, includes linux/signalent.h.
* linux/tile/syscallent.h: Update with new asm-generic syscalls.
The version previously committed was the from the first tile patch
to LKML, which subsequently was changed to use <asm-generic/unistd.h>.
* linux/tile/syscallent1.h: Copy from linux/tile/syscallent.h.
* mem.c (addtileflags) [TILE]: use %ld properly for a "long" variable.
* process.c [TILE]: Choose clone arguments correctly and properly
suppress all "struct user" related offsets in user_struct_offsets.
* signal.c [TILE]: Use tile_regs not upeek.
* syscall.c (update_personality) [TILE]: Print mode.
(PT_FLAGS_COMPAT) [TILE]: Provide if not in system headers.
(tile_regs) [TILE]: Define 'struct pt_regs' variable to hold state.
(get_regs) [TILE]: use PTRACE_GETREGS to set tile_regs rather than using upeek.
(get_scno) [TILE]: Set personality.
(get_syscall_args) [TILE]: Use tile_regs.
(get_syscall_result) [TILE]: Update tile_regs.
(get_error) [TILE]: Use tile_regs.
(printcall) [TILE]: Print pc.
(arg0_offset, arg1_offset, restore_arg0, restore_arg1) [TILE]:
Properly handle tile call semantics and support tilegx.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 20:48:33 +04:00
u_error = - tile_regs . regs [ 0 ] ;
} else {
tcp - > u_rval = tile_regs . regs [ 0 ] ;
2011-08-24 20:07:22 +04:00
}
2012-02-25 05:44:25 +04:00
# elif defined(MICROBLAZE)
2013-02-07 16:14:48 +04:00
if ( check_errno & & is_negated_errno ( microblaze_r3 ) ) {
2011-08-24 20:07:22 +04:00
tcp - > u_rval = - 1 ;
2013-02-07 16:14:48 +04:00
u_error = - microblaze_r3 ;
2011-08-24 20:07:22 +04:00
}
else {
2013-02-07 16:14:48 +04:00
tcp - > u_rval = microblaze_r3 ;
2011-08-24 20:07:22 +04:00
}
2013-02-14 16:26:27 +04:00
# elif defined(OR1K)
if ( check_errno & & is_negated_errno ( or1k_regs . gpr [ 11 ] ) ) {
tcp - > u_rval = - 1 ;
u_error = - or1k_regs . gpr [ 11 ] ;
}
else {
tcp - > u_rval = or1k_regs . gpr [ 11 ] ;
}
2013-03-25 21:22:07 +04:00
# elif defined(XTENSA)
if ( check_errno & & is_negated_errno ( xtensa_a2 ) ) {
tcp - > u_rval = - 1 ;
u_error = - xtensa_a2 ;
}
else {
tcp - > u_rval = xtensa_a2 ;
}
2013-08-16 11:17:06 +04:00
# elif defined(ARC)
if ( check_errno & & is_negated_errno ( arc_regs . scratch . r0 ) ) {
tcp - > u_rval = - 1 ;
u_error = - arc_regs . scratch . r0 ;
}
else {
tcp - > u_rval = arc_regs . scratch . r0 ;
}
2012-02-25 05:44:25 +04:00
# endif
2011-08-24 20:07:22 +04:00
tcp - > u_error = u_error ;
}
2011-08-22 13:54:06 +04:00
2011-08-24 20:07:22 +04:00
static void
dumpio ( struct tcb * tcp )
{
2013-02-21 19:13:47 +04:00
int ( * func ) ( ) ;
2011-08-24 20:07:22 +04:00
if ( syserror ( tcp ) )
return ;
2013-02-22 16:37:36 +04:00
if ( ( unsigned long ) tcp - > u_arg [ 0 ] > = num_quals )
2011-08-24 20:07:22 +04:00
return ;
2013-02-21 19:13:47 +04:00
func = tcp - > s_ent - > sys_func ;
if ( func = = printargs )
2011-08-24 20:07:22 +04:00
return ;
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_READ ) {
2013-02-21 19:13:47 +04:00
if ( func = = sys_read | |
func = = sys_pread | |
func = = sys_recv | |
2015-02-01 01:57:00 +03:00
func = = sys_recvfrom ) {
2011-08-24 20:07:22 +04:00
dumpstr ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_rval ) ;
2015-02-01 01:57:00 +03:00
return ;
} else if ( func = = sys_readv ) {
2011-08-24 20:07:22 +04:00
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
2015-02-01 01:57:00 +03:00
return ;
2014-10-15 17:11:43 +04:00
# if HAVE_SENDMSG
2015-02-01 01:57:00 +03:00
} else if ( func = = sys_recvmsg ) {
2014-10-15 17:11:43 +04:00
dumpiov_in_msghdr ( tcp , tcp - > u_arg [ 1 ] ) ;
2015-02-01 01:57:00 +03:00
return ;
} else if ( func = = sys_recvmmsg ) {
2014-11-06 19:23:26 +03:00
dumpiov_in_mmsghdr ( tcp , tcp - > u_arg [ 1 ] ) ;
2015-02-01 01:57:00 +03:00
return ;
2014-10-15 17:11:43 +04:00
# endif
2015-02-01 01:57:00 +03:00
}
2011-08-22 13:54:06 +04:00
}
2011-08-24 20:07:22 +04:00
if ( qual_flags [ tcp - > u_arg [ 0 ] ] & QUAL_WRITE ) {
2013-02-21 19:13:47 +04:00
if ( func = = sys_write | |
func = = sys_pwrite | |
func = = sys_send | |
func = = sys_sendto )
2011-08-24 20:07:22 +04:00
dumpstr ( tcp , tcp - > u_arg [ 1 ] , tcp - > u_arg [ 2 ] ) ;
2013-02-21 19:13:47 +04:00
else if ( func = = sys_writev )
2011-08-24 20:07:22 +04:00
dumpiov ( tcp , tcp - > u_arg [ 2 ] , tcp - > u_arg [ 1 ] ) ;
2014-10-15 17:11:43 +04:00
# if HAVE_SENDMSG
else if ( func = = sys_sendmsg )
dumpiov_in_msghdr ( tcp , tcp - > u_arg [ 1 ] ) ;
2014-11-06 19:23:26 +03:00
else if ( func = = sys_sendmmsg )
dumpiov_in_mmsghdr ( tcp , tcp - > u_arg [ 1 ] ) ;
2014-10-15 17:11:43 +04:00
# endif
2011-08-22 13:54:06 +04:00
}
}
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 ;
2011-08-25 02:29:56 +04:00
int res ;
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. */
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( Tflag | | cflag )
2010-03-29 21:51:02 +04:00
gettimeofday ( & tv , NULL ) ;
2008-12-17 22:21:59 +03:00
2014-04-16 10:33:35 +04:00
# ifdef USE_LIBUNWIND
if ( stack_trace_enabled ) {
if ( tcp - > s_ent - > sys_flags & STACKTRACE_INVALIDATE_CACHE )
unwind_cache_invalidate ( tcp ) ;
}
# endif
2011-12-23 04:50:49 +04:00
# if SUPPORTED_PERSONALITIES > 1
update_personality ( tcp , tcp - > currpers ) ;
# endif
Optimize out PTRACE_PEEKUSER with -i
strace -i was fetching PC with a separate PEEKUSER
despite having GETREGS data:
ptrace(PTRACE_GETREGS, 22331, 0, 0x8087f00) = 0
ptrace(PTRACE_PEEKUSER, 22331, 4*EIP, [0x80dd7b7]) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22331, 0, SIG_0) = 0
Now it does this:
ptrace(PTRACE_GETREGS, 22549, 0, 0x8087ea0) = 0
write(3, "[080dd7b7] ioctl(0, SNDCTL_TMR_T"..., 82) = 82
ptrace(PTRACE_SYSCALL, 22549, 0, SIG_0) = 0
Analogous improvement in sys_sigreturn() is also implemented.
* defs.h: Declare extern struct pt_regs regs for SPARC[64] and ARM.
Declare clear_regs(), get_regs() and get_regs_error flag variable.
* strace.c (trace): Call get_regs(pid) as soon as we know the tcb
and that it is stopped.
* syscall.c (get_regs): New function. Used to fetch registers early,
just after tracee has stopped.
(printcall): Move it here from util.c. Use global regs.REG data,
if available on the arch, instead of re-fetching it.
(get_scno): Use global regs.REG data.
(get_syscall_result): Likewise.
* signal.c (sys_sigreturn): Likewise.
* util.c (printcall): Moved to syscall.c.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2013-02-05 19:36:13 +04:00
res = ( get_regs_error ? - 1 : get_syscall_result ( tcp ) ) ;
2012-03-20 20:10:35 +04:00
if ( res = = 1 ) {
syscall_fixup_on_sysexit ( tcp ) ; /* never fails */
2013-02-16 17:25:56 +04:00
get_error ( tcp ) ; /* never fails */
if ( need_fork_exec_workarounds )
syscall_fixup_for_fork_exec ( tcp ) ;
2013-05-14 18:07:46 +04:00
if ( filtered ( tcp ) | | hide_log_until_execve )
2013-02-16 17:25:56 +04:00
goto ret ;
2010-03-29 21:51:02 +04:00
}
2000-02-01 20:58:41 +03:00
2010-03-29 21:51:02 +04:00
if ( cflag ) {
2014-05-29 22:10:00 +04:00
count_syscall ( tcp , & tv ) ;
2011-06-22 16:32:43 +04:00
if ( cflag = = CFLAG_ONLY_STATS ) {
Fix -z display.
Before this patch, the following:
open("qwerty", O_RDONLY) = -1 ENOENT
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
was shown totally wrongly with -z:
open("qwerty", O_RDONLY) = 38
(yes, that's right, write syscall is lost!)
Now it is shown "less wrongly" as:
open("qwerty", O_RDONLY <unfinished ...>
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
* syscall.c (trace_syscall_exiting): Use common TCB_INSYSCALL clearing
via "goto ret". This fixes totally broken display of -z, but even now
it is not working as intended. Add a comment about that.
(trace_syscall_entering): Use common TCB_INSYSCALL setting
via "goto ret".
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-22 04:06:35 +04:00
goto ret ;
2008-12-17 22:21:59 +03:00
}
2010-03-29 21:51:02 +04:00
}
2008-12-17 22:21:59 +03:00
2012-03-21 14:06:20 +04:00
/* If not in -ff mode, and printing_tcp != tcp,
* then the log currently does not end with output
* of _our syscall entry_ , but with something else .
* We need to say which syscall ' s return is this .
*
* Forced reprinting via TCB_REPRINT is used only by
* " strace -ff -oLOG test/threaded_execve " corner case .
* It ' s the only case when - ff mode needs reprinting .
*/
if ( ( followfork < 2 & & printing_tcp ! = tcp ) | | ( tcp - > flags & TCB_REPRINT ) ) {
tcp - > flags & = ~ TCB_REPRINT ;
printleader ( tcp ) ;
2013-02-21 19:13:47 +04:00
if ( tcp - > qual_flg & UNDEFINED_SCNO )
2013-02-21 18:46:34 +04:00
tprintf ( " <... %s resumed> " , undefined_scno_name ( tcp ) ) ;
2012-03-21 14:06:20 +04:00
else
2013-02-21 19:13:47 +04:00
tprintf ( " <... %s resumed> " , tcp - > s_ent - > sys_name ) ;
2012-03-21 14:06:20 +04:00
}
printing_tcp = tcp ;
2010-03-29 21:51:02 +04:00
if ( res ! = 1 ) {
2012-03-21 14:06:20 +04:00
/* There was error in one of prior ptrace ops */
2011-09-01 12:00:28 +04:00
tprints ( " ) " ) ;
2011-08-25 03:27:59 +04:00
tabto ( ) ;
2012-01-28 04:25:03 +04:00
tprints ( " = ? <unavailable> \n " ) ;
2012-03-13 14:44:31 +04:00
line_ended ( ) ;
2010-03-29 21:51:02 +04:00
tcp - > flags & = ~ TCB_INSYSCALL ;
return res ;
}
2012-03-21 14:06:20 +04:00
sys_res = 0 ;
2013-02-21 19:13:47 +04:00
if ( tcp - > qual_flg & QUAL_RAW ) {
2012-03-21 14:06:20 +04:00
/* sys_res = printargs(tcp); - but it's nop on sysexit */
2012-03-13 14:44:31 +04:00
} else {
Fix -z display.
Before this patch, the following:
open("qwerty", O_RDONLY) = -1 ENOENT
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
was shown totally wrongly with -z:
open("qwerty", O_RDONLY) = 38
(yes, that's right, write syscall is lost!)
Now it is shown "less wrongly" as:
open("qwerty", O_RDONLY <unfinished ...>
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
* syscall.c (trace_syscall_exiting): Use common TCB_INSYSCALL clearing
via "goto ret". This fixes totally broken display of -z, but even now
it is not working as intended. Add a comment about that.
(trace_syscall_entering): Use common TCB_INSYSCALL setting
via "goto ret".
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-22 04:06:35 +04:00
/* FIXME: not_failing_only (IOW, option -z) is broken:
* failure of syscall is known only after syscall return .
* Thus we end up with something like this on , say , ENOENT :
* open ( " doesnt_exist " , O_RDONLY < unfinished . . . >
* { next syscall decode }
* whereas the intended result is that open ( . . . ) line
* is not shown at all .
*/
2010-03-29 21:51:02 +04:00
if ( not_failing_only & & tcp - > u_error )
Fix -z display.
Before this patch, the following:
open("qwerty", O_RDONLY) = -1 ENOENT
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
was shown totally wrongly with -z:
open("qwerty", O_RDONLY) = 38
(yes, that's right, write syscall is lost!)
Now it is shown "less wrongly" as:
open("qwerty", O_RDONLY <unfinished ...>
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
* syscall.c (trace_syscall_exiting): Use common TCB_INSYSCALL clearing
via "goto ret". This fixes totally broken display of -z, but even now
it is not working as intended. Add a comment about that.
(trace_syscall_entering): Use common TCB_INSYSCALL setting
via "goto ret".
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-22 04:06:35 +04:00
goto ret ; /* ignore failed syscalls */
2013-02-21 19:13:47 +04:00
sys_res = tcp - > s_ent - > sys_func ( tcp ) ;
2010-03-29 21:51:02 +04:00
}
2011-09-01 12:00:28 +04:00
tprints ( " ) " ) ;
2011-08-25 03:27:59 +04:00
tabto ( ) ;
Fix -z display.
Before this patch, the following:
open("qwerty", O_RDONLY) = -1 ENOENT
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
was shown totally wrongly with -z:
open("qwerty", O_RDONLY) = 38
(yes, that's right, write syscall is lost!)
Now it is shown "less wrongly" as:
open("qwerty", O_RDONLY <unfinished ...>
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
* syscall.c (trace_syscall_exiting): Use common TCB_INSYSCALL clearing
via "goto ret". This fixes totally broken display of -z, but even now
it is not working as intended. Add a comment about that.
(trace_syscall_entering): Use common TCB_INSYSCALL setting
via "goto ret".
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-22 04:06:35 +04:00
u_error = tcp - > u_error ;
2013-02-21 19:13:47 +04:00
if ( tcp - > qual_flg & QUAL_RAW ) {
2010-03-29 21:51:02 +04:00
if ( u_error )
tprintf ( " = -1 (errno %ld) " , u_error ) ;
else
tprintf ( " = %#lx " , tcp - > u_rval ) ;
}
else if ( ! ( sys_res & RVAL_NONE ) & & u_error ) {
switch ( u_error ) {
2012-01-12 14:26:34 +04:00
/* Blocked signals do not interrupt any syscalls.
* In this case syscalls don ' t return ERESTARTfoo codes .
*
* Deadly signals set to SIG_DFL interrupt syscalls
* and kill the process regardless of which of the codes below
* is returned by the interrupted syscall .
* In some cases , kernel forces a kernel - generated deadly
* signal to be unblocked and set to SIG_DFL ( and thus cause
* death ) if it is blocked or SIG_IGNed : for example , SIGSEGV
* or SIGILL . ( The alternative is to leave process spinning
* forever on the faulty instruction - not useful ) .
*
* SIG_IGNed signals and non - deadly signals set to SIG_DFL
* ( for example , SIGCHLD , SIGWINCH ) interrupt syscalls ,
* but kernel will always restart them .
*/
2010-03-29 21:51:02 +04:00
case ERESTARTSYS :
2012-01-12 14:26:34 +04:00
/* Most common type of signal-interrupted syscall exit code.
* The system call will be restarted with the same arguments
* if SA_RESTART is set ; otherwise , it will fail with EINTR .
*/
tprints ( " = ? ERESTARTSYS (To be restarted if SA_RESTART is set) " ) ;
2010-03-29 21:51:02 +04:00
break ;
case ERESTARTNOINTR :
2012-01-12 14:26:34 +04:00
/* Rare. For example, fork() returns this if interrupted.
* SA_RESTART is ignored ( assumed set ) : the restart is unconditional .
*/
2011-09-01 12:00:28 +04:00
tprints ( " = ? ERESTARTNOINTR (To be restarted) " ) ;
2010-03-29 21:51:02 +04:00
break ;
case ERESTARTNOHAND :
2012-01-12 14:26:34 +04:00
/* pause(), rt_sigsuspend() etc use this code.
* SA_RESTART is ignored ( assumed not set ) :
* syscall won ' t restart ( will return EINTR instead )
2013-02-19 19:59:26 +04:00
* even after signal with SA_RESTART set . However ,
* after SIG_IGN or SIG_DFL signal it will restart
* ( thus the name " restart only if has no handler " ) .
2012-01-12 14:26:34 +04:00
*/
2013-03-05 19:56:35 +04:00
tprints ( " = ? ERESTARTNOHAND (To be restarted if no handler) " ) ;
2010-03-29 21:51:02 +04:00
break ;
case ERESTART_RESTARTBLOCK :
2012-01-12 14:26:34 +04:00
/* Syscalls like nanosleep(), poll() which can't be
* restarted with their original arguments use this
* code . Kernel will execute restart_syscall ( ) instead ,
* which changes arguments before restarting syscall .
* SA_RESTART is ignored ( assumed not set ) similarly
* to ERESTARTNOHAND . ( Kernel can ' t honor SA_RESTART
* since restart data is saved in " restart block "
* in task struct , and if signal handler uses a syscall
* which in turn saves another such restart block ,
* old data is lost and restart becomes impossible )
*/
tprints ( " = ? ERESTART_RESTARTBLOCK (Interrupted by signal) " ) ;
2010-03-29 21:51:02 +04:00
break ;
default :
if ( u_error < 0 )
2011-08-21 19:26:55 +04:00
tprintf ( " = -1 E??? (errno %ld) " , u_error ) ;
2014-09-10 17:46:04 +04:00
else if ( ( unsigned long ) 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 )
2011-09-01 12:00:28 +04:00
tprints ( " = ? " ) ;
2010-03-29 21:51:02 +04:00
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 ;
2014-06-04 07:00:41 +04:00
case RVAL_FD :
if ( show_fd_path ) {
tprints ( " = " ) ;
printfd ( tcp , tcp - > u_rval ) ;
}
else
tprintf ( " = %ld " , tcp - > u_rval ) ;
break ;
2012-04-16 14:16:45 +04:00
# if defined(LINUX_MIPSN32) || defined(X32)
/*
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 ;
*/
# 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 ) ;
}
Tidy up order of includes; make bool variables explicit.
Bool variables are more compact in data and (on x86) on code too:
text data bss dec hex filename
237950 676 19044 257670 3ee86 strace.before
237838 676 19012 257526 3edf6 strace
* defs.h: Group library includes at the top of the file.
Rename dtime to Tflag, debug to debug_flag.
Change debug_flag,Tflag,qflag,not_failing_only,show_fd_path,tracing_paths
variable declarations from int to bool.
* strace.c: Change corresponding definitions. Do the same for static
variables iflag,rflag,print_pid_pfx.
Rename dtime to Tflag, debug to debug_flag.
* syscall.c: Rename dtime to Tflag, debug to debug_flag.
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2012-03-15 15:49:52 +04:00
if ( Tflag ) {
2010-03-29 21:51:02 +04:00
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
}
2012-01-28 04:25:03 +04:00
tprints ( " \n " ) ;
2010-03-29 21:51:02 +04:00
dumpio ( tcp ) ;
2012-03-13 14:44:31 +04:00
line_ended ( ) ;
2013-07-23 11:11:35 +04:00
# ifdef USE_LIBUNWIND
if ( stack_trace_enabled )
2014-04-16 10:33:02 +04:00
unwind_print_stacktrace ( tcp ) ;
2013-07-23 11:11:35 +04:00
# endif
Fix -z display.
Before this patch, the following:
open("qwerty", O_RDONLY) = -1 ENOENT
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
was shown totally wrongly with -z:
open("qwerty", O_RDONLY) = 38
(yes, that's right, write syscall is lost!)
Now it is shown "less wrongly" as:
open("qwerty", O_RDONLY <unfinished ...>
write(2, "wc: qwerty: No such file or dire"..., 38) = 38
* syscall.c (trace_syscall_exiting): Use common TCB_INSYSCALL clearing
via "goto ret". This fixes totally broken display of -z, but even now
it is not working as intended. Add a comment about that.
(trace_syscall_entering): Use common TCB_INSYSCALL setting
via "goto ret".
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
2011-08-22 04:06:35 +04:00
ret :
2010-03-29 21:51:02 +04:00
tcp - > flags & = ~ TCB_INSYSCALL ;
return 0 ;
}
int
trace_syscall ( struct tcb * tcp )
{
return exiting ( tcp ) ?
trace_syscall_exiting ( tcp ) : trace_syscall_entering ( tcp ) ;
}