aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2008-05-19 00:40:12 -0400
committerPaul Mundt <lethal@linux-sh.org>2008-07-28 05:10:28 -0400
commit3bc24a1a5441ef621daf737ec93b0a10e8999d59 (patch)
tree09e3e2e8eda617de72f643aa22ba86490b16cd17
parent9b14ec35f03d89c88cba225add8b6eca15203964 (diff)
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: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/kernel/ptrace_32.c23
-rw-r--r--arch/sh/kernel/signal_32.c25
-rw-r--r--fs/Kconfig.binfmt2
-rw-r--r--include/asm-sh/elf.h53
-rw-r--r--include/asm-sh/mmu.h4
-rw-r--r--include/asm-sh/ptrace.h5
6 files changed, 108 insertions, 4 deletions
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index fddb547f3c2b..2bc72def5cf8 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -241,6 +241,29 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
241 break; 241 break;
242 } 242 }
243#endif 243#endif
244#ifdef CONFIG_BINFMT_ELF_FDPIC
245 case PTRACE_GETFDPIC: {
246 unsigned long tmp = 0;
247
248 switch (addr) {
249 case PTRACE_GETFDPIC_EXEC:
250 tmp = child->mm->context.exec_fdpic_loadmap;
251 break;
252 case PTRACE_GETFDPIC_INTERP:
253 tmp = child->mm->context.interp_fdpic_loadmap;
254 break;
255 default:
256 break;
257 }
258
259 ret = 0;
260 if (put_user(tmp, (unsigned long *) data)) {
261 ret = -EFAULT;
262 break;
263 }
264 break;
265 }
266#endif
244 default: 267 default:
245 ret = ptrace_request(child, request, addr, data); 268 ret = ptrace_request(child, request, addr, data);
246 break; 269 break;
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index f311551d9a05..46170a9a7221 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -33,6 +33,11 @@
33 33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35 35
36struct fdpic_func_descriptor {
37 unsigned long text;
38 unsigned long GOT;
39};
40
36/* 41/*
37 * Atomically swap in the new signal mask, and wait for a signal. 42 * Atomically swap in the new signal mask, and wait for a signal.
38 */ 43 */
@@ -378,7 +383,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
378 regs->regs[4] = signal; /* Arg for signal handler */ 383 regs->regs[4] = signal; /* Arg for signal handler */
379 regs->regs[5] = 0; 384 regs->regs[5] = 0;
380 regs->regs[6] = (unsigned long) &frame->sc; 385 regs->regs[6] = (unsigned long) &frame->sc;
381 regs->pc = (unsigned long) ka->sa.sa_handler; 386
387 if (current->personality & FDPIC_FUNCPTRS) {
388 struct fdpic_func_descriptor __user *funcptr =
389 (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
390
391 __get_user(regs->pc, &funcptr->text);
392 __get_user(regs->regs[12], &funcptr->GOT);
393 } else
394 regs->pc = (unsigned long)ka->sa.sa_handler;
382 395
383 set_fs(USER_DS); 396 set_fs(USER_DS);
384 397
@@ -458,7 +471,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
458 regs->regs[4] = signal; /* Arg for signal handler */ 471 regs->regs[4] = signal; /* Arg for signal handler */
459 regs->regs[5] = (unsigned long) &frame->info; 472 regs->regs[5] = (unsigned long) &frame->info;
460 regs->regs[6] = (unsigned long) &frame->uc; 473 regs->regs[6] = (unsigned long) &frame->uc;
461 regs->pc = (unsigned long) ka->sa.sa_handler; 474
475 if (current->personality & FDPIC_FUNCPTRS) {
476 struct fdpic_func_descriptor __user *funcptr =
477 (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
478
479 __get_user(regs->pc, &funcptr->text);
480 __get_user(regs->regs[12], &funcptr->GOT);
481 } else
482 regs->pc = (unsigned long)ka->sa.sa_handler;
462 483
463 set_fs(USER_DS); 484 set_fs(USER_DS);
464 485
diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt
index 3263084eef9e..4a551af6f3fc 100644
--- a/fs/Kconfig.binfmt
+++ b/fs/Kconfig.binfmt
@@ -30,7 +30,7 @@ config COMPAT_BINFMT_ELF
30config BINFMT_ELF_FDPIC 30config BINFMT_ELF_FDPIC
31 bool "Kernel support for FDPIC ELF binaries" 31 bool "Kernel support for FDPIC ELF binaries"
32 default y 32 default y
33 depends on (FRV || BLACKFIN) 33 depends on (FRV || BLACKFIN || (SUPERH32 && !MMU))
34 help 34 help
35 ELF FDPIC binaries are based on ELF, but allow the individual load 35 ELF FDPIC binaries are based on ELF, but allow the individual load
36 segments of a binary to be located in memory independently of each 36 segments of a binary to be located in memory independently of each
diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h
index 05092da1aa59..f01449a8d378 100644
--- a/include/asm-sh/elf.h
+++ b/include/asm-sh/elf.h
@@ -1,10 +1,15 @@
1#ifndef __ASM_SH_ELF_H 1#ifndef __ASM_SH_ELF_H
2#define __ASM_SH_ELF_H 2#define __ASM_SH_ELF_H
3 3
4#include <linux/utsname.h>
4#include <asm/auxvec.h> 5#include <asm/auxvec.h>
5#include <asm/ptrace.h> 6#include <asm/ptrace.h>
6#include <asm/user.h> 7#include <asm/user.h>
7 8
9/* ELF header e_flags defines */
10#define EF_SH_PIC 0x100 /* -fpic */
11#define EF_SH_FDPIC 0x8000 /* -mfdpic */
12
8/* SH (particularly SHcompact) relocation types */ 13/* SH (particularly SHcompact) relocation types */
9#define R_SH_NONE 0 14#define R_SH_NONE 0
10#define R_SH_DIR32 1 15#define R_SH_DIR32 1
@@ -43,6 +48,28 @@
43#define R_SH_RELATIVE 165 48#define R_SH_RELATIVE 165
44#define R_SH_GOTOFF 166 49#define R_SH_GOTOFF 166
45#define R_SH_GOTPC 167 50#define R_SH_GOTPC 167
51
52/* FDPIC relocs */
53#define R_SH_GOT20 70
54#define R_SH_GOTOFF20 71
55#define R_SH_GOTFUNCDESC 72
56#define R_SH_GOTFUNCDESC20 73
57#define R_SH_GOTOFFFUNCDESC 74
58#define R_SH_GOTOFFFUNCDESC20 75
59#define R_SH_FUNCDESC 76
60#define R_SH_FUNCDESC_VALUE 77
61
62#if 0 /* XXX - later .. */
63#define R_SH_GOT20 198
64#define R_SH_GOTOFF20 199
65#define R_SH_GOTFUNCDESC 200
66#define R_SH_GOTFUNCDESC20 201
67#define R_SH_GOTOFFFUNCDESC 202
68#define R_SH_GOTOFFFUNCDESC20 203
69#define R_SH_FUNCDESC 204
70#define R_SH_FUNCDESC_VALUE 205
71#endif
72
46/* SHmedia relocs */ 73/* SHmedia relocs */
47#define R_SH_IMM_LOW16 246 74#define R_SH_IMM_LOW16 246
48#define R_SH_IMM_LOW16_PCREL 247 75#define R_SH_IMM_LOW16_PCREL 247
@@ -77,9 +104,12 @@ typedef struct user_fpu_struct elf_fpregset_t;
77/* 104/*
78 * This is used to ensure we don't load something for the wrong architecture. 105 * This is used to ensure we don't load something for the wrong architecture.
79 */ 106 */
80#define elf_check_arch(x) ( (x)->e_machine == EM_SH ) 107#define elf_check_arch(x) ((x)->e_machine == EM_SH)
108#define elf_check_fdpic(x) ((x)->e_flags & EF_SH_FDPIC)
109#define elf_check_const_displacement(x) ((x)->e_flags & EF_SH_PIC)
81 110
82#define USE_ELF_CORE_DUMP 111#define USE_ELF_CORE_DUMP
112#define ELF_FDPIC_CORE_EFLAGS EF_SH_FDPIC
83#define ELF_EXEC_PAGESIZE PAGE_SIZE 113#define ELF_EXEC_PAGESIZE PAGE_SIZE
84 114
85/* This is the location that an ET_DYN program is loaded if exec'ed. Typical 115/* 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;
136 _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \ 166 _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \
137 _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; \ 167 _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; \
138 _r->sr = SR_FD; } while (0) 168 _r->sr = SR_FD; } while (0)
169
170#define ELF_FDPIC_PLAT_INIT(_r, _exec_map_addr, _interp_map_addr, \
171 _dynamic_addr) \
172do { \
173 _r->regs[0] = 0; \
174 _r->regs[1] = 0; \
175 _r->regs[2] = 0; \
176 _r->regs[3] = 0; \
177 _r->regs[4] = 0; \
178 _r->regs[5] = 0; \
179 _r->regs[6] = 0; \
180 _r->regs[7] = 0; \
181 _r->regs[8] = _exec_map_addr; \
182 _r->regs[9] = _interp_map_addr; \
183 _r->regs[10] = _dynamic_addr; \
184 _r->regs[11] = 0; \
185 _r->regs[12] = 0; \
186 _r->regs[13] = 0; \
187 _r->regs[14] = 0; \
188 _r->sr = SR_FD; \
189} while (0)
139#endif 190#endif
140 191
141#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) 192#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT)
diff --git a/include/asm-sh/mmu.h b/include/asm-sh/mmu.h
index eb0358c097d0..fdcb93bc6d11 100644
--- a/include/asm-sh/mmu.h
+++ b/include/asm-sh/mmu.h
@@ -12,6 +12,10 @@ typedef struct {
12 struct vm_list_struct *vmlist; 12 struct vm_list_struct *vmlist;
13 unsigned long end_brk; 13 unsigned long end_brk;
14#endif 14#endif
15#ifdef CONFIG_BINFMT_ELF_FDPIC
16 unsigned long exec_fdpic_loadmap;
17 unsigned long interp_fdpic_loadmap;
18#endif
15} mm_context_t; 19} mm_context_t;
16 20
17/* 21/*
diff --git a/include/asm-sh/ptrace.h b/include/asm-sh/ptrace.h
index 7d36dc3bee69..643ab5a7cf3b 100644
--- a/include/asm-sh/ptrace.h
+++ b/include/asm-sh/ptrace.h
@@ -87,6 +87,11 @@ struct pt_dspregs {
87 unsigned long mod; 87 unsigned long mod;
88}; 88};
89 89
90#define PTRACE_GETFDPIC 31 /* get the ELF fdpic loadmap address */
91
92#define PTRACE_GETFDPIC_EXEC 0 /* [addr] request the executable loadmap */
93#define PTRACE_GETFDPIC_INTERP 1 /* [addr] request the interpreter loadmap */
94
90#define PTRACE_GETDSPREGS 55 95#define PTRACE_GETDSPREGS 55
91#define PTRACE_SETDSPREGS 56 96#define PTRACE_SETDSPREGS 56
92#endif 97#endif