Commit f9720205d1f847cb59e197e851b5276425363f6b
Committed by
Bryan Wu
1 parent
f778089cb2
Exists in
master
and in
7 other branches
Binfmt_flat: Add minimum support for the Blackfin relocations
Add minimum support for the Blackfin relocations, since we don't have enough space in each reloc. The idea is to store a value with one relocation so that subsequent ones can access it. Actually, this patch is required for Blackfin. Currently if BINFMT_FLAT is enabled, git-tree kernel will fail to compile. Signed-off-by: Bernd Schmidt <bernd.schmidt@analog.com> Signed-off-by: Bryan Wu <bryan.wu@analog.com> Cc: David McCullough <davidm@snapgear.com> Cc: Greg Ungerer <gerg@snapgear.com> Cc: Miles Bader <miles.bader@necel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Showing 6 changed files with 15 additions and 6 deletions Inline Diff
fs/binfmt_flat.c
1 | /****************************************************************************/ | 1 | /****************************************************************************/ |
2 | /* | 2 | /* |
3 | * linux/fs/binfmt_flat.c | 3 | * linux/fs/binfmt_flat.c |
4 | * | 4 | * |
5 | * Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com> | 5 | * Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com> |
6 | * Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com> | 6 | * Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com> |
7 | * Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com> | 7 | * Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com> |
8 | * Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com> | 8 | * Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com> |
9 | * based heavily on: | 9 | * based heavily on: |
10 | * | 10 | * |
11 | * linux/fs/binfmt_aout.c: | 11 | * linux/fs/binfmt_aout.c: |
12 | * Copyright (C) 1991, 1992, 1996 Linus Torvalds | 12 | * Copyright (C) 1991, 1992, 1996 Linus Torvalds |
13 | * linux/fs/binfmt_flat.c for 2.0 kernel | 13 | * linux/fs/binfmt_flat.c for 2.0 kernel |
14 | * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> | 14 | * Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com> |
15 | * JAN/99 -- coded full program relocation (gerg@snapgear.com) | 15 | * JAN/99 -- coded full program relocation (gerg@snapgear.com) |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/sched.h> | 20 | #include <linux/sched.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/mman.h> | 22 | #include <linux/mman.h> |
23 | #include <linux/a.out.h> | 23 | #include <linux/a.out.h> |
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/signal.h> | 25 | #include <linux/signal.h> |
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/file.h> | 28 | #include <linux/file.h> |
29 | #include <linux/stat.h> | 29 | #include <linux/stat.h> |
30 | #include <linux/fcntl.h> | 30 | #include <linux/fcntl.h> |
31 | #include <linux/ptrace.h> | 31 | #include <linux/ptrace.h> |
32 | #include <linux/user.h> | 32 | #include <linux/user.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/binfmts.h> | 34 | #include <linux/binfmts.h> |
35 | #include <linux/personality.h> | 35 | #include <linux/personality.h> |
36 | #include <linux/init.h> | 36 | #include <linux/init.h> |
37 | #include <linux/flat.h> | 37 | #include <linux/flat.h> |
38 | #include <linux/syscalls.h> | 38 | #include <linux/syscalls.h> |
39 | 39 | ||
40 | #include <asm/byteorder.h> | 40 | #include <asm/byteorder.h> |
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
44 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
45 | 45 | ||
46 | /****************************************************************************/ | 46 | /****************************************************************************/ |
47 | 47 | ||
48 | #if 0 | 48 | #if 0 |
49 | #define DEBUG 1 | 49 | #define DEBUG 1 |
50 | #endif | 50 | #endif |
51 | 51 | ||
52 | #ifdef DEBUG | 52 | #ifdef DEBUG |
53 | #define DBG_FLT(a...) printk(a) | 53 | #define DBG_FLT(a...) printk(a) |
54 | #else | 54 | #else |
55 | #define DBG_FLT(a...) | 55 | #define DBG_FLT(a...) |
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ | 58 | #define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */ |
59 | #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ | 59 | #define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */ |
60 | 60 | ||
61 | struct lib_info { | 61 | struct lib_info { |
62 | struct { | 62 | struct { |
63 | unsigned long start_code; /* Start of text segment */ | 63 | unsigned long start_code; /* Start of text segment */ |
64 | unsigned long start_data; /* Start of data segment */ | 64 | unsigned long start_data; /* Start of data segment */ |
65 | unsigned long start_brk; /* End of data segment */ | 65 | unsigned long start_brk; /* End of data segment */ |
66 | unsigned long text_len; /* Length of text segment */ | 66 | unsigned long text_len; /* Length of text segment */ |
67 | unsigned long entry; /* Start address for this module */ | 67 | unsigned long entry; /* Start address for this module */ |
68 | unsigned long build_date; /* When this one was compiled */ | 68 | unsigned long build_date; /* When this one was compiled */ |
69 | short loaded; /* Has this library been loaded? */ | 69 | short loaded; /* Has this library been loaded? */ |
70 | } lib_list[MAX_SHARED_LIBS]; | 70 | } lib_list[MAX_SHARED_LIBS]; |
71 | }; | 71 | }; |
72 | 72 | ||
73 | #ifdef CONFIG_BINFMT_SHARED_FLAT | 73 | #ifdef CONFIG_BINFMT_SHARED_FLAT |
74 | static int load_flat_shared_library(int id, struct lib_info *p); | 74 | static int load_flat_shared_library(int id, struct lib_info *p); |
75 | #endif | 75 | #endif |
76 | 76 | ||
77 | static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs); | 77 | static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs); |
78 | static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file); | 78 | static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file); |
79 | 79 | ||
80 | static struct linux_binfmt flat_format = { | 80 | static struct linux_binfmt flat_format = { |
81 | .module = THIS_MODULE, | 81 | .module = THIS_MODULE, |
82 | .load_binary = load_flat_binary, | 82 | .load_binary = load_flat_binary, |
83 | .core_dump = flat_core_dump, | 83 | .core_dump = flat_core_dump, |
84 | .min_coredump = PAGE_SIZE | 84 | .min_coredump = PAGE_SIZE |
85 | }; | 85 | }; |
86 | 86 | ||
87 | /****************************************************************************/ | 87 | /****************************************************************************/ |
88 | /* | 88 | /* |
89 | * Routine writes a core dump image in the current directory. | 89 | * Routine writes a core dump image in the current directory. |
90 | * Currently only a stub-function. | 90 | * Currently only a stub-function. |
91 | */ | 91 | */ |
92 | 92 | ||
93 | static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file) | 93 | static int flat_core_dump(long signr, struct pt_regs * regs, struct file *file) |
94 | { | 94 | { |
95 | printk("Process %s:%d received signr %d and should have core dumped\n", | 95 | printk("Process %s:%d received signr %d and should have core dumped\n", |
96 | current->comm, current->pid, (int) signr); | 96 | current->comm, current->pid, (int) signr); |
97 | return(1); | 97 | return(1); |
98 | } | 98 | } |
99 | 99 | ||
100 | /****************************************************************************/ | 100 | /****************************************************************************/ |
101 | /* | 101 | /* |
102 | * create_flat_tables() parses the env- and arg-strings in new user | 102 | * create_flat_tables() parses the env- and arg-strings in new user |
103 | * memory and creates the pointer tables from them, and puts their | 103 | * memory and creates the pointer tables from them, and puts their |
104 | * addresses on the "stack", returning the new stack pointer value. | 104 | * addresses on the "stack", returning the new stack pointer value. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | static unsigned long create_flat_tables( | 107 | static unsigned long create_flat_tables( |
108 | unsigned long pp, | 108 | unsigned long pp, |
109 | struct linux_binprm * bprm) | 109 | struct linux_binprm * bprm) |
110 | { | 110 | { |
111 | unsigned long *argv,*envp; | 111 | unsigned long *argv,*envp; |
112 | unsigned long * sp; | 112 | unsigned long * sp; |
113 | char * p = (char*)pp; | 113 | char * p = (char*)pp; |
114 | int argc = bprm->argc; | 114 | int argc = bprm->argc; |
115 | int envc = bprm->envc; | 115 | int envc = bprm->envc; |
116 | char dummy; | 116 | char dummy; |
117 | 117 | ||
118 | sp = (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p); | 118 | sp = (unsigned long *) ((-(unsigned long)sizeof(char *))&(unsigned long) p); |
119 | 119 | ||
120 | sp -= envc+1; | 120 | sp -= envc+1; |
121 | envp = sp; | 121 | envp = sp; |
122 | sp -= argc+1; | 122 | sp -= argc+1; |
123 | argv = sp; | 123 | argv = sp; |
124 | 124 | ||
125 | flat_stack_align(sp); | 125 | flat_stack_align(sp); |
126 | if (flat_argvp_envp_on_stack()) { | 126 | if (flat_argvp_envp_on_stack()) { |
127 | --sp; put_user((unsigned long) envp, sp); | 127 | --sp; put_user((unsigned long) envp, sp); |
128 | --sp; put_user((unsigned long) argv, sp); | 128 | --sp; put_user((unsigned long) argv, sp); |
129 | } | 129 | } |
130 | 130 | ||
131 | put_user(argc,--sp); | 131 | put_user(argc,--sp); |
132 | current->mm->arg_start = (unsigned long) p; | 132 | current->mm->arg_start = (unsigned long) p; |
133 | while (argc-->0) { | 133 | while (argc-->0) { |
134 | put_user((unsigned long) p, argv++); | 134 | put_user((unsigned long) p, argv++); |
135 | do { | 135 | do { |
136 | get_user(dummy, p); p++; | 136 | get_user(dummy, p); p++; |
137 | } while (dummy); | 137 | } while (dummy); |
138 | } | 138 | } |
139 | put_user((unsigned long) NULL, argv); | 139 | put_user((unsigned long) NULL, argv); |
140 | current->mm->arg_end = current->mm->env_start = (unsigned long) p; | 140 | current->mm->arg_end = current->mm->env_start = (unsigned long) p; |
141 | while (envc-->0) { | 141 | while (envc-->0) { |
142 | put_user((unsigned long)p, envp); envp++; | 142 | put_user((unsigned long)p, envp); envp++; |
143 | do { | 143 | do { |
144 | get_user(dummy, p); p++; | 144 | get_user(dummy, p); p++; |
145 | } while (dummy); | 145 | } while (dummy); |
146 | } | 146 | } |
147 | put_user((unsigned long) NULL, envp); | 147 | put_user((unsigned long) NULL, envp); |
148 | current->mm->env_end = (unsigned long) p; | 148 | current->mm->env_end = (unsigned long) p; |
149 | return (unsigned long)sp; | 149 | return (unsigned long)sp; |
150 | } | 150 | } |
151 | 151 | ||
152 | /****************************************************************************/ | 152 | /****************************************************************************/ |
153 | 153 | ||
154 | #ifdef CONFIG_BINFMT_ZFLAT | 154 | #ifdef CONFIG_BINFMT_ZFLAT |
155 | 155 | ||
156 | #include <linux/zlib.h> | 156 | #include <linux/zlib.h> |
157 | 157 | ||
158 | #define LBUFSIZE 4000 | 158 | #define LBUFSIZE 4000 |
159 | 159 | ||
160 | /* gzip flag byte */ | 160 | /* gzip flag byte */ |
161 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ | 161 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ |
162 | #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ | 162 | #define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ |
163 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ | 163 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ |
164 | #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ | 164 | #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ |
165 | #define COMMENT 0x10 /* bit 4 set: file comment present */ | 165 | #define COMMENT 0x10 /* bit 4 set: file comment present */ |
166 | #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ | 166 | #define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ |
167 | #define RESERVED 0xC0 /* bit 6,7: reserved */ | 167 | #define RESERVED 0xC0 /* bit 6,7: reserved */ |
168 | 168 | ||
169 | static int decompress_exec( | 169 | static int decompress_exec( |
170 | struct linux_binprm *bprm, | 170 | struct linux_binprm *bprm, |
171 | unsigned long offset, | 171 | unsigned long offset, |
172 | char *dst, | 172 | char *dst, |
173 | long len, | 173 | long len, |
174 | int fd) | 174 | int fd) |
175 | { | 175 | { |
176 | unsigned char *buf; | 176 | unsigned char *buf; |
177 | z_stream strm; | 177 | z_stream strm; |
178 | loff_t fpos; | 178 | loff_t fpos; |
179 | int ret, retval; | 179 | int ret, retval; |
180 | 180 | ||
181 | DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len); | 181 | DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len); |
182 | 182 | ||
183 | memset(&strm, 0, sizeof(strm)); | 183 | memset(&strm, 0, sizeof(strm)); |
184 | strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); | 184 | strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); |
185 | if (strm.workspace == NULL) { | 185 | if (strm.workspace == NULL) { |
186 | DBG_FLT("binfmt_flat: no memory for decompress workspace\n"); | 186 | DBG_FLT("binfmt_flat: no memory for decompress workspace\n"); |
187 | return -ENOMEM; | 187 | return -ENOMEM; |
188 | } | 188 | } |
189 | buf = kmalloc(LBUFSIZE, GFP_KERNEL); | 189 | buf = kmalloc(LBUFSIZE, GFP_KERNEL); |
190 | if (buf == NULL) { | 190 | if (buf == NULL) { |
191 | DBG_FLT("binfmt_flat: no memory for read buffer\n"); | 191 | DBG_FLT("binfmt_flat: no memory for read buffer\n"); |
192 | retval = -ENOMEM; | 192 | retval = -ENOMEM; |
193 | goto out_free; | 193 | goto out_free; |
194 | } | 194 | } |
195 | 195 | ||
196 | /* Read in first chunk of data and parse gzip header. */ | 196 | /* Read in first chunk of data and parse gzip header. */ |
197 | fpos = offset; | 197 | fpos = offset; |
198 | ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); | 198 | ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); |
199 | 199 | ||
200 | strm.next_in = buf; | 200 | strm.next_in = buf; |
201 | strm.avail_in = ret; | 201 | strm.avail_in = ret; |
202 | strm.total_in = 0; | 202 | strm.total_in = 0; |
203 | 203 | ||
204 | retval = -ENOEXEC; | 204 | retval = -ENOEXEC; |
205 | 205 | ||
206 | /* Check minimum size -- gzip header */ | 206 | /* Check minimum size -- gzip header */ |
207 | if (ret < 10) { | 207 | if (ret < 10) { |
208 | DBG_FLT("binfmt_flat: file too small?\n"); | 208 | DBG_FLT("binfmt_flat: file too small?\n"); |
209 | goto out_free_buf; | 209 | goto out_free_buf; |
210 | } | 210 | } |
211 | 211 | ||
212 | /* Check gzip magic number */ | 212 | /* Check gzip magic number */ |
213 | if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) { | 213 | if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) { |
214 | DBG_FLT("binfmt_flat: unknown compression magic?\n"); | 214 | DBG_FLT("binfmt_flat: unknown compression magic?\n"); |
215 | goto out_free_buf; | 215 | goto out_free_buf; |
216 | } | 216 | } |
217 | 217 | ||
218 | /* Check gzip method */ | 218 | /* Check gzip method */ |
219 | if (buf[2] != 8) { | 219 | if (buf[2] != 8) { |
220 | DBG_FLT("binfmt_flat: unknown compression method?\n"); | 220 | DBG_FLT("binfmt_flat: unknown compression method?\n"); |
221 | goto out_free_buf; | 221 | goto out_free_buf; |
222 | } | 222 | } |
223 | /* Check gzip flags */ | 223 | /* Check gzip flags */ |
224 | if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) || | 224 | if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) || |
225 | (buf[3] & RESERVED)) { | 225 | (buf[3] & RESERVED)) { |
226 | DBG_FLT("binfmt_flat: unknown flags?\n"); | 226 | DBG_FLT("binfmt_flat: unknown flags?\n"); |
227 | goto out_free_buf; | 227 | goto out_free_buf; |
228 | } | 228 | } |
229 | 229 | ||
230 | ret = 10; | 230 | ret = 10; |
231 | if (buf[3] & EXTRA_FIELD) { | 231 | if (buf[3] & EXTRA_FIELD) { |
232 | ret += 2 + buf[10] + (buf[11] << 8); | 232 | ret += 2 + buf[10] + (buf[11] << 8); |
233 | if (unlikely(LBUFSIZE == ret)) { | 233 | if (unlikely(LBUFSIZE == ret)) { |
234 | DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n"); | 234 | DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n"); |
235 | goto out_free_buf; | 235 | goto out_free_buf; |
236 | } | 236 | } |
237 | } | 237 | } |
238 | if (buf[3] & ORIG_NAME) { | 238 | if (buf[3] & ORIG_NAME) { |
239 | for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) | 239 | for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) |
240 | ; | 240 | ; |
241 | if (unlikely(LBUFSIZE == ret)) { | 241 | if (unlikely(LBUFSIZE == ret)) { |
242 | DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n"); | 242 | DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n"); |
243 | goto out_free_buf; | 243 | goto out_free_buf; |
244 | } | 244 | } |
245 | } | 245 | } |
246 | if (buf[3] & COMMENT) { | 246 | if (buf[3] & COMMENT) { |
247 | for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) | 247 | for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) |
248 | ; | 248 | ; |
249 | if (unlikely(LBUFSIZE == ret)) { | 249 | if (unlikely(LBUFSIZE == ret)) { |
250 | DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n"); | 250 | DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n"); |
251 | goto out_free_buf; | 251 | goto out_free_buf; |
252 | } | 252 | } |
253 | } | 253 | } |
254 | 254 | ||
255 | strm.next_in += ret; | 255 | strm.next_in += ret; |
256 | strm.avail_in -= ret; | 256 | strm.avail_in -= ret; |
257 | 257 | ||
258 | strm.next_out = dst; | 258 | strm.next_out = dst; |
259 | strm.avail_out = len; | 259 | strm.avail_out = len; |
260 | strm.total_out = 0; | 260 | strm.total_out = 0; |
261 | 261 | ||
262 | if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) { | 262 | if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) { |
263 | DBG_FLT("binfmt_flat: zlib init failed?\n"); | 263 | DBG_FLT("binfmt_flat: zlib init failed?\n"); |
264 | goto out_free_buf; | 264 | goto out_free_buf; |
265 | } | 265 | } |
266 | 266 | ||
267 | while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) { | 267 | while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) { |
268 | ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); | 268 | ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); |
269 | if (ret <= 0) | 269 | if (ret <= 0) |
270 | break; | 270 | break; |
271 | if (ret >= (unsigned long) -4096) | 271 | if (ret >= (unsigned long) -4096) |
272 | break; | 272 | break; |
273 | len -= ret; | 273 | len -= ret; |
274 | 274 | ||
275 | strm.next_in = buf; | 275 | strm.next_in = buf; |
276 | strm.avail_in = ret; | 276 | strm.avail_in = ret; |
277 | strm.total_in = 0; | 277 | strm.total_in = 0; |
278 | } | 278 | } |
279 | 279 | ||
280 | if (ret < 0) { | 280 | if (ret < 0) { |
281 | DBG_FLT("binfmt_flat: decompression failed (%d), %s\n", | 281 | DBG_FLT("binfmt_flat: decompression failed (%d), %s\n", |
282 | ret, strm.msg); | 282 | ret, strm.msg); |
283 | goto out_zlib; | 283 | goto out_zlib; |
284 | } | 284 | } |
285 | 285 | ||
286 | retval = 0; | 286 | retval = 0; |
287 | out_zlib: | 287 | out_zlib: |
288 | zlib_inflateEnd(&strm); | 288 | zlib_inflateEnd(&strm); |
289 | out_free_buf: | 289 | out_free_buf: |
290 | kfree(buf); | 290 | kfree(buf); |
291 | out_free: | 291 | out_free: |
292 | kfree(strm.workspace); | 292 | kfree(strm.workspace); |
293 | out: | 293 | out: |
294 | return retval; | 294 | return retval; |
295 | } | 295 | } |
296 | 296 | ||
297 | #endif /* CONFIG_BINFMT_ZFLAT */ | 297 | #endif /* CONFIG_BINFMT_ZFLAT */ |
298 | 298 | ||
299 | /****************************************************************************/ | 299 | /****************************************************************************/ |
300 | 300 | ||
301 | static unsigned long | 301 | static unsigned long |
302 | calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp) | 302 | calc_reloc(unsigned long r, struct lib_info *p, int curid, int internalp) |
303 | { | 303 | { |
304 | unsigned long addr; | 304 | unsigned long addr; |
305 | int id; | 305 | int id; |
306 | unsigned long start_brk; | 306 | unsigned long start_brk; |
307 | unsigned long start_data; | 307 | unsigned long start_data; |
308 | unsigned long text_len; | 308 | unsigned long text_len; |
309 | unsigned long start_code; | 309 | unsigned long start_code; |
310 | 310 | ||
311 | #ifdef CONFIG_BINFMT_SHARED_FLAT | 311 | #ifdef CONFIG_BINFMT_SHARED_FLAT |
312 | if (r == 0) | 312 | if (r == 0) |
313 | id = curid; /* Relocs of 0 are always self referring */ | 313 | id = curid; /* Relocs of 0 are always self referring */ |
314 | else { | 314 | else { |
315 | id = (r >> 24) & 0xff; /* Find ID for this reloc */ | 315 | id = (r >> 24) & 0xff; /* Find ID for this reloc */ |
316 | r &= 0x00ffffff; /* Trim ID off here */ | 316 | r &= 0x00ffffff; /* Trim ID off here */ |
317 | } | 317 | } |
318 | if (id >= MAX_SHARED_LIBS) { | 318 | if (id >= MAX_SHARED_LIBS) { |
319 | printk("BINFMT_FLAT: reference 0x%x to shared library %d", | 319 | printk("BINFMT_FLAT: reference 0x%x to shared library %d", |
320 | (unsigned) r, id); | 320 | (unsigned) r, id); |
321 | goto failed; | 321 | goto failed; |
322 | } | 322 | } |
323 | if (curid != id) { | 323 | if (curid != id) { |
324 | if (internalp) { | 324 | if (internalp) { |
325 | printk("BINFMT_FLAT: reloc address 0x%x not in same module " | 325 | printk("BINFMT_FLAT: reloc address 0x%x not in same module " |
326 | "(%d != %d)", (unsigned) r, curid, id); | 326 | "(%d != %d)", (unsigned) r, curid, id); |
327 | goto failed; | 327 | goto failed; |
328 | } else if ( ! p->lib_list[id].loaded && | 328 | } else if ( ! p->lib_list[id].loaded && |
329 | load_flat_shared_library(id, p) > (unsigned long) -4096) { | 329 | load_flat_shared_library(id, p) > (unsigned long) -4096) { |
330 | printk("BINFMT_FLAT: failed to load library %d", id); | 330 | printk("BINFMT_FLAT: failed to load library %d", id); |
331 | goto failed; | 331 | goto failed; |
332 | } | 332 | } |
333 | /* Check versioning information (i.e. time stamps) */ | 333 | /* Check versioning information (i.e. time stamps) */ |
334 | if (p->lib_list[id].build_date && p->lib_list[curid].build_date && | 334 | if (p->lib_list[id].build_date && p->lib_list[curid].build_date && |
335 | p->lib_list[curid].build_date < p->lib_list[id].build_date) { | 335 | p->lib_list[curid].build_date < p->lib_list[id].build_date) { |
336 | printk("BINFMT_FLAT: library %d is younger than %d", id, curid); | 336 | printk("BINFMT_FLAT: library %d is younger than %d", id, curid); |
337 | goto failed; | 337 | goto failed; |
338 | } | 338 | } |
339 | } | 339 | } |
340 | #else | 340 | #else |
341 | id = 0; | 341 | id = 0; |
342 | #endif | 342 | #endif |
343 | 343 | ||
344 | start_brk = p->lib_list[id].start_brk; | 344 | start_brk = p->lib_list[id].start_brk; |
345 | start_data = p->lib_list[id].start_data; | 345 | start_data = p->lib_list[id].start_data; |
346 | start_code = p->lib_list[id].start_code; | 346 | start_code = p->lib_list[id].start_code; |
347 | text_len = p->lib_list[id].text_len; | 347 | text_len = p->lib_list[id].text_len; |
348 | 348 | ||
349 | if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { | 349 | if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { |
350 | printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)", | 350 | printk("BINFMT_FLAT: reloc outside program 0x%x (0 - 0x%x/0x%x)", |
351 | (int) r,(int)(start_brk-start_code),(int)text_len); | 351 | (int) r,(int)(start_brk-start_code),(int)text_len); |
352 | goto failed; | 352 | goto failed; |
353 | } | 353 | } |
354 | 354 | ||
355 | if (r < text_len) /* In text segment */ | 355 | if (r < text_len) /* In text segment */ |
356 | addr = r + start_code; | 356 | addr = r + start_code; |
357 | else /* In data segment */ | 357 | else /* In data segment */ |
358 | addr = r - text_len + start_data; | 358 | addr = r - text_len + start_data; |
359 | 359 | ||
360 | /* Range checked already above so doing the range tests is redundant...*/ | 360 | /* Range checked already above so doing the range tests is redundant...*/ |
361 | return(addr); | 361 | return(addr); |
362 | 362 | ||
363 | failed: | 363 | failed: |
364 | printk(", killing %s!\n", current->comm); | 364 | printk(", killing %s!\n", current->comm); |
365 | send_sig(SIGSEGV, current, 0); | 365 | send_sig(SIGSEGV, current, 0); |
366 | 366 | ||
367 | return RELOC_FAILED; | 367 | return RELOC_FAILED; |
368 | } | 368 | } |
369 | 369 | ||
370 | /****************************************************************************/ | 370 | /****************************************************************************/ |
371 | 371 | ||
372 | void old_reloc(unsigned long rl) | 372 | void old_reloc(unsigned long rl) |
373 | { | 373 | { |
374 | #ifdef DEBUG | 374 | #ifdef DEBUG |
375 | char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" }; | 375 | char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" }; |
376 | #endif | 376 | #endif |
377 | flat_v2_reloc_t r; | 377 | flat_v2_reloc_t r; |
378 | unsigned long *ptr; | 378 | unsigned long *ptr; |
379 | 379 | ||
380 | r.value = rl; | 380 | r.value = rl; |
381 | #if defined(CONFIG_COLDFIRE) | 381 | #if defined(CONFIG_COLDFIRE) |
382 | ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset); | 382 | ptr = (unsigned long *) (current->mm->start_code + r.reloc.offset); |
383 | #else | 383 | #else |
384 | ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset); | 384 | ptr = (unsigned long *) (current->mm->start_data + r.reloc.offset); |
385 | #endif | 385 | #endif |
386 | 386 | ||
387 | #ifdef DEBUG | 387 | #ifdef DEBUG |
388 | printk("Relocation of variable at DATASEG+%x " | 388 | printk("Relocation of variable at DATASEG+%x " |
389 | "(address %p, currently %x) into segment %s\n", | 389 | "(address %p, currently %x) into segment %s\n", |
390 | r.reloc.offset, ptr, (int)*ptr, segment[r.reloc.type]); | 390 | r.reloc.offset, ptr, (int)*ptr, segment[r.reloc.type]); |
391 | #endif | 391 | #endif |
392 | 392 | ||
393 | switch (r.reloc.type) { | 393 | switch (r.reloc.type) { |
394 | case OLD_FLAT_RELOC_TYPE_TEXT: | 394 | case OLD_FLAT_RELOC_TYPE_TEXT: |
395 | *ptr += current->mm->start_code; | 395 | *ptr += current->mm->start_code; |
396 | break; | 396 | break; |
397 | case OLD_FLAT_RELOC_TYPE_DATA: | 397 | case OLD_FLAT_RELOC_TYPE_DATA: |
398 | *ptr += current->mm->start_data; | 398 | *ptr += current->mm->start_data; |
399 | break; | 399 | break; |
400 | case OLD_FLAT_RELOC_TYPE_BSS: | 400 | case OLD_FLAT_RELOC_TYPE_BSS: |
401 | *ptr += current->mm->end_data; | 401 | *ptr += current->mm->end_data; |
402 | break; | 402 | break; |
403 | default: | 403 | default: |
404 | printk("BINFMT_FLAT: Unknown relocation type=%x\n", r.reloc.type); | 404 | printk("BINFMT_FLAT: Unknown relocation type=%x\n", r.reloc.type); |
405 | break; | 405 | break; |
406 | } | 406 | } |
407 | 407 | ||
408 | #ifdef DEBUG | 408 | #ifdef DEBUG |
409 | printk("Relocation became %x\n", (int)*ptr); | 409 | printk("Relocation became %x\n", (int)*ptr); |
410 | #endif | 410 | #endif |
411 | } | 411 | } |
412 | 412 | ||
413 | /****************************************************************************/ | 413 | /****************************************************************************/ |
414 | 414 | ||
415 | static int load_flat_file(struct linux_binprm * bprm, | 415 | static int load_flat_file(struct linux_binprm * bprm, |
416 | struct lib_info *libinfo, int id, unsigned long *extra_stack) | 416 | struct lib_info *libinfo, int id, unsigned long *extra_stack) |
417 | { | 417 | { |
418 | struct flat_hdr * hdr; | 418 | struct flat_hdr * hdr; |
419 | unsigned long textpos = 0, datapos = 0, result; | 419 | unsigned long textpos = 0, datapos = 0, result; |
420 | unsigned long realdatastart = 0; | 420 | unsigned long realdatastart = 0; |
421 | unsigned long text_len, data_len, bss_len, stack_len, flags; | 421 | unsigned long text_len, data_len, bss_len, stack_len, flags; |
422 | unsigned long len, reallen, memp = 0; | 422 | unsigned long len, reallen, memp = 0; |
423 | unsigned long extra, rlim; | 423 | unsigned long extra, rlim; |
424 | unsigned long *reloc = 0, *rp; | 424 | unsigned long *reloc = 0, *rp; |
425 | struct inode *inode; | 425 | struct inode *inode; |
426 | int i, rev, relocs = 0; | 426 | int i, rev, relocs = 0; |
427 | loff_t fpos; | 427 | loff_t fpos; |
428 | unsigned long start_code, end_code; | 428 | unsigned long start_code, end_code; |
429 | int ret; | 429 | int ret; |
430 | 430 | ||
431 | hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ | 431 | hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ |
432 | inode = bprm->file->f_path.dentry->d_inode; | 432 | inode = bprm->file->f_path.dentry->d_inode; |
433 | 433 | ||
434 | text_len = ntohl(hdr->data_start); | 434 | text_len = ntohl(hdr->data_start); |
435 | data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start); | 435 | data_len = ntohl(hdr->data_end) - ntohl(hdr->data_start); |
436 | bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end); | 436 | bss_len = ntohl(hdr->bss_end) - ntohl(hdr->data_end); |
437 | stack_len = ntohl(hdr->stack_size); | 437 | stack_len = ntohl(hdr->stack_size); |
438 | if (extra_stack) { | 438 | if (extra_stack) { |
439 | stack_len += *extra_stack; | 439 | stack_len += *extra_stack; |
440 | *extra_stack = stack_len; | 440 | *extra_stack = stack_len; |
441 | } | 441 | } |
442 | relocs = ntohl(hdr->reloc_count); | 442 | relocs = ntohl(hdr->reloc_count); |
443 | flags = ntohl(hdr->flags); | 443 | flags = ntohl(hdr->flags); |
444 | rev = ntohl(hdr->rev); | 444 | rev = ntohl(hdr->rev); |
445 | 445 | ||
446 | if (strncmp(hdr->magic, "bFLT", 4)) { | 446 | if (strncmp(hdr->magic, "bFLT", 4)) { |
447 | /* | 447 | /* |
448 | * because a lot of people do not manage to produce good | 448 | * because a lot of people do not manage to produce good |
449 | * flat binaries, we leave this printk to help them realise | 449 | * flat binaries, we leave this printk to help them realise |
450 | * the problem. We only print the error if its not a script file | 450 | * the problem. We only print the error if its not a script file |
451 | */ | 451 | */ |
452 | if (strncmp(hdr->magic, "#!", 2)) | 452 | if (strncmp(hdr->magic, "#!", 2)) |
453 | printk("BINFMT_FLAT: bad header magic\n"); | 453 | printk("BINFMT_FLAT: bad header magic\n"); |
454 | ret = -ENOEXEC; | 454 | ret = -ENOEXEC; |
455 | goto err; | 455 | goto err; |
456 | } | 456 | } |
457 | 457 | ||
458 | if (flags & FLAT_FLAG_KTRACE) | 458 | if (flags & FLAT_FLAG_KTRACE) |
459 | printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename); | 459 | printk("BINFMT_FLAT: Loading file: %s\n", bprm->filename); |
460 | 460 | ||
461 | if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { | 461 | if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { |
462 | printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION); | 462 | printk("BINFMT_FLAT: bad flat file version 0x%x (supported 0x%x and 0x%x)\n", rev, FLAT_VERSION, OLD_FLAT_VERSION); |
463 | ret = -ENOEXEC; | 463 | ret = -ENOEXEC; |
464 | goto err; | 464 | goto err; |
465 | } | 465 | } |
466 | 466 | ||
467 | /* Don't allow old format executables to use shared libraries */ | 467 | /* Don't allow old format executables to use shared libraries */ |
468 | if (rev == OLD_FLAT_VERSION && id != 0) { | 468 | if (rev == OLD_FLAT_VERSION && id != 0) { |
469 | printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n", | 469 | printk("BINFMT_FLAT: shared libraries are not available before rev 0x%x\n", |
470 | (int) FLAT_VERSION); | 470 | (int) FLAT_VERSION); |
471 | ret = -ENOEXEC; | 471 | ret = -ENOEXEC; |
472 | goto err; | 472 | goto err; |
473 | } | 473 | } |
474 | 474 | ||
475 | /* | 475 | /* |
476 | * fix up the flags for the older format, there were all kinds | 476 | * fix up the flags for the older format, there were all kinds |
477 | * of endian hacks, this only works for the simple cases | 477 | * of endian hacks, this only works for the simple cases |
478 | */ | 478 | */ |
479 | if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags)) | 479 | if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags)) |
480 | flags = FLAT_FLAG_RAM; | 480 | flags = FLAT_FLAG_RAM; |
481 | 481 | ||
482 | #ifndef CONFIG_BINFMT_ZFLAT | 482 | #ifndef CONFIG_BINFMT_ZFLAT |
483 | if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { | 483 | if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { |
484 | printk("Support for ZFLAT executables is not enabled.\n"); | 484 | printk("Support for ZFLAT executables is not enabled.\n"); |
485 | ret = -ENOEXEC; | 485 | ret = -ENOEXEC; |
486 | goto err; | 486 | goto err; |
487 | } | 487 | } |
488 | #endif | 488 | #endif |
489 | 489 | ||
490 | /* | 490 | /* |
491 | * Check initial limits. This avoids letting people circumvent | 491 | * Check initial limits. This avoids letting people circumvent |
492 | * size limits imposed on them by creating programs with large | 492 | * size limits imposed on them by creating programs with large |
493 | * arrays in the data or bss. | 493 | * arrays in the data or bss. |
494 | */ | 494 | */ |
495 | rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; | 495 | rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; |
496 | if (rlim >= RLIM_INFINITY) | 496 | if (rlim >= RLIM_INFINITY) |
497 | rlim = ~0; | 497 | rlim = ~0; |
498 | if (data_len + bss_len > rlim) { | 498 | if (data_len + bss_len > rlim) { |
499 | ret = -ENOMEM; | 499 | ret = -ENOMEM; |
500 | goto err; | 500 | goto err; |
501 | } | 501 | } |
502 | 502 | ||
503 | /* Flush all traces of the currently running executable */ | 503 | /* Flush all traces of the currently running executable */ |
504 | if (id == 0) { | 504 | if (id == 0) { |
505 | result = flush_old_exec(bprm); | 505 | result = flush_old_exec(bprm); |
506 | if (result) { | 506 | if (result) { |
507 | ret = result; | 507 | ret = result; |
508 | goto err; | 508 | goto err; |
509 | } | 509 | } |
510 | 510 | ||
511 | /* OK, This is the point of no return */ | 511 | /* OK, This is the point of no return */ |
512 | set_personality(PER_LINUX_32BIT); | 512 | set_personality(PER_LINUX_32BIT); |
513 | } | 513 | } |
514 | 514 | ||
515 | /* | 515 | /* |
516 | * calculate the extra space we need to map in | 516 | * calculate the extra space we need to map in |
517 | */ | 517 | */ |
518 | extra = max(bss_len + stack_len, relocs * sizeof(unsigned long)); | 518 | extra = max(bss_len + stack_len, relocs * sizeof(unsigned long)); |
519 | 519 | ||
520 | /* | 520 | /* |
521 | * there are a couple of cases here, the separate code/data | 521 | * there are a couple of cases here, the separate code/data |
522 | * case, and then the fully copied to RAM case which lumps | 522 | * case, and then the fully copied to RAM case which lumps |
523 | * it all together. | 523 | * it all together. |
524 | */ | 524 | */ |
525 | if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) { | 525 | if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) { |
526 | /* | 526 | /* |
527 | * this should give us a ROM ptr, but if it doesn't we don't | 527 | * this should give us a ROM ptr, but if it doesn't we don't |
528 | * really care | 528 | * really care |
529 | */ | 529 | */ |
530 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); | 530 | DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); |
531 | 531 | ||
532 | down_write(¤t->mm->mmap_sem); | 532 | down_write(¤t->mm->mmap_sem); |
533 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0); | 533 | textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC, MAP_PRIVATE, 0); |
534 | up_write(¤t->mm->mmap_sem); | 534 | up_write(¤t->mm->mmap_sem); |
535 | if (!textpos || textpos >= (unsigned long) -4096) { | 535 | if (!textpos || textpos >= (unsigned long) -4096) { |
536 | if (!textpos) | 536 | if (!textpos) |
537 | textpos = (unsigned long) -ENOMEM; | 537 | textpos = (unsigned long) -ENOMEM; |
538 | printk("Unable to mmap process text, errno %d\n", (int)-textpos); | 538 | printk("Unable to mmap process text, errno %d\n", (int)-textpos); |
539 | ret = textpos; | 539 | ret = textpos; |
540 | goto err; | 540 | goto err; |
541 | } | 541 | } |
542 | 542 | ||
543 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | 543 | len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); |
544 | down_write(¤t->mm->mmap_sem); | 544 | down_write(¤t->mm->mmap_sem); |
545 | realdatastart = do_mmap(0, 0, len, | 545 | realdatastart = do_mmap(0, 0, len, |
546 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); | 546 | PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); |
547 | /* Remap to use all availabe slack region space */ | 547 | /* Remap to use all availabe slack region space */ |
548 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { | 548 | if (realdatastart && (realdatastart < (unsigned long)-4096)) { |
549 | reallen = ksize(realdatastart); | 549 | reallen = ksize(realdatastart); |
550 | if (reallen > len) { | 550 | if (reallen > len) { |
551 | realdatastart = do_mremap(realdatastart, len, | 551 | realdatastart = do_mremap(realdatastart, len, |
552 | reallen, MREMAP_FIXED, realdatastart); | 552 | reallen, MREMAP_FIXED, realdatastart); |
553 | } | 553 | } |
554 | } | 554 | } |
555 | up_write(¤t->mm->mmap_sem); | 555 | up_write(¤t->mm->mmap_sem); |
556 | 556 | ||
557 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { | 557 | if (realdatastart == 0 || realdatastart >= (unsigned long)-4096) { |
558 | if (!realdatastart) | 558 | if (!realdatastart) |
559 | realdatastart = (unsigned long) -ENOMEM; | 559 | realdatastart = (unsigned long) -ENOMEM; |
560 | printk("Unable to allocate RAM for process data, errno %d\n", | 560 | printk("Unable to allocate RAM for process data, errno %d\n", |
561 | (int)-realdatastart); | 561 | (int)-realdatastart); |
562 | do_munmap(current->mm, textpos, text_len); | 562 | do_munmap(current->mm, textpos, text_len); |
563 | ret = realdatastart; | 563 | ret = realdatastart; |
564 | goto err; | 564 | goto err; |
565 | } | 565 | } |
566 | datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); | 566 | datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); |
567 | 567 | ||
568 | DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", | 568 | DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", |
569 | (int)(data_len + bss_len + stack_len), (int)datapos); | 569 | (int)(data_len + bss_len + stack_len), (int)datapos); |
570 | 570 | ||
571 | fpos = ntohl(hdr->data_start); | 571 | fpos = ntohl(hdr->data_start); |
572 | #ifdef CONFIG_BINFMT_ZFLAT | 572 | #ifdef CONFIG_BINFMT_ZFLAT |
573 | if (flags & FLAT_FLAG_GZDATA) { | 573 | if (flags & FLAT_FLAG_GZDATA) { |
574 | result = decompress_exec(bprm, fpos, (char *) datapos, | 574 | result = decompress_exec(bprm, fpos, (char *) datapos, |
575 | data_len + (relocs * sizeof(unsigned long)), 0); | 575 | data_len + (relocs * sizeof(unsigned long)), 0); |
576 | } else | 576 | } else |
577 | #endif | 577 | #endif |
578 | { | 578 | { |
579 | result = bprm->file->f_op->read(bprm->file, (char *) datapos, | 579 | result = bprm->file->f_op->read(bprm->file, (char *) datapos, |
580 | data_len + (relocs * sizeof(unsigned long)), &fpos); | 580 | data_len + (relocs * sizeof(unsigned long)), &fpos); |
581 | } | 581 | } |
582 | if (result >= (unsigned long)-4096) { | 582 | if (result >= (unsigned long)-4096) { |
583 | printk("Unable to read data+bss, errno %d\n", (int)-result); | 583 | printk("Unable to read data+bss, errno %d\n", (int)-result); |
584 | do_munmap(current->mm, textpos, text_len); | 584 | do_munmap(current->mm, textpos, text_len); |
585 | do_munmap(current->mm, realdatastart, data_len + extra); | 585 | do_munmap(current->mm, realdatastart, data_len + extra); |
586 | ret = result; | 586 | ret = result; |
587 | goto err; | 587 | goto err; |
588 | } | 588 | } |
589 | 589 | ||
590 | reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); | 590 | reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); |
591 | memp = realdatastart; | 591 | memp = realdatastart; |
592 | 592 | ||
593 | } else { | 593 | } else { |
594 | 594 | ||
595 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); | 595 | len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); |
596 | down_write(¤t->mm->mmap_sem); | 596 | down_write(¤t->mm->mmap_sem); |
597 | textpos = do_mmap(0, 0, len, | 597 | textpos = do_mmap(0, 0, len, |
598 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); | 598 | PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); |
599 | /* Remap to use all availabe slack region space */ | 599 | /* Remap to use all availabe slack region space */ |
600 | if (textpos && (textpos < (unsigned long) -4096)) { | 600 | if (textpos && (textpos < (unsigned long) -4096)) { |
601 | reallen = ksize(textpos); | 601 | reallen = ksize(textpos); |
602 | if (reallen > len) { | 602 | if (reallen > len) { |
603 | textpos = do_mremap(textpos, len, reallen, | 603 | textpos = do_mremap(textpos, len, reallen, |
604 | MREMAP_FIXED, textpos); | 604 | MREMAP_FIXED, textpos); |
605 | } | 605 | } |
606 | } | 606 | } |
607 | up_write(¤t->mm->mmap_sem); | 607 | up_write(¤t->mm->mmap_sem); |
608 | 608 | ||
609 | if (!textpos || textpos >= (unsigned long) -4096) { | 609 | if (!textpos || textpos >= (unsigned long) -4096) { |
610 | if (!textpos) | 610 | if (!textpos) |
611 | textpos = (unsigned long) -ENOMEM; | 611 | textpos = (unsigned long) -ENOMEM; |
612 | printk("Unable to allocate RAM for process text/data, errno %d\n", | 612 | printk("Unable to allocate RAM for process text/data, errno %d\n", |
613 | (int)-textpos); | 613 | (int)-textpos); |
614 | ret = textpos; | 614 | ret = textpos; |
615 | goto err; | 615 | goto err; |
616 | } | 616 | } |
617 | 617 | ||
618 | realdatastart = textpos + ntohl(hdr->data_start); | 618 | realdatastart = textpos + ntohl(hdr->data_start); |
619 | datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); | 619 | datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); |
620 | reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) + | 620 | reloc = (unsigned long *) (textpos + ntohl(hdr->reloc_start) + |
621 | MAX_SHARED_LIBS * sizeof(unsigned long)); | 621 | MAX_SHARED_LIBS * sizeof(unsigned long)); |
622 | memp = textpos; | 622 | memp = textpos; |
623 | 623 | ||
624 | #ifdef CONFIG_BINFMT_ZFLAT | 624 | #ifdef CONFIG_BINFMT_ZFLAT |
625 | /* | 625 | /* |
626 | * load it all in and treat it like a RAM load from now on | 626 | * load it all in and treat it like a RAM load from now on |
627 | */ | 627 | */ |
628 | if (flags & FLAT_FLAG_GZIP) { | 628 | if (flags & FLAT_FLAG_GZIP) { |
629 | result = decompress_exec(bprm, sizeof (struct flat_hdr), | 629 | result = decompress_exec(bprm, sizeof (struct flat_hdr), |
630 | (((char *) textpos) + sizeof (struct flat_hdr)), | 630 | (((char *) textpos) + sizeof (struct flat_hdr)), |
631 | (text_len + data_len + (relocs * sizeof(unsigned long)) | 631 | (text_len + data_len + (relocs * sizeof(unsigned long)) |
632 | - sizeof (struct flat_hdr)), | 632 | - sizeof (struct flat_hdr)), |
633 | 0); | 633 | 0); |
634 | memmove((void *) datapos, (void *) realdatastart, | 634 | memmove((void *) datapos, (void *) realdatastart, |
635 | data_len + (relocs * sizeof(unsigned long))); | 635 | data_len + (relocs * sizeof(unsigned long))); |
636 | } else if (flags & FLAT_FLAG_GZDATA) { | 636 | } else if (flags & FLAT_FLAG_GZDATA) { |
637 | fpos = 0; | 637 | fpos = 0; |
638 | result = bprm->file->f_op->read(bprm->file, | 638 | result = bprm->file->f_op->read(bprm->file, |
639 | (char *) textpos, text_len, &fpos); | 639 | (char *) textpos, text_len, &fpos); |
640 | if (result < (unsigned long) -4096) | 640 | if (result < (unsigned long) -4096) |
641 | result = decompress_exec(bprm, text_len, (char *) datapos, | 641 | result = decompress_exec(bprm, text_len, (char *) datapos, |
642 | data_len + (relocs * sizeof(unsigned long)), 0); | 642 | data_len + (relocs * sizeof(unsigned long)), 0); |
643 | } | 643 | } |
644 | else | 644 | else |
645 | #endif | 645 | #endif |
646 | { | 646 | { |
647 | fpos = 0; | 647 | fpos = 0; |
648 | result = bprm->file->f_op->read(bprm->file, | 648 | result = bprm->file->f_op->read(bprm->file, |
649 | (char *) textpos, text_len, &fpos); | 649 | (char *) textpos, text_len, &fpos); |
650 | if (result < (unsigned long) -4096) { | 650 | if (result < (unsigned long) -4096) { |
651 | fpos = ntohl(hdr->data_start); | 651 | fpos = ntohl(hdr->data_start); |
652 | result = bprm->file->f_op->read(bprm->file, (char *) datapos, | 652 | result = bprm->file->f_op->read(bprm->file, (char *) datapos, |
653 | data_len + (relocs * sizeof(unsigned long)), &fpos); | 653 | data_len + (relocs * sizeof(unsigned long)), &fpos); |
654 | } | 654 | } |
655 | } | 655 | } |
656 | if (result >= (unsigned long)-4096) { | 656 | if (result >= (unsigned long)-4096) { |
657 | printk("Unable to read code+data+bss, errno %d\n",(int)-result); | 657 | printk("Unable to read code+data+bss, errno %d\n",(int)-result); |
658 | do_munmap(current->mm, textpos, text_len + data_len + extra + | 658 | do_munmap(current->mm, textpos, text_len + data_len + extra + |
659 | MAX_SHARED_LIBS * sizeof(unsigned long)); | 659 | MAX_SHARED_LIBS * sizeof(unsigned long)); |
660 | ret = result; | 660 | ret = result; |
661 | goto err; | 661 | goto err; |
662 | } | 662 | } |
663 | } | 663 | } |
664 | 664 | ||
665 | if (flags & FLAT_FLAG_KTRACE) | 665 | if (flags & FLAT_FLAG_KTRACE) |
666 | printk("Mapping is %x, Entry point is %x, data_start is %x\n", | 666 | printk("Mapping is %x, Entry point is %x, data_start is %x\n", |
667 | (int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start)); | 667 | (int)textpos, 0x00ffffff&ntohl(hdr->entry), ntohl(hdr->data_start)); |
668 | 668 | ||
669 | /* The main program needs a little extra setup in the task structure */ | 669 | /* The main program needs a little extra setup in the task structure */ |
670 | start_code = textpos + sizeof (struct flat_hdr); | 670 | start_code = textpos + sizeof (struct flat_hdr); |
671 | end_code = textpos + text_len; | 671 | end_code = textpos + text_len; |
672 | if (id == 0) { | 672 | if (id == 0) { |
673 | current->mm->start_code = start_code; | 673 | current->mm->start_code = start_code; |
674 | current->mm->end_code = end_code; | 674 | current->mm->end_code = end_code; |
675 | current->mm->start_data = datapos; | 675 | current->mm->start_data = datapos; |
676 | current->mm->end_data = datapos + data_len; | 676 | current->mm->end_data = datapos + data_len; |
677 | /* | 677 | /* |
678 | * set up the brk stuff, uses any slack left in data/bss/stack | 678 | * set up the brk stuff, uses any slack left in data/bss/stack |
679 | * allocation. We put the brk after the bss (between the bss | 679 | * allocation. We put the brk after the bss (between the bss |
680 | * and stack) like other platforms. | 680 | * and stack) like other platforms. |
681 | */ | 681 | */ |
682 | current->mm->start_brk = datapos + data_len + bss_len; | 682 | current->mm->start_brk = datapos + data_len + bss_len; |
683 | current->mm->brk = (current->mm->start_brk + 3) & ~3; | 683 | current->mm->brk = (current->mm->start_brk + 3) & ~3; |
684 | current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len; | 684 | current->mm->context.end_brk = memp + ksize((void *) memp) - stack_len; |
685 | } | 685 | } |
686 | 686 | ||
687 | if (flags & FLAT_FLAG_KTRACE) | 687 | if (flags & FLAT_FLAG_KTRACE) |
688 | printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n", | 688 | printk("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n", |
689 | id ? "Lib" : "Load", bprm->filename, | 689 | id ? "Lib" : "Load", bprm->filename, |
690 | (int) start_code, (int) end_code, | 690 | (int) start_code, (int) end_code, |
691 | (int) datapos, | 691 | (int) datapos, |
692 | (int) (datapos + data_len), | 692 | (int) (datapos + data_len), |
693 | (int) (datapos + data_len), | 693 | (int) (datapos + data_len), |
694 | (int) (((datapos + data_len + bss_len) + 3) & ~3)); | 694 | (int) (((datapos + data_len + bss_len) + 3) & ~3)); |
695 | 695 | ||
696 | text_len -= sizeof(struct flat_hdr); /* the real code len */ | 696 | text_len -= sizeof(struct flat_hdr); /* the real code len */ |
697 | 697 | ||
698 | /* Store the current module values into the global library structure */ | 698 | /* Store the current module values into the global library structure */ |
699 | libinfo->lib_list[id].start_code = start_code; | 699 | libinfo->lib_list[id].start_code = start_code; |
700 | libinfo->lib_list[id].start_data = datapos; | 700 | libinfo->lib_list[id].start_data = datapos; |
701 | libinfo->lib_list[id].start_brk = datapos + data_len + bss_len; | 701 | libinfo->lib_list[id].start_brk = datapos + data_len + bss_len; |
702 | libinfo->lib_list[id].text_len = text_len; | 702 | libinfo->lib_list[id].text_len = text_len; |
703 | libinfo->lib_list[id].loaded = 1; | 703 | libinfo->lib_list[id].loaded = 1; |
704 | libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos; | 704 | libinfo->lib_list[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos; |
705 | libinfo->lib_list[id].build_date = ntohl(hdr->build_date); | 705 | libinfo->lib_list[id].build_date = ntohl(hdr->build_date); |
706 | 706 | ||
707 | /* | 707 | /* |
708 | * We just load the allocations into some temporary memory to | 708 | * We just load the allocations into some temporary memory to |
709 | * help simplify all this mumbo jumbo | 709 | * help simplify all this mumbo jumbo |
710 | * | 710 | * |
711 | * We've got two different sections of relocation entries. | 711 | * We've got two different sections of relocation entries. |
712 | * The first is the GOT which resides at the begining of the data segment | 712 | * The first is the GOT which resides at the begining of the data segment |
713 | * and is terminated with a -1. This one can be relocated in place. | 713 | * and is terminated with a -1. This one can be relocated in place. |
714 | * The second is the extra relocation entries tacked after the image's | 714 | * The second is the extra relocation entries tacked after the image's |
715 | * data segment. These require a little more processing as the entry is | 715 | * data segment. These require a little more processing as the entry is |
716 | * really an offset into the image which contains an offset into the | 716 | * really an offset into the image which contains an offset into the |
717 | * image. | 717 | * image. |
718 | */ | 718 | */ |
719 | if (flags & FLAT_FLAG_GOTPIC) { | 719 | if (flags & FLAT_FLAG_GOTPIC) { |
720 | for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) { | 720 | for (rp = (unsigned long *)datapos; *rp != 0xffffffff; rp++) { |
721 | unsigned long addr; | 721 | unsigned long addr; |
722 | if (*rp) { | 722 | if (*rp) { |
723 | addr = calc_reloc(*rp, libinfo, id, 0); | 723 | addr = calc_reloc(*rp, libinfo, id, 0); |
724 | if (addr == RELOC_FAILED) { | 724 | if (addr == RELOC_FAILED) { |
725 | ret = -ENOEXEC; | 725 | ret = -ENOEXEC; |
726 | goto err; | 726 | goto err; |
727 | } | 727 | } |
728 | *rp = addr; | 728 | *rp = addr; |
729 | } | 729 | } |
730 | } | 730 | } |
731 | } | 731 | } |
732 | 732 | ||
733 | /* | 733 | /* |
734 | * Now run through the relocation entries. | 734 | * Now run through the relocation entries. |
735 | * We've got to be careful here as C++ produces relocatable zero | 735 | * We've got to be careful here as C++ produces relocatable zero |
736 | * entries in the constructor and destructor tables which are then | 736 | * entries in the constructor and destructor tables which are then |
737 | * tested for being not zero (which will always occur unless we're | 737 | * tested for being not zero (which will always occur unless we're |
738 | * based from address zero). This causes an endless loop as __start | 738 | * based from address zero). This causes an endless loop as __start |
739 | * is at zero. The solution used is to not relocate zero addresses. | 739 | * is at zero. The solution used is to not relocate zero addresses. |
740 | * This has the negative side effect of not allowing a global data | 740 | * This has the negative side effect of not allowing a global data |
741 | * reference to be statically initialised to _stext (I've moved | 741 | * reference to be statically initialised to _stext (I've moved |
742 | * __start to address 4 so that is okay). | 742 | * __start to address 4 so that is okay). |
743 | */ | 743 | */ |
744 | if (rev > OLD_FLAT_VERSION) { | 744 | if (rev > OLD_FLAT_VERSION) { |
745 | unsigned long persistent = 0; | ||
745 | for (i=0; i < relocs; i++) { | 746 | for (i=0; i < relocs; i++) { |
746 | unsigned long addr, relval; | 747 | unsigned long addr, relval; |
747 | 748 | ||
748 | /* Get the address of the pointer to be | 749 | /* Get the address of the pointer to be |
749 | relocated (of course, the address has to be | 750 | relocated (of course, the address has to be |
750 | relocated first). */ | 751 | relocated first). */ |
751 | relval = ntohl(reloc[i]); | 752 | relval = ntohl(reloc[i]); |
753 | if (flat_set_persistent (relval, &persistent)) | ||
754 | continue; | ||
752 | addr = flat_get_relocate_addr(relval); | 755 | addr = flat_get_relocate_addr(relval); |
753 | rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); | 756 | rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); |
754 | if (rp == (unsigned long *)RELOC_FAILED) { | 757 | if (rp == (unsigned long *)RELOC_FAILED) { |
755 | ret = -ENOEXEC; | 758 | ret = -ENOEXEC; |
756 | goto err; | 759 | goto err; |
757 | } | 760 | } |
758 | 761 | ||
759 | /* Get the pointer's value. */ | 762 | /* Get the pointer's value. */ |
760 | addr = flat_get_addr_from_rp(rp, relval, flags); | 763 | addr = flat_get_addr_from_rp(rp, relval, flags, &persistent); |
761 | if (addr != 0) { | 764 | if (addr != 0) { |
762 | /* | 765 | /* |
763 | * Do the relocation. PIC relocs in the data section are | 766 | * Do the relocation. PIC relocs in the data section are |
764 | * already in target order | 767 | * already in target order |
765 | */ | 768 | */ |
766 | if ((flags & FLAT_FLAG_GOTPIC) == 0) | 769 | if ((flags & FLAT_FLAG_GOTPIC) == 0) |
767 | addr = ntohl(addr); | 770 | addr = ntohl(addr); |
768 | addr = calc_reloc(addr, libinfo, id, 0); | 771 | addr = calc_reloc(addr, libinfo, id, 0); |
769 | if (addr == RELOC_FAILED) { | 772 | if (addr == RELOC_FAILED) { |
770 | ret = -ENOEXEC; | 773 | ret = -ENOEXEC; |
771 | goto err; | 774 | goto err; |
772 | } | 775 | } |
773 | 776 | ||
774 | /* Write back the relocated pointer. */ | 777 | /* Write back the relocated pointer. */ |
775 | flat_put_addr_at_rp(rp, addr, relval); | 778 | flat_put_addr_at_rp(rp, addr, relval); |
776 | } | 779 | } |
777 | } | 780 | } |
778 | } else { | 781 | } else { |
779 | for (i=0; i < relocs; i++) | 782 | for (i=0; i < relocs; i++) |
780 | old_reloc(ntohl(reloc[i])); | 783 | old_reloc(ntohl(reloc[i])); |
781 | } | 784 | } |
782 | 785 | ||
783 | flush_icache_range(start_code, end_code); | 786 | flush_icache_range(start_code, end_code); |
784 | 787 | ||
785 | /* zero the BSS, BRK and stack areas */ | 788 | /* zero the BSS, BRK and stack areas */ |
786 | memset((void*)(datapos + data_len), 0, bss_len + | 789 | memset((void*)(datapos + data_len), 0, bss_len + |
787 | (memp + ksize((void *) memp) - stack_len - /* end brk */ | 790 | (memp + ksize((void *) memp) - stack_len - /* end brk */ |
788 | libinfo->lib_list[id].start_brk) + /* start brk */ | 791 | libinfo->lib_list[id].start_brk) + /* start brk */ |
789 | stack_len); | 792 | stack_len); |
790 | 793 | ||
791 | return 0; | 794 | return 0; |
792 | err: | 795 | err: |
793 | return ret; | 796 | return ret; |
794 | } | 797 | } |
795 | 798 | ||
796 | 799 | ||
797 | /****************************************************************************/ | 800 | /****************************************************************************/ |
798 | #ifdef CONFIG_BINFMT_SHARED_FLAT | 801 | #ifdef CONFIG_BINFMT_SHARED_FLAT |
799 | 802 | ||
800 | /* | 803 | /* |
801 | * Load a shared library into memory. The library gets its own data | 804 | * Load a shared library into memory. The library gets its own data |
802 | * segment (including bss) but not argv/argc/environ. | 805 | * segment (including bss) but not argv/argc/environ. |
803 | */ | 806 | */ |
804 | 807 | ||
805 | static int load_flat_shared_library(int id, struct lib_info *libs) | 808 | static int load_flat_shared_library(int id, struct lib_info *libs) |
806 | { | 809 | { |
807 | struct linux_binprm bprm; | 810 | struct linux_binprm bprm; |
808 | int res; | 811 | int res; |
809 | char buf[16]; | 812 | char buf[16]; |
810 | 813 | ||
811 | /* Create the file name */ | 814 | /* Create the file name */ |
812 | sprintf(buf, "/lib/lib%d.so", id); | 815 | sprintf(buf, "/lib/lib%d.so", id); |
813 | 816 | ||
814 | /* Open the file up */ | 817 | /* Open the file up */ |
815 | bprm.filename = buf; | 818 | bprm.filename = buf; |
816 | bprm.file = open_exec(bprm.filename); | 819 | bprm.file = open_exec(bprm.filename); |
817 | res = PTR_ERR(bprm.file); | 820 | res = PTR_ERR(bprm.file); |
818 | if (IS_ERR(bprm.file)) | 821 | if (IS_ERR(bprm.file)) |
819 | return res; | 822 | return res; |
820 | 823 | ||
821 | res = prepare_binprm(&bprm); | 824 | res = prepare_binprm(&bprm); |
822 | 825 | ||
823 | if (res <= (unsigned long)-4096) | 826 | if (res <= (unsigned long)-4096) |
824 | res = load_flat_file(&bprm, libs, id, NULL); | 827 | res = load_flat_file(&bprm, libs, id, NULL); |
825 | if (bprm.file) { | 828 | if (bprm.file) { |
826 | allow_write_access(bprm.file); | 829 | allow_write_access(bprm.file); |
827 | fput(bprm.file); | 830 | fput(bprm.file); |
828 | bprm.file = NULL; | 831 | bprm.file = NULL; |
829 | } | 832 | } |
830 | return(res); | 833 | return(res); |
831 | } | 834 | } |
832 | 835 | ||
833 | #endif /* CONFIG_BINFMT_SHARED_FLAT */ | 836 | #endif /* CONFIG_BINFMT_SHARED_FLAT */ |
834 | /****************************************************************************/ | 837 | /****************************************************************************/ |
835 | 838 | ||
836 | /* | 839 | /* |
837 | * These are the functions used to load flat style executables and shared | 840 | * These are the functions used to load flat style executables and shared |
838 | * libraries. There is no binary dependent code anywhere else. | 841 | * libraries. There is no binary dependent code anywhere else. |
839 | */ | 842 | */ |
840 | 843 | ||
841 | static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) | 844 | static int load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs) |
842 | { | 845 | { |
843 | struct lib_info libinfo; | 846 | struct lib_info libinfo; |
844 | unsigned long p = bprm->p; | 847 | unsigned long p = bprm->p; |
845 | unsigned long stack_len; | 848 | unsigned long stack_len; |
846 | unsigned long start_addr; | 849 | unsigned long start_addr; |
847 | unsigned long *sp; | 850 | unsigned long *sp; |
848 | int res; | 851 | int res; |
849 | int i, j; | 852 | int i, j; |
850 | 853 | ||
851 | memset(&libinfo, 0, sizeof(libinfo)); | 854 | memset(&libinfo, 0, sizeof(libinfo)); |
852 | /* | 855 | /* |
853 | * We have to add the size of our arguments to our stack size | 856 | * We have to add the size of our arguments to our stack size |
854 | * otherwise it's too easy for users to create stack overflows | 857 | * otherwise it's too easy for users to create stack overflows |
855 | * by passing in a huge argument list. And yes, we have to be | 858 | * by passing in a huge argument list. And yes, we have to be |
856 | * pedantic and include space for the argv/envp array as it may have | 859 | * pedantic and include space for the argv/envp array as it may have |
857 | * a lot of entries. | 860 | * a lot of entries. |
858 | */ | 861 | */ |
859 | #define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *)) | 862 | #define TOP_OF_ARGS (PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *)) |
860 | stack_len = TOP_OF_ARGS - bprm->p; /* the strings */ | 863 | stack_len = TOP_OF_ARGS - bprm->p; /* the strings */ |
861 | stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */ | 864 | stack_len += (bprm->argc + 1) * sizeof(char *); /* the argv array */ |
862 | stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */ | 865 | stack_len += (bprm->envc + 1) * sizeof(char *); /* the envp array */ |
863 | 866 | ||
864 | 867 | ||
865 | res = load_flat_file(bprm, &libinfo, 0, &stack_len); | 868 | res = load_flat_file(bprm, &libinfo, 0, &stack_len); |
866 | if (res > (unsigned long)-4096) | 869 | if (res > (unsigned long)-4096) |
867 | return res; | 870 | return res; |
868 | 871 | ||
869 | /* Update data segment pointers for all libraries */ | 872 | /* Update data segment pointers for all libraries */ |
870 | for (i=0; i<MAX_SHARED_LIBS; i++) | 873 | for (i=0; i<MAX_SHARED_LIBS; i++) |
871 | if (libinfo.lib_list[i].loaded) | 874 | if (libinfo.lib_list[i].loaded) |
872 | for (j=0; j<MAX_SHARED_LIBS; j++) | 875 | for (j=0; j<MAX_SHARED_LIBS; j++) |
873 | (-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] = | 876 | (-(j+1))[(unsigned long *)(libinfo.lib_list[i].start_data)] = |
874 | (libinfo.lib_list[j].loaded)? | 877 | (libinfo.lib_list[j].loaded)? |
875 | libinfo.lib_list[j].start_data:UNLOADED_LIB; | 878 | libinfo.lib_list[j].start_data:UNLOADED_LIB; |
876 | 879 | ||
877 | compute_creds(bprm); | 880 | compute_creds(bprm); |
878 | current->flags &= ~PF_FORKNOEXEC; | 881 | current->flags &= ~PF_FORKNOEXEC; |
879 | 882 | ||
880 | set_binfmt(&flat_format); | 883 | set_binfmt(&flat_format); |
881 | 884 | ||
882 | p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4; | 885 | p = ((current->mm->context.end_brk + stack_len + 3) & ~3) - 4; |
883 | DBG_FLT("p=%x\n", (int)p); | 886 | DBG_FLT("p=%x\n", (int)p); |
884 | 887 | ||
885 | /* copy the arg pages onto the stack, this could be more efficient :-) */ | 888 | /* copy the arg pages onto the stack, this could be more efficient :-) */ |
886 | for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--) | 889 | for (i = TOP_OF_ARGS - 1; i >= bprm->p; i--) |
887 | * (char *) --p = | 890 | * (char *) --p = |
888 | ((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE]; | 891 | ((char *) page_address(bprm->page[i/PAGE_SIZE]))[i % PAGE_SIZE]; |
889 | 892 | ||
890 | sp = (unsigned long *) create_flat_tables(p, bprm); | 893 | sp = (unsigned long *) create_flat_tables(p, bprm); |
891 | 894 | ||
892 | /* Fake some return addresses to ensure the call chain will | 895 | /* Fake some return addresses to ensure the call chain will |
893 | * initialise library in order for us. We are required to call | 896 | * initialise library in order for us. We are required to call |
894 | * lib 1 first, then 2, ... and finally the main program (id 0). | 897 | * lib 1 first, then 2, ... and finally the main program (id 0). |
895 | */ | 898 | */ |
896 | start_addr = libinfo.lib_list[0].entry; | 899 | start_addr = libinfo.lib_list[0].entry; |
897 | 900 | ||
898 | #ifdef CONFIG_BINFMT_SHARED_FLAT | 901 | #ifdef CONFIG_BINFMT_SHARED_FLAT |
899 | for (i = MAX_SHARED_LIBS-1; i>0; i--) { | 902 | for (i = MAX_SHARED_LIBS-1; i>0; i--) { |
900 | if (libinfo.lib_list[i].loaded) { | 903 | if (libinfo.lib_list[i].loaded) { |
901 | /* Push previos first to call address */ | 904 | /* Push previos first to call address */ |
902 | --sp; put_user(start_addr, sp); | 905 | --sp; put_user(start_addr, sp); |
903 | start_addr = libinfo.lib_list[i].entry; | 906 | start_addr = libinfo.lib_list[i].entry; |
904 | } | 907 | } |
905 | } | 908 | } |
906 | #endif | 909 | #endif |
907 | 910 | ||
908 | /* Stash our initial stack pointer into the mm structure */ | 911 | /* Stash our initial stack pointer into the mm structure */ |
909 | current->mm->start_stack = (unsigned long )sp; | 912 | current->mm->start_stack = (unsigned long )sp; |
910 | 913 | ||
911 | 914 | ||
912 | DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n", | 915 | DBG_FLT("start_thread(regs=0x%x, entry=0x%x, start_stack=0x%x)\n", |
913 | (int)regs, (int)start_addr, (int)current->mm->start_stack); | 916 | (int)regs, (int)start_addr, (int)current->mm->start_stack); |
914 | 917 | ||
915 | start_thread(regs, start_addr, current->mm->start_stack); | 918 | start_thread(regs, start_addr, current->mm->start_stack); |
916 | 919 | ||
917 | if (current->ptrace & PT_PTRACED) | 920 | if (current->ptrace & PT_PTRACED) |
918 | send_sig(SIGTRAP, current, 0); | 921 | send_sig(SIGTRAP, current, 0); |
919 | 922 | ||
920 | return 0; | 923 | return 0; |
921 | } | 924 | } |
922 | 925 | ||
923 | /****************************************************************************/ | 926 | /****************************************************************************/ |
924 | 927 | ||
925 | static int __init init_flat_binfmt(void) | 928 | static int __init init_flat_binfmt(void) |
926 | { | 929 | { |
927 | return register_binfmt(&flat_format); | 930 | return register_binfmt(&flat_format); |
928 | } | 931 | } |
929 | 932 | ||
930 | static void __exit exit_flat_binfmt(void) | 933 | static void __exit exit_flat_binfmt(void) |
931 | { | 934 | { |
932 | unregister_binfmt(&flat_format); | 935 | unregister_binfmt(&flat_format); |
933 | } | 936 | } |
934 | 937 | ||
935 | /****************************************************************************/ | 938 | /****************************************************************************/ |
936 | 939 | ||
937 | core_initcall(init_flat_binfmt); | 940 | core_initcall(init_flat_binfmt); |
938 | module_exit(exit_flat_binfmt); | 941 | module_exit(exit_flat_binfmt); |
939 | 942 | ||
940 | /****************************************************************************/ | 943 | /****************************************************************************/ |
941 | 944 |
include/asm-h8300/flat.h
1 | /* | 1 | /* |
2 | * include/asm-h8300/flat.h -- uClinux flat-format executables | 2 | * include/asm-h8300/flat.h -- uClinux flat-format executables |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #ifndef __H8300_FLAT_H__ | 5 | #ifndef __H8300_FLAT_H__ |
6 | #define __H8300_FLAT_H__ | 6 | #define __H8300_FLAT_H__ |
7 | 7 | ||
8 | #define flat_stack_align(sp) /* nothing needed */ | 8 | #define flat_stack_align(sp) /* nothing needed */ |
9 | #define flat_argvp_envp_on_stack() 1 | 9 | #define flat_argvp_envp_on_stack() 1 |
10 | #define flat_old_ram_flag(flags) 1 | 10 | #define flat_old_ram_flag(flags) 1 |
11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) | 11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
12 | #define flat_set_persistent(relval, p) 0 | ||
12 | 13 | ||
13 | /* | 14 | /* |
14 | * on the H8 a couple of the relocations have an instruction in the | 15 | * on the H8 a couple of the relocations have an instruction in the |
15 | * top byte. As there can only be 24bits of address space, we just | 16 | * top byte. As there can only be 24bits of address space, we just |
16 | * always preserve that 8bits at the top, when it isn't an instruction | 17 | * always preserve that 8bits at the top, when it isn't an instruction |
17 | * is is 0 (davidm@snapgear.com) | 18 | * is is 0 (davidm@snapgear.com) |
18 | */ | 19 | */ |
19 | 20 | ||
20 | #define flat_get_relocate_addr(rel) (rel) | 21 | #define flat_get_relocate_addr(rel) (rel) |
21 | #define flat_get_addr_from_rp(rp, relval, flags) \ | 22 | #define flat_get_addr_from_rp(rp, relval, flags, persistent) \ |
22 | (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff)) | 23 | (get_unaligned(rp) & ((flags & FLAT_FLAG_GOTPIC) ? 0xffffffff: 0x00ffffff)) |
23 | #define flat_put_addr_at_rp(rp, addr, rel) \ | 24 | #define flat_put_addr_at_rp(rp, addr, rel) \ |
24 | put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp) | 25 | put_unaligned (((*(char *)(rp)) << 24) | ((addr) & 0x00ffffff), rp) |
25 | 26 | ||
26 | #endif /* __H8300_FLAT_H__ */ | 27 | #endif /* __H8300_FLAT_H__ */ |
27 | 28 |
include/asm-m32r/flat.h
1 | /* | 1 | /* |
2 | * include/asm-m32r/flat.h | 2 | * include/asm-m32r/flat.h |
3 | * | 3 | * |
4 | * uClinux flat-format executables | 4 | * uClinux flat-format executables |
5 | * | 5 | * |
6 | * Copyright (C) 2004 Kazuhiro Inaoka | 6 | * Copyright (C) 2004 Kazuhiro Inaoka |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive for | 9 | * License. See the file "COPYING" in the main directory of this archive for |
10 | * more details. | 10 | * more details. |
11 | */ | 11 | */ |
12 | #ifndef __ASM_M32R_FLAT_H | 12 | #ifndef __ASM_M32R_FLAT_H |
13 | #define __ASM_M32R_FLAT_H | 13 | #define __ASM_M32R_FLAT_H |
14 | 14 | ||
15 | #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) | 15 | #define flat_stack_align(sp) (*sp += (*sp & 3 ? (4 - (*sp & 3)): 0)) |
16 | #define flat_argvp_envp_on_stack() 0 | 16 | #define flat_argvp_envp_on_stack() 0 |
17 | #define flat_old_ram_flag(flags) (flags) | 17 | #define flat_old_ram_flag(flags) (flags) |
18 | #define flat_set_persistent(relval, p) 0 | ||
18 | #define flat_reloc_valid(reloc, size) \ | 19 | #define flat_reloc_valid(reloc, size) \ |
19 | (((reloc) - textlen_for_m32r_lo16_data) <= (size)) | 20 | (((reloc) - textlen_for_m32r_lo16_data) <= (size)) |
20 | #define flat_get_addr_from_rp(rp, relval, flags) \ | 21 | #define flat_get_addr_from_rp(rp, relval, flags, persistent) \ |
21 | m32r_flat_get_addr_from_rp(rp, relval, (text_len) ) | 22 | m32r_flat_get_addr_from_rp(rp, relval, (text_len) ) |
22 | 23 | ||
23 | #define flat_put_addr_at_rp(rp, addr, relval) \ | 24 | #define flat_put_addr_at_rp(rp, addr, relval) \ |
24 | m32r_flat_put_addr_at_rp(rp, addr, relval) | 25 | m32r_flat_put_addr_at_rp(rp, addr, relval) |
25 | 26 | ||
26 | /* Convert a relocation entry into an address. */ | 27 | /* Convert a relocation entry into an address. */ |
27 | static inline unsigned long | 28 | static inline unsigned long |
28 | flat_get_relocate_addr (unsigned long relval) | 29 | flat_get_relocate_addr (unsigned long relval) |
29 | { | 30 | { |
30 | return relval & 0x00ffffff; /* Mask out top 8-bits */ | 31 | return relval & 0x00ffffff; /* Mask out top 8-bits */ |
31 | } | 32 | } |
32 | 33 | ||
33 | #define flat_m32r_get_reloc_type(relval) ((relval) >> 24) | 34 | #define flat_m32r_get_reloc_type(relval) ((relval) >> 24) |
34 | 35 | ||
35 | #define M32R_SETH_OPCODE 0xd0c00000 /* SETH instruction code */ | 36 | #define M32R_SETH_OPCODE 0xd0c00000 /* SETH instruction code */ |
36 | 37 | ||
37 | #define FLAT_M32R_32 0x00 /* 32bits reloc */ | 38 | #define FLAT_M32R_32 0x00 /* 32bits reloc */ |
38 | #define FLAT_M32R_24 0x01 /* unsigned 24bits reloc */ | 39 | #define FLAT_M32R_24 0x01 /* unsigned 24bits reloc */ |
39 | #define FLAT_M32R_16 0x02 /* 16bits reloc */ | 40 | #define FLAT_M32R_16 0x02 /* 16bits reloc */ |
40 | #define FLAT_M32R_LO16 0x03 /* signed low 16bits reloc (low()) */ | 41 | #define FLAT_M32R_LO16 0x03 /* signed low 16bits reloc (low()) */ |
41 | #define FLAT_M32R_LO16_DATA 0x04 /* signed low 16bits reloc (low()) | 42 | #define FLAT_M32R_LO16_DATA 0x04 /* signed low 16bits reloc (low()) |
42 | for a symbol in .data section */ | 43 | for a symbol in .data section */ |
43 | /* High 16bits of an address used | 44 | /* High 16bits of an address used |
44 | when the lower 16bbits are treated | 45 | when the lower 16bbits are treated |
45 | as unsigned. | 46 | as unsigned. |
46 | To create SETH instruction only. | 47 | To create SETH instruction only. |
47 | 0x1X: X means a number of register. | 48 | 0x1X: X means a number of register. |
48 | 0x10 - 0x3F are reserved. */ | 49 | 0x10 - 0x3F are reserved. */ |
49 | #define FLAT_M32R_HI16_ULO 0x10 /* reloc for SETH Rn,#high(imm16) */ | 50 | #define FLAT_M32R_HI16_ULO 0x10 /* reloc for SETH Rn,#high(imm16) */ |
50 | /* High 16bits of an address used | 51 | /* High 16bits of an address used |
51 | when the lower 16bbits are treated | 52 | when the lower 16bbits are treated |
52 | as signed. | 53 | as signed. |
53 | To create SETH instruction only. | 54 | To create SETH instruction only. |
54 | 0x2X: X means a number of register. | 55 | 0x2X: X means a number of register. |
55 | 0x20 - 0x4F are reserved. */ | 56 | 0x20 - 0x4F are reserved. */ |
56 | #define FLAT_M32R_HI16_SLO 0x20 /* reloc for SETH Rn,#shigh(imm16) */ | 57 | #define FLAT_M32R_HI16_SLO 0x20 /* reloc for SETH Rn,#shigh(imm16) */ |
57 | 58 | ||
58 | static unsigned long textlen_for_m32r_lo16_data = 0; | 59 | static unsigned long textlen_for_m32r_lo16_data = 0; |
59 | 60 | ||
60 | static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp, | 61 | static inline unsigned long m32r_flat_get_addr_from_rp (unsigned long *rp, |
61 | unsigned long relval, | 62 | unsigned long relval, |
62 | unsigned long textlen) | 63 | unsigned long textlen) |
63 | { | 64 | { |
64 | unsigned int reloc = flat_m32r_get_reloc_type (relval); | 65 | unsigned int reloc = flat_m32r_get_reloc_type (relval); |
65 | textlen_for_m32r_lo16_data = 0; | 66 | textlen_for_m32r_lo16_data = 0; |
66 | if (reloc & 0xf0) { | 67 | if (reloc & 0xf0) { |
67 | unsigned long addr = htonl(*rp); | 68 | unsigned long addr = htonl(*rp); |
68 | switch (reloc & 0xf0) | 69 | switch (reloc & 0xf0) |
69 | { | 70 | { |
70 | case FLAT_M32R_HI16_ULO: | 71 | case FLAT_M32R_HI16_ULO: |
71 | case FLAT_M32R_HI16_SLO: | 72 | case FLAT_M32R_HI16_SLO: |
72 | if (addr == 0) { | 73 | if (addr == 0) { |
73 | /* put "seth Rn,#0x0" instead of 0 (addr). */ | 74 | /* put "seth Rn,#0x0" instead of 0 (addr). */ |
74 | *rp = (M32R_SETH_OPCODE | ((reloc & 0x0f)<<24)); | 75 | *rp = (M32R_SETH_OPCODE | ((reloc & 0x0f)<<24)); |
75 | } | 76 | } |
76 | return addr; | 77 | return addr; |
77 | default: | 78 | default: |
78 | break; | 79 | break; |
79 | } | 80 | } |
80 | } else { | 81 | } else { |
81 | switch (reloc) | 82 | switch (reloc) |
82 | { | 83 | { |
83 | case FLAT_M32R_LO16: | 84 | case FLAT_M32R_LO16: |
84 | return htonl(*rp) & 0xFFFF; | 85 | return htonl(*rp) & 0xFFFF; |
85 | case FLAT_M32R_LO16_DATA: | 86 | case FLAT_M32R_LO16_DATA: |
86 | /* FIXME: The return value will decrease by textlen | 87 | /* FIXME: The return value will decrease by textlen |
87 | at m32r_flat_put_addr_at_rp () */ | 88 | at m32r_flat_put_addr_at_rp () */ |
88 | textlen_for_m32r_lo16_data = textlen; | 89 | textlen_for_m32r_lo16_data = textlen; |
89 | return (htonl(*rp) & 0xFFFF) + textlen; | 90 | return (htonl(*rp) & 0xFFFF) + textlen; |
90 | case FLAT_M32R_16: | 91 | case FLAT_M32R_16: |
91 | return htons(*(unsigned short *)rp) & 0xFFFF; | 92 | return htons(*(unsigned short *)rp) & 0xFFFF; |
92 | case FLAT_M32R_24: | 93 | case FLAT_M32R_24: |
93 | return htonl(*rp) & 0xFFFFFF; | 94 | return htonl(*rp) & 0xFFFFFF; |
94 | case FLAT_M32R_32: | 95 | case FLAT_M32R_32: |
95 | return htonl(*rp); | 96 | return htonl(*rp); |
96 | default: | 97 | default: |
97 | break; | 98 | break; |
98 | } | 99 | } |
99 | } | 100 | } |
100 | return ~0; /* bogus value */ | 101 | return ~0; /* bogus value */ |
101 | } | 102 | } |
102 | 103 | ||
103 | static inline void m32r_flat_put_addr_at_rp (unsigned long *rp, | 104 | static inline void m32r_flat_put_addr_at_rp (unsigned long *rp, |
104 | unsigned long addr, | 105 | unsigned long addr, |
105 | unsigned long relval) | 106 | unsigned long relval) |
106 | { | 107 | { |
107 | unsigned int reloc = flat_m32r_get_reloc_type (relval); | 108 | unsigned int reloc = flat_m32r_get_reloc_type (relval); |
108 | if (reloc & 0xf0) { | 109 | if (reloc & 0xf0) { |
109 | unsigned long Rn = reloc & 0x0f; /* get a number of register */ | 110 | unsigned long Rn = reloc & 0x0f; /* get a number of register */ |
110 | Rn <<= 24; /* 0x0R000000 */ | 111 | Rn <<= 24; /* 0x0R000000 */ |
111 | reloc &= 0xf0; | 112 | reloc &= 0xf0; |
112 | switch (reloc) | 113 | switch (reloc) |
113 | { | 114 | { |
114 | case FLAT_M32R_HI16_ULO: /* To create SETH Rn,#high(imm16) */ | 115 | case FLAT_M32R_HI16_ULO: /* To create SETH Rn,#high(imm16) */ |
115 | *rp = (M32R_SETH_OPCODE | Rn | 116 | *rp = (M32R_SETH_OPCODE | Rn |
116 | | ((addr >> 16) & 0xFFFF)); | 117 | | ((addr >> 16) & 0xFFFF)); |
117 | break; | 118 | break; |
118 | case FLAT_M32R_HI16_SLO: /* To create SETH Rn,#shigh(imm16) */ | 119 | case FLAT_M32R_HI16_SLO: /* To create SETH Rn,#shigh(imm16) */ |
119 | *rp = (M32R_SETH_OPCODE | Rn | 120 | *rp = (M32R_SETH_OPCODE | Rn |
120 | | (((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) | 121 | | (((addr >> 16) + ((addr & 0x8000) ? 1 : 0)) |
121 | & 0xFFFF)); | 122 | & 0xFFFF)); |
122 | break; | 123 | break; |
123 | } | 124 | } |
124 | } else { | 125 | } else { |
125 | switch (reloc) { | 126 | switch (reloc) { |
126 | case FLAT_M32R_LO16_DATA: | 127 | case FLAT_M32R_LO16_DATA: |
127 | addr -= textlen_for_m32r_lo16_data; | 128 | addr -= textlen_for_m32r_lo16_data; |
128 | textlen_for_m32r_lo16_data = 0; | 129 | textlen_for_m32r_lo16_data = 0; |
129 | case FLAT_M32R_LO16: | 130 | case FLAT_M32R_LO16: |
130 | *rp = (htonl(*rp) & 0xFFFF0000) | (addr & 0xFFFF); | 131 | *rp = (htonl(*rp) & 0xFFFF0000) | (addr & 0xFFFF); |
131 | break; | 132 | break; |
132 | case FLAT_M32R_16: | 133 | case FLAT_M32R_16: |
133 | *(unsigned short *)rp = addr & 0xFFFF; | 134 | *(unsigned short *)rp = addr & 0xFFFF; |
134 | break; | 135 | break; |
135 | case FLAT_M32R_24: | 136 | case FLAT_M32R_24: |
136 | *rp = (htonl(*rp) & 0xFF000000) | (addr & 0xFFFFFF); | 137 | *rp = (htonl(*rp) & 0xFF000000) | (addr & 0xFFFFFF); |
137 | break; | 138 | break; |
138 | case FLAT_M32R_32: | 139 | case FLAT_M32R_32: |
139 | *rp = addr; | 140 | *rp = addr; |
140 | break; | 141 | break; |
141 | } | 142 | } |
142 | } | 143 | } |
143 | } | 144 | } |
144 | 145 | ||
145 | #endif /* __ASM_M32R_FLAT_H */ | 146 | #endif /* __ASM_M32R_FLAT_H */ |
146 | 147 |
include/asm-m68knommu/flat.h
1 | /* | 1 | /* |
2 | * include/asm-m68knommu/flat.h -- uClinux flat-format executables | 2 | * include/asm-m68knommu/flat.h -- uClinux flat-format executables |
3 | */ | 3 | */ |
4 | 4 | ||
5 | #ifndef __M68KNOMMU_FLAT_H__ | 5 | #ifndef __M68KNOMMU_FLAT_H__ |
6 | #define __M68KNOMMU_FLAT_H__ | 6 | #define __M68KNOMMU_FLAT_H__ |
7 | 7 | ||
8 | #define flat_stack_align(sp) /* nothing needed */ | 8 | #define flat_stack_align(sp) /* nothing needed */ |
9 | #define flat_argvp_envp_on_stack() 1 | 9 | #define flat_argvp_envp_on_stack() 1 |
10 | #define flat_old_ram_flag(flags) (flags) | 10 | #define flat_old_ram_flag(flags) (flags) |
11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) | 11 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
12 | #define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp) | 12 | #define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) |
13 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) | 13 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) |
14 | #define flat_get_relocate_addr(rel) (rel) | 14 | #define flat_get_relocate_addr(rel) (rel) |
15 | #define flat_set_persistent(relval, p) 0 | ||
15 | 16 | ||
16 | #endif /* __M68KNOMMU_FLAT_H__ */ | 17 | #endif /* __M68KNOMMU_FLAT_H__ */ |
17 | 18 |
include/asm-sh/flat.h
1 | /* | 1 | /* |
2 | * include/asm-sh/flat.h | 2 | * include/asm-sh/flat.h |
3 | * | 3 | * |
4 | * uClinux flat-format executables | 4 | * uClinux flat-format executables |
5 | * | 5 | * |
6 | * Copyright (C) 2003 Paul Mundt | 6 | * Copyright (C) 2003 Paul Mundt |
7 | * | 7 | * |
8 | * This file is subject to the terms and conditions of the GNU General Public | 8 | * This file is subject to the terms and conditions of the GNU General Public |
9 | * License. See the file "COPYING" in the main directory of this archive for | 9 | * License. See the file "COPYING" in the main directory of this archive for |
10 | * more details. | 10 | * more details. |
11 | */ | 11 | */ |
12 | #ifndef __ASM_SH_FLAT_H | 12 | #ifndef __ASM_SH_FLAT_H |
13 | #define __ASM_SH_FLAT_H | 13 | #define __ASM_SH_FLAT_H |
14 | 14 | ||
15 | #define flat_stack_align(sp) /* nothing needed */ | 15 | #define flat_stack_align(sp) /* nothing needed */ |
16 | #define flat_argvp_envp_on_stack() 0 | 16 | #define flat_argvp_envp_on_stack() 0 |
17 | #define flat_old_ram_flag(flags) (flags) | 17 | #define flat_old_ram_flag(flags) (flags) |
18 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) | 18 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size)) |
19 | #define flat_get_addr_from_rp(rp, relval, flags) get_unaligned(rp) | 19 | #define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) |
20 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) | 20 | #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) |
21 | #define flat_get_relocate_addr(rel) (rel) | 21 | #define flat_get_relocate_addr(rel) (rel) |
22 | #define flat_set_persistent(relval, p) 0 | ||
22 | 23 | ||
23 | #endif /* __ASM_SH_FLAT_H */ | 24 | #endif /* __ASM_SH_FLAT_H */ |
24 | 25 |
include/asm-v850/flat.h
1 | /* | 1 | /* |
2 | * include/asm-v850/flat.h -- uClinux flat-format executables | 2 | * include/asm-v850/flat.h -- uClinux flat-format executables |
3 | * | 3 | * |
4 | * Copyright (C) 2002,03 NEC Electronics Corporation | 4 | * Copyright (C) 2002,03 NEC Electronics Corporation |
5 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> | 5 | * Copyright (C) 2002,03 Miles Bader <miles@gnu.org> |
6 | * | 6 | * |
7 | * This file is subject to the terms and conditions of the GNU General | 7 | * This file is subject to the terms and conditions of the GNU General |
8 | * Public License. See the file COPYING in the main directory of this | 8 | * Public License. See the file COPYING in the main directory of this |
9 | * archive for more details. | 9 | * archive for more details. |
10 | * | 10 | * |
11 | * Written by Miles Bader <miles@gnu.org> | 11 | * Written by Miles Bader <miles@gnu.org> |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef __V850_FLAT_H__ | 14 | #ifndef __V850_FLAT_H__ |
15 | #define __V850_FLAT_H__ | 15 | #define __V850_FLAT_H__ |
16 | 16 | ||
17 | /* The amount by which a relocation can exceed the program image limits | 17 | /* The amount by which a relocation can exceed the program image limits |
18 | without being regarded as an error. On the v850, the relocations of | 18 | without being regarded as an error. On the v850, the relocations of |
19 | some base-pointers can be offset by 0x8000 (to allow better usage of the | 19 | some base-pointers can be offset by 0x8000 (to allow better usage of the |
20 | space offered by 16-bit signed offsets -- in most cases the offsets used | 20 | space offered by 16-bit signed offsets -- in most cases the offsets used |
21 | with such a base-pointer will be negative). */ | 21 | with such a base-pointer will be negative). */ |
22 | 22 | ||
23 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000)) | 23 | #define flat_reloc_valid(reloc, size) ((reloc) <= (size + 0x8000)) |
24 | 24 | ||
25 | #define flat_stack_align(sp) /* nothing needed */ | 25 | #define flat_stack_align(sp) /* nothing needed */ |
26 | #define flat_argvp_envp_on_stack() 0 | 26 | #define flat_argvp_envp_on_stack() 0 |
27 | #define flat_old_ram_flag(flags) (flags) | 27 | #define flat_old_ram_flag(flags) (flags) |
28 | #define flat_set_persistent(relval, p) 0 | ||
28 | 29 | ||
29 | /* We store the type of relocation in the top 4 bits of the `relval.' */ | 30 | /* We store the type of relocation in the top 4 bits of the `relval.' */ |
30 | 31 | ||
31 | /* Convert a relocation entry into an address. */ | 32 | /* Convert a relocation entry into an address. */ |
32 | static inline unsigned long | 33 | static inline unsigned long |
33 | flat_get_relocate_addr (unsigned long relval) | 34 | flat_get_relocate_addr (unsigned long relval) |
34 | { | 35 | { |
35 | return relval & 0x0fffffff; /* Mask out top 4-bits */ | 36 | return relval & 0x0fffffff; /* Mask out top 4-bits */ |
36 | } | 37 | } |
37 | 38 | ||
38 | #define flat_v850_get_reloc_type(relval) ((relval) >> 28) | 39 | #define flat_v850_get_reloc_type(relval) ((relval) >> 28) |
39 | 40 | ||
40 | #define FLAT_V850_R_32 0 /* Normal 32-bit reloc */ | 41 | #define FLAT_V850_R_32 0 /* Normal 32-bit reloc */ |
41 | #define FLAT_V850_R_HI16S_LO15 1 /* High 16-bits + signed 15-bit low field */ | 42 | #define FLAT_V850_R_HI16S_LO15 1 /* High 16-bits + signed 15-bit low field */ |
42 | #define FLAT_V850_R_HI16S_LO16 2 /* High 16-bits + signed 16-bit low field */ | 43 | #define FLAT_V850_R_HI16S_LO16 2 /* High 16-bits + signed 16-bit low field */ |
43 | 44 | ||
44 | /* Extract the address to be relocated from the symbol reference at RP; | 45 | /* Extract the address to be relocated from the symbol reference at RP; |
45 | RELVAL is the raw relocation-table entry from which RP is derived. | 46 | RELVAL is the raw relocation-table entry from which RP is derived. |
46 | For the v850, RP should always be half-word aligned. */ | 47 | For the v850, RP should always be half-word aligned. */ |
47 | static inline unsigned long flat_get_addr_from_rp (unsigned long *rp, | 48 | static inline unsigned long flat_get_addr_from_rp (unsigned long *rp, |
48 | unsigned long relval, | 49 | unsigned long relval, |
49 | unsigned long flags) | 50 | unsigned long flags, |
51 | unsigned long *persistent) | ||
50 | { | 52 | { |
51 | short *srp = (short *)rp; | 53 | short *srp = (short *)rp; |
52 | 54 | ||
53 | switch (flat_v850_get_reloc_type (relval)) | 55 | switch (flat_v850_get_reloc_type (relval)) |
54 | { | 56 | { |
55 | case FLAT_V850_R_32: | 57 | case FLAT_V850_R_32: |
56 | /* Simple 32-bit address. */ | 58 | /* Simple 32-bit address. */ |
57 | return srp[0] | (srp[1] << 16); | 59 | return srp[0] | (srp[1] << 16); |
58 | 60 | ||
59 | case FLAT_V850_R_HI16S_LO16: | 61 | case FLAT_V850_R_HI16S_LO16: |
60 | /* The high and low halves of the address are in the 16 | 62 | /* The high and low halves of the address are in the 16 |
61 | bits at RP, and the 2nd word of the 32-bit instruction | 63 | bits at RP, and the 2nd word of the 32-bit instruction |
62 | following that, respectively. The low half is _signed_ | 64 | following that, respectively. The low half is _signed_ |
63 | so we have to sign-extend it and add it to the upper | 65 | so we have to sign-extend it and add it to the upper |
64 | half instead of simply or-ing them together. | 66 | half instead of simply or-ing them together. |
65 | 67 | ||
66 | Unlike most relocated address, this one is stored in | 68 | Unlike most relocated address, this one is stored in |
67 | native (little-endian) byte-order to avoid problems with | 69 | native (little-endian) byte-order to avoid problems with |
68 | trashing the low-order bit, so we have to convert to | 70 | trashing the low-order bit, so we have to convert to |
69 | network-byte-order before returning, as that's what the | 71 | network-byte-order before returning, as that's what the |
70 | caller expects. */ | 72 | caller expects. */ |
71 | return htonl ((srp[0] << 16) + srp[2]); | 73 | return htonl ((srp[0] << 16) + srp[2]); |
72 | 74 | ||
73 | case FLAT_V850_R_HI16S_LO15: | 75 | case FLAT_V850_R_HI16S_LO15: |
74 | /* The high and low halves of the address are in the 16 | 76 | /* The high and low halves of the address are in the 16 |
75 | bits at RP, and the upper 15 bits of the 2nd word of the | 77 | bits at RP, and the upper 15 bits of the 2nd word of the |
76 | 32-bit instruction following that, respectively. The | 78 | 32-bit instruction following that, respectively. The |
77 | low half is _signed_ so we have to sign-extend it and | 79 | low half is _signed_ so we have to sign-extend it and |
78 | add it to the upper half instead of simply or-ing them | 80 | add it to the upper half instead of simply or-ing them |
79 | together. The lowest bit is always zero. | 81 | together. The lowest bit is always zero. |
80 | 82 | ||
81 | Unlike most relocated address, this one is stored in | 83 | Unlike most relocated address, this one is stored in |
82 | native (little-endian) byte-order to avoid problems with | 84 | native (little-endian) byte-order to avoid problems with |
83 | trashing the low-order bit, so we have to convert to | 85 | trashing the low-order bit, so we have to convert to |
84 | network-byte-order before returning, as that's what the | 86 | network-byte-order before returning, as that's what the |
85 | caller expects. */ | 87 | caller expects. */ |
86 | return htonl ((srp[0] << 16) + (srp[2] & ~0x1)); | 88 | return htonl ((srp[0] << 16) + (srp[2] & ~0x1)); |
87 | 89 | ||
88 | default: | 90 | default: |
89 | return ~0; /* bogus value */ | 91 | return ~0; /* bogus value */ |
90 | } | 92 | } |
91 | } | 93 | } |
92 | 94 | ||
93 | /* Insert the address ADDR into the symbol reference at RP; | 95 | /* Insert the address ADDR into the symbol reference at RP; |
94 | RELVAL is the raw relocation-table entry from which RP is derived. | 96 | RELVAL is the raw relocation-table entry from which RP is derived. |
95 | For the v850, RP should always be half-word aligned. */ | 97 | For the v850, RP should always be half-word aligned. */ |
96 | static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr, | 98 | static inline void flat_put_addr_at_rp (unsigned long *rp, unsigned long addr, |
97 | unsigned long relval) | 99 | unsigned long relval) |
98 | { | 100 | { |
99 | short *srp = (short *)rp; | 101 | short *srp = (short *)rp; |
100 | 102 | ||
101 | switch (flat_v850_get_reloc_type (relval)) { | 103 | switch (flat_v850_get_reloc_type (relval)) { |
102 | case FLAT_V850_R_32: | 104 | case FLAT_V850_R_32: |
103 | /* Simple 32-bit address. */ | 105 | /* Simple 32-bit address. */ |
104 | srp[0] = addr & 0xFFFF; | 106 | srp[0] = addr & 0xFFFF; |
105 | srp[1] = (addr >> 16); | 107 | srp[1] = (addr >> 16); |
106 | break; | 108 | break; |
107 | 109 | ||
108 | case FLAT_V850_R_HI16S_LO16: | 110 | case FLAT_V850_R_HI16S_LO16: |
109 | /* The high and low halves of the address are in the 16 | 111 | /* The high and low halves of the address are in the 16 |
110 | bits at RP, and the 2nd word of the 32-bit instruction | 112 | bits at RP, and the 2nd word of the 32-bit instruction |
111 | following that, respectively. The low half is _signed_ | 113 | following that, respectively. The low half is _signed_ |
112 | so we must carry its sign bit to the upper half before | 114 | so we must carry its sign bit to the upper half before |
113 | writing the upper half. */ | 115 | writing the upper half. */ |
114 | srp[0] = (addr >> 16) + ((addr >> 15) & 0x1); | 116 | srp[0] = (addr >> 16) + ((addr >> 15) & 0x1); |
115 | srp[2] = addr & 0xFFFF; | 117 | srp[2] = addr & 0xFFFF; |
116 | break; | 118 | break; |
117 | 119 | ||
118 | case FLAT_V850_R_HI16S_LO15: | 120 | case FLAT_V850_R_HI16S_LO15: |
119 | /* The high and low halves of the address are in the 16 | 121 | /* The high and low halves of the address are in the 16 |
120 | bits at RP, and the upper 15 bits of the 2nd word of the | 122 | bits at RP, and the upper 15 bits of the 2nd word of the |
121 | 32-bit instruction following that, respectively. The | 123 | 32-bit instruction following that, respectively. The |
122 | low half is _signed_ so we must carry its sign bit to | 124 | low half is _signed_ so we must carry its sign bit to |
123 | the upper half before writing the upper half. The | 125 | the upper half before writing the upper half. The |
124 | lowest bit we preserve from the existing instruction. */ | 126 | lowest bit we preserve from the existing instruction. */ |
125 | srp[0] = (addr >> 16) + ((addr >> 15) & 0x1); | 127 | srp[0] = (addr >> 16) + ((addr >> 15) & 0x1); |
126 | srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1); | 128 | srp[2] = (addr & 0xFFFE) | (srp[2] & 0x1); |
127 | break; | 129 | break; |
128 | } | 130 | } |
129 | } | 131 | } |
130 | 132 | ||
131 | #endif /* __V850_FLAT_H__ */ | 133 | #endif /* __V850_FLAT_H__ */ |
132 | 134 |