Compare commits

...

1 Commits

Author SHA1 Message Date
Gleb Fotengauer-Malinovskiy
fa82fca19b powerpc, x86_64: drop support of very old kernels
Assume that powerpc/powerpc64 kernel supports PTRACE_GETREGS
and x86_64 kernel supports PTRACE_GETREGSET.
This effectively drops support of powerpc/powerpc64 kernel
versions < 2.6.23 and x86_64 kernel versions < 2.6.34.

* linux/getregs_old.h: Remove.
* linux/powerpc/getregs_old.c: Likewise.
* linux/powerpc/getregs_old.h: Likewise.
* linux/powerpc64/getregs_old.c: Likewise.
* linux/powerpc64/getregs_old.h: Likewise.
* linux/x86_64/getregs_old.c: Likewise.
* linux/x86_64/getregs_old.h: Likewise.
* Makefile.am (EXTRA_DIST): Remove them.
* linux/i386/set_error.c (arch_set_error, arch_set_success)
[HAVE_GETREGS_OLD]: Remove.
* linux/powerpc/set_error.c: Likewise.
* linux/x86_64/set_error.c: Likewise.
Include "i386/set_error.c" unconditionally.
* linux/i386/set_scno.c (arch_set_scno) [HAVE_GETREGS_OLD]: Remove.
* linux/powerpc/set_scno.c: Likewise.
* linux/x86_64/set_scno.c: Likewise.
Include "i386/set_scno.c" unconditionally.
* syscall.c: Do not include "getregs_old.h".
[HAVE_GETREGS_OLD]: Do not include "getregs_old.c".
[ARCH_REGS_FOR_GETREGSET] (ptrace_setregset): Define unconditionally.
[ARCH_REGS_FOR_GETREGS] (ptrace_setregs): Define unconditionally.
(get_regs) [HAVE_GETREGS_OLD]: Remove.
* NEWS (Portability): Document this.
2017-03-29 22:29:28 +00:00
16 changed files with 22 additions and 206 deletions

View File

@ -429,7 +429,6 @@ EXTRA_DIST = \
linux/crisv32/userent.h \
linux/dummy.h \
linux/errnoent.h \
linux/getregs_old.h \
linux/hppa/arch_regs.c \
linux/hppa/arch_regs.h \
linux/hppa/arch_rt_sigframe.c \
@ -569,8 +568,6 @@ EXTRA_DIST = \
linux/powerpc/get_error.c \
linux/powerpc/get_scno.c \
linux/powerpc/get_syscall_args.c \
linux/powerpc/getregs_old.c \
linux/powerpc/getregs_old.h \
linux/powerpc/ioctls_arch0.h \
linux/powerpc/ioctls_inc0.h \
linux/powerpc/set_error.c \
@ -586,8 +583,6 @@ EXTRA_DIST = \
linux/powerpc64/get_error.c \
linux/powerpc64/get_scno.c \
linux/powerpc64/get_syscall_args.c \
linux/powerpc64/getregs_old.c \
linux/powerpc64/getregs_old.h \
linux/powerpc64/ioctls_arch0.h \
linux/powerpc64/ioctls_arch1.h \
linux/powerpc64/ioctls_inc0.h \
@ -771,8 +766,6 @@ EXTRA_DIST = \
linux/x86_64/get_error.c \
linux/x86_64/get_scno.c \
linux/x86_64/get_syscall_args.c \
linux/x86_64/getregs_old.c \
linux/x86_64/getregs_old.h \
linux/x86_64/ioctls_arch0.h \
linux/x86_64/ioctls_arch1.h \
linux/x86_64/ioctls_arch2.h \

6
NEWS
View File

@ -16,6 +16,12 @@ Noteworthy changes in release ?.?? (????-??-??)
* Implemented decoding of statx syscall.
* Updated lists of ioctl commands from Linux 4.11.
* Portability
* On powerpc and powerpc64 linux kernel >= 2.6.23 is required.
Older versions without a decent PTRACE_GETREGS support will not work.
* On x86_64 linux kernel >= 2.6.34 is required.
Older versions without a decent PTRACE_GETREGSET support will not work.
* Bug fixes
* Fixed decoding of flags argument of preadv2 and pwritev2 syscalls on x32.

View File

@ -1 +0,0 @@
#undef HAVE_GETREGS_OLD

View File

@ -2,20 +2,12 @@ static int
arch_set_error(struct tcb *tcp)
{
i386_regs.eax = -tcp->u_error;
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, 4 * EAX, i386_regs.eax);
#else
return set_regs(tcp->pid);
#endif
}
static int
arch_set_success(struct tcb *tcp)
{
i386_regs.eax = tcp->u_rval;
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, 4 * EAX, i386_regs.eax);
#else
return set_regs(tcp->pid);
#endif
}

