Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3bc24a1a authored by Paul Mundt's avatar Paul Mundt
Browse files

sh: Initial ELF FDPIC support.

This adds initial support for ELF FDPIC on MMU-less SH, as per version
0.2 of the ABI definition at:

	http://www.codesourcery.com/public/docs/sh-fdpic/sh-fdpic-abi.txt



Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent 9b14ec35
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -240,6 +240,29 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
		}
		break;
	}
#endif
#ifdef CONFIG_BINFMT_ELF_FDPIC
	case PTRACE_GETFDPIC: {
		unsigned long tmp = 0;

		switch (addr) {
		case PTRACE_GETFDPIC_EXEC:
			tmp = child->mm->context.exec_fdpic_loadmap;
			break;
		case PTRACE_GETFDPIC_INTERP:
			tmp = child->mm->context.interp_fdpic_loadmap;
			break;
		default:
			break;
		}

		ret = 0;
		if (put_user(tmp, (unsigned long *) data)) {
			ret = -EFAULT;
			break;
		}
		break;
	}
#endif
	default:
		ret = ptrace_request(child, request, addr, data);
+23 −2
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

struct fdpic_func_descriptor {
	unsigned long	text;
	unsigned long	GOT;
};

/*
 * Atomically swap in the new signal mask, and wait for a signal.
 */
@@ -378,6 +383,14 @@ static int setup_frame(int sig, struct k_sigaction *ka,
	regs->regs[4] = signal; /* Arg for signal handler */
	regs->regs[5] = 0;
	regs->regs[6] = (unsigned long) &frame->sc;

	if (current->personality & FDPIC_FUNCPTRS) {
		struct fdpic_func_descriptor __user *funcptr =
			(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;

		__get_user(regs->pc, &funcptr->text);
		__get_user(regs->regs[12], &funcptr->GOT);
	} else
		regs->pc = (unsigned long)ka->sa.sa_handler;

	set_fs(USER_DS);
@@ -458,6 +471,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	regs->regs[4] = signal; /* Arg for signal handler */
	regs->regs[5] = (unsigned long) &frame->info;
	regs->regs[6] = (unsigned long) &frame->uc;

	if (current->personality & FDPIC_FUNCPTRS) {
		struct fdpic_func_descriptor __user *funcptr =
			(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;

		__get_user(regs->pc, &funcptr->text);
		__get_user(regs->regs[12], &funcptr->GOT);
	} else
		regs->pc = (unsigned long)ka->sa.sa_handler;

	set_fs(USER_DS);
+1 −1
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ config COMPAT_BINFMT_ELF
config BINFMT_ELF_FDPIC
	bool "Kernel support for FDPIC ELF binaries"
	default y
	depends on (FRV || BLACKFIN)
	depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
	help
	  ELF FDPIC binaries are based on ELF, but allow the individual load
	  segments of a binary to be located in memory independently of each
+52 −1
Original line number Diff line number Diff line
#ifndef __ASM_SH_ELF_H
#define __ASM_SH_ELF_H

#include <linux/utsname.h>
#include <asm/auxvec.h>
#include <asm/ptrace.h>
#include <asm/user.h>

/* ELF header e_flags defines */
#define EF_SH_PIC		0x100	/* -fpic */
#define EF_SH_FDPIC		0x8000	/* -mfdpic */

/* SH (particularly SHcompact) relocation types  */
#define	R_SH_NONE		0
#define	R_SH_DIR32		1
@@ -43,6 +48,28 @@
#define	R_SH_RELATIVE		165
#define	R_SH_GOTOFF		166
#define	R_SH_GOTPC		167

/* FDPIC relocs */
#define R_SH_GOT20		70
#define R_SH_GOTOFF20		71
#define R_SH_GOTFUNCDESC	72
#define R_SH_GOTFUNCDESC20	73
#define R_SH_GOTOFFFUNCDESC	74
#define R_SH_GOTOFFFUNCDESC20	75
#define R_SH_FUNCDESC		76
#define R_SH_FUNCDESC_VALUE	77

#if 0 /* XXX - later .. */
#define R_SH_GOT20		198
#define R_SH_GOTOFF20		199
#define R_SH_GOTFUNCDESC	200
#define R_SH_GOTFUNCDESC20	201
#define R_SH_GOTOFFFUNCDESC	202
#define R_SH_GOTOFFFUNCDESC20	203
#define R_SH_FUNCDESC		204
#define R_SH_FUNCDESC_VALUE	205
#endif

/* SHmedia relocs */
#define R_SH_IMM_LOW16		246
#define R_SH_IMM_LOW16_PCREL	247
@@ -78,8 +105,11 @@ typedef struct user_fpu_struct elf_fpregset_t;
 * This is used to ensure we don't load something for the wrong architecture.
 */
#define elf_check_arch(x)		((x)->e_machine == EM_SH)
#define elf_check_fdpic(x)		((x)->e_flags & EF_SH_FDPIC)
#define elf_check_const_displacement(x)	((x)->e_flags & EF_SH_PIC)

#define USE_ELF_CORE_DUMP
#define ELF_FDPIC_CORE_EFLAGS	EF_SH_FDPIC
#define ELF_EXEC_PAGESIZE	PAGE_SIZE

/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
@@ -136,6 +166,27 @@ typedef struct user_fpu_struct elf_fpregset_t;
       _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
       _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; \
       _r->sr = SR_FD; } while (0)

#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr,	\
			    _dynamic_addr)				\
do {									\
	_r->regs[0]	= 0;						\
	_r->regs[1]	= 0;						\
	_r->regs[2]	= 0;						\
	_r->regs[3]	= 0;						\
	_r->regs[4]	= 0;						\
	_r->regs[5]	= 0;						\
	_r->regs[6]	= 0;						\
	_r->regs[7]	= 0;						\
	_r->regs[8]	= _exec_map_addr;				\
	_r->regs[9]	= _interp_map_addr;				\
	_r->regs[10]	= _dynamic_addr;				\
	_r->regs[11]	= 0;						\
	_r->regs[12]	= 0;						\
	_r->regs[13]	= 0;						\
	_r->regs[14]	= 0;						\
	_r->sr		= SR_FD;					\
} while (0)
#endif

#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
+4 −0
Original line number Diff line number Diff line
@@ -12,6 +12,10 @@ typedef struct {
	struct vm_list_struct	*vmlist;
	unsigned long		end_brk;
#endif
#ifdef CONFIG_BINFMT_ELF_FDPIC
	unsigned long		exec_fdpic_loadmap;
	unsigned long		interp_fdpic_loadmap;
#endif
} mm_context_t;

/*
Loading