Commit f9720205d1f847cb59e197e851b5276425363f6b

Authored by Bernd Schmidt
Committed by Bryan Wu
1 parent f778089cb2

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

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(&current->mm->mmap_sem); 532 down_write(&current->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(&current->mm->mmap_sem); 534 up_write(&current->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(&current->mm->mmap_sem); 544 down_write(&current->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(&current->mm->mmap_sem); 555 up_write(&current->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(&current->mm->mmap_sem); 596 down_write(&current->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(&current->mm->mmap_sem); 607 up_write(&current->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