View File

@ -1,10 +1,6 @@
static int
arch_set_scno(struct tcb *tcp, kernel_ulong_t scno)
{
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, 4 * ORIG_EAX, scno);
#else
i386_regs.orig_eax = scno;
return set_regs(tcp->pid);
#endif
}

View File

@ -1,35 +0,0 @@
/*
* PTRACE_GETREGS was added to the PowerPC kernel in v2.6.23,
* we provide a slow fallback for old kernels.
*/
static int
getregs_old(pid_t pid)
{
int i;
long r;
if (iflag) {
r = upeek(pid, sizeof(long) * PT_NIP, &ppc_regs.nip);
if (r)
goto out;
}
#ifdef POWERPC64 /* else we never use it */
r = upeek(pid, sizeof(long) * PT_MSR, &ppc_regs.msr);
if (r)
goto out;
#endif
r = upeek(pid, sizeof(long) * PT_CCR, &ppc_regs.ccr);
if (r)
goto out;
r = upeek(pid, sizeof(long) * PT_ORIG_R3, &ppc_regs.orig_gpr3);
if (r)
goto out;
for (i = 0; i <= 8; i++) {
r = upeek(pid, sizeof(long) * (PT_R0 + i),
&ppc_regs.gpr[i]);
if (r)
goto out;
}
out:
return r;
}

View File

@ -1 +0,0 @@
#include "x86_64/getregs_old.h"

View File

@ -2,11 +2,7 @@ static int
arch_set_error(struct tcb *tcp)
{
ppc_regs.gpr[3] = tcp->u_error;
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, sizeof(long) * (PT_R0 + 3), ppc_regs.gpr[3]);
#else
return set_regs(tcp->pid);
#endif
}
static int
@ -14,10 +10,5 @@ arch_set_success(struct tcb *tcp)
{
ppc_regs.gpr[3] = tcp->u_rval;
ppc_regs.ccr &= ~0x10000000;
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, sizeof(long) * PT_CCR, ppc_regs.ccr) ||
upoke(tcp->pid, sizeof(long) * (PT_R0 + 3), ppc_regs.gpr[3]);
#else
return set_regs(tcp->pid);
#endif
}

View File

@ -1,10 +1,6 @@
static int
arch_set_scno(struct tcb *tcp, kernel_ulong_t scno)
{
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, sizeof(long) * PT_R0, scno);
#else
ppc_regs.gpr[0] = scno;
return set_regs(tcp->pid);
#endif
}

View File

@ -1 +0,0 @@
#include "powerpc/getregs_old.c"

View File

@ -1 +0,0 @@
#include "powerpc/getregs_old.h"

View File

@ -1,68 +0,0 @@
/*
* Copyright (c) 2013 Denys Vlasenko <vda.linux@googlemail.com>
* Copyright (c) 2013-2015 Dmitry V. Levin <ldv@altlinux.org>
* 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.
*/
/*
* PTRACE_GETREGSET was added to the kernel in v2.6.25,
* a PTRACE_GETREGS based fallback is provided for old kernels.
*/
static int
getregs_old(pid_t pid)
{
/* Use old method, with unreliable heuristical detection of 32-bitness. */
long r = ptrace(PTRACE_GETREGS, pid, NULL, &x86_64_regs);
if (r)
return r;
if (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; */
} else {
x86_io.iov_len = sizeof(x86_64_regs);
}
return 0;
}

View File

@ -1,2 +0,0 @@
#define HAVE_GETREGS_OLD
static int getregs_old(pid_t);

View File

@ -1,37 +1,25 @@
#ifndef HAVE_GETREGS_OLD
# define arch_set_error i386_set_error
# define arch_set_success i386_set_success
# include "i386/set_error.c"
# undef arch_set_success
# undef arch_set_error
#endif /* !HAVE_GETREGS_OLD */
#define arch_set_error i386_set_error
#define arch_set_success i386_set_success
#include "i386/set_error.c"
#undef arch_set_success
#undef arch_set_error
static int
arch_set_error(struct tcb *tcp)
{
#ifdef HAVE_GETREGS_OLD
x86_64_regs.rax = - (long long) tcp->u_error;
return upoke(tcp->pid, 8 * RAX, x86_64_regs.rax);
#else
if (x86_io.iov_len == sizeof(i386_regs))
return i386_set_error(tcp);
x86_64_regs.rax = - (long long) tcp->u_error;
return set_regs(tcp->pid);
#endif
}
static int
arch_set_success(struct tcb *tcp)
{
#ifdef HAVE_GETREGS_OLD
x86_64_regs.rax = (long long) tcp->u_rval;
return upoke(tcp->pid, 8 * RAX, x86_64_regs.rax);
#else
if (x86_io.iov_len == sizeof(i386_regs))
return i386_set_success(tcp);
x86_64_regs.rax = (long long) tcp->u_rval;
return set_regs(tcp->pid);
#endif
}

