parisc: Switch to generic COMPAT_BINFMT_ELF

Drop our own compat binfmt implementation in
arch/parisc/kernel/binfmt_elf32.c in favour of the generic
implementation with CONFIG_COMPAT_BINFMT_ELF.

While cleaning up the dependencies, I noticed that ELF_PLATFORM was strangely
defined: On a 32-bit kernel, it was defined to "PARISC", while when running in
compat mode on a 64-bit kernel it was defined to "PARISC32". Since it doesn't
seem to be used in glibc yet, it's now defined in both cases to "PARISC". In
any case, it can be distinguished because it's either a 32-bit or a 64-bit ELF
file.

Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
Helge Deller 2018-04-11 09:09:53 +02:00
parent 2a03bb9e7a
commit 71d577db01
4 changed files with 42 additions and 132 deletions

View File

@ -338,6 +338,7 @@ source "mm/Kconfig"
config COMPAT
def_bool y
depends on 64BIT
select COMPAT_BINFMT_ELF if BINFMT_ELF
config SYSVIPC_COMPAT
def_bool y

View File

@ -192,6 +192,12 @@ struct compat_shmid64_ds {
compat_ulong_t __unused6;
};
/*
* The type of struct elf_prstatus.pr_reg in compatible core dumps.
*/
#define COMPAT_ELF_NGREG 80
typedef compat_ulong_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
/*
* A pointer passed in from user mode. This should not
* be used for syscall parameters, just declare them

View File

@ -6,7 +6,7 @@
* ELF register definitions..
*/
#include <asm/ptrace.h>
#include <linux/types.h>
#define EM_PARISC 15
@ -169,16 +169,12 @@ typedef struct elf64_fdesc {
__u64 gp;
} Elf64_Fdesc;
#ifdef __KERNEL__
#ifdef CONFIG_64BIT
#define Elf_Fdesc Elf64_Fdesc
#else
#define Elf_Fdesc Elf32_Fdesc
#endif /*CONFIG_64BIT*/
#endif /*__KERNEL__*/
/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */
#define PT_HP_TLS (PT_LOOS + 0x0)
@ -212,45 +208,45 @@ typedef struct elf64_fdesc {
#define PF_HP_LAZYSWAP 0x04000000
#define PF_HP_SBP 0x08000000
/*
* This yields a string that ld.so will use to load implementation
* specific libraries for optimization. This is more specific in
* intent than poking at uname or /proc/cpuinfo.
*/
#define ELF_PLATFORM ("PARISC")
/*
* The following definitions are those for 32-bit ELF binaries on a 32-bit
* kernel and for 64-bit binaries on a 64-bit kernel. To run 32-bit binaries
* on a 64-bit kernel, arch/parisc/kernel/binfmt_elf32.c defines these
* macros appropriately and then #includes binfmt_elf.c, which then includes
* this file.
* on a 64-bit kernel, fs/compat_binfmt_elf.c defines ELF_CLASS and then
* #includes binfmt_elf.c, which then includes this file.
*/
#ifndef ELF_CLASS
/*
* This is used to ensure we don't load something for the wrong architecture.
*
* Note that this header file is used by default in fs/binfmt_elf.c. So
* the following macros are for the default case. However, for the 64
* bit kernel we also support 32 bit parisc binaries. To do that
* arch/parisc/kernel/binfmt_elf32.c defines its own set of these
* macros, and then it includes fs/binfmt_elf.c to provide an alternate
* elf binary handler for 32 bit binaries (on the 64 bit kernel).
*/
#ifdef CONFIG_64BIT
#define ELF_CLASS ELFCLASS64
#define ELF_CLASS ELFCLASS64
#else
#define ELF_CLASS ELFCLASS32
#endif
typedef unsigned long elf_greg_t;
/*
* This yields a string that ld.so will use to load implementation
* specific libraries for optimization. This is more specific in
* intent than poking at uname or /proc/cpuinfo.
*/
#define ELF_PLATFORM ("PARISC\0")
#define SET_PERSONALITY(ex) \
({ \
set_personality((current->personality & ~PER_MASK) | PER_LINUX); \
current->thread.map_base = DEFAULT_MAP_BASE; \
current->thread.task_size = DEFAULT_TASK_SIZE \
current->thread.task_size = DEFAULT_TASK_SIZE; \
})
#endif /* ! ELF_CLASS */
#define COMPAT_SET_PERSONALITY(ex) \
({ \
set_thread_flag(TIF_32BIT); \
current->thread.map_base = DEFAULT_MAP_BASE32; \
current->thread.task_size = DEFAULT_TASK_SIZE32; \
})
/*
* Fill in general registers in a core dump. This saves pretty
@ -277,10 +273,12 @@ typedef unsigned long elf_greg_t;
#define ELF_CORE_COPY_REGS(dst, pt) \
memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \
memcpy(dst + 0, pt->gr, 32 * sizeof(elf_greg_t)); \
memcpy(dst + 32, pt->sr, 8 * sizeof(elf_greg_t)); \
memcpy(dst + 40, pt->iaoq, 2 * sizeof(elf_greg_t)); \
memcpy(dst + 42, pt->iasq, 2 * sizeof(elf_greg_t)); \
{ int i; \
for (i = 0; i < 32; i++) dst[i] = pt->gr[i]; \
for (i = 0; i < 8; i++) dst[32 + i] = pt->sr[i]; \
} \
dst[40] = pt->iaoq[0]; dst[41] = pt->iaoq[1]; \
dst[42] = pt->iasq[0]; dst[43] = pt->iasq[1]; \
dst[44] = pt->sar; dst[45] = pt->iir; \
dst[46] = pt->isr; dst[47] = pt->ior; \
dst[48] = mfctl(22); dst[49] = mfctl(0); \
@ -292,7 +290,7 @@ typedef unsigned long elf_greg_t;
dst[60] = mfctl(12); dst[61] = mfctl(13); \
dst[62] = mfctl(10); dst[63] = mfctl(15);
#endif /* ! ELF_CLASS */
#define CORE_DUMP_USE_REGSET
#define ELF_NGREG 80 /* We only need 64 at present, but leave space
for expansion. */
@ -310,7 +308,10 @@ extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *);
struct pt_regs; /* forward declaration... */
#define elf_check_arch(x) ((x)->e_machine == EM_PARISC && (x)->e_ident[EI_CLASS] == ELF_CLASS)
#define elf_check_arch(x) \
((x)->e_machine == EM_PARISC && (x)->e_ident[EI_CLASS] == ELF_CLASS)
#define compat_elf_check_arch(x) \
((x)->e_machine == EM_PARISC && (x)->e_ident[EI_CLASS] == ELFCLASS32)
/*
* These are used to set parameters in the core dumps.

View File

@ -1,98 +0,0 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels
*
* Copyright (C) 2000 John Marvin
* Copyright (C) 2000 Hewlett Packard Co.
*
* Heavily inspired from various other efforts to do the same thing
* (ia64,sparc64/mips64)
*/
/* Make sure include/asm-parisc/elf.h does the right thing */
#define ELF_CLASS ELFCLASS32
#define ELF_CORE_COPY_REGS(dst, pt) \
memset(dst, 0, sizeof(dst)); /* don't leak any "random" bits */ \
{ int i; \
for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \
for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \
} \
dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \
dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \
dst[44] = (elf_greg_t) pt->sar; dst[45] = (elf_greg_t) pt->iir; \
dst[46] = (elf_greg_t) pt->isr; dst[47] = (elf_greg_t) pt->ior; \
dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \
dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \
dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \
dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \
dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \
dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \
dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \
dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15);
typedef unsigned int elf_greg_t;
#include <linux/spinlock.h>
#include <asm/processor.h>
#include <linux/module.h>
#include <linux/elfcore.h>
#include <linux/compat.h> /* struct compat_timeval */
#define elf_prstatus elf_prstatus32
struct elf_prstatus32
{
struct elf_siginfo pr_info; /* Info associated with signal */
short pr_cursig; /* Current signal */
unsigned int pr_sigpend; /* Set of pending signals */
unsigned int pr_sighold; /* Set of held signals */
pid_t pr_pid;
pid_t pr_ppid;
pid_t pr_pgrp;
pid_t pr_sid;
struct compat_timeval pr_utime; /* User time */
struct compat_timeval pr_stime; /* System time */
struct compat_timeval pr_cutime; /* Cumulative user time */
struct compat_timeval pr_cstime; /* Cumulative system time */
elf_gregset_t pr_reg; /* GP registers */
int pr_fpvalid; /* True if math co-processor being used. */
};
#define elf_prpsinfo elf_prpsinfo32
struct elf_prpsinfo32
{
char pr_state; /* numeric process state */
char pr_sname; /* char for pr_state */
char pr_zomb; /* zombie */
char pr_nice; /* nice val */
unsigned int pr_flag; /* flags */
u16 pr_uid;
u16 pr_gid;
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
/* Lots missing */
char pr_fname[16]; /* filename of executable */
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};
#define init_elf_binfmt init_elf32_binfmt
#define ELF_PLATFORM ("PARISC32\0")
/*
* We should probably use this macro to set a flag somewhere to indicate
* this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we
* could set a processor dependent flag in the thread_struct.
*/
#undef SET_PERSONALITY
#define SET_PERSONALITY(ex) \
set_thread_flag(TIF_32BIT); \
current->thread.map_base = DEFAULT_MAP_BASE32; \
current->thread.task_size = DEFAULT_TASK_SIZE32 \
#undef ns_to_timeval
#define ns_to_timeval ns_to_compat_timeval
#include "../../../fs/binfmt_elf.c"