View File

@ -1,19 +1,13 @@
#ifndef HAVE_GETREGS_OLD
# define arch_set_scno i386_set_scno
# include "i386/set_scno.c"
# undef arch_set_scno
#endif /* !HAVE_GETREGS_OLD */
#define arch_set_scno i386_set_scno
#include "i386/set_scno.c"
#undef arch_set_scno
static int
arch_set_scno(struct tcb *tcp, kernel_ulong_t scno)
{
#ifdef HAVE_GETREGS_OLD
return upoke(tcp->pid, 8 * ORIG_RAX, scno);
#else
if (x86_io.iov_len == sizeof(i386_regs))
return i386_set_scno(tcp, scno);
x86_64_regs.orig_rax = scno;
return set_regs(tcp->pid);
#endif
}

View File

@ -1072,8 +1072,6 @@ print_pc(struct tcb *tcp)
(kernel_ulong_t) ARCH_PC_REG);
}
#include "getregs_old.h"
#undef ptrace_getregset_or_getregs
#undef ptrace_setregset_or_setregs
#ifdef ARCH_REGS_FOR_GETREGSET
@ -1098,25 +1096,23 @@ ptrace_getregset(pid_t pid)
# endif
}
# ifndef HAVE_GETREGS_OLD
# define ptrace_setregset_or_setregs ptrace_setregset
# define ptrace_setregset_or_setregs ptrace_setregset
static int
ptrace_setregset(pid_t pid)
{
# ifdef ARCH_IOVEC_FOR_GETREGSET
# ifdef ARCH_IOVEC_FOR_GETREGSET
/* variable iovec */
return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS,
&ARCH_IOVEC_FOR_GETREGSET);
# else
# else
/* constant iovec */
static struct iovec io = {
.iov_base = &ARCH_REGS_FOR_GETREGSET,
.iov_len = sizeof(ARCH_REGS_FOR_GETREGSET)
};
return ptrace(PTRACE_SETREGSET, pid, NT_PRSTATUS, &io);
# endif
# endif
}
# endif /* !HAVE_GETREGS_OLD */
#elif defined ARCH_REGS_FOR_GETREGS
@ -1132,19 +1128,17 @@ ptrace_getregs(pid_t pid)
# endif
}
# ifndef HAVE_GETREGS_OLD
# define ptrace_setregset_or_setregs ptrace_setregs
# define ptrace_setregset_or_setregs ptrace_setregs
static int
ptrace_setregs(pid_t pid)
{
# if defined SPARC || defined SPARC64
# if defined SPARC || defined SPARC64
/* SPARC systems have the meaning of data and addr reversed */
return ptrace(PTRACE_SETREGS, pid, (void *) &ARCH_REGS_FOR_GETREGS, 0);
# else
# else
return ptrace(PTRACE_SETREGS, pid, NULL, &ARCH_REGS_FOR_GETREGS);
# endif
# endif
}
# endif /* !HAVE_GETREGS_OLD */
#endif /* ARCH_REGS_FOR_GETREGSET || ARCH_REGS_FOR_GETREGS */
@ -1154,30 +1148,8 @@ get_regs(pid_t pid)
#undef USE_GET_SYSCALL_RESULT_REGS
#ifdef ptrace_getregset_or_getregs
# ifdef HAVE_GETREGS_OLD
/*
* Try PTRACE_GETREGSET/PTRACE_GETREGS first,
* fallback to getregs_old.
*/
static int use_getregs_old;
if (use_getregs_old < 0) {
get_regs_error = ptrace_getregset_or_getregs(pid);
return;
} else if (use_getregs_old == 0) {
get_regs_error = ptrace_getregset_or_getregs(pid);
if (get_regs_error >= 0) {
use_getregs_old = -1;
return;
}
if (errno == EPERM || errno == ESRCH)
return;
use_getregs_old = 1;
}
get_regs_error = getregs_old(pid);
# else /* !HAVE_GETREGS_OLD */
/* Assume that PTRACE_GETREGSET/PTRACE_GETREGS works. */
get_regs_error = ptrace_getregset_or_getregs(pid);
# endif /* !HAVE_GETREGS_OLD */
#else /* !ptrace_getregset_or_getregs */
@ -1282,9 +1254,6 @@ get_syscall_result(struct tcb *tcp)
#endif
#include "get_error.c"
#include "set_error.c"
#ifdef HAVE_GETREGS_OLD
# include "getregs_old.c"
#endif
const char *
syscall_name(kernel_ulong_t scno)